ref/unref display_buffer by using buffer's user_data 86/172686/2
authorBoram Park <boram1288.park@samsung.com>
Thu, 15 Mar 2018 06:56:00 +0000 (15:56 +0900)
committerBoram Park <boram1288.park@samsung.com>
Thu, 15 Mar 2018 07:34:45 +0000 (16:34 +0900)
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: If24e558b0136c0f0072b223f62837e2a55557db9

src/tdm_exynos.c
src/tdm_exynos_display.c
src/tdm_exynos_display.h
src/tdm_exynos_layer.c
src/tdm_exynos_layer.h
src/tdm_exynos_output.c
src/tdm_exynos_types.h

index 561574a1dfc6074271e5c18e05239eed10fdf154..7213e50d5a45601e2b07e8366d47b7c62edf45e9 100644 (file)
@@ -222,7 +222,6 @@ tdm_exynos_deinit(tdm_backend_data *bdata)
 
        drmRemoveUserHandler(exynos_data->drm_fd, _tdm_exynos_drm_user_handler);
 
-       tdm_exynos_layer_destroy_buffer_list(exynos_data);
        tdm_exynos_display_destroy_output_list(exynos_data);
 
        if (exynos_data->plane_res)
index 7d5024e979cdc3717382245a0f18613c5fc7fef7..d2a28061af1d786796be8f187a2fb3c4a44546b1 100644 (file)
@@ -341,6 +341,8 @@ tdm_exynos_display_destroy_output_list(tdm_exynos_data *exynos_data)
                        tdm_exynos_layer_data *l = NULL, *ll = NULL;
                        LIST_FOR_EACH_ENTRY_SAFE(l, ll, &o->layer_list, link) {
                                LIST_DEL(&l->link);
+                               if (l->display_buffer)
+                                       tbm_surface_internal_unref(l->display_buffer->buffer);
                                if (l->formats)
                                        free(l->formats);
                                if (l->props)
@@ -617,20 +619,6 @@ tdm_exynos_display_get_property(tdm_exynos_data *exynos_data,
        return TDM_ERROR_OPERATION_FAILED;
 }
 
-tdm_exynos_display_buffer *
-tdm_exynos_display_find_buffer(tdm_exynos_data *exynos_data,
-                                                                        tbm_surface_h buffer)
-{
-       tdm_exynos_display_buffer *display_buffer = NULL;
-
-       LIST_FOR_EACH_ENTRY(display_buffer, &exynos_data->buffer_list, link) {
-               if (display_buffer->buffer == buffer)
-                       return display_buffer;
-       }
-
-       return NULL;
-}
-
 tdm_error
 exynos_display_get_capability(tdm_backend_data *bdata, tdm_caps_display *caps)
 {
index da499b9d8634bab7c8b9e80df5dcac69a5fa1b75..94a1fe9d8d85fadf425e7f8aeefa8aebb14a477c 100644 (file)
@@ -13,7 +13,6 @@ tdm_error    tdm_exynos_display_set_property(tdm_exynos_data *exynos_data,
 tdm_error    tdm_exynos_display_get_property(tdm_exynos_data *exynos_data,
                                                                                                        unsigned int obj_id, unsigned int obj_type,
                                                                                                        const char *name, unsigned int *value, int *is_immutable);
-tdm_exynos_display_buffer* tdm_exynos_display_find_buffer(tdm_exynos_data *exynos_data, tbm_surface_h buffer);
 void         tdm_exynos_display_to_tdm_mode(drmModeModeInfoPtr drm_mode, tdm_output_mode *tdm_mode);
 
 
index 5eb7a71d0b633e9c5fd710352bd833b4b8b6eaeb..3b226b287f9ab97e26a8ec3bfc7ca2b0f6cbaf0d 100644 (file)
@@ -6,51 +6,16 @@
 #include <tdm_helper.h>
 #include "tdm_exynos.h"
 
+static int tdm_exynos_buffer_key;
+#define TDM_EXYNOS_BUFFER_KEY ((unsigned long)&tdm_exynos_buffer_key)
+
 static void
-_tdm_exynos_layer_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
+_tdm_exynos_display_buffer_destroy(void *user_data)
 {
-       tdm_exynos_data *exynos_data;
-       tdm_exynos_output_data *output_data = NULL;
-       tdm_exynos_layer_data *layer_data = NULL;
-       tdm_exynos_display_buffer *display_buffer;
-       int ret;
-
-       if (!user_data) {
-               TDM_ERR("no user_data");
-               return;
-       }
-       if (!buffer) {
-               TDM_ERR("no buffer");
-               return;
-       }
-
-       exynos_data = (tdm_exynos_data *)user_data;
-
-       display_buffer = tdm_exynos_display_find_buffer(exynos_data, buffer);
-       if (!display_buffer) {
-               TDM_ERR("no display_buffer");
-               return;
-       }
-       LIST_DEL(&display_buffer->link);
-
-       if (exynos_data->hwc_mode) {
-               /* pending to free the display buffer when the display buffer is set on the layer */
-               LIST_FOR_EACH_ENTRY(output_data, &exynos_data->output_list, link) {
-                       if (!output_data->hwc_enable) continue;
-
-                       LIST_FOR_EACH_ENTRY(layer_data, &output_data->layer_list, link) {
-                               if (!layer_data->display_buffer) continue;
-                               if (layer_data->display_buffer->buffer == buffer && display_buffer->fb_id > 0) {
-                                       TDM_DBG("drmModeRmFB is pending!!! fb_id:%d", display_buffer->fb_id);
-                                       layer_data->pending_free_display_buffer = display_buffer;
-                                       return;
-                               }
-                       }
-               }
-       }
+       tdm_exynos_display_buffer *display_buffer = (tdm_exynos_display_buffer *)user_data;
 
        if (display_buffer->fb_id > 0) {
-               ret = drmModeRmFB(exynos_data->drm_fd, display_buffer->fb_id);
+               int ret = drmModeRmFB(display_buffer->exynos_data->drm_fd, display_buffer->fb_id);
                if (ret < 0) {
                        TDM_ERR("rm fb failed");
                        return;
@@ -62,15 +27,69 @@ _tdm_exynos_layer_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
        free(display_buffer);
 }
 
-void
-tdm_exynos_layer_destroy_buffer_list(tdm_exynos_data *exynos_data)
+static tdm_exynos_display_buffer *
+_tdm_exynos_display_get_buffer(tdm_exynos_data *exynos_data, tbm_surface_h buffer)
 {
-       tdm_exynos_display_buffer *b = NULL, *bb = NULL;
+       tdm_exynos_display_buffer *display_buffer = NULL;
+
+       if (!tbm_surface_internal_get_user_data(buffer, TDM_EXYNOS_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_exynos_display_buffer));
+               RETURN_VAL_IF_FAIL(display_buffer != NULL, NULL);
+
+               if (!tbm_surface_internal_add_user_data(buffer, TDM_EXYNOS_BUFFER_KEY, _tdm_exynos_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_EXYNOS_BUFFER_KEY, display_buffer)) {
+                       TDM_ERR("FAIL to set user_data for surface %p", buffer);
+                       tbm_surface_internal_delete_user_data(buffer, TDM_EXYNOS_BUFFER_KEY);
+                       free(display_buffer);
+                       return NULL;
+               }
+
+               display_buffer->exynos_data = exynos_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]);
 
-       LIST_FOR_EACH_ENTRY_SAFE(b, bb, &exynos_data->buffer_list, link) {
-               tdm_buffer_remove_destroy_handler(b->buffer, _tdm_exynos_layer_cb_destroy_buffer, exynos_data);
-               _tdm_exynos_layer_cb_destroy_buffer(b->buffer, exynos_data);
+               ret = drmModeAddFB2(exynos_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("exynos_data->drm_fd : %d, display_buffer->fb_id:%u", exynos_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;
 }
 
 tdm_error
@@ -256,74 +275,24 @@ exynos_layer_set_buffer(tdm_layer *layer, tbm_surface_h buffer)
        tdm_exynos_layer_data *layer_data = layer;
        tdm_exynos_data *exynos_data;
        tdm_exynos_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);
 
        exynos_data = layer_data->exynos_data;
 
-       display_buffer = tdm_exynos_display_find_buffer(exynos_data, buffer);
+       display_buffer = _tdm_exynos_display_get_buffer(exynos_data, buffer);
        if (!display_buffer) {
-               display_buffer = calloc(1, sizeof(tdm_exynos_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_exynos_layer_cb_destroy_buffer, exynos_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, &exynos_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;
-
-               width = tbm_surface_get_width(buffer);
-               height = tbm_surface_get_height(buffer);
-               format = tbm_surface_get_format(buffer);
-               count = tbm_surface_internal_get_num_bos(buffer);
-               for (i = 0; i < count; i++) {
-                       tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
-                       handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
-               }
-               count = tbm_surface_internal_get_num_planes(format);
-               for (i = 0; i < count; i++)
-                       tbm_surface_internal_get_plane_data(buffer, i, &size, &offsets[i], &pitches[i]);
-
-               TDM_DBG("AddFB2: drm_fd(%d) size(%dx%d) format(%c%c%c%c) handles(%d,%d,%d) pitches(%d,%d,%d) offsets(%d,%d,%d) buffer(%p)",
-                               exynos_data->drm_fd, width, height, FOURCC_STR(format), handles[0], handles[1], handles[2],
-                               pitches[0], pitches[1], pitches[2], offsets[0], offsets[1], offsets[2], buffer);
-
-               ret = drmModeAddFB2(exynos_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("exynos_data->drm_fd: %d, plane_id:%u, zpos(%d) display_buffer->fb_id:%u",
-                               exynos_data->drm_fd, layer_data->plane_id, layer_data->zpos, 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;
@@ -336,7 +305,10 @@ exynos_layer_unset_buffer(tdm_layer *layer)
 
        RETURN_VAL_IF_FAIL(layer_data, TDM_ERROR_INVALID_PARAMETER);
 
-       layer_data->display_buffer = NULL;
+       if (!(layer_data->capabilities & TDM_LAYER_CAPABILITY_PRIMARY) && layer_data->display_buffer) {
+               tbm_surface_internal_unref(layer_data->display_buffer->buffer);
+               layer_data->display_buffer = NULL;
+       }
        layer_data->display_buffer_changed = 1;
 
        return TDM_ERROR_NONE;
index f01377bd4029d689610f286368dd8e06b60bb2f2..cad66b47a34eb5d400eb4aa502aaecc1cc3cff87 100644 (file)
@@ -9,7 +9,5 @@ tdm_exynos_layer_get_supported_format(tdm_layer *layer, const tbm_format **out_f
 tdm_error
 exynos_layer_get_available_properties(tdm_layer *layer, const tdm_prop **out_props,
                                                                          int *out_prop_count);
-void
-tdm_exynos_layer_destroy_buffer_list(tdm_exynos_data *exynos_data);
 
 #endif /* _TDM_EXYNOS_LAYER_H_ */
index db409bcedfbc8a1f8ebee98bc5591cccfb40500c..47b36095d66de63aaaae36c5ef3e62b7980f635b 100644 (file)
@@ -260,26 +260,6 @@ _tdm_exynos_output_transform_layer_info(int width, int height, tdm_info_layer *i
        info->dst_pos = dst_pos;
 }
 
-static int
-_tdm_exynos_output_free_display_buffer(tdm_exynos_data *exynos_data, tdm_exynos_display_buffer *display_buffer)
-{
-       int ret;
-
-       if (display_buffer->fb_id > 0) {
-               ret = drmModeRmFB(exynos_data->drm_fd, display_buffer->fb_id);
-               if (ret < 0) {
-                       TDM_ERR("rm fb failed");
-                       return 0;
-               }
-               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);
-
-       return 1;
-}
-
 static tdm_error
 _tdm_exynos_output_commit_primary_layer(tdm_exynos_layer_data *layer_data,
                                                                                                  void *user_data, int *do_waitvblank)
@@ -363,31 +343,11 @@ _tdm_exynos_output_commit_primary_layer(tdm_exynos_layer_data *layer_data,
 
                *do_waitvblank = 1;
 
-               /* free pending display buffer */
-               if (layer_data->pending_free_display_buffer) {
-                       _tdm_exynos_output_free_display_buffer(output_data->exynos_data, layer_data->pending_free_display_buffer);
-                       layer_data->pending_free_display_buffer = NULL;
-               }
-
                return TDM_ERROR_NONE;
        } else if (layer_data->display_buffer_changed) {
                layer_data->display_buffer_changed = 0;
 
-               if (!layer_data->display_buffer) {
-                       TDM_DBG("SetCrtc: drm_fd(%d) crtc_id(%u) off",
-                                       exynos_data->drm_fd, output_data->crtc_id);
-
-                       if (drmModeSetCrtc(exynos_data->drm_fd, output_data->crtc_id,
-                                                          0, 0, 0, NULL, 0, NULL)) {
-                               TDM_ERR("unset crtc failed: %m");
-                               return TDM_ERROR_OPERATION_FAILED;
-                       }
-
-                       if (output_data->status == TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
-                               tdm_exynos_output_update_status(output_data, TDM_OUTPUT_CONN_STATUS_CONNECTED);
-
-                       *do_waitvblank = 0;
-               } else {
+               if (layer_data->display_buffer) {
                        tbm_surface_info_s info;
                        int ret;
                        tdm_exynos_event_data *event_data = calloc(1, sizeof(tdm_exynos_event_data));
@@ -415,12 +375,9 @@ _tdm_exynos_output_commit_primary_layer(tdm_exynos_layer_data *layer_data,
                                return TDM_ERROR_OPERATION_FAILED;
                        }
                        *do_waitvblank = 0;
-
-                       /* free pending display buffer */
-                       if (layer_data->pending_free_display_buffer) {
-                               _tdm_exynos_output_free_display_buffer(output_data->exynos_data, layer_data->pending_free_display_buffer);
-                               layer_data->pending_free_display_buffer = NULL;
-                       }
+               } else {
+                       /* to call a user commit handler whenever committed */
+                       *do_waitvblank = 1;
                }
        }
 
@@ -526,12 +483,6 @@ _tdm_exynos_output_commit_layer(tdm_exynos_layer_data *layer_data)
                return TDM_ERROR_OPERATION_FAILED;
        }
 
-       /* free pending display buffer */
-       if (layer_data->pending_free_display_buffer) {
-               _tdm_exynos_output_free_display_buffer(output_data->exynos_data, layer_data->pending_free_display_buffer);
-               layer_data->pending_free_display_buffer = NULL;
-       }
-
        return TDM_ERROR_NONE;
 }
 
index 84bf8a3b877fdec136078b844ae754bec0b5ac9c..6e7affde58e6297f181f48e8ca1ca3c293b59ffa 100644 (file)
@@ -170,8 +170,6 @@ struct _tdm_exynos_layer_data {
 
        tdm_exynos_display_buffer *display_buffer;
        int display_buffer_changed;
-       tdm_exynos_display_buffer *pending_free_display_buffer;
-       int pending_free_ready;
 
        tbm_format *formats;
        int format_count;
@@ -208,8 +206,7 @@ struct _tdm_exynos_hwc_window_data {
 };
 
 struct _tdm_exynos_display_buffer {
-       struct list_head link;
-
+       tdm_exynos_data *exynos_data;
        unsigned int fb_id;
        tbm_surface_h buffer;
        int width;