hwc: get display buffer from list 11/203311/3
authorChangyeon Lee <cyeon.lee@samsung.com>
Thu, 4 Apr 2019 06:12:23 +0000 (15:12 +0900)
committerSooChan Lim <sc1.lim@samsung.com>
Tue, 16 Apr 2019 08:24:02 +0000 (08:24 +0000)
Change-Id: I7b884526d0d4f22dbb696b7a3aedb3e643cb57c4

src/tdm_vc4.c
src/tdm_vc4.h
src/tdm_vc4_display.c
src/tdm_vc4_types.h

index 338a8fb..5e24be9 100644 (file)
@@ -214,6 +214,8 @@ tdm_vc4_deinit(tdm_backend_data *bdata)
        _tdm_vc4_udev_deinit(vc4_data);
 #endif
 
+       tdm_vc4_data_destroy_buffer_list(vc4_data);
+
        tdm_vc4_display_destroy_output_list(vc4_data);
 
        if (vc4_data->plane_res)
index 0488d2a..8f1b863 100644 (file)
@@ -94,5 +94,5 @@ 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);
 
 tdm_vc4_layer_data * vc4_output_data_get_layer_data(tdm_vc4_output_data *output_data, int layer_zops);
-
+void                 tdm_vc4_data_destroy_buffer_list(tdm_vc4_data *vc4_data);
 #endif /* _TDM_VC4_H_ */
index 38d84be..ffe914a 100644 (file)
@@ -4,9 +4,6 @@
 
 #include "tdm_vc4.h"
 
-static int tdm_vc4_buffer_key;
-#define TDM_VC4_BUFFER_KEY ((unsigned long)&tdm_vc4_buffer_key)
-
 #define MIN_WIDTH   2
 
 #define MODE_WIDTH_LIMIT 1280
@@ -82,89 +79,6 @@ check_hw_restriction(unsigned int crtc_w, unsigned int crtc_h, unsigned int buf_
        return TDM_ERROR_NONE;
 }
 
-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)
 {
@@ -2322,31 +2236,155 @@ vc4_layer_get_info(tdm_layer *layer, tdm_info_layer *info)
        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_cb_destroy_buffer(tbm_surface_h buffer, void *user_data)
+{
+       tdm_vc4_data *vc4_data;
+       tdm_vc4_display_buffer *display_buffer;
+       char buf[256] = {0,};
+       char *ret_tmp;
+
+       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;
+       }
+
+       if (display_buffer->fb_id > 0) {
+               if (drmModeRmFB(vc4_data->drm_fd, display_buffer->fb_id) < 0) {
+                       ret_tmp = strerror_r(errno, buf, sizeof(buf));
+                       TDM_ERR("rm fb failed: %d(%s,%s)\n", errno, buf, ret_tmp);
+               }
+       }
+
+       TDM_DBG("destroy buffer fd:%d", display_buffer->fds[0]);
+
+       LIST_DEL(&display_buffer->link);
+       free(display_buffer);
+}
+
+void
+tdm_vc4_data_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);
+       }
+}
+
 tdm_error
 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;
+       TDM_DBG("layer[%p]zpos[%d]", layer, layer_data->zpos);
 
-       display_buffer = _tdm_vc4_display_get_buffer(vc4_data, buffer);
+       vc4_data = layer_data->vc4_data;
+       display_buffer = _tdm_vc4_display_find_buffer(vc4_data, buffer);
        if (!display_buffer) {
-               TDM_ERR("alloc failed");
-               return TDM_ERROR_OUT_OF_MEMORY;
-       }
+               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;
 
-       if (layer_data->display_buffer)
-               tbm_surface_internal_unref(layer_data->display_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);
+
+               if (!display_buffer->fb_id) {
+                       display_buffer->width = tbm_surface_get_width(buffer);
+                       display_buffer->height = tbm_surface_get_height(buffer);
+                       display_buffer->format = tbm_surface_get_format(buffer);
+                       display_buffer->count = tbm_surface_internal_get_num_bos(buffer);
+                       count = tbm_surface_internal_get_num_planes(display_buffer->format);
+                       TDM_DBG("set buffer layer(%d): %dx%d %c%c%c%c bo_num:%d plane_num:%d",
+                                       layer_data->capabilities,
+                                       display_buffer->width, display_buffer->height,
+                                       FOURCC_STR(display_buffer->format), display_buffer->count, count);
+
+                       for (i = 0; i < display_buffer->count; i++) {
+                               tbm_bo bo = tbm_surface_internal_get_bo(buffer, i);
+                               display_buffer->handles[i] = tbm_bo_get_handle(bo, TBM_DEVICE_DEFAULT).u32;
+                               display_buffer->fds[i] = tbm_bo_get_handle(bo, TBM_DEVICE_MM).u32; /* ToDo */
+                               TDM_DBG("    set buffer layer(%d): bo%d(fd:%d handle:%d)",
+                                               layer_data->capabilities,
+                                               i, display_buffer->fds[i], display_buffer->handles[i]);
+                       }
+                       for (i = 0; i < count; i++) {
+                               tbm_surface_internal_get_plane_data(buffer, i, &display_buffer->size,
+                                                                                                       &display_buffer->offsets[i],
+                                                                                                       &display_buffer->pitches[i]);
+                               TDM_DBG("    set buffer layer(%d): plane%d(size:%d offset:%d pitch:%d)",
+                                               layer_data->capabilities,
+                                               i, display_buffer->size, display_buffer->offsets[i],
+                                               display_buffer->pitches[i]);
+                       }
 
-       layer_data->display_buffer = display_buffer;
-       tbm_surface_internal_ref(layer_data->display_buffer->buffer);
+                       ret = drmModeAddFB2(vc4_data->drm_fd, display_buffer->width, display_buffer->height,
+                                               display_buffer->format, display_buffer->handles, display_buffer->pitches,
+                                               display_buffer->offsets, &display_buffer->fb_id, 0);
+                       if (ret < 0) {
+                               TDM_ERR("add fb failed: %m");
+                               free(display_buffer);
+                               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);
 
-       layer_data->display_buffer_changed = 1;
+                       if (IS_RGB(display_buffer->format))
+                               display_buffer->width = display_buffer->pitches[0] >> 2;
+                       else
+                               display_buffer->width = display_buffer->pitches[0];
+               }
+       }
+
+       if (layer_data->display_buffer != display_buffer) {
+               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;
 }
index bb06daf..a045117 100644 (file)
@@ -116,10 +116,19 @@ struct _tdm_vc4_data {
 };
 
 struct _tdm_vc4_display_buffer {
-       tdm_vc4_data *vc4_data;
+       struct list_head link;
+
        unsigned int fb_id;
        tbm_surface_h buffer;
        int width;
+       unsigned int height;
+       unsigned int format;
+       unsigned int handles[4];
+       unsigned int fds[4];
+       unsigned int pitches[4];
+       unsigned int offsets[4];
+       unsigned int size;
+       unsigned int count;
 };
 
 struct _tdm_vc4_event_data {