From 53501ba5df9a6ce5ecbdad983e7371287b342f6f Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Tue, 13 Aug 2019 20:38:03 +0900 Subject: [PATCH 01/16] Package version up to 1.6.8 Change-Id: Ib8adc572ea1692e36bb623f0bde4f685170b0e76 --- 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 f8de9fe..1c5433c 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 6 -%define TPL_VERSION_PATCH 7 +%define TPL_VERSION_PATCH 8 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From 631f0f8b3764746b14e5a03012412ac823ec96ef Mon Sep 17 00:00:00 2001 From: SooChan Lim Date: Fri, 1 Nov 2019 13:25:26 +0900 Subject: [PATCH 02/16] package version up to 1.7.0 tizen 6.0 starts here. Change-Id: I607119bcfac5f8d3e1438bbe5e784475025ff319 --- packaging/libtpl-egl.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 1c5433c..a06d7ae 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -3,8 +3,8 @@ #TPL VERSION MACROS %define TPL_VERSION_MAJOR 1 -%define TPL_VERSION_MINOR 6 -%define TPL_VERSION_PATCH 8 +%define TPL_VERSION_MINOR 7 +%define TPL_VERSION_PATCH 0 %define TPL_VERSION %{TPL_VERSION_MAJOR}.%{TPL_VERSION_MINOR}.%{TPL_VERSION_PATCH} #TPL WINDOW SYSTEM DEFINITION -- 2.7.4 From 30f807920870e70360bffaa3a135e09d8b5ea34d Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Mon, 26 Aug 2019 11:48:59 +0900 Subject: [PATCH 03/16] tpl_wayland_egl: set need_to_release flag before commit it is possible that get release event before need_to_rlease flag is set Change-Id: I2010350256cbaa90eaa9f506acd1748f1bd247b6 --- src/tpl_wayland_egl.c | 3 ++- src/tpl_wayland_egl_thread.c | 12 +++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 54f9402..70e37a5 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -929,10 +929,11 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, wayland_tbm_client_set_buffer_serial(wayland_egl_display->wl_tbm_client, (void *)wayland_egl_buffer->wl_proxy, wayland_egl_buffer->serial); - wl_surface_commit(wl_egl_window->surface); wayland_egl_buffer->need_to_release = TPL_TRUE; + wl_surface_commit(wl_egl_window->surface); + wl_display_flush(wayland_egl_display->wl_dpy); TPL_LOG_B("WL_EGL", diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index f3c361f..1c5d5bf 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -1810,6 +1810,10 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, } } } + + /* Dependent on wl_buffer release event. */ + buf_info->need_to_release = TPL_TRUE; + wl_surface_commit(wl_surface); TRACE_MARK("[COMMIT] BO(%d)", @@ -1847,10 +1851,6 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, TPL_ERR("Failed to release tbm_surface(%p) when vk_surface_commit.", tbm_surface); } - - /* Dependent on wl_buffer release event. */ - buf_info->need_to_release = TPL_TRUE; - } static void @@ -1928,13 +1928,15 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, wayland_tbm_client_set_buffer_serial(disp_source->wl_tbm_client, (void *)buf_info->wl_buffer, buf_info->serial); + + buf_info->need_to_release = TPL_TRUE; + wl_surface_commit(wl_surface); TRACE_ASYNC_BEGIN((int)tbm_surface, "[COMMIT ~ RELEASE] BO(%d)", tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); buf_info->need_to_commit = TPL_FALSE; - 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, -- 2.7.4 From 514d363d7e82fe829dce3b2774d5e503be38d561 Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Mon, 26 Aug 2019 12:51:30 +0900 Subject: [PATCH 04/16] tpl_wayland_egl: check latest_transform in surface_commit if rotated buffer is canceled dequeue, wl_surface_set_buffer_transform isn't called Change-Id: I19e9b363bf21a532ae05aa6bd0dd7644e88a72ab --- src/tpl_wayland_egl.c | 32 +++++++++----------------------- src/tpl_wayland_egl_thread.c | 29 +++++++++++------------------ 2 files changed, 20 insertions(+), 41 deletions(-) diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 70e37a5..71f90c7 100644 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -63,7 +63,6 @@ struct _tpl_wayland_egl_buffer { int window_transform; tbm_bo bo; tpl_bool_t w_rotated; /* TRUE if need to call wayland_tbm_client_set_buffer_transform */ - tpl_bool_t rotated; /* TRUE if need to call wl_surface_set_buffer_transform */ 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 */ @@ -878,10 +877,10 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, wayland_egl_buffer->w_rotated = TPL_FALSE; } - if (wayland_egl_buffer->rotated == TPL_TRUE) { + if (wayland_egl_surface->latest_transform != wayland_egl_buffer->transform) { + wayland_egl_surface->latest_transform = wayland_egl_buffer->transform; wl_surface_set_buffer_transform(wl_egl_window->surface, wayland_egl_buffer->transform); - wayland_egl_buffer->rotated = TPL_FALSE; } wl_surface_attach(wl_egl_window->surface, (void *)wayland_egl_buffer->wl_proxy, @@ -1324,6 +1323,7 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou wayland_egl_buffer->dy = wl_egl_window->dy; wayland_egl_buffer->width = wl_egl_window->width; wayland_egl_buffer->height = wl_egl_window->height; + wayland_egl_buffer->transform = tizen_private->transform; if (wayland_egl_buffer->window_transform != tizen_private->window_transform) { wayland_egl_buffer->window_transform = tizen_private->window_transform; @@ -1332,14 +1332,6 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou wayland_egl_buffer->w_rotated = TPL_FALSE; } - if (wayland_egl_surface->latest_transform != tizen_private->transform) { - wayland_egl_surface->latest_transform = tizen_private->transform; - wayland_egl_buffer->transform = tizen_private->transform; - wayland_egl_buffer->rotated = TPL_TRUE; - } else { - wayland_egl_buffer->rotated = TPL_FALSE; - } - if (wayland_egl_surface->is_activated != is_activated) wayland_egl_buffer->is_new = TPL_TRUE; @@ -1360,10 +1352,11 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou wayland_egl_buffer->wl_proxy, tbm_surface, tbm_bo_export(wayland_egl_buffer->bo)); TPL_LOG_B("WL_EGL", - "[DEQ] size(%dx%d) transform(%d) rotated(%s)", + "[DEQ] size(%dx%d) transform(%d) w_transform(%d) w_rotated(%s)", wayland_egl_buffer->width, wayland_egl_buffer->height, wayland_egl_buffer->transform, - wayland_egl_buffer->rotated ? "[TRUE]" : "[FALSE]"); + wayland_egl_buffer->window_transform, + wayland_egl_buffer->w_rotated ? "[TRUE]" : "[FALSE]"); if (lock_res == 0) pthread_mutex_unlock(&wayland_egl_display->wl_event_mutex); return tbm_surface; @@ -1412,7 +1405,6 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou wayland_egl_buffer->bo = tbm_surface_internal_get_bo(tbm_surface, 0); wayland_egl_buffer->wayland_egl_surface = wayland_egl_surface; wayland_egl_buffer->transform = tizen_private->transform; - wayland_egl_buffer->rotated = TPL_TRUE; if (wayland_egl_buffer->window_transform != tizen_private->window_transform) { wayland_egl_buffer->window_transform = tizen_private->window_transform; @@ -1421,13 +1413,6 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou wayland_egl_buffer->w_rotated = TPL_FALSE; } - if (wayland_egl_surface->latest_transform != tizen_private->transform) { - wayland_egl_surface->latest_transform = tizen_private->transform; - wayland_egl_buffer->rotated = TPL_TRUE; - } else { - wayland_egl_buffer->rotated = TPL_FALSE; - } - /* 'is_new' flag is to check wheter it is a new buffer need to commit * in frontbuffer mode. */ wayland_egl_buffer->is_new = TPL_TRUE; @@ -1448,10 +1433,11 @@ __tpl_wayland_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeou tbm_bo_export(wayland_egl_buffer->bo)); TPL_LOG_B("WL_EGL", - "[DEQ] size(%dx%d) transform(%d) rotated(%s)", + "[DEQ] size(%dx%d) transform(%d) w_transform(%d) w_rotated(%s)", wayland_egl_buffer->width, wayland_egl_buffer->height, wayland_egl_buffer->transform, - wayland_egl_buffer->rotated ? "[TRUE]" : "[FALSE]"); + wayland_egl_buffer->window_transform, + wayland_egl_buffer->w_rotated ? "[TRUE]" : "[FALSE]"); if (wayland_egl_surface->dequeued_buffers) { TPL_OBJECT_LOCK(&wayland_egl_surface->base); diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 1c5d5bf..99b36b2 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -145,7 +145,6 @@ struct _twe_wl_buffer_info { tpl_bool_t w_rotated; /* for wl_surface_set_buffer_transform */ int transform; - tpl_bool_t rotated; /* for damage region */ int num_rects; int *rects; @@ -1382,11 +1381,6 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->w_rotated = TPL_TRUE; } - if (surf_source->latest_transform != tizen_private->transform) { - surf_source->latest_transform = tizen_private->transform; - buf_info->rotated = TPL_TRUE; - } - buf_info->transform = tizen_private->transform; buf_info->dx = wl_egl_window->dx; buf_info->dy = wl_egl_window->dy; @@ -1419,10 +1413,12 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); TPL_LOG_T(BACKEND, - "[REUSE_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) transform(%d)", + "[REUSE_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) " + "transform(%d) w_transform(%d)", buf_info, tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)), - buf_info->width, buf_info->height, buf_info->transform); + buf_info->width, buf_info->height, + buf_info->transform, buf_info->w_transform); return; } @@ -1454,11 +1450,6 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->w_rotated = TPL_TRUE; } - if (surf_source->latest_transform != tizen_private->transform) { - surf_source->latest_transform = tizen_private->transform; - buf_info->rotated = TPL_TRUE; - } - buf_info->transform = tizen_private->transform; if (surf_source->set_serial_is_used) { @@ -1481,7 +1472,7 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, buf_info->height = surf_source->swapchain_properties.height; buf_info->w_transform = 0; buf_info->w_rotated = TPL_FALSE; - buf_info->rotated = TPL_FALSE; + buf_info->transform = 0; buf_info->serial = 0; } @@ -1522,10 +1513,12 @@ _twe_surface_set_wl_buffer_info(twe_wl_surf_source *surf_source, TRACE_MARK("[SET_BUFFER_INFO] BO(%d)", tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); TPL_LOG_T(BACKEND, - "[NEW_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) transform(%d)", + "[NEW_BUF] buf_info(%p) tbm_surface(%p) bo(%d) (%dx%d) " + "transform(%d) w_transform(%d)", buf_info, tbm_surface, tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)), - buf_info->width, buf_info->height, buf_info->transform); + buf_info->width, buf_info->height, + buf_info->transform, buf_info->w_transform); } static void @@ -1881,9 +1874,9 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, buf_info->w_rotated = TPL_FALSE; } - if (buf_info->rotated == TPL_TRUE) { + if (surf_source->latest_transform != buf_info->transform) { + surf_source->latest_transform = buf_info->transform; wl_surface_set_buffer_transform(wl_surface, buf_info->transform); - buf_info->rotated = TPL_FALSE; } if (wl_egl_window) { -- 2.7.4 From 16c88f212c6ec2642e6308f9baf77a12771495de Mon Sep 17 00:00:00 2001 From: Changyeon Lee Date: Tue, 6 Aug 2019 19:53:07 +0900 Subject: [PATCH 05/16] tpl_surface: set post_interval in tdm_client_vblank_wait Change-Id: Ib936a993439f0bb3ab4c2d5049204305da013142 --- src/tpl_internal.h | 1 + src/tpl_surface.c | 19 +++++++++++++++++-- src/tpl_wayland_egl.c | 2 +- src/tpl_wayland_egl_thread.c | 23 ++++++++++++++++++++++- src/tpl_wayland_egl_thread.h | 2 ++ src/tpl_wl_egl_thread.c | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 75 insertions(+), 4 deletions(-) mode change 100644 => 100755 src/tpl_internal.h mode change 100644 => 100755 src/tpl_surface.c mode change 100644 => 100755 src/tpl_wayland_egl.c mode change 100644 => 100755 src/tpl_wayland_egl_thread.c mode change 100644 => 100755 src/tpl_wayland_egl_thread.h mode change 100644 => 100755 src/tpl_wl_egl_thread.c diff --git a/src/tpl_internal.h b/src/tpl_internal.h old mode 100644 new mode 100755 index 6dff22f..ba161c9 --- a/src/tpl_internal.h +++ b/src/tpl_internal.h @@ -110,6 +110,7 @@ struct _tpl_surface_backend { tpl_result_t (*destroy_swapchain)(tpl_surface_t *surface); tpl_result_t (*set_rotation_capability)(tpl_surface_t *surface, tpl_bool_t set); + tpl_result_t (*set_post_interval)(tpl_surface_t *surface, int post_interval); }; struct _tpl_object { diff --git a/src/tpl_surface.c b/src/tpl_surface.c old mode 100644 new mode 100755 index 8c14e82..994aec3 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -243,16 +243,29 @@ tpl_surface_validate(tpl_surface_t *surface) tpl_result_t tpl_surface_set_post_interval(tpl_surface_t *surface, int interval) { + tpl_result_t ret = TPL_ERROR_NONE; + if (!surface || (surface->type != TPL_SURFACE_TYPE_WINDOW)) { TPL_ERR("Invalid surface!"); return TPL_ERROR_INVALID_PARAMETER; } + if (interval <= 0) + return TPL_ERROR_NONE; + TPL_OBJECT_LOCK(surface); - surface->post_interval = interval; + + if (surface->backend.set_post_interval) + ret = surface->backend.set_post_interval(surface, interval); + + if (ret == TPL_ERROR_NONE) + surface->post_interval = interval; + TPL_OBJECT_UNLOCK(surface); - return TPL_ERROR_NONE; + TPL_LOG_F("tpl_surface_t(%p) post_interval(%d)", surface, surface->post_interval); + + return ret; } int @@ -269,6 +282,8 @@ tpl_surface_get_post_interval(tpl_surface_t *surface) interval = surface->post_interval; TPL_OBJECT_UNLOCK(surface); + TPL_LOG_F("tpl_surface_t(%p) post_interval(%d)", surface, interval); + return interval; } diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c old mode 100644 new mode 100755 index 71f90c7..69b34de --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -962,7 +962,7 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface, if (wayland_egl_display->tdm_client) { int tdm_lock_res = pthread_mutex_lock(&wayland_egl_display->tdm_mutex); tdm_err = tdm_client_vblank_wait(wayland_egl_surface->tdm_vblank, - 1, /* interval */ + surface->post_interval, /* interval */ __cb_tdm_client_wait_vblank, /* handler */ surface->backend.data); /* user_data */ diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c old mode 100644 new mode 100755 index 99b36b2..13a6a14 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -134,6 +134,8 @@ struct _twe_wl_surf_source { GMutex sub_thread_mutex; GCond sub_thread_cond; int draw_done_count; + + int post_interval; }; struct _twe_wl_buffer_info { @@ -1739,7 +1741,7 @@ _twe_surface_wait_vblank(twe_wl_surf_source *surf_source) } tdm_err = tdm_client_vblank_wait(surf_source->vblank, - 1, /* TODO: interval */ + surf_source->post_interval, /* TODO: interval */ __cb_tdm_client_wait_vblank, (void *)surf_source); @@ -2498,6 +2500,8 @@ twe_surface_add(twe_thread* thread, source->set_serial_is_used = TPL_FALSE; source->serial = 0; + source->post_interval = 1; + if (!disp_source->is_vulkan_dpy) { struct wl_egl_window *wl_egl_window = (struct wl_egl_window *)native_handle; @@ -3371,3 +3375,20 @@ twe_get_native_buffer_from_pixmap(tpl_handle_t pixmap) return tbm_surface; } +tpl_result_t +twe_surface_set_post_interval(twe_surface_h twe_surface, int post_interval) +{ + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)twe_surface; + + if (!surf_source || g_source_is_destroyed(&surf_source->gsource)) { + TPL_ERR("Invalid parameter. surf_source(%p)", surf_source); + return TPL_ERROR_INVALID_PARAMETER; + } + + surf_source->post_interval = post_interval; + + TPL_LOG_T(BACKEND, "surf_source(%p) post_interval(%d)", + surf_source, surf_source->post_interval); + + return TPL_ERROR_NONE; +} diff --git a/src/tpl_wayland_egl_thread.h b/src/tpl_wayland_egl_thread.h old mode 100644 new mode 100755 index 6cb9116..067def1 --- a/src/tpl_wayland_egl_thread.h +++ b/src/tpl_wayland_egl_thread.h @@ -110,3 +110,5 @@ twe_get_native_window_info(tpl_handle_t window, int *width, int *height, tbm_for tbm_surface_h twe_get_native_buffer_from_pixmap(tpl_handle_t pixmap); +tpl_result_t +twe_surface_set_post_interval(twe_surface_h twe_surface, int post_interval); diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c old mode 100644 new mode 100755 index 4ebe168..980c599 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -477,6 +477,36 @@ __tpl_wl_egl_surface_set_rotation_capability(tpl_surface_t *surface, } static tpl_result_t +__tpl_wl_egl_surface_set_post_interval(tpl_surface_t *surface, + int post_interval) +{ + tpl_wayland_egl_surface_t *wayland_egl_surface = NULL; + + if (!surface) { + TPL_ERR("Invalid parameter. tpl_surface(%p)", surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + wayland_egl_surface = (tpl_wayland_egl_surface_t *)surface->backend.data; + if (!wayland_egl_surface) { + TPL_ERR("Invalid parameter. wayland_egl_surface(%p)", + wayland_egl_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (!wayland_egl_surface->twe_surface) { + TPL_ERR("Invalid parameter. wayland_egl_surface(%p) twe_surface(%p)", + wayland_egl_surface, wayland_egl_surface->twe_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + twe_surface_set_post_interval(wayland_egl_surface->twe_surface, + post_interval); + + return TPL_ERROR_NONE; +} + +static tpl_result_t __tpl_wl_egl_surface_enqueue_buffer(tpl_surface_t *surface, tbm_surface_h tbm_surface, int num_rects, const int *rects, tbm_fd sync_fence) @@ -805,5 +835,7 @@ __tpl_surface_init_backend_wl_egl_thread(tpl_surface_backend_t *backend) backend->enqueue_buffer = __tpl_wl_egl_surface_enqueue_buffer; backend->set_rotation_capability = __tpl_wl_egl_surface_set_rotation_capability; + backend->set_post_interval = + __tpl_wl_egl_surface_set_post_interval; } -- 2.7.4 From 1192f77560a082299b777867cc143ae5463963d5 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 8 Nov 2019 13:30:39 +0900 Subject: [PATCH 06/16] Package version up to 1.7.1 Change-Id: Ifa18b79ce7d511e8d294fe59ab0713e36123b111 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 a06d7ae..7b4b3eb 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 7 -%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 1d38c642bbc5d42ff5d987aad1b01a7ed136f317 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Mon, 11 Nov 2019 11:38:59 +0900 Subject: [PATCH 07/16] Rename the directory of wayland-egl to wayland-egl-tizen. Change-Id: I4e2c8f4764a26ace10c26e0b55db9e6118d38a41 Signed-off-by: Joonbum Ko --- Makefile.am | 4 ++-- configure.ac | 2 +- src/tpl_wayland_egl.c | 4 ++-- src/tpl_wayland_egl_thread.c | 4 ++-- src/{wayland-egl => wayland-egl-tizen}/Makefile.am | 0 src/{wayland-egl => wayland-egl-tizen}/wayland-egl-tizen-priv.h | 0 src/{wayland-egl => wayland-egl-tizen}/wayland-egl-tizen.c | 0 src/{wayland-egl => wayland-egl-tizen}/wayland-egl-tizen.h | 0 tc/Makefile.am | 2 +- worker_test/Makefile | 9 +++------ 10 files changed, 11 insertions(+), 14 deletions(-) rename src/{wayland-egl => wayland-egl-tizen}/Makefile.am (100%) rename src/{wayland-egl => wayland-egl-tizen}/wayland-egl-tizen-priv.h (100%) rename src/{wayland-egl => wayland-egl-tizen}/wayland-egl-tizen.c (100%) rename src/{wayland-egl => wayland-egl-tizen}/wayland-egl-tizen.h (100%) diff --git a/Makefile.am b/Makefile.am index 66af45b..57ca9b8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,10 +1,10 @@ if WITH_UTEST SUBDIRS = src \ - src/wayland-egl \ + src/wayland-egl-tizen \ tc \ pkgconfig else SUBDIRS = src \ - src/wayland-egl \ + src/wayland-egl-tizen \ pkgconfig endif diff --git a/configure.ac b/configure.ac index 8a4f706..077366e 100644 --- a/configure.ac +++ b/configure.ac @@ -212,7 +212,7 @@ AC_CHECK_FUNCS([clock_gettime memset]) AC_CONFIG_FILES([ Makefile src/Makefile - src/wayland-egl/Makefile + src/wayland-egl-tizen/Makefile pkgconfig/Makefile pkgconfig/tpl-egl.pc pkgconfig/wayland-egl-tizen.pc diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 69b34de..d3d4d38 100755 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -2,8 +2,8 @@ #include #include -#include "wayland-egl/wayland-egl-tizen.h" -#include "wayland-egl/wayland-egl-tizen-priv.h" +#include "wayland-egl-tizen/wayland-egl-tizen.h" +#include "wayland-egl-tizen/wayland-egl-tizen-priv.h" #undef inline diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 13a6a14..dca6597 100755 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -13,8 +13,8 @@ #include "tpl_utils.h" #include "tpl_internal.h" -#include "wayland-egl/wayland-egl-tizen.h" -#include "wayland-egl/wayland-egl-tizen-priv.h" +#include "wayland-egl-tizen/wayland-egl-tizen.h" +#include "wayland-egl-tizen/wayland-egl-tizen-priv.h" #include "tpl_wayland_egl_thread.h" #include "wayland-vulkan/wayland-vulkan-client-protocol.h" #include "tpl_utils.h" diff --git a/src/wayland-egl/Makefile.am b/src/wayland-egl-tizen/Makefile.am similarity index 100% rename from src/wayland-egl/Makefile.am rename to src/wayland-egl-tizen/Makefile.am diff --git a/src/wayland-egl/wayland-egl-tizen-priv.h b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h similarity index 100% rename from src/wayland-egl/wayland-egl-tizen-priv.h rename to src/wayland-egl-tizen/wayland-egl-tizen-priv.h diff --git a/src/wayland-egl/wayland-egl-tizen.c b/src/wayland-egl-tizen/wayland-egl-tizen.c similarity index 100% rename from src/wayland-egl/wayland-egl-tizen.c rename to src/wayland-egl-tizen/wayland-egl-tizen.c diff --git a/src/wayland-egl/wayland-egl-tizen.h b/src/wayland-egl-tizen/wayland-egl-tizen.h similarity index 100% rename from src/wayland-egl/wayland-egl-tizen.h rename to src/wayland-egl-tizen/wayland-egl-tizen.h diff --git a/tc/Makefile.am b/tc/Makefile.am index 0c864ed..574dd53 100644 --- a/tc/Makefile.am +++ b/tc/Makefile.am @@ -26,4 +26,4 @@ tpl_test_LDFLAGS = ${LDFLAGS} \ @TPL_TEST_LIBS@ tpl_test_LDADD = ../src/libtpl-egl.la \ - ../src/wayland-egl/libwayland-egl.la + ../src/wayland-egl-tizen/libwayland-egl-tizen.la diff --git a/worker_test/Makefile b/worker_test/Makefile index b6989e7..7caa717 100644 --- a/worker_test/Makefile +++ b/worker_test/Makefile @@ -9,17 +9,14 @@ LDFLAGS += CFLAGS += -I../src -CFLAGS += `pkg-config --cflags libtbm glib-2.0 wayland-tbm-client wayland-tbm-server libtdm-client` -LDFLAGS += `pkg-config --libs libtbm glib-2.0 wayland-tbm-client wayland-tbm-server libtdm-client` - -WAYLAND_EGL_OBJ_PATH = ../src/wayland-egl/wayland-egl.o +CFLAGS += `pkg-config --cflags libtbm glib-2.0 wayland-tbm-client wayland-tbm-server libtdm-client wayland-egl` +LDFLAGS += `pkg-config --libs libtbm glib-2.0 wayland-tbm-client wayland-tbm-server libtdm-client wayland-egl` SRCS += $(SRC_DIR)/worker_test.c SRCS += ../src/tpl.c SRCS += ../src/tpl_utils_hlist.c SRCS += ../src/tpl_utils_map.c SRCS += ../src/tpl_object.c -SRCS += ../src/wayland-egl/wayland-egl.c SRCS += ../src/tpl_wayland_egl_thread.c HEADERS += ../src/tpl_wayland_egl_thread.h HEADERS += ../src/tpl_utils.h @@ -33,7 +30,7 @@ all : $(BIN_NAME) %.o: %.c $(CC) -c -o $@ $< $(CFLAGS) $(LDFLAGS) -$(BIN_NAME) : $(OBJS) $(WAYLAND_EGL_OBJ_PATH) ${SRCS} $(HEADERS) +$(BIN_NAME) : $(OBJS) ${SRCS} $(HEADERS) $(CC) ${SRCS} -o $@ $(CFLAGS) $(LDFLAGS) clean: -- 2.7.4 From f05d29898d4ef28372a701b7f464c1d6e6c70c45 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Mon, 11 Nov 2019 13:32:48 +0900 Subject: [PATCH 08/16] wayland-egl-tizen: Added new API to create render sync fd. New API wl_egl_window_tizen_get_render_sync_fd(struct wl_egl_window*) /** * Create a sync fence fd that can tell render done. * * If eglSwapBuffers works async, it returns fd which tells * when the render job is finished. * This fd can wait asynchronously via poll or select. * * Important * * This requires the following premise: * - After ddk calls libplpl-egl's tpl_surface_dequeue_buffer to get the buffer, * and until it calls tpl_surface_enqueue_buffer, * it is called the gpu rendering job interval. * - Therefore, when using the dma_buf implicit fence, * there is no guarantee that the rendering job is finished * with the fence obtained through this API. * * The fence_fd obtained through this function is one-time available, * can not be reused, so caller must close it when finished using it. * * @param egl_window handle to wl_egl_window. * @return sync fd on success, -1 on failure. */ Change-Id: Ia19f88108cfe8d0e5e6477acbd83a2df173f5507 Signed-off-by: Joonbum Ko --- src/wayland-egl-tizen/wayland-egl-tizen-priv.h | 2 ++ src/wayland-egl-tizen/wayland-egl-tizen.c | 24 +++++++++++++++++++++++- src/wayland-egl-tizen/wayland-egl-tizen.h | 26 ++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h index 5b65a70..69df3bc 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h @@ -22,6 +22,7 @@ struct tizen_private { int (*get_rotation_capability)(struct wl_egl_window *, void *); void (*set_frontbuffer_callback)(struct wl_egl_window *, void *, int); void (*set_window_serial_callback)(struct wl_egl_window *, void *, unsigned int); + int (*create_render_sync_fd)(struct wl_egl_window *, void *); }; static struct tizen_private* tizen_private_create() @@ -40,6 +41,7 @@ static struct tizen_private* tizen_private_create() private->get_rotation_capability = NULL; private->set_window_serial_callback = NULL; private->set_frontbuffer_callback = NULL; + private->create_render_sync_fd = NULL; } return private; diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.c b/src/wayland-egl-tizen/wayland-egl-tizen.c index 4c127bc..888f8af 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.c +++ b/src/wayland-egl-tizen/wayland-egl-tizen.c @@ -250,4 +250,26 @@ wl_egl_window_tizen_set_window_serial(struct wl_egl_window *egl_window, if (private->set_window_serial_callback) private->set_window_serial_callback(egl_window, egl_window->driver_private, serial); -} \ No newline at end of file +} + +int +wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window) +{ + struct tizen_private *private = NULL; + + if (egl_window == NULL) { + WL_EGL_ERR("egl_window is NULL"); + return -1; + } + + private = egl_window->driver_private; + if (private == NULL) { + WL_EGL_ERR("wl_egl_window(%p) dirver_private is NULL", egl_window); + return -1; + } + + if (private->create_render_sync_fd) + return private->create_render_sync_fd(egl_window, egl_window->driver_private); + + return -1; +} diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.h b/src/wayland-egl-tizen/wayland-egl-tizen.h index b305e27..96127a0 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen.h @@ -73,6 +73,32 @@ void wl_egl_window_tizen_set_window_serial(struct wl_egl_window *egl_window, unsigned int serial); +/* temporary APIs for testing sync feature */ +/** + * Create a sync fence fd that can tell render done. + * + * If eglSwapBuffers works async, it returns fd which tells + * when the render job is finished. + * This fd can wait asynchronously via poll or select. + * + * Important * + * This requires the following premise: + * - After ddk calls libplpl-egl's tpl_surface_dequeue_buffer to get the buffer, + * and until it calls tpl_surface_enqueue_buffer, + * it is called the gpu rendering job interval. + * - Therefore, when using the dma_buf implicit fence, + * there is no guarantee that the rendering job is finished + * with the fence obtained through this API. + * + * The fence_fd obtained through this function is one-time available, + * can not be reused, so caller must close it when finished using it. + * + * @param egl_window handle to wl_egl_window. + * @return sync fd on success, -1 on failure. + */ +int +wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window); + #ifdef __cplusplus } #endif -- 2.7.4 From 94f58f690824087365bf7835f7d5d4859e772063 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Tue, 12 Nov 2019 11:27:07 +0900 Subject: [PATCH 09/16] tpl_wayland_egl_thread: Implemented the render sync feature. - Create a timeline in surface units and create a sync fence to pass to the user. - The sync fence user get is signaled at the time of tpl surface enqueue. - This feature can help user sync by telling gpu render done, but this feature alone does not guarantee sync. Therefore, users should handle this sync_fence properly using poll or select. Change-Id: If1c8a894fc8e103141b88d4479274f926753e52f Signed-off-by: Joonbum Ko --- src/tpl_wayland_egl_thread.c | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index dca6597..101cf8f 100755 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -78,6 +78,7 @@ struct _twe_wl_disp_source { twe_del_source *disp_del_source; twe_thread *thread; GMutex wl_event_mutex; + /* TODO : surface list */ }; @@ -120,6 +121,10 @@ struct _twe_wl_surf_source { twe_wl_disp_source *disp_source; twe_del_source *surf_del_source; + tbm_fd render_sync_timeline; + int render_sync_timestamp; + unsigned int render_sync_fence_number; + GMutex surf_mutex; GMutex free_queue_mutex; @@ -1221,6 +1226,41 @@ __cb_set_window_serial_callback(struct wl_egl_window *wl_egl_window, } } +static int +__cb_create_render_sync_fd(struct wl_egl_window *wl_egl_window, void *private) +{ + TPL_ASSERT(private); + TPL_ASSERT(wl_egl_window); + + struct tizen_private *tizen_private = (struct tizen_private *)private; + twe_wl_surf_source *surf_source = NULL; + + tbm_fd render_sync_fd = -1; + + surf_source = (twe_wl_surf_source *)tizen_private->data; + if (!surf_source) { + TPL_ERR("Invalid parameter. twe_surface(%p)", surf_source); + return -1; + } + + if (surf_source->render_sync_timeline != -1) { + char name[32]; + snprintf(name, 32, "%u", surf_source->render_sync_fence_number++); + render_sync_fd = tbm_sync_fence_create(surf_source->render_sync_timeline, + name, + surf_source->render_sync_timestamp + 1); + TPL_DEBUG("[RENDER_SYNC] surf_source(%p) timeline(%d) timestamp(%d) name(%s) sync_fence(%d)", + surf_source, surf_source->render_sync_timeline, surf_source->render_sync_timestamp, + name, render_sync_fd); + + TRACE_ASYNC_BEGIN(surf_source->render_sync_timestamp + 1, "[SYNC_FENCE]"); + + return render_sync_fd; + } + + return -1; +} + static void __cb_tss_flusher_flush_callback(void *data, struct tizen_surface_shm_flusher *tss_flusher) @@ -1554,6 +1594,18 @@ _twe_surface_trace_enqueue_buffer(twe_wl_surf_source *surf_source, return; } + if (surf_source->render_sync_timeline != -1) { + + surf_source->render_sync_timestamp++; + TRACE_ASYNC_END(surf_source->render_sync_timestamp, "[SYNC_FENCE]"); + + TPL_DEBUG("[RENDER_SYNC][INC] surf_source(%p) timeline(%d) timestamp(%d)", + surf_source, surf_source->render_sync_timeline, surf_source->render_sync_timestamp); + if (!tbm_sync_timeline_inc(surf_source->render_sync_timeline, 1)) { + TPL_ERR("Failed to increase timeline(%d)", surf_source->render_sync_timeline); + } + } + if (surf_source->in_use_buffers) { g_mutex_lock(&surf_source->surf_mutex); /* Stop tracking of this canceled tbm_surface */ @@ -2502,6 +2554,10 @@ twe_surface_add(twe_thread* thread, source->post_interval = 1; + source->render_sync_timeline = tbm_sync_timeline_create(); + source->render_sync_timestamp = 0; + source->render_sync_fence_number = 0; + if (!disp_source->is_vulkan_dpy) { struct wl_egl_window *wl_egl_window = (struct wl_egl_window *)native_handle; @@ -2521,6 +2577,7 @@ twe_surface_add(twe_thread* thread, __cb_get_rotation_capability; private->set_window_serial_callback = (void *) __cb_set_window_serial_callback; + private->create_render_sync_fd = (void *)__cb_create_render_sync_fd; source->latest_transform = private->transform; -- 2.7.4 From 76696ef8252c097185b333aa0472fa3e89f72f5e Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Wed, 13 Nov 2019 11:40:23 +0900 Subject: [PATCH 10/16] wayland-egl-tizen: Added new API to get presentation sync fd. /** * Create a sync fence fd that can tell presentation done. * * It returns fd which tells when the presentation is finished. * This fd can wait asynchronously via poll or select. * * Important * * This fence lets caller knows when wl_surface received PRESENT or DISCARD * events from the server. * In case of receiving DISCARD, it is not actually displayed on the display, * but it releases the fence like PRESENT. * In most cases that are not complicated, attached buffer will not be discarded. * * @param egl_window handle to wl_egl_window. * @return sync fd on success, -1 on failure. */ int wl_egl_window_tizen_create_presentation_sync_fd(struct wl_egl_window *egl_window) Change-Id: I9c69dea4b78aba34db284b25dd47dd0544672bb4 Signed-off-by: Joonbum Ko --- src/wayland-egl-tizen/wayland-egl-tizen-priv.h | 2 ++ src/wayland-egl-tizen/wayland-egl-tizen.c | 22 ++++++++++++++++++++++ src/wayland-egl-tizen/wayland-egl-tizen.h | 19 +++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h index 69df3bc..6fd31ea 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h @@ -23,6 +23,7 @@ struct tizen_private { void (*set_frontbuffer_callback)(struct wl_egl_window *, void *, int); void (*set_window_serial_callback)(struct wl_egl_window *, void *, unsigned int); int (*create_render_sync_fd)(struct wl_egl_window *, void *); + int (*create_presentation_sync_fd)(struct wl_egl_window *, void *); }; static struct tizen_private* tizen_private_create() @@ -42,6 +43,7 @@ static struct tizen_private* tizen_private_create() private->set_window_serial_callback = NULL; private->set_frontbuffer_callback = NULL; private->create_render_sync_fd = NULL; + private->create_presentation_sync_fd = NULL; } return private; diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.c b/src/wayland-egl-tizen/wayland-egl-tizen.c index 888f8af..831951c 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.c +++ b/src/wayland-egl-tizen/wayland-egl-tizen.c @@ -273,3 +273,25 @@ wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window) return -1; } + +int +wl_egl_window_tizen_create_presentation_sync_fd(struct wl_egl_window *egl_window) +{ + struct tizen_private *private = NULL; + + if (egl_window == NULL) { + WL_EGL_ERR("egl_window is NULL"); + return -1; + } + + private = egl_window->driver_private; + if (private == NULL) { + WL_EGL_ERR("wl_egl_window(%p) dirver_private is NULL", egl_window); + return -1; + } + + if (private->create_presentation_sync_fd) + return private->create_presentation_sync_fd(egl_window, egl_window->driver_private); + + return -1; +} diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.h b/src/wayland-egl-tizen/wayland-egl-tizen.h index 96127a0..00b8b75 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen.h @@ -99,6 +99,25 @@ wl_egl_window_tizen_set_window_serial(struct wl_egl_window *egl_window, int wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window); +/** + * Create a sync fence fd that can tell presentation done. + * + * It returns fd which tells when the presentation is finished. + * This fd can wait asynchronously via poll or select. + * + * Important * + * This fence lets caller knows when wl_surface received PRESENT or DISCARD + * events from the server. + * In case of receiving DISCARD, it is not actually displayed on the display, + * but it releases the fence like PRESENT. + * In most cases that are not complicated, attached buffer will not be discarded. + * + * @param egl_window handle to wl_egl_window. + * @return sync fd on success, -1 on failure. + */ +int +wl_egl_window_tizen_create_presentation_sync_fd(struct wl_egl_window *egl_window); + #ifdef __cplusplus } #endif -- 2.7.4 From e32a763836f8e61b9c3a00e62a975193e761fae6 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 14 Nov 2019 19:31:42 +0900 Subject: [PATCH 11/16] tpl_wayland_egl_thread: Implemented the presentation sync feature. - Create a timeline in surface and create a sync fence to pass to the user. - The sync fence user get is signaled at the time of presentation done. - This feature can help user sync by telling presentation done. Users should handle this sync_fence properly using poll or select. - This patch depends on wayland-extension and enlightenment. Change-Id: I180ac6b23cc89ed3f7f0ebfc934893efa873dd6a Signed-off-by: Joonbum Ko --- configure.ac | 2 +- packaging/libtpl-egl.spec | 1 + src/tpl_wayland_egl_thread.c | 175 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 077366e..7a761bb 100644 --- a/configure.ac +++ b/configure.ac @@ -60,7 +60,7 @@ AC_ARG_WITH([wayland], [with_wayland=yes]) AS_IF([test "${with_wayland}" = "yes" || test "${with_wayland}" = "1"], - [PKG_CHECK_MODULES([TPL_WL], [libtdm-client wayland-tbm-client wayland-tbm-server tizen-surface-client glib-2.0 wayland-egl wayland-egl-backend]) + [PKG_CHECK_MODULES([TPL_WL], [libtdm-client wayland-tbm-client wayland-tbm-server tizen-surface-client glib-2.0 wayland-egl presentation-time-client wayland-egl-backend]) TPL_CFLAGS+="$TPL_WL_CFLAGS" TPL_CFLAGS+=" -DTPL_WINSYS_WL=1 " TPL_LIBS+="$TPL_WL_LIBS"], diff --git a/packaging/libtpl-egl.spec b/packaging/libtpl-egl.spec index 7b4b3eb..b49148a 100644 --- a/packaging/libtpl-egl.spec +++ b/packaging/libtpl-egl.spec @@ -79,6 +79,7 @@ BuildRequires: pkgconfig(wayland-egl-backend) BuildRequires: pkgconfig(wayland-tbm-client) BuildRequires: pkgconfig(wayland-tbm-server) BuildRequires: pkgconfig(tizen-surface-client) +BuildRequires: pkgconfig(presentation-time-client) BuildRequires: pkgconfig(glib-2.0) %endif diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 101cf8f..f7fb447 100755 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "tpl_utils.h" #include "tpl_internal.h" @@ -67,6 +68,7 @@ struct _twe_wl_disp_source { struct wl_event_queue *ev_queue; struct wayland_tbm_client *wl_tbm_client; struct tizen_surface_shm *tss; /* used for surface buffer_flush */ + struct wp_presentation *presentation; struct { int min_buffer; int max_buffer; @@ -125,6 +127,12 @@ struct _twe_wl_surf_source { int render_sync_timestamp; unsigned int render_sync_fence_number; + tbm_fd presentation_sync_timeline; + int presentation_sync_timestamp; + int presentation_sync_ts_backup; + int presentation_sync_req_cnt; + GMutex pst_mutex; + GMutex surf_mutex; GMutex free_queue_mutex; @@ -788,6 +796,13 @@ __cb_wl_resistry_global_callback(void *data, struct wl_registry *wl_registry, &wayland_vulkan_interface, version); } + + if (!strcmp(interface, wp_presentation_interface.name)) { + disp_source->presentation = + wl_registry_bind(wl_registry, + name, &wp_presentation_interface, 1); + TPL_DEBUG("bind wp_presentation_interface"); + } } void @@ -867,6 +882,12 @@ _twe_display_wayland_init(twe_wl_disp_source *disp_source) TPL_LOG_T(BACKEND, "wl_vk_client(%p) init.", disp_source->wl_vk_client); } + if (disp_source->presentation) { + wl_proxy_set_queue((struct wl_proxy *)disp_source->presentation, + disp_source->ev_queue); + TPL_LOG_T(BACKEND, "wp_presentation(%p) init.", disp_source->presentation); + } + fini: if (display_wrapper) wl_proxy_wrapper_destroy(display_wrapper); @@ -1261,6 +1282,44 @@ __cb_create_render_sync_fd(struct wl_egl_window *wl_egl_window, void *private) return -1; } +static int +__cb_create_presentation_sync_fd(struct wl_egl_window *wl_egl_window, void *private) +{ + TPL_ASSERT(private); + TPL_ASSERT(wl_egl_window); + + struct tizen_private *tizen_private = (struct tizen_private *)private; + twe_wl_surf_source *surf_source = NULL; + + tbm_fd presentation_sync_fd = -1; + + surf_source = (twe_wl_surf_source *)tizen_private->data; + if (!surf_source) { + TPL_ERR("Invalid parameter. twe_surface(%p)", surf_source); + return -1; + } + + if (surf_source->presentation_sync_timeline != -1) { + g_mutex_lock(&surf_source->pst_mutex); + + presentation_sync_fd = tbm_sync_fence_create(surf_source->presentation_sync_timeline, + NULL, + surf_source->presentation_sync_timestamp++); + TPL_DEBUG("[PRESENTATION_SYNC] surf_source(%p) timeline(%d) timestamp(%d) sync_fence(%d)", + surf_source, surf_source->presentation_sync_timeline, surf_source->presentation_sync_timestamp, + presentation_sync_fd); + + TRACE_ASYNC_BEGIN(surf_source->presentation_sync_timestamp, "[PRESENTATION]"); + + surf_source->presentation_sync_req_cnt++; + + g_mutex_unlock(&surf_source->pst_mutex); + return presentation_sync_fd; + } + + return -1; +} + static void __cb_tss_flusher_flush_callback(void *data, struct tizen_surface_shm_flusher *tss_flusher) @@ -1901,6 +1960,105 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, } static void +__cb_presentation_feedback_sync_output(void *data, + struct wp_presentation_feedback *presentation_feedback, + struct wl_output *output) +{ + TPL_IGNORE(data); + TPL_IGNORE(presentation_feedback); + TPL_IGNORE(output); +} + +static void +__cb_presentation_feedback_presented(void *data, + struct wp_presentation_feedback *presentation_feedback, + uint32_t tv_sec_hi, + uint32_t tv_sec_lo, + uint32_t tv_nsec, + uint32_t refresh_nsec, + uint32_t seq_hi, + uint32_t seq_lo, + uint32_t flags) +{ + TPL_IGNORE(tv_sec_hi); + TPL_IGNORE(tv_sec_lo); + TPL_IGNORE(tv_nsec); + TPL_IGNORE(refresh_nsec); + TPL_IGNORE(seq_hi); + TPL_IGNORE(seq_lo); + TPL_IGNORE(flags); + + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; + + g_mutex_lock(&surf_source->pst_mutex); + + TPL_DEBUG("[FEEDBACK][PRESENTED] surf_source(%p) wl_surface(%p)", + surf_source, surf_source->surf); + + if (surf_source->presentation_sync_timeline != -1 && + surf_source->presentation_sync_req_cnt > 0) { + + surf_source->presentation_sync_ts_backup++; + surf_source->presentation_sync_req_cnt--; + + TRACE_ASYNC_END(surf_source->presentation_sync_ts_backup, "[PRESENTATION]"); + + TPL_DEBUG("[PRESENTATION][INC] surf_source(%p) timeline(%d) timestamp(%d)", + surf_source, surf_source->presentation_sync_timeline, + surf_source->presentation_sync_ts_backup); + if (!tbm_sync_timeline_inc(surf_source->presentation_sync_timeline, 1)) { + TPL_ERR("Failed to increase timeline(%d)", + surf_source->presentation_sync_timeline); + } + } + + if (presentation_feedback) + wp_presentation_feedback_destroy(presentation_feedback); + + g_mutex_unlock(&surf_source->pst_mutex); +} + +static void +__cb_presentation_feedback_discarded(void *data, + struct wp_presentation_feedback *presentation_feedback) +{ + twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data; + + g_mutex_lock(&surf_source->pst_mutex); + + TPL_DEBUG("[FEEDBACK][DISCARDED] surf_source(%p) wl_surface(%p)", + surf_source, surf_source->surf); + + if (surf_source->presentation_sync_timeline != -1 && + surf_source->presentation_sync_req_cnt > 0) { + + surf_source->presentation_sync_ts_backup++; + surf_source->presentation_sync_req_cnt--; + + TRACE_ASYNC_END(surf_source->presentation_sync_ts_backup, "[PRESENTATION]"); + + TPL_DEBUG("[PRESENTATION][INC] surf_source(%p) timeline(%d) timestamp(%d)", + surf_source, surf_source->presentation_sync_timeline, + surf_source->presentation_sync_ts_backup); + if (!tbm_sync_timeline_inc(surf_source->presentation_sync_timeline, 1)) { + TPL_ERR("Failed to increase timeline(%d)", + surf_source->presentation_sync_timeline); + } + } + + if (presentation_feedback) + wp_presentation_feedback_destroy(presentation_feedback); + + g_mutex_unlock(&surf_source->pst_mutex); +} + +static const struct wp_presentation_feedback_listener feedback_listener = { + __cb_presentation_feedback_sync_output, /* sync_output feedback -*/ + __cb_presentation_feedback_presented, + __cb_presentation_feedback_discarded +}; + +static void _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, tbm_surface_h tbm_surface) { @@ -1909,6 +2067,7 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, struct wl_surface *wl_surface = surf_source->surf; struct wl_egl_window *wl_egl_window = surf_source->wl_egl_window; uint32_t version; + struct wp_presentation_feedback *p_feedback; tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, (void **)&buf_info); @@ -1920,6 +2079,15 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, version = wl_proxy_get_version((struct wl_proxy *)wl_surface); + g_mutex_lock(&surf_source->pst_mutex); + if (disp_source->presentation && + surf_source->presentation_sync_req_cnt > 0) { + p_feedback = wp_presentation_feedback(disp_source->presentation, + wl_surface); + wp_presentation_feedback_add_listener(p_feedback, &feedback_listener, surf_source); + } + g_mutex_unlock(&surf_source->pst_mutex); + if (buf_info->w_rotated == TPL_TRUE) { wayland_tbm_client_set_buffer_transform( disp_source->wl_tbm_client, @@ -2558,6 +2726,11 @@ twe_surface_add(twe_thread* thread, source->render_sync_timestamp = 0; source->render_sync_fence_number = 0; + source->presentation_sync_timeline = tbm_sync_timeline_create(); + source->presentation_sync_timestamp = 0; + source->presentation_sync_ts_backup = 0; + source->presentation_sync_req_cnt = 0; + if (!disp_source->is_vulkan_dpy) { struct wl_egl_window *wl_egl_window = (struct wl_egl_window *)native_handle; @@ -2578,6 +2751,7 @@ twe_surface_add(twe_thread* thread, private->set_window_serial_callback = (void *) __cb_set_window_serial_callback; private->create_render_sync_fd = (void *)__cb_create_render_sync_fd; + private->create_presentation_sync_fd = (void *)__cb_create_presentation_sync_fd; source->latest_transform = private->transform; @@ -2607,6 +2781,7 @@ twe_surface_add(twe_thread* thread, g_source_attach(&source->gsource, g_main_loop_get_context(ctx->twe_loop)); g_mutex_init(&source->surf_mutex); + g_mutex_init(&source->pst_mutex); g_mutex_init(&source->free_queue_mutex); g_cond_init(&source->free_queue_cond); -- 2.7.4 From d6375a343b0cc5bf7945aa6bdcc456b4aec2bbae Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 14 Nov 2019 20:33:32 +0900 Subject: [PATCH 12/16] wayland-egl-tizen: Added new API to merge sync fds. New API /** * Get a new fence fd with fence1 and fence2 merged * * It returns a new fence fd waiting for both fences to be signaled. * If user succeed in obtaining a new merged fence using this API, * the two fence fds passed must be closed by the user. * * Multiple calls to this API allow to merge multiple fences. * * The two fence fds caller want to merge should be closed * if caller is not going to use them after * the new merged fd is created. * * @param egl_window handle to wl_egl_window * @param sync_fd1 first fd to merge with second fd * @param sync_fd2 seconde fd to merge with first fd * @return merged fd on success, -1 on failure. */ int wl_egl_window_tizen_merge_sync_fds(struct wl_egl_window *egl_window, int sync_fd1, int sync_fd2); Change-Id: I29ac248c836392b9e6acb141a30bb70dc5e9731f Signed-off-by: Joonbum Ko --- src/wayland-egl-tizen/wayland-egl-tizen-priv.h | 2 ++ src/wayland-egl-tizen/wayland-egl-tizen.c | 23 +++++++++++++++++++++++ src/wayland-egl-tizen/wayland-egl-tizen.h | 22 ++++++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h index 6fd31ea..9a6b812 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h @@ -24,6 +24,7 @@ struct tizen_private { void (*set_window_serial_callback)(struct wl_egl_window *, void *, unsigned int); int (*create_render_sync_fd)(struct wl_egl_window *, void *); int (*create_presentation_sync_fd)(struct wl_egl_window *, void *); + int (*merge_sync_fds)(void *, int, int); }; static struct tizen_private* tizen_private_create() @@ -44,6 +45,7 @@ static struct tizen_private* tizen_private_create() private->set_frontbuffer_callback = NULL; private->create_render_sync_fd = NULL; private->create_presentation_sync_fd = NULL; + private->merge_sync_fds = NULL; } return private; diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.c b/src/wayland-egl-tizen/wayland-egl-tizen.c index 831951c..70e66a3 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.c +++ b/src/wayland-egl-tizen/wayland-egl-tizen.c @@ -295,3 +295,26 @@ wl_egl_window_tizen_create_presentation_sync_fd(struct wl_egl_window *egl_window return -1; } + +int +wl_egl_window_tizen_merge_sync_fds(struct wl_egl_window *egl_window, + int sync_fd1, int sync_fd2) +{ + struct tizen_private *private = NULL; + + if (egl_window == NULL) { + WL_EGL_ERR("egl_window is NULL"); + return -1; + } + + private = egl_window->driver_private; + if (private == NULL) { + WL_EGL_ERR("wl_egl_window(%p) dirver_private is NULL", egl_window); + return -1; + } + + if (private->merge_sync_fds) + return private->merge_sync_fds(egl_window->driver_private, sync_fd1, sync_fd2); + + return -1; +} \ No newline at end of file diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.h b/src/wayland-egl-tizen/wayland-egl-tizen.h index 00b8b75..041488c 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen.h @@ -118,6 +118,28 @@ wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window); int wl_egl_window_tizen_create_presentation_sync_fd(struct wl_egl_window *egl_window); +/** + * Get a new fence fd with fence1 and fence2 merged + * + * It returns a new fence fd waiting for both fences to be signaled. + * If user succeed in obtaining a new merged fence using this API, + * the two fence fds passed must be closed by the user. + * + * Multiple calls to this API allow to merge multiple fences. + * + * The two fence fds caller want to merge should be closed + * if caller is not going to use them after + * the new merged fd is created. + * + * @param egl_window handle to wl_egl_window + * @param sync_fd1 first fd to merge with second fd + * @param sync_fd2 seconde fd to merge with first fd + * @return merged fd on success, -1 on failure. + */ +int +wl_egl_window_tizen_merge_sync_fds(struct wl_egl_window *egl_window, + int sync_fd1, int sync_fd2); + #ifdef __cplusplus } #endif -- 2.7.4 From 8645365b9a9d54f1e2f9fbf7fde5e69e5ad9ae49 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 15 Nov 2019 15:14:47 +0900 Subject: [PATCH 13/16] tpl_wayland_egl_thread: Implemented merge sync fence. Change-Id: Ic5697fd0dbade852d9340b2c490d6247a12f46f1 Signed-off-by: Joonbum Ko --- src/tpl_wayland_egl_thread.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index f7fb447..6368d91 100755 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -1320,6 +1320,35 @@ __cb_create_presentation_sync_fd(struct wl_egl_window *wl_egl_window, void *priv return -1; } +static int +__cb_merge_sync_fds(void *private, int sync_fd1, int sync_fd2) +{ + TPL_ASSERT(private); + + struct tizen_private *tizen_private = (struct tizen_private *)private; + twe_wl_surf_source *surf_source = NULL; + tbm_fd merged_fd; + + surf_source = (twe_wl_surf_source *)tizen_private->data; + if (!surf_source) { + TPL_ERR("Invalid parameter. twe_surface(%p)", surf_source); + return -1; + } + + if (surf_source->render_sync_timeline == -1 && + surf_source->presentation_sync_timeline == -1) { + TPL_ERR("There is no timeline for any sync fd in surf_source(%p)", surf_source); + return -1; + } + + merged_fd = tbm_sync_fence_merge(NULL, sync_fd1, sync_fd2); + + TPL_DEBUG("[FENCE_MERGE] surf_source(%p) fence1(%d) + fence2(%d) = merged(%d)", + surf_source, sync_fd1, sync_fd2, merged_fd); + + return merged_fd; +} + static void __cb_tss_flusher_flush_callback(void *data, struct tizen_surface_shm_flusher *tss_flusher) @@ -2752,6 +2781,7 @@ twe_surface_add(twe_thread* thread, __cb_set_window_serial_callback; private->create_render_sync_fd = (void *)__cb_create_render_sync_fd; private->create_presentation_sync_fd = (void *)__cb_create_presentation_sync_fd; + private->merge_sync_fds = (void *)__cb_merge_sync_fds; source->latest_transform = private->transform; -- 2.7.4 From 9f7b27bb3c91b6a0c02dcc8ca1310780bcc5e9c2 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 12 Mar 2020 14:04:16 +0900 Subject: [PATCH 14/16] wayland-egl-tizen: Changed API name render_sync_fd to commit_sync_fd. - If the user wants to know the render done using EGLSyncKHR, tpl_surface_dequeue_buffer, tpl_surface_enqueue_buffer and wl_surface_commit occur at similar moments. Therefore, it only tells when wl_surface_commit is done, but does not guarantee render done. - If EGLSyncKHR or dma_buf implicit fence is not used, render done can be guaranteed. Change-Id: I43d7bdd10a33d0b559ecd1d219261bbb5415b574 Signed-off-by: Joonbum Ko --- src/tpl_wayland_egl_thread.c | 61 +++++++++++++------------- src/wayland-egl-tizen/wayland-egl-tizen-priv.h | 4 +- src/wayland-egl-tizen/wayland-egl-tizen.c | 6 +-- src/wayland-egl-tizen/wayland-egl-tizen.h | 19 ++++---- 4 files changed, 45 insertions(+), 45 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 6368d91..0176383 100755 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -123,9 +123,9 @@ struct _twe_wl_surf_source { twe_wl_disp_source *disp_source; twe_del_source *surf_del_source; - tbm_fd render_sync_timeline; - int render_sync_timestamp; - unsigned int render_sync_fence_number; + tbm_fd commit_sync_timeline; + int commit_sync_timestamp; + unsigned int commit_sync_fence_number; tbm_fd presentation_sync_timeline; int presentation_sync_timestamp; @@ -1248,7 +1248,7 @@ __cb_set_window_serial_callback(struct wl_egl_window *wl_egl_window, } static int -__cb_create_render_sync_fd(struct wl_egl_window *wl_egl_window, void *private) +__cb_create_commit_sync_fd(struct wl_egl_window *wl_egl_window, void *private) { TPL_ASSERT(private); TPL_ASSERT(wl_egl_window); @@ -1256,7 +1256,7 @@ __cb_create_render_sync_fd(struct wl_egl_window *wl_egl_window, void *private) struct tizen_private *tizen_private = (struct tizen_private *)private; twe_wl_surf_source *surf_source = NULL; - tbm_fd render_sync_fd = -1; + tbm_fd commit_sync_fd = -1; surf_source = (twe_wl_surf_source *)tizen_private->data; if (!surf_source) { @@ -1264,19 +1264,19 @@ __cb_create_render_sync_fd(struct wl_egl_window *wl_egl_window, void *private) return -1; } - if (surf_source->render_sync_timeline != -1) { + if (surf_source->commit_sync_timeline != -1) { char name[32]; - snprintf(name, 32, "%u", surf_source->render_sync_fence_number++); - render_sync_fd = tbm_sync_fence_create(surf_source->render_sync_timeline, + snprintf(name, 32, "%u", surf_source->commit_sync_fence_number++); + commit_sync_fd = tbm_sync_fence_create(surf_source->commit_sync_timeline, name, - surf_source->render_sync_timestamp + 1); - TPL_DEBUG("[RENDER_SYNC] surf_source(%p) timeline(%d) timestamp(%d) name(%s) sync_fence(%d)", - surf_source, surf_source->render_sync_timeline, surf_source->render_sync_timestamp, - name, render_sync_fd); + surf_source->commit_sync_timestamp + 1); + TPL_DEBUG("[COMMIT_SYNC] surf_source(%p) timeline(%d) timestamp(%d) name(%s) sync_fence(%d)", + surf_source, surf_source->commit_sync_timeline, surf_source->commit_sync_timestamp, + name, commit_sync_fd); - TRACE_ASYNC_BEGIN(surf_source->render_sync_timestamp + 1, "[SYNC_FENCE]"); + TRACE_ASYNC_BEGIN(surf_source->commit_sync_timestamp + 1, "[SYNC_FENCE]"); - return render_sync_fd; + return commit_sync_fd; } return -1; @@ -1335,7 +1335,7 @@ __cb_merge_sync_fds(void *private, int sync_fd1, int sync_fd2) return -1; } - if (surf_source->render_sync_timeline == -1 && + if (surf_source->commit_sync_timeline == -1 && surf_source->presentation_sync_timeline == -1) { TPL_ERR("There is no timeline for any sync fd in surf_source(%p)", surf_source); return -1; @@ -1682,18 +1682,6 @@ _twe_surface_trace_enqueue_buffer(twe_wl_surf_source *surf_source, return; } - if (surf_source->render_sync_timeline != -1) { - - surf_source->render_sync_timestamp++; - TRACE_ASYNC_END(surf_source->render_sync_timestamp, "[SYNC_FENCE]"); - - TPL_DEBUG("[RENDER_SYNC][INC] surf_source(%p) timeline(%d) timestamp(%d)", - surf_source, surf_source->render_sync_timeline, surf_source->render_sync_timestamp); - if (!tbm_sync_timeline_inc(surf_source->render_sync_timeline, 1)) { - TPL_ERR("Failed to increase timeline(%d)", surf_source->render_sync_timeline); - } - } - if (surf_source->in_use_buffers) { g_mutex_lock(&surf_source->surf_mutex); /* Stop tracking of this canceled tbm_surface */ @@ -2193,6 +2181,17 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source, if (surf_source->committed_buffers) { __tpl_list_push_back(surf_source->committed_buffers, tbm_surface); } + + if (surf_source->commit_sync_timeline != -1) { + surf_source->commit_sync_timestamp++; + TRACE_ASYNC_END(surf_source->commit_sync_timestamp, "[SYNC_FENCE]"); + + TPL_DEBUG("[COMMIT_SYNC][INC] surf_source(%p) timeline(%d) timestamp(%d)", + surf_source, surf_source->commit_sync_timeline, surf_source->commit_sync_timestamp); + if (!tbm_sync_timeline_inc(surf_source->commit_sync_timeline, 1)) { + TPL_ERR("Failed to increase timeline(%d)", surf_source->commit_sync_timeline); + } + } } /* The following function _twe_thread_wl_surface_acquire_and_commit can be @@ -2751,9 +2750,9 @@ twe_surface_add(twe_thread* thread, source->post_interval = 1; - source->render_sync_timeline = tbm_sync_timeline_create(); - source->render_sync_timestamp = 0; - source->render_sync_fence_number = 0; + source->commit_sync_timeline = tbm_sync_timeline_create(); + source->commit_sync_timestamp = 0; + source->commit_sync_fence_number = 0; source->presentation_sync_timeline = tbm_sync_timeline_create(); source->presentation_sync_timestamp = 0; @@ -2779,7 +2778,7 @@ twe_surface_add(twe_thread* thread, __cb_get_rotation_capability; private->set_window_serial_callback = (void *) __cb_set_window_serial_callback; - private->create_render_sync_fd = (void *)__cb_create_render_sync_fd; + private->create_commit_sync_fd = (void *)__cb_create_commit_sync_fd; private->create_presentation_sync_fd = (void *)__cb_create_presentation_sync_fd; private->merge_sync_fds = (void *)__cb_merge_sync_fds; diff --git a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h index 9a6b812..caeb5b0 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen-priv.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen-priv.h @@ -22,7 +22,7 @@ struct tizen_private { int (*get_rotation_capability)(struct wl_egl_window *, void *); void (*set_frontbuffer_callback)(struct wl_egl_window *, void *, int); void (*set_window_serial_callback)(struct wl_egl_window *, void *, unsigned int); - int (*create_render_sync_fd)(struct wl_egl_window *, void *); + int (*create_commit_sync_fd)(struct wl_egl_window *, void *); int (*create_presentation_sync_fd)(struct wl_egl_window *, void *); int (*merge_sync_fds)(void *, int, int); }; @@ -43,7 +43,7 @@ static struct tizen_private* tizen_private_create() private->get_rotation_capability = NULL; private->set_window_serial_callback = NULL; private->set_frontbuffer_callback = NULL; - private->create_render_sync_fd = NULL; + private->create_commit_sync_fd = NULL; private->create_presentation_sync_fd = NULL; private->merge_sync_fds = NULL; } diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.c b/src/wayland-egl-tizen/wayland-egl-tizen.c index 70e66a3..b4e679c 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.c +++ b/src/wayland-egl-tizen/wayland-egl-tizen.c @@ -253,7 +253,7 @@ wl_egl_window_tizen_set_window_serial(struct wl_egl_window *egl_window, } int -wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window) +wl_egl_window_tizen_create_commit_sync_fd(struct wl_egl_window *egl_window) { struct tizen_private *private = NULL; @@ -268,8 +268,8 @@ wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window) return -1; } - if (private->create_render_sync_fd) - return private->create_render_sync_fd(egl_window, egl_window->driver_private); + if (private->create_commit_sync_fd) + return private->create_commit_sync_fd(egl_window, egl_window->driver_private); return -1; } diff --git a/src/wayland-egl-tizen/wayland-egl-tizen.h b/src/wayland-egl-tizen/wayland-egl-tizen.h index 041488c..921b193 100644 --- a/src/wayland-egl-tizen/wayland-egl-tizen.h +++ b/src/wayland-egl-tizen/wayland-egl-tizen.h @@ -75,20 +75,21 @@ wl_egl_window_tizen_set_window_serial(struct wl_egl_window *egl_window, /* temporary APIs for testing sync feature */ /** - * Create a sync fence fd that can tell render done. + * Create a sync fence fd that can tell wl_surface_commit done. * * If eglSwapBuffers works async, it returns fd which tells - * when the render job is finished. + * when wl_surface_commit called. * This fd can wait asynchronously via poll or select. * * Important * * This requires the following premise: - * - After ddk calls libplpl-egl's tpl_surface_dequeue_buffer to get the buffer, - * and until it calls tpl_surface_enqueue_buffer, - * it is called the gpu rendering job interval. - * - Therefore, when using the dma_buf implicit fence, - * there is no guarantee that the rendering job is finished - * with the fence obtained through this API. + * - If the user wants to know the render done using EGLSyncKHR, + * tpl_surface_dequeue_buffer, tpl_surface_enqueue_buffer and + * wl_surface_commit occur at similar moments. + * Therefore, it only tells when wl_surface_commit is done, + * but does not guarantee render done. + * - If EGLSyncKHR or dma_buf implicit fence is not used, + * render done can be guaranteed. * * The fence_fd obtained through this function is one-time available, * can not be reused, so caller must close it when finished using it. @@ -97,7 +98,7 @@ wl_egl_window_tizen_set_window_serial(struct wl_egl_window *egl_window, * @return sync fd on success, -1 on failure. */ int -wl_egl_window_tizen_create_render_sync_fd(struct wl_egl_window *egl_window); +wl_egl_window_tizen_create_commit_sync_fd(struct wl_egl_window *egl_window); /** * Create a sync fence fd that can tell presentation done. -- 2.7.4 From 350c6164114b59b35c4d95c24188f922b963d8e5 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Tue, 17 Mar 2020 17:00:21 +0900 Subject: [PATCH 15/16] Package version up to 1.7.2 Change-Id: Ic9008c2a0752c62bd0c9a3c50033fb16971e0c20 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 b49148a..d4eccf4 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 7 -%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 93c6381fdaa12494c3f51e689f9f6a03e1bf6ee4 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Fri, 20 Mar 2020 10:45:38 +0900 Subject: [PATCH 16/16] Deleted the unused codes related with worker_thread. - The worker_thread that was created for vulkan has been replaced with twe_thread, so it is obsolete and has been deprecated for a long time. Change-Id: I0d1774b772c1c9b7820806fd5029952848dc2eb0 Signed-off-by: Joonbum Ko --- src/Makefile.am | 1 - src/tpl_wayland_vk_wsi.c | 252 +---------------------- src/tpl_worker_thread.c | 508 ----------------------------------------------- src/tpl_worker_thread.h | 30 --- 4 files changed, 1 insertion(+), 790 deletions(-) delete mode 100644 src/tpl_worker_thread.c delete mode 100644 src/tpl_worker_thread.h diff --git a/src/Makefile.am b/src/Makefile.am index d885262..d7823b7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,7 +29,6 @@ libtpl_egl_la_SOURCES += tpl_wayland_egl.c \ tpl_wayland_egl_thread.c \ tpl_wayland_vk_wsi.c \ tpl_wl_vk_thread.c \ - tpl_worker_thread.c \ wayland-vulkan/wayland-vulkan-protocol.c endif diff --git a/src/tpl_wayland_vk_wsi.c b/src/tpl_wayland_vk_wsi.c index f2e2adc..3f91540 100644 --- a/src/tpl_wayland_vk_wsi.c +++ b/src/tpl_wayland_vk_wsi.c @@ -15,17 +15,6 @@ #define CLIENT_QUEUE_SIZE 3 -#define USE_WORKER_THREAD -#ifndef USE_WORKER_THREAD -#define USE_WORKER_THREAD 0 -#else -#include "tpl_worker_thread.h" -#include -#include -#undef USE_WORKER_THREAD -#define USE_WORKER_THREAD 1 -#endif - typedef struct _tpl_wayland_vk_wsi_display tpl_wayland_vk_wsi_display_t; typedef struct _tpl_wayland_vk_wsi_surface tpl_wayland_vk_wsi_surface_t; typedef struct _tpl_wayland_vk_wsi_buffer tpl_wayland_vk_wsi_buffer_t; @@ -43,23 +32,6 @@ struct _tpl_wayland_vk_wsi_display { struct _tpl_wayland_vk_wsi_surface { tbm_surface_queue_h tbm_queue; int buffer_count; - -#if USE_WORKER_THREAD == 1 - /* - * TODO: it can move to libtbm - * libtbm already has free queue's pthread_cond and pthread_mutex - */ - pthread_mutex_t free_queue_mutex; - pthread_cond_t free_queue_cond; - - /* tbm_surface list */ - tpl_list_t vblank_list; - pthread_mutex_t vblank_list_mutex; - - tpl_bool_t vblank_done; - - tpl_worker_surface_t worker_surface; -#endif int present_mode; }; @@ -68,10 +40,6 @@ struct _tpl_wayland_vk_wsi_buffer { struct wl_proxy *wl_proxy; tbm_fd sync_timeline; unsigned int sync_timestamp; - -#if USE_WORKER_THREAD == 1 - tbm_fd wait_sync; -#endif }; static const struct wl_registry_listener registry_listener; @@ -366,10 +334,6 @@ __tpl_wayland_vk_wsi_display_query_window_supported_present_modes( if (modes) { *modes = TPL_DISPLAY_PRESENT_MODE_MAILBOX | TPL_DISPLAY_PRESENT_MODE_IMMEDIATE | wayland_vk_wsi_display->surface_capabilities.present_modes; -#if USE_WORKER_THREAD == 1 - if (__tpl_worker_support_vblank() == TPL_TRUE) - *modes |= TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED; -#endif } return TPL_ERROR_NONE; @@ -455,14 +419,7 @@ __tpl_wayland_vk_wsi_surface_commit_buffer(tpl_surface_t *surface, wl_display_flush(surface->display->native_handle); wayland_vk_wsi_buffer->sync_timestamp++; -#if USE_WORKER_THREAD == 1 - pthread_mutex_lock(&wayland_vk_wsi_surface->free_queue_mutex); -#endif tbm_surface_queue_release(wayland_vk_wsi_surface->tbm_queue, tbm_surface); -#if USE_WORKER_THREAD == 1 - pthread_mutex_unlock(&wayland_vk_wsi_surface->free_queue_mutex); - pthread_cond_signal(&wayland_vk_wsi_surface->free_queue_cond); -#endif } static tpl_result_t @@ -495,9 +452,6 @@ __tpl_wayland_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, tbm_surface_internal_unref(tbm_surface); -#if USE_WORKER_THREAD == 1 - wayland_vk_wsi_buffer->wait_sync = sync_fence; -#endif tsq_err = tbm_surface_queue_enqueue(wayland_vk_wsi_surface->tbm_queue, tbm_surface); if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { @@ -505,7 +459,6 @@ __tpl_wayland_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, return TPL_ERROR_INVALID_OPERATION; } -#if USE_WORKER_THREAD == 0 if (sync_fence != -1) { /* non worker thread mode */ /* TODO: set max wait time */ @@ -526,10 +479,6 @@ __tpl_wayland_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); -#else - __tpl_worker_new_buffer_notify(&wayland_vk_wsi_surface->worker_surface); - -#endif /* * tbm_surface insert to free queue. @@ -574,7 +523,6 @@ __tpl_wayland_vk_wsi_surface_dequeue_buffer(tpl_surface_t *surface, if (sync_fence) *sync_fence = -1; -#if USE_WORKER_THREAD == 0 TPL_OBJECT_UNLOCK(surface); while (tbm_surface_queue_can_dequeue( wayland_vk_wsi_surface->tbm_queue, 0) == 0) { @@ -586,46 +534,10 @@ __tpl_wayland_vk_wsi_surface_dequeue_buffer(tpl_surface_t *surface, } } TPL_OBJECT_LOCK(surface); -#else - /* - * TODO: it can move to libtbm - * libtbm already has free queue's pthread_cond and pthread_mutex - */ - struct timespec abs_time; - if (timeout_ns != UINT64_MAX) { - clock_gettime(CLOCK_REALTIME, &abs_time); - abs_time.tv_sec += (timeout_ns / 1000000000L); - abs_time.tv_nsec += (timeout_ns % 1000000000L); - if (abs_time.tv_nsec >= 1000000000L) { - abs_time.tv_sec += (abs_time.tv_nsec / 1000000000L); - abs_time.tv_nsec = (abs_time.tv_nsec % 1000000000L); - } - } - pthread_mutex_lock(&wayland_vk_wsi_surface->free_queue_mutex); - while (tbm_surface_queue_can_dequeue(wayland_vk_wsi_surface->tbm_queue, - 0) == 0) { - if (timeout_ns != UINT64_MAX) { - int ret; - ret = pthread_cond_timedwait(&wayland_vk_wsi_surface->free_queue_cond, - &wayland_vk_wsi_surface->free_queue_mutex, - &abs_time); - if (ret == ETIMEDOUT) { - /* timeout */ - pthread_mutex_unlock(&wayland_vk_wsi_surface->free_queue_mutex); - return NULL; - } - } else { - pthread_cond_wait(&wayland_vk_wsi_surface->free_queue_cond, - &wayland_vk_wsi_surface->free_queue_mutex); - } - } -#endif tsq_err = tbm_surface_queue_dequeue(wayland_vk_wsi_surface->tbm_queue, &tbm_surface); -#if USE_WORKER_THREAD == 1 - pthread_mutex_unlock(&wayland_vk_wsi_surface->free_queue_mutex); -#endif + if (!tbm_surface) { TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d", tsq_err); @@ -774,120 +686,6 @@ release_buffer_fail: return ret; } -#if USE_WORKER_THREAD == 1 -static void -__tpl_wayland_vk_wsi_process_draw_done(tpl_surface_t *surface, - tbm_surface_h tbm_surface, - tpl_result_t result) -{ - tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; - tpl_wayland_vk_wsi_buffer_t *wayland_vk_wsi_buffer = NULL; - tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; - - TPL_ASSERT(surface); - TPL_ASSERT(tbm_surface); - TPL_ASSERT(tbm_surface_internal_is_valid(tbm_surface)); - - wayland_vk_wsi_surface = - (tpl_wayland_vk_wsi_surface_t *)surface->backend.data; - wayland_vk_wsi_buffer = - __tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(tbm_surface); - wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *) - surface->display->backend.data; - - TPL_ASSERT(wayland_vk_wsi_surface); - TPL_ASSERT(wayland_vk_wsi_buffer); - TPL_ASSERT(wayland_vk_wsi_display); - - close(wayland_vk_wsi_buffer->wait_sync); - wayland_vk_wsi_buffer->wait_sync = -1; - - /* if server supported current supported mode then just send */ - - if (wayland_vk_wsi_surface->present_mode & - wayland_vk_wsi_display->surface_capabilities.present_modes) { - __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); - return; - } - - if (wayland_vk_wsi_surface->present_mode == TPL_DISPLAY_PRESENT_MODE_FIFO) { - pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); - /* unref in tpl list remove callback - (__tpl_wayland_vk_wsi_buffer_remove_from_vblank_list) */ - tbm_surface_internal_ref(tbm_surface); - __tpl_list_push_back(&wayland_vk_wsi_surface->vblank_list, tbm_surface); - pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); - } else if (wayland_vk_wsi_surface->present_mode == TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED && - wayland_vk_wsi_surface->vblank_done == TPL_FALSE) { - /* if can't process previous vblank event, send buffer immediately */ - pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); - /* unref in tpl list remove callback - (__tpl_wayland_vk_wsi_buffer_remove_from_vblank_list) */ - tbm_surface_internal_ref(tbm_surface); - __tpl_list_push_back(&wayland_vk_wsi_surface->vblank_list, tbm_surface); - wayland_vk_wsi_surface->vblank_done = TPL_TRUE; - pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); - } else { - __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); - } -} - -static int -__tpl_wayland_vk_wsi_draw_wait_fd_get(tpl_surface_t *surface, - tbm_surface_h tbm_surface) -{ - tpl_wayland_vk_wsi_buffer_t *wayland_vk_wsi_buffer = NULL; - - /*TPL_ASSERT(surface);*/ - TPL_ASSERT(tbm_surface); - - wayland_vk_wsi_buffer = - __tpl_wayland_vk_wsi_get_wayland_buffer_from_tbm_surface(tbm_surface); - - TPL_ASSERT(wayland_vk_wsi_buffer); - - return wayland_vk_wsi_buffer->wait_sync; -} - -static void -__tpl_wayland_vk_wsi_buffer_remove_from_vblank_list(void *data) -{ - tbm_surface_h tbm_surface = data; - tbm_surface_internal_unref(tbm_surface); -} - -static void -__tpl_wayland_vk_wsi_vblank(tpl_surface_t *surface, unsigned int sequence, - unsigned int tv_sec, unsigned int tv_usec) -{ - tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface; - tbm_surface_h tbm_surface; - - TPL_ASSERT(surface); - - wayland_vk_wsi_surface = - (tpl_wayland_vk_wsi_surface_t *) surface->backend.data; - - TPL_ASSERT(wayland_vk_wsi_surface); - - if ((wayland_vk_wsi_surface->present_mode & - (TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED)) == 0) - return; - - pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); - tbm_surface = __tpl_list_pop_front(&wayland_vk_wsi_surface->vblank_list, - __tpl_wayland_vk_wsi_buffer_remove_from_vblank_list); - pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); - - if (tbm_surface_internal_is_valid(tbm_surface)) { - __tpl_wayland_vk_wsi_surface_commit_buffer(surface, tbm_surface); - wayland_vk_wsi_surface->vblank_done = TPL_TRUE; - } else { - wayland_vk_wsi_surface->vblank_done = TPL_FALSE; - } -} -#endif - static tpl_result_t __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, tbm_format format, int width, @@ -919,16 +717,6 @@ __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, if ((present_mode & wayland_vk_wsi_display->surface_capabilities.present_modes) == 0) { /* server not supported current mode check client mode */ switch (present_mode) { -#if USE_WORKER_THREAD == 1 - case TPL_DISPLAY_PRESENT_MODE_FIFO: - case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED: - if (__tpl_worker_support_vblank() == TPL_FALSE) { - TPL_ERR("Unsupported present mode: %d, worker not support vblank", - present_mode); - return TPL_ERROR_INVALID_PARAMETER; - } - break; -#endif case TPL_DISPLAY_PRESENT_MODE_MAILBOX: case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE: break; @@ -956,28 +744,6 @@ __tpl_wayland_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, surface->width = width; surface->height = height; -#if USE_WORKER_THREAD == 1 - pthread_mutex_init(&wayland_vk_wsi_surface->free_queue_mutex, NULL); - pthread_cond_init(&wayland_vk_wsi_surface->free_queue_cond, NULL); - - wayland_vk_wsi_surface->worker_surface.surface = surface; - wayland_vk_wsi_surface->worker_surface.tbm_queue = - wayland_vk_wsi_surface->tbm_queue; - - wayland_vk_wsi_surface->worker_surface.draw_done = - __tpl_wayland_vk_wsi_process_draw_done; - wayland_vk_wsi_surface->worker_surface.draw_wait_fd_get = - __tpl_wayland_vk_wsi_draw_wait_fd_get; - if ((wayland_vk_wsi_surface->present_mode & - (TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED))) { - wayland_vk_wsi_surface->worker_surface.vblank = - __tpl_wayland_vk_wsi_vblank; - pthread_mutex_init(&wayland_vk_wsi_surface->vblank_list_mutex, NULL); - __tpl_list_init(&wayland_vk_wsi_surface->vblank_list); - } - - __tpl_worker_surface_list_insert(&wayland_vk_wsi_surface->worker_surface); -#endif return TPL_ERROR_NONE; } @@ -993,9 +759,6 @@ __tpl_wayland_vk_wsi_surface_destroy_swapchain(tpl_surface_t *surface) wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data; TPL_ASSERT(wayland_vk_wsi_surface); -#if USE_WORKER_THREAD == 1 - __tpl_worker_surface_list_remove(&wayland_vk_wsi_surface->worker_surface); -#endif if (surface->type == TPL_SURFACE_TYPE_WINDOW) { wl_display_flush(surface->display->native_handle); @@ -1005,19 +768,6 @@ __tpl_wayland_vk_wsi_surface_destroy_swapchain(tpl_surface_t *surface) wayland_vk_wsi_surface->tbm_queue = NULL; } -#if USE_WORKER_THREAD == 1 - if ((wayland_vk_wsi_surface->present_mode & - (TPL_DISPLAY_PRESENT_MODE_FIFO | TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED))) { - pthread_mutex_lock(&wayland_vk_wsi_surface->vblank_list_mutex); - __tpl_list_fini(&wayland_vk_wsi_surface->vblank_list, - __tpl_wayland_vk_wsi_buffer_remove_from_vblank_list); - pthread_mutex_unlock(&wayland_vk_wsi_surface->vblank_list_mutex); - pthread_mutex_destroy(&wayland_vk_wsi_surface->vblank_list_mutex); - } - - pthread_cond_destroy(&wayland_vk_wsi_surface->free_queue_cond); - pthread_mutex_destroy(&wayland_vk_wsi_surface->free_queue_mutex); -#endif return TPL_ERROR_NONE; } diff --git a/src/tpl_worker_thread.c b/src/tpl_worker_thread.c deleted file mode 100644 index feca15c..0000000 --- a/src/tpl_worker_thread.c +++ /dev/null @@ -1,508 +0,0 @@ -#include "tpl_worker_thread.h" -#include "tpl_internal.h" - -#include -/*#define __USE_GNU*/ -#include -#include -#include -#include - -#define TPL_ERR_ERRNO(f, x...) \ - do { int err = errno; char buf[256] = {0,}; \ - strerror_r(err, buf, 255); \ - TPL_ERR(f " | error: %d(%s)", ##x, err, buf); \ - } while (0); - -#define TPL_WARN_ERRNO(f, x...) \ - do { int err = errno; char buf[256] = {0,}; \ - strerror_r(err, buf, 255); \ - TPL_WARN(f " | error: %d(%s)", ##x, err, buf); \ - } while (0); - -static struct { - int running; - int epoll_fd; - int event_fd; - - pthread_t worker_id; - tpl_list_t surface_list; - pthread_mutex_t surface_mutex; - tpl_bool_t support_vblank; -} tpl_worker_thread; - -tpl_bool_t -__tpl_worker_support_vblank() -{ - return tpl_worker_thread.support_vblank; -} - -void -__tpl_worker_surface_list_insert(tpl_worker_surface_t *surface) -{ - TPL_ASSERT(surface->surface); - - if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { - TPL_ERR_ERRNO("surface list mutex lock failed"); - return; - } - - surface->draw_wait_buffer = NULL; - __tpl_list_push_back(&tpl_worker_thread.surface_list, surface); - - pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); -} - -void -__tpl_worker_surface_list_remove(tpl_worker_surface_t *surface) -{ - if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { - TPL_ERR_ERRNO("surface list mutex lock failed"); - return; - } - - __tpl_list_remove_data(&tpl_worker_thread.surface_list, surface, - TPL_FIRST, NULL); - - pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); -} - -static void -__tpl_worker_event_send() -{ - int len; - uint64_t dummy_event = 1; - - if (tpl_worker_thread.event_fd == -1) { - TPL_ERR("worker thread not working"); - return; - } - - len = write(tpl_worker_thread.event_fd, - &dummy_event, - sizeof(dummy_event)); - if (len < 0) - TPL_WARN_ERRNO("event fd(%d) write failed.", - tpl_worker_thread.event_fd); -} - -static void -__tpl_worker_prepare_draw_wait_buffer(int epoll_fd, - tpl_worker_surface_t *surface) -{ - if (surface->draw_wait_buffer) - return; - - if (surface->draw_wait_buffer_get) { - int wait_fd = -1; - tbm_surface_h tbm_surface; - - while ((tbm_surface = surface->draw_wait_buffer_get(surface->surface)) != NULL) { - if (surface->draw_wait_fd_get) - wait_fd = surface->draw_wait_fd_get(surface->surface, tbm_surface); - - if (wait_fd != -1) { - struct epoll_event wait_fence_event; - int epoll_err; - - wait_fence_event.events = EPOLLIN; - wait_fence_event.data.ptr = surface; - epoll_err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, - wait_fd, - &wait_fence_event); - if (epoll_err == 0) { - surface->draw_wait_buffer = tbm_surface; - return; - } - } /* else can't(or not need) wait fence in poll */ - - if (surface->draw_done) - surface->draw_done(surface->surface, tbm_surface, - TPL_ERROR_INVALID_OPERATION); - } - return; - } - - while (tbm_surface_queue_can_acquire(surface->tbm_queue, 0)) { - tbm_surface_h tbm_surface = NULL; - tbm_surface_queue_error_e tsq_err; - int wait_fd = -1; - - tsq_err = tbm_surface_queue_acquire(surface->tbm_queue, &tbm_surface); - if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE || tbm_surface == NULL) { - TPL_ERR("Failed to acquire tbm_surface. | tsq_err = %d", tsq_err); - return; - } - - if (surface->draw_wait_fd_get) - wait_fd = surface->draw_wait_fd_get(surface->surface, tbm_surface); - - if (wait_fd != -1) { - struct epoll_event wait_fence_event; - int epoll_err; - - wait_fence_event.events = EPOLLIN; - wait_fence_event.data.ptr = surface; - epoll_err = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, - wait_fd, - &wait_fence_event); - if (epoll_err == 0) { - surface->draw_wait_buffer = tbm_surface; - return; - } - } /* else can't(or not need) wait fence in poll */ - - if (surface->draw_done) - surface->draw_done(surface->surface, tbm_surface, - TPL_ERROR_INVALID_OPERATION); - } -} - -void -__tpl_worker_new_buffer_notify(tpl_worker_surface_t *surface) -{ - TPL_ASSERT(surface->surface); - - __tpl_worker_event_send(); -} - -static tpl_bool_t -__tpl_worker_regist_vblank_handler(tdm_client_vblank *tdm_vblank); - -static void -__tpl_worker_cb_vblank(tdm_client_vblank *tdm_vblank, tdm_error error, - unsigned int sequence, unsigned int tv_sec, - unsigned int tv_usec, void *user_data) -{ - tpl_list_node_t *trail; - - if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { - TPL_ERR_ERRNO("surface list mutex lock failed"); - return; - } - - for (trail = __tpl_list_get_front_node(&tpl_worker_thread.surface_list); - trail != NULL; - trail = __tpl_list_node_next(trail)) { - tpl_worker_surface_t *surface; - - surface = __tpl_list_node_get_data(trail); - if (surface->vblank) - surface->vblank(surface->surface, sequence, tv_sec, tv_usec); - } - pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); - - __tpl_worker_regist_vblank_handler(tdm_vblank); -} - -static tpl_bool_t -__tpl_worker_regist_vblank_handler(tdm_client_vblank *tdm_vblank) -{ - tdm_error tdm_err; - - tdm_err = tdm_client_vblank_wait(tdm_vblank, - 1, /* interval */ - __tpl_worker_cb_vblank, /* handler */ - NULL); - if (tdm_err != TDM_ERROR_NONE) { - TPL_ERR("Failed to tdm_client_wait_vblank. error:%d", tdm_err); - return TPL_FALSE; - } - return TPL_TRUE; -} - -static int -__tpl_worker_prepare_event_fd(int epoll_fd) -{ - int event_fd; - struct epoll_event event; - event.events = EPOLLIN; - event.data.ptr = &tpl_worker_thread; - - event_fd = eventfd(0, EFD_CLOEXEC); - if (event_fd == -1) { - TPL_ERR_ERRNO("eventfd() failed"); - return -1; - } - - if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, event_fd, &event) != 0) { - TPL_ERR_ERRNO("eventfd epoll ctl epoll_fd: %d, event_fd: %d.", - epoll_fd, tpl_worker_thread.event_fd); - close(event_fd); - return -1; - } - return event_fd; -} - -/* FIXME: Temporarily added 'unused' attribute to suppress warning. */ -/* Remove this attribute when you use this function. */ -static tpl_bool_t __attribute__((unused)) -__tpl_worker_prepare_vblank(int epoll_fd, tdm_client **ret_client, tdm_client_vblank **ret_vblank) -{ - tdm_error tdm_err; - tdm_client *tdm_client = NULL; - tdm_client_output *tdm_output = NULL; - tdm_client_vblank *tdm_vblank = NULL; - int tdm_fd, ret; - struct epoll_event event; - - TPL_ASSERT(ret_client); - TPL_ASSERT(ret_vblank); - - tdm_client = tdm_client_create(&tdm_err); - if (!tdm_client) { - TPL_ERR("tdm_client_create failed | tdm_err: %d\n", tdm_err); - goto error_cleanup; - } - - tdm_err = tdm_client_get_fd(tdm_client, &tdm_fd); - if (tdm_err != TDM_ERROR_NONE || tdm_fd < 0) { - TPL_ERR("tdm_client_get_fd failed | tdm_err: %d\n", tdm_err); - goto error_cleanup; - } - - tdm_output = tdm_client_get_output(tdm_client, "primary", &tdm_err); - if (!tdm_output) { - TPL_ERR("Failed to get tdm client output. tdm_err(%d)", tdm_err); - goto error_cleanup; - } - - tdm_vblank = tdm_client_output_create_vblank(tdm_output, &tdm_err); - if (!tdm_vblank) { - TPL_ERR("Failed to create tdm vblank output. tdm_err(%d)", tdm_err); - goto error_cleanup; - } - - tdm_client_vblank_set_enable_fake(tdm_vblank, 1); - tdm_client_vblank_set_sync(tdm_vblank, 0); - - if (__tpl_worker_regist_vblank_handler(tdm_vblank) == TPL_FALSE) - goto error_cleanup; - - event.events = EPOLLIN; - event.data.ptr = tdm_client; - ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, tdm_fd, &event); - if (ret != 0) { - TPL_ERR_ERRNO("tdm epoll ctl epoll_fd: %d, tdm_fd: %d.", - epoll_fd, tdm_fd); - goto error_cleanup; - } - - *ret_vblank = tdm_vblank; - *ret_client = tdm_client; - - return TPL_TRUE; - -error_cleanup: - if (tdm_vblank) - tdm_client_vblank_destroy(tdm_vblank); - if (tdm_client) - tdm_client_destroy(tdm_client); - return TPL_FALSE; -} - -static void * -__tpl_worker_thread_loop(void *arg) -{ -#define EPOLL_MAX_SIZE 100 - int ret, epoll_fd = epoll_create(EPOLL_MAX_SIZE); - struct epoll_event ev_list[EPOLL_MAX_SIZE]; - tdm_client *tdm_client = NULL; - tdm_client_vblank *tdm_vblank = NULL; - - if (epoll_fd == -1) { - TPL_ERR_ERRNO("epoll create failed"); - goto cleanup; - } - - /* event fd */ - tpl_worker_thread.event_fd = __tpl_worker_prepare_event_fd(epoll_fd); - if (tpl_worker_thread.event_fd == -1) - goto cleanup; - - /* vblank fd */ - /* FIXME: vblank has performance problem */ - /*if (__tpl_worker_prepare_vblank(epoll_fd, &tdm_client, &tdm_vblank)) - tpl_worker_thread.support_vblank = TPL_TRUE;*/ - tpl_worker_thread.support_vblank = TPL_TRUE; - - while (tpl_worker_thread.running) { - int i; - tpl_list_node_t *trail; - - /* set buffer's sync fd and vblank list */ - if (pthread_mutex_lock(&tpl_worker_thread.surface_mutex) != 0) { - TPL_ERR_ERRNO("surface list mutex lock failed"); - goto cleanup; - } - - for (trail = __tpl_list_get_front_node(&tpl_worker_thread.surface_list); - trail != NULL; - trail = __tpl_list_node_next(trail)) { - tpl_worker_surface_t *surface = __tpl_list_node_get_data(trail); - TPL_ASSERT(surface); - - __tpl_worker_prepare_draw_wait_buffer(epoll_fd, surface); - } - pthread_mutex_unlock(&tpl_worker_thread.surface_mutex); - - /* wait events */ -cont_epoll_wait: - ret = epoll_wait(epoll_fd, ev_list, EPOLL_MAX_SIZE, -1); - if (ret == -1) { - if (errno != EINTR) - TPL_ERR_ERRNO("epoll fd: %d.", epoll_fd); - goto cont_epoll_wait; - } - - for (i = 0; i < ret; i++) { - if (ev_list[i].data.ptr == &tpl_worker_thread) { - /* thread terminate event */ - if (ev_list[i].events & EPOLLIN) { - int len; - uint64_t read_buf; - - len = read(tpl_worker_thread.event_fd, - &read_buf, sizeof(uint64_t)); - if (len < 0) { - TPL_WARN_ERRNO("event fd(%d) read failed.", - tpl_worker_thread.event_fd); - continue; - } else { - continue; - } - } - } else if (ev_list[i].data.ptr == tdm_client) { - /* vblank */ - tdm_error tdm_err = tdm_client_handle_events(tdm_client); - - if (tdm_err != TDM_ERROR_NONE) { - TPL_ERR("Failed to tdm_client_handle_events"); - /** - * TODO: Error handling - * - * Currently, no error handling implemented to keep flow identical - * to ensure no side effect. - */ - } - /* process in __tpl_worker_cb_vblank */ - } else { - /* draw done */ - tpl_worker_surface_t *surface = ev_list[i].data.ptr; - - if (!(ev_list[i].events & EPOLLIN)) - continue; - - if (surface->draw_wait_buffer) { - int wait_fd; - - wait_fd = surface->draw_wait_fd_get(surface->surface, - surface->draw_wait_buffer); - if (wait_fd == -1) { - if (surface->draw_done) - surface->draw_done(surface->surface, surface->draw_wait_buffer, - TPL_ERROR_INVALID_OPERATION); - surface->draw_wait_buffer = NULL; - } else { - int fence_result; - - switch (fence_result = tbm_sync_fence_wait(wait_fd, 0)) { - case 0: - TPL_ERR_ERRNO("sync_fence_wait return error."); - break; - case 1: - /* some time recieve event two times */ - epoll_ctl(epoll_fd, EPOLL_CTL_DEL, wait_fd, NULL); - if (surface->draw_done) - surface->draw_done(surface->surface, - surface->draw_wait_buffer, - TPL_ERROR_NONE); - surface->draw_wait_buffer = NULL; - break; - case -1: - TPL_WARN("sync_fence_wait return timeout."); - break; - } - } - } else { - TPL_WARN("recieve already signaled event\n"); - } - - /* prepare next buffer in loop start time */ - } - } - } - -cleanup: - /* thread cleanup */ - if (tdm_vblank) - tdm_client_vblank_destroy(tdm_vblank); - if (tdm_client) - tdm_client_destroy(tdm_client); - - if (epoll_fd != -1) { - close(epoll_fd); - epoll_fd = -1; - } - if (tpl_worker_thread.event_fd != -1) { - close(tpl_worker_thread.event_fd); - tpl_worker_thread.event_fd = -1; - } - - return NULL; -} - -static void __attribute__((constructor)) -__tpl_worker_init(void) -{ - /* - * It can be move to display or surface create function - * with pthread_once - */ - tpl_worker_thread.running = 1; - tpl_worker_thread.support_vblank = TPL_FALSE; - - if (pthread_mutex_init(&tpl_worker_thread.surface_mutex, NULL) != 0) { - TPL_ERR_ERRNO("surface list mutex init failed"); - goto error; - } - - __tpl_list_init(&tpl_worker_thread.surface_list); - - if (pthread_create(&tpl_worker_thread.worker_id, NULL, - __tpl_worker_thread_loop, - NULL) != 0) { - TPL_ERR_ERRNO("worker thread create failed"); - goto error_thread_create; - } - /*pthread_setname_np(tpl_worker_thread.worker_id, "tpl_worker_thread");*/ - - return; - -error_thread_create: - pthread_mutex_destroy(&tpl_worker_thread.surface_mutex); - -error: - tpl_worker_thread.running = 0; -} - -static void __attribute__((destructor)) -__tpl_worker_fini(void) -{ - if (tpl_worker_thread.running == 0) - return; - - /* deinitailize global object */ - tpl_worker_thread.running = 0; - - /* maybe EPOLLRDHUP not work with eventfd */ - /* close(tpl_worker_thread.event_fd); */ - __tpl_worker_event_send(); - - if (__tpl_list_get_count(&tpl_worker_thread.surface_list)) - TPL_WARN("called destructor, but tpl surface count: %d", - __tpl_list_get_count(&tpl_worker_thread.surface_list)); - - pthread_join(tpl_worker_thread.worker_id, NULL); - pthread_mutex_destroy(&tpl_worker_thread.surface_mutex); -} diff --git a/src/tpl_worker_thread.h b/src/tpl_worker_thread.h deleted file mode 100644 index f7562a9..0000000 --- a/src/tpl_worker_thread.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef TPL_WORKER_THREAD_H -#define TPL_WORKER_THREAD_H - -#include "tpl.h" -#include -#include -#include -#include - -typedef struct __tpl_worker_surface tpl_worker_surface_t; - -struct __tpl_worker_surface { - tpl_surface_t *surface; - tbm_surface_queue_h tbm_queue; - - void (*draw_done)(tpl_surface_t *surface, tbm_surface_h tbm_surface, tpl_result_t result); - int (*draw_wait_fd_get)(tpl_surface_t *surface, tbm_surface_h tbm_surface); - void (*vblank)(tpl_surface_t *surface, unsigned int sequence, unsigned int tv_sec, - unsigned int tv_usec); - tbm_surface_h (*draw_wait_buffer_get)(tpl_surface_t *surface); - - tbm_surface_h draw_wait_buffer; -}; - -tpl_bool_t __tpl_worker_support_vblank(); -void __tpl_worker_surface_list_insert(tpl_worker_surface_t *surface); -void __tpl_worker_surface_list_remove(tpl_worker_surface_t *surface); -void __tpl_worker_new_buffer_notify(tpl_worker_surface_t *surface); - -#endif //TPL_WORKER_THREAD_H -- 2.7.4