Fixed a bug related to render sync fd. 64/241364/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Wed, 19 Aug 2020 10:41:16 +0000 (19:41 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Wed, 19 Aug 2020 10:47:10 +0000 (19:47 +0900)
 - 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 <joonbum.ko@samsung.com>
src/tpl_wayland_egl_thread.c

index 2fe051d85ab8567a01b4a7cb7bc704b82891a5b9..bb7544295b209fbedb6277f9d92e88f8fb5c1f95 100755 (executable)
@@ -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;