swapchain: separated swapchain.c 84/102984/2
authordeasung.kim <deasung.kim@samsung.com>
Tue, 1 Nov 2016 04:35:24 +0000 (13:35 +0900)
committerGwan-gyeong Mun <kk.moon@samsung.com>
Wed, 11 Jan 2017 05:23:40 +0000 (21:23 -0800)
modified vk_swapchain_t
added backend data
added backend funcs
added swapchain_tpl.c for tpl_backend

Change-Id: I4a3bd967df1e7afc0b0f91d14fd11ca29b135804

src/wsi/Makefile.am
src/wsi/swapchain.c
src/wsi/swapchain_tpl.c [new file with mode: 0644]
src/wsi/wsi.h

index 24455e5..0715f85 100644 (file)
@@ -13,12 +13,13 @@ vulkan_wsi_tizen_la_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/include           \
 
 vulkan_wsi_tizen_la_LDFLAGS = -module -avoid-version
 vulkan_wsi_tizen_la_LIBADD = $(top_builddir)/src/utils/libutils.la     \
-                                                        $(TPL_LIBS) $(TBM_CFLAGS) $(TDM_CFLAGS)
+                                                        $(TPL_LIBS) $(TBM_LIBS) $(TDM_LIBS)
 
 vulkan_wsi_tizen_la_SOURCES = wsi.h                            \
                                                          entry-points.c        \
                                                          surface.c                     \
                                                          swapchain.c           \
+                                                         swapchain_tpl.c       \
                                                          display.c                     \
                                                          allocator.c           \
                                                          icd.c                         \
index 4300bc2..ac87ad2 100644 (file)
@@ -25,6 +25,7 @@
 #include "wsi.h"
 #include <string.h>
 #include <unistd.h>
+#include <stdio.h>
 
 #define TBM_FORMAT_0   0
 
