wayland_egl_thread: Implemented the function waiting sync_fence to render done. 74/228574/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Wed, 18 Mar 2020 09:01:00 +0000 (18:01 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Fri, 20 Mar 2020 05:37:42 +0000 (14:37 +0900)
 - In the case of mesa, tbm_surface with guaranteed 'render done'
  is not enqueued.
 - To compensate for this, fence fd is delivered to the platform side
  from mesa driver, but libtpl-egl did not have the function to use it.

 - The added function ensures the following operation.
  1. When __tpl_wl_egl_surface_enqueue_buffer is called,
   if sync_fd (!=-1) is received.
  2. This is the case when the buffer is not complete.
  3. Create gsource to poll sync_fd in twe_thread.
  4. Attach it to twe_thread. (poll starting)
  5. If G_IO_IN occurs in sync_fd, it is known as render_done
   and acquire_and_commit is performed. (twe_thread)
  6. After completing just one role, the created source will be removed.

Change-Id: I16558f700df98afd372bbc83613a8633062953c0
Signed-off-by: Joonbum Ko <joonbum.ko@samsung.com>
.vscode/settings.json [deleted file]
src/tpl_wayland_egl_thread.c
src/tpl_wayland_egl_thread.h
src/tpl_wl_egl_thread.c

diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644 (file)
index d10fd7e..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-{
-    "files.associations": {
-        "tpl_utils.h": "c"
-    }
-}
\ No newline at end of file
index e8b68acd2780f66cc051573703b69fb92a326d76..8abbd6d5b39576914263f64ee923639f28a70406 100755 (executable)
@@ -1712,8 +1712,7 @@ __cb_tbm_queue_acquirable_callback(tbm_surface_queue_h surface_queue,
        uint64_t value = 1;
        int ret;
 
-       if (!surf_source->disp_source->is_vulkan_dpy
-               || !surf_source->use_sync_fence) {
+       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)",
@@ -3188,15 +3187,117 @@ twe_surface_commit_without_enqueue(twe_surface_h twe_surface,
        g_mutex_unlock(&surf_source->surf_mutex);
 }
 
+static gboolean
+_twe_thread_fence_wait_source_dispatch(GSource *source, GSourceFunc cb, gpointer data)
+{
+       twe_fence_wait_source *wait_source = (twe_fence_wait_source *)source;
+       twe_wl_surf_source *surf_source = wait_source->surf_source;
+       tbm_surface_h tbm_surface = wait_source->tbm_surface;
+       GIOCondition cond = g_source_query_unix_fd(source, wait_source->tag);
+
+       if (cond & G_IO_IN) {
+               TPL_LOG_T(BACKEND, "[RENDER DONE] wait_source(%p) tbm_surface(%p) fence_fd(%d)",
+                                 wait_source, tbm_surface, wait_source->fence_fd);
+       } else {
+               /* When some io errors occur, it is not considered as a critical error.
+                * There may be problems with the screen, but it does not affect the operation. */
+               TPL_WARN("Invalid GIOCondition occured. fd(%d) cond(%d)",
+                                wait_source->fence_fd, cond);
+       }
+
+       /* Since this source is going to be removed, acquire_and_commit must be
+        * executed even in a situation other than G_IO_IN.
+        * Nevertheless, there may be room for improvement. */
+       _twe_thread_wl_surface_acquire_and_commit(surf_source);
+       tbm_surface_internal_unref(tbm_surface);
+
+       /* This source is used only once and does not allow reuse.
+        * So finalize will be executed immediately. */
+       g_source_remove_unix_fd(&wait_source->gsource, wait_source->tag);
+       g_source_destroy(&wait_source->gsource);
+       g_source_unref(&wait_source->gsource);
+
+       return G_SOURCE_REMOVE;
+}
+
+static void
+_twe_thread_fence_wait_source_finalize(GSource *source)
+{
+       twe_fence_wait_source *wait_source = (twe_fence_wait_source *)source;
+
+       TPL_DEBUG("[FINALIZE] wait_source(%p) fence_fd(%d)",
+                         wait_source, wait_source->fence_fd);
+
+       close(wait_source->fence_fd);
+
+       wait_source->fence_fd = -1;
+       wait_source->surf_source = NULL;
+       wait_source->tbm_surface = NULL;
+       wait_source->tag = NULL;
+}
+
+static GSourceFuncs _twe_fence_wait_source_funcs = {
+       .prepare = NULL,
+       .check = NULL,
+       .dispatch = _twe_thread_fence_wait_source_dispatch,
+       .finalize = _twe_thread_fence_wait_source_finalize,
+};
+
+tpl_result_t
+_twe_thread_fence_wait_source_attach(twe_wl_surf_source *surf_source,
+                                                                        tbm_surface_h tbm_surface, tbm_fd sync_fd)
+{
+       twe_fence_wait_source *wait_source = NULL;
+
+       wait_source = (twe_fence_wait_source *)g_source_new(&_twe_fence_wait_source_funcs,
+                                                                                       sizeof(twe_fence_wait_source));
+       if (!wait_source) {
+               TPL_ERR("[WAIT_SOURCE] Failed to create GSource");
+               return TPL_ERROR_OUT_OF_MEMORY;
+       }
+
+       tbm_surface_internal_ref(tbm_surface);
+
+       wait_source->fence_fd = sync_fd;
+       wait_source->surf_source = surf_source;
+       wait_source->tbm_surface = tbm_surface;
+
+       wait_source->tag = g_source_add_unix_fd(&wait_source->gsource,
+                                                                                       wait_source->fence_fd,
+                                                                                       G_IO_IN);
+       g_source_attach(&wait_source->gsource, g_main_loop_get_context(_twe_ctx->twe_loop));
+
+       return TPL_ERROR_NONE;
+}
+
 tpl_result_t
 twe_surface_set_sync_fd(twe_surface_h twe_surface,
                                                tbm_surface_h tbm_surface, tbm_fd sync_fd)
 {
-       TPL_IGNORE(twe_surface);
-       TPL_IGNORE(tbm_surface);
-       TPL_IGNORE(sync_fd);
+       twe_wl_surf_source *surf_source = (twe_wl_surf_source *)twe_surface;
+       tpl_result_t ret = TPL_ERROR_NONE;
 
-       return TPL_ERROR_NONE;
+       if (!surf_source) {
+               TPL_ERR("Invalid parameter. twe_surface(%p)", twe_surface);
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!tbm_surface || !tbm_surface_internal_is_valid(tbm_surface)) {
+               TPL_ERR("Invalid parameter. tbm_surface(%p)", tbm_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;
+       }
+
+       surf_source->use_sync_fence = TPL_TRUE;
+
+       return ret;
 }
 
 tbm_fd
index 067def19fdaff6288fe33532a190bbdded7a197b..3a1730503cd12fc8ecdd7e6391a69f8e1a38447e 100755 (executable)
@@ -90,7 +90,7 @@ twe_surface_set_damage_region(tbm_surface_h tbm_surface,
 
 tpl_result_t
 twe_surface_set_sync_fd(twe_surface_h twe_surface,
-                                               tbm_surface_h tbm_surface, tbm_fd wait_fd);
+                                               tbm_surface_h tbm_surface, tbm_fd sync_fd);
 
 tbm_fd
 twe_surface_create_sync_fd(tbm_surface_h tbm_surface);
index 92c7ef0402bf9a1005d0d0a64c034959ab958a77..e20801a4a3899552a87a3244a83afa25091c696f 100755 (executable)
@@ -583,8 +583,12 @@ __tpl_wl_egl_surface_enqueue_buffer(tpl_surface_t *surface,
        }
 
        if (sync_fence != -1) {
-               tbm_sync_fence_wait(sync_fence, -1);
-               close(sync_fence);
+               ret = twe_surface_set_sync_fd(wayland_egl_surface->twe_surface,
+                                                                         tbm_surface, sync_fence);
+               if (ret != TPL_ERROR_NONE) {
+                       TPL_WARN("Failed to set sync fd (%d). But it will continue.",
+                                        sync_fence);
+               }
        }
 
        tsq_err = tbm_surface_queue_enqueue(wayland_egl_surface->tbm_queue,