Implementation for SwapInterval is zero 31/304131/8
authorjinbong, Lee <jinbong.lee@samsung.com>
Wed, 10 Jan 2024 11:10:42 +0000 (11:10 +0000)
committerjinbong, Lee <jinbong.lee@samsung.com>
Thu, 11 Jan 2024 11:05:21 +0000 (11:05 +0000)
 - asynchronous swap mode implementation for benchmark
 - Clearing waiting-buffers will be run in vblank event's callback,
   because of vblank callback will be called at least once if there is a buffer waiting to commit
 - add vblank_enable flag it can be changed during runtime, and it is related with post_interval & vblank

Change-Id: Ieb50ebad4350b293fa7e243ce960f125ee7029dd

src/tpl_surface.c
src/tpl_wayland_egl.c
src/tpl_wl_egl_thread.c
src/tpl_wl_vk_thread.c

index 9bed148..443c6ad 100755 (executable)
@@ -255,16 +255,18 @@ tpl_surface_set_post_interval(tpl_surface_t *surface, int interval)
                return TPL_ERROR_INVALID_PARAMETER;
        }
 
-       if (interval <= 0)
+       if (interval < 0)
                return TPL_ERROR_NONE;
 
        TPL_OBJECT_LOCK(surface);
 
-       if (surface->backend.set_post_interval)
-               ret = surface->backend.set_post_interval(surface, interval);
+       if (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;
+               if (ret == TPL_ERROR_NONE)
+                       surface->post_interval = interval;
+       }
 
        TPL_OBJECT_UNLOCK(surface);
 
index 38c2f39..d464136 100755 (executable)
@@ -1004,7 +1004,7 @@ __tpl_wayland_egl_surface_commit(tpl_surface_t *surface,
        }
 
        /* TPL_WAIT_VBLANK = 1 */
