wl_egl: support for frontbuffer mode set by surface 45/286745/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Thu, 12 Jan 2023 07:16:50 +0000 (16:16 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Thu, 12 Jan 2023 07:16:53 +0000 (16:16 +0900)
 - 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 <joonbum.ko@samsung.com>
src/tpl_wl_egl_thread.c

index 10ff5f5..681b8ac 100755 (executable)
@@ -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)