diff options
author | Boram Park <boram1288.park@samsung.com> | 2018-03-15 16:23:51 +0900 |
---|---|---|
committer | Boram Park <boram1288.park@samsung.com> | 2018-03-15 16:36:01 +0900 |
commit | bed0ef2b800c9e2b8c1518940bb862a2ed64a7aa (patch) | |
tree | eeddabbb5011c131f25133b127f5cfabcc52e185 | |
parent | fd43a56b5af5d7abea7caa0b260748506f536c03 (diff) | |
download | libtdm-vc4-bed0ef2b800c9e2b8c1518940bb862a2ed64a7aa.tar.gz libtdm-vc4-bed0ef2b800c9e2b8c1518940bb862a2ed64a7aa.tar.bz2 libtdm-vc4-bed0ef2b800c9e2b8c1518940bb862a2ed64a7aa.zip |
ref/unref display_buffer by using buffer's user_data
Freeing a buffer before removing a buffer from DRM system makes a issue.
To ensure that a buffer is alive until removing it from DRM, do ref/unref
a buffer.
Change-Id: I97bcd451ab1e4e7cb4a40d5358312c8a898a10c8
-rw-r--r-- | src/tdm_vc4.c | 1 | ||||
-rw-r--r-- | src/tdm_vc4.h | 1 | ||||
-rw-r--r-- | src/tdm_vc4_display.c | 217 |
3 files changed, 97 insertions, 122 deletions
diff --git a/src/tdm_vc4.c b/src/tdm_vc4.c index 54de28b..9402d5f 100644 --- a/src/tdm_vc4.c +++ b/src/tdm_vc4.c @@ -212,7 +212,6 @@ tdm_vc4_deinit(tdm_backend_data *bdata) _tdm_vc4_udev_deinit(vc4_data); #endif - tdm_vc4_display_destroy_buffer_list(vc4_data); tdm_vc4_display_destroy_output_list(vc4_data); if (vc4_data->plane_res) diff --git a/src/tdm_vc4.h b/src/tdm_vc4.h index a083837..13250a2 100644 --- a/src/tdm_vc4.h +++ b/src/tdm_vc4.h @@ -142,6 +142,5 @@ void tdm_vc4_display_update_output_status(tdm_vc4_data *vc4_data); tdm_error tdm_vc4_display_create_output_list(tdm_vc4_data *vc4_data); void tdm_vc4_display_destroy_output_list(tdm_vc4_data *vc4_data); tdm_error tdm_vc4_display_create_layer_list(tdm_vc4_data *vc4_data); -void tdm_vc4_display_destroy_buffer_list(tdm_vc4_data *vc4_data); #endif /* _TDM_VC4_H_ */ diff --git a/src/tdm_vc4_display.c b/src/tdm_vc4_display.c index e6c6885..f8663a7 100644 --- a/src/tdm_vc4_display.c +++ b/src/tdm_vc4_display.c @@ -7,6 +7,9 @@ #include "tdm_vc4.h" +static int tdm_vc4_buffer_key; +#define TDM_VC4_BUFFER_KEY ((unsigned long)&tdm_vc4_buffer_key) + #define MIN_WIDTH 32 #define LIST_INSERT_AFTER(__after, __item) \ @@ -27,8 +30,7 @@ typedef enum { } tdm_vc4_event_type; typedef struct _tdm_vc4_display_buffer { - struct list_head link; - + tdm_vc4_data *vc4_data; unsigned int fb_id; tbm_surface_h buffer; int width; @@ -131,6 +133,89 @@ static tdm_error _tdm_vc4_output_update_status(tdm_vc4_output_data *output_data, tdm_output_conn_status status); +static void +_tdm_vc4_display_buffer_destroy(void *user_data) +{ + tdm_vc4_display_buffer *display_buffer = (tdm_vc4_display_buffer *)user_data; + + if (display_buffer->fb_id > 0) { + int ret = drmModeRmFB(display_buffer->vc4_data->drm_fd, display_buffer->fb_id); + if (ret < 0) { + TDM_ERR("rm fb failed"); + return; + } + TDM_DBG("drmModeRmFB success!!! fb_id:%d", display_buffer->fb_id); + } else + TDM_DBG("drmModeRmFB not called fb_id:%d", display_buffer->fb_id); + + free(display_buffer); +} + +static tdm_vc4_display_buffer * +_tdm_vc4_display_get_buffer(tdm_vc4_data *vc4_data, tbm_surface_h buffer) +{ + tdm_vc4_display_buffer *display_buffer = NULL; + + if (!tbm_surface_internal_get_user_data(buffer, TDM_VC4_BUFFER_KEY, (void **)&display_buffer)) { + unsigned int width; + unsigned int height; + unsigned int format; + unsigned int handles[4] = {0,}; + unsigned int pitches[4] = {0,}; + unsigned int offsets[4] = {0,}; + unsigned int size; + tbm_bo bo; + int i, count, ret; + + display_buffer = calloc(1, sizeof(tdm_vc4_display_buffer)); + RETURN_VAL_IF_FAIL(display_buffer != NULL, NULL); + + if (!tbm_surface_internal_add_user_data(buffer, TDM_VC4_BUFFER_KEY, _tdm_vc4_display_buffer_destroy)) { + TDM_ERR("FAIL to create user_data for surface %p", buffer); + free(display_buffer); + return NULL; + } + if (!tbm_surface_internal_set_user_data(buffer, TDM_VC4_BUFFER_KEY, display_buffer)) { + TDM_ERR("FAIL to set user_data for surface %p", buffer); + tbm_surface_internal_delete_user_data(buffer, TDM_VC4_BUFFER_KEY); + free(display_buffer); + return NULL; + } + + display_buffer->vc4_data = vc4_data; + display_buffer->buffer = buffer; + + width = tbm_surface_get_width(buffer); + height = tbm_surface_get_height(buffer); + format = tbm_surface_get_format(buffer); + count = tbm_surface_internal_get_num_planes(format); + bo = tbm_surface_internal_get_bo(buffer, 0); + handles[0] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32; + for (i = 1; i < count; i++) + handles[i] = handles[0]; + + for (i = 0; i < count; i++) + tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]); + + ret = drmModeAddFB2(vc4_data->drm_fd, width, height, format, + handles, pitches, offsets, &display_buffer->fb_id, 0); + if (ret < 0) { + TDM_ERR("add fb failed: %m"); + free(display_buffer); + return NULL; + } + TDM_DBG("vc4_data->drm_fd : %d, display_buffer->fb_id:%u", vc4_data->drm_fd, + display_buffer->fb_id); + + if (IS_RGB(format)) + display_buffer->width = pitches[0] >> 2; + else + display_buffer->width = pitches[0]; + } + + return display_buffer; +} + static drmModeModeInfoPtr _tdm_vc4_display_get_mode(tdm_vc4_output_data *output_data) { @@ -280,19 +365,6 @@ _tdm_vc4_display_set_crtc(tdm_vc4_data *vc4_data, tdm_vc4_output_data *output_da return TDM_ERROR_NONE; } -static tdm_vc4_display_buffer * -_tdm_vc4_display_find_buffer(tdm_vc4_data *vc4_data, tbm_surface_h buffer) -{ - tdm_vc4_display_buffer *display_buffer = NULL; - - LIST_FOR_EACH_ENTRY(display_buffer, &vc4_data->buffer_list, link) { - if (display_buffer->buffer == buffer) - return display_buffer; - } - - return NULL; -} - static void _tdm_vc4_display_to_tdm_mode(drmModeModeInfoPtr vc4_mode, tdm_output_mode *tdm_mode) @@ -767,44 +839,6 @@ failed: } #endif -static void -_tdm_vc4_display_cb_destroy_buffer(tbm_surface_h buffer, void *user_data) -{ - tdm_vc4_data *vc4_data; - tdm_vc4_display_buffer *display_buffer; - int ret; - - if (!user_data) { - TDM_ERR("no user_data"); - return; - } - if (!buffer) { - TDM_ERR("no buffer"); - return; - } - - vc4_data = (tdm_vc4_data *)user_data; - - display_buffer = _tdm_vc4_display_find_buffer(vc4_data, buffer); - if (!display_buffer) { - TDM_ERR("no display_buffer"); - return; - } - LIST_DEL(&display_buffer->link); - - if (display_buffer->fb_id > 0) { - ret = drmModeRmFB(vc4_data->drm_fd, display_buffer->fb_id); - if (ret < 0) { - TDM_ERR("rm fb failed"); - return; - } - TDM_DBG("drmModeRmFB success!!! fb_id:%d", display_buffer->fb_id); - } else - TDM_DBG("drmModeRmFB not called fb_id:%d", display_buffer->fb_id); - - free(display_buffer); -} - tdm_error tdm_vc4_display_create_layer_list(tdm_vc4_data *vc4_data) { @@ -864,17 +898,6 @@ tdm_vc4_display_destroy_output_list(tdm_vc4_data *vc4_data) } void -tdm_vc4_display_destroy_buffer_list(tdm_vc4_data *vc4_data) -{ - tdm_vc4_display_buffer *b = NULL, *bb = NULL; - - LIST_FOR_EACH_ENTRY_SAFE(b, bb, &vc4_data->buffer_list, link) { - tdm_buffer_remove_destroy_handler(b->buffer, _tdm_vc4_display_cb_destroy_buffer, vc4_data); - _tdm_vc4_display_cb_destroy_buffer(b->buffer, vc4_data); - } -} - -void tdm_vc4_display_update_output_status(tdm_vc4_data *vc4_data) { tdm_vc4_output_data *output_data = NULL; @@ -1957,73 +1980,24 @@ vc4_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer) tdm_vc4_layer_data *layer_data = layer; tdm_vc4_data *vc4_data; tdm_vc4_display_buffer *display_buffer; - tdm_error err = TDM_ERROR_NONE; - int ret, i, count; RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); RETURN_VAL_IF_FAIL(buffer, TDM_ERROR_INVALID_PARAMETER); vc4_data = layer_data->vc4_data; - display_buffer = _tdm_vc4_display_find_buffer(vc4_data, buffer); + display_buffer = _tdm_vc4_display_get_buffer(vc4_data, buffer); if (!display_buffer) { - display_buffer = calloc(1, sizeof(tdm_vc4_display_buffer)); - if (!display_buffer) { - TDM_ERR("alloc failed"); - return TDM_ERROR_OUT_OF_MEMORY; - } - display_buffer->buffer = buffer; - - err = tdm_buffer_add_destroy_handler(buffer, _tdm_vc4_display_cb_destroy_buffer, - vc4_data); - if (err != TDM_ERROR_NONE) { - TDM_ERR("add destroy handler fail"); - free(display_buffer); - return TDM_ERROR_OPERATION_FAILED; - } - - LIST_ADDTAIL(&display_buffer->link, &vc4_data->buffer_list); + TDM_ERR("alloc failed"); + return TDM_ERROR_OUT_OF_MEMORY; } - if (display_buffer->fb_id == 0) { - unsigned int width; - unsigned int height; - unsigned int format; - unsigned int handles[4] = {0,}; - unsigned int pitches[4] = {0,}; - unsigned int offsets[4] = {0,}; - unsigned int size; - tbm_bo bo; - - width = tbm_surface_get_width(buffer); - height = tbm_surface_get_height(buffer); - format = tbm_surface_get_format(buffer); - count = tbm_surface_internal_get_num_planes(format); - - bo = tbm_surface_internal_get_bo(buffer, 0); - handles[0] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32; - for (i = 1; i < count; i++) - handles[i] = handles[0]; - - for (i = 0; i < count; i++) - tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]); - - ret = drmModeAddFB2(vc4_data->drm_fd, width, height, format, - handles, pitches, offsets, &display_buffer->fb_id, 0); - if (ret < 0) { - TDM_ERR("add fb failed: %m"); - return TDM_ERROR_OPERATION_FAILED; - } - TDM_DBG("vc4_data->drm_fd : %d, display_buffer->fb_id:%u", vc4_data->drm_fd, - display_buffer->fb_id); - - if (IS_RGB(format)) - display_buffer->width = pitches[0] >> 2; - else - display_buffer->width = pitches[0]; - } + if (layer_data->display_buffer) + tbm_surface_internal_unref(layer_data->display_buffer->buffer); layer_data->display_buffer = display_buffer; + tbm_surface_internal_ref(layer_data->display_buffer->buffer); + layer_data->display_buffer_changed = 1; return TDM_ERROR_NONE; @@ -2036,6 +2010,9 @@ vc4_layer_unset_buffer(tdm_layer *layer) RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER); + if (layer_data->display_buffer) + tbm_surface_internal_unref(layer_data->display_buffer->buffer); + layer_data->display_buffer = NULL; layer_data->display_buffer_changed = 1; |