From: joonbum.ko Date: Wed, 11 Oct 2017 08:53:58 +0000 (+0900) Subject: tpl_wayland_egl_thread: Added an internal API to set sync fence fd to buffer. X-Git-Tag: accepted/tizen/unified/20171206.063114~16 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=26b1d26b9e5ccf183ec5edf70848ce6e6eea548b;p=platform%2Fcore%2Fuifw%2Flibtpl-egl.git tpl_wayland_egl_thread: Added an internal API to set sync fence fd to buffer. - The newly created sub-thread waits for draw_done via sync fence fd and sends the acquirable event to eventfd of surf_source when the drawing is completed. - The newly created sub-thread will be destroyed after sending the acquirable event. Change-Id: I9740b46ab8cdfab3e3ed289c6c073de836eeb5d6 Signed-off-by: joonbum.ko --- diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 91d25f4..921cb71 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -30,11 +30,11 @@ typedef struct _twe_tdm_source twe_tdm_source; typedef struct _twe_del_source twe_del_source; struct _twe_thread_context { - int ref_cnt; - GThread *twe_thread; GMainLoop *twe_loop; + int ref_cnt; + twe_tdm_source *tdm_source; GMutex thread_mutex; @@ -129,8 +129,11 @@ struct _twe_wl_buffer_info { GThread *fence_waiting_thread; + /* for checking draw done */ tpl_bool_t draw_done; tbm_fd draw_done_fence; + + /* for checking released from display server */ tbm_fd sync_timeline; unsigned int sync_timestamp; @@ -1496,14 +1499,17 @@ static void __cb_tbm_queue_acquirable_callback(tbm_surface_queue_h surface_queue, void *data) { - twe_wl_surf_source *source = (twe_wl_surf_source *)data; + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; uint64_t value = 1; int ret; - ret = write(source->event_fd, &value, sizeof(uint64_t)); + if (surf_source->disp_source->is_vulkan_dpy) + return; + + ret = write(surf_source->event_fd, &value, sizeof(uint64_t)); if (ret == -1) { TPL_ERR("failed to send acquirable event. twe_wl_surf_source(%p)", - source); + surf_source); return; } } @@ -1673,6 +1679,7 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) { tbm_surface_h tbm_surface = NULL; 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); @@ -1695,6 +1702,13 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) tbm_surface_internal_ref(tbm_surface); + tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, + (void **)&buf_info); + if (buf_info && buf_info->fence_waiting_thread) { + g_thread_join(buf_info->fence_waiting_thread); + buf_info->fence_waiting_thread = NULL; + } + TPL_LOG_T("WL_EGL", "[ACQ] tbm_surface(%p) bo(%d)", tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); @@ -2372,6 +2386,77 @@ twe_surface_commit_without_enqueue(twe_surface_h twe_surface, TPL_OBJECT_UNLOCK(&surf_source->obj); } +static gpointer +_twe_sync_fence_waiting(gpointer data) +{ + twe_wl_buffer_info *buf_info = (twe_wl_buffer_info *)data; + twe_wl_surf_source *surf_source = buf_info->surf_source; + uint64_t value = 1; + int ret; + + if (buf_info->draw_done_fence == -1) + return data; + + TRACE_BEGIN("Fence waiting. BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + /* non worker thread mode */ + /* TODO: set max wait time */ + if (tbm_sync_fence_wait(buf_info->draw_done_fence, -1) != 1) { + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_ERR("Failed to wait sync fence. | error: %d(%s)", errno, buf); + } + TRACE_END(); + + close(buf_info->draw_done_fence); + buf_info->draw_done_fence = -1; + buf_info->draw_done = TPL_TRUE; + + ret = write(surf_source->event_fd, &value, sizeof(uint64_t)); + if (ret == -1) { + TPL_ERR("failed to send acquirable event. twe_wl_surf_source(%p)", + surf_source); + } + + return data; +} + +tpl_result_t +twe_surface_set_sync_fd(tbm_surface_h tbm_surface, tbm_fd sync_fd) +{ + twe_wl_buffer_info *buf_info = NULL; + + tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, + (void **)&buf_info); + if (!buf_info) { + TPL_ERR("wl_buffer_info is not existed in tbm_surface(%p)", + tbm_surface); + return TPL_ERROR_INVALID_OPERATION; + } + + if (sync_fd == -1) { + TPL_WARN("It will be managed with async mode."); + } + + if (buf_info->fence_waiting_thread) { + g_thread_join(buf_info->fence_waiting_thread); + buf_info->fence_waiting_thread = NULL; + } + + if (buf_info->draw_done_fence != -1) { + close(buf_info->draw_done_fence); + buf_info->draw_done_fence = -1; + } + + buf_info->draw_done_fence = sync_fd; + + buf_info->fence_waiting_thread = g_thread_new("fence_waiting_thread", + _twe_sync_fence_waiting, + buf_info); + + return TPL_ERROR_NONE; +} + tpl_result_t twe_check_native_handle_is_wl_display(tpl_handle_t display) { diff --git a/src/tpl_wayland_egl_thread.h b/src/tpl_wayland_egl_thread.h index c366b43..631ac8c 100644 --- a/src/tpl_wayland_egl_thread.h +++ b/src/tpl_wayland_egl_thread.h @@ -84,6 +84,9 @@ twe_surface_set_damage_region(tbm_surface_h tbm_surface, int num_rects, const int *rects); tpl_result_t +twe_surface_set_sync_fd(tbm_surface_h tbm_surface, tbm_fd wait_fd); + +tpl_result_t twe_check_native_handle_is_wl_display(tpl_handle_t display); tpl_result_t