From a59d74fb5048cbbfa2fbd16a093fb63d877c13e7 Mon Sep 17 00:00:00 2001 From: Joonbum Ko Date: Wed, 19 Aug 2020 19:41:16 +0900 Subject: [PATCH] Fixed a bug related to render sync fd. - Very occasionally, when twe_thread is pushed down by scheduling, a sync_fd cannot be attached to twe_thread. - In this case, queue_can_acquire and render_done_cnt are different and the commit is delayed by one frame. - This problem may cause can_dequeue_timeout depending on the hwc situation. - Even if queue_flush is performed after can_dequeue_timeout, the commit latency cannot be restored until another interrupt occurs. Change-Id: I32bc48d523e815a944cbfb935277adc1bcc2bf44 Signed-off-by: Joonbum Ko --- src/tpl_wayland_egl_thread.c | 82 +++++++++++++++++++++--------------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 2fe051d..bb75442 100755 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -97,6 +97,12 @@ struct _twe_del_source { void (*destroy_target_source_func)(void *); }; + +struct sync_info { + tbm_surface_h tbm_surface; + int sync_fd; +}; + struct _twe_wl_surf_source { GSource gsource; gpointer tag; @@ -118,6 +124,7 @@ struct _twe_wl_surf_source { tpl_list_t *in_use_buffers; /* Trace tbm_surface from DEQUEUE to ENQUEUE */ tpl_list_t *fence_waiting_sources; /* Trace fence_wait_source from ENQUEUE to fence signaled */ tpl_list_t *vblank_waiting_buffers; /* for FIFO/FIFO_RELAXED modes */ + tpl_list_t *render_done_fences; /* for attaching to twe_thread with fences passed by enqueue */ tbm_surface_h draw_done_buffer; /* for MAILBOX mode */ int render_done_cnt; @@ -154,11 +161,6 @@ struct _twe_wl_surf_source { int post_interval; - struct { - tbm_surface_h tbm_surface; - int sync_fd; - } sync_info; - struct zwp_linux_surface_synchronization_v1 *surface_sync; }; @@ -2654,28 +2656,27 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data) } if (surf_source->use_sync_fence && - surf_source->sync_info.sync_fd > 0 && - surf_source->sync_info.tbm_surface) { - - int sync_fd = surf_source->sync_info.sync_fd; - tbm_surface_h tbm_surface = surf_source->sync_info.tbm_surface; - - if (!surf_source->use_surface_sync) { - res = _twe_thread_fence_wait_source_attach(surf_source, tbm_surface, sync_fd); - if (res != TPL_ERROR_NONE) { - TPL_ERR("Failed to attach source with fence_fd(%d) result(%d)", - sync_fd, res); - surf_source->use_sync_fence = TPL_FALSE; - } else { - surf_source->use_sync_fence = TPL_TRUE; + surf_source->render_done_fences) { + + while (__tpl_list_get_count(surf_source->render_done_fences)) { + struct sync_info *sync = __tpl_list_pop_front(surf_source->render_done_fences, + NULL); + if (sync) { + res = _twe_thread_fence_wait_source_attach(surf_source, + sync->tbm_surface, + sync->sync_fd); + if (res != TPL_ERROR_NONE) { + TPL_ERR("Failed to attach source with fence_fd(%d) result(%d)", + sync->sync_fd, res); + surf_source->use_sync_fence = TPL_FALSE; + } + + sync->sync_fd = -1; + sync->tbm_surface = NULL; + free(sync); } } - - surf_source->sync_info.sync_fd = -1; - surf_source->sync_info.tbm_surface = NULL; - } - - if (!surf_source->use_sync_fence){ + } else { _twe_thread_wl_surface_acquire_and_commit(surf_source); } } @@ -3112,6 +3113,7 @@ twe_surface_add(twe_thread* thread, source->committed_buffers = __tpl_list_alloc(); source->in_use_buffers = __tpl_list_alloc(); source->fence_waiting_sources = __tpl_list_alloc(); + source->render_done_fences = __tpl_list_alloc(); source->render_done_cnt = 0; source->cb_data = NULL; @@ -3138,9 +3140,6 @@ twe_surface_add(twe_thread* thread, source->presentation_sync_ts_backup = 0; source->presentation_sync_req_cnt = 0; - source->sync_info.tbm_surface = NULL; - source->sync_info.sync_fd = -1; - if (!disp_source->is_vulkan_dpy) { struct wl_egl_window *wl_egl_window = (struct wl_egl_window *)native_handle; @@ -3718,13 +3717,26 @@ twe_surface_set_sync_fd(twe_surface_h twe_surface, close(buf_info->acquire_fence_fd); buf_info->acquire_fence_fd = sync_fd; } else { - g_mutex_lock(&surf_source->surf_mutex); - surf_source->sync_info.sync_fd = sync_fd; - surf_source->sync_info.tbm_surface = tbm_surface; - surf_source->use_sync_fence = TPL_TRUE; - TPL_DEBUG("[SET_SYNC_FD] surf_source(%p) tbm_surface(%p) sync_fd(%d)", - surf_source, tbm_surface, sync_fd); - g_mutex_unlock(&surf_source->surf_mutex); + /* The sync_info being pushed will be popped when surface_dispatch + * is called and attached to the twe_thread. */ + struct sync_info *sync = (struct sync_info *)calloc(1, sizeof(struct sync_info)); + if (sync) { + sync->sync_fd = sync_fd; + sync->tbm_surface = tbm_surface; + + if (surf_source->render_done_fences) { + g_mutex_lock(&surf_source->surf_mutex); + __tpl_list_push_back(surf_source->render_done_fences, + (void *)sync); + surf_source->use_sync_fence = TPL_TRUE; + TPL_DEBUG("[SET_SYNC_FD] surf_source(%p) tbm_surface(%p) sync_fd(%d)", + surf_source, tbm_surface, sync_fd); + g_mutex_unlock(&surf_source->surf_mutex); + } else { + surf_source->use_sync_fence = TPL_FALSE; + free(sync); + } + } } return ret; -- 2.34.1