tpl_wayland_egl_thread: Implemented present modes to support vulkan wsi. 69/161969/2
authorjoonbum.ko <joonbum.ko@samsung.com>
Fri, 13 Oct 2017 08:45:06 +0000 (17:45 +0900)
committerjoonbum.ko <joonbum.ko@samsung.com>
Tue, 28 Nov 2017 10:46:58 +0000 (19:46 +0900)
 - Added _twe_surface_wait_vblank internal function to be called properly according to present mode.
 - Added _twe_thread_wl_vk_surface_commit internal function for wl_surface of vulkan.
 - Added a list of vblank_waiting_buffers to support FIFO and FIFO_RELAXED modes.

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

index 921cb71..283f720 100644 (file)
@@ -103,6 +103,8 @@ struct _twe_wl_surf_source {
        tpl_object_t obj; /* for mutex lock */
        tpl_list_t *committed_buffers;
        tpl_list_t *in_use_buffers;
+       tpl_list_t *vblank_waiting_buffers; /* for FIFO/FIFO_RELAXED modes */
+       tbm_surface_h draw_done_buffer; /* for MAILBOX mode */
        tdm_client_vblank *vblank;
        tpl_bool_t vblank_done;
        tpl_bool_t is_destroying;
@@ -1300,8 +1302,9 @@ __cb_buffer_release_callback(void *data, struct wl_proxy *wl_buffer)
                                          buf_info->wl_buffer, tbm_surface,
                                          tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
                        tbm_surface_internal_unref(tbm_surface);
-               }
 
+                       return;
+               }
        } else {
                TPL_ERR("Invalid parameter | tbm_surface(%p)", tbm_surface);
        }
@@ -1534,11 +1537,15 @@ static void __cb_tbm_queue_trace_callback(tbm_surface_queue_h tbm_queue,
 }
 
 static void
+_twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source,
+                                                                tbm_surface_h tbm_surface);
+static void
 __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error,
                                                        unsigned int sequence, unsigned int tv_sec,
                                                        unsigned int tv_usec, void *user_data)
 {
        twe_wl_surf_source *surf_source = (twe_wl_surf_source *)user_data;
+       twe_wl_disp_source *disp_source = NULL;
 
        if (!surf_source) {
                TPL_ERR("Invalid parameter. user_data(%p)", user_data);
@@ -1550,18 +1557,111 @@ __cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error,
                return;
        }
 
+       disp_source = surf_source->disp_source;
+
        surf_source->vblank_done = TPL_TRUE;
-       _twe_thread_wl_surface_acquire_and_commit(surf_source);
+
+       if (!disp_source->is_vulkan_dpy)
+               _twe_thread_wl_surface_acquire_and_commit(surf_source);
+       else {
+               switch (surf_source->swapchain_properties.present_mode) {
+               case TPL_DISPLAY_PRESENT_MODE_MAILBOX:
+                       if (surf_source->draw_done_buffer) {
+                               _twe_thread_wl_vk_surface_commit(surf_source,
+                                                                                                surf_source->draw_done_buffer);
+                               surf_source->draw_done_buffer = NULL;
+                       }
+                       break;
+
+               case TPL_DISPLAY_PRESENT_MODE_FIFO:
+               case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED:
+                       if (surf_source->vblank_waiting_buffers) {
+                               tbm_surface_h tbm_surface = NULL;
+                               tbm_surface = (tbm_surface_h)__tpl_list_pop_front(
+                                                                       surf_source->vblank_waiting_buffers,
+                                                                       NULL);
+                               if (tbm_surface)
+                                       _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface);
+                       }
+                       break;
+               }
+       }
 }
 
 static tdm_client_vblank*
 _twe_surface_create_vblank(tdm_client *tdm_client);
 
