2 * Copyright © 2016 S-Core Corporation
3 * Copyright © 2016-2017 Samsung Electronics co., Ltd. All Rights Reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
30 #define TBM_FORMAT_0 0
32 #define RETURN_FORMAT(comp, opaque, pre, post, inherit) \
34 if (comp == VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) \
35 return TBM_FORMAT_##opaque; \
36 else if (comp == VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) \
37 return TBM_FORMAT_##pre; \
38 else if (comp == VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) \
39 return TBM_FORMAT_##post; \
40 else if (comp == VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) \
41 return TBM_FORMAT_##inherit; \
46 static inline tbm_format
47 get_tbm_format(VkFormat format, VkCompositeAlphaFlagBitsKHR comp)
51 case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
52 RETURN_FORMAT(comp, RGBX4444, RGBA4444, 0, RGBA4444);
53 case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
54 RETURN_FORMAT(comp, BGRX4444, BGRA4444, 0, BGRA4444);
56 case VK_FORMAT_R5G6B5_UNORM_PACK16:
57 RETURN_FORMAT(comp, RGB565, RGB565, RGB565, RGB565);
58 case VK_FORMAT_B5G6R5_UNORM_PACK16:
59 RETURN_FORMAT(comp, BGR565, BGR565, BGR565, BGR565);
61 case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
62 RETURN_FORMAT(comp, RGBX5551, RGBA5551, 0, RGBA5551);
63 case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
64 RETURN_FORMAT(comp, BGRX5551, BGRA5551, 0, BGRA5551);
65 case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
66 RETURN_FORMAT(comp, XRGB1555, ARGB1555, 0, ARGB1555);
68 case VK_FORMAT_R8G8B8_UNORM:
69 RETURN_FORMAT(comp, BGR888, BGR888, BGR888, BGR888);
70 case VK_FORMAT_B8G8R8_UNORM:
71 RETURN_FORMAT(comp, RGB888, RGB888, RGB888, RGB888);
73 case VK_FORMAT_B8G8R8A8_UNORM:
74 RETURN_FORMAT(comp, XRGB8888, ARGB8888, 0, ARGB8888);
75 case VK_FORMAT_A8B8G8R8_UNORM_PACK32:
76 RETURN_FORMAT(comp, XBGR8888, ABGR8888, 0, ABGR8888);
78 case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
79 RETURN_FORMAT(comp, XRGB2101010, ARGB2101010, 0, ARGB2101010);
80 case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
81 RETURN_FORMAT(comp, XBGR2101010, ABGR2101010, 0, ABGR2101010);
89 VKAPI_ATTR VkResult VKAPI_CALL
90 vk_CreateSwapchainKHR(VkDevice device,
91 const VkSwapchainCreateInfoKHR *info,
92 const VkAllocationCallbacks *allocator,
93 VkSwapchainKHR *swapchain)
95 vk_icd_t *icd = vk_get_icd();
96 vk_swapchain_t *chain;
99 VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)(uintptr_t)info->surface;
101 tbm_surface_h *buffers;
102 VkResult error = VK_ERROR_DEVICE_LOST;
104 VK_ASSERT(surface->base.platform == VK_ICD_WSI_PLATFORM_WAYLAND);
106 format = get_tbm_format(info->imageFormat, info->compositeAlpha);
107 VK_CHECK(format, return VK_ERROR_SURFACE_LOST_KHR, "Not supported image format.\n");
109 allocator = vk_get_allocator(device, allocator);
111 chain = vk_alloc(allocator, sizeof(vk_swapchain_t), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
112 VK_CHECK(chain, return VK_ERROR_OUT_OF_HOST_MEMORY, "vk_alloc() failed.\n");
114 memset(chain, 0x00, sizeof(vk_swapchain_t));
116 chain->allocator = *allocator;
117 chain->surface = info->surface;
119 /* Don't check NULL for display and window. There might be default ones for some systems. */
121 chain->tpl_display = vk_get_tpl_display(surface->display);
122 VK_CHECK(chain->tpl_display, goto error, "vk_get_tpl_display() failed.\n");
124 chain->tpl_surface = tpl_surface_create(chain->tpl_display, surface->surface,
125 TPL_SURFACE_TYPE_WINDOW, format);
126 VK_CHECK(chain->tpl_surface, goto error, "tpl_surface_create() failed.\n");
128 res = tpl_surface_create_swapchain(chain->tpl_surface, format,
129 info->imageExtent.width, info->imageExtent.height,
130 info->minImageCount);
131 VK_CHECK(res == TPL_ERROR_NONE, goto error, "tpl_surface_create_swapchain() failed.\n");
133 /* Initialize swapchain buffers. */
134 res = tpl_surface_get_swapchain_buffers(chain->tpl_surface, &buffers, &buffer_count);
135 VK_CHECK(res == TPL_ERROR_NONE, goto error_get_buffers, "tpl_surface_get_swapchain_buffers() failed.\n");
137 chain->buffers = vk_alloc(allocator, buffer_count * sizeof(vk_buffer_t),
138 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
139 VK_CHECK(chain->buffers, goto error_mem_alloc, "vk_alloc() failed.\n");
141 for (i = 0; i < buffer_count; i++) {
142 VkImageCreateInfo image_info = {
143 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
148 { info->imageExtent.width, info->imageExtent.height, 1 },
150 info->imageArrayLayers,
151 VK_SAMPLE_COUNT_1_BIT,
152 VK_IMAGE_TILING_LINEAR,
154 info->imageSharingMode,
155 info->queueFamilyIndexCount,
156 info->pQueueFamilyIndices,
157 VK_IMAGE_LAYOUT_UNDEFINED,
160 chain->buffers[i].tbm = buffers[i];
161 icd->create_presentable_image(device, buffers[i], &image_info, allocator,
162 &chain->buffers[i].image);
165 chain->buffer_count = buffer_count;
166 *swapchain = (VkSwapchainKHR)(uintptr_t)chain;
170 error = VK_ERROR_OUT_OF_HOST_MEMORY;
173 tpl_surface_destroy_swapchain(chain->tpl_surface);
176 if (chain->tpl_display)
177 tpl_object_unreference((tpl_object_t *)chain->tpl_display);
179 if (chain->tpl_surface)
180 tpl_object_unreference((tpl_object_t *)chain->tpl_surface);
183 vk_free(allocator, chain->buffers);
185 vk_free(allocator, chain);
186 *swapchain = VK_NULL_HANDLE;
190 VKAPI_ATTR VkResult VKAPI_CALL
191 vk_CreateSharedSwapchainsKHR(VkDevice device,
192 uint32_t swapchain_count,
193 const VkSwapchainCreateInfoKHR *infos,
194 const VkAllocationCallbacks *allocator,
195 VkSwapchainKHR *swapchains)
201 VKAPI_ATTR void VKAPI_CALL
202 vk_DestroySwapchainKHR(VkDevice device,
203 VkSwapchainKHR swapchain,
204 const VkAllocationCallbacks *allocator)
206 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
208 tpl_surface_destroy_swapchain(chain->tpl_surface);
209 free(chain->buffers);
211 if (chain->tpl_surface)
212 tpl_object_unreference((tpl_object_t *)chain->tpl_surface);
214 if (chain->tpl_display)
215 tpl_object_unreference((tpl_object_t *)chain->tpl_display);
217 vk_free(&chain->allocator, chain);
220 VKAPI_ATTR VkResult VKAPI_CALL
221 vk_GetSwapchainImagesKHR(VkDevice device,
222 VkSwapchainKHR swapchain,
223 uint32_t *image_count,
226 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
231 *image_count = MIN(*image_count, chain->buffer_count);
233 for (i = 0; i < *image_count; i++)
234 images[i] = chain->buffers[i].image;
236 if (*image_count < chain->buffer_count)
237 return VK_INCOMPLETE;
239 *image_count = chain->buffer_count;
245 VKAPI_ATTR VkResult VKAPI_CALL
246 vk_AcquireNextImageKHR(VkDevice device,
247 VkSwapchainKHR swapchain,
249 VkSemaphore semaphore,
251 uint32_t *image_index)
253 vk_icd_t *icd = vk_get_icd();
256 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
259 if (icd->acquire_image) {
260 next = tpl_surface_dequeue_buffer_with_sync(chain->tpl_surface, timeout, &sync_fd);
265 next = tpl_surface_dequeue_buffer(chain->tpl_surface);
266 VK_CHECK(next, return VK_ERROR_SURFACE_LOST_KHR, "tpl_surface_dequeue_buffers() failed\n.");
269 for (i = 0; i < chain->buffer_count; i++) {
270 if (next == chain->buffers[i].tbm) {
272 if (icd->acquire_image)
273 icd->acquire_image(device, chain->buffers[i].image, sync_fd, semaphore, fence);
275 /* TODO: We can do optimization here by returning buffer index immediatly despite the
276 * buffer is not released yet. The fence or semaphore will be signaled when
277 * wl_buffer.release actually arrives. */
283 return VK_ERROR_SURFACE_LOST_KHR;
286 VKAPI_ATTR VkResult VKAPI_CALL
287 vk_QueuePresentKHR(VkQueue queue,
288 const VkPresentInfoKHR *info)
290 vk_icd_t *icd = vk_get_icd();
293 for (i = 0; i < info->swapchainCount; i++) {
296 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)info->pSwapchains[i];
298 if (icd->queue_signal_release_image)
299 icd->queue_signal_release_image(queue, info->waitSemaphoreCount, info->pWaitSemaphores,
300 chain->buffers[info->pImageIndices[i]].image, &sync_fd);
302 res = tpl_surface_enqueue_buffer_with_damage_and_sync(chain->tpl_surface,
303 chain->buffers[info->pImageIndices[i]].tbm,
306 if (info->pResults != NULL)
307 info->pResults[i] = res == TPL_ERROR_NONE ? VK_SUCCESS : VK_ERROR_DEVICE_LOST;