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
29static PFN_vkVoidFunction
30anv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
31{
32   ANV_FROM_HANDLE(anv_physical_device, physical_device, physicalDevice);
33   return anv_lookup_entrypoint(&physical_device->info, pName);
34}
35
36static uint64_t
37anv_wsi_image_get_modifier(VkImage _image)
38{
39   ANV_FROM_HANDLE(anv_image, image, _image);
40   return image->drm_format_mod;
41}
42
43VkResult
44anv_init_wsi(struct anv_physical_device *physical_device)
45{
46   VkResult result;
47
48   result = wsi_device_init(&physical_device->wsi_device,
49                            anv_physical_device_to_handle(physical_device),
50                            anv_wsi_proc_addr,
51                            &physical_device->instance->alloc,
52                            physical_device->master_fd,
53                            &physical_device->instance->dri_options);
54   if (result != VK_SUCCESS)
55      return result;
56
57   physical_device->wsi_device.supports_modifiers = true;
58   physical_device->wsi_device.image_get_modifier = anv_wsi_image_get_modifier;
59
60   return VK_SUCCESS;
61}
62
63void
64anv_finish_wsi(struct anv_physical_device *physical_device)
65{
66   wsi_device_finish(&physical_device->wsi_device,
67                     &physical_device->instance->alloc);
68}
69
70void anv_DestroySurfaceKHR(
71    VkInstance                                   _instance,
72    VkSurfaceKHR                                 _surface,
73    const VkAllocationCallbacks*                 pAllocator)
74{
75   ANV_FROM_HANDLE(anv_instance, instance, _instance);
76   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
77
78   if (!surface)
79      return;
80
81   vk_free2(&instance->alloc, pAllocator, surface);
82}
83
84VkResult anv_GetPhysicalDeviceSurfaceSupportKHR(
85    VkPhysicalDevice                            physicalDevice,
86    uint32_t                                    queueFamilyIndex,
87    VkSurfaceKHR                                surface,
88    VkBool32*                                   pSupported)
89{
90   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
91
92   return wsi_common_get_surface_support(&device->wsi_device,
93                                         queueFamilyIndex,
94                                         surface,
95                                         pSupported);
96}
97
98VkResult anv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
99    VkPhysicalDevice                            physicalDevice,
100    VkSurfaceKHR                                surface,
101    VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities)
102{
103   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
104
105   return wsi_common_get_surface_capabilities(&device->wsi_device,
106                                              surface,
107                                              pSurfaceCapabilities);
108}
109
110VkResult anv_GetPhysicalDeviceSurfaceCapabilities2KHR(
111    VkPhysicalDevice                            physicalDevice,
112    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
113    VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities)
114{
115   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
116
117   return wsi_common_get_surface_capabilities2(&device->wsi_device,
118                                               pSurfaceInfo,
119                                               pSurfaceCapabilities);
120}
121
122VkResult anv_GetPhysicalDeviceSurfaceCapabilities2EXT(
123 	VkPhysicalDevice                            physicalDevice,
124	VkSurfaceKHR                                surface,
125	VkSurfaceCapabilities2EXT*                  pSurfaceCapabilities)
126{
127   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
128
129   return wsi_common_get_surface_capabilities2ext(&device->wsi_device,
130                                                  surface,
131                                                  pSurfaceCapabilities);
132}
133
134VkResult anv_GetPhysicalDeviceSurfaceFormatsKHR(
135    VkPhysicalDevice                            physicalDevice,
136    VkSurfaceKHR                                surface,
137    uint32_t*                                   pSurfaceFormatCount,
138    VkSurfaceFormatKHR*                         pSurfaceFormats)
139{
140   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
141
142   return wsi_common_get_surface_formats(&device->wsi_device, surface,
143                                         pSurfaceFormatCount, pSurfaceFormats);
144}
145
146VkResult anv_GetPhysicalDeviceSurfaceFormats2KHR(
147    VkPhysicalDevice                            physicalDevice,
148    const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
149    uint32_t*                                   pSurfaceFormatCount,
150    VkSurfaceFormat2KHR*                        pSurfaceFormats)
151{
152   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
153
154   return wsi_common_get_surface_formats2(&device->wsi_device, pSurfaceInfo,
155                                          pSurfaceFormatCount, pSurfaceFormats);
156}
157
158VkResult anv_GetPhysicalDeviceSurfacePresentModesKHR(
159    VkPhysicalDevice                            physicalDevice,
160    VkSurfaceKHR                                surface,
161    uint32_t*                                   pPresentModeCount,
162    VkPresentModeKHR*                           pPresentModes)
163{
164   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
165
166   return wsi_common_get_surface_present_modes(&device->wsi_device, surface,
167                                               pPresentModeCount,
168                                               pPresentModes);
169}
170
171VkResult anv_CreateSwapchainKHR(
172    VkDevice                                     _device,
173    const VkSwapchainCreateInfoKHR*              pCreateInfo,
174    const VkAllocationCallbacks*                 pAllocator,
175    VkSwapchainKHR*                              pSwapchain)
176{
177   ANV_FROM_HANDLE(anv_device, device, _device);
178   struct wsi_device *wsi_device = &device->instance->physicalDevice.wsi_device;
179   const VkAllocationCallbacks *alloc;
180
181   if (pAllocator)
182     alloc = pAllocator;
183   else
184     alloc = &device->alloc;
185
186   return wsi_common_create_swapchain(wsi_device, _device,
187                                      pCreateInfo, alloc, pSwapchain);
188}
189
190void anv_DestroySwapchainKHR(
191    VkDevice                                     _device,
192    VkSwapchainKHR                               swapchain,
193    const VkAllocationCallbacks*                 pAllocator)
194{
195   ANV_FROM_HANDLE(anv_device, device, _device);
196   const VkAllocationCallbacks *alloc;
197
198   if (pAllocator)
199     alloc = pAllocator;
200   else
201     alloc = &device->alloc;
202
203   wsi_common_destroy_swapchain(_device, swapchain, alloc);
204}
205
206VkResult anv_GetSwapchainImagesKHR(
207    VkDevice                                     device,
208    VkSwapchainKHR                               swapchain,
209    uint32_t*                                    pSwapchainImageCount,
210    VkImage*                                     pSwapchainImages)
211{
212   return wsi_common_get_images(swapchain,
213                                pSwapchainImageCount,
214                                pSwapchainImages);
215}
216
217VkResult anv_AcquireNextImageKHR(
218    VkDevice                                     device,
219    VkSwapchainKHR                               swapchain,
220    uint64_t                                     timeout,
221    VkSemaphore                                  semaphore,
222    VkFence                                      fence,
223    uint32_t*                                    pImageIndex)
224{
225   VkAcquireNextImageInfoKHR acquire_info = {
226      .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
227      .swapchain = swapchain,
228      .timeout = timeout,
229      .semaphore = semaphore,
230      .fence = fence,
231      .deviceMask = 0,
232   };
233
234   return anv_AcquireNextImage2KHR(device, &acquire_info, pImageIndex);
235}
236
237VkResult anv_AcquireNextImage2KHR(
238    VkDevice                                     _device,
239    const VkAcquireNextImageInfoKHR*             pAcquireInfo,
240    uint32_t*                                    pImageIndex)
241{
242   ANV_FROM_HANDLE(anv_device, device, _device);
243   struct anv_physical_device *pdevice = &device->instance->physicalDevice;
244
245   VkResult result = wsi_common_acquire_next_image2(&pdevice->wsi_device,
246                                                    _device,
247                                                    pAcquireInfo,
248                                                    pImageIndex);
249
250   /* Thanks to implicit sync, the image is ready immediately.  However, we
251    * should wait for the current GPU state to finish.
252    */
253   if (pAcquireInfo->fence != VK_NULL_HANDLE) {
254      anv_QueueSubmit(anv_queue_to_handle(&device->queue), 0, NULL,
255                      pAcquireInfo->fence);
256   }
257
258   return result;
259}
260
261VkResult anv_QueuePresentKHR(
262    VkQueue                                  _queue,
263    const VkPresentInfoKHR*                  pPresentInfo)
264{
265   ANV_FROM_HANDLE(anv_queue, queue, _queue);
266   struct anv_physical_device *pdevice =
267      &queue->device->instance->physicalDevice;
268
269   return wsi_common_queue_present(&pdevice->wsi_device,
270                                   anv_device_to_handle(queue->device),
271                                   _queue, 0,
272                                   pPresentInfo);
273}
274
275VkResult anv_GetDeviceGroupPresentCapabilitiesKHR(
276    VkDevice                                    device,
277    VkDeviceGroupPresentCapabilitiesKHR*        pCapabilities)
278{
279   memset(pCapabilities->presentMask, 0,
280          sizeof(pCapabilities->presentMask));
281   pCapabilities->presentMask[0] = 0x1;
282   pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
283
284   return VK_SUCCESS;
285}
286
287VkResult anv_GetDeviceGroupSurfacePresentModesKHR(
288    VkDevice                                    device,
289    VkSurfaceKHR                                surface,
290    VkDeviceGroupPresentModeFlagsKHR*           pModes)
291{
292   *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
293
294   return VK_SUCCESS;
295}
296
297VkResult anv_GetPhysicalDevicePresentRectanglesKHR(
298    VkPhysicalDevice                            physicalDevice,
299    VkSurfaceKHR                                surface,
300    uint32_t*                                   pRectCount,
301    VkRect2D*                                   pRects)
302{
303   ANV_FROM_HANDLE(anv_physical_device, device, physicalDevice);
304
305   return wsi_common_get_present_rectangles(&device->wsi_device,
306                                            surface,
307                                            pRectCount, pRects);
308}
309