Merge remote-tracking branch 'public/master' into vulkan
[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_instance *instance)
28 {
29 VkResult result;
30
31 result = anv_x11_init_wsi(instance);
32 if (result != VK_SUCCESS)
33 return result;
34
35 #ifdef HAVE_WAYLAND_PLATFORM
36 result = anv_wl_init_wsi(instance);
37 if (result != VK_SUCCESS) {
38 anv_x11_finish_wsi(instance);
39 return result;
40 }
41 #endif
42
43 return VK_SUCCESS;
44 }
45
46 void
47 anv_finish_wsi(struct anv_instance *instance)
48 {
49 #ifdef HAVE_WAYLAND_PLATFORM
50 anv_wl_finish_wsi(instance);
51 #endif
52 anv_x11_finish_wsi(instance);
53 }
54
55 void anv_DestroySurfaceKHR(
56 VkInstance _instance,
57 VkSurfaceKHR _surface,
58 const VkAllocationCallbacks* pAllocator)
59 {
60 ANV_FROM_HANDLE(anv_instance, instance, _instance);
61 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
62
63 anv_free2(&instance->alloc, pAllocator, surface);
64 }
65
66 VkResult anv_GetPhysicalDeviceSurfaceSupportKHR(
67 VkPhysicalDevice physicalDevice,
68 uint32_t queueFamilyIndex,
69 VkSurfaceKHR _surface,
70 VkBool32* pSupported)
71 {
72 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
73 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
74 struct anv_wsi_interface *iface = device->instance->wsi[surface->platform];
75
76 return iface->get_support(surface, device, queueFamilyIndex, pSupported);
77 }
78
79 VkResult anv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
80 VkPhysicalDevice physicalDevice,
81 VkSurfaceKHR _surface,
82 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
83 {
84 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
85 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
86 struct anv_wsi_interface *iface = device->instance->wsi[surface->platform];
87
88 return iface->get_capabilities(surface, device, pSurfaceCapabilities);
89 }
90
91 VkResult anv_GetPhysicalDeviceSurfaceFormatsKHR(
92 VkPhysicalDevice physicalDevice,
93 VkSurfaceKHR _surface,
94 uint32_t* pSurfaceFormatCount,
95 VkSurfaceFormatKHR* pSurfaceFormats)
96 {
97 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
98 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
99 struct anv_wsi_interface *iface = device->instance->wsi[surface->platform];
100
101 return iface->get_formats(surface, device, pSurfaceFormatCount,
102 pSurfaceFormats);
103 }
104
105 VkResult anv_GetPhysicalDeviceSurfacePresentModesKHR(
106 VkPhysicalDevice physicalDevice,
107 VkSurfaceKHR _surface,
108 uint32_t* pPresentModeCount,
109 VkPresentModeKHR* pPresentModes)
110 {
111 ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
112 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, _surface);
113 struct anv_wsi_interface *iface = device->instance->wsi[surface->platform];
114
115 return iface->get_present_modes(surface, device, pPresentModeCount,
116 pPresentModes);
117 }
118
119 VkResult anv_CreateSwapchainKHR(
120 VkDevice _device,
121 const VkSwapchainCreateInfoKHR* pCreateInfo,
122 const VkAllocationCallbacks* pAllocator,
123 VkSwapchainKHR* pSwapchain)
124 {
125 ANV_FROM_HANDLE(anv_device, device, _device);
126 ANV_FROM_HANDLE(_VkIcdSurfaceBase, surface, pCreateInfo->surface);
127 struct anv_wsi_interface *iface = device->instance->wsi[surface->platform];
128 struct anv_swapchain *swapchain;
129
130 VkResult result = iface->create_swapchain(surface, device, pCreateInfo,
131 pAllocator, &swapchain);
132 if (result != VK_SUCCESS)
133 return result;
134
135 if (pAllocator)
136 swapchain->alloc = *pAllocator;
137 else
138 swapchain->alloc = device->alloc;
139
140 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++)
141 swapchain->fences[i] = VK_NULL_HANDLE;
142
143 *pSwapchain = anv_swapchain_to_handle(swapchain);
144
145 return VK_SUCCESS;
146 }
147
148 void anv_DestroySwapchainKHR(
149 VkDevice device,
150 VkSwapchainKHR _swapchain,
151 const VkAllocationCallbacks* pAllocator)
152 {
153 ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
154
155 for (unsigned i = 0; i < ARRAY_SIZE(swapchain->fences); i++) {
156 if (swapchain->fences[i] != VK_NULL_HANDLE)
157 anv_DestroyFence(device, swapchain->fences[i], pAllocator);
158 }
159
160 swapchain->destroy(swapchain, pAllocator);
161 }
162
163 VkResult anv_GetSwapchainImagesKHR(
164 VkDevice device,
165 VkSwapchainKHR _swapchain,
166 uint32_t* pSwapchainImageCount,
167 VkImage* pSwapchainImages)
168 {
169 ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
170
171 return swapchain->get_images(swapchain, pSwapchainImageCount,
172 pSwapchainImages);
173 }
174
175 VkResult anv_AcquireNextImageKHR(
176 VkDevice device,
177 VkSwapchainKHR _swapchain,
178 uint64_t timeout,
179 VkSemaphore semaphore,
180 VkFence fence,
181 uint32_t* pImageIndex)
182 {
183 ANV_FROM_HANDLE(anv_swapchain, swapchain, _swapchain);
184
185 return swapchain->acquire_next_image(swapchain, timeout, semaphore,
186 pImageIndex);
187 }
188
189 VkResult anv_QueuePresentKHR(
190 VkQueue _queue,
191 const VkPresentInfoKHR* pPresentInfo)
192 {
193 ANV_FROM_HANDLE(anv_queue, queue, _queue);
194 VkResult result;
195
196 for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
197 ANV_FROM_HANDLE(anv_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
198
199 assert(swapchain->device == queue->device);
200
201 if (swapchain->fences[0] == VK_NULL_HANDLE) {
202 result = anv_CreateFence(anv_device_to_handle(queue->device),
203 &(VkFenceCreateInfo) {
204 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
205 .flags = 0,
206 }, &swapchain->alloc, &swapchain->fences[0]);
207 if (result != VK_SUCCESS)
208 return result;
209 } else {
210 anv_ResetFences(anv_device_to_handle(queue->device),
211 1, &swapchain->fences[0]);
212 }
213
214 anv_QueueSubmit(_queue, 0, NULL, swapchain->fences[0]);
215
216 result = swapchain->queue_present(swapchain, queue,
217 pPresentInfo->pImageIndices[i]);
218 /* TODO: What if one of them returns OUT_OF_DATE? */
219 if (result != VK_SUCCESS)
220 return result;
221
222 VkFence last = swapchain->fences[2];
223 swapchain->fences[2] = swapchain->fences[1];
224 swapchain->fences[1] = swapchain->fences[0];
225 swapchain->fences[0] = last;
226
227 if (last != VK_NULL_HANDLE) {
228 anv_WaitForFences(anv_device_to_handle(queue->device),
229 1, &last, true, 1);
230 }
231 }
232
233 return VK_SUCCESS;
234 }