From 5b989cb1a0f883b59f0513628f0a344f249e26d6 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Thu, 12 Jan 2023 16:16:50 +0900 Subject: [PATCH] wl_egl: support for frontbuffer mode set by surface - Patch for supporting this API. wl_egl_window_tizen_set_frontbuffer_mode() AS-IS: - If the application, which wants to use frontbuffer rendering, sets the frontbuffer mode using setenv(), EGL driver checks whether frontbuffer mode is set using getenv() and if it true calls tpl_surface_set_frontbuffer_mode(). PROBLEMS: - The operation using setenv()/getenv() is not thread safe. - Using env value to set frontbuffer mode cannot manage on/off in runtime. - Using env value to set frontbuffer mode cannot set by surface. TO-BE: - Application would be better to use this API wl_egl_window_tizen_set_frontbuffer_mode() - This API makes supports the setting of frontbuffer mode to the desired surface(window). - This API gurantee thread safety using tpl_surface object lock. - Using this API can help application to turn on/off the frontbuffer mode in runtime. Change-Id: I608309869dcb9d0bd0ba42c7e54afee6da1b5e04 Signed-off-by: Joonbum Ko --- src/tpl_wl_egl_thread.c | 92 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 72 insertions(+), 20 deletions(-) diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index 10ff5f5..681b8ac 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -1402,6 +1402,37 @@ __cb_create_commit_sync_fd(struct wl_egl_window *wl_egl_window, void *private) return commit_sync_fd; } +static void +__cb_client_window_set_frontbuffer_mode(struct wl_egl_window *wl_egl_window, + void *private, int set) +{ + TPL_ASSERT(private); + TPL_ASSERT(wl_egl_window); + struct tizen_private *tizen_private = (struct tizen_private *)private; + tpl_wl_egl_surface_t *wl_egl_surface = (tpl_wl_egl_surface_t *)tizen_private->data; + TPL_CHECK_ON_NULL_RETURN(wl_egl_surface); + + tpl_surface_t *surface = wl_egl_surface->tpl_surface; + TPL_CHECK_ON_NULL_RETURN(surface); + + tpl_bool_t is_frontbuffer_mode = set ? TPL_TRUE : TPL_FALSE; + + TPL_OBJECT_LOCK(surface); + if (is_frontbuffer_mode == surface->is_frontbuffer_mode) { + TPL_OBJECT_UNLOCK(surface); + return; + } + + TPL_INFO("[FRONTBUFFER_MODE]", + "[%s] wl_egl_surface(%p) wl_egl_window(%p)", + is_frontbuffer_mode ? "ON" : "OFF", + wl_egl_surface, wl_egl_window); + + surface->is_frontbuffer_mode = is_frontbuffer_mode; + + TPL_OBJECT_UNLOCK(surface); +} + #if TIZEN_FEATURE_ENABLE static int __cb_create_presentation_sync_fd(struct wl_egl_window *wl_egl_window, void *private) @@ -1807,6 +1838,7 @@ __tpl_wl_egl_surface_init(tpl_surface_t *surface) tizen_private->set_window_serial_callback = (void *) __cb_set_window_serial_callback; tizen_private->create_commit_sync_fd = (void *)__cb_create_commit_sync_fd; + tizen_private->set_frontbuffer_callback = (void *)__cb_client_window_set_frontbuffer_mode; #if TIZEN_FEATURE_ENABLE tizen_private->create_presentation_sync_fd = (void *)__cb_create_presentation_sync_fd; #else @@ -2597,14 +2629,32 @@ __tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, wl_egl_surface->width = surface->width; wl_egl_surface->height = surface->height; - if (surface->is_frontbuffer_mode && surface->frontbuffer != NULL) { - /* If surface->frontbuffer is already set in frontbuffer mode, - * it will return that frontbuffer if it is still activated, - * otherwise dequeue the new buffer after initializing - * surface->frontbuffer to NULL. */ - if (is_activated && !wl_egl_surface->reset) { - bo_name = _get_tbm_surface_bo_name(surface->frontbuffer); + /* If surface->frontbuffer is not null, the frontbuffer rendering mode will be + * maintained if the surface state meets the conditions below. + * 1. surface->is_frontbuffer_mode == TPL_TRUE + * - It may be changed to true or false by calling + * tpl_surface_set_frontbuffer_mode(will be deprecated) + * or + * wl_egl_window_tizen_set_frontbuffer_mode (recommanded) + * 2. is_activated == TPL_TRUE + * - To check wheter direct display is possible. + * 3. wl_egl_surface->reset == TPL_FALSE + * - tbm_queue reset should not have occured due to window resize. + * If surface is not satisfied with any of above conditions, + * frontbuffer rendering will be stopped and surface->frontbuffer becomes null. + * */ + if (surface->frontbuffer) { + if (!surface->is_frontbuffer_mode || + !is_activated || + wl_egl_surface->reset) { + surface->frontbuffer = NULL; + wl_egl_surface->need_to_enqueue = TPL_TRUE; + TPL_INFO("[FRONTBUFFER RENDERING STOP]", + "wl_egl_surface(%p) wl_egl_window(%p)", + wl_egl_surface, wl_egl_surface->wl_egl_window); + } else { + bo_name = _get_tbm_surface_bo_name(surface->frontbuffer); TPL_LOG_T("WL_EGL", "[DEQ][F] surface->frontbuffer(%p) BO_NAME(%d)", surface->frontbuffer, bo_name); @@ -2613,12 +2663,7 @@ __tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, bo_name); tpl_gmutex_unlock(&wl_egl_display->wl_event_mutex); return surface->frontbuffer; - } else { - surface->frontbuffer = NULL; - wl_egl_surface->need_to_enqueue = TPL_TRUE; } - } else { - surface->frontbuffer = NULL; } tsq_err = tbm_surface_queue_dequeue(wl_egl_surface->tbm_queue, @@ -2656,8 +2701,15 @@ __tpl_wl_egl_surface_dequeue_buffer(tpl_surface_t *surface, uint64_t timeout_ns, } } - if (surface->is_frontbuffer_mode && is_activated) + if (surface->is_frontbuffer_mode && is_activated) { + if (surface->frontbuffer == NULL) { + TPL_INFO("[FRONTBUFFER RENDERING START]", + "wl_egl_surface(%p) wl_egl_window(%p) bo(%d)", + wl_egl_surface, wl_egl_surface->wl_egl_window, + _get_tbm_surface_bo_name(tbm_surface)); + } surface->frontbuffer = tbm_surface; + } wl_egl_surface->reset = TPL_FALSE; @@ -2772,8 +2824,13 @@ __tpl_wl_egl_surface_enqueue_buffer(tpl_surface_t *surface, if (!wl_egl_surface->need_to_enqueue || !wl_egl_buffer->need_to_commit) { - TPL_WARN("[ENQ_SKIP][Frontbuffer:%s] tbm_surface(%p) need not to enqueue", - ((surface->frontbuffer == tbm_surface) ? "ON" : "OFF"), tbm_surface); + + if (acquire_fence != -1) { + close(acquire_fence); + acquire_fence = -1; + } + TPL_LOG_T("FRONTBUFFER_MODE", "[ENQ_SKIP] tbm_surface(%p) bo(%d) need not to enqueue", + tbm_surface, _get_tbm_surface_bo_name(tbm_surface)); TRACE_ASYNC_END((intptr_t)tbm_surface, "[DEQ]~[ENQ] BO_NAME:%d", bo_name); tpl_gmutex_unlock(&wl_egl_buffer->mutex); return TPL_ERROR_NONE; @@ -2790,11 +2847,6 @@ __tpl_wl_egl_surface_enqueue_buffer(tpl_surface_t *surface, */ if (surface->frontbuffer == tbm_surface) wl_egl_surface->need_to_enqueue = TPL_FALSE; - - if (acquire_fence != -1) { - close(acquire_fence); - acquire_fence = -1; - } } if (wl_egl_buffer->acquire_fence_fd != -1) -- 2.7.4