From 9d6715fdb36bbd85f62a314f71a3f7c32ace1e90 Mon Sep 17 00:00:00 2001 From: "jinbong, Lee" Date: Wed, 10 Jan 2024 11:10:42 +0000 Subject: [PATCH] Implementation for SwapInterval is zero - 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 | 12 ++++---- src/tpl_wayland_egl.c | 4 +-- src/tpl_wl_egl_thread.c | 53 +++++++++++++++++++++++------------ src/tpl_wl_vk_thread.c | 74 +++++++++++++++++++++++++++++++++++++------------ 4 files changed, 101 insertions(+), 42 deletions(-) diff --git a/src/tpl_surface.c b/src/tpl_surface.c index 9bed148..443c6ad 100755 --- a/src/tpl_surface.c +++ b/src/tpl_surface.c @@ -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); diff --git a/src/tpl_wayland_egl.c b/src/tpl_wayland_egl.c index 38c2f39..d464136 100755 --- a/src/tpl_wayland_egl.c +++ b/src/tpl_wayland_egl.c @@ -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(); diff --git a/src/tpl_wl_egl_thread.c b/src/tpl_wl_egl_thread.c index 785e7bd..8e2d576 100755 --- a/src/tpl_wl_egl_thread.c +++ b/src/tpl_wl_egl_thread.c @@ -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); diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c index 3ad9b00..319d339 100644 --- a/src/tpl_wl_vk_thread.c +++ b/src/tpl_wl_vk_thread.c @@ -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 -- 2.7.4