tpl_wayland_egl_thread: Added twe_surface_set_buffer API. 83/134983/3
authorjoonbum.ko <joonbum.ko@samsung.com>
Thu, 27 Apr 2017 04:02:39 +0000 (13:02 +0900)
committerjoonbum.ko <joonbum.ko@samsung.com>
Wed, 21 Jun 2017 07:04:26 +0000 (16:04 +0900)
 - NEW API : twe_surface_set_buffer(twe_surface_h ,tbm_surface_h)
 - I expect it to be called immediately after tbm_surface_queue_dequeue() inside tpl_surface_dequeue_buffer().

 - The input parameter tbm_surface_h must be a dequeued buffer from tbm_surface_queue.

 - Operation :
  * Create twe_wl_buffer_info and set to tbm_surface as user_data.
  * Create wl_buffer with wl_tbm_client, wl_surface and set to twe_wl_buffer_info.
  * Get wl_egl_window's size and set to twe_wl_buffer_info.

Change-Id: I6b1b5d4a46ccb8cb7b475c8a068a1991dc156ab9
Signed-off-by: joonbum.ko <joonbum.ko@samsung.com>
src/tpl_wayland_egl_thread.c
src/tpl_wayland_egl_thread.h

index 89ac01f..eee1b5c 100644 (file)
@@ -22,6 +22,7 @@ typedef struct _twe_thread                    twe_thread;
 typedef struct _twe_thread_context     twe_thread_context;
 typedef void*  twe_display_h;
 typedef void*  twe_surface_h;
+typedef void*  twe_buffer_h;
 
 #else
 #include "wayland-egl/wayland-egl-priv.h"
@@ -29,10 +30,14 @@ typedef void*       twe_surface_h;
 #include "tpl_utils.h"
 #endif
 
+static int buffer_info_key;
+#define KEY_BUFFER_INFO (unsigned long)(&buffer_info_key)
+
 #define CLIENT_QUEUE_SIZE 3
 
 typedef struct _twe_wl_disp_source     twe_wl_disp_source;
 typedef struct _twe_wl_surf_source     twe_wl_surf_source;
+typedef struct _twe_wl_buffer_info     twe_wl_buffer_info;
 
 struct _twe_thread_context {
        int ref_cnt;
@@ -73,6 +78,14 @@ struct _twe_wl_surf_source {
        twe_wl_disp_source *disp_source;
 };
 
+struct _twe_wl_buffer_info {
+       struct wl_proxy *wl_buffer;
+       int dx, dy;
+       int width, height;
+       int rotation;
+       twe_wl_surf_source *surf_source;
+};
+
 static twe_thread_context *_twe_ctx;
 
 static gpointer
@@ -703,6 +716,128 @@ twe_surface_set_rotation_capablity(twe_surface_h twe_surface, tpl_bool_t set)
        source->rotation_capability = set;
 }
 