-       if (wayland_egl_display->tdm_client) {
+       if (wayland_egl_display->tdm_client && surface->post_interval > 0) {
                int tdm_lock_res = pthread_mutex_lock(&wayland_egl_display->tdm_mutex);
                tdm_err = tdm_client_vblank_wait(wayland_egl_surface->tdm_vblank,
                                                                                 surface->post_interval, /* interval */
@@ -1107,7 +1107,7 @@ __tpl_wayland_egl_surface_enqueue_buffer(tpl_surface_t *surface,
                                        tbm_bo_export(wayland_egl_buffer->bo));
 
        TRACE_BEGIN("[WAIT_VBLANK]");
-       if (wayland_egl_surface->vblank_done == TPL_FALSE)
+       if (wayland_egl_surface->vblank_done == TPL_FALSE && surface->post_interval > 0)
                __tpl_wayland_egl_surface_wait_vblank(surface);
        TRACE_END();
 
index 785e7bd..8e2d576 100755 (executable)
@@ -155,6 +155,7 @@ struct _tpl_wl_egl_surface {
        tpl_bool_t                    need_to_enqueue;
        tpl_bool_t                    prerotation_capability;
        tpl_bool_t                    vblank_done;
+       tpl_bool_t                    vblank_enable;
        tpl_bool_t                    set_serial_is_used;
        tpl_bool_t                    initialized_in_thread;
        tpl_bool_t                    frontbuffer_activated;
@@ -1781,6 +1782,8 @@ __tpl_wl_egl_surface_init(tpl_surface_t *surface)
 
        wl_egl_surface->post_interval          = surface->post_interval;
 
+       wl_egl_surface->vblank_enable          = TPL_FALSE;
+
        wl_egl_surface->commit_sync.fd         = -1;
        wl_egl_surface->presentation_sync.fd   = -1;
 
@@ -2029,21 +2032,30 @@ _thread_wl_egl_surface_init(tpl_wl_egl_surface_t *wl_egl_surface)
                                vblank = NULL;
                        } else {
                                vblank->waiting_buffers = __tpl_list_alloc();
-                               vblank->wl_egl_surface = wl_egl_surface;
-                               tpl_gmutex_init(&vblank->mutex);
-
-                               __tpl_list_push_back(wl_egl_display->tdm.surface_vblanks,
-                                                                        (void *)vblank);
-
-                               TPL_INFO("[VBLANK_INIT]",
-                                                "wl_egl_surface(%p) tdm_client(%p) tdm_vblank(%p)",
-                                                wl_egl_surface, wl_egl_display->tdm.tdm_client,
-                                                vblank->tdm_vblank);
+                               if (!vblank->waiting_buffers) {
+                                       tdm_client_vblank_destroy(vblank->tdm_vblank);
+                                       free(vblank);
+                                       vblank = NULL;
+                               } else{
+                                       vblank->wl_egl_surface = wl_egl_surface;
+                                       tpl_gmutex_init(&vblank->mutex);
+
+                                       __tpl_list_push_back(wl_egl_display->tdm.surface_vblanks,
+                                                                               (void *)vblank);
+
+                                       TPL_INFO("[VBLANK_INIT]",
+                                                       "wl_egl_surface(%p) tdm_client(%p) tdm_vblank(%p)",
+                                                       wl_egl_surface, wl_egl_display->tdm.tdm_client,
+                                                       vblank->tdm_vblank);
+                               }
                        }
                }
        }
 
        wl_egl_surface->vblank = vblank;
+       wl_egl_surface->vblank_enable = (vblank != NULL &&
+                                                                       wl_egl_surface->post_interval > 0);
+
 #if TIZEN_FEATURE_ENABLE
        if (wl_egl_display->tss) {
                wl_egl_surface->tss_flusher =
@@ -2291,7 +2303,9 @@ __tpl_wl_egl_surface_set_post_interval(tpl_surface_t *surface,
                         "wl_egl_surface(%p) post_interval(%d -> %d)",
                         wl_egl_surface, wl_egl_surface->post_interval, post_interval);
 
+       tpl_gmutex_lock(&wl_egl_surface->surf_mutex);
        wl_egl_surface->post_interval = post_interval;
+       tpl_gmutex_unlock(&wl_egl_surface->surf_mutex);
 
        return TPL_ERROR_NONE;
 }
@@ -2885,7 +2899,7 @@ __thread_func_waiting_source_dispatch(tpl_gsource *gsource, uint64_t message)
 
        tpl_gmutex_lock(&wl_egl_surface->surf_mutex);
 
-       if (wl_egl_surface->vblank == NULL || wl_egl_surface->vblank_done)
+       if (!wl_egl_surface->vblank_enable || wl_egl_surface->vblank_done)
                _thread_wl_surface_commit(wl_egl_surface, wl_egl_buffer);
        else {
                tpl_gmutex_lock(&wl_egl_surface->vblank->mutex);
@@ -2973,7 +2987,7 @@ _thread_surface_queue_acquire(tpl_wl_egl_surface_t *wl_egl_surface)
                }
 
                if (ready_to_commit) {
-                       if (wl_egl_surface->vblank == NULL || wl_egl_surface->vblank_done)
+                       if (!wl_egl_surface->vblank_enable || wl_egl_surface->vblank_done)
                                ready_to_commit = TPL_TRUE;
                        else {
                                wl_egl_buffer->status = WAITING_VBLANK;
@@ -3008,9 +3022,9 @@ __cb_tdm_client_vblank(tdm_client_vblank *vblank, tdm_error error,
                TPL_WARN("[TDM_ERROR_TIMEOUT] It will keep going. wl_egl_surface(%p)",
                                 wl_egl_surface);
 
+       tpl_gmutex_lock(&wl_egl_surface->surf_mutex);
        wl_egl_surface->vblank_done = TPL_TRUE;
 
-       tpl_gmutex_lock(&wl_egl_surface->surf_mutex);
        if (wl_egl_surface->vblank && wl_egl_surface->vblank->waiting_buffers) {
                tpl_bool_t is_empty = TPL_TRUE;
                do {
@@ -3028,8 +3042,11 @@ __cb_tdm_client_vblank(tdm_client_vblank *vblank, tdm_error error,
                         * flush all vblank waiting buffers of its wl_egl_surface.
                         * Otherwise, only one wl_egl_buffer will be commited per one vblank event.
                         */
-                       if (error == TDM_ERROR_NONE) break;
+                       if (error == TDM_ERROR_NONE && wl_egl_surface->post_interval > 0)
+                               break;
                } while (!is_empty);
+
+               wl_egl_surface->vblank_enable = (wl_egl_surface->post_interval > 0);
        }
        tpl_gmutex_unlock(&wl_egl_surface->surf_mutex);
 }
@@ -3500,9 +3517,11 @@ _thread_wl_surface_commit(tpl_wl_egl_surface_t *wl_egl_surface,
                          wl_egl_buffer, wl_egl_buffer->wl_buffer, wl_egl_buffer->tbm_surface,
                          wl_egl_buffer->bo_name);
 
-       if (wl_egl_surface->vblank != NULL &&
-               _thread_surface_vblank_wait(wl_egl_surface) != TPL_ERROR_NONE)
-               TPL_ERR("Failed to set wait vblank.");
+       if (wl_egl_surface->post_interval > 0 && wl_egl_surface->vblank != NULL) {
+               wl_egl_surface->vblank_enable = TPL_TRUE;
+               if (_thread_surface_vblank_wait(wl_egl_surface) != TPL_ERROR_NONE)
+                       TPL_ERR("Failed to set wait vblank.");
+       }
 
        tpl_gmutex_lock(&wl_egl_surface->commit_sync.mutex);
 
index 3ad9b00..319d339 100644 (file)
@@ -145,6 +145,7 @@ struct _tpl_wl_vk_surface {
        tpl_bool_t                    is_activated;
        tpl_bool_t                    reset; /* TRUE if queue reseted by external  */
        tpl_bool_t                    vblank_done;
+       tpl_bool_t                    vblank_enable;
        tpl_bool_t                    initialized_in_thread;
 
        /* To make sure that tpl_gsource has been successfully finalized. */
@@ -1152,13 +1153,21 @@ _thread_wl_vk_surface_init(tpl_wl_vk_surface_t *wl_vk_surface)
 
        /* tbm_surface_queue will be created at swapchain_create */
 
-       wl_vk_surface->vblank = _thread_create_tdm_client_vblank(
-                                                               wl_vk_display->tdm.tdm_client);
-       if (wl_vk_surface->vblank) {
-               TPL_INFO("[VBLANK_INIT]",
-                                "wl_vk_surface(%p) tdm_client(%p) vblank(%p)",
-                                wl_vk_surface, wl_vk_display->tdm.tdm_client,
-                                wl_vk_surface->vblank);
+       if (wl_vk_display->use_wait_vblank) {
+               wl_vk_surface->vblank = _thread_create_tdm_client_vblank(
+                                                                       wl_vk_display->tdm.tdm_client);
+               if (wl_vk_surface->vblank) {
+                       TPL_INFO("[VBLANK_INIT]",
+                                       "wl_vk_surface(%p) tdm_client(%p) vblank(%p)",
+                                       wl_vk_surface, wl_vk_display->tdm.tdm_client,
+                                       wl_vk_surface->vblank);
+
+                       wl_vk_surface->vblank_waiting_buffers = __tpl_list_alloc();
+                       if (!wl_vk_surface->vblank_waiting_buffers) {
+                               tdm_client_vblank_destroy(wl_vk_surface->vblank);
+                               wl_vk_surface->vblank = NULL;
+                       }
+               }
        }
 
 #if TIZEN_FEATURE_ENABLE
@@ -1177,7 +1186,9 @@ _thread_wl_vk_surface_init(tpl_wl_vk_surface_t *wl_vk_surface)
                }
        }
 #endif
-       wl_vk_surface->vblank_waiting_buffers = __tpl_list_alloc();
+
+       wl_vk_surface->vblank_enable = (wl_vk_surface->vblank != NULL &&
+               wl_vk_surface->post_interval > 0);
 }
 
 static void
@@ -1342,6 +1353,7 @@ __tpl_wl_vk_surface_init(tpl_surface_t *surface)
        wl_vk_surface->render_done_cnt         = 0;
 
        wl_vk_surface->vblank                  = NULL;
+       wl_vk_surface->vblank_enable           = TPL_FALSE;
 #if TIZEN_FEATURE_ENABLE
        wl_vk_surface->surface_sync            = NULL;
 #endif
@@ -1451,7 +1463,9 @@ __tpl_wl_vk_surface_set_post_interval(tpl_surface_t *surface,
                         "wl_vk_surface(%p) post_interval(%d -> %d)",
                         wl_vk_surface, wl_vk_surface->post_interval, post_interval);
 
+       tpl_gmutex_lock(&wl_vk_surface->surf_mutex);
        wl_vk_surface->post_interval = post_interval;
+       tpl_gmutex_unlock(&wl_vk_surface->surf_mutex);
 
        return TPL_ERROR_NONE;
 }
@@ -2351,7 +2365,7 @@ _thread_surface_queue_acquire(tpl_wl_vk_surface_t *wl_vk_surface)
                        }
                }
 
