ce9ec32f3ecc260e666137ab04779fc4cbcbe402
[mesa.git] / src / intel / vulkan / anv_wsi.c
1 /*
2 * Copyright © 2015 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "anv_wsi.h"
25
26 VkResult
27 anv_init_wsi(struct anv_physical_device *physical_device)
28 {
29 VkResult result;
30
31 memset(physical_device->wsi, 0, sizeof(physical_device->wsi));
32
33 #ifdef VK_USE_PLATFORM_XCB_KHR
34 result = anv_x11_init_wsi(physical_device);
35 if (result != VK_SUCCESS)
36 return result;
37 #endif
38
39 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
40 result = anv_wl_init_wsi(physical_device);
41 if (result != VK_SUCCESS) {
42 anv_x11_finish_wsi(physical_device);
43 return result;
44 }
45 #endif
46
47 return VK_SUCCESS;
48 }
49
50 void
51 anv_finish_wsi(struct anv_physical_device *physical_device)
52 {
53 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
54 anv_wl_finish_wsi(physical_device);
55 #endif
56 #ifdef VK_USE_PLATFORM_XCB_KHR
57 anv_x11_finish_wsi(physical_device);
58 #endif
59 }
60
61 void anv_DestroySurfaceKHR(
62 VkInstance _instance,
63 VkSurfaceKHR _surface,
64 const VkAllocationCallbacks* pAllocator)
65 {
66 ANV_FROM_HANDLE(anv_instance, instance, _instance);
67 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
68
69 anv_free2(&instance->alloc, pAllocator, surface);
70 }
71
72 VkResult anv_GetPhysicalDeviceSurfaceSupportKHR(
73 VkPhysicalDevice physicalDevice,
74 uint32_t queueFamilyIndex,
75 VkSurfaceKHR _surface,
76 VkBool32* pSupported)
77 {
78 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
79 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
80 struct anv_wsi_interface *iface = device->wsi[surface->platform];
81
82 return iface->get_support(surface, device, queueFamilyIndex, pSupported);
83 }
84
85 VkResult anv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
86 VkPhysicalDevice physicalDevice,
87 VkSurfaceKHR _surface,
88 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
89 {
90 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
91 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
92 struct anv_wsi_interface *iface = device->wsi[surface->platform];
93
94 return iface->get_capabilities(surface, device, pSurfaceCapabilities);
95 }
96
97 VkResult anv_GetPhysicalDeviceSurfaceFormatsKHR(
98 VkPhysicalDevice physicalDevice,
99 VkSurfaceKHR _surface,
100 uint32_t* pSurfaceFormatCount,
101 VkSurfaceFormatKHR* pSurfaceFormats)
102 {
103 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
104 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
105 struct anv_wsi_interface *iface = device->wsi[surface->platform];
106
107 return iface->get_formats(surface, device, pSurfaceFormatCount,
108 pSurfaceFormats);
109 }
110
111 VkResult anv_GetPhysicalDeviceSurfacePresentModesKHR(
112 VkPhysicalDevice physicalDevice,
113 VkSurfaceKHR _surface,
114 uint32_t* pPresentModeCount,
115 VkPresentModeKHR* pPresentModes)
116 {
117 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
118 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
119 struct anv_wsi_interface *iface = device->wsi[surface->platform];
120
121 return iface->get_present_modes(surface, device, pPresentModeCount,
122 pPresentModes);
123 }
124
125 VkResult anv_CreateSwapchainKHR(
126 VkDevice _device,
127 const VkSwapchainCreateInfoKHR* pCreateInfo,
128 const VkAllocationCallbacks* pAllocator,
129 VkSwapchainKHR* pSwapchain)
130 {
131 ANV_FROM_HANDLE(anv_device, device, _device);
132 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, pCreateInfo->surface);
133 struct anv_wsi_interface *iface =
134 device->instance->physicalDevice.wsi[surface->platform];
135 struct anv_swapchain *swapchain;
136
137 VkResult result = iface->create_swapchain(surface, device, pCreateInfo,
138 pAllocator, &swapchain);
139 if (result != VK_SUCCESS)
140 return result;
141
142 if (pAllocator)
143 swapchain->alloc = *pAllocator;
144 else
145 swapchain->alloc = device->alloc;
146
147 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++)
148 swapchain->fences[i] = VK_NULL_HANDLE;
149
150 *pSwapchain = anv_swapchain_to_handle(swapchain);
151
152 return VK_SUCCESS;
153 }
154
155 void anv_DestroySwapchainKHR(
156 VkDevice device,
157 VkSwapchainKHR _swapchain,
158 const VkAllocationCallbacks* pAllocator)
159 {
160 ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
161
162 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) {
163 if (swapchain->fences[i] != VK_NULL_HANDLE)
164 anv_DestroyFence(device, swapchain->fences[i], pAllocator);
165 }
166
167 swapchain->destroy(swapchain, pAllocator);
168 }
169
170 VkResult anv_GetSwapchainImagesKHR(
171 VkDevice device,
172 VkSwapchainKHR _swapchain,
173 uint32_t* pSwapchainImageCount,
174 VkImage* pSwapchainImages)
175 {
176 ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
177
178 return swapchain->get_images(swapchain, pSwapchainImageCount,
179 pSwapchainImages);
180 }
181
182 VkResult anv_AcquireNextImageKHR(
183 VkDevice device,
184 VkSwapchainKHR _swapchain,
185 uint64_t timeout,
186 VkSemaphore semaphore,
187 VkFence fence,
188 uint32_t* pImageIndex)
189 {
190 ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
191
192 return swapchain->acquire_next_image(swapchain, timeout, semaphore,
193 pImageIndex);
194 }
195
196 VkResult anv_QueuePresentKHR(
197 VkQueue _queue,
198 const VkPresentInfoKHR* pPresentInfo)
199 {
200 ANV_FROM_HANDLE(anv_queue, queue, _queue);
201 VkResult result;
202
203 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
204 ANV_FROM_HANDLE(anv_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
205
206 assert(swapchain->device == queue->device);
207
208 if (swapchain->fences[0] == VK_NULL_HANDLE) {
209 result = anv_CreateFence(anv_device_to_handle(queue->device),
210 &(VkFenceCreateInfo) {
211 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
212 .flags = 0,
213 }, &swapchain->alloc, &swapchain->fences[0]);
214 if (result != VK_SUCCESS)
215 return result;
216 } else {
217 anv_ResetFences(anv_device_to_handle(queue->device),
218 1, &swapchain->fences[0]);
219 }
220
221 anv_QueueSubmit(_queue, 0, NULL, swapchain->fences[0]);
222
223 result = swapchain->queue_present(swapchain, queue,
224 pPresentInfo->pImageIndices[i]);
225 /* TODO: What if one of them returns OUT_OF_DATE? */
226 if (result != VK_SUCCESS)
227 return result;
228
229 VkFence last = swapchain->fences[2];
230 swapchain->fences[2] = swapchain->fences[1];
231 swapchain->fences[1] = swapchain->fences[0];
232 swapchain->fences[0] = last;
233
234 if (last != VK_NULL_HANDLE) {
235 anv_WaitForFences(anv_device_to_handle(queue->device),
236 1, &last, true, 1);
237 }
238 }
239
240 return VK_SUCCESS;
241 }