From 240e51510b5316cd85a086272b5ddb650ea1e413 Mon Sep 17 00:00:00 2001 From: "deasung.kim" Date: Tue, 1 Nov 2016 13:35:24 +0900 Subject: [PATCH] swapchain: separated swapchain.c modified vk_swapchain_t added backend data added backend funcs added swapchain_tpl.c for tpl_backend Change-Id: I4a3bd967df1e7afc0b0f91d14fd11ca29b135804 --- src/wsi/Makefile.am | 3 +- src/wsi/swapchain.c | 172 +++++++++++++++++------------------------- src/wsi/swapchain_tpl.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++ src/wsi/wsi.h | 23 +++++- 4 files changed, 285 insertions(+), 107 deletions(-) create mode 100644 src/wsi/swapchain_tpl.c diff --git a/src/wsi/Makefile.am b/src/wsi/Makefile.am index 24455e5..0715f85 100644 --- a/src/wsi/Makefile.am +++ b/src/wsi/Makefile.am @@ -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 \ diff --git a/src/wsi/swapchain.c b/src/wsi/swapchain.c index 4300bc2..ac87ad2 100644 --- a/src/wsi/swapchain.c +++ b/src/wsi/swapchain.c @@ -25,6 +25,7 @@ #include "wsi.h" #include #include +#include #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 index 0000000..1d9812d --- /dev/null +++ b/src/wsi/swapchain_tpl.c @@ -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 + +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; +} diff --git a/src/wsi/wsi.h b/src/wsi/wsi.h index 8dd9e99..948895a 100644 --- a/src/wsi/wsi.h +++ b/src/wsi/wsi.h @@ -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); -- 2.7.4