-               if (!wl_vk_display->use_wait_vblank || wl_vk_surface->vblank_done)
+               if (!wl_vk_surface->vblank_enable || wl_vk_surface->vblank_done)
                        ready_to_commit = TPL_TRUE;
                else {
                        wl_vk_buffer->status = WAITING_VBLANK;
@@ -2560,14 +2574,30 @@ __cb_tdm_client_vblank(tdm_client_vblank *vblank, tdm_error error,
                TPL_WARN("[TDM_ERROR_TIMEOUT] It will keep going. wl_vk_surface(%p)",
                                 wl_vk_surface);
 
+       tpl_gmutex_lock(&wl_vk_surface->surf_mutex);
        wl_vk_surface->vblank_done = TPL_TRUE;
 
-       tpl_gmutex_lock(&wl_vk_surface->surf_mutex);
-       wl_vk_buffer = (tpl_wl_vk_buffer_t *)__tpl_list_pop_front(
-                                               wl_vk_surface->vblank_waiting_buffers,
-                                               NULL);
-       if (wl_vk_buffer)
-               _thread_wl_surface_commit(wl_vk_surface, wl_vk_buffer);
+       if (wl_vk_surface->vblank && wl_vk_surface->vblank_waiting_buffers) {
+               tpl_bool_t is_empty = TPL_TRUE;
+               do {
+                       tpl_wl_vk_buffer_t* wl_vk_buffer =(tpl_wl_vk_buffer_t *)
+                               __tpl_list_pop_front(wl_vk_surface->vblank_waiting_buffers, NULL);
+                       is_empty = __tpl_list_is_empty(wl_vk_surface->vblank_waiting_buffers);
+
+                       if (!wl_vk_buffer) break;
+
+                       _thread_wl_surface_commit(wl_vk_surface, wl_vk_buffer);
+
+                       /* If tdm error such as TIMEOUT occured,
+                        * flush all vblank waiting buffers of its wl_vk_surface.
+                        * Otherwise, only one wl_vk_buffer will be commited per one vblank event.
+                        */
+                       if (error == TDM_ERROR_NONE && wl_vk_surface->post_interval > 0)
+                               break;
+               } while (!is_empty);
+
+               wl_vk_surface->vblank_enable = (wl_vk_surface->post_interval > 0);
+       }
        tpl_gmutex_unlock(&wl_vk_surface->surf_mutex);
 }
 
@@ -2584,6 +2614,12 @@ _thread_surface_vblank_wait(tpl_wl_vk_surface_t *wl_vk_surface)
                        TPL_WARN("Failed to create vblank. wl_vk_surface(%p)",
                                         wl_vk_surface);
                        return TPL_ERROR_OUT_OF_MEMORY;
+               } else {
+                       wl_vk_surface->vblank_waiting_buffers = __tpl_list_alloc();
+                       if (!wl_vk_surface->vblank_waiting_buffers) {
+                               tdm_client_vblank_destroy(wl_vk_surface->vblank);
+                               wl_vk_surface->vblank = NULL;
+                       }
                }
        }
 
@@ -2710,9 +2746,11 @@ _thread_wl_surface_commit(tpl_wl_vk_surface_t *wl_vk_surface,
                          wl_vk_buffer, wl_vk_buffer->wl_buffer, wl_vk_buffer->tbm_surface,
                          wl_vk_buffer->bo_name);
 
-       if (wl_vk_display->use_wait_vblank &&
-               _thread_surface_vblank_wait(wl_vk_surface) != TPL_ERROR_NONE)
-               TPL_ERR("Failed to set wait vblank.");
+       if (wl_vk_surface->post_interval > 0 && wl_vk_surface->vblank != NULL) {
+               wl_vk_surface->vblank_enable = TPL_TRUE;
+               if (_thread_surface_vblank_wait(wl_vk_surface) != TPL_ERROR_NONE)
+                       TPL_ERR("Failed to set wait vblank.");
+       }
 }
 
 tpl_bool_t