From 6e2d314e63195043b33f4eccc198b063a0c2346b Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 29 Dec 2017 16:24:20 +0900 Subject: [PATCH 01/16] tpl_wl_vk_thread: Supported to resize swapchain. Change-Id: Ibc427cbcdf95a9920b139104ce4ed4922d072e82 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 14 +++++++++++++- src/tpl_wl_vk_thread.c | 18 +++++++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index f37d599..ba1ece6 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -1585,6 +1585,18 @@ static void __cb_tbm_queue_reset_callback(tbm_surface_queue_h tbm_queue, void *data) { + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; + + if (surf_source && !g_source_is_destroyed(&surf_source->gsource)) { + surf_source->swapchain_properties.width = + tbm_surface_queue_get_width(tbm_queue); + surf_source->swapchain_properties.height = + tbm_surface_queue_get_height(tbm_queue); + surf_source->swapchain_properties.buffer_count = + tbm_surface_queue_get_size(tbm_queue); + surf_source->format = tbm_surface_queue_get_format(tbm_queue); + } + TPL_LOG_T(BACKEND, "tbm_queue(%p) has been reset!", tbm_queue); } @@ -2551,7 +2563,7 @@ twe_surface_create_swapchain(twe_surface_h twe_surface, if (tbm_surface_queue_add_reset_cb(surf_source->tbm_queue, __cb_tbm_queue_reset_callback, - NULL) != TBM_SURFACE_QUEUE_ERROR_NONE) { + surf_source) != TBM_SURFACE_QUEUE_ERROR_NONE) { TPL_ERR("Failed to register reset callback to tbm_surface_queue(%p)", surf_source->tbm_queue); tbm_surface_queue_destroy(surf_source->tbm_queue); diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c index 8167b3d..b175f39 100644 --- a/src/tpl_wl_vk_thread.c +++ b/src/tpl_wl_vk_thread.c @@ -608,12 +608,24 @@ __tpl_wl_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, TPL_ASSERT(wayland_vk_wsi_display); if (wayland_vk_wsi_surface->tbm_queue) { - TPL_LOG_T("WL_VK", "[REUSE] wayland_vk_wsi_surface(%p) tbm_queue(%p) size(%d)", - wayland_vk_wsi_surface, wayland_vk_wsi_surface->tbm_queue, - wayland_vk_wsi_surface->buffer_count); + int old_width = tbm_surface_queue_get_width(wayland_vk_wsi_surface->tbm_queue); + int old_height = tbm_surface_queue_get_height(wayland_vk_wsi_surface->tbm_queue); + + if (old_width != width || old_height != height) { + tbm_surface_queue_reset(wayland_vk_wsi_surface->tbm_queue, + width, height, format); + TPL_LOG_T("WL_VK", + "[RESIZE] wayland_vk_wsi_surface(%p) tbm_queue(%p), (%d x %d) -> (%d x %d)", + wayland_vk_wsi_surface, wayland_vk_wsi_surface->tbm_queue, + old_width, old_height, width, height); + } + wayland_vk_wsi_surface->buffer_count = tbm_surface_queue_get_size(wayland_vk_wsi_surface->tbm_queue); wayland_vk_wsi_surface->reset = TPL_FALSE; + TPL_LOG_T("WL_VK", "[REUSE] wayland_vk_wsi_surface(%p) tbm_queue(%p) size(%d)", + wayland_vk_wsi_surface, wayland_vk_wsi_surface->tbm_queue, + wayland_vk_wsi_surface->buffer_count); return TPL_ERROR_NONE; } -- 2.7.4 From 9f3cbfac505490b319b774fba24fd3bd560d151e Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Tue, 2 Jan 2018 13:25:03 +0900 Subject: [PATCH 02/16] tpl: Added a new API tpl_surface_get() - tpl_surface_t *tpl_surface_get(tpl_display_t *display, tpl_handle_t handle) - Like tpl_display_get(), it will find and return if there is a tpl_surface that was created in the given native handle at runtime. - Avoid creating multiple tpl_surfaces with the same native handle. Change-Id: Ia2b7a7ddef32153c47ba11dea4e08130fd36cb56 Signed-off-by: joonbum.ko --- src/tpl.h | 22 ++++++++++++++++++++++ src/tpl_surface.c | 31 ++++++++++++++++++++++++------- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/tpl.h b/src/tpl.h index 0ebf067..27a3ba9 100644 --- a/src/tpl.h +++ b/src/tpl.h @@ -396,6 +396,28 @@ tpl_surface_create(tpl_display_t *display, tpl_handle_t handle, tpl_surface_type_t type, tbm_format format); /** + * Get TPL surface object for the given native surface. + * + * If there's already existing TPL surface for the given native surface, + * then return the existed TPL surface. + * + * This API is not incremented the reference count of found TPL surface object. + * To ensure that the obtained TPL surface is safe to use, it must be increased + * the ref count by using tpl_object_reference(). + * When it becomes unnecessary, it should be decreased by using tpl_object_unreference(). + * + * @param display TPL display used to create TPL surface with given handle. + * @param handle Handle to the native surface. + * @return pointer to TPL surface if it has already been created, NULL otherwise. + * + * @see tpl_surface_create() + * @see tpl_object_reference() + * @see tpl_object_unreference() + */ +tpl_surface_t * +tpl_surface_get(tpl_display_t *display, tpl_handle_t handle); + +/** * Get the TPL display where the given TPL surface was created from. * * @param surface surface to get display. diff --git a/src/tpl_surface.c b/src/tpl_surface.c index a7a6b1e..2252f15 100644 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -36,13 +36,6 @@ tpl_surface_create(tpl_display_t *display, tpl_handle_t handle, return NULL; } - surface = __tpl_runtime_find_surface(display->backend.type, handle); - if (surface) { - TPL_LOG_F("[REUSE] tpl_display_t(%p) tpl_surface_t(%p) native_handle(%p) format(%d)", - display, surface, handle, format); - return surface; - } - surface = (tpl_surface_t *) calloc(1, sizeof(tpl_surface_t)); if (!surface) { TPL_ERR("Failed to allocate memory for surface!"); @@ -89,6 +82,30 @@ tpl_surface_create(tpl_display_t *display, tpl_handle_t handle, return surface; } +tpl_surface_t * +tpl_surface_get(tpl_display_t *display, tpl_handle_t handle) +{ + tpl_surface_t *surface = NULL; + + if (!display) { + TPL_ERR("Display is NULL!"); + return NULL; + } + + if (!handle) { + TPL_ERR("Handle is NULL!"); + return NULL; + } + + surface = __tpl_runtime_find_surface(display->backend.type, handle); + if (surface) { + TPL_LOG_F("[REUSE] tpl_display_t(%p) tpl_surface_t(%p) native_handle(%p)", + display, surface, handle); + } + + return surface; +} + tpl_display_t * tpl_surface_get_display(tpl_surface_t *surface) { -- 2.7.4 From c4f5aacbde5bb2e46e67975a360f96353a5cecd5 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Tue, 2 Jan 2018 14:50:50 +0900 Subject: [PATCH 03/16] tpl_wayland_egl_thread: Set to GUARANTEE_CYCLE mode to swapchain tbm_queue. Change-Id: Ie9435f58924932314bbe7a37b71a88cd6937f077 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index ba1ece6..96dbb8c 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -2561,6 +2561,11 @@ twe_surface_create_swapchain(twe_surface_h twe_surface, width, height, TBM_FORMAT_ARGB8888); + if (!surf_source->tbm_queue) { + TPL_ERR("TBM surface queue creation failed!"); + return TPL_ERROR_OUT_OF_MEMORY; + } + if (tbm_surface_queue_add_reset_cb(surf_source->tbm_queue, __cb_tbm_queue_reset_callback, surf_source) != TBM_SURFACE_QUEUE_ERROR_NONE) { @@ -2570,9 +2575,13 @@ twe_surface_create_swapchain(twe_surface_h twe_surface, return TPL_ERROR_INVALID_OPERATION; } - if (!surf_source->tbm_queue) { - TPL_ERR("TBM surface queue creation failed!"); - return TPL_ERROR_OUT_OF_MEMORY; + if (tbm_surface_queue_set_modes(surf_source->tbm_queue, + TBM_SURFACE_QUEUE_MODE_GUARANTEE_CYCLE) != + TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to set queue mode to tbm_surface_queue(%p)", + surf_source->tbm_queue); + tbm_surface_queue_destroy(surf_source->tbm_queue); + return TPL_ERROR_INVALID_OPERATION; } if (tbm_surface_queue_add_trace_cb(surf_source->tbm_queue, -- 2.7.4 From 37144dc23b3056ad32ee27eb807ab3d19a7d356e Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Tue, 2 Jan 2018 15:10:38 +0900 Subject: [PATCH 04/16] tpl_wayland_egl_thread: Fixed wrong codes in committed_buffers list. Change-Id: Ice96bd544bb38800a6678c1c44bf79875fb26c5d Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 96dbb8c..ef91619 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -1224,8 +1224,6 @@ static void __cb_tss_flusher_flush_callback(void *data, */ if (surf_source->committed_buffers) { TPL_OBJECT_LOCK(&surf_source->obj); - __tpl_list_fini(surf_source->committed_buffers, - (tpl_free_func_t)__cb_buffer_remove_from_list); while (!__tpl_list_is_empty(surf_source->committed_buffers)) { tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; tbm_surface_h tbm_surface = @@ -2257,10 +2255,19 @@ _twe_thread_wl_surf_source_destroy(void *source) surf_source->in_use_buffers = NULL; } - if (surf_source->committed_buffers) { - __tpl_list_free(surf_source->committed_buffers, - (tpl_free_func_t)__cb_buffer_remove_from_list); - surf_source->committed_buffers = NULL; + while (!__tpl_list_is_empty(surf_source->committed_buffers)) { + tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; + tbm_surface_h tbm_surface = + __tpl_list_pop_front(surf_source->committed_buffers, + (tpl_free_func_t)__cb_buffer_remove_from_list); + + TRACE_ASYNC_END((int)tbm_surface, "[COMMIT ~ RELEASE] BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo( + tbm_surface, 0))); + tsq_err = tbm_surface_queue_release(surf_source->tbm_queue, tbm_surface); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) + TPL_ERR("Failed to release. tbm_surface(%p) tsq_err(%d)", + tbm_surface, tsq_err); } if (surf_source->vblank_waiting_buffers) { -- 2.7.4 From 7133e8bfdb37f0de9a98dd8bd09503df37c86eca Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Tue, 2 Jan 2018 16:32:34 +0900 Subject: [PATCH 05/16] tpl_wayland_egl_thread: Fixed potential bugs related with the swapchain. - vk_sub_thread must be equal to swapchain's lifetime. Change-Id: I85c84feea5d21e2b64ceda2625af0158483406cd Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 121 +++++++++++++++++++++++++++++-------------- 1 file changed, 82 insertions(+), 39 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index ef91619..49dcb7e 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -1659,6 +1659,8 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, disp_source = surf_source->disp_source; + TPL_OBJECT_LOCK(&surf_source->obj); + surf_source->vblank_done = TPL_TRUE; if (!disp_source->is_vulkan_dpy) @@ -1705,6 +1707,8 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, break; } } + + TPL_OBJECT_UNLOCK(&surf_source->obj); } static tdm_client_vblank* @@ -1787,6 +1791,8 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, } if (surf_source->committed_buffers) { + __tpl_list_remove_data(surf_source->in_use_buffers, + (void *)tbm_surface, TPL_FIRST, NULL); __tpl_list_push_back(surf_source->committed_buffers, tbm_surface); } @@ -1954,6 +1960,9 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) _twe_thread_wl_surface_commit(surf_source, tbm_surface); } else { /* wayland_vulkan */ + TPL_LOG_T(BACKEND, "[ACQ] tbm_surface(%p) bo(%d)", + tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); switch (surf_source->swapchain_properties.present_mode) { case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface); @@ -2325,6 +2334,8 @@ _vk_sub_thread_loop(gpointer data) g_mutex_lock(&surf_source->sub_thread_mutex); /* Do nothing */ + TPL_DEBUG("vk_sub_thread(%p) vk_sub_loop(%p) run", + surf_source->vk_sub_thread, surf_source->vk_sub_loop); g_cond_signal(&surf_source->sub_thread_cond); g_mutex_unlock(&surf_source->sub_thread_mutex); @@ -2421,28 +2432,9 @@ twe_surface_add(twe_thread* thread, _twe_surface_buffer_flusher_init(source); } else { struct wl_surface *wl_surf = (struct wl_surface *)native_handle; - GMainContext *context; source->wl_egl_window = NULL; source->surf = wl_surf; - - /* TODO : Below lines about sub_thread will be deleted. - * It is temporary code for sync_drawing. */ - - g_mutex_init(&source->sub_thread_mutex); - g_cond_init(&source->sub_thread_cond); - - context = g_main_context_new(); - source->vk_sub_loop = g_main_loop_new(context, FALSE); - g_main_context_unref(context); - - g_mutex_lock(&source->sub_thread_mutex); - - source->vk_sub_thread = g_thread_new("twe_sub_thread", _vk_sub_thread_loop, - source); - - g_cond_wait(&source->sub_thread_cond, &source->sub_thread_mutex); - g_mutex_unlock(&source->sub_thread_mutex); } source->surf_del_source = _twe_del_source_init(ctx, source); @@ -2490,25 +2482,6 @@ twe_surface_del(twe_surface_h twe_surface) twe_surface); surf_del_source = surf_source->surf_del_source; - while (surf_source->vk_sub_loop && - !g_main_loop_is_running(surf_source->vk_sub_loop)) { - /* Do nothing */ - } - - g_mutex_lock(&surf_source->sub_thread_mutex); - - g_main_loop_quit(surf_source->vk_sub_loop); - g_thread_join(surf_source->vk_sub_thread); - g_main_loop_unref(surf_source->vk_sub_loop); - - g_mutex_unlock(&surf_source->sub_thread_mutex); - - surf_source->vk_sub_thread = NULL; - surf_source->vk_sub_loop = NULL; - - g_mutex_clear(&surf_source->sub_thread_mutex); - g_cond_clear(&surf_source->sub_thread_cond); - g_mutex_lock(&_twe_ctx->thread_mutex); _twe_thread_del_source_trigger(surf_del_source); @@ -2528,12 +2501,19 @@ twe_surface_create_swapchain(twe_surface_h twe_surface, { twe_wl_surf_source *surf_source = (twe_wl_surf_source *)twe_surface; twe_wl_disp_source *disp_source = NULL; + GMainContext *context; if (!surf_source || g_source_is_destroyed(&surf_source->gsource)) { TPL_ERR("twe_surface(%p) is invalid.", twe_surface); return TPL_ERROR_INVALID_PARAMETER; } + if (surf_source->tbm_queue) { + TPL_LOG_B(BACKEND, "[REUSE SWAPCHAIN] surf_source(%p) tbm_queue(%p)", + surf_source, surf_source->tbm_queue); + return TPL_ERROR_NONE; + } + disp_source = surf_source->disp_source; TPL_ASSERT(disp_source); @@ -2626,6 +2606,22 @@ twe_surface_create_swapchain(twe_surface_h twe_surface, "[SWAPCHAIN_CREATE][2/2] w(%d) h(%d) f(%d) p(%d) b_cnt(%d)", width, height, format, present_mode, buffer_count); + /* TODO : Below lines about sub_thread will be deleted. + * It is temporary code for sync_drawing. */ + + g_mutex_init(&surf_source->sub_thread_mutex); + g_cond_init(&surf_source->sub_thread_cond); + + context = g_main_context_new(); + surf_source->vk_sub_loop = g_main_loop_new(context, FALSE); + + g_main_context_unref(context); + g_mutex_lock(&surf_source->sub_thread_mutex); + surf_source->vk_sub_thread = g_thread_new("twe_sub_thread", _vk_sub_thread_loop, + surf_source); + g_cond_wait(&surf_source->sub_thread_cond, &surf_source->sub_thread_mutex); + g_mutex_unlock(&surf_source->sub_thread_mutex); + return TPL_ERROR_NONE; } @@ -2642,6 +2638,54 @@ twe_surface_destroy_swapchain(twe_surface_h twe_surface) TPL_LOG_T(BACKEND, "[SWAPCHAIN_DESTROY] twe_surface(%p) tbm_queue(%p)", twe_surface, surf_source->tbm_queue); + while (surf_source->vk_sub_loop && + !g_main_loop_is_running(surf_source->vk_sub_loop)) { + /* Do nothing */ + } + + if (surf_source->vk_sub_thread) { + TPL_DEBUG("vk_sub_thread(%d) exit.", surf_source->vk_sub_thread); + g_mutex_lock(&surf_source->sub_thread_mutex); + + g_main_loop_quit(surf_source->vk_sub_loop); + /* Waiting for all drawing buffers. */ + g_thread_join(surf_source->vk_sub_thread); + g_main_loop_unref(surf_source->vk_sub_loop); + + g_mutex_unlock(&surf_source->sub_thread_mutex); + + surf_source->vk_sub_thread = NULL; + surf_source->vk_sub_loop = NULL; + + g_mutex_clear(&surf_source->sub_thread_mutex); + g_cond_clear(&surf_source->sub_thread_cond); + } + + /* Waiting for vblank to commit all draw done buffers.*/ + while (surf_source->vblank_waiting_buffers && + !__tpl_list_is_empty(surf_source->vblank_waiting_buffers)) { + __tpl_util_sys_yield(); + } + + if (surf_source->committed_buffers) { + TPL_OBJECT_LOCK(&surf_source->obj); + while (!__tpl_list_is_empty(surf_source->committed_buffers)) { + tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; + tbm_surface_h tbm_surface = + __tpl_list_pop_front(surf_source->committed_buffers, + (tpl_free_func_t)__cb_buffer_remove_from_list); + + TRACE_ASYNC_END((int)tbm_surface, "[COMMIT ~ RELEASE] BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo( + tbm_surface, 0))); + tsq_err = tbm_surface_queue_release(surf_source->tbm_queue, tbm_surface); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) + TPL_ERR("Failed to release. tbm_surface(%p) tsq_err(%d)", + tbm_surface, tsq_err); + } + TPL_OBJECT_UNLOCK(&surf_source->obj); + } + if (surf_source->tbm_queue) { tbm_surface_queue_destroy(surf_source->tbm_queue); surf_source->tbm_queue = NULL; @@ -2830,7 +2874,6 @@ _twe_thread_sync_draw_source_dispatch(GSource *source, GSourceFunc cb, gpointer TRACE_BEGIN("Fence waiting. BO(%d)", tbm_bo_export( tbm_surface_internal_get_bo(tbm_surface, 0))); - /* Below API is blocking call. * It is waiting for drawing complete in GPU. */ if (tbm_sync_fence_wait(sync_draw_source->draw_fence_fd, -1) != 1) { -- 2.7.4 From 85329f71c77c11d0728a16110821069d5a7c35f8 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Tue, 2 Jan 2018 19:34:45 +0900 Subject: [PATCH 06/16] tpl_wayland_egl_thread: Partially modified event_fd processing method. - Partially modified the way event_fd is handled between vk_sub_thread and twe_thread. - Twe buffers are in draw_done state and write twice to event_fd to send event, but in twe_thread, event_fd may be read only once, and only one buffer may be acquired. - Supplemented it by adding draw_done_count to surf_source. - It is a valid patch only while using vk_sub_thread. Change-Id: I341907ca1cc6466af4d5e2f6bb5173e9382d925f Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 49dcb7e..c23c77e 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -128,6 +128,7 @@ struct _twe_wl_surf_source { GMainLoop *vk_sub_loop; GMutex sub_thread_mutex; GCond sub_thread_cond; + int draw_done_count; }; struct _twe_wl_buffer_info { @@ -2047,6 +2048,14 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data) TPL_ERR("Failed to read from event_fd(%d)", surf_source->event_fd); + if (surf_source->disp_source->is_vulkan_dpy) { + g_mutex_lock(&surf_source->sub_thread_mutex); + while (surf_source->draw_done_count > 0) { + _twe_thread_wl_surface_acquire_and_commit(surf_source); + surf_source->draw_done_count--; + } + g_mutex_unlock(&surf_source->sub_thread_mutex); + } _twe_thread_wl_surface_acquire_and_commit(surf_source); } @@ -2411,6 +2420,7 @@ twe_surface_add(twe_thread* thread, source->vk_sub_loop = NULL; source->vk_sub_thread = NULL; + source->draw_done_count = 0; __tpl_object_init(&source->obj, TPL_OBJECT_SURFACE, NULL); @@ -2863,6 +2873,7 @@ _twe_thread_sync_draw_source_dispatch(GSource *source, GSourceFunc cb, gpointer int ret; uint64_t value = 1; tbm_surface_h tbm_surface = sync_draw_source->tbm_surface; + twe_wl_surf_source *surf_source = sync_draw_source->buf_info->surf_source; tbm_surface_internal_ref(tbm_surface); @@ -2883,6 +2894,10 @@ _twe_thread_sync_draw_source_dispatch(GSource *source, GSourceFunc cb, gpointer sync_draw_source->draw_fence_fd, errno, buf); } + g_mutex_lock(&surf_source->sub_thread_mutex); + surf_source->draw_done_count++; + g_mutex_unlock(&surf_source->sub_thread_mutex); + /* Draw done */ /* Send event to twe_wl_surf_source */ ret = write(sync_draw_source->draw_done_signal_fd, -- 2.7.4 From 418867374e9bfe583d60a420090779ddfca659c4 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 3 Jan 2018 17:22:45 +0900 Subject: [PATCH 07/16] tpl_wayland_egl_thread: Modified wrong log message. Change-Id: Ia7570862a09fd78c109d42da5176c1e855497600 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index c23c77e..1bfbcff 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -290,7 +290,7 @@ _twe_thread_del_source_trigger(twe_del_source *del_source) ret = write(del_source->event_fd, &value, sizeof(uint64_t)); if (ret == -1) { - TPL_ERR("failed to send acquirable event. twe_del_source(%p)", + TPL_ERR("failed to send delete event. twe_del_source(%p)", del_source); return; } @@ -3020,9 +3020,10 @@ twe_surface_set_sync_fd(twe_surface_h twe_surface, ret = write(sync_draw_source->event_fd, &value, sizeof(uint64_t)); if (ret == -1) { - TPL_ERR("failed to send acquirable event. twe_wl_surf_source(%p)", - surf_source); - g_source_remove_unix_fd(&sync_draw_source->gsource, sync_draw_source->tag); + TPL_ERR("failed to send event to wait sync_fd(%d). twe_wl_surf_source(%p)", + sync_fd, surf_source); + g_source_remove_unix_fd(&sync_draw_source->gsource, + sync_draw_source->tag); g_source_destroy(&sync_draw_source->gsource); surf_source->use_sync_fence = TPL_FALSE; return TPL_ERROR_INVALID_OPERATION; -- 2.7.4 From e739cab8e06330e4dbe3238be4cd76b9c4f6e993 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 4 Jan 2018 13:23:36 +0900 Subject: [PATCH 08/16] Package version up to 1.5.1 Change-Id: Icaa51d682e9ae184efccef5452567006e7d02861 Signed-off-by: joonbum.ko --- packaging/libtpl-egl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 53f8edc..7819517 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -4,7 +4,7 @@ #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 %define TPL_VERSION_MINOR 5 -%define TPL_VERSION_PATCH 0 +%define TPL_VERSION_PATCH 1 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From 68c10f8f13a7c9e0c7b506fdc3a8743603dba6d5 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 4 Jan 2018 19:08:23 +0900 Subject: [PATCH 09/16] tpl_wayland_egl_thread: Fixed wrong codes about acquire_and_commit. Change-Id: Ie655e1d79bd424477e20e19b8817a3a263076291 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 1bfbcff..78c3550 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -2055,8 +2055,9 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data) surf_source->draw_done_count--; } g_mutex_unlock(&surf_source->sub_thread_mutex); + } else { + _twe_thread_wl_surface_acquire_and_commit(surf_source); } - _twe_thread_wl_surface_acquire_and_commit(surf_source); } return G_SOURCE_CONTINUE; -- 2.7.4 From afed9ffbdd0fd17227197224395d00d5e868383a Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 4 Jan 2018 20:42:29 +0900 Subject: [PATCH 10/16] tpl_wayland_egl_thread: Fixed bugs about locking mechanism Change-Id: I4e836a24d7e73fa5f8e039beaac67487273a3b0b Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 78c3550..965e5fd 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -1660,13 +1660,12 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, disp_source = surf_source->disp_source; - TPL_OBJECT_LOCK(&surf_source->obj); - surf_source->vblank_done = TPL_TRUE; if (!disp_source->is_vulkan_dpy) _twe_thread_wl_surface_acquire_and_commit(surf_source); else { + TPL_OBJECT_LOCK(&surf_source->obj); switch (surf_source->swapchain_properties.present_mode) { case TPL_DISPLAY_PRESENT_MODE_MAILBOX: if (surf_source->draw_done_buffer) { @@ -1707,9 +1706,8 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, break; } + TPL_OBJECT_UNLOCK(&surf_source->obj); } - - TPL_OBJECT_UNLOCK(&surf_source->obj); } static tdm_client_vblank* @@ -1925,18 +1923,14 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; twe_wl_buffer_info *buf_info = NULL; - TPL_OBJECT_LOCK(&surf_source->obj); - if (surf_source->is_destroying) { TPL_WARN("surf_source(%p) native window is already destroyed.", surf_source); - TPL_OBJECT_UNLOCK(&surf_source->obj); return; } if (!disp_source->is_vulkan_dpy && !surf_source->vblank_done) { TPL_LOG_T(BACKEND, "[ACQ_skip] It will be acquired next vblank."); - TPL_OBJECT_UNLOCK(&surf_source->obj); return; } @@ -1945,7 +1939,6 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { TPL_ERR("Failed to acquire from tbm_queue(%p)", surf_source->tbm_queue); - TPL_OBJECT_UNLOCK(&surf_source->obj); return; } @@ -1954,6 +1947,7 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, (void **)&buf_info); + TPL_OBJECT_LOCK(&surf_source->obj); if (!disp_source->is_vulkan_dpy) { /* wayland_egl */ TPL_LOG_T(BACKEND, "[ACQ] tbm_surface(%p) bo(%d)", tbm_surface, @@ -2021,9 +2015,8 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) break; } } + TPL_OBJECT_UNLOCK(&surf_source->obj); } - - TPL_OBJECT_UNLOCK(&surf_source->obj); } static gboolean -- 2.7.4 From fff05a81301e5398994998d709961c2e9fac57a2 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 5 Jan 2018 11:12:19 +0900 Subject: [PATCH 11/16] Package version up to 1.5.2 Change-Id: Iba46f3a524cd98d95e8a638faad90e30605f5d9d Signed-off-by: joonbum.ko --- packaging/libtpl-egl.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 7819517..0890369 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -4,7 +4,7 @@ #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 %define TPL_VERSION_MINOR 5 -%define TPL_VERSION_PATCH 1 +%define TPL_VERSION_PATCH 2 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From c405ddd636c45505ae91dd036818f4015fd39537 Mon Sep 17 00:00:00 2001 From: Hoyub Lee Date: Wed, 3 Jan 2018 22:31:55 +0900 Subject: [PATCH 12/16] tc: Add test cases for tpl_display Add below tests for tpl_display. TEST CASE | TEST ------------------------------------------------------------------ DEFAULT_tpl_display_get_backend_type | success DEFAULT_tpl_display_get_backend_type | failure DEFAULT_tpl_display_get_native_window_info | success_2 DEFAULT_tpl_display_get_native_pixmap_info | failure DEFAULT_tpl_display_get_buffer_from_native_pixmap | success DEFAULT_tpl_display_get_buffer_from_native_pixmap | failure DEFAULT_tpl_display_query_supported_present_modes | success _from_native_window Change-Id: I2dd81ea35e820441a26df50fee008d55c7ab2943 Signed-off-by: Hoyub Lee --- tc/test/tpl-test_display_test.cpp | 96 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/tc/test/tpl-test_display_test.cpp b/tc/test/tpl-test_display_test.cpp index 923538b..af7df80 100644 --- a/tc/test/tpl-test_display_test.cpp +++ b/tc/test/tpl-test_display_test.cpp @@ -127,9 +127,27 @@ TEST_F(DEFAULT_tpl_display_filter_config, failure_invalid_display) } +typedef TPLTestBase DEFAULT_tpl_display_get_backend_type; + +TEST_F(DEFAULT_tpl_display_get_backend_type, success) { + tpl_backend_type_t result; + + result = tpl_display_get_backend_type(backend->display_handle); + ASSERT_NE(TPL_BACKEND_UNKNOWN, result); +} + +TEST_F(DEFAULT_tpl_display_get_backend_type, failure) { + tpl_backend_type_t result; + + result = tpl_display_get_backend_type(NULL); + ASSERT_EQ(TPL_BACKEND_UNKNOWN, result); +} + + typedef TPLTestBase DEFAULT_tpl_display_get_native_window_info; -TEST_F(DEFAULT_tpl_display_get_native_window_info, success) +// Test with alpha size = 8 +TEST_F(DEFAULT_tpl_display_get_native_window_info, success_1) { tpl_result_t result; int width, height; @@ -147,8 +165,44 @@ TEST_F(DEFAULT_tpl_display_get_native_window_info, success) ASSERT_EQ(TPL_ERROR_NONE, result); } +// Test with alpha size = 0 +TEST_F(DEFAULT_tpl_display_get_native_window_info, success_2) +{ + tpl_result_t result; + int width, height; + tbm_format format; + + result = tpl_display_get_native_window_info(backend->tpl_display, + backend->surface_handle, + &width, &height, &format, + config.depth, 0); + + EXPECT_EQ(config.width, width); + EXPECT_EQ(config.height, height); + EXPECT_EQ(TBM_FORMAT_XRGB8888, format); + + ASSERT_EQ(TPL_ERROR_NONE, result); +} + /* TODO: Make test - DEFAULT_tpl_display_get_native_window_info, failure */ + +typedef TPLTestBase DEFAULT_tpl_display_get_native_pixmap_info; + +/* TODO: Make test - DEFAULT_tpl_display_get_native_pixmap_info, success */ + +TEST_F(DEFAULT_tpl_display_get_native_pixmap_info, failure) { + tpl_result_t result; + int width, height; + tbm_format format; + + result = tpl_display_get_native_pixmap_info(backend->tpl_display, NULL, + &width, &height, &format); + + ASSERT_EQ(TPL_ERROR_INVALID_OPERATION, result); +} + + typedef TPLTestBase EXTRA_tpl_display_query_supported_buffer_count_from_native_window; @@ -167,6 +221,46 @@ TEST_F(EXTRA_tpl_display_query_supported_buffer_count_from_native_window, return; } + // TODO: Add check on min and max + ASSERT_EQ(TPL_ERROR_NONE, result); } + +typedef TPLTestBase DEFAULT_tpl_display_get_buffer_from_native_pixmap; + +/* TODO: Make test - DEFAULT_tpl_display_get_native_pixmap_info, success */ + +TEST_F(DEFAULT_tpl_display_get_buffer_from_native_pixmap, success) { + tbm_surface_h tbm_surface; + + tbm_surface = tpl_display_get_buffer_from_native_pixmap(backend->tpl_display, + backend->surface_handle); + + EXPECT_NE((void *)NULL, tbm_surface); +} + +TEST_F(DEFAULT_tpl_display_get_buffer_from_native_pixmap, failure) { + tbm_surface_h tbm_surface; + + EXPECT_DEATH((tbm_surface = tpl_display_get_buffer_from_native_pixmap(backend->tpl_display, NULL)), + ".*Assertion `pixmap' failed\..*"); +} + + +typedef TPLTestBase DEFAULT_tpl_display_query_supported_present_modes_from_native_window; + +TEST_F(DEFAULT_tpl_display_query_supported_present_modes_from_native_window, success) { + tpl_result_t result; + + result = tpl_display_query_supported_present_modes_from_native_window( + backend->tpl_display, backend->surface_handle, NULL); + + // SUCCEED() if backend does not support operation + if (result == TPL_ERROR_INVALID_OPERATION) { + SUCCEED() << "Backend does not support this operation"; + return; + } + + EXPECT_EQ(TPL_ERROR_NONE, result); +} -- 2.7.4 From f1ff0db5be8282566901f70fbbfd979300105eb4 Mon Sep 17 00:00:00 2001 From: Hoyub Lee Date: Wed, 3 Jan 2018 22:39:41 +0900 Subject: [PATCH 13/16] tc: Add test cases for tpl_surface Add below tests for tpl_surface. TEST CASE | TEST ------------------------------------------------------------------ DEFAULT_tpl_surface_get_rotation | success_1 DEFAULT_tpl_surface_get_rotation | success_2 DEFAULT_tpl_surface_get_rotation | failure DEFAULT_tpl_surface_dequeue_enqueue | deq_enq_dmg_1 DEFAULT_tpl_surface_dequeue_enqueue | deq_enq_dmg_2 DEFAULT_tpl_surface_cancel_dequeued_buff | success DEFAULT_tpl_surface_cancel_dequeued_buff | failure_null_surface DEFAULT_tpl_surface_cancel_dequeued_buff | failure_null_tbm_surf EXTRA_tpl_surface_get_swapchain_buffers | failure_invalid_surface EXTRA_tpl_surface_get_swapchain_buffers | failure_invalid_buffer_count EXTRA_tpl_surface_destroy_swapchain | failure_invalid_surface DEFAULT_tpl_surface_set_frontbuffer_mode | success_activate DEFAULT_tpl_surface_set_frontbuffer_mode | success_deactivate DEFAULT_tpl_surface_set_frontbuffer_mode | failure_null_surface DEFAULT_tpl_surface_set_reset_cb | success DEFAULT_tpl_surface_set_reset_cb | failure DEFAULT_tpl_surface_set_rotation_capabil | success DEFAULT_tpl_surface_set_rotation_capabil | failure Change-Id: I324a2d02aa823712c64c5643d7cb77dd3c17bc0f Signed-off-by: Hoyub Lee --- tc/test/tpl-test_surface_test.cpp | 250 +++++++++++++++++++++++++++++++++++--- 1 file changed, 233 insertions(+), 17 deletions(-) diff --git a/tc/test/tpl-test_surface_test.cpp b/tc/test/tpl-test_surface_test.cpp index ae52edb..d419bae 100644 --- a/tc/test/tpl-test_surface_test.cpp +++ b/tc/test/tpl-test_surface_test.cpp @@ -9,23 +9,6 @@ #include "src/tpl-test_base.h" -typedef TPLTestBase DEFAULT_tpl_surface_validate; - -TEST_F(DEFAULT_tpl_surface_validate, success) -{ - tpl_bool_t result = tpl_surface_validate(backend->tpl_surface); - - ASSERT_EQ(TPL_TRUE, result); -} - -TEST_F(DEFAULT_tpl_surface_validate, failure_invalid_surface) -{ - tpl_bool_t result = tpl_surface_validate(NULL); - - ASSERT_EQ(TPL_FALSE, result); -} - - typedef TPLTestBase DEFAULT_tpl_surface_get_display; TEST_F(DEFAULT_tpl_surface_get_display, success) @@ -107,6 +90,51 @@ TEST_F(DEFAULT_tpl_surface_get_size, failure_invalid_surface) } +typedef TPLTestBase DEFAULT_tpl_surface_get_rotation; + +TEST_F(DEFAULT_tpl_surface_get_rotation, success_1) +{ + tpl_bool_t result; + int rotation; + + result = tpl_surface_get_rotation(backend->tpl_surface, &rotation); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_get_rotation, success_2) +{ + tpl_bool_t result; + + result = tpl_surface_get_rotation(backend->tpl_surface, NULL); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_get_rotation, failure) +{ + tpl_bool_t result; + int rotation; + + result = tpl_surface_get_rotation(NULL, &rotation); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + +typedef TPLTestBase DEFAULT_tpl_surface_validate; + +TEST_F(DEFAULT_tpl_surface_validate, success) +{ + tpl_bool_t result = tpl_surface_validate(backend->tpl_surface); + + ASSERT_EQ(TPL_TRUE, result); +} + +TEST_F(DEFAULT_tpl_surface_validate, failure_invalid_surface) +{ + tpl_bool_t result = tpl_surface_validate(NULL); + + ASSERT_EQ(TPL_FALSE, result); +} + + typedef TPLTestBase DEFAULT_tpl_surface_dequeue_enqueue; // Tests simple normal buffer flow: @@ -132,6 +160,93 @@ TEST_F(DEFAULT_tpl_surface_dequeue_enqueue, deq_enq) ASSERT_EQ(TPL_ERROR_NONE, result); } +// Same with 'deq_enq' test but use tpl_surface_enqueue_buffer_with_damage +TEST_F(DEFAULT_tpl_surface_dequeue_enqueue, deq_enq_dmg_1) +{ + // dequeue + tbm_surface_h tbm_surf = NULL; + tbm_surf = tpl_surface_dequeue_buffer(backend->tpl_surface); + ASSERT_NE((void *)NULL, tbm_surf); + + // set and get interval + int interval_set = 2; + tpl_surface_set_post_interval(backend->tpl_surface, interval_set); + int interval_get = tpl_surface_get_post_interval(backend->tpl_surface); + ASSERT_EQ(interval_set, interval_get); + + // enqueue + tpl_result_t result = TPL_ERROR_INVALID_PARAMETER; + result = tpl_surface_enqueue_buffer_with_damage(backend->tpl_surface, + tbm_surf, 0, NULL); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_dequeue_enqueue, deq_enq_dmg_2) +{ + // dequeue + tbm_surface_h tbm_surf = NULL; + tbm_surf = tpl_surface_dequeue_buffer(backend->tpl_surface); + ASSERT_NE((void *)NULL, tbm_surf); + + // set and get interval + int interval_set = 2; + tpl_surface_set_post_interval(backend->tpl_surface, interval_set); + int interval_get = tpl_surface_get_post_interval(backend->tpl_surface); + ASSERT_EQ(interval_set, interval_get); + + // enqueue + tpl_result_t result = TPL_ERROR_INVALID_PARAMETER; + int rects[4 * 2] = {0, 0, 10, 10, + 1, 1, 10, 10}; + result = tpl_surface_enqueue_buffer_with_damage(backend->tpl_surface, + tbm_surf, 2, rects); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +typedef TPLTestBase DEFAULT_tpl_surface_cancel_dequeued_buffer; + +TEST_F(DEFAULT_tpl_surface_cancel_dequeued_buffer, success) +{ + tpl_bool_t result; + tbm_surface_h tbm_surf; + + // dequeue + tbm_surf = tpl_surface_dequeue_buffer(backend->tpl_surface); + ASSERT_NE((void *)NULL, tbm_surf); + + // cancel dequeued buffer + result = tpl_surface_cancel_dequeued_buffer(backend->tpl_surface, tbm_surf); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_cancel_dequeued_buffer, failure_null_surface) +{ + tpl_bool_t result; + tbm_surface_h tbm_surf; + + // dequeue + tbm_surf = tpl_surface_dequeue_buffer(backend->tpl_surface); + ASSERT_NE((void *)NULL, tbm_surf); + + // cancel dequeued buffer + result = tpl_surface_cancel_dequeued_buffer(NULL, tbm_surf); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + +TEST_F(DEFAULT_tpl_surface_cancel_dequeued_buffer, failure_null_tbm_surf) +{ + tpl_bool_t result; + tbm_surface_h tbm_surf; + + // dequeue + tbm_surf = tpl_surface_dequeue_buffer(backend->tpl_surface); + ASSERT_NE((void *)NULL, tbm_surf); + + // cancel dequeued buffer + result = tpl_surface_cancel_dequeued_buffer(NULL, NULL); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + typedef TPLTestBase EXTRA_tpl_surface_swapchain; @@ -170,3 +285,104 @@ TEST_F(EXTRA_tpl_surface_swapchain, success) ASSERT_EQ(TPL_ERROR_NONE, result); } + +typedef TPLTestBase EXTRA_tpl_surface_get_swapchain_buffers; + +TEST_F(EXTRA_tpl_surface_get_swapchain_buffers, failure_invalid_surface) +{ + tpl_result_t result; + tbm_surface_h **buffers = NULL; + int buffer_get; + + // Get swapchain buffers + result = tpl_surface_get_swapchain_buffers(NULL, buffers, &buffer_get); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + +TEST_F(EXTRA_tpl_surface_get_swapchain_buffers, failure_invalid_buffer_count) +{ + tpl_result_t result; + tbm_surface_h **buffers = NULL; + int buffer_get; + + // Get swapchain buffers + result = tpl_surface_get_swapchain_buffers(backend->tpl_surface, buffers, + NULL); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + + +typedef TPLTestBase EXTRA_tpl_surface_destroy_swapchain; + +TEST_F(EXTRA_tpl_surface_destroy_swapchain, failure_invalid_surface) +{ + tpl_result_t result; + + // Destroy swapchain buffers + result = tpl_surface_destroy_swapchain(NULL); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + + +typedef TPLTestBase DEFAULT_tpl_surface_set_frontbuffer_mode; + +TEST_F(DEFAULT_tpl_surface_set_frontbuffer_mode, success_activate) +{ + tpl_result_t result; + + result = tpl_surface_set_frontbuffer_mode(backend->tpl_surface, TPL_TRUE); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_set_frontbuffer_mode, success_deactivate) +{ + tpl_result_t result; + + result = tpl_surface_set_frontbuffer_mode(backend->tpl_surface, TPL_FALSE); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_set_frontbuffer_mode, failure_null_surface) +{ + tpl_result_t result; + + result = tpl_surface_set_frontbuffer_mode(NULL, TPL_FALSE); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + +typedef TPLTestBase DEFAULT_tpl_surface_set_reset_cb; + +TEST_F(DEFAULT_tpl_surface_set_reset_cb, success) +{ + tpl_result_t result; + + result = tpl_surface_set_reset_cb(backend->tpl_surface, NULL, NULL); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_set_reset_cb, failure) +{ + tpl_result_t result; + + result = tpl_surface_set_reset_cb(NULL, NULL, NULL); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} + + +typedef TPLTestBase DEFAULT_tpl_surface_set_rotation_capability; + +TEST_F(DEFAULT_tpl_surface_set_rotation_capability, success) +{ + tpl_result_t result; + + result = tpl_surface_set_rotation_capability(backend->tpl_surface, TPL_TRUE); + ASSERT_EQ(TPL_ERROR_NONE, result); +} + +TEST_F(DEFAULT_tpl_surface_set_rotation_capability, failure) +{ + tpl_result_t result; + + result = tpl_surface_set_rotation_capability(NULL, TPL_TRUE); + ASSERT_EQ(TPL_ERROR_INVALID_PARAMETER, result); +} -- 2.7.4 From 750b2fe32de4438d3eb8e2ce1ee9a968a511c4f7 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 18 Jan 2018 15:26:43 +0900 Subject: [PATCH 14/16] tpl_wayland_egl: Guaranteed thread safety for wl_event processing. Change-Id: I519c78d1f19303c8d99b1d72cbcb1522d4861f71 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl.c | 59 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index ab534a7..ef08f8b 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -35,6 +35,7 @@ struct _tpl_wayland_egl_display { struct wl_display *wl_dpy; struct wl_event_queue *wl_tbm_event_queue; struct tizen_surface_shm *tizen_surface_shm; /* used for surface buffer_flush */ + pthread_mutex_t wl_event_mutex; }; struct _tpl_wayland_egl_surface { @@ -193,6 +194,11 @@ __tpl_wayland_egl_display_init(tpl_display_t *display) wayland_egl_display->tdm_client = NULL; } + if (pthread_mutex_init(&wayland_egl_display->wl_event_mutex, NULL)) { + TPL_ERR("Failed to initialize wl_event_mutex."); + goto free_wl_display; + } + wayland_egl_display->wl_dpy = wl_dpy; __tpl_wayland_egl_display_buffer_flusher_init(wayland_egl_display); @@ -235,9 +241,12 @@ __tpl_wayland_egl_display_fini(tpl_display_t *display) wayland_egl_display = (tpl_wayland_egl_display_t *)display->backend.data; if (wayland_egl_display) { + int lock_res = 0; TPL_LOG_B("WL_EGL", "[FINI] tpl_wayland_egl_display_t(%p) wl_tbm_client(%p)", wayland_egl_display, wayland_egl_display->wl_tbm_client); + lock_res = pthread_mutex_lock(&wayland_egl_display->wl_event_mutex); + __tpl_wayland_egl_display_buffer_flusher_fini(wayland_egl_display); if (wayland_egl_display->tdm_client) @@ -252,6 +261,11 @@ __tpl_wayland_egl_display_fini(tpl_display_t *display) if (wayland_egl_display->wl_tbm_client) wayland_tbm_client_deinit(wayland_egl_display->wl_tbm_client); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); + if (pthread_mutex_destroy(&wayland_egl_display->wl_event_mutex)) + TPL_ERR("Failed to destroy wl_event_mutex(%p)", + &wayland_egl_display->wl_event_mutex); + wayland_egl_display->wl_tbm_event_queue = NULL; wayland_egl_display->wl_tbm_client = NULL; wayland_egl_display->tdm_client = NULL; @@ -624,15 +638,14 @@ __tpl_wayland_egl_surface_fini(tpl_surface_t *surface) if (surface->type == TPL_SURFACE_TYPE_WINDOW) { struct wl_egl_window *wl_egl_window = (struct wl_egl_window *) surface->native_handle; + int lock_res = 0; TPL_ASSERT(wl_egl_window); /* TPL_ASSERT(wl_egl_window->surface); */ /* to be enabled once evas/gl patch is in place */ wl_egl_window->private = NULL; - wl_display_flush(wayland_egl_display->wl_dpy); - wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, - wayland_egl_display->wl_tbm_event_queue); + __tpl_wayland_egl_surface_buffer_flusher_fini(surface); if (wayland_egl_surface->tdm_vblank) { TPL_LOG_B("WL_EGL", @@ -641,13 +654,18 @@ __tpl_wayland_egl_surface_fini(tpl_surface_t *surface) tdm_client_vblank_destroy(wayland_egl_surface->tdm_vblank); } + wl_display_flush(wayland_egl_display->wl_dpy); + + lock_res = pthread_mutex_lock(&wayland_egl_display->wl_event_mutex); + wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, + wayland_egl_display->wl_tbm_event_queue); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); + TPL_LOG_B("WL_EGL", "[FINI] tpl_wayland_egl_surface_t(%p) wl_egl_window(%p) tbm_queue(%p)", wayland_egl_surface, wl_egl_window, wayland_egl_surface->tbm_queue); tbm_surface_queue_destroy(wayland_egl_surface->tbm_queue); wayland_egl_surface->tbm_queue = NULL; - - __tpl_wayland_egl_surface_buffer_flusher_fini(surface); } /* When surface is destroyed, unreference tbm_surface which tracked by @@ -1008,8 +1026,9 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) wl_display_dispatch_queue_pending(wayland_egl_display->wl_dpy, wayland_egl_display->wl_tbm_event_queue); - if (tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) + if (tbm_surface_queue_can_dequeue(wayland_egl_surface->tbm_queue, 0)) { return TPL_ERROR_NONE; + } TRACE_BEGIN("WAITING FOR DEQUEUEABLE"); TPL_OBJECT_UNLOCK(surface); @@ -1047,9 +1066,13 @@ __tpl_wayland_egl_surface_wait_dequeuable(tpl_surface_t *surface) } ret = TPL_ERROR_INVALID_OPERATION; - break; + TPL_OBJECT_LOCK(surface); + TRACE_END(); + + return ret; } } + TPL_OBJECT_LOCK(surface); TRACE_END(); @@ -1112,10 +1135,13 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou (struct wl_egl_window *)surface->native_handle; tbm_surface_queue_error_e tsq_err = 0; int is_activated = 0; + int lock_res = 0; if (sync_fence) *sync_fence = -1; + lock_res = pthread_mutex_lock(&wayland_egl_display->wl_event_mutex); + /* Check whether the surface was resized by wayland_egl */ if (wayland_egl_surface->resized == TPL_TRUE) { int width, height, format; @@ -1133,6 +1159,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou if (__tpl_wayland_egl_surface_wait_dequeuable(surface)) { TPL_ERR("Failed to wait dequeueable buffer"); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return NULL; } @@ -1169,6 +1196,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou TRACE_ASYNC_BEGIN((int)wayland_egl_buffer, "[DEQ]~[ENQ] BO_NAME:%d", tbm_bo_export(wayland_egl_buffer->bo)); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return surface->frontbuffer; } else surface->frontbuffer = NULL; @@ -1181,6 +1209,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou if (!tbm_surface) { TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d", tsq_err); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return NULL; } @@ -1242,6 +1271,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou wayland_egl_buffer->transform, wayland_egl_buffer->rotated ? "[TRUE]" : "[FALSE]"); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return tbm_surface; } @@ -1250,6 +1280,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou if (!wayland_egl_buffer) { TPL_ERR("Mem alloc for wayland_egl_buffer failed!"); tbm_surface_internal_unref(tbm_surface); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return NULL; } @@ -1260,6 +1291,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou TPL_ERR("Failed to create TBM client buffer!"); tbm_surface_internal_unref(tbm_surface); free(wayland_egl_buffer); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return NULL; } @@ -1328,6 +1360,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); } + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return tbm_surface; } @@ -1631,6 +1664,7 @@ static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, tpl_wayland_egl_surface_t *wayland_egl_surface; tpl_wayland_egl_display_t *wayland_egl_display; int ret; + int lock_res = 0; TPL_CHECK_ON_NULL_RETURN(surface); wayland_egl_surface = surface->backend.data; @@ -1643,6 +1677,8 @@ static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, TPL_CHECK_ON_NULL_RETURN(wayland_egl_display->wl_tbm_event_queue); TPL_CHECK_ON_NULL_RETURN(wayland_egl_surface->tbm_queue); + lock_res = pthread_mutex_lock(&wayland_egl_display->wl_event_mutex); + TPL_LOG_B("WL_EGL", "[FLUSH_CB] tpl_wayland_egl_surface_t(%p)", wayland_egl_surface); @@ -1655,6 +1691,7 @@ static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, if (ret == -1) { TPL_ERR("Failed to wl_display_dispatch_queue_pending ret:%d, err:%d", ret, errno); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return; } @@ -1676,6 +1713,8 @@ static void __cb_tizen_surface_shm_flusher_flush_callback(void *data, } TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); } + + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); } static void __cb_tizen_surface_shm_flusher_free_flush_callback(void *data, @@ -1685,6 +1724,7 @@ static void __cb_tizen_surface_shm_flusher_free_flush_callback(void *data, tpl_wayland_egl_surface_t *wayland_egl_surface; tpl_wayland_egl_display_t *wayland_egl_display; int ret; + int lock_res; TPL_CHECK_ON_NULL_RETURN(surface); wayland_egl_surface = surface->backend.data; @@ -1697,6 +1737,8 @@ static void __cb_tizen_surface_shm_flusher_free_flush_callback(void *data, TPL_CHECK_ON_NULL_RETURN(wayland_egl_display->wl_tbm_event_queue); TPL_CHECK_ON_NULL_RETURN(wayland_egl_surface->tbm_queue); + lock_res = pthread_mutex_lock(&wayland_egl_display->wl_event_mutex); + TPL_LOG_B("WL_EGL", "[FLUSH_CB] tpl_wayland_egl_surface_t(%p)", wayland_egl_surface); @@ -1709,10 +1751,13 @@ static void __cb_tizen_surface_shm_flusher_free_flush_callback(void *data, if (ret == -1) { TPL_ERR("Failed to wl_display_dispatch_queue_pending ret:%d, err:%d", ret, errno); + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return; } tbm_surface_queue_free_flush(wayland_egl_surface->tbm_queue); + + if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); } static const struct tizen_surface_shm_flusher_listener -- 2.7.4 From 743f8fc4a0a948e110e2daa68def281b2ee52112 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 19 Jan 2018 13:13:36 +0900 Subject: [PATCH 15/16] tpl_wayland_egl_thread: Changed to use wl_tbm event queue to use flusher in thread. Change-Id: I2e15a77caa1356b51532a66b9f75d6df44ddb2e8 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 70 +++++++------------------------------------- 1 file changed, 10 insertions(+), 60 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 965e5fd..48e37db 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -822,10 +822,10 @@ _twe_display_shm_init(twe_wl_disp_source *disp_source) goto fini; } - /* set tizen_surface_shm's queue as client's default queue */ + /* set tizen_surface_shm's queue as client's private queue */ if (disp_source->tss) wl_proxy_set_queue((struct wl_proxy *)disp_source->tss, - NULL); + disp_source->ev_queue); TPL_LOG_T(BACKEND, "tizen_surface_shm(%p) init.", disp_source->tss); @@ -1196,80 +1196,30 @@ static void __cb_tss_flusher_flush_callback(void *data, struct tizen_surface_shm_flusher *tss_flusher) { twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; - twe_wl_disp_source *disp_source = surf_source->disp_source; - int ret; + tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; TPL_LOG_T(BACKEND, "[FLUSH_CB] surf_source(%p)", surf_source); - /*First distach pending queue for TPL - - dispatch buffer-release - - dispatch queue flush - */ - TPL_OBJECT_LOCK(&disp_source->obj); - ret = wl_display_dispatch_queue_pending(disp_source->disp, - disp_source->ev_queue); - if (ret == -1) { - _twe_display_print_err(disp_source, "dispatch_queue_pending"); - TPL_OBJECT_UNLOCK(&disp_source->obj); + tsq_err = tbm_surface_queue_flush(surf_source->tbm_queue); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to free flush tbm_queue(%p)", surf_source->tbm_queue); return; } - - tbm_surface_queue_flush(surf_source->tbm_queue); - - /* Only when client call tpl_surface_dequeue_buffer(), client can do - * unreference tbm_surface although there are release events in the event queue. - * After tbm_surface_queue_flush, queue has no tbm_surface, client can do - * unreference committed buffers using the list of committed_buffers. - * Then, client does not need to wait for release_callback to unreference - * committed buffers. - */ - if (surf_source->committed_buffers) { - TPL_OBJECT_LOCK(&surf_source->obj); - while (!__tpl_list_is_empty(surf_source->committed_buffers)) { - tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; - tbm_surface_h tbm_surface = - __tpl_list_pop_front(surf_source->committed_buffers, - (tpl_free_func_t)__cb_buffer_remove_from_list); - - TRACE_ASYNC_END((int)tbm_surface, "[COMMIT ~ RELEASE] BO(%d)", - tbm_bo_export(tbm_surface_internal_get_bo( - tbm_surface, 0))); - tsq_err = tbm_surface_queue_release(surf_source->tbm_queue, tbm_surface); - if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) - TPL_ERR("Failed to release. tbm_surface(%p) tsq_err(%d)", - tbm_surface, tsq_err); - } - TPL_OBJECT_UNLOCK(&surf_source->obj); - } - - TPL_OBJECT_UNLOCK(&disp_source->obj); } static void __cb_tss_flusher_free_flush_callback(void *data, struct tizen_surface_shm_flusher *tss_flusher) { twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; - twe_wl_disp_source *disp_source = surf_source->disp_source; - int ret; + tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; TPL_LOG_T(BACKEND, "[FREE_FLUSH_CB] surf_source(%p)", surf_source); - /* First distach panding queue for TPL - - dispatch buffer-release - - dispatch queue flush - */ - TPL_OBJECT_LOCK(&disp_source->obj); - ret = wl_display_dispatch_queue_pending(disp_source->disp, - disp_source->ev_queue); - if (ret == -1) { - _twe_display_print_err(disp_source, "dispatch_queue_pending"); - TPL_OBJECT_UNLOCK(&disp_source->obj); + tsq_err = tbm_surface_queue_free_flush(surf_source->tbm_queue); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to free flush tbm_queue(%p)", surf_source->tbm_queue); return; } - - tbm_surface_queue_free_flush(surf_source->tbm_queue); - - TPL_OBJECT_UNLOCK(&disp_source->obj); } -- 2.7.4 From 90dca121b44c2784111bf30d31cdef71e4bf758d Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 22 Jan 2018 17:47:02 +0900 Subject: [PATCH 16/16] tpl_wayland_egl_thread: Modified to create timeline fd only for vulkan dpy. Change-Id: I40f7f28ce0663d04e93afa97fc3eaf5fd2448ad7 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 48e37db..4b0a3c7 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -1452,13 +1452,6 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->rotated = TPL_FALSE; } - buf_info->sync_timeline = tbm_sync_timeline_create(); - if (buf_info->sync_timeline == -1) { - char buf[1024]; - strerror_r(errno, buf, sizeof(buf)); - TPL_WARN("Failed to create TBM sync timeline: %d(%s)", errno, buf); - } - buf_info->sync_timestamp = 0; buf_info->surf_source = surf_source; buf_info->num_rects = 0; @@ -1468,12 +1461,21 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->tbm_surface = tbm_surface; buf_info->sync_draw_source = NULL; buf_info->sync_fd = -1; + buf_info->sync_timeline = -1; buf_info->is_vk_image = surf_source->disp_source->is_vulkan_dpy; - if (buf_info->is_vk_image) + if (buf_info->is_vk_image) { + buf_info->sync_timeline = tbm_sync_timeline_create(); + if (buf_info->sync_timeline == -1) { + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_WARN("Failed to create TBM sync timeline: %d(%s)", errno, buf); + } + wayland_tbm_client_set_sync_timeline(surf_source->disp_source->wl_tbm_client, (void *)buf_info->wl_buffer, buf_info->sync_timeline); + } wl_buffer_add_listener((void *)buf_info->wl_buffer, &wl_buffer_release_listener, tbm_surface); -- 2.7.4