101e04c3fSmrg/*
201e04c3fSmrg * Copyright © 2017 Intel Corporation
301e04c3fSmrg *
401e04c3fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
501e04c3fSmrg * copy of this software and associated documentation files (the "Software"),
601e04c3fSmrg * to deal in the Software without restriction, including without limitation
701e04c3fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
801e04c3fSmrg * and/or sell copies of the Software, and to permit persons to whom the
901e04c3fSmrg * Software is furnished to do so, subject to the following conditions:
1001e04c3fSmrg *
1101e04c3fSmrg * The above copyright notice and this permission notice (including the next
1201e04c3fSmrg * paragraph) shall be included in all copies or substantial portions of the
1301e04c3fSmrg * Software.
1401e04c3fSmrg *
1501e04c3fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1601e04c3fSmrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1701e04c3fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1801e04c3fSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1901e04c3fSmrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
2001e04c3fSmrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
2101e04c3fSmrg * IN THE SOFTWARE.
2201e04c3fSmrg */
2301e04c3fSmrg
2401e04c3fSmrg#include "wsi_common_private.h"
257ec681f3Smrg#include "wsi_common_entrypoints.h"
2601e04c3fSmrg#include "util/macros.h"
277ec681f3Smrg#include "util/os_file.h"
287ec681f3Smrg#include "util/os_time.h"
298a1362adSmaya#include "util/xmlconfig.h"
307ec681f3Smrg#include "vk_device.h"
317ec681f3Smrg#include "vk_instance.h"
327ec681f3Smrg#include "vk_physical_device.h"
337ec681f3Smrg#include "vk_queue.h"
3401e04c3fSmrg#include "vk_util.h"
3501e04c3fSmrg
368a1362adSmaya#include <time.h>
378a1362adSmaya#include <stdlib.h>
388a1362adSmaya#include <stdio.h>
3901e04c3fSmrg
4001e04c3fSmrgVkResult
4101e04c3fSmrgwsi_device_init(struct wsi_device *wsi,
4201e04c3fSmrg                VkPhysicalDevice pdevice,
4301e04c3fSmrg                WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
4401e04c3fSmrg                const VkAllocationCallbacks *alloc,
458a1362adSmaya                int display_fd,
467ec681f3Smrg                const struct driOptionCache *dri_options,
477ec681f3Smrg                bool sw_device)
4801e04c3fSmrg{
498a1362adSmaya   const char *present_mode;
507ec681f3Smrg   UNUSED VkResult result;
5101e04c3fSmrg
5201e04c3fSmrg   memset(wsi, 0, sizeof(*wsi));
5301e04c3fSmrg
5401e04c3fSmrg   wsi->instance_alloc = *alloc;
5501e04c3fSmrg   wsi->pdevice = pdevice;
567ec681f3Smrg   wsi->sw = sw_device;
5701e04c3fSmrg#define WSI_GET_CB(func) \
5801e04c3fSmrg   PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
5901e04c3fSmrg   WSI_GET_CB(GetPhysicalDeviceProperties2);
6001e04c3fSmrg   WSI_GET_CB(GetPhysicalDeviceMemoryProperties);
6101e04c3fSmrg   WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties);
6201e04c3fSmrg#undef WSI_GET_CB
6301e04c3fSmrg
6401e04c3fSmrg   wsi->pci_bus_info.sType =
6501e04c3fSmrg      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT;
6601e04c3fSmrg   VkPhysicalDeviceProperties2 pdp2 = {
6701e04c3fSmrg      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
6801e04c3fSmrg      .pNext = &wsi->pci_bus_info,
6901e04c3fSmrg   };
7001e04c3fSmrg   GetPhysicalDeviceProperties2(pdevice, &pdp2);
7101e04c3fSmrg
728a1362adSmaya   wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D;
738a1362adSmaya   wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR;
748a1362adSmaya
7501e04c3fSmrg   GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props);
7601e04c3fSmrg   GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL);
7701e04c3fSmrg
7801e04c3fSmrg#define WSI_GET_CB(func) \
7901e04c3fSmrg   wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
8001e04c3fSmrg   WSI_GET_CB(AllocateMemory);
8101e04c3fSmrg   WSI_GET_CB(AllocateCommandBuffers);
8201e04c3fSmrg   WSI_GET_CB(BindBufferMemory);
8301e04c3fSmrg   WSI_GET_CB(BindImageMemory);
8401e04c3fSmrg   WSI_GET_CB(BeginCommandBuffer);
8501e04c3fSmrg   WSI_GET_CB(CmdCopyImageToBuffer);
8601e04c3fSmrg   WSI_GET_CB(CreateBuffer);
8701e04c3fSmrg   WSI_GET_CB(CreateCommandPool);
8801e04c3fSmrg   WSI_GET_CB(CreateFence);
8901e04c3fSmrg   WSI_GET_CB(CreateImage);
9001e04c3fSmrg   WSI_GET_CB(DestroyBuffer);
9101e04c3fSmrg   WSI_GET_CB(DestroyCommandPool);
9201e04c3fSmrg   WSI_GET_CB(DestroyFence);
9301e04c3fSmrg   WSI_GET_CB(DestroyImage);
9401e04c3fSmrg   WSI_GET_CB(EndCommandBuffer);
9501e04c3fSmrg   WSI_GET_CB(FreeMemory);
9601e04c3fSmrg   WSI_GET_CB(FreeCommandBuffers);
9701e04c3fSmrg   WSI_GET_CB(GetBufferMemoryRequirements);
987ec681f3Smrg   WSI_GET_CB(GetImageDrmFormatModifierPropertiesEXT);
9901e04c3fSmrg   WSI_GET_CB(GetImageMemoryRequirements);
10001e04c3fSmrg   WSI_GET_CB(GetImageSubresourceLayout);
1017ec681f3Smrg   if (!wsi->sw)
1027ec681f3Smrg      WSI_GET_CB(GetMemoryFdKHR);
10301e04c3fSmrg   WSI_GET_CB(GetPhysicalDeviceFormatProperties);
10401e04c3fSmrg   WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR);
1057ec681f3Smrg   WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2);
10601e04c3fSmrg   WSI_GET_CB(ResetFences);
10701e04c3fSmrg   WSI_GET_CB(QueueSubmit);
10801e04c3fSmrg   WSI_GET_CB(WaitForFences);
1097ec681f3Smrg   WSI_GET_CB(MapMemory);
1107ec681f3Smrg   WSI_GET_CB(UnmapMemory);
11101e04c3fSmrg#undef WSI_GET_CB
11201e04c3fSmrg
11301e04c3fSmrg#ifdef VK_USE_PLATFORM_XCB_KHR
1148a1362adSmaya   result = wsi_x11_init_wsi(wsi, alloc, dri_options);
11501e04c3fSmrg   if (result != VK_SUCCESS)
11601e04c3fSmrg      goto fail;
11701e04c3fSmrg#endif
11801e04c3fSmrg
11901e04c3fSmrg#ifdef VK_USE_PLATFORM_WAYLAND_KHR
12001e04c3fSmrg   result = wsi_wl_init_wsi(wsi, alloc, pdevice);
12101e04c3fSmrg   if (result != VK_SUCCESS)
12201e04c3fSmrg      goto fail;
12301e04c3fSmrg#endif
12401e04c3fSmrg
1257ec681f3Smrg#ifdef VK_USE_PLATFORM_WIN32_KHR
1267ec681f3Smrg   result = wsi_win32_init_wsi(wsi, alloc, pdevice);
1277ec681f3Smrg   if (result != VK_SUCCESS)
1287ec681f3Smrg      goto fail;
1297ec681f3Smrg#endif
1307ec681f3Smrg
13101e04c3fSmrg#ifdef VK_USE_PLATFORM_DISPLAY_KHR
13201e04c3fSmrg   result = wsi_display_init_wsi(wsi, alloc, display_fd);
13301e04c3fSmrg   if (result != VK_SUCCESS)
13401e04c3fSmrg      goto fail;
13501e04c3fSmrg#endif
13601e04c3fSmrg
1378a1362adSmaya   present_mode = getenv("MESA_VK_WSI_PRESENT_MODE");
1388a1362adSmaya   if (present_mode) {
1398a1362adSmaya      if (!strcmp(present_mode, "fifo")) {
1408a1362adSmaya         wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR;
1417ec681f3Smrg      } else if (!strcmp(present_mode, "relaxed")) {
1427ec681f3Smrg          wsi->override_present_mode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
1438a1362adSmaya      } else if (!strcmp(present_mode, "mailbox")) {
1448a1362adSmaya         wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
1458a1362adSmaya      } else if (!strcmp(present_mode, "immediate")) {
1468a1362adSmaya         wsi->override_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
1478a1362adSmaya      } else {
1488a1362adSmaya         fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n");
1498a1362adSmaya      }
1508a1362adSmaya   }
1518a1362adSmaya
1528a1362adSmaya   if (dri_options) {
1538a1362adSmaya      if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL))
1548a1362adSmaya         wsi->enable_adaptive_sync = driQueryOptionb(dri_options,
1558a1362adSmaya                                                     "adaptive_sync");
1567ec681f3Smrg
1577ec681f3Smrg      if (driCheckOption(dri_options, "vk_wsi_force_bgra8_unorm_first",  DRI_BOOL)) {
1587ec681f3Smrg         wsi->force_bgra8_unorm_first =
1597ec681f3Smrg            driQueryOptionb(dri_options, "vk_wsi_force_bgra8_unorm_first");
1607ec681f3Smrg      }
1618a1362adSmaya   }
1628a1362adSmaya
16301e04c3fSmrg   return VK_SUCCESS;
1647ec681f3Smrg#if defined(VK_USE_PLATFORM_XCB_KHR) || \
1657ec681f3Smrg   defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
1667ec681f3Smrg   defined(VK_USE_PLATFORM_WIN32_KHR) || \
1677ec681f3Smrg   defined(VK_USE_PLATFORM_DISPLAY_KHR)
16801e04c3fSmrgfail:
16901e04c3fSmrg   wsi_device_finish(wsi, alloc);
17001e04c3fSmrg   return result;
1717ec681f3Smrg#endif
17201e04c3fSmrg}
17301e04c3fSmrg
17401e04c3fSmrgvoid
17501e04c3fSmrgwsi_device_finish(struct wsi_device *wsi,
17601e04c3fSmrg                  const VkAllocationCallbacks *alloc)
17701e04c3fSmrg{
17801e04c3fSmrg#ifdef VK_USE_PLATFORM_DISPLAY_KHR
17901e04c3fSmrg   wsi_display_finish_wsi(wsi, alloc);
18001e04c3fSmrg#endif
18101e04c3fSmrg#ifdef VK_USE_PLATFORM_WAYLAND_KHR
18201e04c3fSmrg   wsi_wl_finish_wsi(wsi, alloc);
18301e04c3fSmrg#endif
1847ec681f3Smrg#ifdef VK_USE_PLATFORM_WIN32_KHR
1857ec681f3Smrg   wsi_win32_finish_wsi(wsi, alloc);
1867ec681f3Smrg#endif
18701e04c3fSmrg#ifdef VK_USE_PLATFORM_XCB_KHR
18801e04c3fSmrg   wsi_x11_finish_wsi(wsi, alloc);
18901e04c3fSmrg#endif
19001e04c3fSmrg}
19101e04c3fSmrg
1927ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
1937ec681f3Smrgwsi_DestroySurfaceKHR(VkInstance _instance,
1947ec681f3Smrg                      VkSurfaceKHR _surface,
1957ec681f3Smrg                      const VkAllocationCallbacks *pAllocator)
19601e04c3fSmrg{
1977ec681f3Smrg   VK_FROM_HANDLE(vk_instance, instance, _instance);
1987ec681f3Smrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
19901e04c3fSmrg
2007ec681f3Smrg   if (!surface)
2017ec681f3Smrg      return;
20201e04c3fSmrg
2037ec681f3Smrg   vk_free2(&instance->alloc, pAllocator, surface);
20401e04c3fSmrg}
20501e04c3fSmrg
20601e04c3fSmrgVkResult
20701e04c3fSmrgwsi_swapchain_init(const struct wsi_device *wsi,
20801e04c3fSmrg                   struct wsi_swapchain *chain,
20901e04c3fSmrg                   VkDevice device,
21001e04c3fSmrg                   const VkSwapchainCreateInfoKHR *pCreateInfo,
21101e04c3fSmrg                   const VkAllocationCallbacks *pAllocator)
21201e04c3fSmrg{
21301e04c3fSmrg   VkResult result;
21401e04c3fSmrg
21501e04c3fSmrg   memset(chain, 0, sizeof(*chain));
21601e04c3fSmrg
2177ec681f3Smrg   vk_object_base_init(NULL, &chain->base, VK_OBJECT_TYPE_SWAPCHAIN_KHR);
2187ec681f3Smrg
21901e04c3fSmrg   chain->wsi = wsi;
22001e04c3fSmrg   chain->device = device;
22101e04c3fSmrg   chain->alloc = *pAllocator;
22201e04c3fSmrg   chain->use_prime_blit = false;
22301e04c3fSmrg
22401e04c3fSmrg   chain->cmd_pools =
22501e04c3fSmrg      vk_zalloc(pAllocator, sizeof(VkCommandPool) * wsi->queue_family_count, 8,
22601e04c3fSmrg                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
22701e04c3fSmrg   if (!chain->cmd_pools)
22801e04c3fSmrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
22901e04c3fSmrg
23001e04c3fSmrg   for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
23101e04c3fSmrg      const VkCommandPoolCreateInfo cmd_pool_info = {
23201e04c3fSmrg         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
23301e04c3fSmrg         .pNext = NULL,
23401e04c3fSmrg         .flags = 0,
23501e04c3fSmrg         .queueFamilyIndex = i,
23601e04c3fSmrg      };
23701e04c3fSmrg      result = wsi->CreateCommandPool(device, &cmd_pool_info, &chain->alloc,
23801e04c3fSmrg                                      &chain->cmd_pools[i]);
23901e04c3fSmrg      if (result != VK_SUCCESS)
24001e04c3fSmrg         goto fail;
24101e04c3fSmrg   }
24201e04c3fSmrg
24301e04c3fSmrg   return VK_SUCCESS;
24401e04c3fSmrg
24501e04c3fSmrgfail:
24601e04c3fSmrg   wsi_swapchain_finish(chain);
24701e04c3fSmrg   return result;
24801e04c3fSmrg}
24901e04c3fSmrg
2508a1362adSmayastatic bool
2518a1362adSmayawsi_swapchain_is_present_mode_supported(struct wsi_device *wsi,
2528a1362adSmaya                                        const VkSwapchainCreateInfoKHR *pCreateInfo,
2538a1362adSmaya                                        VkPresentModeKHR mode)
2548a1362adSmaya{
2558a1362adSmaya      ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
2568a1362adSmaya      struct wsi_interface *iface = wsi->wsi[surface->platform];
2578a1362adSmaya      VkPresentModeKHR *present_modes;
2588a1362adSmaya      uint32_t present_mode_count;
2598a1362adSmaya      bool supported = false;
2608a1362adSmaya      VkResult result;
2618a1362adSmaya
2628a1362adSmaya      result = iface->get_present_modes(surface, &present_mode_count, NULL);
2638a1362adSmaya      if (result != VK_SUCCESS)
2648a1362adSmaya         return supported;
2658a1362adSmaya
2668a1362adSmaya      present_modes = malloc(present_mode_count * sizeof(*present_modes));
2678a1362adSmaya      if (!present_modes)
2688a1362adSmaya         return supported;
2698a1362adSmaya
2708a1362adSmaya      result = iface->get_present_modes(surface, &present_mode_count,
2718a1362adSmaya                                        present_modes);
2728a1362adSmaya      if (result != VK_SUCCESS)
2738a1362adSmaya         goto fail;
2748a1362adSmaya
2758a1362adSmaya      for (uint32_t i = 0; i < present_mode_count; i++) {
2768a1362adSmaya         if (present_modes[i] == mode) {
2778a1362adSmaya            supported = true;
2788a1362adSmaya            break;
2798a1362adSmaya         }
2808a1362adSmaya      }
2818a1362adSmaya
2828a1362adSmayafail:
2838a1362adSmaya      free(present_modes);
2848a1362adSmaya      return supported;
2858a1362adSmaya}
2868a1362adSmaya
2878a1362adSmayaenum VkPresentModeKHR
2888a1362adSmayawsi_swapchain_get_present_mode(struct wsi_device *wsi,
2898a1362adSmaya                               const VkSwapchainCreateInfoKHR *pCreateInfo)
2908a1362adSmaya{
2918a1362adSmaya   if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR)
2928a1362adSmaya      return pCreateInfo->presentMode;
2938a1362adSmaya
2948a1362adSmaya   if (!wsi_swapchain_is_present_mode_supported(wsi, pCreateInfo,
2958a1362adSmaya                                                wsi->override_present_mode)) {
2968a1362adSmaya      fprintf(stderr, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n");
2978a1362adSmaya      return pCreateInfo->presentMode;
2988a1362adSmaya   }
2998a1362adSmaya
3008a1362adSmaya   return wsi->override_present_mode;
3018a1362adSmaya}
3028a1362adSmaya
30301e04c3fSmrgvoid
30401e04c3fSmrgwsi_swapchain_finish(struct wsi_swapchain *chain)
30501e04c3fSmrg{
3067ec681f3Smrg   if (chain->fences) {
3077ec681f3Smrg      for (unsigned i = 0; i < chain->image_count; i++)
3087ec681f3Smrg         chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc);
3097ec681f3Smrg
3107ec681f3Smrg      vk_free(&chain->alloc, chain->fences);
3117ec681f3Smrg   }
31201e04c3fSmrg
31301e04c3fSmrg   for (uint32_t i = 0; i < chain->wsi->queue_family_count; i++) {
31401e04c3fSmrg      chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],
31501e04c3fSmrg                                     &chain->alloc);
31601e04c3fSmrg   }
31701e04c3fSmrg   vk_free(&chain->alloc, chain->cmd_pools);
31801e04c3fSmrg
3197ec681f3Smrg   vk_object_base_finish(&chain->base);
32001e04c3fSmrg}
32101e04c3fSmrg
32201e04c3fSmrgvoid
32301e04c3fSmrgwsi_destroy_image(const struct wsi_swapchain *chain,
32401e04c3fSmrg                  struct wsi_image *image)
32501e04c3fSmrg{
32601e04c3fSmrg   const struct wsi_device *wsi = chain->wsi;
32701e04c3fSmrg
32801e04c3fSmrg   if (image->prime.blit_cmd_buffers) {
32901e04c3fSmrg      for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
33001e04c3fSmrg         wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
33101e04c3fSmrg                                 1, &image->prime.blit_cmd_buffers[i]);
33201e04c3fSmrg      }
33301e04c3fSmrg      vk_free(&chain->alloc, image->prime.blit_cmd_buffers);
33401e04c3fSmrg   }
33501e04c3fSmrg
33601e04c3fSmrg   wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
33701e04c3fSmrg   wsi->DestroyImage(chain->device, image->image, &chain->alloc);
33801e04c3fSmrg   wsi->FreeMemory(chain->device, image->prime.memory, &chain->alloc);
33901e04c3fSmrg   wsi->DestroyBuffer(chain->device, image->prime.buffer, &chain->alloc);
34001e04c3fSmrg}
34101e04c3fSmrg
3427ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
3437ec681f3Smrgwsi_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
3447ec681f3Smrg                                       uint32_t queueFamilyIndex,
3457ec681f3Smrg                                       VkSurfaceKHR _surface,
3467ec681f3Smrg                                       VkBool32 *pSupported)
34701e04c3fSmrg{
3487ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
34901e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
3507ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
35101e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
35201e04c3fSmrg
35301e04c3fSmrg   return iface->get_support(surface, wsi_device,
35401e04c3fSmrg                             queueFamilyIndex, pSupported);
35501e04c3fSmrg}
35601e04c3fSmrg
3577ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
3587ec681f3Smrgwsi_GetPhysicalDeviceSurfaceCapabilitiesKHR(
3597ec681f3Smrg   VkPhysicalDevice physicalDevice,
3607ec681f3Smrg   VkSurfaceKHR _surface,
3617ec681f3Smrg   VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
36201e04c3fSmrg{
3637ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
36401e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
3657ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
36601e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
36701e04c3fSmrg
36801e04c3fSmrg   VkSurfaceCapabilities2KHR caps2 = {
36901e04c3fSmrg      .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
37001e04c3fSmrg   };
37101e04c3fSmrg
3728a1362adSmaya   VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
37301e04c3fSmrg
37401e04c3fSmrg   if (result == VK_SUCCESS)
37501e04c3fSmrg      *pSurfaceCapabilities = caps2.surfaceCapabilities;
37601e04c3fSmrg
37701e04c3fSmrg   return result;
37801e04c3fSmrg}
37901e04c3fSmrg
3807ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
3817ec681f3Smrgwsi_GetPhysicalDeviceSurfaceCapabilities2KHR(
3827ec681f3Smrg   VkPhysicalDevice physicalDevice,
3837ec681f3Smrg   const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
3847ec681f3Smrg   VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
38501e04c3fSmrg{
3867ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
38701e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
3887ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
38901e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
39001e04c3fSmrg
3918a1362adSmaya   return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,
39201e04c3fSmrg                                   pSurfaceCapabilities);
39301e04c3fSmrg}
39401e04c3fSmrg
3957ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
3967ec681f3Smrgwsi_GetPhysicalDeviceSurfaceCapabilities2EXT(
3977ec681f3Smrg   VkPhysicalDevice physicalDevice,
39801e04c3fSmrg   VkSurfaceKHR _surface,
39901e04c3fSmrg   VkSurfaceCapabilities2EXT *pSurfaceCapabilities)
40001e04c3fSmrg{
4017ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
40201e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
4037ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
40401e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
40501e04c3fSmrg
40601e04c3fSmrg   assert(pSurfaceCapabilities->sType ==
40701e04c3fSmrg          VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT);
40801e04c3fSmrg
40901e04c3fSmrg   struct wsi_surface_supported_counters counters = {
41001e04c3fSmrg      .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA,
41101e04c3fSmrg      .pNext = pSurfaceCapabilities->pNext,
41201e04c3fSmrg      .supported_surface_counters = 0,
41301e04c3fSmrg   };
41401e04c3fSmrg
41501e04c3fSmrg   VkSurfaceCapabilities2KHR caps2 = {
41601e04c3fSmrg      .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
41701e04c3fSmrg      .pNext = &counters,
41801e04c3fSmrg   };
41901e04c3fSmrg
4208a1362adSmaya   VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
42101e04c3fSmrg
42201e04c3fSmrg   if (result == VK_SUCCESS) {
42301e04c3fSmrg      VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities;
42401e04c3fSmrg      VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities;
42501e04c3fSmrg
42601e04c3fSmrg      ext_caps->minImageCount = khr_caps.minImageCount;
42701e04c3fSmrg      ext_caps->maxImageCount = khr_caps.maxImageCount;
42801e04c3fSmrg      ext_caps->currentExtent = khr_caps.currentExtent;
42901e04c3fSmrg      ext_caps->minImageExtent = khr_caps.minImageExtent;
43001e04c3fSmrg      ext_caps->maxImageExtent = khr_caps.maxImageExtent;
43101e04c3fSmrg      ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers;
43201e04c3fSmrg      ext_caps->supportedTransforms = khr_caps.supportedTransforms;
43301e04c3fSmrg      ext_caps->currentTransform = khr_caps.currentTransform;
43401e04c3fSmrg      ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha;
43501e04c3fSmrg      ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags;
43601e04c3fSmrg      ext_caps->supportedSurfaceCounters = counters.supported_surface_counters;
43701e04c3fSmrg   }
43801e04c3fSmrg
43901e04c3fSmrg   return result;
44001e04c3fSmrg}
44101e04c3fSmrg
4427ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
4437ec681f3Smrgwsi_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
4447ec681f3Smrg                                       VkSurfaceKHR _surface,
4457ec681f3Smrg                                       uint32_t *pSurfaceFormatCount,
4467ec681f3Smrg                                       VkSurfaceFormatKHR *pSurfaceFormats)
44701e04c3fSmrg{
4487ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
44901e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
4507ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
45101e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
45201e04c3fSmrg
45301e04c3fSmrg   return iface->get_formats(surface, wsi_device,
45401e04c3fSmrg                             pSurfaceFormatCount, pSurfaceFormats);
45501e04c3fSmrg}
45601e04c3fSmrg
4577ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
4587ec681f3Smrgwsi_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
4597ec681f3Smrg                                        const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,
4607ec681f3Smrg                                        uint32_t *pSurfaceFormatCount,
4617ec681f3Smrg                                        VkSurfaceFormat2KHR *pSurfaceFormats)
46201e04c3fSmrg{
4637ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
46401e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
4657ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
46601e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
46701e04c3fSmrg
46801e04c3fSmrg   return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
46901e04c3fSmrg                              pSurfaceFormatCount, pSurfaceFormats);
47001e04c3fSmrg}
47101e04c3fSmrg
4727ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
4737ec681f3Smrgwsi_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
4747ec681f3Smrg                                            VkSurfaceKHR _surface,
4757ec681f3Smrg                                            uint32_t *pPresentModeCount,
4767ec681f3Smrg                                            VkPresentModeKHR *pPresentModes)
47701e04c3fSmrg{
4787ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
47901e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
4807ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
48101e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
48201e04c3fSmrg
48301e04c3fSmrg   return iface->get_present_modes(surface, pPresentModeCount,
48401e04c3fSmrg                                   pPresentModes);
48501e04c3fSmrg}
48601e04c3fSmrg
4877ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
4887ec681f3Smrgwsi_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
4897ec681f3Smrg                                          VkSurfaceKHR _surface,
4907ec681f3Smrg                                          uint32_t *pRectCount,
4917ec681f3Smrg                                          VkRect2D *pRects)
49201e04c3fSmrg{
4937ec681f3Smrg   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
49401e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
4957ec681f3Smrg   struct wsi_device *wsi_device = device->wsi_device;
49601e04c3fSmrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
49701e04c3fSmrg
49801e04c3fSmrg   return iface->get_present_rectangles(surface, wsi_device,
49901e04c3fSmrg                                        pRectCount, pRects);
50001e04c3fSmrg}
50101e04c3fSmrg
5027ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
5037ec681f3Smrgwsi_CreateSwapchainKHR(VkDevice _device,
5047ec681f3Smrg                       const VkSwapchainCreateInfoKHR *pCreateInfo,
5057ec681f3Smrg                       const VkAllocationCallbacks *pAllocator,
5067ec681f3Smrg                       VkSwapchainKHR *pSwapchain)
50701e04c3fSmrg{
5087ec681f3Smrg   VK_FROM_HANDLE(vk_device, device, _device);
50901e04c3fSmrg   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
5107ec681f3Smrg   struct wsi_device *wsi_device = device->physical->wsi_device;
5117ec681f3Smrg   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
5127ec681f3Smrg   const VkAllocationCallbacks *alloc;
51301e04c3fSmrg   struct wsi_swapchain *swapchain;
51401e04c3fSmrg
5157ec681f3Smrg   if (pAllocator)
5167ec681f3Smrg     alloc = pAllocator;
5177ec681f3Smrg   else
5187ec681f3Smrg     alloc = &device->alloc;
5197ec681f3Smrg
5207ec681f3Smrg   VkResult result = iface->create_swapchain(surface, _device, wsi_device,
5217ec681f3Smrg                                             pCreateInfo, alloc,
52201e04c3fSmrg                                             &swapchain);
52301e04c3fSmrg   if (result != VK_SUCCESS)
52401e04c3fSmrg      return result;
52501e04c3fSmrg
5267ec681f3Smrg   swapchain->fences = vk_zalloc(alloc,
5277ec681f3Smrg                                 sizeof (*swapchain->fences) * swapchain->image_count,
5287ec681f3Smrg                                 sizeof (*swapchain->fences),
5297ec681f3Smrg                                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
5307ec681f3Smrg   if (!swapchain->fences) {
5317ec681f3Smrg      swapchain->destroy(swapchain, alloc);
5327ec681f3Smrg      return VK_ERROR_OUT_OF_HOST_MEMORY;
5337ec681f3Smrg   }
5347ec681f3Smrg
53501e04c3fSmrg   *pSwapchain = wsi_swapchain_to_handle(swapchain);
53601e04c3fSmrg
53701e04c3fSmrg   return VK_SUCCESS;
53801e04c3fSmrg}
53901e04c3fSmrg
5407ec681f3SmrgVKAPI_ATTR void VKAPI_CALL
5417ec681f3Smrgwsi_DestroySwapchainKHR(VkDevice _device,
5427ec681f3Smrg                        VkSwapchainKHR _swapchain,
5437ec681f3Smrg                        const VkAllocationCallbacks *pAllocator)
54401e04c3fSmrg{
5457ec681f3Smrg   VK_FROM_HANDLE(vk_device, device, _device);
5467ec681f3Smrg   VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
5477ec681f3Smrg   const VkAllocationCallbacks *alloc;
5487ec681f3Smrg
54901e04c3fSmrg   if (!swapchain)
55001e04c3fSmrg      return;
55101e04c3fSmrg
5527ec681f3Smrg   if (pAllocator)
5537ec681f3Smrg     alloc = pAllocator;
5547ec681f3Smrg   else
5557ec681f3Smrg     alloc = &device->alloc;
5567ec681f3Smrg
5577ec681f3Smrg   swapchain->destroy(swapchain, alloc);
55801e04c3fSmrg}
55901e04c3fSmrg
56001e04c3fSmrgVkResult
56101e04c3fSmrgwsi_common_get_images(VkSwapchainKHR _swapchain,
56201e04c3fSmrg                      uint32_t *pSwapchainImageCount,
56301e04c3fSmrg                      VkImage *pSwapchainImages)
56401e04c3fSmrg{
5657ec681f3Smrg   VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
5667ec681f3Smrg   VK_OUTARRAY_MAKE_TYPED(VkImage, images, pSwapchainImages, pSwapchainImageCount);
56701e04c3fSmrg
56801e04c3fSmrg   for (uint32_t i = 0; i < swapchain->image_count; i++) {
5697ec681f3Smrg      vk_outarray_append_typed(VkImage, &images, image) {
57001e04c3fSmrg         *image = swapchain->get_wsi_image(swapchain, i)->image;
57101e04c3fSmrg      }
57201e04c3fSmrg   }
57301e04c3fSmrg
57401e04c3fSmrg   return vk_outarray_status(&images);
57501e04c3fSmrg}
57601e04c3fSmrg
5777ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
5787ec681f3Smrgwsi_GetSwapchainImagesKHR(VkDevice device,
5797ec681f3Smrg                          VkSwapchainKHR swapchain,
5807ec681f3Smrg                          uint32_t *pSwapchainImageCount,
5817ec681f3Smrg                          VkImage *pSwapchainImages)
5827ec681f3Smrg{
5837ec681f3Smrg   return wsi_common_get_images(swapchain,
5847ec681f3Smrg                                pSwapchainImageCount,
5857ec681f3Smrg                                pSwapchainImages);
5867ec681f3Smrg}
5877ec681f3Smrg
5887ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
5897ec681f3Smrgwsi_AcquireNextImageKHR(VkDevice _device,
5907ec681f3Smrg                        VkSwapchainKHR swapchain,
5917ec681f3Smrg                        uint64_t timeout,
5927ec681f3Smrg                        VkSemaphore semaphore,
5937ec681f3Smrg                        VkFence fence,
5947ec681f3Smrg                        uint32_t *pImageIndex)
5957ec681f3Smrg{
5967ec681f3Smrg   VK_FROM_HANDLE(vk_device, device, _device);
5977ec681f3Smrg
5987ec681f3Smrg   const VkAcquireNextImageInfoKHR acquire_info = {
5997ec681f3Smrg      .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
6007ec681f3Smrg      .swapchain = swapchain,
6017ec681f3Smrg      .timeout = timeout,
6027ec681f3Smrg      .semaphore = semaphore,
6037ec681f3Smrg      .fence = fence,
6047ec681f3Smrg      .deviceMask = 0,
6057ec681f3Smrg   };
6067ec681f3Smrg
6077ec681f3Smrg   return device->dispatch_table.AcquireNextImage2KHR(_device, &acquire_info,
6087ec681f3Smrg                                                      pImageIndex);
6097ec681f3Smrg}
6107ec681f3Smrg
61101e04c3fSmrgVkResult
61201e04c3fSmrgwsi_common_acquire_next_image2(const struct wsi_device *wsi,
61301e04c3fSmrg                               VkDevice device,
61401e04c3fSmrg                               const VkAcquireNextImageInfoKHR *pAcquireInfo,
61501e04c3fSmrg                               uint32_t *pImageIndex)
61601e04c3fSmrg{
6177ec681f3Smrg   VK_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
6187ec681f3Smrg
6197ec681f3Smrg   VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo,
6207ec681f3Smrg                                                   pImageIndex);
6217ec681f3Smrg   if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
6227ec681f3Smrg      return result;
6237ec681f3Smrg
6247ec681f3Smrg   if (wsi->set_memory_ownership) {
6257ec681f3Smrg      VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, *pImageIndex)->memory;
6267ec681f3Smrg      wsi->set_memory_ownership(swapchain->device, mem, true);
6277ec681f3Smrg   }
6287ec681f3Smrg
6297ec681f3Smrg   if (pAcquireInfo->semaphore != VK_NULL_HANDLE &&
6307ec681f3Smrg       wsi->signal_semaphore_for_memory != NULL) {
6317ec681f3Smrg      struct wsi_image *image =
6327ec681f3Smrg         swapchain->get_wsi_image(swapchain, *pImageIndex);
6337ec681f3Smrg      wsi->signal_semaphore_for_memory(device, pAcquireInfo->semaphore,
6347ec681f3Smrg                                       image->memory);
6357ec681f3Smrg   }
6367ec681f3Smrg
6377ec681f3Smrg   if (pAcquireInfo->fence != VK_NULL_HANDLE &&
6387ec681f3Smrg       wsi->signal_fence_for_memory != NULL) {
6397ec681f3Smrg      struct wsi_image *image =
6407ec681f3Smrg         swapchain->get_wsi_image(swapchain, *pImageIndex);
6417ec681f3Smrg      wsi->signal_fence_for_memory(device, pAcquireInfo->fence,
6427ec681f3Smrg                                   image->memory);
6437ec681f3Smrg   }
64401e04c3fSmrg
6457ec681f3Smrg   return result;
6467ec681f3Smrg}
6477ec681f3Smrg
6487ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
6497ec681f3Smrgwsi_AcquireNextImage2KHR(VkDevice _device,
6507ec681f3Smrg                         const VkAcquireNextImageInfoKHR *pAcquireInfo,
6517ec681f3Smrg                         uint32_t *pImageIndex)
6527ec681f3Smrg{
6537ec681f3Smrg   VK_FROM_HANDLE(vk_device, device, _device);
6547ec681f3Smrg
6557ec681f3Smrg   return wsi_common_acquire_next_image2(device->physical->wsi_device,
6567ec681f3Smrg                                         _device, pAcquireInfo, pImageIndex);
65701e04c3fSmrg}
65801e04c3fSmrg
65901e04c3fSmrgVkResult
66001e04c3fSmrgwsi_common_queue_present(const struct wsi_device *wsi,
66101e04c3fSmrg                         VkDevice device,
66201e04c3fSmrg                         VkQueue queue,
66301e04c3fSmrg                         int queue_family_index,
66401e04c3fSmrg                         const VkPresentInfoKHR *pPresentInfo)
66501e04c3fSmrg{
66601e04c3fSmrg   VkResult final_result = VK_SUCCESS;
66701e04c3fSmrg
66801e04c3fSmrg   const VkPresentRegionsKHR *regions =
66901e04c3fSmrg      vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
67001e04c3fSmrg
67101e04c3fSmrg   for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
6727ec681f3Smrg      VK_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
6737ec681f3Smrg      uint32_t image_index = pPresentInfo->pImageIndices[i];
67401e04c3fSmrg      VkResult result;
67501e04c3fSmrg
6767ec681f3Smrg      if (swapchain->fences[image_index] == VK_NULL_HANDLE) {
67701e04c3fSmrg         const VkFenceCreateInfo fence_info = {
67801e04c3fSmrg            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
67901e04c3fSmrg            .pNext = NULL,
68001e04c3fSmrg            .flags = 0,
68101e04c3fSmrg         };
68201e04c3fSmrg         result = wsi->CreateFence(device, &fence_info,
68301e04c3fSmrg                                   &swapchain->alloc,
6847ec681f3Smrg                                   &swapchain->fences[image_index]);
68501e04c3fSmrg         if (result != VK_SUCCESS)
68601e04c3fSmrg            goto fail_present;
68701e04c3fSmrg      } else {
6887ec681f3Smrg         result =
6897ec681f3Smrg            wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
6907ec681f3Smrg                               true, ~0ull);
6917ec681f3Smrg         if (result != VK_SUCCESS)
6927ec681f3Smrg            goto fail_present;
6937ec681f3Smrg
6947ec681f3Smrg         result =
6957ec681f3Smrg            wsi->ResetFences(device, 1, &swapchain->fences[image_index]);
6967ec681f3Smrg         if (result != VK_SUCCESS)
6977ec681f3Smrg            goto fail_present;
69801e04c3fSmrg      }
69901e04c3fSmrg
7007ec681f3Smrg      struct wsi_image *image =
7017ec681f3Smrg         swapchain->get_wsi_image(swapchain, image_index);
7027ec681f3Smrg
7037ec681f3Smrg      struct wsi_memory_signal_submit_info mem_signal = {
7047ec681f3Smrg         .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA,
7057ec681f3Smrg         .pNext = NULL,
7067ec681f3Smrg         .memory = image->memory,
7077ec681f3Smrg      };
7087ec681f3Smrg
70901e04c3fSmrg      VkSubmitInfo submit_info = {
71001e04c3fSmrg         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
7117ec681f3Smrg         .pNext = &mem_signal,
71201e04c3fSmrg      };
71301e04c3fSmrg
71401e04c3fSmrg      VkPipelineStageFlags *stage_flags = NULL;
71501e04c3fSmrg      if (i == 0) {
71601e04c3fSmrg         /* We only need/want to wait on semaphores once.  After that, we're
71701e04c3fSmrg          * guaranteed ordering since it all happens on the same queue.
71801e04c3fSmrg          */
71901e04c3fSmrg         submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount;
72001e04c3fSmrg         submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores;
72101e04c3fSmrg
72201e04c3fSmrg         /* Set up the pWaitDstStageMasks */
72301e04c3fSmrg         stage_flags = vk_alloc(&swapchain->alloc,
72401e04c3fSmrg                                sizeof(VkPipelineStageFlags) *
72501e04c3fSmrg                                pPresentInfo->waitSemaphoreCount,
72601e04c3fSmrg                                8,
72701e04c3fSmrg                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
72801e04c3fSmrg         if (!stage_flags) {
72901e04c3fSmrg            result = VK_ERROR_OUT_OF_HOST_MEMORY;
73001e04c3fSmrg            goto fail_present;
73101e04c3fSmrg         }
73201e04c3fSmrg         for (uint32_t s = 0; s < pPresentInfo->waitSemaphoreCount; s++)
73301e04c3fSmrg            stage_flags[s] = VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT;
73401e04c3fSmrg
73501e04c3fSmrg         submit_info.pWaitDstStageMask = stage_flags;
73601e04c3fSmrg      }
73701e04c3fSmrg
73801e04c3fSmrg      if (swapchain->use_prime_blit) {
73901e04c3fSmrg         /* If we are using prime blits, we need to perform the blit now.  The
74001e04c3fSmrg          * command buffer is attached to the image.
74101e04c3fSmrg          */
74201e04c3fSmrg         submit_info.commandBufferCount = 1;
74301e04c3fSmrg         submit_info.pCommandBuffers =
74401e04c3fSmrg            &image->prime.blit_cmd_buffers[queue_family_index];
7457ec681f3Smrg         mem_signal.memory = image->prime.memory;
74601e04c3fSmrg      }
74701e04c3fSmrg
7487ec681f3Smrg      result = wsi->QueueSubmit(queue, 1, &submit_info, swapchain->fences[image_index]);
74901e04c3fSmrg      vk_free(&swapchain->alloc, stage_flags);
75001e04c3fSmrg      if (result != VK_SUCCESS)
75101e04c3fSmrg         goto fail_present;
75201e04c3fSmrg
7537ec681f3Smrg      if (wsi->sw)
7547ec681f3Smrg	      wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
7557ec681f3Smrg				 true, ~0ull);
7567ec681f3Smrg
75701e04c3fSmrg      const VkPresentRegionKHR *region = NULL;
75801e04c3fSmrg      if (regions && regions->pRegions)
75901e04c3fSmrg         region = &regions->pRegions[i];
76001e04c3fSmrg
7617ec681f3Smrg      result = swapchain->queue_present(swapchain, image_index, region);
7627ec681f3Smrg      if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
76301e04c3fSmrg         goto fail_present;
76401e04c3fSmrg
7657ec681f3Smrg      if (wsi->set_memory_ownership) {
7667ec681f3Smrg         VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, image_index)->memory;
7677ec681f3Smrg         wsi->set_memory_ownership(swapchain->device, mem, false);
76801e04c3fSmrg      }
76901e04c3fSmrg
77001e04c3fSmrg   fail_present:
77101e04c3fSmrg      if (pPresentInfo->pResults != NULL)
77201e04c3fSmrg         pPresentInfo->pResults[i] = result;
77301e04c3fSmrg
77401e04c3fSmrg      /* Let the final result be our first unsuccessful result */
77501e04c3fSmrg      if (final_result == VK_SUCCESS)
77601e04c3fSmrg         final_result = result;
77701e04c3fSmrg   }
77801e04c3fSmrg
77901e04c3fSmrg   return final_result;
78001e04c3fSmrg}
7818a1362adSmaya
7827ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
7837ec681f3Smrgwsi_QueuePresentKHR(VkQueue _queue, const VkPresentInfoKHR *pPresentInfo)
7847ec681f3Smrg{
7857ec681f3Smrg   VK_FROM_HANDLE(vk_queue, queue, _queue);
7867ec681f3Smrg
7877ec681f3Smrg   return wsi_common_queue_present(queue->base.device->physical->wsi_device,
7887ec681f3Smrg                                   vk_device_to_handle(queue->base.device),
7897ec681f3Smrg                                   _queue,
7907ec681f3Smrg                                   queue->queue_family_index,
7917ec681f3Smrg                                   pPresentInfo);
7927ec681f3Smrg}
7937ec681f3Smrg
7948a1362adSmayauint64_t
7958a1362adSmayawsi_common_get_current_time(void)
7968a1362adSmaya{
7977ec681f3Smrg   return os_time_get_nano();
7987ec681f3Smrg}
7997ec681f3Smrg
8007ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
8017ec681f3Smrgwsi_GetDeviceGroupPresentCapabilitiesKHR(VkDevice device,
8027ec681f3Smrg                                         VkDeviceGroupPresentCapabilitiesKHR *pCapabilities)
8037ec681f3Smrg{
8047ec681f3Smrg   memset(pCapabilities->presentMask, 0,
8057ec681f3Smrg          sizeof(pCapabilities->presentMask));
8067ec681f3Smrg   pCapabilities->presentMask[0] = 0x1;
8077ec681f3Smrg   pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
8087ec681f3Smrg
8097ec681f3Smrg   return VK_SUCCESS;
8107ec681f3Smrg}
8117ec681f3Smrg
8127ec681f3SmrgVKAPI_ATTR VkResult VKAPI_CALL
8137ec681f3Smrgwsi_GetDeviceGroupSurfacePresentModesKHR(VkDevice device,
8147ec681f3Smrg                                         VkSurfaceKHR surface,
8157ec681f3Smrg                                         VkDeviceGroupPresentModeFlagsKHR *pModes)
8167ec681f3Smrg{
8177ec681f3Smrg   *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
8187ec681f3Smrg
8197ec681f3Smrg   return VK_SUCCESS;
8208a1362adSmaya}
821