1/*
2 * Copyright © 2017 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 "wsi_common_private.h"
25#include "drm-uapi/drm_fourcc.h"
26#include "util/macros.h"
27#include "util/xmlconfig.h"
28#include "vk_util.h"
29
30#include <time.h>
31#include <unistd.h>
32#include <xf86drm.h>
33#include <stdlib.h>
34#include <stdio.h>
35
36VkResult
37wsi_device_init(struct wsi_device *wsi,
38                VkPhysicalDevice pdevice,
39                WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
40                const VkAllocationCallbacks *alloc,
41                int display_fd,
42                const struct driOptionCache *dri_options)
43{
44   const char *present_mode;
45   VkResult result;
46
47   memset(wsi, 0, sizeof(*wsi));
48
49   wsi->instance_alloc = *alloc;
50   wsi->pdevice = pdevice;
51
52#define WSI_GET_CB(func) \
53   PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
54   WSI_GET_CB(GetPhysicalDeviceProperties2);
55   WSI_GET_CB(GetPhysicalDeviceMemoryProperties);
56   WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties);
57#undef WSI_GET_CB
58
59   wsi->pci_bus_info.sType =
60      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT;
61   VkPhysicalDeviceProperties2 pdp2 = {
62      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
63      .pNext = &wsi->pci_bus_info,
64   };
65   GetPhysicalDeviceProperties2(pdevice, &pdp2);
66
67   wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D;
68   wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR;
69
70   GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props);
71   GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL);
72
73#define WSI_GET_CB(func) \
74   wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
75   WSI_GET_CB(AllocateMemory);
76   WSI_GET_CB(AllocateCommandBuffers);
77   WSI_GET_CB(BindBufferMemory);
78   WSI_GET_CB(BindImageMemory);
79   WSI_GET_CB(BeginCommandBuffer);
80   WSI_GET_CB(CmdCopyImageToBuffer);
81   WSI_GET_CB(CreateBuffer);
82   WSI_GET_CB(CreateCommandPool);
83   WSI_GET_CB(CreateFence);
84   WSI_GET_CB(CreateImage);
85   WSI_GET_CB(DestroyBuffer);
86   WSI_GET_CB(DestroyCommandPool);
87   WSI_GET_CB(DestroyFence);
88   WSI_GET_CB(DestroyImage);
89   WSI_GET_CB(EndCommandBuffer);
90   WSI_GET_CB(FreeMemory);
91   WSI_GET_CB(FreeCommandBuffers);
92   WSI_GET_CB(GetBufferMemoryRequirements);
93   WSI_GET_CB(GetImageMemoryRequirements);
94   WSI_GET_CB(GetImageSubresourceLayout);
95   WSI_GET_CB(GetMemoryFdKHR);
96   WSI_GET_CB(GetPhysicalDeviceFormatProperties);
97   WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR);
98   WSI_GET_CB(ResetFences);
99   WSI_GET_CB(QueueSubmit);
100   WSI_GET_CB(WaitForFences);
101#undef WSI_GET_CB
102
103#ifdef VK_USE_PLATFORM_XCB_KHR
104   result = wsi_x11_init_wsi(wsi, alloc, dri_options);
105   if (result != VK_SUCCESS)
106      goto fail;
107#endif
108
109#ifdef VK_USE_PLATFORM_WAYLAND_KHR
110   result = wsi_wl_init_wsi(wsi, alloc, pdevice);
111   if (result != VK_SUCCESS)
112      goto fail;
113#endif
114
115#ifdef VK_USE_PLATFORM_DISPLAY_KHR
116   result = wsi_display_init_wsi(wsi, alloc, display_fd);
117   if (result != VK_SUCCESS)
118      goto fail;
119#endif
120
121   present_mode = getenv("MESA_VK_WSI_PRESENT_MODE");
122   if (present_mode) {
123      if (!strcmp(present_mode, "fifo")) {
124         wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR;
125      } else if (!strcmp(present_mode, "mailbox")) {
126         wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
127      } else if (!strcmp(present_mode, "immediate")) {
128         wsi->override_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
129      } else {
130         fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n");
131      }
132   }
133
134   if (dri_options) {
135      if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL))
136         wsi->enable_adaptive_sync = driQueryOptionb(dri_options,
137                                                     "adaptive_sync");
138   }
139
140   return VK_SUCCESS;
141
142fail:
143   wsi_device_finish(wsi, alloc);
144   return result;
145}
146
147void
148wsi_device_finish(struct wsi_device *wsi,
149                  const VkAllocationCallbacks *alloc)
150{
151#ifdef VK_USE_PLATFORM_DISPLAY_KHR
152   wsi_display_finish_wsi(wsi, alloc);
153#endif
154#ifdef VK_USE_PLATFORM_WAYLAND_KHR
155   wsi_wl_finish_wsi(wsi, alloc);
156#endif
157#ifdef VK_USE_PLATFORM_XCB_KHR
158   wsi_x11_finish_wsi(wsi, alloc);
159#endif
160}
161
162bool
163wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
164{
165   drmDevicePtr fd_device;
166   int ret = drmGetDevice2(drm_fd, 0, &fd_device);
167   if (ret)
168      return false;
169
170   bool match = false;
171   switch (fd_device->bustype) {
172   case DRM_BUS_PCI:
173      match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain &&
174              wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus &&
175              wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev &&
176              wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func;
177      break;
178
179   default:
180      break;
181   }
182
183   drmFreeDevice(&fd_device);
184
185   return match;
186}
187
188VkResult
189wsi_swapchain_init(const struct wsi_device *wsi,
190                   struct wsi_swapchain *chain,
191                   VkDevice device,
192                   const VkSwapchainCreateInfoKHR *pCreateInfo,
193                   const VkAllocationCallbacks *pAllocator)
194{
195   VkResult result;
196
197   memset(chain, 0, sizeof(*chain));
198
199   chain->wsi = wsi;
200   chain->device = device;
201   chain->alloc = *pAllocator;
202   chain->use_prime_blit = false;
203
204   chain->cmd_pools =
205      vk_zalloc(pAllocator, sizeof(VkCommandPool) * wsi->queue_family_count, 8,
206                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
207   if (!chain->cmd_pools)
208      return VK_ERROR_OUT_OF_HOST_MEMORY;
209
210   for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
211      const VkCommandPoolCreateInfo cmd_pool_info = {
212         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
213         .pNext = NULL,
214         .flags = 0,
215         .queueFamilyIndex = i,
216      };
217      result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc,
218                                      &chain->cmd_pools[i]);
219      if (result != VK_SUCCESS)
220         goto fail;
221   }
222
223   return VK_SUCCESS;
224
225fail:
226   wsi_swapchain_finish(chain);
227   return result;
228}
229
230static bool
231wsi_swapchain_is_present_mode_supported(struct wsi_device *wsi,
232                                        const VkSwapchainCreateInfoKHR *pCreateInfo,
233                                        VkPresentModeKHR mode)
234{
235      ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
236      struct wsi_interface *iface = wsi->wsi[surface->platform];
237      VkPresentModeKHR *present_modes;
238      uint32_t present_mode_count;
239      bool supported = false;
240      VkResult result;
241
242      result = iface->get_present_modes(surface, &present_mode_count, NULL);
243      if (result != VK_SUCCESS)
244         return supported;
245
246      present_modes = malloc(present_mode_count * sizeof(*present_modes));
247      if (!present_modes)
248         return supported;
249
250      result = iface->get_present_modes(surface, &present_mode_count,
251                                        present_modes);
252      if (result != VK_SUCCESS)
253         goto fail;
254
255      for (uint32_t i = 0; i < present_mode_count; i++) {
256         if (present_modes[i] == mode) {
257            supported = true;
258            break;
259         }
260      }
261
262fail:
263      free(present_modes);
264      return supported;
265}
266
267enum VkPresentModeKHR
268wsi_swapchain_get_present_mode(struct wsi_device *wsi,
269                               const VkSwapchainCreateInfoKHR *pCreateInfo)
270{
271   if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR)
272      return pCreateInfo->presentMode;
273
274   if (!wsi_swapchain_is_present_mode_supported(wsi, pCreateInfo,
275                                                wsi->override_present_mode)) {
276      fprintf(stderr, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n");
277      return pCreateInfo->presentMode;
278   }
279
280   return wsi->override_present_mode;
281}
282
283void
284wsi_swapchain_finish(struct wsi_swapchain *chain)
285{
286   for (unsigned i = 0; i < ARRAY_SIZE(chain->fences); i++)
287      chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc);
288
289   for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) {
290      chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],
291                                     &chain->alloc);
292   }
293   vk_free(&chain->alloc, chain->cmd_pools);
294}
295
296static uint32_t
297select_memory_type(const struct wsi_device *wsi,
298                   VkMemoryPropertyFlags props,
299                   uint32_t type_bits)
300{
301   for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
302       const VkMemoryType type = wsi->memory_props.memoryTypes[i];
303       if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props)
304         return i;
305   }
306
307   unreachable("No memory type found");
308}
309
310static uint32_t
311vk_format_size(VkFormat format)
312{
313   switch (format) {
314   case VK_FORMAT_B8G8R8A8_UNORM:
315   case VK_FORMAT_B8G8R8A8_SRGB:
316      return 4;
317   default:
318      unreachable("Unknown WSI Format");
319   }
320}
321
322static inline uint32_t
323align_u32(uint32_t v, uint32_t a)
324{
325   assert(a != 0 && a == (a & -a));
326   return (v + a - 1) & ~(a - 1);
327}
328
329VkResult
330wsi_create_native_image(const struct wsi_swapchain *chain,
331                        const VkSwapchainCreateInfoKHR *pCreateInfo,
332                        uint32_t num_modifier_lists,
333                        const uint32_t *num_modifiers,
334                        const uint64_t *const *modifiers,
335                        struct wsi_image *image)
336{
337   const struct wsi_device *wsi = chain->wsi;
338   VkResult result;
339
340   memset(image, 0, sizeof(*image));
341   for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
342      image->fds[i] = -1;
343
344   struct wsi_image_create_info image_wsi_info = {
345      .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
346      .pNext = NULL,
347   };
348
349   uint32_t image_modifier_count = 0, modifier_prop_count = 0;
350   struct wsi_format_modifier_properties *modifier_props = NULL;
351   uint64_t *image_modifiers = NULL;
352   if (num_modifier_lists == 0) {
353      /* If we don't have modifiers, fall back to the legacy "scanout" flag */
354      image_wsi_info.scanout = true;
355   } else {
356      /* The winsys can't request modifiers if we don't support them. */
357      assert(wsi->supports_modifiers);
358      struct wsi_format_modifier_properties_list modifier_props_list = {
359         .sType = VK_STRUCTURE_TYPE_WSI_FORMAT_MODIFIER_PROPERTIES_LIST_MESA,
360         .pNext = NULL,
361      };
362      VkFormatProperties2 format_props = {
363         .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
364         .pNext = &modifier_props_list,
365      };
366      wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
367                                                 pCreateInfo->imageFormat,
368                                                 &format_props);
369      assert(modifier_props_list.modifier_count > 0);
370      modifier_props = vk_alloc(&chain->alloc,
371                                sizeof(*modifier_props) *
372                                modifier_props_list.modifier_count,
373                                8,
374                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
375      if (!modifier_props) {
376         result = VK_ERROR_OUT_OF_HOST_MEMORY;
377         goto fail;
378      }
379
380      modifier_props_list.modifier_properties = modifier_props;
381      wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
382                                                 pCreateInfo->imageFormat,
383                                                 &format_props);
384      modifier_prop_count = modifier_props_list.modifier_count;
385
386      uint32_t max_modifier_count = 0;
387      for (uint32_t l = 0; l < num_modifier_lists; l++)
388         max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);
389
390      image_modifiers = vk_alloc(&chain->alloc,
391                                 sizeof(*image_modifiers) *
392                                 max_modifier_count,
393                                 8,
394                                 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
395      if (!image_modifiers) {
396         result = VK_ERROR_OUT_OF_HOST_MEMORY;
397         goto fail;
398      }
399
400      image_modifier_count = 0;
401      for (uint32_t l = 0; l < num_modifier_lists; l++) {
402         /* Walk the modifier lists and construct a list of supported
403          * modifiers.
404          */
405         for (uint32_t i = 0; i < num_modifiers[l]; i++) {
406            for (uint32_t j = 0; j < modifier_prop_count; j++) {
407               if (modifier_props[j].modifier == modifiers[l][i])
408                  image_modifiers[image_modifier_count++] = modifiers[l][i];
409            }
410         }
411
412         /* We only want to take the modifiers from the first list */
413         if (image_modifier_count > 0)
414            break;
415      }
416
417      if (image_modifier_count > 0) {
418         image_wsi_info.modifier_count = image_modifier_count;
419         image_wsi_info.modifiers = image_modifiers;
420      } else {
421         /* TODO: Add a proper error here */
422         assert(!"Failed to find a supported modifier!  This should never "
423                 "happen because LINEAR should always be available");
424         result = VK_ERROR_OUT_OF_HOST_MEMORY;
425         goto fail;
426      }
427   }
428
429   const VkImageCreateInfo image_info = {
430      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
431      .pNext = &image_wsi_info,
432      .flags = 0,
433      .imageType = VK_IMAGE_TYPE_2D,
434      .format = pCreateInfo->imageFormat,
435      .extent = {
436         .width = pCreateInfo->imageExtent.width,
437         .height = pCreateInfo->imageExtent.height,
438         .depth = 1,
439      },
440      .mipLevels = 1,
441      .arrayLayers = 1,
442      .samples = VK_SAMPLE_COUNT_1_BIT,
443      .tiling = VK_IMAGE_TILING_OPTIMAL,
444      .usage = pCreateInfo->imageUsage,
445      .sharingMode = pCreateInfo->imageSharingMode,
446      .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
447      .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
448      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
449   };
450   result = wsi->CreateImage(chain->device, &image_info,
451                             &chain->alloc, &image->image);
452   if (result != VK_SUCCESS)
453      goto fail;
454
455   VkMemoryRequirements reqs;
456   wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
457
458   const struct wsi_memory_allocate_info memory_wsi_info = {
459      .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
460      .pNext = NULL,
461      .implicit_sync = true,
462   };
463   const VkExportMemoryAllocateInfo memory_export_info = {
464      .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
465      .pNext = &memory_wsi_info,
466      .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
467   };
468   const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
469      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
470      .pNext = &memory_export_info,
471      .image = image->image,
472      .buffer = VK_NULL_HANDLE,
473   };
474   const VkMemoryAllocateInfo memory_info = {
475      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
476      .pNext = &memory_dedicated_info,
477      .allocationSize = reqs.size,
478      .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
479                                            reqs.memoryTypeBits),
480   };
481   result = wsi->AllocateMemory(chain->device, &memory_info,
482                                &chain->alloc, &image->memory);
483   if (result != VK_SUCCESS)
484      goto fail;
485
486   result = wsi->BindImageMemory(chain->device, image->image,
487                                 image->memory, 0);
488   if (result != VK_SUCCESS)
489      goto fail;
490
491   const VkMemoryGetFdInfoKHR memory_get_fd_info = {
492      .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
493      .pNext = NULL,
494      .memory = image->memory,
495      .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
496   };
497   int fd;
498   result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
499   if (result != VK_SUCCESS)
500      goto fail;
501
502   if (num_modifier_lists > 0) {
503      image->drm_modifier = wsi->image_get_modifier(image->image);
504      assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);
505
506      for (uint32_t j = 0; j < modifier_prop_count; j++) {
507         if (modifier_props[j].modifier == image->drm_modifier) {
508            image->num_planes = modifier_props[j].modifier_plane_count;
509            break;
510         }
511      }
512
513      for (uint32_t p = 0; p < image->num_planes; p++) {
514         const VkImageSubresource image_subresource = {
515            .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p,
516            .mipLevel = 0,
517            .arrayLayer = 0,
518         };
519         VkSubresourceLayout image_layout;
520         wsi->GetImageSubresourceLayout(chain->device, image->image,
521                                        &image_subresource, &image_layout);
522         image->sizes[p] = image_layout.size;
523         image->row_pitches[p] = image_layout.rowPitch;
524         image->offsets[p] = image_layout.offset;
525         if (p == 0) {
526            image->fds[p] = fd;
527         } else {
528            image->fds[p] = dup(fd);
529            if (image->fds[p] == -1) {
530               for (uint32_t i = 0; i < p; i++)
531                  close(image->fds[p]);
532
533               goto fail;
534            }
535         }
536      }
537   } else {
538      const VkImageSubresource image_subresource = {
539         .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
540         .mipLevel = 0,
541         .arrayLayer = 0,
542      };
543      VkSubresourceLayout image_layout;
544      wsi->GetImageSubresourceLayout(chain->device, image->image,
545                                     &image_subresource, &image_layout);
546
547      image->drm_modifier = DRM_FORMAT_MOD_INVALID;
548      image->num_planes = 1;
549      image->sizes[0] = reqs.size;
550      image->row_pitches[0] = image_layout.rowPitch;
551      image->offsets[0] = 0;
552      image->fds[0] = fd;
553   }
554
555   vk_free(&chain->alloc, modifier_props);
556   vk_free(&chain->alloc, image_modifiers);
557
558   return VK_SUCCESS;
559
560fail:
561   vk_free(&chain->alloc, modifier_props);
562   vk_free(&chain->alloc, image_modifiers);
563   wsi_destroy_image(chain, image);
564
565   return result;
566}
567
568#define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
569
570VkResult
571wsi_create_prime_image(const struct wsi_swapchain *chain,
572                       const VkSwapchainCreateInfoKHR *pCreateInfo,
573                       bool use_modifier,
574                       struct wsi_image *image)
575{
576   const struct wsi_device *wsi = chain->wsi;
577   VkResult result;
578
579   memset(image, 0, sizeof(*image));
580
581   const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
582   const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
583                                            WSI_PRIME_LINEAR_STRIDE_ALIGN);
584
585   uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
586   linear_size = align_u32(linear_size, 4096);
587
588   const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
589      .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
590      .pNext = NULL,
591      .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
592   };
593   const VkBufferCreateInfo prime_buffer_info = {
594      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
595      .pNext = &prime_buffer_external_info,
596      .size = linear_size,
597      .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
598      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
599   };
600   result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
601                              &chain->alloc, &image->prime.buffer);
602   if (result != VK_SUCCESS)
603      goto fail;
604
605   VkMemoryRequirements reqs;
606   wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
607   assert(reqs.size <= linear_size);
608
609   const struct wsi_memory_allocate_info memory_wsi_info = {
610      .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
611      .pNext = NULL,
612      .implicit_sync = true,
613   };
614   const VkExportMemoryAllocateInfo prime_memory_export_info = {
615      .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
616      .pNext = &memory_wsi_info,
617      .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
618   };
619   const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
620      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
621      .pNext = &prime_memory_export_info,
622      .image = VK_NULL_HANDLE,
623      .buffer = image->prime.buffer,
624   };
625   const VkMemoryAllocateInfo prime_memory_info = {
626      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
627      .pNext = &prime_memory_dedicated_info,
628      .allocationSize = linear_size,
629      .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
630   };
631   result = wsi->AllocateMemory(chain->device, &prime_memory_info,
632                                &chain->alloc, &image->prime.memory);
633   if (result != VK_SUCCESS)
634      goto fail;
635
636   result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
637                                  image->prime.memory, 0);
638   if (result != VK_SUCCESS)
639      goto fail;
640
641   const VkImageCreateInfo image_info = {
642      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
643      .pNext = NULL,
644      .flags = 0,
645      .imageType = VK_IMAGE_TYPE_2D,
646      .format = pCreateInfo->imageFormat,
647      .extent = {
648         .width = pCreateInfo->imageExtent.width,
649         .height = pCreateInfo->imageExtent.height,
650         .depth = 1,
651      },
652      .mipLevels = 1,
653      .arrayLayers = 1,
654      .samples = VK_SAMPLE_COUNT_1_BIT,
655      .tiling = VK_IMAGE_TILING_OPTIMAL,
656      .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
657      .sharingMode = pCreateInfo->imageSharingMode,
658      .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
659      .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
660      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
661   };
662   result = wsi->CreateImage(chain->device, &image_info,
663                             &chain->alloc, &image->image);
664   if (result != VK_SUCCESS)
665      goto fail;
666
667   wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
668
669   const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
670      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
671      .pNext = NULL,
672      .image = image->image,
673      .buffer = VK_NULL_HANDLE,
674   };
675   const VkMemoryAllocateInfo memory_info = {
676      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
677      .pNext = &memory_dedicated_info,
678      .allocationSize = reqs.size,
679      .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
680                                            reqs.memoryTypeBits),
681   };
682   result = wsi->AllocateMemory(chain->device, &memory_info,
683                                &chain->alloc, &image->memory);
684   if (result != VK_SUCCESS)
685      goto fail;
686
687   result = wsi->BindImageMemory(chain->device, image->image,
688                                 image->memory, 0);
689   if (result != VK_SUCCESS)
690      goto fail;
691
692   image->prime.blit_cmd_buffers =
693      vk_zalloc(&chain->alloc,
694                sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
695                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
696   if (!image->prime.blit_cmd_buffers) {
697      result = VK_ERROR_OUT_OF_HOST_MEMORY;
698      goto fail;
699   }
700
701   for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
702      const VkCommandBufferAllocateInfo cmd_buffer_info = {
703         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
704         .pNext = NULL,
705         .commandPool = chain->cmd_pools[i],
706         .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
707         .commandBufferCount = 1,
708      };
709      result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
710                                           &image->prime.blit_cmd_buffers[i]);
711      if (result != VK_SUCCESS)
712         goto fail;
713
714      const VkCommandBufferBeginInfo begin_info = {
715         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
716      };
717      wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
718
719      struct VkBufferImageCopy buffer_image_copy = {
720         .bufferOffset = 0,
721         .bufferRowLength = linear_stride / cpp,
722         .bufferImageHeight = 0,
723         .imageSubresource = {
724            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
725            .mipLevel = 0,
726            .baseArrayLayer = 0,
727            .layerCount = 1,
728         },
729         .imageOffset = { .x = 0, .y = 0, .z = 0 },
730         .imageExtent = {
731            .width = pCreateInfo->imageExtent.width,
732            .height = pCreateInfo->imageExtent.height,
733            .depth = 1,
734         },
735      };
736      wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
737                                image->image,
738                                VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
739                                image->prime.buffer,
740                                1, &buffer_image_copy);
741
742      result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
743      if (result != VK_SUCCESS)
744         goto fail;
745   }
746
747   const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
748      .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
749      .pNext = NULL,
750      .memory = image->prime.memory,
751      .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
752   };
753   int fd;
754   result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
755   if (result != VK_SUCCESS)
756      goto fail;
757
758   image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
759   image->num_planes = 1;
760   image->sizes[0] = linear_size;
761   image->row_pitches[0] = linear_stride;
762   image->offsets[0] = 0;
763   image->fds[0] = fd;
764
765   return VK_SUCCESS;
766
767fail:
768   wsi_destroy_image(chain, image);
769
770   return result;
771}
772
773void
774wsi_destroy_image(const struct wsi_swapchain *chain,
775                  struct wsi_image *image)
776{
777   const struct wsi_device *wsi = chain->wsi;
778
779   if (image->prime.blit_cmd_buffers) {
780      for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
781         wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
782                                 1, &image->prime.blit_cmd_buffers[i]);
783      }
784      vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
785   }
786
787   wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
788   wsi->DestroyImage(chain->device, image->image, &chain->alloc);
789   wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
790   wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
791}
792
793VkResult
794wsi_common_get_surface_support(struct wsi_device *wsi_device,
795                               uint32_t queueFamilyIndex,
796                               VkSurfaceKHR _surface,
797                               VkBool32* pSupported)
798{
799   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
800   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
801
802   return iface->get_support(surface, wsi_device,
803                             queueFamilyIndex, pSupported);
804}
805
806VkResult
807wsi_common_get_surface_capabilities(struct wsi_device *wsi_device,
808                                    VkSurfaceKHR _surface,
809                                    VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
810{
811   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
812   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
813
814   VkSurfaceCapabilities2KHR caps2 = {
815      .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
816   };
817
818   VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
819
820   if (result == VK_SUCCESS)
821      *pSurfaceCapabilities = caps2.surfaceCapabilities;
822
823   return result;
824}
825
826VkResult
827wsi_common_get_surface_capabilities2(struct wsi_device *wsi_device,
828                                     const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
829                                     VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
830{
831   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
832   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
833
834   return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,
835                                   pSurfaceCapabilities);
836}
837
838VkResult
839wsi_common_get_surface_capabilities2ext(
840   struct wsi_device *wsi_device,
841   VkSurfaceKHR _surface,
842   VkSurfaceCapabilities2EXT *pSurfaceCapabilities)
843{
844   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
845   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
846
847   assert(pSurfaceCapabilities->sType ==
848          VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT);
849
850   struct wsi_surface_supported_counters counters = {
851      .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA,
852      .pNext = pSurfaceCapabilities->pNext,
853      .supported_surface_counters = 0,
854   };
855
856   VkSurfaceCapabilities2KHR caps2 = {
857      .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
858      .pNext = &counters,
859   };
860
861   VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
862
863   if (result == VK_SUCCESS) {
864      VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities;
865      VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities;
866
867      ext_caps->minImageCount = khr_caps.minImageCount;
868      ext_caps->maxImageCount = khr_caps.maxImageCount;
869      ext_caps->currentExtent = khr_caps.currentExtent;
870      ext_caps->minImageExtent = khr_caps.minImageExtent;
871      ext_caps->maxImageExtent = khr_caps.maxImageExtent;
872      ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers;
873      ext_caps->supportedTransforms = khr_caps.supportedTransforms;
874      ext_caps->currentTransform = khr_caps.currentTransform;
875      ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha;
876      ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags;
877      ext_caps->supportedSurfaceCounters = counters.supported_surface_counters;
878   }
879
880   return result;
881}
882
883VkResult
884wsi_common_get_surface_formats(struct wsi_device *wsi_device,
885                               VkSurfaceKHR _surface,
886                               uint32_t *pSurfaceFormatCount,
887                               VkSurfaceFormatKHR *pSurfaceFormats)
888{
889   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
890   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
891
892   return iface->get_formats(surface, wsi_device,
893                             pSurfaceFormatCount, pSurfaceFormats);
894}
895
896VkResult
897wsi_common_get_surface_formats2(struct wsi_device *wsi_device,
898                                const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
899                                uint32_t *pSurfaceFormatCount,
900                                VkSurfaceFormat2KHR *pSurfaceFormats)
901{
902   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
903   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
904
905   return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
906                              pSurfaceFormatCount, pSurfaceFormats);
907}
908
909VkResult
910wsi_common_get_surface_present_modes(struct wsi_device *wsi_device,
911                                     VkSurfaceKHR _surface,
912                                     uint32_t *pPresentModeCount,
913                                     VkPresentModeKHR *pPresentModes)
914{
915   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
916   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
917
918   return iface->get_present_modes(surface, pPresentModeCount,
919                                   pPresentModes);
920}
921
922VkResult
923wsi_common_get_present_rectangles(struct wsi_device *wsi_device,
924                                  VkSurfaceKHR _surface,
925                                  uint32_t* pRectCount,
926                                  VkRect2D* pRects)
927{
928   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
929   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
930
931   return iface->get_present_rectangles(surface, wsi_device,
932                                        pRectCount, pRects);
933}
934
935VkResult
936wsi_common_create_swapchain(struct wsi_device *wsi,
937                            VkDevice device,
938                            const VkSwapchainCreateInfoKHR *pCreateInfo,
939                            const VkAllocationCallbacks *pAllocator,
940                            VkSwapchainKHR *pSwapchain)
941{
942   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
943   struct wsi_interface *iface = wsi->wsi[surface->platform];
944   struct wsi_swapchain *swapchain;
945
946   VkResult result = iface->create_swapchain(surface, device, wsi,
947                                             pCreateInfo, pAllocator,
948                                             &swapchain);
949   if (result != VK_SUCCESS)
950      return result;
951
952   *pSwapchain = wsi_swapchain_to_handle(swapchain);
953
954   return VK_SUCCESS;
955}
956
957void
958wsi_common_destroy_swapchain(VkDevice device,
959                             VkSwapchainKHR _swapchain,
960                             const VkAllocationCallbacks *pAllocator)
961{
962   WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
963   if (!swapchain)
964      return;
965
966   swapchain->destroy(swapchain, pAllocator);
967}
968
969VkResult
970wsi_common_get_images(VkSwapchainKHR _swapchain,
971                      uint32_t *pSwapchainImageCount,
972                      VkImage *pSwapchainImages)
973{
974   WSI_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
975   VK_OUTARRAY_MAKE(images, pSwapchainImages, pSwapchainImageCount);
976
977   for (uint32_t i = 0; i < swapchain->image_count; i++) {
978      vk_outarray_append(&images, image) {
979         *image = swapchain->get_wsi_image(swapchain, i)->image;
980      }
981   }
982
983   return vk_outarray_status(&images);
984}
985
986VkResult
987wsi_common_acquire_next_image2(const struct wsi_device *wsi,
988                               VkDevice device,
989                               const VkAcquireNextImageInfoKHR *pAcquireInfo,
990                               uint32_t *pImageIndex)
991{
992   WSI_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
993
994   return swapchain->acquire_next_image(swapchain, pAcquireInfo, pImageIndex);
995}
996
997VkResult
998wsi_common_queue_present(const struct wsi_device *wsi,
999                         VkDevice device,
1000                         VkQueue queue,
1001                         int queue_family_index,
1002                         const VkPresentInfoKHR *pPresentInfo)
1003{
1004   VkResult final_result = VK_SUCCESS;
1005
1006   const VkPresentRegionsKHR *regions =
1007      vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
1008
1009   for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
1010      WSI_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
1011      VkResult result;
1012
1013      if (swapchain->fences[0] == VK_NULL_HANDLE) {
1014         const VkFenceCreateInfo fence_info = {
1015            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1016            .pNext = NULL,
1017            .flags = 0,
1018         };
1019         result = wsi->CreateFence(device, &fence_info,
1020                                   &swapchain->alloc,
1021                                   &swapchain->fences[0]);
1022         if (result != VK_SUCCESS)
1023            goto fail_present;
1024      } else {
1025         wsi->ResetFences(device, 1, &swapchain->fences[0]);
1026      }
1027
1028      VkSubmitInfo submit_info = {
1029         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
1030         .pNext = NULL,
1031      };
1032
1033      VkPipelineStageFlags *stage_flags = NULL;
1034      if (i == 0) {
1035         /* We only need/want to wait on semaphores once.  After that, we're
1036          * guaranteed ordering since it all happens on the same queue.
1037          */
1038         submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount;
1039         submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores;
1040
1041         /* Set up the pWaitDstStageMasks */
1042         stage_flags = vk_alloc(&swapchain->alloc,
1043                                sizeof(VkPipelineStageFlags) *
1044                                pPresentInfo->waitSemaphoreCount,
1045                                8,
1046                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
1047         if (!stage_flags) {
1048            result = VK_ERROR_OUT_OF_HOST_MEMORY;
1049            goto fail_present;
1050         }
1051         for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++)
1052            stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
1053
1054         submit_info.pWaitDstStageMask = stage_flags;
1055      }
1056
1057      if (swapchain->use_prime_blit) {
1058         /* If we are using prime blits, we need to perform the blit now.  The
1059          * command buffer is attached to the image.
1060          */
1061         struct wsi_image *image =
1062            swapchain->get_wsi_image(swapchain, pPresentInfo->pImageIndices[i]);
1063         submit_info.commandBufferCount = 1;
1064         submit_info.pCommandBuffers =
1065            &image->prime.blit_cmd_buffers[queue_family_index];
1066      }
1067
1068      result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[0]);
1069      vk_free(&swapchain->alloc, stage_flags);
1070      if (result != VK_SUCCESS)
1071         goto fail_present;
1072
1073      const VkPresentRegionKHR *region = NULL;
1074      if (regions && regions->pRegions)
1075         region = &regions->pRegions[i];
1076
1077      result = swapchain->queue_present(swapchain,
1078                                        pPresentInfo->pImageIndices[i],
1079                                        region);
1080      if (result != VK_SUCCESS)
1081         goto fail_present;
1082
1083      VkFence last = swapchain->fences[2];
1084      swapchain->fences[2] = swapchain->fences[1];
1085      swapchain->fences[1] = swapchain->fences[0];
1086      swapchain->fences[0] = last;
1087
1088      if (last != VK_NULL_HANDLE) {
1089         wsi->WaitForFences(device, 1, &last, true, 1);
1090      }
1091
1092   fail_present:
1093      if (pPresentInfo->pResults != NULL)
1094         pPresentInfo->pResults[i] = result;
1095
1096      /* Let the final result be our first unsuccessful result */
1097      if (final_result == VK_SUCCESS)
1098         final_result = result;
1099   }
1100
1101   return final_result;
1102}
1103
1104uint64_t
1105wsi_common_get_current_time(void)
1106{
1107   struct timespec current;
1108   clock_gettime(CLOCK_MONOTONIC, &current);
1109   return current.tv_nsec + current.tv_sec * 1000000000ull;
1110}
1111