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 VkResult (*init)(VkDevice, const VkSwapchainCreateInfoKHR *,
96 vk_swapchain_t *, tbm_format);
97 vk_swapchain_t *chain;
100 uint32_t cnt_success = 0;
101 tbm_surface_h *buffers;
103 vk_icd_t *icd = vk_get_icd();
105 switch(((VkIcdSurfaceBase *)(uintptr_t)info->surface)->platform) {
106 #pragma GCC diagnostic push
107 #pragma GCC diagnostic ignored "-Wswitch"
108 case VK_ICD_WSI_PLATFORM_TBM_QUEUE:
109 #pragma GCC diagnostic pop
110 case VK_ICD_WSI_PLATFORM_WAYLAND:
111 init = swapchain_tpl_init;
113 case VK_ICD_WSI_PLATFORM_DISPLAY:
114 init = swapchain_tdm_init;
117 return VK_ERROR_EXTENSION_NOT_PRESENT;
120 if (allocator == VK_NULL_HANDLE)
121 allocator = vk_get_allocator(device, allocator);
123 chain = vk_alloc(allocator, sizeof(vk_swapchain_t), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
124 VK_CHECK(chain, return VK_ERROR_OUT_OF_HOST_MEMORY, "vk_alloc() failed.\n");
126 memset(chain, 0x00, sizeof(vk_swapchain_t));
128 chain->allocator = allocator;
129 chain->surface = info->surface;
130 chain->buffers = NULL;
131 chain->oldSwapchain = (vk_swapchain_t *)(uintptr_t)info->oldSwapchain;
132 chain->is_retired = VK_FALSE;
134 format = get_tbm_format(info->imageFormat, info->compositeAlpha);
135 VK_CHECK(format, return VK_ERROR_SURFACE_LOST_KHR, "Not supported image format.\n");
137 error = init(device, info, chain, format);
138 VK_CHECK(error == VK_SUCCESS, goto done, "swapchain backend init failed.\n");
140 error = chain->get_buffers(device, chain, &buffers, &chain->buffer_count);
141 VK_CHECK(error == VK_SUCCESS, goto done, "swapchain backend get buffers failed.\n");
142 VK_CHECK(chain->buffer_count >= info->minImageCount, goto error_mem_alloc,
143 "Insufficient buffer_count(%d >= %d)\n", chain->buffer_count, info->minImageCount);
145 chain->buffers = vk_alloc(allocator, chain->buffer_count * sizeof(vk_buffer_t),
146 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
147 VK_CHECK(chain->buffers, goto error_mem_alloc, "vk_alloc() failed.\n");
149 for (i = 0; i < chain->buffer_count; i++) {
150 VkImageCreateInfo image_info = {
151 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
156 { info->imageExtent.width, info->imageExtent.height, 1 },
158 info->imageArrayLayers,
159 VK_SAMPLE_COUNT_1_BIT,
160 VK_IMAGE_TILING_LINEAR,
162 info->imageSharingMode,
163 info->queueFamilyIndexCount,
164 info->pQueueFamilyIndices,
165 VK_IMAGE_LAYOUT_UNDEFINED,
168 chain->buffers[i].tbm = buffers[i];
169 error = icd->create_presentable_image(device, chain->buffers[i].tbm, &image_info,
170 allocator, &chain->buffers[i].image);
171 VK_CHECK(error == VK_SUCCESS, goto done, "create_presentable_image failed.\n");
178 error = VK_ERROR_OUT_OF_HOST_MEMORY;
181 if (error != VK_SUCCESS) {
182 if (cnt_success > 0) {
183 PFN_vkGetDeviceProcAddr icd_gdpa = (PFN_vkGetDeviceProcAddr)icd->get_proc_addr(NULL, "vkGetDeviceProcAddr");
184 if (icd_gdpa != VK_NULL_HANDLE) {
185 PFN_vkDestroyImage destroy_image = (PFN_vkDestroyImage)icd_gdpa(device, "vkDestroyImage");
186 if (destroy_image != VK_NULL_HANDLE) {
187 for (i = 0; i < cnt_success; i++)
188 destroy_image(device, chain->buffers[i].image, allocator);
193 if (chain->buffers) {
194 vk_free(allocator, chain->buffers);
195 chain->buffers = NULL;
199 chain->deinit(device, chain);
202 vk_free(allocator, chain);
206 *swapchain = VK_NULL_HANDLE;
208 *swapchain = (VkSwapchainKHR)(uintptr_t)chain;
214 VKAPI_ATTR VkResult VKAPI_CALL
215 vk_CreateSharedSwapchainsKHR(VkDevice device,
216 uint32_t swapchain_count,
217 const VkSwapchainCreateInfoKHR *infos,
218 const VkAllocationCallbacks *allocator,
219 VkSwapchainKHR *swapchains)
225 VKAPI_ATTR void VKAPI_CALL
226 vk_DestroySwapchainKHR(VkDevice device,
227 VkSwapchainKHR swapchain,
228 const VkAllocationCallbacks *allocator)
230 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
231 vk_icd_t *icd = vk_get_icd();
232 PFN_vkGetDeviceProcAddr icd_gdpa = (PFN_vkGetDeviceProcAddr)icd->get_proc_addr(NULL, "vkGetDeviceProcAddr");
234 if (chain != VK_NULL_HANDLE) {
235 if (allocator == VK_NULL_HANDLE) {
236 if (chain->allocator == VK_NULL_HANDLE)
237 allocator = vk_get_allocator(NULL, NULL);
239 allocator = chain->allocator;
242 if (icd_gdpa != VK_NULL_HANDLE) {
243 PFN_vkDestroyImage destroy_image = (PFN_vkDestroyImage)icd_gdpa(device, "vkDestroyImage");
244 if (destroy_image != VK_NULL_HANDLE) {
247 for (i = 0; i < chain->buffer_count; i++)
248 destroy_image(device, chain->buffers[i].image, allocator);
252 chain->deinit(device, chain);
253 vk_free(allocator, chain->buffers);
254 vk_free(allocator, chain);
258 VKAPI_ATTR VkResult VKAPI_CALL
259 vk_GetSwapchainImagesKHR(VkDevice device,
260 VkSwapchainKHR swapchain,
261 uint32_t *image_count,
264 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
269 *image_count = MIN(*image_count, chain->buffer_count);
271 for (i = 0; i < *image_count; i++)
272 images[i] = chain->buffers[i].image;
274 if (*image_count < chain->buffer_count)
275 return VK_INCOMPLETE;
277 *image_count = chain->buffer_count;
283 VKAPI_ATTR VkResult VKAPI_CALL
284 vk_AcquireNextImageKHR(VkDevice device,
285 VkSwapchainKHR swapchain,
287 VkSemaphore semaphore,
289 uint32_t *image_index)
292 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)swapchain;
293 vk_icd_t *icd = vk_get_icd();
294 tbm_surface_h tbm_surface;
298 if (icd->acquire_image && fence != VK_NULL_HANDLE)
299 res = chain->acquire_image(device, chain, timeout, &tbm_surface, &sync);
301 res = chain->acquire_image(device, chain, timeout, &tbm_surface, NULL);
302 VK_CHECK(res == VK_SUCCESS, return res, "backend acquire image failed\n.");
304 for (i = 0; i < chain->buffer_count; i++) {
305 if (tbm_surface == chain->buffers[i].tbm) {
307 if (icd->acquire_image)
308 icd->acquire_image(device, chain->buffers[i].image, sync, semaphore, fence);
310 /* TODO: We can do optimization here by returning buffer index immediatly despite the
311 * buffer is not released yet. The fence or semaphore will be signaled when
312 * wl_buffer.release actually arrives. */
318 return VK_ERROR_SURFACE_LOST_KHR;
321 VKAPI_ATTR VkResult VKAPI_CALL
322 vk_QueuePresentKHR(VkQueue queue,
323 const VkPresentInfoKHR *info)
326 vk_icd_t *icd = vk_get_icd();
327 VkResult res = VK_SUCCESS;
328 VkPresentRegionsKHR *region_info = NULL;
329 const VkPresentRegionKHR *regions = NULL;
331 for (i = 0; i < info->swapchainCount; i++) {
333 vk_swapchain_t *chain = (vk_swapchain_t *)(uintptr_t)info->pSwapchains[i];
335 if (icd->queue_signal_release_image)
336 res = icd->queue_signal_release_image(queue, info->waitSemaphoreCount,
337 info->pWaitSemaphores,
338 chain->buffers[info->pImageIndices[i]].image,
340 if (res != VK_SUCCESS)
341 VK_ERROR("Failed to queue_signal_release_image. res(%d)", res);
344 region_info = info->pNext;
346 if (VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR != region_info->sType || region_info->swapchainCount <= 0) {
347 VK_ERROR("issue in using extension (%s)", VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME);
348 res = VK_ERROR_DEVICE_LOST;//TODO return proper error code
351 if (VK_SUCCESS == res) {
352 regions = region_info->pRegions;
356 res = chain->present_image(queue, chain,
357 chain->buffers[info->pImageIndices[i]].tbm, sync_fd, regions ? regions->rectangleCount : 0, regions ? regions->pRectangles : NULL);
359 if (info->pResults != NULL)
360 info->pResults[i] = res;