@@ -91,21 +92,25 @@ vk_CreateSwapchainKHR(VkDevice                                                       device,
                                          const VkAllocationCallbacks           *allocator,
                                          VkSwapchainKHR                                        *swapchain)
 {
-       vk_icd_t                        *icd = vk_get_icd();
+       VkResult (*init)(VkDevice, const VkSwapchainCreateInfoKHR *,
+                                        vk_swapchain_t *, tbm_format);
        vk_swapchain_t          *chain;
-       tbm_format                       format;
-       tpl_result_t             res;
-       VkIcdSurfaceWayland     *surface = (VkIcdSurfaceWayland *)(uintptr_t)info->surface;
-       int                                      buffer_count, i;
+       VkResult                         error;
+       uint32_t                         i;
        tbm_surface_h           *buffers;
-       int tpl_present_mode;
-
-       VkResult error = VK_ERROR_DEVICE_LOST;
-
-       VK_ASSERT(surface->base.platform == VK_ICD_WSI_PLATFORM_WAYLAND);
+       tbm_format                       format;
+       vk_icd_t                        *icd = vk_get_icd();
 
-       format = get_tbm_format(info->imageFormat, info->compositeAlpha);
-       VK_CHECK(format, return VK_ERROR_SURFACE_LOST_KHR, "Not supported image format.\n");
+       switch(((VkIcdSurfaceBase *)(uintptr_t)info->surface)->platform) {
+               case VK_ICD_WSI_PLATFORM_WAYLAND:
+                       init = swapchain_tpl_init;
+                       break;
+               case VK_ICD_WSI_PLATFORM_DISPLAY:
+                       init = NULL;
+                       break;
+               default:
+                       return VK_ERROR_EXTENSION_NOT_PRESENT;
+       }
 
        allocator = vk_get_allocator(device, allocator);
 
@@ -117,57 +122,20 @@ vk_CreateSwapchainKHR(VkDevice                                                     device,
        chain->allocator = *allocator;
        chain->surface = info->surface;
 
-       /* Don't check NULL for display and window. There might be default ones for some systems. */
-
-       chain->tpl_display = vk_get_tpl_display(surface->display);
-       VK_CHECK(chain->tpl_display, goto error, "vk_get_tpl_display() failed.\n");
+       format = get_tbm_format(info->imageFormat, info->compositeAlpha);
+       VK_CHECK(format, return VK_ERROR_SURFACE_LOST_KHR, "Not supported image format.\n");
 
-       chain->tpl_surface = tpl_surface_create(chain->tpl_display, surface->surface,
-                                                                                       TPL_SURFACE_TYPE_WINDOW, format);
-       VK_CHECK(chain->tpl_surface, goto error, "tpl_surface_create() failed.\n");
+       error = init(device, info, chain, format);
+       VK_CHECK(error == VK_SUCCESS, goto done, "swapchain backend init failed.\n");
 
-       switch(info->presentMode) {
-               case VK_PRESENT_MODE_IMMEDIATE_KHR:
-                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_IMMEDIATE;
-                       break;
-               case VK_PRESENT_MODE_MAILBOX_KHR:
-                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX;
-                       break;
-               case VK_PRESENT_MODE_FIFO_KHR:
-                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO;
-                       break;
-               case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
-                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED;
-                       break;
-               default:
-                       VK_DEBUG("Unsupported present mode: 0x%x\n", info->presentMode);
-                       goto error;
-       }
+       error = chain->get_buffers(device, chain, &buffers, &chain->buffer_count);
+       VK_CHECK(error == VK_SUCCESS, goto done, "swapchain backend get buffers failed.\n");
 
-       res = tpl_surface_create_swapchain(chain->tpl_surface, format,
-                                                                          info->imageExtent.width, info->imageExtent.height,
-                                                                          info->minImageCount, tpl_present_mode);
-       if (res == TPL_ERROR_OUT_OF_MEMORY) {
-               error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
-               VK_ERROR("tpl_surface_create_swapchain() failed.\n");
-               goto error;
-       }
-       VK_CHECK(res == TPL_ERROR_NONE, goto error, "tpl_surface_create_swapchain() failed.\n");
-
-       /* Initialize swapchain buffers. */
-       res = tpl_surface_get_swapchain_buffers(chain->tpl_surface, &buffers, &buffer_count);
-       if (res == TPL_ERROR_OUT_OF_MEMORY) {
-               error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
-               VK_ERROR("tpl_surface_get_swapchain_buffers() failed.\n");
-               goto error_get_buffers;
-       }
-       VK_CHECK(res == TPL_ERROR_NONE, goto error_get_buffers, "tpl_surface_get_swapchain_buffers() failed.\n");
-
-       chain->buffers = vk_alloc(allocator, buffer_count * sizeof(vk_buffer_t),
+       chain->buffers = vk_alloc(&chain->allocator, chain->buffer_count * sizeof(vk_buffer_t),
                                                          VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
        VK_CHECK(chain->buffers, goto error_mem_alloc, "vk_alloc() failed.\n");
 
-       for (i = 0; i < buffer_count; i++) {
+       for (i = 0; i < chain->buffer_count; i++) {
                VkImageCreateInfo image_info = {
                        VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
                        NULL,
@@ -187,32 +155,27 @@ vk_CreateSwapchainKHR(VkDevice                                                     device,
                };
 
                chain->buffers[i].tbm = buffers[i];
-               icd->create_presentable_image(device, buffers[i], &image_info, allocator,
-                                                                         &chain->buffers[i].image);
+               icd->create_presentable_image(device, chain->buffers[i].tbm, &image_info,
+                                                                         &chain->allocator, &chain->buffers[i].image);
        }
-
-       chain->buffer_count = buffer_count;
-       *swapchain = (VkSwapchainKHR)(uintptr_t)chain;
-       return VK_SUCCESS;
+       goto done;
 
 error_mem_alloc:
        error = VK_ERROR_OUT_OF_HOST_MEMORY;
 
-error_get_buffers:
-       tpl_surface_destroy_swapchain(chain->tpl_surface);
-
-error:
-       if (chain->tpl_display)
-               tpl_object_unreference((tpl_object_t *)chain->tpl_display);
+done:
+       if (error != VK_SUCCESS) {
+               if (chain->deinit)
+                       chain->deinit(device, chain);
 
-       if (chain->tpl_surface)
-               tpl_object_unreference((tpl_object_t *)chain->tpl_surface);
+               if (chain)
+                       vk_free(allocator, chain);
 
-       if (chain->buffers)
-               vk_free(allocator, chain->buffers);
+               *swapchain = VK_NULL_HANDLE;
+       } else {
+               *swapchain = (VkSwapchainKHR)(uintptr_t)chain;
+       }
 
-       vk_free(allocator, chain);
-       *swapchain = VK_NULL_HANDLE;
        return error;
 }
 
@@ -232,17 +195,22 @@ vk_DestroySwapchainKHR(VkDevice                                            device,
                                           VkSwapchainKHR                                swapchain,
                                           const VkAllocationCallbacks  *allocator)
 {
-       vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
+       vk_swapchain_t                  *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
+       vk_icd_t                                *icd = vk_get_icd();
+       PFN_vkGetDeviceProcAddr  icd_gdpa = (PFN_vkGetDeviceProcAddr)icd->get_proc_addr(NULL, "vkGetDeviceProcAddr");
 
-       tpl_surface_destroy_swapchain(chain->tpl_surface);
-       free(chain->buffers);
+       if (icd_gdpa != VK_NULL_HANDLE) {
+               PFN_vkDestroyImage               destroy_image = (PFN_vkDestroyImage)icd_gdpa(device, "vkDestroyImage");
+               if (destroy_image != VK_NULL_HANDLE) {
+                       uint32_t                 i;
 
-       if (chain->tpl_surface)
-               tpl_object_unreference((tpl_object_t *)chain->tpl_surface);
-
-       if (chain->tpl_display)
-               tpl_object_unreference((tpl_object_t *)chain->tpl_display);
+                       for (i = 0; i < chain->buffer_count; i++)
+                               destroy_image(device, chain->buffers[i].image, &chain->allocator);
+               }
+       }
 
+       chain->deinit(device, chain);
+       vk_free(&chain->allocator, chain->buffers);
        vk_free(&chain->allocator, chain);
 }
 
@@ -279,27 +247,24 @@ vk_AcquireNextImageKHR(VkDevice                    device,
                                           VkFence                       fence,
                                           uint32_t                     *image_index)
 {
+       VkResult                 res;
+       vk_swapchain_t  *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
        vk_icd_t                *icd = vk_get_icd();
+       tbm_surface_h    tbm_surface;
+       int                              sync;
        uint32_t                 i;
-       tbm_surface_h    next;
-       vk_swapchain_t  *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
-       int sync_fd = -1;
 
-       if (icd->acquire_image) {
-               next = tpl_surface_dequeue_buffer_with_sync(chain->tpl_surface, timeout, &sync_fd);
-
-               if (next == NULL)
-                       return VK_TIMEOUT;
-       } else {
-               next = tpl_surface_dequeue_buffer(chain->tpl_surface);
-               VK_CHECK(next, return VK_ERROR_SURFACE_LOST_KHR, "tpl_surface_dequeue_buffers() failed\n.");
-       }
+       if (icd->acquire_image)
+               res = chain->acquire_image(device, chain, timeout, &tbm_surface, &sync);
+       else
+               res = chain->acquire_image(device, chain, timeout, &tbm_surface, NULL);
+       VK_CHECK(res == VK_SUCCESS, return res, "backend acquire image failed\n.");
 
        for (i = 0; i < chain->buffer_count; i++) {
-               if (next == chain->buffers[i].tbm) {
+               if (tbm_surface == chain->buffers[i].tbm) {
                        *image_index = i;
                        if (icd->acquire_image)
-                               icd->acquire_image(device, chain->buffers[i].image, sync_fd, semaphore, fence);
+                               icd->acquire_image(device, chain->buffers[i].image, sync, semaphore, fence);
 
                        /* TODO: We can do optimization here by returning buffer index immediatly despite the
                         * buffer is not released yet. The fence or semaphore will be signaled when
@@ -316,24 +281,23 @@ VKAPI_ATTR VkResult VKAPI_CALL
 vk_QueuePresentKHR(VkQueue                                      queue,
                                   const VkPresentInfoKHR       *info)
 {
-       vk_icd_t        *icd = vk_get_icd();
        uint32_t         i;
+       vk_icd_t        *icd = vk_get_icd();
 
        for (i = 0; i < info->swapchainCount; i++) {
-               int sync_fd = -1;
-               tpl_result_t res;
+               VkResult                 res;
+               int                              sync_fd = -1;
                vk_swapchain_t  *chain = (vk_swapchain_t *)(uintptr_t)info->pSwapchains[i];
 
                if (icd->queue_signal_release_image)
                        icd->queue_signal_release_image(queue, info->waitSemaphoreCount, info->pWaitSemaphores,
                                                                                        chain->buffers[info->pImageIndices[i]].image, &sync_fd);
 
-               res = tpl_surface_enqueue_buffer_with_damage_and_sync(chain->tpl_surface,
-                                                                                                                         chain->buffers[info->pImageIndices[i]].tbm,
-                                                                                                                         0, NULL, sync_fd);
+               res = chain->present_image(queue, chain,
+                                                                  chain->buffers[info->pImageIndices[i]].tbm, sync_fd);
 
                if (info->pResults != NULL)
-                       info->pResults[i] = res == TPL_ERROR_NONE ? VK_SUCCESS : VK_ERROR_DEVICE_LOST;
+                       info->pResults[i] = res;
        }
 
        return VK_SUCCESS;
diff --git a/src/wsi/swapchain_tpl.c b/src/wsi/swapchain_tpl.c
new file mode 100644 (file)
index 0000000..1d9812d
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+ * Copyright © 2016 S-Core Corporation
+ * Copyright © 2016-2017 Samsung Electronics co., Ltd. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "wsi.h"
+
+#include <string.h>
+
+typedef struct vk_swapchain_tpl vk_swapchain_tpl_t;
+
+struct vk_swapchain_tpl {
+       tpl_display_t                   *tpl_display;
+       tpl_surface_t                   *tpl_surface;
+       tbm_surface_h                   *buffers;
+};
+
+static VkResult
+swapchain_tpl_queue_present_image(VkQueue                                       queue,
+                                                                 vk_swapchain_t                        *chain,
+                                                                 tbm_surface_h                          tbm_surface,
+                                                                 int                                            sync_fd)
+{
+       tpl_result_t             res;
+       vk_swapchain_tpl_t      *swapchain_tpl = chain->backend_data;
+
+       res = tpl_surface_enqueue_buffer_with_damage_and_sync(swapchain_tpl->tpl_surface,
+                                                                                                                 tbm_surface, 0, NULL, sync_fd);
+       return res == TPL_ERROR_NONE ? VK_SUCCESS : VK_ERROR_DEVICE_LOST;
+}
+
+static VkResult
+swapchain_tpl_acquire_next_image(VkDevice                       device,
+                                                                vk_swapchain_t         *chain,
+                                                                uint64_t                        timeout,
+                                                                tbm_surface_h          *tbm_surface,
+                                                                int                            *sync)
+{
+       vk_swapchain_tpl_t      *swapchain_tpl = chain->backend_data;
+
+       if (sync) {
+               *tbm_surface = tpl_surface_dequeue_buffer_with_sync(swapchain_tpl->tpl_surface,
+                                                                                                                       timeout, sync);
+               if (*tbm_surface == NULL)
+                       return VK_TIMEOUT;
+       } else {
+               *tbm_surface = tpl_surface_dequeue_buffer(swapchain_tpl->tpl_surface);
+               VK_CHECK(*tbm_surface, return VK_ERROR_SURFACE_LOST_KHR, "tpl_surface_dequeue_buffers() failed.\n");
+       }
+
+       return VK_SUCCESS;
+}
+
+static void
+swapchain_tpl_deinit(VkDevice           device,
+                                vk_swapchain_t *chain)
+{
+       vk_swapchain_tpl_t      *swapchain_tpl = chain->backend_data;
+
+       if (swapchain_tpl) {
+               tpl_surface_destroy_swapchain(swapchain_tpl->tpl_surface);
+
+               if (swapchain_tpl->tpl_surface)
+                       tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_surface);
+
+               if (swapchain_tpl->tpl_display)
+                       tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_display);
+
+               if (swapchain_tpl->buffers)
+                       free(swapchain_tpl->buffers);
+               vk_free(&chain->allocator, swapchain_tpl);
+       }
+}
+
+static VkResult
+swapchain_tpl_get_buffers(VkDevice                      device,
+                                                 vk_swapchain_t        *chain,
+                                                 tbm_surface_h    **buffers,
+                                                 uint32_t                      *buffer_count)
+{
+       tpl_result_t             res;
+       int                                      buffer_cnt;
+       VkResult                         error = VK_SUCCESS;
+       vk_swapchain_tpl_t      *swapchain_tpl = chain->backend_data;
+
+       /* Initialize swapchain buffers. */
+       res = tpl_surface_get_swapchain_buffers(swapchain_tpl->tpl_surface,
+                                                                                       &swapchain_tpl->buffers, &buffer_cnt);
+       VK_CHECK(res == TPL_ERROR_NONE, goto done, "tpl_surface_get_swapchain_buffers() failed.\n");
+
+       *buffers = swapchain_tpl->buffers;
+       *buffer_count = buffer_cnt;
+
+done:
+       if (res == TPL_ERROR_OUT_OF_MEMORY)
+               error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+       else if (res != TPL_ERROR_NONE)
+               error = VK_ERROR_SURFACE_LOST_KHR;
+
+       return error;
+}
+
+VkResult
+swapchain_tpl_init(VkDevice                                                     device,
+                                  const VkSwapchainCreateInfoKHR       *info,
+                                  vk_swapchain_t                                       *chain,
+                                  tbm_format                                            format)
+{
+       tpl_result_t             res;
+       VkIcdSurfaceWayland     *surface = (VkIcdSurfaceWayland *)(uintptr_t)info->surface;
+       vk_swapchain_tpl_t      *swapchain_tpl;
+       int                                      tpl_present_mode;
+
+       VkResult error = VK_ERROR_DEVICE_LOST;
+
+       swapchain_tpl = vk_alloc(&chain->allocator, sizeof(vk_swapchain_tpl_t),
+                                                        VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
+       VK_CHECK(swapchain_tpl, return VK_ERROR_OUT_OF_HOST_MEMORY, "vk_alloc() failed.\n");
+       memset(swapchain_tpl, 0x00, sizeof(*swapchain_tpl));
+       chain->backend_data = swapchain_tpl;
+
+       /* Don't check NULL for display and window. There might be default ones for some systems. */
+
+       swapchain_tpl->tpl_display = vk_get_tpl_display(surface->display);
+       VK_CHECK(swapchain_tpl->tpl_display, goto error, "vk_get_tpl_display() failed.\n");
+
+       swapchain_tpl->tpl_surface = tpl_surface_create(swapchain_tpl->tpl_display,
+                                                                                                                  surface->surface,
+                                                                                                                  TPL_SURFACE_TYPE_WINDOW, format);
+       VK_CHECK(swapchain_tpl->tpl_surface, goto error, "tpl_surface_create() failed.\n");
+
+       switch(info->presentMode) {
+               case VK_PRESENT_MODE_IMMEDIATE_KHR:
+                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_IMMEDIATE;
+                       break;
+               case VK_PRESENT_MODE_MAILBOX_KHR:
+                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX;
+                       break;
+               case VK_PRESENT_MODE_FIFO_KHR:
+                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO;
+                       break;
+               case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
+                       tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED;
+                       break;
+               default:
+                       VK_DEBUG("Unsupported present mode: 0x%x\n", info->presentMode);
+                       goto error;
+       }
+
+       res = tpl_surface_create_swapchain(swapchain_tpl->tpl_surface, format,
+                                                                          info->imageExtent.width, info->imageExtent.height,
+                                                                          info->minImageCount, tpl_present_mode);
+       if (res == TPL_ERROR_OUT_OF_MEMORY) {
+               error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
+               VK_ERROR("tpl_surface_create_swapchain() failed.\n");
+               goto error;
+       }
+       VK_CHECK(res == TPL_ERROR_NONE, goto error, "tpl_surface_create_swapchain() failed.\n");
+
+       chain->get_buffers = swapchain_tpl_get_buffers;
+       chain->deinit = swapchain_tpl_deinit;
+       chain->acquire_image = swapchain_tpl_acquire_next_image;
+       chain->present_image = swapchain_tpl_queue_present_image;
+
+       return VK_SUCCESS;
+
+error:
+       if (swapchain_tpl->tpl_display)
+               tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_display);
+
+       if (swapchain_tpl->tpl_surface)
+               tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_surface);
+
+       return error;
+}
index 8dd9e99..948895a 100644 (file)
@@ -124,11 +124,26 @@ struct vk_swapchain {
        VkAllocationCallbacks    allocator;
        VkSurfaceKHR                     surface;
 
-       tpl_display_t                   *tpl_display;
-       tpl_surface_t                   *tpl_surface;
+       VkResult                                (*get_buffers)  (VkDevice,
+                                                                                        vk_swapchain_t *,
+                                                                                        tbm_surface_h **,
+                                                                                        uint32_t *);   /* buffer count */
+       VkResult                                (*acquire_image)(VkDevice,
+                                                                                        vk_swapchain_t *,
+                                                                                        uint64_t,              /* timeout */
+                                                                                        tbm_surface_h *,
+                                                                                        int *);                /* sync fd */
+       VkResult                                (*present_image)(VkQueue,
+                                                                                        vk_swapchain_t *,
+                                                                                        tbm_surface_h,
+                                                                                        int);                  /* sync fd */
+       void                                    (*deinit)               (VkDevice,
+                                                                                        vk_swapchain_t *);
 
        uint32_t                                 buffer_count;
        vk_buffer_t                             *buffers;
+
+       void *backend_data;
 };
 
 VkBool32
@@ -161,6 +176,10 @@ vk_get_tpl_display(tpl_handle_t native_dpy)
        return display;
 };
 
+VkResult
+swapchain_tpl_init(VkDevice device, const VkSwapchainCreateInfoKHR *info,
+                                  vk_swapchain_t *chain, tbm_format format);
+
 /* Entry point proto types. */
 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
 vk_icdGetInstanceProcAddr(VkInstance instance, const char *name);