+static tpl_result_t
+_twe_surface_wait_vblank(twe_wl_surf_source *surf_source)
+{
+       tdm_error tdm_err = TDM_ERROR_NONE;
+
+       if (!_twe_ctx->tdm_source) {
+               TPL_WARN("tdm_vblank feature is disabled.");
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       if (!surf_source->vblank) {
+               surf_source->vblank =
+                       _twe_surface_create_vblank(_twe_ctx->tdm_source->tdm_client);
+               if (!surf_source->vblank) {
+                       TPL_WARN("Failed to create vblank. surf_source(%p)",
+                                        surf_source);
+                       return TPL_ERROR_OUT_OF_MEMORY;
+               }
+       }
+
+       tdm_err = tdm_client_vblank_wait(surf_source->vblank,
+                       1, /* TODO: interval */
+                       __cb_tdm_client_wait_vblank,
+                       (void *)surf_source);
+
+       if (tdm_err == TDM_ERROR_NONE)
+               surf_source->vblank_done = TPL_FALSE;
+       else {
+               TPL_ERR("Failed to tdm_client_vblank_wait. tdm_err(%d)", tdm_err);
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       return TPL_ERROR_NONE;
+}
+
+static void
+_twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source,
+                                                                tbm_surface_h tbm_surface)
+{
+       twe_wl_buffer_info *buf_info = NULL;
+       struct wl_surface *wl_surface = surf_source->surf;
+
+       tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
+                                                                          (void **)&buf_info);
+       if (!buf_info) {
+               TPL_ERR("Failed to get wl_buffer_info from tbm_surface(%p)",
+                               tbm_surface);
+               return;
+       }
+
+       wl_surface_attach(wl_surface, (void *)buf_info->wl_buffer,
+                                         0, 0);
+
+       wl_surface_damage(wl_surface, 0, 0,
+                                         surf_source->swapchain_properties.width,
+                                         surf_source->swapchain_properties.height);
+       wl_surface_commit(wl_surface);
+
+       if (surf_source->swapchain_properties.present_mode
+                       == TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED) {
+               if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+                       TPL_ERR("Failed to set wait vblank");
+       }
+}
+
 static void
 _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source,
                                                          tbm_surface_h tbm_surface)
 {
        twe_wl_buffer_info *buf_info = NULL;
+       twe_wl_disp_source *disp_source = surf_source->disp_source;
        struct wl_surface *wl_surface = surf_source->surf;
        struct wl_egl_window *wl_egl_window = surf_source->wl_egl_window;
        uint32_t version;
@@ -1578,7 +1678,7 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source,
 
        if (buf_info->w_rotated == TPL_TRUE) {
                wayland_tbm_client_set_buffer_transform(
-                               surf_source->disp_source->wl_tbm_client,
+                               disp_source->wl_tbm_client,
                                (void *)buf_info->wl_buffer,
                                buf_info->w_transform);
                buf_info->w_rotated = TPL_FALSE;
@@ -1637,27 +1737,9 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source,
                          buf_info->wl_buffer, tbm_surface,
                          tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
 
-       if (_twe_ctx->tdm_source && !surf_source->vblank) {
-               surf_source->vblank =
-                       _twe_surface_create_vblank(_twe_ctx->tdm_source->tdm_client);
-               if (!surf_source->vblank) {
-                       TPL_WARN("Failed to create vblank. surf_source(%p)",
-                                        surf_source);
-               }
-       }
+       if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+               TPL_ERR("Failed to set wait vblank.");
 
-       if (_twe_ctx->tdm_source && surf_source->vblank) {
-               tdm_error tdm_err = TDM_ERROR_NONE;
-               tdm_err = tdm_client_vblank_wait(surf_source->vblank,
-                                                                                1, /* TODO: interval */
-                                                                                __cb_tdm_client_wait_vblank,
-                                                                                (void *)surf_source);
-
-               if (tdm_err == TDM_ERROR_NONE)
-                       surf_source->vblank_done = TPL_FALSE;
-               else
-                       TPL_ERR("Failed to tdm_client_vblank_wait. tdm_err(%d)", tdm_err);
-       }
 
        if (surf_source->committed_buffers) {
                __tpl_list_push_back(surf_source->committed_buffers, tbm_surface);
@@ -1677,6 +1759,7 @@ _twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source,
 static void
 _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source)
 {
+       twe_wl_disp_source *disp_source = surf_source->disp_source;
        tbm_surface_h tbm_surface = NULL;
        tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
        twe_wl_buffer_info *buf_info = NULL;
@@ -1690,33 +1773,81 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source)
                return;
        }
 
+       if (!disp_source->is_vulkan_dpy && !surf_source->vblank_done) {
+               TPL_LOG_T("WL_EGL", "[ACQ_skip] It will be acquired next vblank.");
+               TPL_OBJECT_UNLOCK(&surf_source->obj);
+               return;
+       }
+
        if (tbm_surface_queue_can_acquire(surf_source->tbm_queue, 0)) {
-               if (surf_source->vblank_done == TPL_TRUE) {
-                       tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface);
-                       if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
-                               TPL_ERR("Failed to acquire from tbm_queue(%p)",
-                                               surf_source->tbm_queue);
-                               TPL_OBJECT_UNLOCK(&surf_source->obj);
-                               return;
-                       }
+               tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface);
+               if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
+                       TPL_ERR("Failed to acquire from tbm_queue(%p)",
+                                       surf_source->tbm_queue);
+                       TPL_OBJECT_UNLOCK(&surf_source->obj);
+                       return;
+               }
 
