xref: /third_party/mesa3d/src/vulkan/wsi/wsi_common.c (revision bf215546)
1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2017 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "wsi_common_private.h"
25bf215546Sopenharmony_ci#include "wsi_common_entrypoints.h"
26bf215546Sopenharmony_ci#include "util/debug.h"
27bf215546Sopenharmony_ci#include "util/macros.h"
28bf215546Sopenharmony_ci#include "util/os_file.h"
29bf215546Sopenharmony_ci#include "util/xmlconfig.h"
30bf215546Sopenharmony_ci#include "vk_device.h"
31bf215546Sopenharmony_ci#include "vk_fence.h"
32bf215546Sopenharmony_ci#include "vk_format.h"
33bf215546Sopenharmony_ci#include "vk_instance.h"
34bf215546Sopenharmony_ci#include "vk_physical_device.h"
35bf215546Sopenharmony_ci#include "vk_queue.h"
36bf215546Sopenharmony_ci#include "vk_semaphore.h"
37bf215546Sopenharmony_ci#include "vk_sync.h"
38bf215546Sopenharmony_ci#include "vk_sync_dummy.h"
39bf215546Sopenharmony_ci#include "vk_util.h"
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci#include <time.h>
42bf215546Sopenharmony_ci#include <stdlib.h>
43bf215546Sopenharmony_ci#include <stdio.h>
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#ifndef _WIN32
46bf215546Sopenharmony_ci#include <unistd.h>
47bf215546Sopenharmony_ci#endif
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ciuint64_t WSI_DEBUG;
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_cistatic const struct debug_control debug_control[] = {
52bf215546Sopenharmony_ci   { "buffer",       WSI_DEBUG_BUFFER },
53bf215546Sopenharmony_ci   { "sw",           WSI_DEBUG_SW },
54bf215546Sopenharmony_ci   { "noshm",        WSI_DEBUG_NOSHM },
55bf215546Sopenharmony_ci   { "linear",       WSI_DEBUG_LINEAR },
56bf215546Sopenharmony_ci   { NULL, },
57bf215546Sopenharmony_ci};
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_ciVkResult
60bf215546Sopenharmony_ciwsi_device_init(struct wsi_device *wsi,
61bf215546Sopenharmony_ci                VkPhysicalDevice pdevice,
62bf215546Sopenharmony_ci                WSI_FN_GetPhysicalDeviceProcAddr proc_addr,
63bf215546Sopenharmony_ci                const VkAllocationCallbacks *alloc,
64bf215546Sopenharmony_ci                int display_fd,
65bf215546Sopenharmony_ci                const struct driOptionCache *dri_options,
66bf215546Sopenharmony_ci                bool sw_device)
67bf215546Sopenharmony_ci{
68bf215546Sopenharmony_ci   const char *present_mode;
69bf215546Sopenharmony_ci   UNUSED VkResult result;
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci   WSI_DEBUG = parse_debug_string(getenv("MESA_VK_WSI_DEBUG"), debug_control);
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ci   memset(wsi, 0, sizeof(*wsi));
74bf215546Sopenharmony_ci
75bf215546Sopenharmony_ci   wsi->instance_alloc = *alloc;
76bf215546Sopenharmony_ci   wsi->pdevice = pdevice;
77bf215546Sopenharmony_ci   wsi->sw = sw_device || (WSI_DEBUG & WSI_DEBUG_SW);
78bf215546Sopenharmony_ci   wsi->wants_linear = (WSI_DEBUG & WSI_DEBUG_LINEAR) != 0;
79bf215546Sopenharmony_ci#define WSI_GET_CB(func) \
80bf215546Sopenharmony_ci   PFN_vk##func func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
81bf215546Sopenharmony_ci   WSI_GET_CB(GetPhysicalDeviceExternalSemaphoreProperties);
82bf215546Sopenharmony_ci   WSI_GET_CB(GetPhysicalDeviceProperties2);
83bf215546Sopenharmony_ci   WSI_GET_CB(GetPhysicalDeviceMemoryProperties);
84bf215546Sopenharmony_ci   WSI_GET_CB(GetPhysicalDeviceQueueFamilyProperties);
85bf215546Sopenharmony_ci#undef WSI_GET_CB
86bf215546Sopenharmony_ci
87bf215546Sopenharmony_ci   wsi->pci_bus_info.sType =
88bf215546Sopenharmony_ci      VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT;
89bf215546Sopenharmony_ci   VkPhysicalDeviceProperties2 pdp2 = {
90bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
91bf215546Sopenharmony_ci      .pNext = &wsi->pci_bus_info,
92bf215546Sopenharmony_ci   };
93bf215546Sopenharmony_ci   GetPhysicalDeviceProperties2(pdevice, &pdp2);
94bf215546Sopenharmony_ci
95bf215546Sopenharmony_ci   wsi->maxImageDimension2D = pdp2.properties.limits.maxImageDimension2D;
96bf215546Sopenharmony_ci   assert(pdp2.properties.limits.optimalBufferCopyRowPitchAlignment <= UINT32_MAX);
97bf215546Sopenharmony_ci   wsi->optimalBufferCopyRowPitchAlignment =
98bf215546Sopenharmony_ci      pdp2.properties.limits.optimalBufferCopyRowPitchAlignment;
99bf215546Sopenharmony_ci   wsi->override_present_mode = VK_PRESENT_MODE_MAX_ENUM_KHR;
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci   GetPhysicalDeviceMemoryProperties(pdevice, &wsi->memory_props);
102bf215546Sopenharmony_ci   GetPhysicalDeviceQueueFamilyProperties(pdevice, &wsi->queue_family_count, NULL);
103bf215546Sopenharmony_ci
104bf215546Sopenharmony_ci   for (VkExternalSemaphoreHandleTypeFlags handle_type = 1;
105bf215546Sopenharmony_ci        handle_type <= VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT;
106bf215546Sopenharmony_ci        handle_type <<= 1) {
107bf215546Sopenharmony_ci      const VkPhysicalDeviceExternalSemaphoreInfo esi = {
108bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_SEMAPHORE_INFO,
109bf215546Sopenharmony_ci         .handleType = handle_type,
110bf215546Sopenharmony_ci      };
111bf215546Sopenharmony_ci      VkExternalSemaphoreProperties esp = {
112bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_EXTERNAL_SEMAPHORE_PROPERTIES,
113bf215546Sopenharmony_ci      };
114bf215546Sopenharmony_ci      GetPhysicalDeviceExternalSemaphoreProperties(pdevice, &esi, &esp);
115bf215546Sopenharmony_ci
116bf215546Sopenharmony_ci      if (esp.externalSemaphoreFeatures &
117bf215546Sopenharmony_ci          VK_EXTERNAL_SEMAPHORE_FEATURE_EXPORTABLE_BIT)
118bf215546Sopenharmony_ci         wsi->semaphore_export_handle_types |= handle_type;
119bf215546Sopenharmony_ci   }
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci   const struct vk_device_extension_table *supported_extensions =
122bf215546Sopenharmony_ci      &vk_physical_device_from_handle(pdevice)->supported_extensions;
123bf215546Sopenharmony_ci   wsi->has_import_memory_host =
124bf215546Sopenharmony_ci      supported_extensions->EXT_external_memory_host;
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci   list_inithead(&wsi->hotplug_fences);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci#define WSI_GET_CB(func) \
129bf215546Sopenharmony_ci   wsi->func = (PFN_vk##func)proc_addr(pdevice, "vk" #func)
130bf215546Sopenharmony_ci   WSI_GET_CB(AllocateMemory);
131bf215546Sopenharmony_ci   WSI_GET_CB(AllocateCommandBuffers);
132bf215546Sopenharmony_ci   WSI_GET_CB(BindBufferMemory);
133bf215546Sopenharmony_ci   WSI_GET_CB(BindImageMemory);
134bf215546Sopenharmony_ci   WSI_GET_CB(BeginCommandBuffer);
135bf215546Sopenharmony_ci   WSI_GET_CB(CmdPipelineBarrier);
136bf215546Sopenharmony_ci   WSI_GET_CB(CmdCopyImageToBuffer);
137bf215546Sopenharmony_ci   WSI_GET_CB(CreateBuffer);
138bf215546Sopenharmony_ci   WSI_GET_CB(CreateCommandPool);
139bf215546Sopenharmony_ci   WSI_GET_CB(CreateFence);
140bf215546Sopenharmony_ci   WSI_GET_CB(CreateImage);
141bf215546Sopenharmony_ci   WSI_GET_CB(CreateSemaphore);
142bf215546Sopenharmony_ci   WSI_GET_CB(DestroyBuffer);
143bf215546Sopenharmony_ci   WSI_GET_CB(DestroyCommandPool);
144bf215546Sopenharmony_ci   WSI_GET_CB(DestroyFence);
145bf215546Sopenharmony_ci   WSI_GET_CB(DestroyImage);
146bf215546Sopenharmony_ci   WSI_GET_CB(DestroySemaphore);
147bf215546Sopenharmony_ci   WSI_GET_CB(EndCommandBuffer);
148bf215546Sopenharmony_ci   WSI_GET_CB(FreeMemory);
149bf215546Sopenharmony_ci   WSI_GET_CB(FreeCommandBuffers);
150bf215546Sopenharmony_ci   WSI_GET_CB(GetBufferMemoryRequirements);
151bf215546Sopenharmony_ci   WSI_GET_CB(GetImageDrmFormatModifierPropertiesEXT);
152bf215546Sopenharmony_ci   WSI_GET_CB(GetImageMemoryRequirements);
153bf215546Sopenharmony_ci   WSI_GET_CB(GetImageSubresourceLayout);
154bf215546Sopenharmony_ci   if (!wsi->sw)
155bf215546Sopenharmony_ci      WSI_GET_CB(GetMemoryFdKHR);
156bf215546Sopenharmony_ci   WSI_GET_CB(GetPhysicalDeviceFormatProperties);
157bf215546Sopenharmony_ci   WSI_GET_CB(GetPhysicalDeviceFormatProperties2KHR);
158bf215546Sopenharmony_ci   WSI_GET_CB(GetPhysicalDeviceImageFormatProperties2);
159bf215546Sopenharmony_ci   WSI_GET_CB(GetSemaphoreFdKHR);
160bf215546Sopenharmony_ci   WSI_GET_CB(ResetFences);
161bf215546Sopenharmony_ci   WSI_GET_CB(QueueSubmit);
162bf215546Sopenharmony_ci   WSI_GET_CB(WaitForFences);
163bf215546Sopenharmony_ci   WSI_GET_CB(MapMemory);
164bf215546Sopenharmony_ci   WSI_GET_CB(UnmapMemory);
165bf215546Sopenharmony_ci#undef WSI_GET_CB
166bf215546Sopenharmony_ci
167bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR
168bf215546Sopenharmony_ci   result = wsi_x11_init_wsi(wsi, alloc, dri_options);
169bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
170bf215546Sopenharmony_ci      goto fail;
171bf215546Sopenharmony_ci#endif
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR
174bf215546Sopenharmony_ci   result = wsi_wl_init_wsi(wsi, alloc, pdevice);
175bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
176bf215546Sopenharmony_ci      goto fail;
177bf215546Sopenharmony_ci#endif
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WIN32_KHR
180bf215546Sopenharmony_ci   result = wsi_win32_init_wsi(wsi, alloc, pdevice);
181bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
182bf215546Sopenharmony_ci      goto fail;
183bf215546Sopenharmony_ci#endif
184bf215546Sopenharmony_ci
185bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_DISPLAY_KHR
186bf215546Sopenharmony_ci   result = wsi_display_init_wsi(wsi, alloc, display_fd);
187bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
188bf215546Sopenharmony_ci      goto fail;
189bf215546Sopenharmony_ci#endif
190bf215546Sopenharmony_ci
191bf215546Sopenharmony_ci   present_mode = getenv("MESA_VK_WSI_PRESENT_MODE");
192bf215546Sopenharmony_ci   if (present_mode) {
193bf215546Sopenharmony_ci      if (!strcmp(present_mode, "fifo")) {
194bf215546Sopenharmony_ci         wsi->override_present_mode = VK_PRESENT_MODE_FIFO_KHR;
195bf215546Sopenharmony_ci      } else if (!strcmp(present_mode, "relaxed")) {
196bf215546Sopenharmony_ci          wsi->override_present_mode = VK_PRESENT_MODE_FIFO_RELAXED_KHR;
197bf215546Sopenharmony_ci      } else if (!strcmp(present_mode, "mailbox")) {
198bf215546Sopenharmony_ci         wsi->override_present_mode = VK_PRESENT_MODE_MAILBOX_KHR;
199bf215546Sopenharmony_ci      } else if (!strcmp(present_mode, "immediate")) {
200bf215546Sopenharmony_ci         wsi->override_present_mode = VK_PRESENT_MODE_IMMEDIATE_KHR;
201bf215546Sopenharmony_ci      } else {
202bf215546Sopenharmony_ci         fprintf(stderr, "Invalid MESA_VK_WSI_PRESENT_MODE value!\n");
203bf215546Sopenharmony_ci      }
204bf215546Sopenharmony_ci   }
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   if (dri_options) {
207bf215546Sopenharmony_ci      if (driCheckOption(dri_options, "adaptive_sync", DRI_BOOL))
208bf215546Sopenharmony_ci         wsi->enable_adaptive_sync = driQueryOptionb(dri_options,
209bf215546Sopenharmony_ci                                                     "adaptive_sync");
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci      if (driCheckOption(dri_options, "vk_wsi_force_bgra8_unorm_first",  DRI_BOOL)) {
212bf215546Sopenharmony_ci         wsi->force_bgra8_unorm_first =
213bf215546Sopenharmony_ci            driQueryOptionb(dri_options, "vk_wsi_force_bgra8_unorm_first");
214bf215546Sopenharmony_ci      }
215bf215546Sopenharmony_ci   }
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci   return VK_SUCCESS;
218bf215546Sopenharmony_ci#if defined(VK_USE_PLATFORM_XCB_KHR) || \
219bf215546Sopenharmony_ci   defined(VK_USE_PLATFORM_WAYLAND_KHR) || \
220bf215546Sopenharmony_ci   defined(VK_USE_PLATFORM_WIN32_KHR) || \
221bf215546Sopenharmony_ci   defined(VK_USE_PLATFORM_DISPLAY_KHR)
222bf215546Sopenharmony_cifail:
223bf215546Sopenharmony_ci   wsi_device_finish(wsi, alloc);
224bf215546Sopenharmony_ci   return result;
225bf215546Sopenharmony_ci#endif
226bf215546Sopenharmony_ci}
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_civoid
229bf215546Sopenharmony_ciwsi_device_finish(struct wsi_device *wsi,
230bf215546Sopenharmony_ci                  const VkAllocationCallbacks *alloc)
231bf215546Sopenharmony_ci{
232bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_DISPLAY_KHR
233bf215546Sopenharmony_ci   wsi_display_finish_wsi(wsi, alloc);
234bf215546Sopenharmony_ci#endif
235bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WAYLAND_KHR
236bf215546Sopenharmony_ci   wsi_wl_finish_wsi(wsi, alloc);
237bf215546Sopenharmony_ci#endif
238bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_WIN32_KHR
239bf215546Sopenharmony_ci   wsi_win32_finish_wsi(wsi, alloc);
240bf215546Sopenharmony_ci#endif
241bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_XCB_KHR
242bf215546Sopenharmony_ci   wsi_x11_finish_wsi(wsi, alloc);
243bf215546Sopenharmony_ci#endif
244bf215546Sopenharmony_ci}
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
247bf215546Sopenharmony_ciwsi_DestroySurfaceKHR(VkInstance _instance,
248bf215546Sopenharmony_ci                      VkSurfaceKHR _surface,
249bf215546Sopenharmony_ci                      const VkAllocationCallbacks *pAllocator)
250bf215546Sopenharmony_ci{
251bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_instance, instance, _instance);
252bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
253bf215546Sopenharmony_ci
254bf215546Sopenharmony_ci   if (!surface)
255bf215546Sopenharmony_ci      return;
256bf215546Sopenharmony_ci
257bf215546Sopenharmony_ci   vk_free2(&instance->alloc, pAllocator, surface);
258bf215546Sopenharmony_ci}
259bf215546Sopenharmony_ci
260bf215546Sopenharmony_civoid
261bf215546Sopenharmony_ciwsi_device_setup_syncobj_fd(struct wsi_device *wsi_device,
262bf215546Sopenharmony_ci                            int fd)
263bf215546Sopenharmony_ci{
264bf215546Sopenharmony_ci#ifdef VK_USE_PLATFORM_DISPLAY_KHR
265bf215546Sopenharmony_ci   wsi_display_setup_syncobj_fd(wsi_device, fd);
266bf215546Sopenharmony_ci#endif
267bf215546Sopenharmony_ci}
268bf215546Sopenharmony_ci
269bf215546Sopenharmony_ciVkResult
270bf215546Sopenharmony_ciwsi_swapchain_init(const struct wsi_device *wsi,
271bf215546Sopenharmony_ci                   struct wsi_swapchain *chain,
272bf215546Sopenharmony_ci                   VkDevice _device,
273bf215546Sopenharmony_ci                   const VkSwapchainCreateInfoKHR *pCreateInfo,
274bf215546Sopenharmony_ci                   const VkAllocationCallbacks *pAllocator,
275bf215546Sopenharmony_ci                   bool use_buffer_blit)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
278bf215546Sopenharmony_ci   VkResult result;
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci   memset(chain, 0, sizeof(*chain));
281bf215546Sopenharmony_ci
282bf215546Sopenharmony_ci   vk_object_base_init(device, &chain->base, VK_OBJECT_TYPE_SWAPCHAIN_KHR);
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci   chain->wsi = wsi;
285bf215546Sopenharmony_ci   chain->device = _device;
286bf215546Sopenharmony_ci   chain->alloc = *pAllocator;
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci   chain->use_buffer_blit = use_buffer_blit || (WSI_DEBUG & WSI_DEBUG_BUFFER);
289bf215546Sopenharmony_ci   if (wsi->sw && !wsi->wants_linear)
290bf215546Sopenharmony_ci      chain->use_buffer_blit = true;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci   chain->buffer_blit_queue = VK_NULL_HANDLE;
293bf215546Sopenharmony_ci   if (use_buffer_blit && wsi->get_buffer_blit_queue)
294bf215546Sopenharmony_ci      chain->buffer_blit_queue = wsi->get_buffer_blit_queue(_device);
295bf215546Sopenharmony_ci
296bf215546Sopenharmony_ci   int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   chain->cmd_pools =
299bf215546Sopenharmony_ci      vk_zalloc(pAllocator, sizeof(VkCommandPool) * cmd_pools_count, 8,
300bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
301bf215546Sopenharmony_ci   if (!chain->cmd_pools)
302bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   for (uint32_t i = 0; i < cmd_pools_count; i++) {
305bf215546Sopenharmony_ci      int queue_family_index = i;
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci      if (chain->buffer_blit_queue != VK_NULL_HANDLE) {
308bf215546Sopenharmony_ci         VK_FROM_HANDLE(vk_queue, queue, chain->buffer_blit_queue);
309bf215546Sopenharmony_ci         queue_family_index = queue->queue_family_index;
310bf215546Sopenharmony_ci      }
311bf215546Sopenharmony_ci      const VkCommandPoolCreateInfo cmd_pool_info = {
312bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
313bf215546Sopenharmony_ci         .pNext = NULL,
314bf215546Sopenharmony_ci         .flags = 0,
315bf215546Sopenharmony_ci         .queueFamilyIndex = queue_family_index,
316bf215546Sopenharmony_ci      };
317bf215546Sopenharmony_ci      result = wsi->CreateCommandPool(_device, &cmd_pool_info, &chain->alloc,
318bf215546Sopenharmony_ci                                      &chain->cmd_pools[i]);
319bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
320bf215546Sopenharmony_ci         goto fail;
321bf215546Sopenharmony_ci   }
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci   return VK_SUCCESS;
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_cifail:
326bf215546Sopenharmony_ci   wsi_swapchain_finish(chain);
327bf215546Sopenharmony_ci   return result;
328bf215546Sopenharmony_ci}
329bf215546Sopenharmony_ci
330bf215546Sopenharmony_cistatic bool
331bf215546Sopenharmony_ciwsi_swapchain_is_present_mode_supported(struct wsi_device *wsi,
332bf215546Sopenharmony_ci                                        const VkSwapchainCreateInfoKHR *pCreateInfo,
333bf215546Sopenharmony_ci                                        VkPresentModeKHR mode)
334bf215546Sopenharmony_ci{
335bf215546Sopenharmony_ci      ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
336bf215546Sopenharmony_ci      struct wsi_interface *iface = wsi->wsi[surface->platform];
337bf215546Sopenharmony_ci      VkPresentModeKHR *present_modes;
338bf215546Sopenharmony_ci      uint32_t present_mode_count;
339bf215546Sopenharmony_ci      bool supported = false;
340bf215546Sopenharmony_ci      VkResult result;
341bf215546Sopenharmony_ci
342bf215546Sopenharmony_ci      result = iface->get_present_modes(surface, &present_mode_count, NULL);
343bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
344bf215546Sopenharmony_ci         return supported;
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci      present_modes = malloc(present_mode_count * sizeof(*present_modes));
347bf215546Sopenharmony_ci      if (!present_modes)
348bf215546Sopenharmony_ci         return supported;
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci      result = iface->get_present_modes(surface, &present_mode_count,
351bf215546Sopenharmony_ci                                        present_modes);
352bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
353bf215546Sopenharmony_ci         goto fail;
354bf215546Sopenharmony_ci
355bf215546Sopenharmony_ci      for (uint32_t i = 0; i < present_mode_count; i++) {
356bf215546Sopenharmony_ci         if (present_modes[i] == mode) {
357bf215546Sopenharmony_ci            supported = true;
358bf215546Sopenharmony_ci            break;
359bf215546Sopenharmony_ci         }
360bf215546Sopenharmony_ci      }
361bf215546Sopenharmony_ci
362bf215546Sopenharmony_cifail:
363bf215546Sopenharmony_ci      free(present_modes);
364bf215546Sopenharmony_ci      return supported;
365bf215546Sopenharmony_ci}
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_cienum VkPresentModeKHR
368bf215546Sopenharmony_ciwsi_swapchain_get_present_mode(struct wsi_device *wsi,
369bf215546Sopenharmony_ci                               const VkSwapchainCreateInfoKHR *pCreateInfo)
370bf215546Sopenharmony_ci{
371bf215546Sopenharmony_ci   if (wsi->override_present_mode == VK_PRESENT_MODE_MAX_ENUM_KHR)
372bf215546Sopenharmony_ci      return pCreateInfo->presentMode;
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci   if (!wsi_swapchain_is_present_mode_supported(wsi, pCreateInfo,
375bf215546Sopenharmony_ci                                                wsi->override_present_mode)) {
376bf215546Sopenharmony_ci      fprintf(stderr, "Unsupported MESA_VK_WSI_PRESENT_MODE value!\n");
377bf215546Sopenharmony_ci      return pCreateInfo->presentMode;
378bf215546Sopenharmony_ci   }
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci   return wsi->override_present_mode;
381bf215546Sopenharmony_ci}
382bf215546Sopenharmony_ci
383bf215546Sopenharmony_civoid
384bf215546Sopenharmony_ciwsi_swapchain_finish(struct wsi_swapchain *chain)
385bf215546Sopenharmony_ci{
386bf215546Sopenharmony_ci   if (chain->fences) {
387bf215546Sopenharmony_ci      for (unsigned i = 0; i < chain->image_count; i++)
388bf215546Sopenharmony_ci         chain->wsi->DestroyFence(chain->device, chain->fences[i], &chain->alloc);
389bf215546Sopenharmony_ci
390bf215546Sopenharmony_ci      vk_free(&chain->alloc, chain->fences);
391bf215546Sopenharmony_ci   }
392bf215546Sopenharmony_ci   if (chain->buffer_blit_semaphores) {
393bf215546Sopenharmony_ci      for (unsigned i = 0; i < chain->image_count; i++)
394bf215546Sopenharmony_ci         chain->wsi->DestroySemaphore(chain->device, chain->buffer_blit_semaphores[i], &chain->alloc);
395bf215546Sopenharmony_ci
396bf215546Sopenharmony_ci      vk_free(&chain->alloc, chain->buffer_blit_semaphores);
397bf215546Sopenharmony_ci   }
398bf215546Sopenharmony_ci   chain->wsi->DestroySemaphore(chain->device, chain->dma_buf_semaphore,
399bf215546Sopenharmony_ci                                &chain->alloc);
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci   int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ?
402bf215546Sopenharmony_ci      1 : chain->wsi->queue_family_count;
403bf215546Sopenharmony_ci   for (uint32_t i = 0; i < cmd_pools_count; i++) {
404bf215546Sopenharmony_ci      chain->wsi->DestroyCommandPool(chain->device, chain->cmd_pools[i],
405bf215546Sopenharmony_ci                                     &chain->alloc);
406bf215546Sopenharmony_ci   }
407bf215546Sopenharmony_ci   vk_free(&chain->alloc, chain->cmd_pools);
408bf215546Sopenharmony_ci
409bf215546Sopenharmony_ci   vk_object_base_finish(&chain->base);
410bf215546Sopenharmony_ci}
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ciVkResult
413bf215546Sopenharmony_ciwsi_configure_image(const struct wsi_swapchain *chain,
414bf215546Sopenharmony_ci                    const VkSwapchainCreateInfoKHR *pCreateInfo,
415bf215546Sopenharmony_ci                    VkExternalMemoryHandleTypeFlags handle_types,
416bf215546Sopenharmony_ci                    struct wsi_image_info *info)
417bf215546Sopenharmony_ci{
418bf215546Sopenharmony_ci   memset(info, 0, sizeof(*info));
419bf215546Sopenharmony_ci   uint32_t queue_family_count = 1;
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ci   if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT)
422bf215546Sopenharmony_ci      queue_family_count = pCreateInfo->queueFamilyIndexCount;
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci   /*
425bf215546Sopenharmony_ci    * TODO: there should be no reason to allocate this, but
426bf215546Sopenharmony_ci    * 15331 shows that games crashed without doing this.
427bf215546Sopenharmony_ci    */
428bf215546Sopenharmony_ci   uint32_t *queue_family_indices =
429bf215546Sopenharmony_ci      vk_alloc(&chain->alloc,
430bf215546Sopenharmony_ci               sizeof(*queue_family_indices) *
431bf215546Sopenharmony_ci               queue_family_count,
432bf215546Sopenharmony_ci               8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
433bf215546Sopenharmony_ci   if (!queue_family_indices)
434bf215546Sopenharmony_ci      goto err_oom;
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   if (pCreateInfo->imageSharingMode == VK_SHARING_MODE_CONCURRENT)
437bf215546Sopenharmony_ci      for (uint32_t i = 0; i < pCreateInfo->queueFamilyIndexCount; i++)
438bf215546Sopenharmony_ci         queue_family_indices[i] = pCreateInfo->pQueueFamilyIndices[i];
439bf215546Sopenharmony_ci
440bf215546Sopenharmony_ci   info->create = (VkImageCreateInfo) {
441bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
442bf215546Sopenharmony_ci      .flags = VK_IMAGE_CREATE_ALIAS_BIT,
443bf215546Sopenharmony_ci      .imageType = VK_IMAGE_TYPE_2D,
444bf215546Sopenharmony_ci      .format = pCreateInfo->imageFormat,
445bf215546Sopenharmony_ci      .extent = {
446bf215546Sopenharmony_ci         .width = pCreateInfo->imageExtent.width,
447bf215546Sopenharmony_ci         .height = pCreateInfo->imageExtent.height,
448bf215546Sopenharmony_ci         .depth = 1,
449bf215546Sopenharmony_ci      },
450bf215546Sopenharmony_ci      .mipLevels = 1,
451bf215546Sopenharmony_ci      .arrayLayers = 1,
452bf215546Sopenharmony_ci      .samples = VK_SAMPLE_COUNT_1_BIT,
453bf215546Sopenharmony_ci      .tiling = VK_IMAGE_TILING_OPTIMAL,
454bf215546Sopenharmony_ci      .usage = pCreateInfo->imageUsage,
455bf215546Sopenharmony_ci      .sharingMode = pCreateInfo->imageSharingMode,
456bf215546Sopenharmony_ci      .queueFamilyIndexCount = queue_family_count,
457bf215546Sopenharmony_ci      .pQueueFamilyIndices = queue_family_indices,
458bf215546Sopenharmony_ci      .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
459bf215546Sopenharmony_ci   };
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci   if (handle_types != 0) {
462bf215546Sopenharmony_ci      info->ext_mem = (VkExternalMemoryImageCreateInfo) {
463bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
464bf215546Sopenharmony_ci         .handleTypes = handle_types,
465bf215546Sopenharmony_ci      };
466bf215546Sopenharmony_ci      __vk_append_struct(&info->create, &info->ext_mem);
467bf215546Sopenharmony_ci   }
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci   info->wsi = (struct wsi_image_create_info) {
470bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
471bf215546Sopenharmony_ci   };
472bf215546Sopenharmony_ci   __vk_append_struct(&info->create, &info->wsi);
473bf215546Sopenharmony_ci
474bf215546Sopenharmony_ci   if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
475bf215546Sopenharmony_ci      info->create.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
476bf215546Sopenharmony_ci                            VK_IMAGE_CREATE_EXTENDED_USAGE_BIT;
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci      const VkImageFormatListCreateInfo *format_list_in =
479bf215546Sopenharmony_ci         vk_find_struct_const(pCreateInfo->pNext,
480bf215546Sopenharmony_ci                              IMAGE_FORMAT_LIST_CREATE_INFO);
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_ci      assume(format_list_in && format_list_in->viewFormatCount > 0);
483bf215546Sopenharmony_ci
484bf215546Sopenharmony_ci      const uint32_t view_format_count = format_list_in->viewFormatCount;
485bf215546Sopenharmony_ci      VkFormat *view_formats =
486bf215546Sopenharmony_ci         vk_alloc(&chain->alloc, sizeof(VkFormat) * view_format_count,
487bf215546Sopenharmony_ci                  8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
488bf215546Sopenharmony_ci      if (!view_formats)
489bf215546Sopenharmony_ci         goto err_oom;
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci      ASSERTED bool format_found = false;
492bf215546Sopenharmony_ci      for (uint32_t i = 0; i < format_list_in->viewFormatCount; i++) {
493bf215546Sopenharmony_ci         if (pCreateInfo->imageFormat == format_list_in->pViewFormats[i])
494bf215546Sopenharmony_ci            format_found = true;
495bf215546Sopenharmony_ci         view_formats[i] = format_list_in->pViewFormats[i];
496bf215546Sopenharmony_ci      }
497bf215546Sopenharmony_ci      assert(format_found);
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci      info->format_list = (VkImageFormatListCreateInfo) {
500bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO,
501bf215546Sopenharmony_ci         .viewFormatCount = view_format_count,
502bf215546Sopenharmony_ci         .pViewFormats = view_formats,
503bf215546Sopenharmony_ci      };
504bf215546Sopenharmony_ci      __vk_append_struct(&info->create, &info->format_list);
505bf215546Sopenharmony_ci   }
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_ci   return VK_SUCCESS;
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_cierr_oom:
510bf215546Sopenharmony_ci   wsi_destroy_image_info(chain, info);
511bf215546Sopenharmony_ci   return VK_ERROR_OUT_OF_HOST_MEMORY;
512bf215546Sopenharmony_ci}
513bf215546Sopenharmony_ci
514bf215546Sopenharmony_civoid
515bf215546Sopenharmony_ciwsi_destroy_image_info(const struct wsi_swapchain *chain,
516bf215546Sopenharmony_ci                       struct wsi_image_info *info)
517bf215546Sopenharmony_ci{
518bf215546Sopenharmony_ci   vk_free(&chain->alloc, (void *)info->create.pQueueFamilyIndices);
519bf215546Sopenharmony_ci   vk_free(&chain->alloc, (void *)info->format_list.pViewFormats);
520bf215546Sopenharmony_ci   vk_free(&chain->alloc, (void *)info->drm_mod_list.pDrmFormatModifiers);
521bf215546Sopenharmony_ci   vk_free(&chain->alloc, info->modifier_props);
522bf215546Sopenharmony_ci}
523bf215546Sopenharmony_ci
524bf215546Sopenharmony_ciVkResult
525bf215546Sopenharmony_ciwsi_create_image(const struct wsi_swapchain *chain,
526bf215546Sopenharmony_ci                 const struct wsi_image_info *info,
527bf215546Sopenharmony_ci                 struct wsi_image *image)
528bf215546Sopenharmony_ci{
529bf215546Sopenharmony_ci   const struct wsi_device *wsi = chain->wsi;
530bf215546Sopenharmony_ci   VkResult result;
531bf215546Sopenharmony_ci
532bf215546Sopenharmony_ci   memset(image, 0, sizeof(*image));
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci#ifndef _WIN32
535bf215546Sopenharmony_ci   image->dma_buf_fd = -1;
536bf215546Sopenharmony_ci#endif
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ci   result = wsi->CreateImage(chain->device, &info->create,
539bf215546Sopenharmony_ci                             &chain->alloc, &image->image);
540bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
541bf215546Sopenharmony_ci      goto fail;
542bf215546Sopenharmony_ci
543bf215546Sopenharmony_ci   result = info->create_mem(chain, info, image);
544bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
545bf215546Sopenharmony_ci      goto fail;
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_ci   result = wsi->BindImageMemory(chain->device, image->image,
548bf215546Sopenharmony_ci                                 image->memory, 0);
549bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
550bf215546Sopenharmony_ci      goto fail;
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci   if (info->finish_create) {
553bf215546Sopenharmony_ci      result = info->finish_create(chain, info, image);
554bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
555bf215546Sopenharmony_ci         goto fail;
556bf215546Sopenharmony_ci   }
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   return VK_SUCCESS;
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_cifail:
561bf215546Sopenharmony_ci   wsi_destroy_image(chain, image);
562bf215546Sopenharmony_ci   return result;
563bf215546Sopenharmony_ci}
564bf215546Sopenharmony_ci
565bf215546Sopenharmony_civoid
566bf215546Sopenharmony_ciwsi_destroy_image(const struct wsi_swapchain *chain,
567bf215546Sopenharmony_ci                  struct wsi_image *image)
568bf215546Sopenharmony_ci{
569bf215546Sopenharmony_ci   const struct wsi_device *wsi = chain->wsi;
570bf215546Sopenharmony_ci
571bf215546Sopenharmony_ci#ifndef _WIN32
572bf215546Sopenharmony_ci   if (image->dma_buf_fd >= 0)
573bf215546Sopenharmony_ci      close(image->dma_buf_fd);
574bf215546Sopenharmony_ci#endif
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci   if (image->cpu_map != NULL) {
577bf215546Sopenharmony_ci      wsi->UnmapMemory(chain->device, image->buffer.buffer != VK_NULL_HANDLE ?
578bf215546Sopenharmony_ci                                      image->buffer.memory : image->memory);
579bf215546Sopenharmony_ci   }
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci   if (image->buffer.blit_cmd_buffers) {
582bf215546Sopenharmony_ci      int cmd_buffer_count =
583bf215546Sopenharmony_ci         chain->buffer_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci      for (uint32_t i = 0; i < cmd_buffer_count; i++) {
586bf215546Sopenharmony_ci         wsi->FreeCommandBuffers(chain->device, chain->cmd_pools[i],
587bf215546Sopenharmony_ci                                 1, &image->buffer.blit_cmd_buffers[i]);
588bf215546Sopenharmony_ci      }
589bf215546Sopenharmony_ci      vk_free(&chain->alloc, image->buffer.blit_cmd_buffers);
590bf215546Sopenharmony_ci   }
591bf215546Sopenharmony_ci
592bf215546Sopenharmony_ci   wsi->FreeMemory(chain->device, image->memory, &chain->alloc);
593bf215546Sopenharmony_ci   wsi->DestroyImage(chain->device, image->image, &chain->alloc);
594bf215546Sopenharmony_ci   wsi->FreeMemory(chain->device, image->buffer.memory, &chain->alloc);
595bf215546Sopenharmony_ci   wsi->DestroyBuffer(chain->device, image->buffer.buffer, &chain->alloc);
596bf215546Sopenharmony_ci}
597bf215546Sopenharmony_ci
598bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
599bf215546Sopenharmony_ciwsi_GetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
600bf215546Sopenharmony_ci                                       uint32_t queueFamilyIndex,
601bf215546Sopenharmony_ci                                       VkSurfaceKHR _surface,
602bf215546Sopenharmony_ci                                       VkBool32 *pSupported)
603bf215546Sopenharmony_ci{
604bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
605bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
606bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
607bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
608bf215546Sopenharmony_ci
609bf215546Sopenharmony_ci   return iface->get_support(surface, wsi_device,
610bf215546Sopenharmony_ci                             queueFamilyIndex, pSupported);
611bf215546Sopenharmony_ci}
612bf215546Sopenharmony_ci
613bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
614bf215546Sopenharmony_ciwsi_GetPhysicalDeviceSurfaceCapabilitiesKHR(
615bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
616bf215546Sopenharmony_ci   VkSurfaceKHR _surface,
617bf215546Sopenharmony_ci   VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
618bf215546Sopenharmony_ci{
619bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
620bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
621bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
622bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
623bf215546Sopenharmony_ci
624bf215546Sopenharmony_ci   VkSurfaceCapabilities2KHR caps2 = {
625bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
626bf215546Sopenharmony_ci   };
627bf215546Sopenharmony_ci
628bf215546Sopenharmony_ci   VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
629bf215546Sopenharmony_ci
630bf215546Sopenharmony_ci   if (result == VK_SUCCESS)
631bf215546Sopenharmony_ci      *pSurfaceCapabilities = caps2.surfaceCapabilities;
632bf215546Sopenharmony_ci
633bf215546Sopenharmony_ci   return result;
634bf215546Sopenharmony_ci}
635bf215546Sopenharmony_ci
636bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
637bf215546Sopenharmony_ciwsi_GetPhysicalDeviceSurfaceCapabilities2KHR(
638bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
639bf215546Sopenharmony_ci   const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
640bf215546Sopenharmony_ci   VkSurfaceCapabilities2KHR *pSurfaceCapabilities)
641bf215546Sopenharmony_ci{
642bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
643bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
644bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
645bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
646bf215546Sopenharmony_ci
647bf215546Sopenharmony_ci   return iface->get_capabilities2(surface, wsi_device, pSurfaceInfo->pNext,
648bf215546Sopenharmony_ci                                   pSurfaceCapabilities);
649bf215546Sopenharmony_ci}
650bf215546Sopenharmony_ci
651bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
652bf215546Sopenharmony_ciwsi_GetPhysicalDeviceSurfaceCapabilities2EXT(
653bf215546Sopenharmony_ci   VkPhysicalDevice physicalDevice,
654bf215546Sopenharmony_ci   VkSurfaceKHR _surface,
655bf215546Sopenharmony_ci   VkSurfaceCapabilities2EXT *pSurfaceCapabilities)
656bf215546Sopenharmony_ci{
657bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
658bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
659bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
660bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci   assert(pSurfaceCapabilities->sType ==
663bf215546Sopenharmony_ci          VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT);
664bf215546Sopenharmony_ci
665bf215546Sopenharmony_ci   struct wsi_surface_supported_counters counters = {
666bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_WSI_SURFACE_SUPPORTED_COUNTERS_MESA,
667bf215546Sopenharmony_ci      .pNext = pSurfaceCapabilities->pNext,
668bf215546Sopenharmony_ci      .supported_surface_counters = 0,
669bf215546Sopenharmony_ci   };
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci   VkSurfaceCapabilities2KHR caps2 = {
672bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR,
673bf215546Sopenharmony_ci      .pNext = &counters,
674bf215546Sopenharmony_ci   };
675bf215546Sopenharmony_ci
676bf215546Sopenharmony_ci   VkResult result = iface->get_capabilities2(surface, wsi_device, NULL, &caps2);
677bf215546Sopenharmony_ci
678bf215546Sopenharmony_ci   if (result == VK_SUCCESS) {
679bf215546Sopenharmony_ci      VkSurfaceCapabilities2EXT *ext_caps = pSurfaceCapabilities;
680bf215546Sopenharmony_ci      VkSurfaceCapabilitiesKHR khr_caps = caps2.surfaceCapabilities;
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_ci      ext_caps->minImageCount = khr_caps.minImageCount;
683bf215546Sopenharmony_ci      ext_caps->maxImageCount = khr_caps.maxImageCount;
684bf215546Sopenharmony_ci      ext_caps->currentExtent = khr_caps.currentExtent;
685bf215546Sopenharmony_ci      ext_caps->minImageExtent = khr_caps.minImageExtent;
686bf215546Sopenharmony_ci      ext_caps->maxImageExtent = khr_caps.maxImageExtent;
687bf215546Sopenharmony_ci      ext_caps->maxImageArrayLayers = khr_caps.maxImageArrayLayers;
688bf215546Sopenharmony_ci      ext_caps->supportedTransforms = khr_caps.supportedTransforms;
689bf215546Sopenharmony_ci      ext_caps->currentTransform = khr_caps.currentTransform;
690bf215546Sopenharmony_ci      ext_caps->supportedCompositeAlpha = khr_caps.supportedCompositeAlpha;
691bf215546Sopenharmony_ci      ext_caps->supportedUsageFlags = khr_caps.supportedUsageFlags;
692bf215546Sopenharmony_ci      ext_caps->supportedSurfaceCounters = counters.supported_surface_counters;
693bf215546Sopenharmony_ci   }
694bf215546Sopenharmony_ci
695bf215546Sopenharmony_ci   return result;
696bf215546Sopenharmony_ci}
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
699bf215546Sopenharmony_ciwsi_GetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
700bf215546Sopenharmony_ci                                       VkSurfaceKHR _surface,
701bf215546Sopenharmony_ci                                       uint32_t *pSurfaceFormatCount,
702bf215546Sopenharmony_ci                                       VkSurfaceFormatKHR *pSurfaceFormats)
703bf215546Sopenharmony_ci{
704bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
705bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
706bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
707bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
708bf215546Sopenharmony_ci
709bf215546Sopenharmony_ci   return iface->get_formats(surface, wsi_device,
710bf215546Sopenharmony_ci                             pSurfaceFormatCount, pSurfaceFormats);
711bf215546Sopenharmony_ci}
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
714bf215546Sopenharmony_ciwsi_GetPhysicalDeviceSurfaceFormats2KHR(VkPhysicalDevice physicalDevice,
715bf215546Sopenharmony_ci                                        const VkPhysicalDeviceSurfaceInfo2KHR * pSurfaceInfo,
716bf215546Sopenharmony_ci                                        uint32_t *pSurfaceFormatCount,
717bf215546Sopenharmony_ci                                        VkSurfaceFormat2KHR *pSurfaceFormats)
718bf215546Sopenharmony_ci{
719bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
720bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pSurfaceInfo->surface);
721bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
722bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci   return iface->get_formats2(surface, wsi_device, pSurfaceInfo->pNext,
725bf215546Sopenharmony_ci                              pSurfaceFormatCount, pSurfaceFormats);
726bf215546Sopenharmony_ci}
727bf215546Sopenharmony_ci
728bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
729bf215546Sopenharmony_ciwsi_GetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
730bf215546Sopenharmony_ci                                            VkSurfaceKHR _surface,
731bf215546Sopenharmony_ci                                            uint32_t *pPresentModeCount,
732bf215546Sopenharmony_ci                                            VkPresentModeKHR *pPresentModes)
733bf215546Sopenharmony_ci{
734bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
735bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
736bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
737bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci   return iface->get_present_modes(surface, pPresentModeCount,
740bf215546Sopenharmony_ci                                   pPresentModes);
741bf215546Sopenharmony_ci}
742bf215546Sopenharmony_ci
743bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
744bf215546Sopenharmony_ciwsi_GetPhysicalDevicePresentRectanglesKHR(VkPhysicalDevice physicalDevice,
745bf215546Sopenharmony_ci                                          VkSurfaceKHR _surface,
746bf215546Sopenharmony_ci                                          uint32_t *pRectCount,
747bf215546Sopenharmony_ci                                          VkRect2D *pRects)
748bf215546Sopenharmony_ci{
749bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, device, physicalDevice);
750bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, _surface);
751bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->wsi_device;
752bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
753bf215546Sopenharmony_ci
754bf215546Sopenharmony_ci   return iface->get_present_rectangles(surface, wsi_device,
755bf215546Sopenharmony_ci                                        pRectCount, pRects);
756bf215546Sopenharmony_ci}
757bf215546Sopenharmony_ci
758bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
759bf215546Sopenharmony_ciwsi_CreateSwapchainKHR(VkDevice _device,
760bf215546Sopenharmony_ci                       const VkSwapchainCreateInfoKHR *pCreateInfo,
761bf215546Sopenharmony_ci                       const VkAllocationCallbacks *pAllocator,
762bf215546Sopenharmony_ci                       VkSwapchainKHR *pSwapchain)
763bf215546Sopenharmony_ci{
764bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
765bf215546Sopenharmony_ci   ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
766bf215546Sopenharmony_ci   struct wsi_device *wsi_device = device->physical->wsi_device;
767bf215546Sopenharmony_ci   struct wsi_interface *iface = wsi_device->wsi[surface->platform];
768bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc;
769bf215546Sopenharmony_ci   struct wsi_swapchain *swapchain;
770bf215546Sopenharmony_ci
771bf215546Sopenharmony_ci   if (pAllocator)
772bf215546Sopenharmony_ci     alloc = pAllocator;
773bf215546Sopenharmony_ci   else
774bf215546Sopenharmony_ci     alloc = &device->alloc;
775bf215546Sopenharmony_ci
776bf215546Sopenharmony_ci   VkResult result = iface->create_swapchain(surface, _device, wsi_device,
777bf215546Sopenharmony_ci                                             pCreateInfo, alloc,
778bf215546Sopenharmony_ci                                             &swapchain);
779bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
780bf215546Sopenharmony_ci      return result;
781bf215546Sopenharmony_ci
782bf215546Sopenharmony_ci   swapchain->fences = vk_zalloc(alloc,
783bf215546Sopenharmony_ci                                 sizeof (*swapchain->fences) * swapchain->image_count,
784bf215546Sopenharmony_ci                                 sizeof (*swapchain->fences),
785bf215546Sopenharmony_ci                                 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
786bf215546Sopenharmony_ci   if (!swapchain->fences) {
787bf215546Sopenharmony_ci      swapchain->destroy(swapchain, alloc);
788bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
789bf215546Sopenharmony_ci   }
790bf215546Sopenharmony_ci
791bf215546Sopenharmony_ci   if (swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
792bf215546Sopenharmony_ci      swapchain->buffer_blit_semaphores = vk_zalloc(alloc,
793bf215546Sopenharmony_ci                                         sizeof (*swapchain->buffer_blit_semaphores) * swapchain->image_count,
794bf215546Sopenharmony_ci                                         sizeof (*swapchain->buffer_blit_semaphores),
795bf215546Sopenharmony_ci                                         VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
796bf215546Sopenharmony_ci      if (!swapchain->buffer_blit_semaphores) {
797bf215546Sopenharmony_ci         swapchain->destroy(swapchain, alloc);
798bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_HOST_MEMORY;
799bf215546Sopenharmony_ci      }
800bf215546Sopenharmony_ci   }
801bf215546Sopenharmony_ci
802bf215546Sopenharmony_ci   *pSwapchain = wsi_swapchain_to_handle(swapchain);
803bf215546Sopenharmony_ci
804bf215546Sopenharmony_ci   return VK_SUCCESS;
805bf215546Sopenharmony_ci}
806bf215546Sopenharmony_ci
807bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL
808bf215546Sopenharmony_ciwsi_DestroySwapchainKHR(VkDevice _device,
809bf215546Sopenharmony_ci                        VkSwapchainKHR _swapchain,
810bf215546Sopenharmony_ci                        const VkAllocationCallbacks *pAllocator)
811bf215546Sopenharmony_ci{
812bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
813bf215546Sopenharmony_ci   VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
814bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc;
815bf215546Sopenharmony_ci
816bf215546Sopenharmony_ci   if (!swapchain)
817bf215546Sopenharmony_ci      return;
818bf215546Sopenharmony_ci
819bf215546Sopenharmony_ci   if (pAllocator)
820bf215546Sopenharmony_ci     alloc = pAllocator;
821bf215546Sopenharmony_ci   else
822bf215546Sopenharmony_ci     alloc = &device->alloc;
823bf215546Sopenharmony_ci
824bf215546Sopenharmony_ci   swapchain->destroy(swapchain, alloc);
825bf215546Sopenharmony_ci}
826bf215546Sopenharmony_ci
827bf215546Sopenharmony_ciVkResult
828bf215546Sopenharmony_ciwsi_common_get_images(VkSwapchainKHR _swapchain,
829bf215546Sopenharmony_ci                      uint32_t *pSwapchainImageCount,
830bf215546Sopenharmony_ci                      VkImage *pSwapchainImages)
831bf215546Sopenharmony_ci{
832bf215546Sopenharmony_ci   VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
833bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkImage, images, pSwapchainImages, pSwapchainImageCount);
834bf215546Sopenharmony_ci
835bf215546Sopenharmony_ci   for (uint32_t i = 0; i < swapchain->image_count; i++) {
836bf215546Sopenharmony_ci      vk_outarray_append_typed(VkImage, &images, image) {
837bf215546Sopenharmony_ci         *image = swapchain->get_wsi_image(swapchain, i)->image;
838bf215546Sopenharmony_ci      }
839bf215546Sopenharmony_ci   }
840bf215546Sopenharmony_ci
841bf215546Sopenharmony_ci   return vk_outarray_status(&images);
842bf215546Sopenharmony_ci}
843bf215546Sopenharmony_ci
844bf215546Sopenharmony_ciVkImage
845bf215546Sopenharmony_ciwsi_common_get_image(VkSwapchainKHR _swapchain, uint32_t index)
846bf215546Sopenharmony_ci{
847bf215546Sopenharmony_ci   VK_FROM_HANDLE(wsi_swapchain, swapchain, _swapchain);
848bf215546Sopenharmony_ci   assert(index < swapchain->image_count);
849bf215546Sopenharmony_ci   return swapchain->get_wsi_image(swapchain, index)->image;
850bf215546Sopenharmony_ci}
851bf215546Sopenharmony_ci
852bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
853bf215546Sopenharmony_ciwsi_GetSwapchainImagesKHR(VkDevice device,
854bf215546Sopenharmony_ci                          VkSwapchainKHR swapchain,
855bf215546Sopenharmony_ci                          uint32_t *pSwapchainImageCount,
856bf215546Sopenharmony_ci                          VkImage *pSwapchainImages)
857bf215546Sopenharmony_ci{
858bf215546Sopenharmony_ci   return wsi_common_get_images(swapchain,
859bf215546Sopenharmony_ci                                pSwapchainImageCount,
860bf215546Sopenharmony_ci                                pSwapchainImages);
861bf215546Sopenharmony_ci}
862bf215546Sopenharmony_ci
863bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
864bf215546Sopenharmony_ciwsi_AcquireNextImageKHR(VkDevice _device,
865bf215546Sopenharmony_ci                        VkSwapchainKHR swapchain,
866bf215546Sopenharmony_ci                        uint64_t timeout,
867bf215546Sopenharmony_ci                        VkSemaphore semaphore,
868bf215546Sopenharmony_ci                        VkFence fence,
869bf215546Sopenharmony_ci                        uint32_t *pImageIndex)
870bf215546Sopenharmony_ci{
871bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
872bf215546Sopenharmony_ci
873bf215546Sopenharmony_ci   const VkAcquireNextImageInfoKHR acquire_info = {
874bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_ACQUIRE_NEXT_IMAGE_INFO_KHR,
875bf215546Sopenharmony_ci      .swapchain = swapchain,
876bf215546Sopenharmony_ci      .timeout = timeout,
877bf215546Sopenharmony_ci      .semaphore = semaphore,
878bf215546Sopenharmony_ci      .fence = fence,
879bf215546Sopenharmony_ci      .deviceMask = 0,
880bf215546Sopenharmony_ci   };
881bf215546Sopenharmony_ci
882bf215546Sopenharmony_ci   return device->dispatch_table.AcquireNextImage2KHR(_device, &acquire_info,
883bf215546Sopenharmony_ci                                                      pImageIndex);
884bf215546Sopenharmony_ci}
885bf215546Sopenharmony_ci
886bf215546Sopenharmony_cistatic VkResult
887bf215546Sopenharmony_ciwsi_signal_semaphore_for_image(struct vk_device *device,
888bf215546Sopenharmony_ci                               const struct wsi_swapchain *chain,
889bf215546Sopenharmony_ci                               const struct wsi_image *image,
890bf215546Sopenharmony_ci                               VkSemaphore _semaphore)
891bf215546Sopenharmony_ci{
892bf215546Sopenharmony_ci   if (device->physical->supported_sync_types == NULL)
893bf215546Sopenharmony_ci      return VK_SUCCESS;
894bf215546Sopenharmony_ci
895bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_semaphore, semaphore, _semaphore);
896bf215546Sopenharmony_ci
897bf215546Sopenharmony_ci   vk_semaphore_reset_temporary(device, semaphore);
898bf215546Sopenharmony_ci
899bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
900bf215546Sopenharmony_ci   VkResult result = wsi_create_sync_for_dma_buf_wait(chain, image,
901bf215546Sopenharmony_ci                                                      VK_SYNC_FEATURE_GPU_WAIT,
902bf215546Sopenharmony_ci                                                      &semaphore->temporary);
903bf215546Sopenharmony_ci   if (result != VK_ERROR_FEATURE_NOT_PRESENT)
904bf215546Sopenharmony_ci      return result;
905bf215546Sopenharmony_ci#endif
906bf215546Sopenharmony_ci
907bf215546Sopenharmony_ci   if (chain->wsi->signal_semaphore_with_memory) {
908bf215546Sopenharmony_ci      return device->create_sync_for_memory(device, image->memory,
909bf215546Sopenharmony_ci                                            false /* signal_memory */,
910bf215546Sopenharmony_ci                                            &semaphore->temporary);
911bf215546Sopenharmony_ci   } else {
912bf215546Sopenharmony_ci      return vk_sync_create(device, &vk_sync_dummy_type,
913bf215546Sopenharmony_ci                            0 /* flags */, 0 /* initial_value */,
914bf215546Sopenharmony_ci                            &semaphore->temporary);
915bf215546Sopenharmony_ci   }
916bf215546Sopenharmony_ci}
917bf215546Sopenharmony_ci
918bf215546Sopenharmony_cistatic VkResult
919bf215546Sopenharmony_ciwsi_signal_fence_for_image(struct vk_device *device,
920bf215546Sopenharmony_ci                           const struct wsi_swapchain *chain,
921bf215546Sopenharmony_ci                           const struct wsi_image *image,
922bf215546Sopenharmony_ci                           VkFence _fence)
923bf215546Sopenharmony_ci{
924bf215546Sopenharmony_ci   if (device->physical->supported_sync_types == NULL)
925bf215546Sopenharmony_ci      return VK_SUCCESS;
926bf215546Sopenharmony_ci
927bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_fence, fence, _fence);
928bf215546Sopenharmony_ci
929bf215546Sopenharmony_ci   vk_fence_reset_temporary(device, fence);
930bf215546Sopenharmony_ci
931bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
932bf215546Sopenharmony_ci   VkResult result = wsi_create_sync_for_dma_buf_wait(chain, image,
933bf215546Sopenharmony_ci                                                      VK_SYNC_FEATURE_CPU_WAIT,
934bf215546Sopenharmony_ci                                                      &fence->temporary);
935bf215546Sopenharmony_ci   if (result != VK_ERROR_FEATURE_NOT_PRESENT)
936bf215546Sopenharmony_ci      return result;
937bf215546Sopenharmony_ci#endif
938bf215546Sopenharmony_ci
939bf215546Sopenharmony_ci   if (chain->wsi->signal_fence_with_memory) {
940bf215546Sopenharmony_ci      return device->create_sync_for_memory(device, image->memory,
941bf215546Sopenharmony_ci                                            false /* signal_memory */,
942bf215546Sopenharmony_ci                                            &fence->temporary);
943bf215546Sopenharmony_ci   } else {
944bf215546Sopenharmony_ci      return vk_sync_create(device, &vk_sync_dummy_type,
945bf215546Sopenharmony_ci                            0 /* flags */, 0 /* initial_value */,
946bf215546Sopenharmony_ci                            &fence->temporary);
947bf215546Sopenharmony_ci   }
948bf215546Sopenharmony_ci}
949bf215546Sopenharmony_ci
950bf215546Sopenharmony_ciVkResult
951bf215546Sopenharmony_ciwsi_common_acquire_next_image2(const struct wsi_device *wsi,
952bf215546Sopenharmony_ci                               VkDevice _device,
953bf215546Sopenharmony_ci                               const VkAcquireNextImageInfoKHR *pAcquireInfo,
954bf215546Sopenharmony_ci                               uint32_t *pImageIndex)
955bf215546Sopenharmony_ci{
956bf215546Sopenharmony_ci   VK_FROM_HANDLE(wsi_swapchain, swapchain, pAcquireInfo->swapchain);
957bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
958bf215546Sopenharmony_ci
959bf215546Sopenharmony_ci   VkResult result = swapchain->acquire_next_image(swapchain, pAcquireInfo,
960bf215546Sopenharmony_ci                                                   pImageIndex);
961bf215546Sopenharmony_ci   if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
962bf215546Sopenharmony_ci      return result;
963bf215546Sopenharmony_ci   struct wsi_image *image =
964bf215546Sopenharmony_ci      swapchain->get_wsi_image(swapchain, *pImageIndex);
965bf215546Sopenharmony_ci
966bf215546Sopenharmony_ci   if (pAcquireInfo->semaphore != VK_NULL_HANDLE) {
967bf215546Sopenharmony_ci      VkResult signal_result =
968bf215546Sopenharmony_ci         wsi_signal_semaphore_for_image(device, swapchain, image,
969bf215546Sopenharmony_ci                                        pAcquireInfo->semaphore);
970bf215546Sopenharmony_ci      if (signal_result != VK_SUCCESS)
971bf215546Sopenharmony_ci         return signal_result;
972bf215546Sopenharmony_ci   }
973bf215546Sopenharmony_ci
974bf215546Sopenharmony_ci   if (pAcquireInfo->fence != VK_NULL_HANDLE) {
975bf215546Sopenharmony_ci      VkResult signal_result =
976bf215546Sopenharmony_ci         wsi_signal_fence_for_image(device, swapchain, image,
977bf215546Sopenharmony_ci                                    pAcquireInfo->fence);
978bf215546Sopenharmony_ci      if (signal_result != VK_SUCCESS)
979bf215546Sopenharmony_ci         return signal_result;
980bf215546Sopenharmony_ci   }
981bf215546Sopenharmony_ci
982bf215546Sopenharmony_ci   if (wsi->set_memory_ownership)
983bf215546Sopenharmony_ci      wsi->set_memory_ownership(swapchain->device, image->memory, true);
984bf215546Sopenharmony_ci
985bf215546Sopenharmony_ci   return result;
986bf215546Sopenharmony_ci}
987bf215546Sopenharmony_ci
988bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
989bf215546Sopenharmony_ciwsi_AcquireNextImage2KHR(VkDevice _device,
990bf215546Sopenharmony_ci                         const VkAcquireNextImageInfoKHR *pAcquireInfo,
991bf215546Sopenharmony_ci                         uint32_t *pImageIndex)
992bf215546Sopenharmony_ci{
993bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_device, device, _device);
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_ci   return wsi_common_acquire_next_image2(device->physical->wsi_device,
996bf215546Sopenharmony_ci                                         _device, pAcquireInfo, pImageIndex);
997bf215546Sopenharmony_ci}
998bf215546Sopenharmony_ci
999bf215546Sopenharmony_ciVkResult
1000bf215546Sopenharmony_ciwsi_common_queue_present(const struct wsi_device *wsi,
1001bf215546Sopenharmony_ci                         VkDevice device,
1002bf215546Sopenharmony_ci                         VkQueue queue,
1003bf215546Sopenharmony_ci                         int queue_family_index,
1004bf215546Sopenharmony_ci                         const VkPresentInfoKHR *pPresentInfo)
1005bf215546Sopenharmony_ci{
1006bf215546Sopenharmony_ci   VkResult final_result = VK_SUCCESS;
1007bf215546Sopenharmony_ci
1008bf215546Sopenharmony_ci   STACK_ARRAY(VkPipelineStageFlags, stage_flags,
1009bf215546Sopenharmony_ci               MAX2(1, pPresentInfo->waitSemaphoreCount));
1010bf215546Sopenharmony_ci   for (uint32_t s = 0; s < MAX2(1, pPresentInfo->waitSemaphoreCount); s++)
1011bf215546Sopenharmony_ci      stage_flags[s] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
1012bf215546Sopenharmony_ci
1013bf215546Sopenharmony_ci   const VkPresentRegionsKHR *regions =
1014bf215546Sopenharmony_ci      vk_find_struct_const(pPresentInfo->pNext, PRESENT_REGIONS_KHR);
1015bf215546Sopenharmony_ci
1016bf215546Sopenharmony_ci   for (uint32_t i = 0; i < pPresentInfo->swapchainCount; i++) {
1017bf215546Sopenharmony_ci      VK_FROM_HANDLE(wsi_swapchain, swapchain, pPresentInfo->pSwapchains[i]);
1018bf215546Sopenharmony_ci      uint32_t image_index = pPresentInfo->pImageIndices[i];
1019bf215546Sopenharmony_ci      VkResult result;
1020bf215546Sopenharmony_ci
1021bf215546Sopenharmony_ci      if (swapchain->fences[image_index] == VK_NULL_HANDLE) {
1022bf215546Sopenharmony_ci         const VkFenceCreateInfo fence_info = {
1023bf215546Sopenharmony_ci            .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
1024bf215546Sopenharmony_ci            .pNext = NULL,
1025bf215546Sopenharmony_ci            .flags = VK_FENCE_CREATE_SIGNALED_BIT,
1026bf215546Sopenharmony_ci         };
1027bf215546Sopenharmony_ci         result = wsi->CreateFence(device, &fence_info,
1028bf215546Sopenharmony_ci                                   &swapchain->alloc,
1029bf215546Sopenharmony_ci                                   &swapchain->fences[image_index]);
1030bf215546Sopenharmony_ci         if (result != VK_SUCCESS)
1031bf215546Sopenharmony_ci            goto fail_present;
1032bf215546Sopenharmony_ci
1033bf215546Sopenharmony_ci         if (swapchain->use_buffer_blit && swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
1034bf215546Sopenharmony_ci            const VkSemaphoreCreateInfo sem_info = {
1035bf215546Sopenharmony_ci               .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
1036bf215546Sopenharmony_ci               .pNext = NULL,
1037bf215546Sopenharmony_ci               .flags = 0,
1038bf215546Sopenharmony_ci            };
1039bf215546Sopenharmony_ci            result = wsi->CreateSemaphore(device, &sem_info,
1040bf215546Sopenharmony_ci                                          &swapchain->alloc,
1041bf215546Sopenharmony_ci                                          &swapchain->buffer_blit_semaphores[image_index]);
1042bf215546Sopenharmony_ci            if (result != VK_SUCCESS)
1043bf215546Sopenharmony_ci               goto fail_present;
1044bf215546Sopenharmony_ci         }
1045bf215546Sopenharmony_ci      } else {
1046bf215546Sopenharmony_ci         result =
1047bf215546Sopenharmony_ci            wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
1048bf215546Sopenharmony_ci                               true, ~0ull);
1049bf215546Sopenharmony_ci         if (result != VK_SUCCESS)
1050bf215546Sopenharmony_ci            goto fail_present;
1051bf215546Sopenharmony_ci      }
1052bf215546Sopenharmony_ci
1053bf215546Sopenharmony_ci      result = wsi->ResetFences(device, 1, &swapchain->fences[image_index]);
1054bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1055bf215546Sopenharmony_ci         goto fail_present;
1056bf215546Sopenharmony_ci
1057bf215546Sopenharmony_ci      VkSubmitInfo submit_info = {
1058bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
1059bf215546Sopenharmony_ci      };
1060bf215546Sopenharmony_ci
1061bf215546Sopenharmony_ci      if (i == 0) {
1062bf215546Sopenharmony_ci         /* We only need/want to wait on semaphores once.  After that, we're
1063bf215546Sopenharmony_ci          * guaranteed ordering since it all happens on the same queue.
1064bf215546Sopenharmony_ci          */
1065bf215546Sopenharmony_ci         submit_info.waitSemaphoreCount = pPresentInfo->waitSemaphoreCount;
1066bf215546Sopenharmony_ci         submit_info.pWaitSemaphores = pPresentInfo->pWaitSemaphores;
1067bf215546Sopenharmony_ci         submit_info.pWaitDstStageMask = stage_flags;
1068bf215546Sopenharmony_ci      }
1069bf215546Sopenharmony_ci
1070bf215546Sopenharmony_ci      struct wsi_image *image =
1071bf215546Sopenharmony_ci         swapchain->get_wsi_image(swapchain, image_index);
1072bf215546Sopenharmony_ci
1073bf215546Sopenharmony_ci      VkQueue submit_queue = queue;
1074bf215546Sopenharmony_ci      if (swapchain->use_buffer_blit) {
1075bf215546Sopenharmony_ci         if (swapchain->buffer_blit_queue == VK_NULL_HANDLE) {
1076bf215546Sopenharmony_ci            submit_info.commandBufferCount = 1;
1077bf215546Sopenharmony_ci            submit_info.pCommandBuffers =
1078bf215546Sopenharmony_ci               &image->buffer.blit_cmd_buffers[queue_family_index];
1079bf215546Sopenharmony_ci         } else {
1080bf215546Sopenharmony_ci            /* If we are using a blit using the driver's private queue, then
1081bf215546Sopenharmony_ci             * do an empty submit signalling a semaphore, and then submit the
1082bf215546Sopenharmony_ci             * blit waiting on that.  This ensures proper queue ordering of
1083bf215546Sopenharmony_ci             * vkQueueSubmit() calls.
1084bf215546Sopenharmony_ci             */
1085bf215546Sopenharmony_ci            submit_info.signalSemaphoreCount = 1;
1086bf215546Sopenharmony_ci            submit_info.pSignalSemaphores =
1087bf215546Sopenharmony_ci               &swapchain->buffer_blit_semaphores[image_index];
1088bf215546Sopenharmony_ci
1089bf215546Sopenharmony_ci            result = wsi->QueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
1090bf215546Sopenharmony_ci            if (result != VK_SUCCESS)
1091bf215546Sopenharmony_ci               goto fail_present;
1092bf215546Sopenharmony_ci
1093bf215546Sopenharmony_ci            /* Now prepare the blit submit.  It needs to then wait on the
1094bf215546Sopenharmony_ci             * semaphore we signaled above.
1095bf215546Sopenharmony_ci             */
1096bf215546Sopenharmony_ci            submit_queue = swapchain->buffer_blit_queue;
1097bf215546Sopenharmony_ci            submit_info.waitSemaphoreCount = 1;
1098bf215546Sopenharmony_ci            submit_info.pWaitSemaphores = submit_info.pSignalSemaphores;
1099bf215546Sopenharmony_ci            submit_info.signalSemaphoreCount = 0;
1100bf215546Sopenharmony_ci            submit_info.pSignalSemaphores = NULL;
1101bf215546Sopenharmony_ci            submit_info.commandBufferCount = 1;
1102bf215546Sopenharmony_ci            submit_info.pCommandBuffers = &image->buffer.blit_cmd_buffers[0];
1103bf215546Sopenharmony_ci            submit_info.pWaitDstStageMask = stage_flags;
1104bf215546Sopenharmony_ci         }
1105bf215546Sopenharmony_ci      }
1106bf215546Sopenharmony_ci
1107bf215546Sopenharmony_ci      VkFence fence = swapchain->fences[image_index];
1108bf215546Sopenharmony_ci
1109bf215546Sopenharmony_ci      bool has_signal_dma_buf = false;
1110bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
1111bf215546Sopenharmony_ci      result = wsi_prepare_signal_dma_buf_from_semaphore(swapchain, image);
1112bf215546Sopenharmony_ci      if (result == VK_SUCCESS) {
1113bf215546Sopenharmony_ci         assert(submit_info.signalSemaphoreCount == 0);
1114bf215546Sopenharmony_ci         submit_info.signalSemaphoreCount = 1;
1115bf215546Sopenharmony_ci         submit_info.pSignalSemaphores = &swapchain->dma_buf_semaphore;
1116bf215546Sopenharmony_ci         has_signal_dma_buf = true;
1117bf215546Sopenharmony_ci      } else if (result == VK_ERROR_FEATURE_NOT_PRESENT) {
1118bf215546Sopenharmony_ci         result = VK_SUCCESS;
1119bf215546Sopenharmony_ci         has_signal_dma_buf = false;
1120bf215546Sopenharmony_ci      } else {
1121bf215546Sopenharmony_ci         goto fail_present;
1122bf215546Sopenharmony_ci      }
1123bf215546Sopenharmony_ci#endif
1124bf215546Sopenharmony_ci
1125bf215546Sopenharmony_ci      struct wsi_memory_signal_submit_info mem_signal;
1126bf215546Sopenharmony_ci      if (!has_signal_dma_buf) {
1127bf215546Sopenharmony_ci         /* If we don't have dma-buf signaling, signal the memory object by
1128bf215546Sopenharmony_ci          * chaining wsi_memory_signal_submit_info into VkSubmitInfo.
1129bf215546Sopenharmony_ci          */
1130bf215546Sopenharmony_ci         result = VK_SUCCESS;
1131bf215546Sopenharmony_ci         has_signal_dma_buf = false;
1132bf215546Sopenharmony_ci         mem_signal = (struct wsi_memory_signal_submit_info) {
1133bf215546Sopenharmony_ci            .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA,
1134bf215546Sopenharmony_ci            .memory = image->memory,
1135bf215546Sopenharmony_ci         };
1136bf215546Sopenharmony_ci         __vk_append_struct(&submit_info, &mem_signal);
1137bf215546Sopenharmony_ci      }
1138bf215546Sopenharmony_ci
1139bf215546Sopenharmony_ci      result = wsi->QueueSubmit(submit_queue, 1, &submit_info, fence);
1140bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1141bf215546Sopenharmony_ci         goto fail_present;
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci#ifdef HAVE_LIBDRM
1144bf215546Sopenharmony_ci      if (has_signal_dma_buf) {
1145bf215546Sopenharmony_ci         result = wsi_signal_dma_buf_from_semaphore(swapchain, image);
1146bf215546Sopenharmony_ci         if (result != VK_SUCCESS)
1147bf215546Sopenharmony_ci            goto fail_present;
1148bf215546Sopenharmony_ci      }
1149bf215546Sopenharmony_ci#else
1150bf215546Sopenharmony_ci      assert(!has_signal_dma_buf);
1151bf215546Sopenharmony_ci#endif
1152bf215546Sopenharmony_ci
1153bf215546Sopenharmony_ci      if (wsi->sw)
1154bf215546Sopenharmony_ci	      wsi->WaitForFences(device, 1, &swapchain->fences[image_index],
1155bf215546Sopenharmony_ci				 true, ~0ull);
1156bf215546Sopenharmony_ci
1157bf215546Sopenharmony_ci      const VkPresentRegionKHR *region = NULL;
1158bf215546Sopenharmony_ci      if (regions && regions->pRegions)
1159bf215546Sopenharmony_ci         region = &regions->pRegions[i];
1160bf215546Sopenharmony_ci
1161bf215546Sopenharmony_ci      result = swapchain->queue_present(swapchain, image_index, region);
1162bf215546Sopenharmony_ci      if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
1163bf215546Sopenharmony_ci         goto fail_present;
1164bf215546Sopenharmony_ci
1165bf215546Sopenharmony_ci      if (wsi->set_memory_ownership) {
1166bf215546Sopenharmony_ci         VkDeviceMemory mem = swapchain->get_wsi_image(swapchain, image_index)->memory;
1167bf215546Sopenharmony_ci         wsi->set_memory_ownership(swapchain->device, mem, false);
1168bf215546Sopenharmony_ci      }
1169bf215546Sopenharmony_ci
1170bf215546Sopenharmony_ci   fail_present:
1171bf215546Sopenharmony_ci      if (pPresentInfo->pResults != NULL)
1172bf215546Sopenharmony_ci         pPresentInfo->pResults[i] = result;
1173bf215546Sopenharmony_ci
1174bf215546Sopenharmony_ci      /* Let the final result be our first unsuccessful result */
1175bf215546Sopenharmony_ci      if (final_result == VK_SUCCESS)
1176bf215546Sopenharmony_ci         final_result = result;
1177bf215546Sopenharmony_ci   }
1178bf215546Sopenharmony_ci
1179bf215546Sopenharmony_ci   STACK_ARRAY_FINISH(stage_flags);
1180bf215546Sopenharmony_ci
1181bf215546Sopenharmony_ci   return final_result;
1182bf215546Sopenharmony_ci}
1183bf215546Sopenharmony_ci
1184bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1185bf215546Sopenharmony_ciwsi_QueuePresentKHR(VkQueue _queue, const VkPresentInfoKHR *pPresentInfo)
1186bf215546Sopenharmony_ci{
1187bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_queue, queue, _queue);
1188bf215546Sopenharmony_ci
1189bf215546Sopenharmony_ci   return wsi_common_queue_present(queue->base.device->physical->wsi_device,
1190bf215546Sopenharmony_ci                                   vk_device_to_handle(queue->base.device),
1191bf215546Sopenharmony_ci                                   _queue,
1192bf215546Sopenharmony_ci                                   queue->queue_family_index,
1193bf215546Sopenharmony_ci                                   pPresentInfo);
1194bf215546Sopenharmony_ci}
1195bf215546Sopenharmony_ci
1196bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1197bf215546Sopenharmony_ciwsi_GetDeviceGroupPresentCapabilitiesKHR(VkDevice device,
1198bf215546Sopenharmony_ci                                         VkDeviceGroupPresentCapabilitiesKHR *pCapabilities)
1199bf215546Sopenharmony_ci{
1200bf215546Sopenharmony_ci   memset(pCapabilities->presentMask, 0,
1201bf215546Sopenharmony_ci          sizeof(pCapabilities->presentMask));
1202bf215546Sopenharmony_ci   pCapabilities->presentMask[0] = 0x1;
1203bf215546Sopenharmony_ci   pCapabilities->modes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1204bf215546Sopenharmony_ci
1205bf215546Sopenharmony_ci   return VK_SUCCESS;
1206bf215546Sopenharmony_ci}
1207bf215546Sopenharmony_ci
1208bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
1209bf215546Sopenharmony_ciwsi_GetDeviceGroupSurfacePresentModesKHR(VkDevice device,
1210bf215546Sopenharmony_ci                                         VkSurfaceKHR surface,
1211bf215546Sopenharmony_ci                                         VkDeviceGroupPresentModeFlagsKHR *pModes)
1212bf215546Sopenharmony_ci{
1213bf215546Sopenharmony_ci   *pModes = VK_DEVICE_GROUP_PRESENT_MODE_LOCAL_BIT_KHR;
1214bf215546Sopenharmony_ci
1215bf215546Sopenharmony_ci   return VK_SUCCESS;
1216bf215546Sopenharmony_ci}
1217bf215546Sopenharmony_ci
1218bf215546Sopenharmony_ciVkResult
1219bf215546Sopenharmony_ciwsi_common_create_swapchain_image(const struct wsi_device *wsi,
1220bf215546Sopenharmony_ci                                  const VkImageCreateInfo *pCreateInfo,
1221bf215546Sopenharmony_ci                                  VkSwapchainKHR _swapchain,
1222bf215546Sopenharmony_ci                                  VkImage *pImage)
1223bf215546Sopenharmony_ci{
1224bf215546Sopenharmony_ci   VK_FROM_HANDLE(wsi_swapchain, chain, _swapchain);
1225bf215546Sopenharmony_ci
1226bf215546Sopenharmony_ci#ifndef NDEBUG
1227bf215546Sopenharmony_ci   const VkImageCreateInfo *swcInfo = &chain->image_info.create;
1228bf215546Sopenharmony_ci   assert(pCreateInfo->flags == 0);
1229bf215546Sopenharmony_ci   assert(pCreateInfo->imageType == swcInfo->imageType);
1230bf215546Sopenharmony_ci   assert(pCreateInfo->format == swcInfo->format);
1231bf215546Sopenharmony_ci   assert(pCreateInfo->extent.width == swcInfo->extent.width);
1232bf215546Sopenharmony_ci   assert(pCreateInfo->extent.height == swcInfo->extent.height);
1233bf215546Sopenharmony_ci   assert(pCreateInfo->extent.depth == swcInfo->extent.depth);
1234bf215546Sopenharmony_ci   assert(pCreateInfo->mipLevels == swcInfo->mipLevels);
1235bf215546Sopenharmony_ci   assert(pCreateInfo->arrayLayers == swcInfo->arrayLayers);
1236bf215546Sopenharmony_ci   assert(pCreateInfo->samples == swcInfo->samples);
1237bf215546Sopenharmony_ci   assert(pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL);
1238bf215546Sopenharmony_ci   assert(!(pCreateInfo->usage & ~swcInfo->usage));
1239bf215546Sopenharmony_ci
1240bf215546Sopenharmony_ci   vk_foreach_struct_const(ext, pCreateInfo->pNext) {
1241bf215546Sopenharmony_ci      switch (ext->sType) {
1242bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO: {
1243bf215546Sopenharmony_ci         const VkImageFormatListCreateInfo *iflci =
1244bf215546Sopenharmony_ci            (const VkImageFormatListCreateInfo *)ext;
1245bf215546Sopenharmony_ci         const VkImageFormatListCreateInfo *swc_iflci =
1246bf215546Sopenharmony_ci            &chain->image_info.format_list;
1247bf215546Sopenharmony_ci
1248bf215546Sopenharmony_ci         for (uint32_t i = 0; i < iflci->viewFormatCount; i++) {
1249bf215546Sopenharmony_ci            bool found = false;
1250bf215546Sopenharmony_ci            for (uint32_t j = 0; j < swc_iflci->viewFormatCount; j++) {
1251bf215546Sopenharmony_ci               if (iflci->pViewFormats[i] == swc_iflci->pViewFormats[j]) {
1252bf215546Sopenharmony_ci                  found = true;
1253bf215546Sopenharmony_ci                  break;
1254bf215546Sopenharmony_ci               }
1255bf215546Sopenharmony_ci            }
1256bf215546Sopenharmony_ci            assert(found);
1257bf215546Sopenharmony_ci         }
1258bf215546Sopenharmony_ci         break;
1259bf215546Sopenharmony_ci      }
1260bf215546Sopenharmony_ci
1261bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_IMAGE_SWAPCHAIN_CREATE_INFO_KHR:
1262bf215546Sopenharmony_ci         break;
1263bf215546Sopenharmony_ci
1264bf215546Sopenharmony_ci      default:
1265bf215546Sopenharmony_ci         assert(!"Unsupported image create extension");
1266bf215546Sopenharmony_ci      }
1267bf215546Sopenharmony_ci   }
1268bf215546Sopenharmony_ci#endif
1269bf215546Sopenharmony_ci
1270bf215546Sopenharmony_ci   return wsi->CreateImage(chain->device, &chain->image_info.create,
1271bf215546Sopenharmony_ci                           &chain->alloc, pImage);
1272bf215546Sopenharmony_ci}
1273bf215546Sopenharmony_ci
1274bf215546Sopenharmony_ciVkResult
1275bf215546Sopenharmony_ciwsi_common_bind_swapchain_image(const struct wsi_device *wsi,
1276bf215546Sopenharmony_ci                                VkImage vk_image,
1277bf215546Sopenharmony_ci                                VkSwapchainKHR _swapchain,
1278bf215546Sopenharmony_ci                                uint32_t image_idx)
1279bf215546Sopenharmony_ci{
1280bf215546Sopenharmony_ci   VK_FROM_HANDLE(wsi_swapchain, chain, _swapchain);
1281bf215546Sopenharmony_ci   struct wsi_image *image = chain->get_wsi_image(chain, image_idx);
1282bf215546Sopenharmony_ci
1283bf215546Sopenharmony_ci   return wsi->BindImageMemory(chain->device, vk_image, image->memory, 0);
1284bf215546Sopenharmony_ci}
1285bf215546Sopenharmony_ci
1286bf215546Sopenharmony_ciuint32_t
1287bf215546Sopenharmony_ciwsi_select_memory_type(const struct wsi_device *wsi,
1288bf215546Sopenharmony_ci                       VkMemoryPropertyFlags req_props,
1289bf215546Sopenharmony_ci                       VkMemoryPropertyFlags deny_props,
1290bf215546Sopenharmony_ci                       uint32_t type_bits)
1291bf215546Sopenharmony_ci{
1292bf215546Sopenharmony_ci   assert(type_bits != 0);
1293bf215546Sopenharmony_ci
1294bf215546Sopenharmony_ci   VkMemoryPropertyFlags common_props = ~0;
1295bf215546Sopenharmony_ci   u_foreach_bit(t, type_bits) {
1296bf215546Sopenharmony_ci      const VkMemoryType type = wsi->memory_props.memoryTypes[t];
1297bf215546Sopenharmony_ci
1298bf215546Sopenharmony_ci      common_props &= type.propertyFlags;
1299bf215546Sopenharmony_ci
1300bf215546Sopenharmony_ci      if (deny_props & type.propertyFlags)
1301bf215546Sopenharmony_ci         continue;
1302bf215546Sopenharmony_ci
1303bf215546Sopenharmony_ci      if (!(req_props & ~type.propertyFlags))
1304bf215546Sopenharmony_ci         return t;
1305bf215546Sopenharmony_ci   }
1306bf215546Sopenharmony_ci
1307bf215546Sopenharmony_ci   if ((deny_props & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) &&
1308bf215546Sopenharmony_ci       (common_props & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
1309bf215546Sopenharmony_ci      /* If they asked for non-device-local and all the types are device-local
1310bf215546Sopenharmony_ci       * (this is commonly true for UMA platforms), try again without denying
1311bf215546Sopenharmony_ci       * device-local types
1312bf215546Sopenharmony_ci       */
1313bf215546Sopenharmony_ci      deny_props &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
1314bf215546Sopenharmony_ci      return wsi_select_memory_type(wsi, req_props, deny_props, type_bits);
1315bf215546Sopenharmony_ci   }
1316bf215546Sopenharmony_ci
1317bf215546Sopenharmony_ci   unreachable("No memory type found");
1318bf215546Sopenharmony_ci}
1319bf215546Sopenharmony_ci
1320bf215546Sopenharmony_ciuint32_t
1321bf215546Sopenharmony_ciwsi_select_device_memory_type(const struct wsi_device *wsi,
1322bf215546Sopenharmony_ci                              uint32_t type_bits)
1323bf215546Sopenharmony_ci{
1324bf215546Sopenharmony_ci   return wsi_select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
1325bf215546Sopenharmony_ci                                 0 /* deny_props */, type_bits);
1326bf215546Sopenharmony_ci}
1327bf215546Sopenharmony_ci
1328bf215546Sopenharmony_cistatic uint32_t
1329bf215546Sopenharmony_ciwsi_select_host_memory_type(const struct wsi_device *wsi,
1330bf215546Sopenharmony_ci                            uint32_t type_bits)
1331bf215546Sopenharmony_ci{
1332bf215546Sopenharmony_ci   return wsi_select_memory_type(wsi, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT,
1333bf215546Sopenharmony_ci                                 0 /* deny_props */, type_bits);
1334bf215546Sopenharmony_ci}
1335bf215546Sopenharmony_ci
1336bf215546Sopenharmony_ciVkResult
1337bf215546Sopenharmony_ciwsi_create_buffer_image_mem(const struct wsi_swapchain *chain,
1338bf215546Sopenharmony_ci                            const struct wsi_image_info *info,
1339bf215546Sopenharmony_ci                            struct wsi_image *image,
1340bf215546Sopenharmony_ci                            VkExternalMemoryHandleTypeFlags handle_types,
1341bf215546Sopenharmony_ci                            bool implicit_sync)
1342bf215546Sopenharmony_ci{
1343bf215546Sopenharmony_ci   const struct wsi_device *wsi = chain->wsi;
1344bf215546Sopenharmony_ci   VkResult result;
1345bf215546Sopenharmony_ci
1346bf215546Sopenharmony_ci   const VkExternalMemoryBufferCreateInfo buffer_external_info = {
1347bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
1348bf215546Sopenharmony_ci      .pNext = NULL,
1349bf215546Sopenharmony_ci      .handleTypes = handle_types,
1350bf215546Sopenharmony_ci   };
1351bf215546Sopenharmony_ci   const VkBufferCreateInfo buffer_info = {
1352bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
1353bf215546Sopenharmony_ci      .pNext = &buffer_external_info,
1354bf215546Sopenharmony_ci      .size = info->linear_size,
1355bf215546Sopenharmony_ci      .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
1356bf215546Sopenharmony_ci      .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
1357bf215546Sopenharmony_ci   };
1358bf215546Sopenharmony_ci   result = wsi->CreateBuffer(chain->device, &buffer_info,
1359bf215546Sopenharmony_ci                              &chain->alloc, &image->buffer.buffer);
1360bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1361bf215546Sopenharmony_ci      return result;
1362bf215546Sopenharmony_ci
1363bf215546Sopenharmony_ci   VkMemoryRequirements reqs;
1364bf215546Sopenharmony_ci   wsi->GetBufferMemoryRequirements(chain->device, image->buffer.buffer, &reqs);
1365bf215546Sopenharmony_ci   assert(reqs.size <= info->linear_size);
1366bf215546Sopenharmony_ci
1367bf215546Sopenharmony_ci   struct wsi_memory_allocate_info memory_wsi_info = {
1368bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
1369bf215546Sopenharmony_ci      .pNext = NULL,
1370bf215546Sopenharmony_ci      .implicit_sync = implicit_sync,
1371bf215546Sopenharmony_ci   };
1372bf215546Sopenharmony_ci   VkMemoryDedicatedAllocateInfo buf_mem_dedicated_info = {
1373bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1374bf215546Sopenharmony_ci      .pNext = &memory_wsi_info,
1375bf215546Sopenharmony_ci      .image = VK_NULL_HANDLE,
1376bf215546Sopenharmony_ci      .buffer = image->buffer.buffer,
1377bf215546Sopenharmony_ci   };
1378bf215546Sopenharmony_ci   VkMemoryAllocateInfo buf_mem_info = {
1379bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1380bf215546Sopenharmony_ci      .pNext = &buf_mem_dedicated_info,
1381bf215546Sopenharmony_ci      .allocationSize = info->linear_size,
1382bf215546Sopenharmony_ci      .memoryTypeIndex =
1383bf215546Sopenharmony_ci         info->select_buffer_memory_type(wsi, reqs.memoryTypeBits),
1384bf215546Sopenharmony_ci   };
1385bf215546Sopenharmony_ci
1386bf215546Sopenharmony_ci   void *sw_host_ptr = NULL;
1387bf215546Sopenharmony_ci   if (info->alloc_shm)
1388bf215546Sopenharmony_ci      sw_host_ptr = info->alloc_shm(image, info->linear_size);
1389bf215546Sopenharmony_ci
1390bf215546Sopenharmony_ci   VkExportMemoryAllocateInfo memory_export_info;
1391bf215546Sopenharmony_ci   VkImportMemoryHostPointerInfoEXT host_ptr_info;
1392bf215546Sopenharmony_ci   if (sw_host_ptr != NULL) {
1393bf215546Sopenharmony_ci      host_ptr_info = (VkImportMemoryHostPointerInfoEXT) {
1394bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
1395bf215546Sopenharmony_ci         .pHostPointer = sw_host_ptr,
1396bf215546Sopenharmony_ci         .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1397bf215546Sopenharmony_ci      };
1398bf215546Sopenharmony_ci      __vk_append_struct(&buf_mem_info, &host_ptr_info);
1399bf215546Sopenharmony_ci   } else if (handle_types != 0) {
1400bf215546Sopenharmony_ci      memory_export_info = (VkExportMemoryAllocateInfo) {
1401bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
1402bf215546Sopenharmony_ci         .handleTypes = handle_types,
1403bf215546Sopenharmony_ci      };
1404bf215546Sopenharmony_ci      __vk_append_struct(&buf_mem_info, &memory_export_info);
1405bf215546Sopenharmony_ci   }
1406bf215546Sopenharmony_ci
1407bf215546Sopenharmony_ci   result = wsi->AllocateMemory(chain->device, &buf_mem_info,
1408bf215546Sopenharmony_ci                                &chain->alloc, &image->buffer.memory);
1409bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1410bf215546Sopenharmony_ci      return result;
1411bf215546Sopenharmony_ci
1412bf215546Sopenharmony_ci   result = wsi->BindBufferMemory(chain->device, image->buffer.buffer,
1413bf215546Sopenharmony_ci                                  image->buffer.memory, 0);
1414bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1415bf215546Sopenharmony_ci      return result;
1416bf215546Sopenharmony_ci
1417bf215546Sopenharmony_ci   wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
1418bf215546Sopenharmony_ci
1419bf215546Sopenharmony_ci   const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
1420bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1421bf215546Sopenharmony_ci      .pNext = NULL,
1422bf215546Sopenharmony_ci      .image = image->image,
1423bf215546Sopenharmony_ci      .buffer = VK_NULL_HANDLE,
1424bf215546Sopenharmony_ci   };
1425bf215546Sopenharmony_ci   const VkMemoryAllocateInfo memory_info = {
1426bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1427bf215546Sopenharmony_ci      .pNext = &memory_dedicated_info,
1428bf215546Sopenharmony_ci      .allocationSize = reqs.size,
1429bf215546Sopenharmony_ci      .memoryTypeIndex =
1430bf215546Sopenharmony_ci         info->select_image_memory_type(wsi, reqs.memoryTypeBits),
1431bf215546Sopenharmony_ci   };
1432bf215546Sopenharmony_ci
1433bf215546Sopenharmony_ci   result = wsi->AllocateMemory(chain->device, &memory_info,
1434bf215546Sopenharmony_ci                                &chain->alloc, &image->memory);
1435bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1436bf215546Sopenharmony_ci      return result;
1437bf215546Sopenharmony_ci
1438bf215546Sopenharmony_ci   image->num_planes = 1;
1439bf215546Sopenharmony_ci   image->sizes[0] = info->linear_size;
1440bf215546Sopenharmony_ci   image->row_pitches[0] = info->linear_stride;
1441bf215546Sopenharmony_ci   image->offsets[0] = 0;
1442bf215546Sopenharmony_ci
1443bf215546Sopenharmony_ci   return VK_SUCCESS;
1444bf215546Sopenharmony_ci}
1445bf215546Sopenharmony_ci
1446bf215546Sopenharmony_ciVkResult
1447bf215546Sopenharmony_ciwsi_finish_create_buffer_image(const struct wsi_swapchain *chain,
1448bf215546Sopenharmony_ci                               const struct wsi_image_info *info,
1449bf215546Sopenharmony_ci                               struct wsi_image *image)
1450bf215546Sopenharmony_ci{
1451bf215546Sopenharmony_ci   const struct wsi_device *wsi = chain->wsi;
1452bf215546Sopenharmony_ci   VkResult result;
1453bf215546Sopenharmony_ci
1454bf215546Sopenharmony_ci   int cmd_buffer_count =
1455bf215546Sopenharmony_ci      chain->buffer_blit_queue != VK_NULL_HANDLE ? 1 : wsi->queue_family_count;
1456bf215546Sopenharmony_ci   image->buffer.blit_cmd_buffers =
1457bf215546Sopenharmony_ci      vk_zalloc(&chain->alloc,
1458bf215546Sopenharmony_ci                sizeof(VkCommandBuffer) * cmd_buffer_count, 8,
1459bf215546Sopenharmony_ci                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1460bf215546Sopenharmony_ci   if (!image->buffer.blit_cmd_buffers)
1461bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
1462bf215546Sopenharmony_ci
1463bf215546Sopenharmony_ci   for (uint32_t i = 0; i < cmd_buffer_count; i++) {
1464bf215546Sopenharmony_ci      const VkCommandBufferAllocateInfo cmd_buffer_info = {
1465bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
1466bf215546Sopenharmony_ci         .pNext = NULL,
1467bf215546Sopenharmony_ci         .commandPool = chain->cmd_pools[i],
1468bf215546Sopenharmony_ci         .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
1469bf215546Sopenharmony_ci         .commandBufferCount = 1,
1470bf215546Sopenharmony_ci      };
1471bf215546Sopenharmony_ci      result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
1472bf215546Sopenharmony_ci                                           &image->buffer.blit_cmd_buffers[i]);
1473bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1474bf215546Sopenharmony_ci         return result;
1475bf215546Sopenharmony_ci
1476bf215546Sopenharmony_ci      const VkCommandBufferBeginInfo begin_info = {
1477bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
1478bf215546Sopenharmony_ci      };
1479bf215546Sopenharmony_ci      wsi->BeginCommandBuffer(image->buffer.blit_cmd_buffers[i], &begin_info);
1480bf215546Sopenharmony_ci
1481bf215546Sopenharmony_ci      VkImageMemoryBarrier img_mem_barrier = {
1482bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
1483bf215546Sopenharmony_ci         .pNext = NULL,
1484bf215546Sopenharmony_ci         .srcAccessMask = 0,
1485bf215546Sopenharmony_ci         .dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT,
1486bf215546Sopenharmony_ci         .oldLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
1487bf215546Sopenharmony_ci         .newLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1488bf215546Sopenharmony_ci         .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1489bf215546Sopenharmony_ci         .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
1490bf215546Sopenharmony_ci         .image = image->image,
1491bf215546Sopenharmony_ci         .subresourceRange = {
1492bf215546Sopenharmony_ci            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1493bf215546Sopenharmony_ci            .baseMipLevel = 0,
1494bf215546Sopenharmony_ci            .levelCount = 1,
1495bf215546Sopenharmony_ci            .baseArrayLayer = 0,
1496bf215546Sopenharmony_ci            .layerCount = 1,
1497bf215546Sopenharmony_ci         },
1498bf215546Sopenharmony_ci      };
1499bf215546Sopenharmony_ci      wsi->CmdPipelineBarrier(image->buffer.blit_cmd_buffers[i],
1500bf215546Sopenharmony_ci                              VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
1501bf215546Sopenharmony_ci                              VK_PIPELINE_STAGE_TRANSFER_BIT,
1502bf215546Sopenharmony_ci                              0,
1503bf215546Sopenharmony_ci                              0, NULL,
1504bf215546Sopenharmony_ci                              0, NULL,
1505bf215546Sopenharmony_ci                              1, &img_mem_barrier);
1506bf215546Sopenharmony_ci
1507bf215546Sopenharmony_ci      struct VkBufferImageCopy buffer_image_copy = {
1508bf215546Sopenharmony_ci         .bufferOffset = 0,
1509bf215546Sopenharmony_ci         .bufferRowLength = info->linear_stride /
1510bf215546Sopenharmony_ci                            vk_format_get_blocksize(info->create.format),
1511bf215546Sopenharmony_ci         .bufferImageHeight = 0,
1512bf215546Sopenharmony_ci         .imageSubresource = {
1513bf215546Sopenharmony_ci            .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1514bf215546Sopenharmony_ci            .mipLevel = 0,
1515bf215546Sopenharmony_ci            .baseArrayLayer = 0,
1516bf215546Sopenharmony_ci            .layerCount = 1,
1517bf215546Sopenharmony_ci         },
1518bf215546Sopenharmony_ci         .imageOffset = { .x = 0, .y = 0, .z = 0 },
1519bf215546Sopenharmony_ci         .imageExtent = info->create.extent,
1520bf215546Sopenharmony_ci      };
1521bf215546Sopenharmony_ci      wsi->CmdCopyImageToBuffer(image->buffer.blit_cmd_buffers[i],
1522bf215546Sopenharmony_ci                                image->image,
1523bf215546Sopenharmony_ci                                VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1524bf215546Sopenharmony_ci                                image->buffer.buffer,
1525bf215546Sopenharmony_ci                                1, &buffer_image_copy);
1526bf215546Sopenharmony_ci
1527bf215546Sopenharmony_ci      img_mem_barrier.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
1528bf215546Sopenharmony_ci      img_mem_barrier.dstAccessMask = 0;
1529bf215546Sopenharmony_ci      img_mem_barrier.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
1530bf215546Sopenharmony_ci      img_mem_barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
1531bf215546Sopenharmony_ci      wsi->CmdPipelineBarrier(image->buffer.blit_cmd_buffers[i],
1532bf215546Sopenharmony_ci                              VK_PIPELINE_STAGE_TRANSFER_BIT,
1533bf215546Sopenharmony_ci                              VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
1534bf215546Sopenharmony_ci                              0,
1535bf215546Sopenharmony_ci                              0, NULL,
1536bf215546Sopenharmony_ci                              0, NULL,
1537bf215546Sopenharmony_ci                              1, &img_mem_barrier);
1538bf215546Sopenharmony_ci
1539bf215546Sopenharmony_ci      result = wsi->EndCommandBuffer(image->buffer.blit_cmd_buffers[i]);
1540bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1541bf215546Sopenharmony_ci         return result;
1542bf215546Sopenharmony_ci   }
1543bf215546Sopenharmony_ci
1544bf215546Sopenharmony_ci   return VK_SUCCESS;
1545bf215546Sopenharmony_ci}
1546bf215546Sopenharmony_ci
1547bf215546Sopenharmony_ciVkResult
1548bf215546Sopenharmony_ciwsi_configure_buffer_image(UNUSED const struct wsi_swapchain *chain,
1549bf215546Sopenharmony_ci                           const VkSwapchainCreateInfoKHR *pCreateInfo,
1550bf215546Sopenharmony_ci                           uint32_t stride_align, uint32_t size_align,
1551bf215546Sopenharmony_ci                           struct wsi_image_info *info)
1552bf215546Sopenharmony_ci{
1553bf215546Sopenharmony_ci   const struct wsi_device *wsi = chain->wsi;
1554bf215546Sopenharmony_ci
1555bf215546Sopenharmony_ci   assert(util_is_power_of_two_nonzero(stride_align));
1556bf215546Sopenharmony_ci   assert(util_is_power_of_two_nonzero(size_align));
1557bf215546Sopenharmony_ci
1558bf215546Sopenharmony_ci   VkResult result = wsi_configure_image(chain, pCreateInfo,
1559bf215546Sopenharmony_ci                                         0 /* handle_types */, info);
1560bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1561bf215546Sopenharmony_ci      return result;
1562bf215546Sopenharmony_ci
1563bf215546Sopenharmony_ci   info->create.usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1564bf215546Sopenharmony_ci   info->wsi.buffer_blit_src = true;
1565bf215546Sopenharmony_ci
1566bf215546Sopenharmony_ci   const uint32_t cpp = vk_format_get_blocksize(pCreateInfo->imageFormat);
1567bf215546Sopenharmony_ci   info->linear_stride = pCreateInfo->imageExtent.width * cpp;
1568bf215546Sopenharmony_ci   info->linear_stride = ALIGN_POT(info->linear_stride, stride_align);
1569bf215546Sopenharmony_ci
1570bf215546Sopenharmony_ci   /* Since we can pick the stride to be whatever we want, also align to the
1571bf215546Sopenharmony_ci    * device's optimalBufferCopyRowPitchAlignment so we get efficient copies.
1572bf215546Sopenharmony_ci    */
1573bf215546Sopenharmony_ci   assert(wsi->optimalBufferCopyRowPitchAlignment > 0);
1574bf215546Sopenharmony_ci   info->linear_stride = ALIGN_POT(info->linear_stride,
1575bf215546Sopenharmony_ci                                   wsi->optimalBufferCopyRowPitchAlignment);
1576bf215546Sopenharmony_ci
1577bf215546Sopenharmony_ci   info->linear_size = info->linear_stride * pCreateInfo->imageExtent.height;
1578bf215546Sopenharmony_ci   info->linear_size = ALIGN_POT(info->linear_size, size_align);
1579bf215546Sopenharmony_ci
1580bf215546Sopenharmony_ci   info->finish_create = wsi_finish_create_buffer_image;
1581bf215546Sopenharmony_ci
1582bf215546Sopenharmony_ci   return VK_SUCCESS;
1583bf215546Sopenharmony_ci}
1584bf215546Sopenharmony_ci
1585bf215546Sopenharmony_cistatic VkResult
1586bf215546Sopenharmony_ciwsi_create_cpu_linear_image_mem(const struct wsi_swapchain *chain,
1587bf215546Sopenharmony_ci                                const struct wsi_image_info *info,
1588bf215546Sopenharmony_ci                                struct wsi_image *image)
1589bf215546Sopenharmony_ci{
1590bf215546Sopenharmony_ci   const struct wsi_device *wsi = chain->wsi;
1591bf215546Sopenharmony_ci   VkResult result;
1592bf215546Sopenharmony_ci
1593bf215546Sopenharmony_ci   VkMemoryRequirements reqs;
1594bf215546Sopenharmony_ci   wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
1595bf215546Sopenharmony_ci
1596bf215546Sopenharmony_ci   VkSubresourceLayout layout;
1597bf215546Sopenharmony_ci   wsi->GetImageSubresourceLayout(chain->device, image->image,
1598bf215546Sopenharmony_ci                                  &(VkImageSubresource) {
1599bf215546Sopenharmony_ci                                     .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
1600bf215546Sopenharmony_ci                                     .mipLevel = 0,
1601bf215546Sopenharmony_ci                                     .arrayLayer = 0,
1602bf215546Sopenharmony_ci                                  }, &layout);
1603bf215546Sopenharmony_ci   assert(layout.offset == 0);
1604bf215546Sopenharmony_ci
1605bf215546Sopenharmony_ci   const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
1606bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
1607bf215546Sopenharmony_ci      .image = image->image,
1608bf215546Sopenharmony_ci      .buffer = VK_NULL_HANDLE,
1609bf215546Sopenharmony_ci   };
1610bf215546Sopenharmony_ci   VkMemoryAllocateInfo memory_info = {
1611bf215546Sopenharmony_ci      .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
1612bf215546Sopenharmony_ci      .pNext = &memory_dedicated_info,
1613bf215546Sopenharmony_ci      .allocationSize = reqs.size,
1614bf215546Sopenharmony_ci      .memoryTypeIndex =
1615bf215546Sopenharmony_ci         wsi_select_host_memory_type(wsi, reqs.memoryTypeBits),
1616bf215546Sopenharmony_ci   };
1617bf215546Sopenharmony_ci
1618bf215546Sopenharmony_ci   void *sw_host_ptr = NULL;
1619bf215546Sopenharmony_ci   if (info->alloc_shm)
1620bf215546Sopenharmony_ci      sw_host_ptr = info->alloc_shm(image, layout.size);
1621bf215546Sopenharmony_ci
1622bf215546Sopenharmony_ci   VkImportMemoryHostPointerInfoEXT host_ptr_info;
1623bf215546Sopenharmony_ci   if (sw_host_ptr != NULL) {
1624bf215546Sopenharmony_ci      host_ptr_info = (VkImportMemoryHostPointerInfoEXT) {
1625bf215546Sopenharmony_ci         .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_HOST_POINTER_INFO_EXT,
1626bf215546Sopenharmony_ci         .pHostPointer = sw_host_ptr,
1627bf215546Sopenharmony_ci         .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT,
1628bf215546Sopenharmony_ci      };
1629bf215546Sopenharmony_ci      __vk_append_struct(&memory_info, &host_ptr_info);
1630bf215546Sopenharmony_ci   }
1631bf215546Sopenharmony_ci
1632bf215546Sopenharmony_ci   result = wsi->AllocateMemory(chain->device, &memory_info,
1633bf215546Sopenharmony_ci                                &chain->alloc, &image->memory);
1634bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1635bf215546Sopenharmony_ci      return result;
1636bf215546Sopenharmony_ci
1637bf215546Sopenharmony_ci   result = wsi->MapMemory(chain->device, image->memory,
1638bf215546Sopenharmony_ci                           0, VK_WHOLE_SIZE, 0, &image->cpu_map);
1639bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1640bf215546Sopenharmony_ci      return result;
1641bf215546Sopenharmony_ci
1642bf215546Sopenharmony_ci   image->num_planes = 1;
1643bf215546Sopenharmony_ci   image->sizes[0] = reqs.size;
1644bf215546Sopenharmony_ci   image->row_pitches[0] = layout.rowPitch;
1645bf215546Sopenharmony_ci   image->offsets[0] = 0;
1646bf215546Sopenharmony_ci
1647bf215546Sopenharmony_ci   return VK_SUCCESS;
1648bf215546Sopenharmony_ci}
1649bf215546Sopenharmony_ci
1650bf215546Sopenharmony_cistatic VkResult
1651bf215546Sopenharmony_ciwsi_create_cpu_buffer_image_mem(const struct wsi_swapchain *chain,
1652bf215546Sopenharmony_ci                                const struct wsi_image_info *info,
1653bf215546Sopenharmony_ci                                struct wsi_image *image)
1654bf215546Sopenharmony_ci{
1655bf215546Sopenharmony_ci   VkResult result;
1656bf215546Sopenharmony_ci
1657bf215546Sopenharmony_ci   result = wsi_create_buffer_image_mem(chain, info, image, 0,
1658bf215546Sopenharmony_ci                                        false /* implicit_sync */);
1659bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1660bf215546Sopenharmony_ci      return result;
1661bf215546Sopenharmony_ci
1662bf215546Sopenharmony_ci   result = chain->wsi->MapMemory(chain->device, image->buffer.memory,
1663bf215546Sopenharmony_ci                                  0, VK_WHOLE_SIZE, 0, &image->cpu_map);
1664bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1665bf215546Sopenharmony_ci      return result;
1666bf215546Sopenharmony_ci
1667bf215546Sopenharmony_ci   return VK_SUCCESS;
1668bf215546Sopenharmony_ci}
1669bf215546Sopenharmony_ci
1670bf215546Sopenharmony_ciVkResult
1671bf215546Sopenharmony_ciwsi_configure_cpu_image(const struct wsi_swapchain *chain,
1672bf215546Sopenharmony_ci                        const VkSwapchainCreateInfoKHR *pCreateInfo,
1673bf215546Sopenharmony_ci                        uint8_t *(alloc_shm)(struct wsi_image *image,
1674bf215546Sopenharmony_ci                                             unsigned size),
1675bf215546Sopenharmony_ci                        struct wsi_image_info *info)
1676bf215546Sopenharmony_ci{
1677bf215546Sopenharmony_ci   const VkExternalMemoryHandleTypeFlags handle_types =
1678bf215546Sopenharmony_ci      alloc_shm ? VK_EXTERNAL_MEMORY_HANDLE_TYPE_HOST_ALLOCATION_BIT_EXT : 0;
1679bf215546Sopenharmony_ci
1680bf215546Sopenharmony_ci   if (chain->use_buffer_blit) {
1681bf215546Sopenharmony_ci      VkResult result = wsi_configure_buffer_image(chain, pCreateInfo,
1682bf215546Sopenharmony_ci                                                   1 /* stride_align */,
1683bf215546Sopenharmony_ci                                                   1 /* size_align */,
1684bf215546Sopenharmony_ci                                                   info);
1685bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1686bf215546Sopenharmony_ci         return result;
1687bf215546Sopenharmony_ci
1688bf215546Sopenharmony_ci      info->select_buffer_memory_type = wsi_select_host_memory_type;
1689bf215546Sopenharmony_ci      info->select_image_memory_type = wsi_select_device_memory_type;
1690bf215546Sopenharmony_ci      info->create_mem = wsi_create_cpu_buffer_image_mem;
1691bf215546Sopenharmony_ci   } else {
1692bf215546Sopenharmony_ci      VkResult result = wsi_configure_image(chain, pCreateInfo,
1693bf215546Sopenharmony_ci                                            handle_types, info);
1694bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1695bf215546Sopenharmony_ci         return result;
1696bf215546Sopenharmony_ci
1697bf215546Sopenharmony_ci      /* Force the image to be linear */
1698bf215546Sopenharmony_ci      info->create.tiling = VK_IMAGE_TILING_LINEAR;
1699bf215546Sopenharmony_ci
1700bf215546Sopenharmony_ci      info->create_mem = wsi_create_cpu_linear_image_mem;
1701bf215546Sopenharmony_ci   }
1702bf215546Sopenharmony_ci
1703bf215546Sopenharmony_ci   info->alloc_shm = alloc_shm;
1704bf215546Sopenharmony_ci
1705bf215546Sopenharmony_ci   return VK_SUCCESS;
1706bf215546Sopenharmony_ci}
1707