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 typedef struct vk_swapchain_tpl vk_swapchain_tpl_t;
32 struct vk_swapchain_tpl {
33 tpl_display_t *tpl_display;
34 tpl_surface_t *tpl_surface;
35 tbm_surface_h *buffers;
44 swapchain_tpl_queue_present_image(VkQueue queue,
45 vk_swapchain_t *chain,
46 tbm_surface_h tbm_surface,
49 const VkRectLayerKHR *rects)
52 vk_swapchain_tpl_t *swapchain_tpl = chain->backend_data;
53 struct swap_region *region = NULL;
55 if (chain->is_retired == VK_TRUE) {
56 res = tpl_surface_cancel_dequeued_buffer(swapchain_tpl->tpl_surface, tbm_surface);
57 if (res != TPL_ERROR_NONE)
58 VK_ERROR("failed to cancel_dequeued_buffer. tpl_surface(%p) tbm_surface(%p)\n",
59 swapchain_tpl->tpl_surface, tbm_surface);
61 return VK_ERROR_OUT_OF_DATE_KHR;
65 region = (struct swap_region *)malloc(sizeof(struct swap_region));
68 VK_ERROR("Failed to allocate swap_region");
69 return VK_ERROR_DEVICE_LOST;
72 region->num_rects = num_rects;
74 region->rects = (int *)malloc(sizeof(int) * 4 * num_rects);
77 VK_ERROR("Failed to allocate swap_region->rects.");
79 return VK_ERROR_DEVICE_LOST;
82 for (int i = 0; i < num_rects; i++) {
83 VkRectLayerKHR *pRects = &rects[i];
84 //copy first 4 ints from VkRectLayerKHR
85 memcpy((char *)region->rects + sizeof(int)*4*i, (char *)pRects, sizeof(int) * 4);
89 res = tpl_surface_enqueue_buffer_with_damage_and_sync(swapchain_tpl->tpl_surface,
90 tbm_surface, region ? region->num_rects : 0, region ? region->rects : NULL, sync_fd);
91 if (res == TPL_ERROR_NONE && chain->oldSwapchain != VK_NULL_HANDLE) {
92 chain->oldSwapchain->is_retired = VK_TRUE;
93 chain->oldSwapchain = VK_NULL_HANDLE;
97 if (region->rects) free(region->rects);
101 return res == TPL_ERROR_NONE ? VK_SUCCESS : VK_ERROR_DEVICE_LOST;
105 swapchain_tpl_acquire_next_image(VkDevice device,
106 vk_swapchain_t *chain,
108 tbm_surface_h *tbm_surface,
111 vk_swapchain_tpl_t *swapchain_tpl = chain->backend_data;
113 *tbm_surface = tpl_surface_dequeue_buffer_with_sync(swapchain_tpl->tpl_surface,
116 if (*tbm_surface == NULL && !tpl_surface_validate(swapchain_tpl->tpl_surface)) {
117 /* Returning VK_ERROR_OUT_OF_DATE_KHR calls swapchain_tpl_deinit
118 * to destroy the existing swapchain, but does not want the existing
119 * tpl_surface and tpl_display to be destroyed. */
120 tpl_object_reference((tpl_object_t *)swapchain_tpl->tpl_display);
121 tpl_object_reference((tpl_object_t *)swapchain_tpl->tpl_surface);
122 return VK_ERROR_OUT_OF_DATE_KHR;
125 if (*tbm_surface == NULL) {
128 else if (timeout != UINT64_MAX)
131 return VK_ERROR_SURFACE_LOST_KHR;
138 swapchain_tpl_deinit(VkDevice device,
139 vk_swapchain_t *chain)
141 vk_swapchain_tpl_t *swapchain_tpl = chain->backend_data;
144 tpl_surface_destroy_swapchain(swapchain_tpl->tpl_surface);
146 if (swapchain_tpl->tpl_surface)
147 tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_surface);
149 if (swapchain_tpl->tpl_display)
150 tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_display);
152 if (swapchain_tpl->buffers)
153 free(swapchain_tpl->buffers);
154 vk_free(chain->allocator, swapchain_tpl);
159 swapchain_tpl_get_buffers(VkDevice device,
160 vk_swapchain_t *chain,
161 tbm_surface_h **buffers,
162 uint32_t *buffer_count)
166 VkResult error = VK_SUCCESS;
167 vk_swapchain_tpl_t *swapchain_tpl = chain->backend_data;
169 /* Initialize swapchain buffers. */
170 res = tpl_surface_get_swapchain_buffers(swapchain_tpl->tpl_surface,
171 &swapchain_tpl->buffers, &buffer_cnt);
172 VK_CHECK(res == TPL_ERROR_NONE, goto done, "tpl_surface_get_swapchain_buffers() failed.\n");
174 *buffers = swapchain_tpl->buffers;
175 *buffer_count = buffer_cnt;
178 if (res == TPL_ERROR_OUT_OF_MEMORY)
179 error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
180 else if (res != TPL_ERROR_NONE)
181 error = VK_ERROR_SURFACE_LOST_KHR;
187 swapchain_tpl_init(VkDevice device,
188 const VkSwapchainCreateInfoKHR *info,
189 vk_swapchain_t *chain,
193 VkIcdSurfaceBase *surface = (VkIcdSurfaceBase *)(uintptr_t)info->surface;
194 vk_swapchain_tpl_t *swapchain_tpl;
195 tpl_handle_t native_window;
196 int tpl_present_mode;
197 vk_bool_t need_to_create = VK_TRUE;
199 VkResult error = VK_ERROR_DEVICE_LOST;
201 swapchain_tpl = vk_alloc(chain->allocator, sizeof(vk_swapchain_tpl_t),
202 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
203 VK_CHECK(swapchain_tpl, goto error, "vk_alloc() failed.\n");
204 memset(swapchain_tpl, 0x00, sizeof(*swapchain_tpl));
205 chain->backend_data = swapchain_tpl;
207 /* Don't check NULL for display and window. There might be default ones for some systems. */
209 swapchain_tpl->tpl_display = vk_get_tpl_display(surface);
210 VK_CHECK(swapchain_tpl->tpl_display, goto error, "vk_get_tpl_display() failed.\n");
211 native_window = vk_get_tpl_native_window(surface);
213 swapchain_tpl->tpl_surface = tpl_surface_get(swapchain_tpl->tpl_display,
215 if (swapchain_tpl->tpl_surface) {
216 if (chain->oldSwapchain != VK_NULL_HANDLE) {
217 vk_swapchain_tpl_t *oldSwapchain_tpl =
218 (vk_swapchain_tpl_t *)chain->oldSwapchain->backend_data;
219 if (tpl_surface_validate(oldSwapchain_tpl->tpl_surface))
220 need_to_create = VK_TRUE;
222 need_to_create = VK_FALSE;
224 need_to_create = VK_FALSE;
229 swapchain_tpl->tpl_surface = tpl_surface_create(swapchain_tpl->tpl_display,
231 TPL_SURFACE_TYPE_WINDOW, format);
233 tpl_object_reference((tpl_object_t *)swapchain_tpl->tpl_surface);
236 VK_CHECK(swapchain_tpl->tpl_surface, goto error, "tpl_surface_create() failed.\n");
238 switch(info->presentMode) {
239 case VK_PRESENT_MODE_IMMEDIATE_KHR:
240 tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_IMMEDIATE;
242 case VK_PRESENT_MODE_MAILBOX_KHR:
243 tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_MAILBOX;
245 case VK_PRESENT_MODE_FIFO_KHR:
246 tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO;
248 case VK_PRESENT_MODE_FIFO_RELAXED_KHR:
249 tpl_present_mode = TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED;
252 VK_DEBUG("Unsupported present mode: 0x%x\n", info->presentMode);
256 res = tpl_surface_create_swapchain(swapchain_tpl->tpl_surface, format,
257 info->imageExtent.width, info->imageExtent.height,
258 info->minImageCount, tpl_present_mode);
259 if (res == TPL_ERROR_OUT_OF_MEMORY) {
260 error = VK_ERROR_OUT_OF_DEVICE_MEMORY;
261 VK_ERROR("tpl_surface_create_swapchain() failed.\n");
264 VK_CHECK(res == TPL_ERROR_NONE, goto error, "tpl_surface_create_swapchain() failed.\n");
266 chain->get_buffers = swapchain_tpl_get_buffers;
267 chain->deinit = swapchain_tpl_deinit;
268 chain->acquire_image = swapchain_tpl_acquire_next_image;
269 chain->present_image = swapchain_tpl_queue_present_image;
275 if (swapchain_tpl->tpl_display)
276 tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_display);
278 if (swapchain_tpl->tpl_surface)
279 tpl_object_unreference((tpl_object_t *)swapchain_tpl->tpl_surface);
281 vk_free(chain->allocator, swapchain_tpl);
283 error = VK_ERROR_OUT_OF_HOST_MEMORY;