975ad18146cf699462cd088d5c14e53503792e2f
[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_private.h"
25 #include "wsi_common.h"
26 #include "vk_format_info.h"
27 #include "vk_util.h"
28
29 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
30 #define WSI_CB(x) .x = anv_##x
31 static const struct wsi_callbacks wsi_cbs = {
32 WSI_CB(GetPhysicalDeviceFormatProperties),
33 };
34 #endif
35
36 static PFN_vkVoidFunction
37 anv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
38 {
39 ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
40 return anv_lookup_entrypoint(&physical_device->info, pName);
41 }
42
43 static uint32_t
44 anv_wsi_queue_get_family_index(VkQueue queue)
45 {
46 return 0;
47 }
48
49 VkResult
50 anv_init_wsi(struct anv_physical_device *physical_device)
51 {
52 VkResult result;
53
54 wsi_device_init(&physical_device->wsi_device,
55 anv_physical_device_to_handle(physical_device),
56 anv_wsi_proc_addr);
57
58 physical_device->wsi_device.queue_get_family_index =
59 anv_wsi_queue_get_family_index;
60
61 #ifdef VK_USE_PLATFORM_XCB_KHR
62 result = wsi_x11_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
63 if (result != VK_SUCCESS)
64 return result;
65 #endif
66
67 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
68 result = wsi_wl_init_wsi(&physical_device->wsi_device, &physical_device->instance->alloc,
69 anv_physical_device_to_handle(physical_device),
70 &wsi_cbs);
71 if (result != VK_SUCCESS) {
72 #ifdef VK_USE_PLATFORM_XCB_KHR
73 wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
74 #endif
75 return result;
76 }
77 #endif
78
79 return VK_SUCCESS;
80 }
81
82 void
83 anv_finish_wsi(struct anv_physical_device *physical_device)
84 {
85 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
86 wsi_wl_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
87 #endif
88 #ifdef VK_USE_PLATFORM_XCB_KHR
89 wsi_x11_finish_wsi(&physical_device->wsi_device, &physical_device->instance->alloc);
90 #endif
91 }
92
93 void anv_DestroySurfaceKHR(
94 VkInstance _instance,
95 VkSurfaceKHR _surface,
96 const VkAllocationCallbacks* pAllocator)
97 {
98 ANV_FROM_HANDLE(anv_instance, instance, _instance);
99 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
100
101 if (!surface)
102 return;
103
104 vk_free2(&instance->alloc, pAllocator, surface);
105 }
106
107 VkResult anv_GetPhysicalDeviceSurfaceSupportKHR(
108 VkPhysicalDevice physicalDevice,
109 uint32_t queueFamilyIndex,
110 VkSurfaceKHR _surface,
111 VkBool32* pSupported)
112 {
113 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
114 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
115 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
116
117 return iface->get_support(surface, &device->wsi_device,
118 &device->instance->alloc,
119 queueFamilyIndex, device->local_fd, true, pSupported);
120 }
121
122 VkResult anv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
123 VkPhysicalDevice physicalDevice,
124 VkSurfaceKHR _surface,
125 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
126 {
127 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
128 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
129 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
130
131 return iface->get_capabilities(surface, pSurfaceCapabilities);
132 }
133
134 VkResult anv_GetPhysicalDeviceSurfaceCapabilities2KHR(
135 VkPhysicalDevice physicalDevice,
136 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
137 VkSurfaceCapabilities2KHR* pSurfaceCapabilities)
138 {
139 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
140 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
141 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
142
143 return iface->get_capabilities2(surface, pSurfaceInfo->pNext,
144 pSurfaceCapabilities);
145 }
146
147 VkResult anv_GetPhysicalDeviceSurfaceFormatsKHR(
148 VkPhysicalDevice physicalDevice,
149 VkSurfaceKHR _surface,
150 uint32_t* pSurfaceFormatCount,
151 VkSurfaceFormatKHR* pSurfaceFormats)
152 {
153 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
154 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
155 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
156
157 return iface->get_formats(surface, &device->wsi_device, pSurfaceFormatCount,
158 pSurfaceFormats);
159 }
160
161 VkResult anv_GetPhysicalDeviceSurfaceFormats2KHR(
162 VkPhysicalDevice physicalDevice,
163 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
164 uint32_t* pSurfaceFormatCount,
165 VkSurfaceFormat2KHR* pSurfaceFormats)
166 {
167 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
168 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
169 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
170
171 return iface->get_formats2(surface, &device->wsi_device, pSurfaceInfo->pNext,
172 pSurfaceFormatCount, pSurfaceFormats);
173 }
174
175 VkResult anv_GetPhysicalDeviceSurfacePresentModesKHR(
176 VkPhysicalDevice physicalDevice,
177 VkSurfaceKHR _surface,
178 uint32_t* pPresentModeCount,
179 VkPresentModeKHR* pPresentModes)
180 {
181 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
182 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
183 struct wsi_interface *iface = device->wsi_device.wsi[surface->platform];
184
185 return iface->get_present_modes(surface, pPresentModeCount,
186 pPresentModes);
187 }
188
189 VkResult anv_CreateSwapchainKHR(
190 VkDevice _device,
191 const VkSwapchainCreateInfoKHR* pCreateInfo,
192 const VkAllocationCallbacks* pAllocator,
193 VkSwapchainKHR* pSwapchain)
194 {
195 ANV_FROM_HANDLE(anv_device, device, _device);
196 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
197 struct wsi_interface *iface =
198 device->instance->physicalDevice.wsi_device.wsi[surface->platform];
199 struct wsi_swapchain *swapchain;
200 const VkAllocationCallbacks *alloc;
201
202 if (pAllocator)
203 alloc = pAllocator;
204 else
205 alloc = &device->alloc;
206 VkResult result = iface->create_swapchain(surface, _device,
207 &device->instance->physicalDevice.wsi_device,
208 device->instance->physicalDevice.local_fd,
209 pCreateInfo,
210 alloc,
211 &swapchain);
212 if (result != VK_SUCCESS)
213 return result;
214
215 swapchain->alloc = *alloc;
216
217 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++)
218 swapchain->fences[i] = VK_NULL_HANDLE;
219
220 *pSwapchain = wsi_swapchain_to_handle(swapchain);
221
222 return VK_SUCCESS;
223 }
224
225 void anv_DestroySwapchainKHR(
226 VkDevice _device,
227 VkSwapchainKHR _swapchain,
228 const VkAllocationCallbacks* pAllocator)
229 {
230 ANV_FROM_HANDLE(anv_device, device, _device);
231 ANV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
232 const VkAllocationCallbacks *alloc;
233
234 if (!swapchain)
235 return;
236
237 if (pAllocator)
238 alloc = pAllocator;
239 else
240 alloc = &device->alloc;
241 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) {
242 if (swapchain->fences[i] != VK_NULL_HANDLE)
243 anv_DestroyFence(_device, swapchain->fences[i], pAllocator);
244 }
245
246 swapchain->destroy(swapchain, alloc);
247 }
248
249 VkResult anv_GetSwapchainImagesKHR(
250 VkDevice device,
251 VkSwapchainKHR _swapchain,
252 uint32_t* pSwapchainImageCount,
253 VkImage* pSwapchainImages)
254 {
255 ANV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
256
257 return swapchain->get_images(swapchain, pSwapchainImageCount,
258 pSwapchainImages);
259 }
260
261 VkResult anv_AcquireNextImageKHR(
262 VkDevice _device,
263 VkSwapchainKHR _swapchain,
264 uint64_t timeout,
265 VkSemaphore semaphore,
266 VkFence _fence,
267 uint32_t* pImageIndex)
268 {
269 ANV_FROM_HANDLE(anv_device, device, _device);
270 ANV_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
271 ANV_FROM_HANDLE(anv_fence, fence, _fence);
272
273 VkResult result = swapchain->acquire_next_image(swapchain, timeout,
274 semaphore, pImageIndex);
275
276 /* Thanks to implicit sync, the image is ready immediately. However, we
277 * should wait for the current GPU state to finish.
278 */
279 if (fence)
280 anv_QueueSubmit(anv_queue_to_handle(&device->queue), 0, NULL, _fence);
281
282 return result;
283 }
284
285 VkResult anv_QueuePresentKHR(
286 VkQueue _queue,
287 const VkPresentInfoKHR* pPresentInfo)
288 {
289 ANV_FROM_HANDLE(anv_queue, queue, _queue);
290 struct anv_physical_device *pdevice =
291 &queue->device->instance->physicalDevice;
292
293 return wsi_common_queue_present(&pdevice->wsi_device,
294 anv_device_to_handle(queue->device),
295 _queue, 0,
296 pPresentInfo);
297 }