Fixed a bug occured by fence signaled before enqueue. 82/238882/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Thu, 25 Jun 2020 11:24:13 +0000 (20:24 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Tue, 30 Jun 2020 09:40:22 +0000 (18:40 +0900)
 Changed g_source_attach from main thread to twe_thread.

 - Fixed problem scenario
 [MT] : main thread
 [TWE] : twe thread
 1. [MT] __tpl_wl_egl_surface_enqueue_buffer (with sync_fd)
 2. [MT] twe_surface_set_sync_fd
 3. [MT] g_source_attach  start<- It takes too long time (abnormal)
  [MT] : blocking wait at g_source_attach()
 4. [TWE] fence wait source dispatch. but there is no acquirable buffer in tbm_queue.
 5. [TWE] fence wait source finalize.
 6. [MT] g_source_attach  done.
 7. [MT] tbm_surface_queue_enqueue. but it will be not commit.
 8. [MT] call can_dequeue_timeout
  -> The release event does not come because
    the previous buffer was not wl_surface_commit.
 9. [MT] 10s later, timeout and force flush occured.

Change-Id: I8e7b57c0f5b78caa333410ef75e5bd8ce50d7173
Signed-off-by: Joonbum Ko <joonbum.ko@samsung.com>
src/tpl_wayland_egl_thread.c

index 5bff04f..6cd5c58 100755 (executable)
@@ -147,6 +147,11 @@ struct _twe_wl_surf_source {
        tpl_bool_t use_sync_fence;
 
        int post_interval;
+
+       struct {
+               tbm_surface_h tbm_surface;
+               int sync_fd;
+       } sync_info;
 };
 
 struct _twe_wl_buffer_info {
@@ -214,6 +219,10 @@ _twe_surface_wait_vblank(twe_wl_surf_source *surf_source);
 static struct tizen_private *
 _get_tizen_private(struct wl_egl_window *);
 
+tpl_result_t
+_twe_thread_fence_wait_source_attach(twe_wl_surf_source *surf_source,
+                                                                        tbm_surface_h tbm_surface, tbm_fd sync_fd);
+
 static gpointer
 _twe_thread_loop(gpointer data)
 {
@@ -1842,14 +1851,12 @@ __cb_tbm_queue_acquirable_callback(tbm_surface_queue_h surface_queue,
 
        g_mutex_lock(&surf_source->surf_mutex);
 
-       if (!surf_source->use_sync_fence) {
-               ret = write(surf_source->event_fd, &value, sizeof(uint64_t));
-               if (ret == -1) {
-                       TPL_ERR("failed to send acquirable event. twe_wl_surf_source(%p)",
-                                       surf_source);
-                       g_mutex_unlock(&surf_source->surf_mutex);
-                       return;
-               }
+       ret = write(surf_source->event_fd, &value, sizeof(uint64_t));
+       if (ret == -1) {
+               TPL_ERR("failed to send acquirable event. twe_wl_surf_source(%p)",
+                               surf_source);
+               g_mutex_unlock(&surf_source->surf_mutex);
+               return;
        }
 
        g_mutex_unlock(&surf_source->surf_mutex);
@@ -2466,8 +2473,25 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                        res = TPL_ERROR_INVALID_CONNECTION;
                }
 
-               _twe_thread_wl_surface_acquire_and_commit(surf_source);
+               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;
 
+                       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) ret(%d)",
+                                               sync_fd, res);
+                               surf_source->use_sync_fence = TPL_FALSE;
+                       }
+
+                       surf_source->sync_info.sync_fd = -1;
+                       surf_source->sync_info.tbm_surface = NULL;
+               } else {
+                       _twe_thread_wl_surface_acquire_and_commit(surf_source);
+               }
        }
 
        if (cond && !(cond & G_IO_IN)) {
@@ -2919,6 +2943,9 @@ 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;
@@ -3445,12 +3472,13 @@ _twe_thread_fence_wait_source_attach(twe_wl_surf_source *surf_source,
                                                                                        G_IO_IN);
 
        /* When waiting is over, it will be removed from the list. */
-       g_mutex_lock(&surf_source->surf_mutex);
        __tpl_list_push_back(surf_source->fence_waiting_sources, (void *)wait_source);
-       g_mutex_unlock(&surf_source->surf_mutex);
 
        g_source_attach(&wait_source->gsource, g_main_loop_get_context(_twe_ctx->twe_loop));
 
+       TPL_LOG_T(BACKEND, "fence_wait_source(%p) attached | tbm_surface(%p) fence_fd(%d)",
+                         wait_source, tbm_surface, sync_fd);
+
        return TPL_ERROR_NONE;
 }
 
@@ -3471,15 +3499,13 @@ twe_surface_set_sync_fd(twe_surface_h twe_surface,
                return TPL_ERROR_INVALID_PARAMETER;
        }
 
-       ret = _twe_thread_fence_wait_source_attach(surf_source, tbm_surface, sync_fd);
-       if (ret != TPL_ERROR_NONE) {
-               TPL_ERR("Failed to attach source with fence_fd(%d) ret(%d)",
-                               sync_fd, ret);
-               surf_source->use_sync_fence = TPL_FALSE;
-               return ret;
-       }
-
+       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);
 
        return ret;
 }