+void
+__cb_twe_buffer_free_callback(twe_wl_buffer_info *buf_info)
+{
+       twe_wl_surf_source *surf_source = buf_info->surf_source;
+       twe_wl_disp_source *disp_source = surf_source->disp_source;
+
+       TPL_LOG_T("WL_EGL", "[FREE] twe_buffer(%p) wl_buffer(%p)",
+                         buf_info, buf_info->wl_buffer);
+
+       wl_display_flush(disp_source->disp);
+
+       if (buf_info->wl_buffer)
+               wayland_tbm_client_destroy_buffer(disp_source->wl_tbm_client,
+                                                                                 (void *)buf_info->wl_buffer);
+
+       free(buf_info);
+}
+
+static void
+__cb_buffer_release_callback(void *data, struct wl_proxy *wl_buffer)
+{
+       twe_wl_buffer_info *buf_info = NULL;
+       tbm_surface_h tbm_surface = (tbm_surface_h)data;
+
+       TPL_LOG_T("WL_EGL", "[RELEASE_CB] wl_buffer(%p) tbm_surface(%p)",
+                         wl_buffer, tbm_surface);
+
+       if (tbm_surface_internal_is_valid(tbm_surface)) {
+               tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
+                                                                                  (void **)&buf_info);
+               if (buf_info) {
+                       twe_wl_surf_source *surf_source = buf_info->surf_source;
+                       tbm_surface_queue_error_e tsq_err;
+
+                       tsq_err = tbm_surface_queue_release(surf_source->tbm_queue,
+                                                                                               tbm_surface);
+                       if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE)
+                               TPL_ERR("tbm_surface(%p) tsq_err(%d)", tbm_surface, tsq_err);
+
+                       tbm_surface_internal_unref(tbm_surface);
+               }
+
+       } else {
+               TPL_ERR("Invalid parameter | tbm_surface(%p)", tbm_surface);
+       }
+}
+
+static const struct wl_buffer_listener wl_buffer_release_listener = {
+       (void *)__cb_buffer_release_callback,
+};
+
+tpl_result_t
+twe_surface_set_buffer(twe_surface_h twe_surface, tbm_surface_h tbm_surface)
+{
+       twe_wl_surf_source *source = (twe_wl_surf_source *)twe_surface;
+       twe_wl_buffer_info *buf_info = NULL;
+       struct wl_egl_window *wl_egl_window = NULL;
+       int ret = 0;
+
+       if (!source) {
+               TPL_ERR("Invalid parameter. twe_surface(%p)", twe_surface);
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       wl_egl_window = source->wl_egl_window;
+
+       if (!tbm_surface || !tbm_surface_internal_is_valid(tbm_surface)) {
+               TPL_ERR("Invalid parameter. tbm_surface(%p)", tbm_surface);
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
+                                                                          (void **)&buf_info);
+       /* If buf_info is already existed, reuse it. */
+       if (buf_info) {
+               buf_info->rotation = wl_egl_window->rotation;
+               buf_info->dx = wl_egl_window->dx;
+               buf_info->dy = wl_egl_window->dy;
+
+               return TPL_ERROR_NONE;
+       } else {
+               buf_info = (twe_wl_buffer_info *)calloc(1, sizeof(twe_wl_buffer_info));
+       }
+
+       if (!buf_info) {
+               TPL_ERR("Failed to allocate memory for twe_wl_buffer_info.");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       buf_info->wl_buffer =
+               (struct wl_proxy *)wayland_tbm_client_create_buffer(
+                               source->disp_source->wl_tbm_client, tbm_surface);
+
+       if (!buf_info->wl_buffer) {
+               TPL_ERR("Failed to create wl_buffer from tbm_surface(%p)",
+                               tbm_surface);
+               free(buf_info);
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       wl_buffer_add_listener((void *)buf_info->wl_buffer,
+                                                  &wl_buffer_release_listener, tbm_surface);
+       wl_display_flush(source->disp_source->disp);
+
+       ret = tbm_surface_internal_add_user_data(tbm_surface, KEY_BUFFER_INFO,
+                                                                                        (tbm_data_free)__cb_twe_buffer_free_callback);
+       if (ret) {
+               ret = tbm_surface_internal_set_user_data(tbm_surface,
+                                                                                                KEY_BUFFER_INFO,
+                                                                                                buf_info);
+       }
+
+       if (!ret) {
+               TPL_ERR("Failed to set user_data to tbm_surface(%p)", tbm_surface);
+               free(buf_info);
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       return TPL_ERROR_NONE;
+}
+
+
 #ifdef WORKER_TEST_ONLY
 static void reg_global(void *data,
                                           struct wl_registry *wl_registry,
index 405f2a7..337d80d 100644 (file)
@@ -9,6 +9,7 @@ typedef struct _twe_thread_context      twe_thread_context;
 
 typedef void*  twe_display_h;
 typedef void*  twe_surface_h;
+typedef void*  twe_buffer_h;
 
 twe_thread*
 twe_thread_create(void);
@@ -39,3 +40,6 @@ twe_surface_get_rotation(twe_surface_h twe_surface);
 void
 twe_surface_set_rotation_capablity(twe_surface_h twe_surface, tpl_bool_t set);
 
+tpl_result_t
+twe_surface_set_buffer(twe_surface_h twe_surface, tbm_surface_h tbm_surface);
+