1 /*
2 * Copyright © 2020 Raspberry Pi
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 "v3dv_private.h"
27 #include "drm-uapi/drm_fourcc.h"
28 #include "vk_format_info.h"
29 #include "vk_util.h"
30 #include "wsi_common.h"
31
32 static PFN_vkVoidFunction
v3dv_wsi_proc_addr(VkPhysicalDevice physicalDevice,const char * pName)33 v3dv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
34 {
35 V3DV_FROM_HANDLE(v3dv_physical_device, physical_device, physicalDevice);
36 return v3dv_lookup_entrypoint(&physical_device->devinfo, pName);
37 }
38
39 VkResult
v3dv_wsi_init(struct v3dv_physical_device * physical_device)40 v3dv_wsi_init(struct v3dv_physical_device *physical_device)
41 {
42 VkResult result;
43
44 result = wsi_device_init(&physical_device->wsi_device,
45 v3dv_physical_device_to_handle(physical_device),
46 v3dv_wsi_proc_addr,
47 &physical_device->instance->alloc,
48 physical_device->display_fd, NULL, false);
49
50 if (result != VK_SUCCESS)
51 return result;
52
53 physical_device->wsi_device.supports_modifiers = true;
54
55 return VK_SUCCESS;
56 }
57
58 void
v3dv_wsi_finish(struct v3dv_physical_device * physical_device)59 v3dv_wsi_finish(struct v3dv_physical_device *physical_device)
60 {
61 wsi_device_finish(&physical_device->wsi_device,
62 &physical_device->instance->alloc);
63 }
64
v3dv_DestroySurfaceKHR(VkInstance _instance,VkSurfaceKHR _surface,const VkAllocationCallbacks * pAllocator)65 void v3dv_DestroySurfaceKHR(
66 VkInstance _instance,
67 VkSurfaceKHR _surface,
68 const VkAllocationCallbacks* pAllocator)
69 {
70 V3DV_FROM_HANDLE(v3dv_instance, instance, _instance);
71 ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
72
73 if (!surface)
74 return;
75
76 vk_free2(&instance->alloc, pAllocator, surface);
77 }
78
v3dv_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,uint32_t queueFamilyIndex,VkSurfaceKHR surface,VkBool32 * pSupported)79 VkResult v3dv_GetPhysicalDeviceSurfaceSupportKHR(
80 VkPhysicalDevice physicalDevice,
81 uint32_t queueFamilyIndex,
82 VkSurfaceKHR surface,
83 VkBool32* pSupported)
84 {
85 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
86
87 return wsi_common_get_surface_support(&device->wsi_device,
88 queueFamilyIndex,
89 surface,
90 pSupported);
91 }
92
93 static void
contraint_surface_capabilities(VkSurfaceCapabilitiesKHR * caps)94 contraint_surface_capabilities(VkSurfaceCapabilitiesKHR *caps)
95 {
96 /* Our display pipeline requires that images are linear, so we cannot
97 * ensure that our swapchain images can be sampled. If we are running under
98 * a compositor in windowed mode, the DRM modifier negotiation should
99 * probably end up selecting an UIF layout for the swapchain images but it
100 * may still choose linear and send images directly for scanout if the
101 * surface is in fullscreen mode for example. If we are not running under
102 * a compositor, then we would always need them to be linear anyway.
103 */
104 caps->supportedUsageFlags &= ~VK_IMAGE_USAGE_SAMPLED_BIT;
105 }
106
v3dv_GetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,VkSurfaceCapabilitiesKHR * pSurfaceCapabilities)107 VkResult v3dv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
108 VkPhysicalDevice physicalDevice,
109 VkSurfaceKHR surface,
110 VkSurfaceCapabilitiesKHR* pSurfaceCapabilities)
111 {
112 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
113
114 VkResult result;
115 result = wsi_common_get_surface_capabilities(&device->wsi_device,
116 surface,
117 pSurfaceCapabilities);
118 contraint_surface_capabilities(pSurfaceCapabilities);
119 return result;
120 }
121
v3dv_GetPhysicalDeviceSurfaceCapabilities2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,VkSurfaceCapabilities2KHR * pSurfaceCapabilities)122 VkResult v3dv_GetPhysicalDeviceSurfaceCapabilities2KHR(
123 VkPhysicalDevice physicalDevice,
124 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
125 VkSurfaceCapabilities2KHR* pSurfaceCapabilities)
126 {
127 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
128
129 VkResult result;
130 result = wsi_common_get_surface_capabilities2(&device->wsi_device,
131 pSurfaceInfo,
132 pSurfaceCapabilities);
133 contraint_surface_capabilities(&pSurfaceCapabilities->surfaceCapabilities);
134 return result;
135 }
136
v3dv_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pSurfaceFormatCount,VkSurfaceFormatKHR * pSurfaceFormats)137 VkResult v3dv_GetPhysicalDeviceSurfaceFormatsKHR(
138 VkPhysicalDevice physicalDevice,
139 VkSurfaceKHR surface,
140 uint32_t* pSurfaceFormatCount,
141 VkSurfaceFormatKHR* pSurfaceFormats)
142 {
143 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
144
145 return wsi_common_get_surface_formats(&device->wsi_device, surface,
146 pSurfaceFormatCount, pSurfaceFormats);
147 }
148
v3dv_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,uint32_t * pSurfaceFormatCount,VkSurfaceFormat2KHR * pSurfaceFormats)149 VkResult v3dv_GetPhysicalDeviceSurfaceFormats2KHR(
150 VkPhysicalDevice physicalDevice,
151 const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
152 uint32_t* pSurfaceFormatCount,
153 VkSurfaceFormat2KHR* pSurfaceFormats)
154 {
155 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
156
157 return wsi_common_get_surface_formats2(&device->wsi_device, pSurfaceInfo,
158 pSurfaceFormatCount, pSurfaceFormats);
159 }
160
v3dv_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pPresentModeCount,VkPresentModeKHR * pPresentModes)161 VkResult v3dv_GetPhysicalDeviceSurfacePresentModesKHR(
162 VkPhysicalDevice physicalDevice,
163 VkSurfaceKHR surface,
164 uint32_t* pPresentModeCount,
165 VkPresentModeKHR* pPresentModes)
166 {
167 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
168
169 return wsi_common_get_surface_present_modes(&device->wsi_device, surface,
170 pPresentModeCount,
171 pPresentModes);
172 }
173
v3dv_CreateSwapchainKHR(VkDevice _device,const VkSwapchainCreateInfoKHR * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkSwapchainKHR * pSwapchain)174 VkResult v3dv_CreateSwapchainKHR(
175 VkDevice _device,
176 const VkSwapchainCreateInfoKHR* pCreateInfo,
177 const VkAllocationCallbacks* pAllocator,
178 VkSwapchainKHR* pSwapchain)
179 {
180 V3DV_FROM_HANDLE(v3dv_device, device, _device);
181 struct wsi_device *wsi_device = &device->instance->physicalDevice.wsi_device;
182 const VkAllocationCallbacks *alloc;
183
184 if (pAllocator)
185 alloc = pAllocator;
186 else
187 alloc = &device->alloc;
188
189 return wsi_common_create_swapchain(wsi_device, _device,
190 pCreateInfo, alloc, pSwapchain);
191 }
192
v3dv_DestroySwapchainKHR(VkDevice _device,VkSwapchainKHR swapchain,const VkAllocationCallbacks * pAllocator)193 void v3dv_DestroySwapchainKHR(
194 VkDevice _device,
195 VkSwapchainKHR swapchain,
196 const VkAllocationCallbacks* pAllocator)
197 {
198 V3DV_FROM_HANDLE(v3dv_device, device, _device);
199 const VkAllocationCallbacks *alloc;
200
201 if (pAllocator)
202 alloc = pAllocator;
203 else
204 alloc = &device->alloc;
205
206 wsi_common_destroy_swapchain(_device, swapchain, alloc);
207 }
208
v3dv_GetSwapchainImagesKHR(VkDevice device,VkSwapchainKHR swapchain,uint32_t * pSwapchainImageCount,VkImage * pSwapchainImages)209 VkResult v3dv_GetSwapchainImagesKHR(
210 VkDevice device,
211 VkSwapchainKHR swapchain,
212 uint32_t* pSwapchainImageCount,
213 VkImage* pSwapchainImages)
214 {
215 return wsi_common_get_images(swapchain,
216 pSwapchainImageCount,
217 pSwapchainImages);
218 }
219
v3dv_AcquireNextImageKHR(VkDevice device,VkSwapchainKHR swapchain,uint64_t timeout,VkSemaphore semaphore,VkFence fence,uint32_t * pImageIndex)220 VkResult v3dv_AcquireNextImageKHR(
221 VkDevice device,
222 VkSwapchainKHR swapchain,
223 uint64_t timeout,
224 VkSemaphore semaphore,
225 VkFence fence,
226 uint32_t* pImageIndex)
227 {
228 VkAcquireNextImageInfoKHR acquire_info = {
229 .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
230 .swapchain = swapchain,
231 .timeout = timeout,
232 .semaphore = semaphore,
233 .fence = fence,
234 .deviceMask = 0,
235 };
236
237 return v3dv_AcquireNextImage2KHR(device, &acquire_info, pImageIndex);
238 }
239
v3dv_AcquireNextImage2KHR(VkDevice _device,const VkAcquireNextImageInfoKHR * pAcquireInfo,uint32_t * pImageIndex)240 VkResult v3dv_AcquireNextImage2KHR(
241 VkDevice _device,
242 const VkAcquireNextImageInfoKHR* pAcquireInfo,
243 uint32_t* pImageIndex)
244 {
245 V3DV_FROM_HANDLE(v3dv_device, device, _device);
246 V3DV_FROM_HANDLE(v3dv_fence, fence, pAcquireInfo->fence);
247 V3DV_FROM_HANDLE(v3dv_semaphore, semaphore, pAcquireInfo->semaphore);
248
249 struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
250
251 VkResult result;
252 result = wsi_common_acquire_next_image2(&pdevice->wsi_device, _device,
253 pAcquireInfo, pImageIndex);
254
255 if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) {
256 if (fence)
257 drmSyncobjSignal(device->render_fd, &fence->sync, 1);
258 if (semaphore)
259 drmSyncobjSignal(device->render_fd, &semaphore->sync, 1);
260 }
261
262 return result;
263 }
264
v3dv_QueuePresentKHR(VkQueue _queue,const VkPresentInfoKHR * pPresentInfo)265 VkResult v3dv_QueuePresentKHR(
266 VkQueue _queue,
267 const VkPresentInfoKHR* pPresentInfo)
268 {
269 V3DV_FROM_HANDLE(v3dv_queue, queue, _queue);
270 struct v3dv_physical_device *pdevice =
271 &queue->device->instance->physicalDevice;
272
273 return wsi_common_queue_present(&pdevice->wsi_device,
274 v3dv_device_to_handle(queue->device),
275 _queue, 0,
276 pPresentInfo);
277 }
278
v3dv_GetDeviceGroupPresentCapabilitiesKHR(VkDevice device,VkDeviceGroupPresentCapabilitiesKHR * pCapabilities)279 VkResult v3dv_GetDeviceGroupPresentCapabilitiesKHR(
280 VkDevice device,
281 VkDeviceGroupPresentCapabilitiesKHR* pCapabilities)
282 {
283 memset(pCapabilities->presentMask, 0,
284 sizeof(pCapabilities->presentMask));
285 pCapabilities->presentMask[0] = 0x1;
286 pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
287
288 return VK_SUCCESS;
289 }
290
v3dv_GetDeviceGroupSurfacePresentModesKHR(VkDevice device,VkSurfaceKHR surface,VkDeviceGroupPresentModeFlagsKHR * pModes)291 VkResult v3dv_GetDeviceGroupSurfacePresentModesKHR(
292 VkDevice device,
293 VkSurfaceKHR surface,
294 VkDeviceGroupPresentModeFlagsKHR* pModes)
295 {
296 *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
297
298 return VK_SUCCESS;
299 }
300
v3dv_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,VkSurfaceKHR surface,uint32_t * pRectCount,VkRect2D * pRects)301 VkResult v3dv_GetPhysicalDevicePresentRectanglesKHR(
302 VkPhysicalDevice physicalDevice,
303 VkSurfaceKHR surface,
304 uint32_t* pRectCount,
305 VkRect2D* pRects)
306 {
307 V3DV_FROM_HANDLE(v3dv_physical_device, device, physicalDevice);
308
309 return wsi_common_get_present_rectangles(&device->wsi_device,
310 surface,
311 pRectCount, pRects);
312 }
313