From 5646c5705fda8957a21c745d6cbba6b93701c5c0 Mon Sep 17 00:00:00 2001 From: "joonbum.ko" Date: Fri, 20 Oct 2017 15:04:25 +0900 Subject: [PATCH] tpl_wl_vk_thread: Integrated wl_vk_thread backend. Change-Id: Ie4491b28750f5639da02f474a3e5fdb742c6f07b Signed-off-by: joonbum.ko --- src/Makefile.am | 1 + src/tpl.c | 6 + src/tpl.h | 1 + src/tpl_internal.h | 2 + src/tpl_wayland_egl_thread.c | 43 ++- src/tpl_wl_vk_thread.c | 616 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 662 insertions(+), 7 deletions(-) create mode 100644 src/tpl_wl_vk_thread.c diff --git a/src/Makefile.am b/src/Makefile.am index d29509f..af61301 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -26,6 +26,7 @@ libtpl_egl_la_SOURCES += tpl_wayland_egl.c \ tpl_wl_egl_thread.c \ tpl_wayland_egl_thread.c \ tpl_wayland_vk_wsi.c \ + tpl_wl_vk_thread.c \ tpl_worker_thread.c \ wayland-vulkan/wayland-vulkan-protocol.c endif diff --git a/src/tpl.c b/src/tpl.c index 0f75d5f..7b0a213 100644 --- a/src/tpl.c +++ b/src/tpl.c @@ -301,6 +301,9 @@ __tpl_display_init_backend(tpl_display_t *display, tpl_backend_type_t type) case TPL_BACKEND_WAYLAND_VULKAN_WSI: __tpl_display_init_backend_wayland_vk_wsi(&display->backend); break; + case TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD: + __tpl_display_init_backend_wl_vk_wsi_thread(&display->backend); + break; case TPL_BACKEND_TBM: __tpl_display_init_backend_tbm(&display->backend, type); break; @@ -343,6 +346,9 @@ __tpl_surface_init_backend(tpl_surface_t *surface, tpl_backend_type_t type) case TPL_BACKEND_WAYLAND_VULKAN_WSI: __tpl_surface_init_backend_wayland_vk_wsi(&surface->backend); break; + case TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD: + __tpl_surface_init_backend_wl_vk_wsi_thread(&surface->backend); + break; case TPL_BACKEND_TBM: __tpl_surface_init_backend_tbm(&surface->backend, type); break; diff --git a/src/tpl.h b/src/tpl.h index ff20ff4..0ebf067 100644 --- a/src/tpl.h +++ b/src/tpl.h @@ -194,6 +194,7 @@ typedef enum { TPL_BACKEND_X11_DRI3, TPL_BACKEND_TBM, TPL_BACKEND_WAYLAND_VULKAN_WSI, + TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD, TPL_BACKEND_TBM_VULKAN_WSI, TPL_BACKEND_COUNT, TPL_BACKEND_MAX diff --git a/src/tpl_internal.h b/src/tpl_internal.h index 2fa642f..56552a4 100644 --- a/src/tpl_internal.h +++ b/src/tpl_internal.h @@ -220,6 +220,7 @@ void __tpl_display_init_backend_tbm(tpl_display_backend_t *backend, void __tpl_display_init_backend_wayland_egl(tpl_display_backend_t *backend); void __tpl_display_init_backend_wl_egl_thread(tpl_display_backend_t *backend); void __tpl_display_init_backend_wayland_vk_wsi(tpl_display_backend_t *backend); +void __tpl_display_init_backend_wl_vk_wsi_thread(tpl_display_backend_t *backend); void __tpl_display_init_backend_x11_dri2(tpl_display_backend_t *backend); void __tpl_display_init_backend_x11_dri3(tpl_display_backend_t *backend); void __tpl_surface_init_backend_gbm(tpl_surface_backend_t *backend); @@ -228,6 +229,7 @@ void __tpl_surface_init_backend_tbm(tpl_surface_backend_t *backend, void __tpl_surface_init_backend_wayland_egl(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_wl_egl_thread(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_wayland_vk_wsi(tpl_surface_backend_t *backend); +void __tpl_surface_init_backend_wl_vk_wsi_thread(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_x11_dri2(tpl_surface_backend_t *backend); void __tpl_surface_init_backend_x11_dri3(tpl_surface_backend_t *backend); diff --git a/src/tpl_wayland_egl_thread.c b/src/tpl_wayland_egl_thread.c index ad49932..7f12646 100644 --- a/src/tpl_wayland_egl_thread.c +++ b/src/tpl_wayland_egl_thread.c @@ -861,8 +861,6 @@ _twe_display_vk_init(twe_wl_disp_source *disp_source) NULL); } - TPL_LOG_T("WL_VK", "wl_vk_client(%p) init.", disp_source->wl_vk_client); - fini: if (queue) wl_event_queue_destroy(queue); @@ -950,7 +948,8 @@ twe_display_add(twe_thread* thread, source->gfd.revents = 0; __tpl_object_init(&source->obj, TPL_OBJECT_DISPLAY, NULL); - if (backend == TPL_BACKEND_WAYLAND_VULKAN_WSI) { + if (backend == TPL_BACKEND_WAYLAND_VULKAN_WSI || + backend == TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD) { source->is_vulkan_dpy = TPL_TRUE; source->surface_capabilities.min_buffer = 2; source->surface_capabilities.max_buffer = VK_CLIENT_QUEUE_SIZE; @@ -1658,6 +1657,10 @@ _twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source, buf_info->sync_timestamp++; + TPL_LOG_T("WL_VK", "[COMMIT] wl_buffer(%p) tbm_surface(%p) bo(%d)", + buf_info->wl_buffer, tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + if (surf_source->swapchain_properties.present_mode == TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED) { if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE) @@ -1801,6 +1804,9 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) return; } + TRACE_ASYNC_END((int)tbm_surface, "DRAWING BO(%d)", + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + tbm_surface_internal_ref(tbm_surface); tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO, @@ -1824,9 +1830,16 @@ _twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source) case TPL_DISPLAY_PRESENT_MODE_MAILBOX: if (surf_source->draw_done_buffer) { + g_mutex_lock(&surf_source->free_queue_mutex); + TPL_LOG_T("WL_VK", "[SKIP] tbm_surface(%p) bo(%d)", + tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo( + tbm_surface, 0))); tbm_surface_internal_unref(surf_source->draw_done_buffer); tbm_surface_queue_release(surf_source->tbm_queue, surf_source->draw_done_buffer); + g_cond_signal(&surf_source->free_queue_cond); + g_mutex_unlock(&surf_source->free_queue_mutex); } surf_source->draw_done_buffer = tbm_surface; @@ -1871,7 +1884,6 @@ static gboolean _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data) { 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)) { @@ -1890,8 +1902,7 @@ _twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data) TPL_ERR("Failed to read from event_fd(%d)", surf_source->event_fd); - if (!disp_source->is_vulkan_dpy) - _twe_thread_wl_surface_acquire_and_commit(surf_source); + _twe_thread_wl_surface_acquire_and_commit(surf_source); } return G_SOURCE_CONTINUE; @@ -2355,6 +2366,24 @@ twe_surface_create_swapchain(twe_surface_h twe_surface, return TPL_ERROR_OUT_OF_MEMORY; } + if (tbm_surface_queue_add_trace_cb(surf_source->tbm_queue, + __cb_tbm_queue_trace_callback, + (void *)surf_source) != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to register trace callback to tbm_surface_queue(%p)", + surf_source->tbm_queue); + tbm_surface_queue_destroy(surf_source->tbm_queue); + return TPL_ERROR_INVALID_OPERATION; + } + + if (tbm_surface_queue_add_acquirable_cb(surf_source->tbm_queue, + __cb_tbm_queue_acquirable_callback, + (void *)surf_source) != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to register acquirable callback to tbm_surface_queue(%p)", + surf_source->tbm_queue); + tbm_surface_queue_destroy(surf_source->tbm_queue); + return TPL_ERROR_INVALID_OPERATION; + } + surf_source->format = format; surf_source->swapchain_properties.width = width; surf_source->swapchain_properties.height = height; @@ -2365,7 +2394,7 @@ twe_surface_create_swapchain(twe_surface_h twe_surface, twe_surface, surf_source->tbm_queue); TPL_LOG_T("WL_VK", "[SWAPCHAIN_CREATE][2/2] w(%d) h(%d) f(%d) p(%d) b_cnt(%d)", - width, height, present_mode, buffer_count); + width, height, format, present_mode, buffer_count); return TPL_ERROR_NONE; } diff --git a/src/tpl_wl_vk_thread.c b/src/tpl_wl_vk_thread.c new file mode 100644 index 0000000..fd518bf --- /dev/null +++ b/src/tpl_wl_vk_thread.c @@ -0,0 +1,616 @@ +#define inline __inline__ +#undef inline + +#include "tpl_internal.h" + +#include +#include +#include + +#include + +#include "tpl_wayland_egl_thread.h" + +typedef struct _tpl_wayland_vk_wsi_display tpl_wayland_vk_wsi_display_t; +typedef struct _tpl_wayland_vk_wsi_surface tpl_wayland_vk_wsi_surface_t; +typedef struct _tpl_wayland_vk_wsi_buffer tpl_wayland_vk_wsi_buffer_t; + +struct _tpl_wayland_vk_wsi_display { + twe_thread *wl_thread; + twe_display_h twe_display; +}; + +struct _tpl_wayland_vk_wsi_surface { + twe_surface_h twe_surface; + tbm_surface_queue_h tbm_queue; + int buffer_count; +}; + +static tpl_result_t __tpl_wl_vk_wsi_surface_destroy_swapchain( + tpl_surface_t *surface); + +static TPL_INLINE tpl_bool_t +__tpl_wl_vk_wsi_display_is_wl_display(tpl_handle_t native_dpy) +{ + if (!native_dpy) return TPL_FALSE; + + if (twe_check_native_handle_is_wl_display(native_dpy)) + return TPL_TRUE; + + return TPL_FALSE; +} + +static tpl_result_t +__tpl_wl_vk_wsi_display_init(tpl_display_t *display) +{ + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; + + TPL_ASSERT(display); + + /* Do not allow default display in wayland */ + if (!display->native_handle) { + TPL_ERR("Invalid native handle for display."); + return TPL_ERROR_INVALID_PARAMETER; + } + + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *) calloc(1, + sizeof(tpl_wayland_vk_wsi_display_t)); + if (!wayland_vk_wsi_display) { + TPL_ERR("Failed to allocate memory for new tpl_wayland_vk_wsi_display_t."); + return TPL_ERROR_OUT_OF_MEMORY; + } + + display->backend.data = wayland_vk_wsi_display; + + if (twe_check_native_handle_is_wl_display(display->native_handle)) { + wayland_vk_wsi_display->wl_thread = twe_thread_create(); + if (!wayland_vk_wsi_display->wl_thread) { + TPL_ERR("Failed to create twe_thread."); + goto free_display; + } + + wayland_vk_wsi_display->twe_display = + twe_display_add(wayland_vk_wsi_display->wl_thread, + display->native_handle, + display->backend.type); + if (!wayland_vk_wsi_display->twe_display) { + TPL_ERR("Failed to add native_display(%p) to thread(%p)", + display->native_handle, + wayland_vk_wsi_display->wl_thread); + goto free_display; + } + + } else { + TPL_ERR("Invalid native handle for display."); + goto free_display; + } + + TPL_LOG_T("WL_VK", + "[INIT DISPLAY] wayland_vk_wsi_display(%p) twe_thread(%p) twe_display(%p)", + wayland_vk_wsi_display, + wayland_vk_wsi_display->wl_thread, + wayland_vk_wsi_display->twe_display); + + return TPL_ERROR_NONE; + +free_display: + if (wayland_vk_wsi_display) { + if (wayland_vk_wsi_display->twe_display) + twe_display_del(wayland_vk_wsi_display->twe_display); + if (wayland_vk_wsi_display->wl_thread) + twe_thread_destroy(wayland_vk_wsi_display->wl_thread); + + wayland_vk_wsi_display->wl_thread = NULL; + wayland_vk_wsi_display->twe_display = NULL; + + free(wayland_vk_wsi_display); + display->backend.data = NULL; + } + + return TPL_ERROR_INVALID_OPERATION; +} + +static void +__tpl_wl_vk_wsi_display_fini(tpl_display_t *display) +{ + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display; + + TPL_ASSERT(display); + + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *)display->backend.data; + if (wayland_vk_wsi_display) { + + TPL_LOG_T("WL_VK", + "[FINI] wayland_vk_wsi_display(%p) twe_thread(%p) twe_display(%p)", + wayland_vk_wsi_display, + wayland_vk_wsi_display->wl_thread, + wayland_vk_wsi_display->twe_display); + + if (wayland_vk_wsi_display->twe_display) { + tpl_result_t ret = TPL_ERROR_NONE; + ret = twe_display_del(wayland_vk_wsi_display->twe_display); + if (ret != TPL_ERROR_NONE) + TPL_ERR("Failed to delete twe_display(%p) from twe_thread(%p)", + wayland_vk_wsi_display->twe_display, + wayland_vk_wsi_display->wl_thread); + wayland_vk_wsi_display->twe_display = NULL; + } + + if (wayland_vk_wsi_display->wl_thread) { + twe_thread_destroy(wayland_vk_wsi_display->wl_thread); + wayland_vk_wsi_display->wl_thread = NULL; + } + + free(wayland_vk_wsi_display); + } + display->backend.data = NULL; +} + +static tpl_result_t +__tpl_wl_vk_wsi_display_query_config(tpl_display_t *display, + tpl_surface_type_t surface_type, + int red_size, int green_size, + int blue_size, int alpha_size, + int color_depth, int *native_visual_id, + tpl_bool_t *is_slow) +{ + TPL_ASSERT(display); + + if (surface_type == TPL_SURFACE_TYPE_WINDOW && red_size == 8 && + green_size == 8 && blue_size == 8 && + (color_depth == 32 || color_depth == 24)) { + + if (alpha_size == 8) { + if (native_visual_id) *native_visual_id = TBM_FORMAT_ARGB8888; + if (is_slow) *is_slow = TPL_FALSE; + return TPL_ERROR_NONE; + } + if (alpha_size == 0) { + if (native_visual_id) *native_visual_id = TBM_FORMAT_XRGB8888; + if (is_slow) *is_slow = TPL_FALSE; + return TPL_ERROR_NONE; + } + } + + return TPL_ERROR_INVALID_PARAMETER; +} + +static tpl_result_t +__tpl_wl_vk_wsi_display_filter_config(tpl_display_t *display, + int *visual_id, + int alpha_size) +{ + TPL_IGNORE(display); + TPL_IGNORE(visual_id); + TPL_IGNORE(alpha_size); + return TPL_ERROR_NONE; +} + +static tpl_result_t +__tpl_wl_vk_wsi_display_query_window_supported_buffer_count( + tpl_display_t *display, + tpl_handle_t window, int *min, int *max) +{ + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; + tpl_result_t res = TPL_ERROR_NONE; + + TPL_ASSERT(display); + TPL_ASSERT(window); + + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *)display->backend.data; + + if (!wayland_vk_wsi_display) return TPL_ERROR_INVALID_OPERATION; + + res = twe_display_get_buffer_count(wayland_vk_wsi_display->twe_display, + min, max); + if (res != TPL_ERROR_NONE) { + TPL_ERR("Failed to query buffer count. twe_display(%p)", + wayland_vk_wsi_display->twe_display); + return res; + } + + return TPL_ERROR_NONE; +} + +static tpl_result_t +__tpl_wl_vk_wsi_display_query_window_supported_present_modes( + tpl_display_t *display, + tpl_handle_t window, int *modes) +{ + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; + tpl_result_t res = TPL_ERROR_NONE; + + TPL_ASSERT(display); + TPL_ASSERT(window); + + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *)display->backend.data; + + if (!wayland_vk_wsi_display) return TPL_ERROR_INVALID_OPERATION; + + if (modes) { + res = twe_display_get_present_mode(wayland_vk_wsi_display->twe_display, + modes); + if (res != TPL_ERROR_NONE) { + TPL_ERR("Failed to query present modes. twe_display(%p)", + wayland_vk_wsi_display->twe_display); + return res; + } + } + + return TPL_ERROR_NONE; +} + +static tpl_result_t +__tpl_wl_vk_wsi_surface_init(tpl_surface_t *surface) +{ + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; + twe_surface_h twe_surface = NULL; + + TPL_ASSERT(surface); + TPL_ASSERT(surface->type == TPL_SURFACE_TYPE_WINDOW); + TPL_ASSERT(surface->native_handle); + + wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) calloc(1, + sizeof(tpl_wayland_vk_wsi_surface_t)); + if (!wayland_vk_wsi_surface) { + TPL_ERR("Failed to allocate memory for new tpl_wayland_vk_wsi_surface_t."); + return TPL_ERROR_OUT_OF_MEMORY; + } + + wayland_vk_wsi_display = + (tpl_wayland_vk_wsi_display_t *)surface->display->backend.data; + if (!wayland_vk_wsi_display) { + TPL_ERR("Invalid parameter. wayland_vk_wsi_display(%p)", + wayland_vk_wsi_display); + free(wayland_vk_wsi_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + surface->backend.data = (void *)wayland_vk_wsi_surface; + wayland_vk_wsi_surface->tbm_queue = NULL; + + twe_surface = twe_surface_add(wayland_vk_wsi_display->wl_thread, + wayland_vk_wsi_display->twe_display, + surface->native_handle, + surface->format); + if (!twe_surface) { + TPL_ERR("Failed to add native_surface(%p) to thread(%p)", + surface->native_handle, wayland_vk_wsi_display->wl_thread); + free(wayland_vk_wsi_surface); + surface->backend.data = NULL; + return TPL_ERROR_OUT_OF_MEMORY; + } + + wayland_vk_wsi_surface->twe_surface = twe_surface; + + TPL_LOG_T("WL_VK", + "[INIT]tpl_surface(%p) tpl_wayland_vk_wsi_surface(%p) twe_surface(%p)", + surface, wayland_vk_wsi_surface, twe_surface); + + return TPL_ERROR_NONE; +} + +static void +__tpl_wl_vk_wsi_surface_fini(tpl_surface_t *surface) +{ + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; + + TPL_ASSERT(surface); + TPL_ASSERT(surface->display); + + wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data; + if (wayland_vk_wsi_surface == NULL) return; + + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *) + surface->display->backend.data; + if (wayland_vk_wsi_display == NULL) return; + + if (wayland_vk_wsi_surface->tbm_queue) + __tpl_wl_vk_wsi_surface_destroy_swapchain(surface); + + TPL_LOG_T("WL_VK", + "[FINI] wayland_vk_wsi_surface(%p) native_surface(%p) twe_surface(%p)", + wayland_vk_wsi_surface, surface->native_handle, + wayland_vk_wsi_surface->twe_surface); + + if (twe_surface_del(wayland_vk_wsi_surface->twe_surface) + != TPL_ERROR_NONE) { + TPL_ERR("Failed to delete twe_surface(%p) from thread(%p)", + wayland_vk_wsi_surface->twe_surface, + wayland_vk_wsi_display->wl_thread); + } + + wayland_vk_wsi_surface->twe_surface = NULL; + + free(wayland_vk_wsi_surface); + surface->backend.data = NULL; +} + +static tpl_result_t +__tpl_wl_vk_wsi_surface_enqueue_buffer(tpl_surface_t *surface, + tbm_surface_h tbm_surface, + int num_rects, const int *rects, + tbm_fd sync_fence) +{ + + TPL_ASSERT(surface); + TPL_ASSERT(surface->display); + TPL_ASSERT(surface->display->native_handle); + TPL_ASSERT(tbm_surface); + + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = + (tpl_wayland_vk_wsi_surface_t *) surface->backend.data; + tbm_surface_queue_error_e tsq_err; + + if (!tbm_surface_internal_is_valid(tbm_surface)) { + TPL_ERR("Failed to enqueue tbm_surface(%p) Invalid value.", + tbm_surface); + return TPL_ERROR_INVALID_PARAMETER; + } + + if (sync_fence != -1) { + tpl_result_t res = TPL_ERROR_NONE; + res = twe_surface_set_sync_fd(tbm_surface, sync_fence); + if (res != TPL_ERROR_NONE) { + TPL_ERR("Failed to set sync_fd to tbm_surface(%p)", tbm_surface); + tbm_surface_internal_unref(tbm_surface); + return res; + } + } + + tsq_err = tbm_surface_queue_enqueue(wayland_vk_wsi_surface->tbm_queue, + tbm_surface); + if (tsq_err == TBM_SURFACE_QUEUE_ERROR_NONE) { + tbm_surface_internal_unref(tbm_surface); + } else { + TPL_ERR("Failed to enqeueue tbm_surface. | tsq_err = %d", tsq_err); + return TPL_ERROR_INVALID_OPERATION; + } + + TPL_LOG_T("WL_VK", "[ENQ] tbm_surface(%p) bo(%d)", + tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + + return TPL_ERROR_NONE; +} + +static tpl_bool_t +__tpl_wl_vk_wsi_surface_validate(tpl_surface_t *surface) +{ + TPL_ASSERT(surface); + TPL_ASSERT(surface->backend.data); + + return TPL_TRUE; +} + +static tbm_surface_h +__tpl_wl_vk_wsi_surface_dequeue_buffer(tpl_surface_t *surface, + uint64_t timeout_ns, + tbm_fd *sync_fence) +{ + TPL_ASSERT(surface); + TPL_ASSERT(surface->backend.data); + TPL_ASSERT(surface->display); + + tbm_surface_h tbm_surface = NULL; + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = + (tpl_wayland_vk_wsi_surface_t *)surface->backend.data; + tbm_surface_queue_error_e tsq_err = 0; + + if (sync_fence) + *sync_fence = -1; + + if (!tbm_surface_queue_can_dequeue(wayland_vk_wsi_surface->tbm_queue, 0)) { + if (timeout_ns == 0) return NULL; + else { + tpl_result_t res = TPL_ERROR_NONE; + res = twe_surface_wait_dequeueable(wayland_vk_wsi_surface->twe_surface, + timeout_ns); + if (res == TPL_ERROR_TIME_OUT) { + TPL_ERR("Failed to get buffer during timeout_ns(%u)", timeout_ns); + return NULL; + } else if (res != TPL_ERROR_NONE) { + TPL_ERR("Invalid parameter. twe_surface(%p) timeout_ns(%u)", + wayland_vk_wsi_surface->twe_surface, timeout_ns); + return NULL; + } + } + } + + tsq_err = tbm_surface_queue_dequeue(wayland_vk_wsi_surface->tbm_queue, + &tbm_surface); + if (!tbm_surface) { + TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d", + tsq_err); + return NULL; + } + + tbm_surface_internal_ref(tbm_surface); + + if (sync_fence) { + *sync_fence = twe_surface_create_sync_fd(tbm_surface); + } + + TPL_LOG_T("WL_VK", "[DEQ] tbm_surface(%p) bo(%d)", + tbm_surface, + tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0))); + + return tbm_surface; +} + +static tpl_result_t +__tpl_wl_vk_wsi_surface_get_swapchain_buffers(tpl_surface_t *surface, + tbm_surface_h **buffers, + int *buffer_count) +{ + tbm_surface_h buffer = NULL; + tbm_surface_h *swapchain_buffers = NULL; + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; + tbm_surface_queue_error_e tsq_err; + int i, dequeue_count; + tpl_result_t ret = TPL_ERROR_NONE; + + TPL_ASSERT(surface); + TPL_ASSERT(surface->backend.data); + TPL_ASSERT(surface->display); + TPL_ASSERT(buffers); + TPL_ASSERT(buffer_count); + + wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *)surface->backend.data; + swapchain_buffers = (tbm_surface_h *)calloc( + wayland_vk_wsi_surface->buffer_count, sizeof(tbm_surface_h)); + if (!swapchain_buffers) { + TPL_ERR("Failed to allocate memory for buffers."); + return TPL_ERROR_OUT_OF_MEMORY; + } + + for (i = 0 ; i < wayland_vk_wsi_surface->buffer_count ; i++) { + tsq_err = tbm_surface_queue_dequeue(wayland_vk_wsi_surface->tbm_queue, &buffer); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to get tbm_surface from tbm_surface_queue | tsq_err = %d", + tsq_err); + dequeue_count = i; + ret = TPL_ERROR_OUT_OF_MEMORY; + goto get_buffer_fail; + } + swapchain_buffers[i] = buffer; + TPL_DEBUG("swapchain_buffers[%d] = tbm_surface(%p)", i, buffer); + } + + for (i = 0 ; i < wayland_vk_wsi_surface->buffer_count ; i++) { + tsq_err = tbm_surface_queue_release(wayland_vk_wsi_surface->tbm_queue, + swapchain_buffers[i]); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to release tbm_surface. | tsq_err = %d", tsq_err); + ret = TPL_ERROR_INVALID_OPERATION; + goto release_buffer_fail; + } + } + + *buffers = swapchain_buffers; + *buffer_count = wayland_vk_wsi_surface->buffer_count; + return TPL_ERROR_NONE; + +get_buffer_fail: + for (i = 0 ; i < dequeue_count ; i++) { + tsq_err = tbm_surface_queue_release(wayland_vk_wsi_surface->tbm_queue, + swapchain_buffers[i]); + if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) { + TPL_ERR("Failed to release tbm_surface. | tsq_err = %d", tsq_err); + goto release_buffer_fail; + } + } + +release_buffer_fail: + free(swapchain_buffers); + return ret; +} + +static tpl_result_t +__tpl_wl_vk_wsi_surface_create_swapchain(tpl_surface_t *surface, + tbm_format format, int width, + int height, int buffer_count, int present_mode) +{ + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; + tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL; + tpl_result_t res = TPL_ERROR_NONE; + + TPL_ASSERT(surface); + TPL_ASSERT(surface->backend.data); + TPL_ASSERT(surface->display); + + wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data; + TPL_ASSERT(wayland_vk_wsi_surface); + + wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *) + surface->display->backend.data; + TPL_ASSERT(wayland_vk_wsi_display); + + res = twe_surface_create_swapchain(wayland_vk_wsi_surface->twe_surface, + width, height, format, + buffer_count, present_mode); + if (res != TPL_ERROR_NONE) { + TPL_ERR("Failed to create swapchain. twe_surface(%p)", + wayland_vk_wsi_surface->twe_surface); + return res; + } + + wayland_vk_wsi_surface->tbm_queue = twe_surface_get_tbm_queue( + wayland_vk_wsi_surface->twe_surface); + wayland_vk_wsi_surface->buffer_count = buffer_count; + + return TPL_ERROR_NONE; +} + +static tpl_result_t +__tpl_wl_vk_wsi_surface_destroy_swapchain(tpl_surface_t *surface) +{ + tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL; + tpl_result_t res = TPL_ERROR_NONE; + + TPL_ASSERT(surface); + TPL_ASSERT(surface->backend.data); + TPL_ASSERT(surface->display); + + wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data; + TPL_ASSERT(wayland_vk_wsi_surface); + + res = twe_surface_destroy_swapchain(wayland_vk_wsi_surface->twe_surface); + if (res != TPL_ERROR_NONE) { + TPL_ERR("Failed to destroy swapchain. twe_surface(%p)", + wayland_vk_wsi_surface->twe_surface); + return res; + } + + return TPL_ERROR_NONE; +} + +tpl_bool_t +__tpl_display_choose_backend_wayland_vk_wsi_thread(tpl_handle_t native_dpy) +{ + if (!native_dpy) return TPL_FALSE; + + if (twe_check_native_handle_is_wl_display(native_dpy)) + return TPL_TRUE; + + return TPL_FALSE; +} + +void +__tpl_display_init_backend_wl_vk_wsi_thread(tpl_display_backend_t *backend) +{ + TPL_ASSERT(backend); + + backend->type = TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD; + backend->data = NULL; + + backend->init = __tpl_wl_vk_wsi_display_init; + backend->fini = __tpl_wl_vk_wsi_display_fini; + backend->query_config = __tpl_wl_vk_wsi_display_query_config; + backend->filter_config = __tpl_wl_vk_wsi_display_filter_config; + backend->query_window_supported_buffer_count = + __tpl_wl_vk_wsi_display_query_window_supported_buffer_count; + backend->query_window_supported_present_modes = + __tpl_wl_vk_wsi_display_query_window_supported_present_modes; +} + +void +__tpl_surface_init_backend_wl_vk_wsi_thread(tpl_surface_backend_t *backend) +{ + TPL_ASSERT(backend); + + backend->type = TPL_BACKEND_WAYLAND_VULKAN_WSI_THREAD; + backend->data = NULL; + + backend->init = __tpl_wl_vk_wsi_surface_init; + backend->fini = __tpl_wl_vk_wsi_surface_fini; + backend->validate = __tpl_wl_vk_wsi_surface_validate; + backend->dequeue_buffer = __tpl_wl_vk_wsi_surface_dequeue_buffer; + backend->enqueue_buffer = __tpl_wl_vk_wsi_surface_enqueue_buffer; + backend->get_swapchain_buffers = + __tpl_wl_vk_wsi_surface_get_swapchain_buffers; + backend->create_swapchain = __tpl_wl_vk_wsi_surface_create_swapchain; + backend->destroy_swapchain = __tpl_wl_vk_wsi_surface_destroy_swapchain; +} -- 2.7.4