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 if (res == TPL_ERROR_OUT_OF_MEMORY) {
132 error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
133 VK_ERROR("tpl_surface_create_swapchain() failed.\n");
136 VK_CHECK(res == TPL_ERROR_NONE, goto error, "tpl_surface_create_swapchain() failed.\n");
138 /* Initialize swapchain buffers. */
139 res = tpl_surface_get_swapchain_buffers(chain->tpl_surface, &buffers, &buffer_count);
140 if (res == TPL_ERROR_OUT_OF_MEMORY) {
141 error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
142 VK_ERROR("tpl_surface_get_swapchain_buffers() failed.\n");
143 goto error_get_buffers;
145 VK_CHECK(res == TPL_ERROR_NONE, goto error_get_buffers, "tpl_surface_get_swapchain_buffers() failed.\n");
147 chain->buffers = vk_alloc(allocator, buffer_count * sizeof(vk_buffer_t),
148 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
149 VK_CHECK(chain->buffers, goto error_mem_alloc, "vk_alloc() failed.\n");
151 for (i = 0; i < buffer_count; i++) {
152 VkImageCreateInfo image_info = {
153 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
158 { info->imageExtent.width, info->imageExtent.height, 1 },
160 info->imageArrayLayers,
161 VK_SAMPLE_COUNT_1_BIT,
162 VK_IMAGE_TILING_LINEAR,
164 info->imageSharingMode,
165 info->queueFamilyIndexCount,
166 info->pQueueFamilyIndices,
167 VK_IMAGE_LAYOUT_UNDEFINED,
170 chain->buffers[i].tbm = buffers[i];
171 icd->create_presentable_image(device, buffers[i], &image_info, allocator,
172 &chain->buffers[i].image);
175 chain->buffer_count = buffer_count;
176 *swapchain = (VkSwapchainKHR)(uintptr_t)chain;
180 error = VK_ERROR_OUT_OF_HOST_MEMORY;
183 tpl_surface_destroy_swapchain(chain->tpl_surface);
186 if (chain->tpl_display)
187 tpl_object_unreference((tpl_object_t *)chain->tpl_display);
189 if (chain->tpl_surface)
190 tpl_object_unreference((tpl_object_t *)chain->tpl_surface);
193 vk_free(allocator, chain->buffers);
195 vk_free(allocator, chain);
196 *swapchain = VK_NULL_HANDLE;
200 VKAPI_ATTR VkResult VKAPI_CALL
201 vk_CreateSharedSwapchainsKHR(VkDevice device,
202 uint32_t swapchain_count,
203 const VkSwapchainCreateInfoKHR *infos,
204 const VkAllocationCallbacks *allocator,
205 VkSwapchainKHR *swapchains)
211 VKAPI_ATTR void VKAPI_CALL
212 vk_DestroySwapchainKHR(VkDevice device,
213 VkSwapchainKHR swapchain,
214 const VkAllocationCallbacks *allocator)
216 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
218 tpl_surface_destroy_swapchain(chain->tpl_surface);
219 free(chain->buffers);
221 if (chain->tpl_surface)
222 tpl_object_unreference((tpl_object_t *)chain->tpl_surface);
224 if (chain->tpl_display)
225 tpl_object_unreference((tpl_object_t *)chain->tpl_display);
227 vk_free(&chain->allocator, chain);
230 VKAPI_ATTR VkResult VKAPI_CALL
231 vk_GetSwapchainImagesKHR(VkDevice device,
232 VkSwapchainKHR swapchain,
233 uint32_t *image_count,
236 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
241 *image_count = MIN(*image_count, chain->buffer_count);
243 for (i = 0; i < *image_count; i++)
244 images[i] = chain->buffers[i].image;
246 if (*image_count < chain->buffer_count)
247 return VK_INCOMPLETE;
249 *image_count = chain->buffer_count;
255 VKAPI_ATTR VkResult VKAPI_CALL
256 vk_AcquireNextImageKHR(VkDevice device,
257 VkSwapchainKHR swapchain,
259 VkSemaphore semaphore,
261 uint32_t *image_index)
263 vk_icd_t *icd = vk_get_icd();
266 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
269 if (icd->acquire_image) {
270 next = tpl_surface_dequeue_buffer_with_sync(chain->tpl_surface, timeout, &sync_fd);
275 next = tpl_surface_dequeue_buffer(chain->tpl_surface);
276 VK_CHECK(next, return VK_ERROR_SURFACE_LOST_KHR, "tpl_surface_dequeue_buffers() failed\n.");
279 for (i = 0; i < chain->buffer_count; i++) {
280 if (next == chain->buffers[i].tbm) {
282 if (icd->acquire_image)
283 icd->acquire_image(device, chain->buffers[i].image, sync_fd, semaphore, fence);
285 /* TODO: We can do optimization here by returning buffer index immediatly despite the
286 * buffer is not released yet. The fence or semaphore will be signaled when
287 * wl_buffer.release actually arrives. */
293 return VK_ERROR_SURFACE_LOST_KHR;
296 VKAPI_ATTR VkResult VKAPI_CALL
297 vk_QueuePresentKHR(VkQueue queue,
298 const VkPresentInfoKHR *info)
300 vk_icd_t *icd = vk_get_icd();
303 for (i = 0; i < info->swapchainCount; i++) {
306 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)info->pSwapchains[i];
308 if (icd->queue_signal_release_image)
309 icd->queue_signal_release_image(queue, info->waitSemaphoreCount, info->pWaitSemaphores,
310 chain->buffers[info->pImageIndices[i]].image, &sync_fd);
312 res = tpl_surface_enqueue_buffer_with_damage_and_sync(chain->tpl_surface,
313 chain->buffers[info->pImageIndices[i]].tbm,
316 if (info->pResults != NULL)
317 info->pResults[i] = res == TPL_ERROR_NONE ? VK_SUCCESS : VK_ERROR_DEVICE_LOST;