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