From ecf5c18de6ac408bd3415e14ae7cd77b0eb4ac6e Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 13 Oct 2017 17:45:06 +0900 Subject: [PATCH] tpl_wayland_egl_thread: Implemented present modes to support vulkan wsi. - 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 --- src/tpl_wayland_egl_thread.c | 233 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 185 insertions(+), 48 deletions(-) diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index 921cb71..283f720 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -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) { -- 2.7.4