From 753ed2639149010f1442e38a98ca640c4a183cb8 Mon Sep 17 00:00:00 2001 From: Hoyub Lee Date: Fri, 15 Dec 2017 19:03:11 +0900 Subject: [PATCH 01/16] build: Add support for gcov Change-Id: I4a70f6180469514dd68e7ed545fdff4d3e2dd312 Signed-off-by: Hoyub Lee --- configure.ac | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/configure.ac b/configure.ac index 48ec7ed..8a6985c 100644 --- a/configure.ac +++ b/configure.ac @@ -162,6 +162,21 @@ AS_IF([test "${with_utest}" = "yes" || test "${with_utest}" = "1"], AM_CONDITIONAL([WITH_UTEST], [test "${with_utest}" = "yes" || test "${with_utest}" = "1"]) +AC_ARG_ENABLE([gcov], + [AS_HELP_STRING([--enable-gcov=yes|no],[Enable gcov.])], + [], + []) + +# TODO: Apply pkgconfig on gcov +AS_IF([test "${enable_gcov}" = "yes" || test "${enable_gcov}" = "1"], + [TPL_CFLAGS+=" -fprofile-arcs -ftest-coverage" + TPL_LIBS+=" -lgcov " + WL_EGL_CFLAGS+=" -fprofile-arcs -ftest-coverage" + WL_EGL_LIBS+=" -lgcov "], + []) + +AM_CONDITIONAL([ENABLE_GCOV], [test "${enable_gcov}" = "yes" || test "${enable_gcov}" = "1"]) + TPL_CFLAGS+="$TPL_ESSENTIAL_CFLAGS" TPL_LIBS+="$TPL_ESSENTIAL_LIBS" -- 2.7.4 From 56500e2f3c1f2972146781813d988cf14fa12cdc Mon Sep 17 00:00:00 2001 From: Hoyub Lee Date: Fri, 15 Dec 2017 19:04:12 +0900 Subject: [PATCH 02/16] build: Add ENABLE_TPL_TEST_GCOV option on spec Change-Id: I984348d96269bb8230cd41141d556bd76b2447be Signed-off-by: Hoyub Lee --- packaging/libtpl-egl.spec | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 38d6051..53f8edc 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -1,4 +1,5 @@ %bcond_with utest +%bcond_with utest_gcov #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 @@ -19,7 +20,8 @@ %define ENABLE_DEFAULT_WL_THREAD 0 #TPL INSTALL OPTION -%define ENABLE_TPL_TEST 0 +%define ENABLE_TPL_TEST 0 +%define ENABLE_TPL_TEST_GCOV 0 #WAYLAND-EGL VERSION MACROS %define WL_EGL_VERSION_MAJOR 1 @@ -153,6 +155,9 @@ export WL_EGL_VERSION_PATCH=%{WL_EGL_VERSION_PATCH} %endif %if %{with utest} || "%{ENABLE_TPL_TEST}" == "1" --with-utest=yes \ +%if %{with utest_gcov} || "%{ENABLE_TPL_TEST_GCOV}" == "1" + --enable-gcov=yes \ +%endif %endif --enable-dlog=%{ENABLE_DLOG} \ --enable-dlog-default=%{ENABLE_DEFAULT_LOG} \ -- 2.7.4 From 5df571b0a458bdedef3a601fc57052a519fbaa28 Mon Sep 17 00:00:00 2001 From: Hoyub Lee Date: Fri, 15 Dec 2017 19:09:32 +0900 Subject: [PATCH 03/16] tc: Apply gcov on tpl-test Change-Id: Ia4d65ce73d4d34393203a9883f6f55bf4a71afc7 Signed-off-by: Hoyub Lee --- src/Makefile.am | 4 ++++ src/wayland-egl/Makefile.am | 4 ++++ tc/src/main.cpp | 3 +++ tc/src/tpl-test_base.cpp | 5 +++++ 4 files changed, 16 insertions(+) diff --git a/src/Makefile.am b/src/Makefile.am index af61301..8c4f651 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,10 @@ libtpl_egl_laincludedir = $(includedir) libtpl_egl_la_CFLAGS = -I$(srcdir) \ @TPL_CFLAGS@ +if ENABLE_GCOV +libtpl_egl_la_CFLAGS += -DTIZEN_TEST_GCOV +endif + libtpl_egl_la_LIBADD = @TPL_LIBS@ libtpl_egl_la_LDFLAGS = -version-number @TPL_VERSION_MAJOR@:@TPL_VERSION_MINOR@:@TPL_VERSION_PATCH@ diff --git a/src/wayland-egl/Makefile.am b/src/wayland-egl/Makefile.am index e51bc63..cf0a9e6 100644 --- a/src/wayland-egl/Makefile.am +++ b/src/wayland-egl/Makefile.am @@ -7,6 +7,10 @@ libwayland_egl_laincludedir = $(includedir) libwayland_egl_la_CFLAGS = -I$(srcdir) \ @WL_EGL_CFLAGS@ +if ENABLE_GCOV +libwayland_egl_la_CFLAGS += -DTIZEN_TEST_GCOV +endif + libwayland_egl_la_LIBADD = @WL_EGL_LIBS@ libwayland_egl_la_LDFLAGS = -version-number @WL_EGL_VERSION_MAJOR@:@WL_EGL_VERSION_MINOR@:@WL_EGL_VERSION_PATCH@ libwayland_egl_la_SOURCES = wayland-egl.c diff --git a/tc/src/main.cpp b/tc/src/main.cpp index fa0afd3..3dd5afe 100644 --- a/tc/src/main.cpp +++ b/tc/src/main.cpp @@ -103,6 +103,9 @@ tpl_test_parse_arguments(int argc, char **argv) int main(int argc, char **argv) { +#ifdef TIZEN_TEST_GCOV + setenv("GCOV_PREFIX", "/tmp/daemon", 1); +#endif // Setup configurations TPLTestBase::config = tpl_test_parse_arguments(argc, argv); diff --git a/tc/src/tpl-test_base.cpp b/tc/src/tpl-test_base.cpp index a1ef6b4..d6c5b75 100644 --- a/tc/src/tpl-test_base.cpp +++ b/tc/src/tpl-test_base.cpp @@ -21,5 +21,10 @@ void TPLTestBase::TearDownTestCase() { backend->tpl_backend_finalize(&config); + +#ifdef TIZEN_TEST_GCOV + void __gcov_flush(void); + __gcov_flush(); +#endif } -- 2.7.4 From d9ea671fd253b9c6782eb37e4b61d9d044d9574b Mon Sep 17 00:00:00 2001 From: Hoyub Lee Date: Wed, 3 Jan 2018 15:16:05 +0900 Subject: [PATCH 04/16] tpl_wayland_egl: Add necessity check for buffer release On buffer release cb, there was no checking mechanism to check if this buffer needs to be released or not. This patch will add checking if this buffer has to be released or not. Therefore, unnecessary buffer release cb will be detected and handled correctly. Change-Id: I08224b2eeca1cc97b685c95ce5fb06981f37909c Signed-off-by: Hoyub Lee --- src/tpl_wayland_egl.c | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 35cb53f..ab534a7 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -64,6 +64,7 @@ struct _tpl_wayland_egl_buffer { tpl_bool_t rotated; /* TRUE if need to call wl_surface_set_buffer_transform */ tpl_bool_t reset; /* TRUE if queue reseted by external */ tpl_bool_t is_new; /* for frontbuffer mode */ + tpl_bool_t need_to_release; /* for checking need release */ struct wl_proxy *wl_proxy; /* wl_buffer proxy */ }; @@ -795,6 +796,8 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, wl_surface_commit(wl_egl_window->surface); + wayland_egl_buffer->need_to_release = TPL_TRUE; + wl_display_flush(wayland_egl_display->wl_dpy); TPL_LOG_B("WL_EGL", @@ -1416,22 +1419,31 @@ __cb_client_buffer_release_callback(void *data, struct wl_proxy *proxy) __tpl_wayland_egl_get_wayland_buffer_from_tbm_surface(tbm_surface); if (wayland_egl_buffer) { - wayland_egl_surface = wayland_egl_buffer->wayland_egl_surface; - - if (wayland_egl_surface->attached_buffers) { - TPL_OBJECT_LOCK(&wayland_egl_surface->base); - /* Stop tracking of this released tbm_surface. */ - __tpl_list_remove_data(wayland_egl_surface->attached_buffers, - (void *)tbm_surface, TPL_FIRST, NULL); - TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + if (wayland_egl_buffer->need_to_release) { + wayland_egl_surface = wayland_egl_buffer->wayland_egl_surface; + + if (wayland_egl_surface->attached_buffers) { + TPL_OBJECT_LOCK(&wayland_egl_surface->base); + /* Stop tracking of this released tbm_surface. */ + __tpl_list_remove_data(wayland_egl_surface->attached_buffers, + (void *)tbm_surface, TPL_FIRST, NULL); + TPL_OBJECT_UNLOCK(&wayland_egl_surface->base); + } + /* If tbm_surface_queue was reset before release_cb called out, + * tbm_surface_queue_release doesn't have to be done. */ + if (wayland_egl_buffer->reset == TPL_FALSE) + tbm_surface_queue_release(wayland_egl_surface->tbm_queue, + tbm_surface); + + wayland_egl_buffer->need_to_release = TPL_FALSE; + + tbm_surface_internal_unref(tbm_surface); + } else { + TPL_WARN("No need to release buffer | wl_buffer(%p) tbm_surface(%p) bo(%d)", + proxy, tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); } - /* If tbm_surface_queue was reset before release_cb called out, - * tbm_surface_queue_release doesn't have to be done. */ - if (wayland_egl_buffer->reset == TPL_FALSE) - tbm_surface_queue_release(wayland_egl_surface->tbm_queue, tbm_surface); } - - tbm_surface_internal_unref(tbm_surface); } } -- 2.7.4 From 1b2b1429a64c991097b0cda065772377558df636 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 14 Dec 2017 16:19:39 +0900 Subject: [PATCH 05/16] tpl_wayland_egl_thread: Implemented sub_thread for sync drawing. - This sub_thread for vulkan swapchain is temporary feature. - It will be destoryed when kernel can supports polling sync_fd. - tbm_sync_fence_wait() is blocking call and it will be called in this vk_sub_thread. Change-Id: I73cfd513cd4540266fdc728f3b7b66a4905c5fdf Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index e8bf76b..5081675 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -118,6 +118,10 @@ struct _twe_wl_surf_source { GMutex free_queue_mutex; GCond free_queue_cond; + + /* for waiting draw done */ + GThread *vk_sub_thread; + GMainLoop *vk_sub_loop; }; struct _twe_wl_buffer_info { @@ -2238,6 +2242,16 @@ _twe_thread_wl_surf_source_destroy(void *source) g_mutex_unlock(&_twe_ctx->thread_mutex); } +static gpointer +_vk_sub_thread_loop(gpointer data) +{ + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; + + g_main_loop_run(surf_source->vk_sub_loop); + + return surf_source->vk_sub_thread; +} + twe_surface_h twe_surface_add(twe_thread* thread, twe_display_h twe_display, @@ -2324,8 +2338,18 @@ 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; + + context = g_main_context_new(); + source->vk_sub_loop = g_main_loop_new(context, FALSE); + g_main_context_unref(context); + + /* TODO : Below line will be deleted. It is temporary code for sync_drawing. */ + source->vk_sub_thread = g_thread_new("twe_sub_thread", _vk_sub_thread_loop, + source); } source->surf_del_source = _twe_del_source_init(ctx, source); @@ -2374,6 +2398,11 @@ twe_surface_del(twe_surface_h twe_surface) surf_del_source = surf_source->surf_del_source; g_mutex_lock(&_twe_ctx->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); + _twe_thread_del_source_trigger(surf_del_source); g_cond_wait(&_twe_ctx->thread_cond, &_twe_ctx->thread_mutex); -- 2.7.4 From 1420295cfcf9337818dec1a1f6d3c676cf7df850 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 15 Dec 2017 11:48:31 +0900 Subject: [PATCH 06/16] tpl_wayland_egl_thread: Added parameter twe_surface_h to twe_surface_set_sync_fd. Change-Id: Ib448d8acf4fe218a208506bba90003f9466d1273 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 6 +++++- src/tpl_wayland_egl_thread.h | 3 ++- src/tpl_wl_vk_thread.c | 3 ++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 5081675..7274b2f 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -2684,10 +2684,14 @@ twe_surface_commit_without_enqueue(twe_surface_h twe_surface, } tpl_result_t -twe_surface_set_sync_fd(tbm_surface_h tbm_surface, tbm_fd sync_fd) +twe_surface_set_sync_fd(twe_surface_h twe_surface, + tbm_surface_h tbm_surface, tbm_fd sync_fd) { twe_wl_buffer_info *buf_info = NULL; + /* TODO : It will be used at soon */ + TPL_IGNORE(twe_surface); + tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, (void **)&buf_info); if (!buf_info) { diff --git a/src/tpl_wayland_egl_thread.h b/src/tpl_wayland_egl_thread.h index 3e22829..ad44dd0 100644 --- a/src/tpl_wayland_egl_thread.h +++ b/src/tpl_wayland_egl_thread.h @@ -84,7 +84,8 @@ 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); +twe_surface_set_sync_fd(twe_surface_h twe_surface, + tbm_surface_h tbm_surface, tbm_fd wait_fd); tbm_fd twe_surface_create_sync_fd(tbm_surface_h tbm_surface); diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c index b917001..527ee3a 100644 --- a/src/tpl_wl_vk_thread.c +++ b/src/tpl_wl_vk_thread.c @@ -355,7 +355,8 @@ __tpl_wl_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, if (sync_fence != -1) { tpl_result_t res = TPL_ERROR_NONE; - res = twe_surface_set_sync_fd(tbm_surface, sync_fence); + res = twe_surface_set_sync_fd(wayland_vk_wsi_surface->twe_surface, + tbm_surface, sync_fence); if (res != TPL_ERROR_NONE) { TPL_ERR("Failed to set sync_fd to tbm_surface(%p)", tbm_surface); tbm_surface_internal_unref(tbm_surface); -- 2.7.4 From 856dee6178214a53ac4f8bb76768f1cb38f9434c Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 3 Jan 2018 18:06:17 +0900 Subject: [PATCH 07/16] tpl_wayland_egl_thread: Added an exception checking. Change-Id: Id3562d0832f7ab5d911dd83d9b7571e349a62751 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 7274b2f..d865a69 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -292,7 +292,7 @@ _twe_del_source_init(twe_thread_context *ctx, void *target_source) source = (twe_del_source *)g_source_new(&_twe_del_source_funcs, sizeof(twe_del_source)); if (!source) { - TPL_ERR("[THREAD] Failed to create GSource"); + TPL_ERR("[THREAD] Failed to create twe_del_source."); return NULL; } @@ -947,6 +947,11 @@ twe_display_add(twe_thread* thread, source = (twe_wl_disp_source *)g_source_new(&_twe_wl_disp_funcs, sizeof(twe_wl_disp_source)); + if (!source) { + TPL_ERR("Failed to create twe_wl_disp_source."); + return NULL; + } + source->disp = display; source->ev_queue = ev_queue; source->wl_tbm_client = wl_tbm_client; @@ -2261,7 +2266,6 @@ twe_surface_add(twe_thread* thread, twe_thread_context *ctx = thread->ctx; twe_wl_surf_source *source = NULL; twe_wl_disp_source *disp_source = (twe_wl_disp_source *)twe_display; - GIOChannel *event_channel = NULL; gboolean is_destroyed = FALSE; tbm_surface_queue_h tbm_queue = NULL; @@ -2275,8 +2279,7 @@ twe_surface_add(twe_thread* thread, source = (twe_wl_surf_source *)g_source_new(&_twe_wl_surface_funcs, sizeof(twe_wl_surf_source)); if (!source) { - TPL_ERR("[THREAD] Failed to create GSource from event_channel(%p)", - event_channel); + TPL_ERR("[THREAD] Failed to create twe_wl_surf_source"); return NULL; } -- 2.7.4 From 7513387589a725918d5ee47ff6458a3c46ef1756 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 15 Dec 2017 17:36:06 +0900 Subject: [PATCH 08/16] tpl_wayland_egl_thread: Implemented sync_draw_source. - One sync_draw_source is created for each buffer which is enqueued to tbm_queue. - sync_draw_source will be attached to vk_sub_thread. - It is created when set sync_fence_fd and blocking waits in vk_sub_thread until fence is released. Change-Id: I1aba360f52a2c6d245bb52c34c42a465dacc5215 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 243 +++++++++++++++++++++++++++++++------------ src/tpl_wl_vk_thread.c | 5 +- 2 files changed, 178 insertions(+), 70 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index d865a69..29f92a4 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -31,6 +31,7 @@ typedef struct _twe_wl_surf_source twe_wl_surf_source; typedef struct _twe_wl_buffer_info twe_wl_buffer_info; typedef struct _twe_tdm_source twe_tdm_source; typedef struct _twe_del_source twe_del_source; +typedef struct _vk_sync_draw_source twe_sync_draw_source; struct _twe_thread_context { GThread *twe_thread; @@ -120,6 +121,7 @@ struct _twe_wl_surf_source { GCond free_queue_cond; /* for waiting draw done */ + tpl_bool_t use_sync_fence; GThread *vk_sub_thread; GMainLoop *vk_sub_loop; }; @@ -144,17 +146,26 @@ struct _twe_wl_buffer_info { /* 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; + twe_sync_draw_source *sync_draw_source; tbm_surface_h tbm_surface; twe_wl_surf_source *surf_source; }; +struct _vk_sync_draw_source { + GSource gsource; + gpointer tag; + int event_fd; + int draw_done_signal_fd; + tbm_fd draw_fence_fd; + tbm_surface_h tbm_surface; + twe_wl_buffer_info *buf_info; +}; static twe_thread_context *_twe_ctx; static twe_tdm_source * @@ -1270,11 +1281,6 @@ __cb_twe_buffer_free_callback(twe_wl_buffer_info *buf_info) wl_display_flush(disp_source->disp); - if (buf_info->draw_done_fence != -1) { - close(buf_info->draw_done_fence); - buf_info->draw_done_fence = -1; - } - if (buf_info->wl_buffer) wayland_tbm_client_destroy_buffer(disp_source->wl_tbm_client, (void *)buf_info->wl_buffer); @@ -1462,7 +1468,6 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, TPL_WARN("Failed to create TBM sync timeline: %d(%s)", errno, buf); } - buf_info->draw_done_fence = -1; buf_info->sync_timestamp = 0; buf_info->surf_source = surf_source; buf_info->num_rects = 0; @@ -1470,6 +1475,7 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->need_to_commit = TPL_TRUE; buf_info->draw_done = TPL_FALSE; buf_info->tbm_surface = tbm_surface; + buf_info->sync_draw_source = NULL; wl_buffer_add_listener((void *)buf_info->wl_buffer, &wl_buffer_release_listener, tbm_surface); @@ -1541,11 +1547,14 @@ __cb_tbm_queue_acquirable_callback(tbm_surface_queue_h surface_queue, uint64_t value = 1; int ret; - 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; + if (!surf_source->disp_source->is_vulkan_dpy + || !surf_source->use_sync_fence) { + 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; + } } } @@ -1658,46 +1667,6 @@ _twe_surface_wait_vblank(twe_wl_surf_source *surf_source) return TPL_ERROR_NONE; } -static tpl_result_t -_twe_surface_wait_draw_done(tbm_surface_h tbm_surface) -{ - twe_wl_buffer_info *buf_info = NULL; - - if (!tbm_surface || !tbm_surface_internal_is_valid(tbm_surface)) { - TPL_ERR("Invalid 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) { - TPL_ERR("Failed to get twe_wl_buffer_info from tbm_surface(%p)", - tbm_surface); - return TPL_ERROR_INVALID_OPERATION; - } - - if (buf_info->draw_done_fence == -1) { - TPL_WARN("tbm_surface(%p) will be presented immediately.", tbm_surface); - return TPL_ERROR_NONE; - } - - TRACE_BEGIN("Fence waiting. BO(%d)", - tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); - 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(%d). | error: %d(%s)", - buf_info->draw_done_fence, errno, buf); - } - TRACE_END(); - - close(buf_info->draw_done_fence); - buf_info->draw_done_fence = -1; - buf_info->draw_done = TPL_TRUE; - - return TPL_ERROR_NONE; -} - static void _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, tbm_surface_h tbm_surface) @@ -1882,12 +1851,6 @@ _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); - if (!buf_info->draw_done && buf_info->draw_done_fence != -1) { - /* wait until draw done. */ - if (_twe_surface_wait_draw_done(tbm_surface) != TPL_ERROR_NONE) - TPL_ERR("Failed to wait drawing complete."); - } - if (!disp_source->is_vulkan_dpy) { /* wayland_egl */ TPL_LOG_T(BACKEND, "[ACQ] tbm_surface(%p) bo(%d)", tbm_surface, @@ -2316,6 +2279,7 @@ twe_surface_add(twe_thread* thread, source->cb_data = NULL; source->rotate_cb = NULL; source->format = format; + source->use_sync_fence = TPL_FALSE; /* for vulkan swapchain */ source->vblank_waiting_buffers = NULL; @@ -2686,33 +2650,178 @@ twe_surface_commit_without_enqueue(twe_surface_h twe_surface, TPL_OBJECT_UNLOCK(&surf_source->obj); } +static gboolean +_twe_thread_sync_draw_source_dispatch(GSource *source, GSourceFunc cb, gpointer data) +{ + twe_sync_draw_source *sync_draw_source = (twe_sync_draw_source *)source; + GIOCondition cond; + + if (g_source_is_destroyed(source)) { + TPL_ERR("del_source(%p) already destroyed.", source); + return G_SOURCE_REMOVE; + } + + cond = g_source_query_unix_fd(source, sync_draw_source->tag); + + if (cond & G_IO_IN) { + ssize_t s; + uint64_t u; + int ret; + uint64_t value = 1; + tbm_surface_h tbm_surface = sync_draw_source->tbm_surface; + + tbm_surface_internal_ref(tbm_surface); + + s = read(sync_draw_source->event_fd, &u, sizeof(uint64_t)); + if (s != sizeof(uint64_t)) + TPL_ERR("Failed to read from event_fd(%d)", + sync_draw_source->event_fd); + + 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) { + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_ERR("Failed to wait sync fence(%d). | error: %d(%s)", + sync_draw_source->draw_fence_fd, errno, buf); + } + + /* Draw done */ + /* Send event to twe_wl_surf_source */ + ret = write(sync_draw_source->draw_done_signal_fd, + &value, sizeof(uint64_t)); + if (ret == -1) { + TPL_ERR("failed to send acquirable event. tbm_surface(%p)", + tbm_surface); + return G_SOURCE_REMOVE; + } + TRACE_END(); + + tbm_surface_internal_unref(tbm_surface); + } + + return G_SOURCE_REMOVE; +} + +static void +_twe_thread_sync_draw_source_finalize(GSource *source) +{ + twe_sync_draw_source *sync_draw_source = (twe_sync_draw_source *)source; + twe_wl_buffer_info *buf_info = sync_draw_source->buf_info; + + TPL_LOG_T(BACKEND, "gsource(%p) event_fd(%d)", + source, sync_draw_source->event_fd); + + close(sync_draw_source->event_fd); + + buf_info->sync_draw_source = NULL; + sync_draw_source->tag = NULL; + sync_draw_source->event_fd = -1; + sync_draw_source->draw_done_signal_fd = -1; + sync_draw_source->buf_info = NULL; + sync_draw_source->tbm_surface = NULL; + + return; +} + +static GSourceFuncs _twe_sync_draw_source_funcs = { + .prepare = NULL, + .check = NULL, + .dispatch = _twe_thread_sync_draw_source_dispatch, + .finalize = _twe_thread_sync_draw_source_finalize, +}; + +static twe_sync_draw_source * +_twe_sync_draw_source_attach(twe_wl_surf_source *surf_source, + twe_wl_buffer_info *buf_info, + tbm_fd sync_fd) +{ + twe_sync_draw_source *source = NULL; + + if (!surf_source->vk_sub_thread || !surf_source->vk_sub_loop) { + TPL_ERR("Invalid parameter. vk_sub_thread is not initialized."); + return NULL; + } + + if (!buf_info) { + TPL_ERR("Invalid parameter. buf_info is NULL"); + return NULL; + } + + source = (twe_sync_draw_source *)g_source_new(&_twe_sync_draw_source_funcs, + sizeof(twe_sync_draw_source)); + if (!source) { + TPL_ERR("[THREAD] Failed to create GSource"); + return NULL; + } + + source->event_fd = eventfd(0, EFD_CLOEXEC); + if (source->event_fd < 0) { + TPL_ERR("[THREAD] Failed to create eventfd. errno(%d)", errno); + g_source_unref(&source->gsource); + return NULL; + } + + source->tag = g_source_add_unix_fd(&source->gsource, + source->event_fd, + G_IO_IN); + source->draw_done_signal_fd = surf_source->event_fd; + source->draw_fence_fd = sync_fd; + source->buf_info = buf_info; + source->tbm_surface = buf_info->tbm_surface; + + g_source_attach(&source->gsource, g_main_loop_get_context(surf_source->vk_sub_loop)); + g_source_unref(&source->gsource); + + return source; +} + tpl_result_t twe_surface_set_sync_fd(twe_surface_h twe_surface, tbm_surface_h tbm_surface, tbm_fd sync_fd) { + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)twe_surface; twe_wl_buffer_info *buf_info = NULL; - - /* TODO : It will be used at soon */ - TPL_IGNORE(twe_surface); + twe_sync_draw_source *sync_draw_source = NULL; + int ret; + uint64_t value = 1; 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); + surf_source->use_sync_fence = TPL_FALSE; return TPL_ERROR_INVALID_OPERATION; } - if (sync_fd == -1) { - TPL_WARN("It will be managed with async mode."); + sync_draw_source = _twe_sync_draw_source_attach(surf_source, + buf_info, sync_fd); + if (!sync_draw_source) { + TPL_ERR("Failed to create and attach sync_draw_source."); + surf_source->use_sync_fence = TPL_FALSE; + return TPL_ERROR_INVALID_OPERATION; } - if (buf_info->draw_done_fence != -1) { - close(buf_info->draw_done_fence); - buf_info->draw_done_fence = -1; + /* Draw done */ + /* Send event to twe_wl_surf_source */ + 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); + g_source_destroy(&sync_draw_source->gsource); + g_source_unref(&sync_draw_source->gsource); + surf_source->use_sync_fence = TPL_FALSE; + return TPL_ERROR_INVALID_OPERATION; } - buf_info->draw_done_fence = sync_fd; + surf_source->use_sync_fence = TPL_TRUE; return TPL_ERROR_NONE; } diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c index 527ee3a..b1eaf75 100644 --- a/src/tpl_wl_vk_thread.c +++ b/src/tpl_wl_vk_thread.c @@ -358,9 +358,8 @@ __tpl_wl_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, res = twe_surface_set_sync_fd(wayland_vk_wsi_surface->twe_surface, tbm_surface, sync_fence); if (res != TPL_ERROR_NONE) { - TPL_ERR("Failed to set sync_fd to tbm_surface(%p)", tbm_surface); - tbm_surface_internal_unref(tbm_surface); - return res; + TPL_WARN("Failed to set sync_fd(%d). Fallback to async mode.", + sync_fence); } } -- 2.7.4 From e3716d8057e860a70ed827070ee01fc19d4af78f Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Mon, 18 Dec 2017 15:45:05 +0900 Subject: [PATCH 09/16] tpl_wayland_egl_thread: Fixed vblank operation in FIFO mode. - Do not add a vblank_wait when there is already a buffer waiting for vblank. Change-Id: If15cdf031de5214280285543f32673f73ef92b58 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 29f92a4..8a0fb30 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -180,6 +180,8 @@ static void _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source); static void __cb_buffer_remove_from_list(void *data); +static tpl_result_t +_twe_surface_wait_vblank(twe_wl_surf_source *surf_source); static gpointer _twe_thread_loop(gpointer data) @@ -1331,6 +1333,8 @@ __cb_buffer_release_callback(void *data, struct wl_proxy *wl_buffer) buf_info->need_to_release = TPL_FALSE; + TRACE_MARK("[RELEASE] BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); TRACE_ASYNC_END((int)tbm_surface, "[COMMIT ~ RELEASE] BO(%d)", tbm_bo_export(tbm_surface_internal_get_bo( tbm_surface, 0))); @@ -1615,6 +1619,24 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, break; case TPL_DISPLAY_PRESENT_MODE_FIFO: + if (surf_source->vblank_waiting_buffers) { + tbm_surface_h tbm_surface = NULL; + tbm_surface = (tbm_surface_h)__tpl_list_pop_front( + surf_source->vblank_waiting_buffers, + NULL); + if (tbm_surface) + _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface); + } + + if (!__tpl_list_is_empty(surf_source->vblank_waiting_buffers)) { + tpl_result_t res = TPL_ERROR_NONE; + res = _twe_surface_wait_vblank(surf_source); + if (res != TPL_ERROR_NONE) + TPL_ERR("Failed to set wait vblank. surf_source(%p)", + surf_source); + } + break; + case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED: if (surf_source->vblank_waiting_buffers) { tbm_surface_h tbm_surface = NULL; @@ -1624,6 +1646,7 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error, if (tbm_surface) _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface); } + break; } } @@ -1690,10 +1713,13 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, surf_source->swapchain_properties.height); wl_surface_commit(wl_surface); + TRACE_MARK("[COMMIT] BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); TRACE_ASYNC_BEGIN((int)tbm_surface, "[COMMIT ~ RELEASE] BO(%d)", tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); buf_info->sync_timestamp++; + buf_info->need_to_release = TPL_TRUE; TPL_LOG_T(BACKEND, "[COMMIT] wl_buffer(%p) tbm_surface(%p) bo(%d)", buf_info->wl_buffer, tbm_surface, @@ -1886,13 +1912,16 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) break; case TPL_DISPLAY_PRESENT_MODE_FIFO: - if (surf_source->vblank_waiting_buffers) { - __tpl_list_push_back(surf_source->vblank_waiting_buffers, - (void *)tbm_surface); + if (surf_source->vblank_done) { if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE) { TPL_WARN("Failed to set wait vblank. Falling back to IMMEDIATE_MODE."); _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface); } + } + if (surf_source->vblank_waiting_buffers) { + __tpl_list_push_back(surf_source->vblank_waiting_buffers, + (void *)tbm_surface); + } else { TPL_ERR("Invalid list. vblank_waiting_buffers is NULL."); } -- 2.7.4 From 023a78b551f5696322bec3f0ecb689fec303fcd5 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 27 Dec 2017 10:46:04 +0900 Subject: [PATCH 10/16] tpl_wl_vk_thread: Enqueue tbm_surface before set sync_fd. Change-Id: I6e1d29275448aa43bc1232545510553c1ae2cd4a Signed-off-by: joonbum.ko --- src/tpl_wl_vk_thread.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c index b1eaf75..8167b3d 100644 --- a/src/tpl_wl_vk_thread.c +++ b/src/tpl_wl_vk_thread.c @@ -353,6 +353,15 @@ __tpl_wl_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, return TPL_ERROR_INVALID_PARAMETER; } + tsq_err = tbm_surface_queue_enqueue(wayland_vk_wsi_surface->tbm_queue, + tbm_surface); + if (tsq_err == TBM_SURFACE_QUEUE_ERROR_NONE) { + tbm_surface_internal_unref(tbm_surface); + } else { + TPL_ERR("Failed to enqeueue tbm_surface. | tsq_err = %d", tsq_err); + return TPL_ERROR_INVALID_OPERATION; + } + if (sync_fence != -1) { tpl_result_t res = TPL_ERROR_NONE; res = twe_surface_set_sync_fd(wayland_vk_wsi_surface->twe_surface, @@ -363,18 +372,10 @@ __tpl_wl_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, } } - tsq_err = tbm_surface_queue_enqueue(wayland_vk_wsi_surface->tbm_queue, - tbm_surface); - if (tsq_err == TBM_SURFACE_QUEUE_ERROR_NONE) { - tbm_surface_internal_unref(tbm_surface); - } else { - TPL_ERR("Failed to enqeueue tbm_surface. | tsq_err = %d", tsq_err); - return TPL_ERROR_INVALID_OPERATION; - } - - TPL_LOG_T("WL_VK", "[ENQ] tbm_surface(%p) bo(%d)", + TPL_LOG_T("WL_VK", "[ENQ] tbm_surface(%p) bo(%d) sync_fence(%d)", tbm_surface, - tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)), + sync_fence); return TPL_ERROR_NONE; } -- 2.7.4 From bdf4af68cf7f918f1166a32e12afed8730c000cc Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 27 Dec 2017 14:30:45 +0900 Subject: [PATCH 11/16] tpl_wayland_egl_thread: Deleted unnecessary codes. - It should be deleted because it can cause blocking in vkWaitForFences(). Change-Id: Ia945ca3f05c613e7ae50efb9f80d92a5663921ed Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 8a0fb30..d110276 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -2865,19 +2865,16 @@ twe_surface_create_sync_fd(tbm_surface_h tbm_surface) (void **)&buf_info); if (buf_info) { - if (buf_info->sync_timestamp) { - /* first return -1 */ - char name[32]; - snprintf(name, 32, "%d", - tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); - sync_fd = tbm_sync_fence_create(buf_info->sync_timeline, - name, - buf_info->sync_timestamp); - if (sync_fd == -1) { - char buf[1024]; - strerror_r(errno, buf, sizeof(buf)); - TPL_ERR("Failed to create TBM sync fence: %d(%s)", errno, buf); - } + char name[32]; + snprintf(name, 32, "%d", + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + sync_fd = tbm_sync_fence_create(buf_info->sync_timeline, + name, + buf_info->sync_timestamp); + if (sync_fd == -1) { + char buf[1024]; + strerror_r(errno, buf, sizeof(buf)); + TPL_ERR("Failed to create TBM sync fence: %d(%s)", errno, buf); } } -- 2.7.4 From 406a63e3adcec82c1da32e795ff6206ceebc02a8 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Wed, 27 Dec 2017 10:58:08 +0900 Subject: [PATCH 12/16] tpl_wayland_egl_thread: Modified the management of committed buffer to use sync timeline. - If tdm_fd is created for a dequeued buffer, it must be dependent on the sync timeline, not the release event. Change-Id: I66b181b1ce3b12fd7a9a076359c545a19096558b Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 65 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 4 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index d110276..644c24c 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -150,6 +150,10 @@ struct _twe_wl_buffer_info { /* for checking released from display server */ tbm_fd sync_timeline; unsigned int sync_timestamp; + tbm_fd sync_fd; + tpl_bool_t is_vk_image; + + /* for waiting draw done */ twe_sync_draw_source *sync_draw_source; tbm_surface_h tbm_surface; @@ -1349,6 +1353,35 @@ __cb_buffer_release_callback(void *data, struct wl_proxy *wl_buffer) return; } + + if (buf_info && buf_info->is_vk_image && !buf_info->need_to_release) { + twe_wl_surf_source *surf_source = buf_info->surf_source; + + g_mutex_lock(&surf_source->free_queue_mutex); + + if (surf_source->committed_buffers) { + TPL_OBJECT_LOCK(&surf_source->obj); + __tpl_list_remove_data(surf_source->committed_buffers, + (void *)tbm_surface, + TPL_FIRST, NULL); + TPL_OBJECT_UNLOCK(&surf_source->obj); + } + + TRACE_MARK("[RELEASE] BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + TRACE_ASYNC_END((int)tbm_surface, "[COMMIT ~ RELEASE] BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo( + tbm_surface, 0))); + + TPL_LOG_T(BACKEND, "[REL] wl_buffer(%p) tbm_surface(%p) bo(%d)", + buf_info->wl_buffer, tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + + tbm_surface_internal_unref(tbm_surface); + + g_mutex_unlock(&surf_source->free_queue_mutex); + } + } else { TPL_ERR("Invalid parameter | tbm_surface(%p)", tbm_surface); } @@ -1405,6 +1438,7 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->need_to_commit = TPL_TRUE; buf_info->draw_done = TPL_FALSE; + buf_info->sync_fd = -1; if (surf_source->in_use_buffers) { TPL_OBJECT_LOCK(&surf_source->obj); @@ -1480,6 +1514,13 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->draw_done = TPL_FALSE; buf_info->tbm_surface = tbm_surface; buf_info->sync_draw_source = NULL; + buf_info->sync_fd = -1; + buf_info->is_vk_image = surf_source->disp_source->is_vulkan_dpy; + + if (buf_info->is_vk_image) + 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); @@ -1696,6 +1737,7 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, { twe_wl_buffer_info *buf_info = NULL; struct wl_surface *wl_surface = surf_source->surf; + tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE; tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, (void **)&buf_info); @@ -1719,7 +1761,6 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); buf_info->sync_timestamp++; - buf_info->need_to_release = TPL_TRUE; TPL_LOG_T(BACKEND, "[COMMIT] wl_buffer(%p) tbm_surface(%p) bo(%d)", buf_info->wl_buffer, tbm_surface, @@ -1734,6 +1775,21 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, if (surf_source->committed_buffers) { __tpl_list_push_back(surf_source->committed_buffers, tbm_surface); } + + /* Presented buffer's sync operating dependent on tdm timeline fence. */ + if (buf_info->sync_fd != -1) { + g_mutex_lock(&surf_source->free_queue_mutex); + 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) when vk_surface_commit.", + tbm_surface); + g_cond_signal(&surf_source->free_queue_cond); + g_mutex_unlock(&surf_source->free_queue_mutex); + buf_info->need_to_release = TPL_FALSE; + } else { + /* Dependent on wl_buffer release event. */ + buf_info->need_to_release = TPL_TRUE; + } } static void @@ -1884,6 +1940,8 @@ _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 */ + twe_sync_draw_source *sync_draw_source = buf_info->sync_draw_source; + switch (surf_source->swapchain_properties.present_mode) { case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface); @@ -2746,15 +2804,15 @@ _twe_thread_sync_draw_source_finalize(GSource *source) source, sync_draw_source->event_fd); close(sync_draw_source->event_fd); + close(sync_draw_source->draw_fence_fd); buf_info->sync_draw_source = NULL; + sync_draw_source->draw_fence_fd = -1; sync_draw_source->tag = NULL; sync_draw_source->event_fd = -1; sync_draw_source->draw_done_signal_fd = -1; sync_draw_source->buf_info = NULL; sync_draw_source->tbm_surface = NULL; - - return; } static GSourceFuncs _twe_sync_draw_source_funcs = { @@ -2845,7 +2903,6 @@ twe_surface_set_sync_fd(twe_surface_h twe_surface, surf_source); g_source_remove_unix_fd(&sync_draw_source->gsource, sync_draw_source->tag); g_source_destroy(&sync_draw_source->gsource); - g_source_unref(&sync_draw_source->gsource); surf_source->use_sync_fence = TPL_FALSE; return TPL_ERROR_INVALID_OPERATION; } -- 2.7.4 From 7c92126773cc8cc3353b57e26ba0d17a6fe3535a Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Thu, 28 Dec 2017 17:07:16 +0900 Subject: [PATCH 13/16] tpl_wayland_egl_thread: Synchronized creation and deletion of vk_sub_thread. Change-Id: I39a169d783d27f9a4b2f2e2b2747d809752acbd7 Signed-off-by: joonbum.ko --- src/tpl_wayland_egl_thread.c | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 644c24c..f37d599 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -122,8 +122,12 @@ struct _twe_wl_surf_source { /* for waiting draw done */ tpl_bool_t use_sync_fence; + + /* Temporary sub worker thread */ GThread *vk_sub_thread; GMainLoop *vk_sub_loop; + GMutex sub_thread_mutex; + GCond sub_thread_cond; }; struct _twe_wl_buffer_info { @@ -1940,8 +1944,6 @@ _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 */ - twe_sync_draw_source *sync_draw_source = buf_info->sync_draw_source; - switch (surf_source->swapchain_properties.present_mode) { case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface); @@ -2302,6 +2304,11 @@ _vk_sub_thread_loop(gpointer data) { twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; + g_mutex_lock(&surf_source->sub_thread_mutex); + /* Do nothing */ + g_cond_signal(&surf_source->sub_thread_cond); + g_mutex_unlock(&surf_source->sub_thread_mutex); + g_main_loop_run(surf_source->vk_sub_loop); return surf_source->vk_sub_thread; @@ -2372,6 +2379,9 @@ twe_surface_add(twe_thread* thread, source->vblank_waiting_buffers = NULL; source->draw_done_buffer = NULL; + source->vk_sub_loop = NULL; + source->vk_sub_thread = NULL; + __tpl_object_init(&source->obj, TPL_OBJECT_SURFACE, NULL); if (!disp_source->is_vulkan_dpy) { @@ -2397,13 +2407,23 @@ twe_surface_add(twe_thread* thread, 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); - /* TODO : Below line will be deleted. It is temporary code for sync_drawing. */ + 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); @@ -2451,12 +2471,27 @@ twe_surface_del(twe_surface_h twe_surface) twe_surface); surf_del_source = surf_source->surf_del_source; - g_mutex_lock(&_twe_ctx->thread_mutex); + 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); g_cond_wait(&_twe_ctx->thread_cond, &_twe_ctx->thread_mutex); -- 2.7.4 From 6e2d314e63195043b33f4eccc198b063a0c2346b Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 29 Dec 2017 16:24:20 +0900 Subject: [PATCH 14/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 15/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 16/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