NULL);
}
- TPL_LOG_T("WL_VK", "wl_vk_client(%p) init.", disp_source->wl_vk_client);
-
fini:
if (queue)
wl_event_queue_destroy(queue);
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;
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)
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,
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;
_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)) {
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;
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;
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;
}
--- /dev/null
+#define inline __inline__
+#undef inline
+
+#include "tpl_internal.h"
+
+#include <tbm_surface.h>
+#include <tbm_surface_internal.h>
+#include <tbm_surface_queue.h>
+
+#include <tbm_sync.h>
+
+#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;
+}