-                       tbm_surface_internal_ref(tbm_surface);
+               tbm_surface_internal_ref(tbm_surface);
 
-                       tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
-                                                                                          (void **)&buf_info);
-                       if (buf_info && buf_info->fence_waiting_thread) {
-                               g_thread_join(buf_info->fence_waiting_thread);
-                               buf_info->fence_waiting_thread = NULL;
-                       }
+               tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
+                                                                                  (void **)&buf_info);
+               if (buf_info && buf_info->fence_waiting_thread) {
+                       g_thread_join(buf_info->fence_waiting_thread);
+                       buf_info->fence_waiting_thread = NULL;
+               }
 
+               if (!disp_source->is_vulkan_dpy) { /* wayland_egl */
                        TPL_LOG_T("WL_EGL", "[ACQ] tbm_surface(%p) bo(%d)",
-                                         tbm_surface,
-                                         tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
+                                       tbm_surface,
+                                       tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
 
                        _twe_thread_wl_surface_commit(surf_source, tbm_surface);
-
-               } else {
-                       TPL_LOG_T("WL_EGL", "[ACQ_skip] It will be acquired next vblank.");
+               } else { /* wayland_vulkan */
+                       switch (surf_source->swapchain_properties.present_mode) {
+                       case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE:
+                               _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface);
+                               break;
+
+                       case TPL_DISPLAY_PRESENT_MODE_MAILBOX:
+                               if (surf_source->draw_done_buffer) {
+                                       tbm_surface_internal_unref(surf_source->draw_done_buffer);
+                                       tbm_surface_queue_release(surf_source->tbm_queue,
+                                                                                         surf_source->draw_done_buffer);
+                               }
+
+                               surf_source->draw_done_buffer = tbm_surface;
+
+                               if (surf_source->vblank_done) {
+                                       if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+                                               TPL_ERR("Failed to set wait vblank");
+                               }
+                               break;
+
+                       case TPL_DISPLAY_PRESENT_MODE_FIFO:
+                               if (surf_source->vblank_waiting_buffers) {
+                                       __tpl_list_push_back(surf_source->vblank_waiting_buffers,
+                                                                                (void *)tbm_surface);
+                                       if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+                                               TPL_ERR("Failed to set wait vblank");
+                               } else {
+                                       TPL_ERR("Invalid list. vblank_waiting_buffers is NULL.");
+                               }
+                               break;
+
+                       case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED:
+                               if (surf_source->vblank_done) {
+                                       _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface);
+                               } else {
+                                       if (surf_source->vblank_waiting_buffers) {
+                                               __tpl_list_push_back(surf_source->vblank_waiting_buffers,
+                                                                                        (void *)tbm_surface);
+                                       } else {
+                                               TPL_ERR("Invalid list. vblank_waiting_buffers is NULL.");
+                                       }
+                               }
+                               break;
+                       }
                }
        }
 
@@ -1726,7 +1857,8 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source)
 static gboolean
 _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data)
 {
-       twe_wl_surf_source *wl_surf_source = (twe_wl_surf_source *)source;
+       twe_wl_surf_source *surf_source = (twe_wl_surf_source *)source;
+       twe_wl_disp_source *disp_source = surf_source->disp_source;
        GIOCondition cond;
 
        if (g_source_is_destroyed(source)) {
@@ -1734,18 +1866,19 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data)
                return G_SOURCE_REMOVE;
        }
 
-       cond = g_source_query_unix_fd(source, wl_surf_source->tag);
+       cond = g_source_query_unix_fd(source, surf_source->tag);
 
        if (cond & G_IO_IN) {
                ssize_t s;
                uint64_t u;
 
-               s = read(wl_surf_source->event_fd, &u, sizeof(uint64_t));
+               s = read(surf_source->event_fd, &u, sizeof(uint64_t));
                if (s != sizeof(uint64_t))
                        TPL_ERR("Failed to read from event_fd(%d)",
-                                       wl_surf_source->event_fd);
+                                       surf_source->event_fd);
 
-               _twe_thread_wl_surface_acquire_and_commit(wl_surf_source);
+               if (!disp_source->is_vulkan_dpy)
+                       _twe_thread_wl_surface_acquire_and_commit(surf_source);
        }
 
        return G_SOURCE_CONTINUE;
@@ -2070,6 +2203,10 @@ twe_surface_add(twe_thread* thread,
        source->rotate_cb = NULL;
        source->format = format;
 
+       /* for vulkan swapchain */
+       source->vblank_waiting_buffers = NULL;
+       source->draw_done_buffer = NULL;
+
        __tpl_object_init(&source->obj, TPL_OBJECT_SURFACE, NULL);
 
        if (!disp_source->is_vulkan_dpy) {