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