Back up the legacy codes of wl_vk_thread to unused. 36/257736/1
authorJoonbum Ko <joonbum.ko@samsung.com>
Fri, 30 Apr 2021 06:27:54 +0000 (15:27 +0900)
committerJoonbum Ko <joonbum.ko@samsung.com>
Fri, 30 Apr 2021 06:39:00 +0000 (15:39 +0900)
Change-Id: Ie9276cd997b89be2f558306daaee3e3eb3738be9
Signed-off-by: Joonbum Ko <joonbum.ko@samsung.com>
src/unused/tpl_wl_vk_thread_legacy.c [new file with mode: 0644]

diff --git a/src/unused/tpl_wl_vk_thread_legacy.c b/src/unused/tpl_wl_vk_thread_legacy.c
new file mode 100644 (file)
index 0000000..cb4f549
--- /dev/null
@@ -0,0 +1,832 @@
+#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;
+       tbm_surface_h *swapchain_buffers;
+       int buffer_count;
+       tpl_bool_t is_activated;
+       tpl_bool_t reset;
+       tpl_util_atomic_uint swapchain_reference;
+};
+
+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, surface->num_buffers);
+       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;
+       wayland_vk_wsi_surface->is_activated = TPL_FALSE;
+       wayland_vk_wsi_surface->swapchain_buffers = NULL;
+
+       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);
+
+       if (wayland_vk_wsi_surface->swapchain_buffers) {
+               free(wayland_vk_wsi_surface->swapchain_buffers);
+               wayland_vk_wsi_surface->swapchain_buffers = NULL;
+       }
+
+       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 there are received region information,
+        * save it to buf_info in tbm_surface user_data using below API. */
+       if (num_rects && rects) {
+               tpl_result_t ret = TPL_ERROR_NONE;
+               ret = twe_surface_set_damage_region(tbm_surface, num_rects, rects);
+               if (ret != TPL_ERROR_NONE) {
+                       TPL_WARN("Failed to set damage region. num_rects(%d) rects(%p)",
+                                        num_rects, rects);
+               }
+       }
+       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;
+       }
+
+       if (sync_fence != -1) {
+               tpl_result_t res = TPL_ERROR_NONE;
+               res = twe_surface_set_sync_fd(wayland_vk_wsi_surface->twe_surface,
+                                                                         tbm_surface, sync_fence);
+               if (res != TPL_ERROR_NONE) {
+                       TPL_WARN("Failed to set sync_fd(%d). Fallback to async mode.",
+                                        sync_fence);
+               }
+       }
+
+       TPL_LOG_T("WL_VK", "[ENQ] tbm_surface(%p) bo(%d) sync_fence(%d)",
+                         tbm_surface,
+                         tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)),
+                         sync_fence);
+
+       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);
+
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface =
+               (tpl_wayland_vk_wsi_surface_t *)surface->backend.data;
+
+       return !(wayland_vk_wsi_surface->reset);
+}
+
+static tpl_result_t
+__tpl_wl_vk_wsi_surface_cancel_dequeued_buffer(tpl_surface_t *surface,
+                                                                                          tbm_surface_h tbm_surface)
+{
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+       tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *)surface->backend.data;
+       if (!wayland_vk_wsi_surface) {
+               TPL_ERR("Invalid backend surface. surface(%p) wayland_vk_wsi_surface(%p)",
+                               surface, wayland_vk_wsi_surface);
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       if (!tbm_surface_internal_is_valid(tbm_surface)) {
+               TPL_ERR("Invalid buffer. tbm_surface(%p)", tbm_surface);
+               return TPL_ERROR_INVALID_PARAMETER;
+       }
+
+       tbm_surface_internal_unref(tbm_surface);
+
+       tsq_err = tbm_surface_queue_cancel_dequeue(wayland_vk_wsi_surface->tbm_queue,
+                                                                                          tbm_surface);
+       if (tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
+               TPL_ERR("Failed to release tbm_surface(%p)", tbm_surface);
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       TPL_LOG_T("WL_VK", "[CANCEL BUFFER] tpl_surface(%p) tbm_surface(%p)",
+                         surface, tbm_surface);
+
+       return TPL_ERROR_NONE;
+}
+
+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;
+       tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display =
+               (tpl_wayland_vk_wsi_display_t *)surface->display->backend.data;
+       tbm_surface_queue_error_e tsq_err = 0;
+       tpl_result_t lock_res = TPL_ERROR_NONE;
+       tpl_result_t res = TPL_ERROR_NONE;
+
+       if (sync_fence)
+               *sync_fence = -1;
+
+       TPL_OBJECT_UNLOCK(surface);
+       TRACE_BEGIN("WAIT_DEQUEUEABLE");
+       lock_res = twe_display_lock(wayland_vk_wsi_display->twe_display);
+       res = twe_surface_wait_dequeueable(wayland_vk_wsi_surface->twe_surface,
+                                                                          timeout_ns);
+       TRACE_END();
+       TPL_OBJECT_LOCK(surface);
+
+       if (res == TPL_ERROR_TIME_OUT) {
+               TPL_ERR("Failed to get buffer during timeout_ns(%" PRIu64 ")",
+                               timeout_ns);
+               if (lock_res == TPL_ERROR_NONE)
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+               return NULL;
+       } else if (res != TPL_ERROR_NONE) {
+               TPL_ERR("Invalid operation. twe_surface(%p) timeout_ns(%" PRIu64 ")",
+                               wayland_vk_wsi_surface->twe_surface, timeout_ns);
+               if (lock_res == TPL_ERROR_NONE)
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+               return NULL;
+       }
+
+       if (wayland_vk_wsi_surface->reset) {
+               TPL_LOG_T("WL_VK", "tbm_queue(%p) has been reset. Do not process dequeue.",
+                                 wayland_vk_wsi_surface->tbm_queue);
+               if (lock_res == TPL_ERROR_NONE)
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+               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(%p) | tsq_err = %d",
+                               wayland_vk_wsi_surface->tbm_queue, tsq_err);
+               if (lock_res == TPL_ERROR_NONE)
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+               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_queue(%p) tbm_surface(%p) bo(%d)",
+                         wayland_vk_wsi_surface->tbm_queue, tbm_surface,
+                         tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
+
+       if (lock_res == TPL_ERROR_NONE)
+               twe_display_unlock(wayland_vk_wsi_display->twe_display);
+
+       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)
+{
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+       tpl_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL;
+       int i;
+       tpl_result_t ret = TPL_ERROR_NONE;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->backend.data);
+       TPL_ASSERT(surface->display);
+       TPL_ASSERT(surface->display->backend.data);
+       TPL_ASSERT(buffers);
+       TPL_ASSERT(buffer_count);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *)surface->backend.data;
+       wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *)surface->display->backend.data;
+
+       if (twe_display_lock(wayland_vk_wsi_display->twe_display) == TPL_ERROR_NONE) {
+               ret = twe_surface_get_swapchain_buffers(wayland_vk_wsi_surface->twe_surface,
+                                                                                               NULL, buffer_count);
+               if (ret != TPL_ERROR_NONE) {
+                       TPL_ERR("Failed to get buffer_count. twe_surface(%p)",
+                                       wayland_vk_wsi_surface->twe_surface);
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+                       return ret;
+               }
+
+               wayland_vk_wsi_surface->swapchain_buffers = (tbm_surface_h *)calloc(
+                                                                               *buffer_count,
+                                                                               sizeof(tbm_surface_h));
+               if (!wayland_vk_wsi_surface->swapchain_buffers) {
+                       TPL_ERR("Failed to allocate memory for buffers.");
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+                       return TPL_ERROR_OUT_OF_MEMORY;
+               }
+
+               ret = twe_surface_get_swapchain_buffers(wayland_vk_wsi_surface->twe_surface,
+                                                                                               wayland_vk_wsi_surface->swapchain_buffers,
+                                                                                               buffer_count);
+               if (ret != TPL_ERROR_NONE) {
+                       TPL_ERR("Failed to get swapchain_buffers. wayland_vk_wsi_surface(%p) twe_surface(%p)",
+                                       wayland_vk_wsi_surface, wayland_vk_wsi_surface->twe_surface);
+                       free(wayland_vk_wsi_surface->swapchain_buffers);
+                       wayland_vk_wsi_surface->swapchain_buffers = NULL;
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+                       return ret;
+               }
+
+               for (i = 0; i < *buffer_count; i++) {
+                       if (wayland_vk_wsi_surface->swapchain_buffers[i]) {
+                               TPL_DEBUG("swapchain_buffers[%d] = tbm_surface(%p) bo(%d)",
+                                                 i, wayland_vk_wsi_surface->swapchain_buffers[i],
+                                                 tbm_bo_export(tbm_surface_internal_get_bo(
+                                                         wayland_vk_wsi_surface->swapchain_buffers[i], 0)));
+                               tbm_surface_internal_ref(wayland_vk_wsi_surface->swapchain_buffers[i]);
+                       }
+               }
+
+               *buffers = wayland_vk_wsi_surface->swapchain_buffers;
+
+               twe_display_unlock(wayland_vk_wsi_display->twe_display);
+       }
+
+       return TPL_ERROR_NONE;
+}
+
+static void
+__cb_tbm_queue_reset_callback(tbm_surface_queue_h surface_queue,
+                                                          void *data)
+{
+       tpl_surface_t *surface = NULL;
+       tpl_wayland_vk_wsi_surface_t *wayland_vk_wsi_surface = NULL;
+       tpl_bool_t is_activated = TPL_FALSE;
+
+       surface = (tpl_surface_t *)data;
+       TPL_CHECK_ON_NULL_RETURN(surface);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *)surface->backend.data;
+       TPL_CHECK_ON_NULL_RETURN(wayland_vk_wsi_surface);
+
+       /* When queue_reset_callback is called, if is_activated is different from
+        * its previous state change the reset flag to TPL_TRUE to get a new buffer
+        * with the changed state(ACTIVATED/DEACTIVATED) at the next frame. */
+       is_activated = twe_surface_check_activated(wayland_vk_wsi_surface->twe_surface);
+
+       if (wayland_vk_wsi_surface->is_activated != is_activated) {
+               if (is_activated) {
+                       TPL_LOG_T("WL_VK",
+                                         "[ACTIVATED_CB] wayland_vk_wsi_surface(%p) tbm_queue(%p)",
+                                         wayland_vk_wsi_surface, surface_queue);
+               } else {
+                       TPL_LOG_T("WL_VK",
+                                         "[DEACTIVATED_CB] wayland_vk_wsi_surface(%p) tbm_queue(%p)",
+                                         wayland_vk_wsi_surface, surface_queue);
+               }
+               wayland_vk_wsi_surface->is_activated = is_activated;
+       }
+
+       wayland_vk_wsi_surface->reset = TPL_TRUE;
+
+       if (surface->reset_cb)
+               surface->reset_cb(surface->reset_data);
+}
+
+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);
+
+       if (wayland_vk_wsi_surface->tbm_queue) {
+               int old_width = tbm_surface_queue_get_width(wayland_vk_wsi_surface->tbm_queue);
+               int old_height = tbm_surface_queue_get_height(wayland_vk_wsi_surface->tbm_queue);
+
+               if (old_width != width || old_height != height) {
+                       tbm_surface_queue_reset(wayland_vk_wsi_surface->tbm_queue,
+                                                                       width, height, format);
+                       TPL_LOG_T("WL_VK",
+                                         "[RESIZE] wayland_vk_wsi_surface(%p) tbm_queue(%p), (%d x %d) -> (%d x %d)",
+                                         wayland_vk_wsi_surface, wayland_vk_wsi_surface->tbm_queue,
+                                         old_width, old_height, width, height);
+               }
+
+               if (wayland_vk_wsi_surface->swapchain_buffers) {
+                       int i;
+                       for (i = 0; i < wayland_vk_wsi_surface->buffer_count; i++) {
+                               if (wayland_vk_wsi_surface->swapchain_buffers[i]) {
+                                       TPL_DEBUG("unref tbm_surface(%p)", wayland_vk_wsi_surface->swapchain_buffers[i]);
+                                       tbm_surface_internal_unref(wayland_vk_wsi_surface->swapchain_buffers[i]);
+                                       wayland_vk_wsi_surface->swapchain_buffers[i] = NULL;
+                               }
+                       }
+
+                       free(wayland_vk_wsi_surface->swapchain_buffers);
+                       wayland_vk_wsi_surface->swapchain_buffers = NULL;
+               }
+
+               wayland_vk_wsi_surface->buffer_count =
+                       tbm_surface_queue_get_size(wayland_vk_wsi_surface->tbm_queue);
+               wayland_vk_wsi_surface->reset = TPL_FALSE;
+
+               __tpl_util_atomic_inc(&wayland_vk_wsi_surface->swapchain_reference);
+
+               TPL_LOG_T("WL_VK", "[REUSE] wayland_vk_wsi_surface(%p) tbm_queue(%p) size(%d)",
+                                 wayland_vk_wsi_surface, wayland_vk_wsi_surface->tbm_queue,
+                                 wayland_vk_wsi_surface->buffer_count);
+               return TPL_ERROR_NONE;
+       }
+
+       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);
+
+       /* Set reset_callback to tbm_queue */
+       if (tbm_surface_queue_add_reset_cb(wayland_vk_wsi_surface->tbm_queue,
+                                  __cb_tbm_queue_reset_callback,
+                                  (void *)surface) != TBM_SURFACE_QUEUE_ERROR_NONE) {
+               TPL_ERR("TBM surface queue add reset cb failed!");
+               twe_surface_destroy_swapchain(wayland_vk_wsi_surface->twe_surface);
+               wayland_vk_wsi_surface->tbm_queue = NULL;
+               return TPL_ERROR_INVALID_OPERATION;
+       }
+
+       wayland_vk_wsi_surface->buffer_count = buffer_count;
+       wayland_vk_wsi_surface->reset = TPL_FALSE;
+
+       __tpl_util_atomic_set(&wayland_vk_wsi_surface->swapchain_reference, 1);
+
+       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_wayland_vk_wsi_display_t *wayland_vk_wsi_display = NULL;
+       tpl_result_t res = TPL_ERROR_NONE;
+       unsigned int ref;
+
+       TPL_ASSERT(surface);
+       TPL_ASSERT(surface->backend.data);
+       TPL_ASSERT(surface->display);
+       TPL_ASSERT(surface->display->backend.data);
+
+       wayland_vk_wsi_surface = (tpl_wayland_vk_wsi_surface_t *) surface->backend.data;
+       wayland_vk_wsi_display = (tpl_wayland_vk_wsi_display_t *) surface->display->backend.data;
+
+       if (twe_display_lock(wayland_vk_wsi_display->twe_display) == TPL_ERROR_NONE) {
+               ref = __tpl_util_atomic_dec(&wayland_vk_wsi_surface->swapchain_reference);
+               if (ref > 0) {
+                       TPL_LOG_T("WL_VK",
+                                         "This swapchain is still valid. | twe_surface(%p)",
+                                         wayland_vk_wsi_surface->twe_surface);
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+                       return TPL_ERROR_NONE;
+               }
+
+
+               if (wayland_vk_wsi_surface->reset) {
+                       TPL_LOG_T("WL_VK",
+                                         "Since reset is in the TRUE state, it will not be destroyed.");
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+                       return TPL_ERROR_NONE;
+               }
+
+               if (wayland_vk_wsi_surface->swapchain_buffers) {
+                       int i;
+                       for (i = 0; i < wayland_vk_wsi_surface->buffer_count; i++) {
+                               TPL_DEBUG("Stop tracking tbm_surface(%p)",
+                                                 wayland_vk_wsi_surface->swapchain_buffers[i]);
+                               tbm_surface_internal_unref(wayland_vk_wsi_surface->swapchain_buffers[i]);
+                               wayland_vk_wsi_surface->swapchain_buffers[i] = NULL;
+                       }
+
+                       free(wayland_vk_wsi_surface->swapchain_buffers);
+                       wayland_vk_wsi_surface->swapchain_buffers = NULL;
+               }
+
+               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);
+                       twe_display_unlock(wayland_vk_wsi_display->twe_display);
+                       return res;
+               }
+
+               wayland_vk_wsi_surface->tbm_queue = NULL;
+
+               twe_display_unlock(wayland_vk_wsi_display->twe_display);
+       }
+
+       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->cancel_dequeued_buffer =
+               __tpl_wl_vk_wsi_surface_cancel_dequeued_buffer;
+       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;
+}