1/* 2 * Copyright © 2017 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 */ 23 24#include "wsi_common_private.h" 25#include "wsi_common_drm.h" 26#include "util/macros.h" 27#include "util/os_file.h" 28#include "util/xmlconfig.h" 29#include "vk_device.h" 30#include "vk_physical_device.h" 31#include "vk_util.h" 32#include "drm-uapi/drm_fourcc.h" 33 34#include <errno.h> 35#include <linux/dma-buf.h> 36#include <linux/sync_file.h> 37#include <time.h> 38#include <unistd.h> 39#include <stdlib.h> 40#include <stdio.h> 41#include <xf86drm.h> 42 43struct dma_buf_export_sync_file_wsi { 44 __u32 flags; 45 __s32 fd; 46}; 47 48struct dma_buf_import_sync_file_wsi { 49 __u32 flags; 50 __s32 fd; 51}; 52 53#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE_WSI _IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file_wsi) 54#define DMA_BUF_IOCTL_IMPORT_SYNC_FILE_WSI _IOW(DMA_BUF_BASE, 3, struct dma_buf_import_sync_file_wsi) 55 56static VkResult 57wsi_dma_buf_export_sync_file(int dma_buf_fd, int *sync_file_fd) 58{ 59 /* Don't keep trying an IOCTL that doesn't exist. */ 60 static bool no_dma_buf_sync_file = false; 61 if (no_dma_buf_sync_file) 62 return VK_ERROR_FEATURE_NOT_PRESENT; 63 64 struct dma_buf_export_sync_file_wsi export = { 65 .flags = DMA_BUF_SYNC_RW, 66 .fd = -1, 67 }; 68 int ret = drmIoctl(dma_buf_fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE_WSI, &export); 69 if (ret) { 70 if (errno == ENOTTY || errno == EBADF || errno == ENOSYS) { 71 no_dma_buf_sync_file = true; 72 return VK_ERROR_FEATURE_NOT_PRESENT; 73 } else { 74 return VK_ERROR_OUT_OF_HOST_MEMORY; 75 } 76 } 77 78 *sync_file_fd = export.fd; 79 80 return VK_SUCCESS; 81} 82 83static VkResult 84wsi_dma_buf_import_sync_file(int dma_buf_fd, int sync_file_fd) 85{ 86 /* Don't keep trying an IOCTL that doesn't exist. */ 87 static bool no_dma_buf_sync_file = false; 88 if (no_dma_buf_sync_file) 89 return VK_ERROR_FEATURE_NOT_PRESENT; 90 91 struct dma_buf_import_sync_file_wsi import = { 92 .flags = DMA_BUF_SYNC_RW, 93 .fd = sync_file_fd, 94 }; 95 int ret = drmIoctl(dma_buf_fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE_WSI, &import); 96 if (ret) { 97 if (errno == ENOTTY || errno == EBADF || errno == ENOSYS) { 98 no_dma_buf_sync_file = true; 99 return VK_ERROR_FEATURE_NOT_PRESENT; 100 } else { 101 return VK_ERROR_OUT_OF_HOST_MEMORY; 102 } 103 } 104 105 return VK_SUCCESS; 106} 107 108static VkResult 109prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain *chain, 110 const struct wsi_image *image) 111{ 112 VkResult result; 113 114 if (!(chain->wsi->semaphore_export_handle_types & 115 VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT)) 116 return VK_ERROR_FEATURE_NOT_PRESENT; 117 118 int sync_file_fd = -1; 119 result = wsi_dma_buf_export_sync_file(image->dma_buf_fd, &sync_file_fd); 120 if (result != VK_SUCCESS) 121 return result; 122 123 result = wsi_dma_buf_import_sync_file(image->dma_buf_fd, sync_file_fd); 124 close(sync_file_fd); 125 if (result != VK_SUCCESS) 126 return result; 127 128 /* If we got here, all our checks pass. Create the actual semaphore */ 129 const VkExportSemaphoreCreateInfo export_info = { 130 .sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO, 131 .handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, 132 }; 133 const VkSemaphoreCreateInfo semaphore_info = { 134 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, 135 .pNext = &export_info, 136 }; 137 result = chain->wsi->CreateSemaphore(chain->device, &semaphore_info, 138 &chain->alloc, 139 &chain->dma_buf_semaphore); 140 if (result != VK_SUCCESS) 141 return result; 142 143 return VK_SUCCESS; 144} 145 146VkResult 147wsi_prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain *chain, 148 const struct wsi_image *image) 149{ 150 VkResult result; 151 152 /* We cache result - 1 in the swapchain */ 153 if (unlikely(chain->signal_dma_buf_from_semaphore == 0)) { 154 result = prepare_signal_dma_buf_from_semaphore(chain, image); 155 assert(result <= 0); 156 chain->signal_dma_buf_from_semaphore = (int)result - 1; 157 } else { 158 result = (VkResult)(chain->signal_dma_buf_from_semaphore + 1); 159 } 160 161 return result; 162} 163 164VkResult 165wsi_signal_dma_buf_from_semaphore(const struct wsi_swapchain *chain, 166 const struct wsi_image *image) 167{ 168 VkResult result; 169 170 const VkSemaphoreGetFdInfoKHR get_fd_info = { 171 .sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR, 172 .semaphore = chain->dma_buf_semaphore, 173 .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, 174 }; 175 int sync_file_fd = -1; 176 result = chain->wsi->GetSemaphoreFdKHR(chain->device, &get_fd_info, 177 &sync_file_fd); 178 if (result != VK_SUCCESS) 179 return result; 180 181 result = wsi_dma_buf_import_sync_file(image->dma_buf_fd, sync_file_fd); 182 close(sync_file_fd); 183 return result; 184} 185 186static const struct vk_sync_type * 187get_sync_file_sync_type(struct vk_device *device, 188 enum vk_sync_features req_features) 189{ 190 for (const struct vk_sync_type *const *t = 191 device->physical->supported_sync_types; *t; t++) { 192 if (req_features & ~(*t)->features) 193 continue; 194 195 if ((*t)->import_sync_file != NULL) 196 return *t; 197 } 198 199 return NULL; 200} 201 202VkResult 203wsi_create_sync_for_dma_buf_wait(const struct wsi_swapchain *chain, 204 const struct wsi_image *image, 205 enum vk_sync_features req_features, 206 struct vk_sync **sync_out) 207{ 208 VK_FROM_HANDLE(vk_device, device, chain->device); 209 VkResult result; 210 211 const struct vk_sync_type *sync_type = 212 get_sync_file_sync_type(device, req_features); 213 if (sync_type == NULL) 214 return VK_ERROR_FEATURE_NOT_PRESENT; 215 216 int sync_file_fd = -1; 217 result = wsi_dma_buf_export_sync_file(image->dma_buf_fd, &sync_file_fd); 218 if (result != VK_SUCCESS) 219 return result; 220 221 struct vk_sync *sync = NULL; 222 result = vk_sync_create(device, sync_type, VK_SYNC_IS_SHAREABLE, 0, &sync); 223 if (result != VK_SUCCESS) 224 goto fail_close_sync_file; 225 226 result = vk_sync_import_sync_file(device, sync, sync_file_fd); 227 if (result != VK_SUCCESS) 228 goto fail_destroy_sync; 229 230 close(sync_file_fd); 231 *sync_out = sync; 232 233 return VK_SUCCESS; 234 235fail_destroy_sync: 236 vk_sync_destroy(device, sync); 237fail_close_sync_file: 238 close(sync_file_fd); 239 240 return result; 241} 242 243bool 244wsi_common_drm_devices_equal(int fd_a, int fd_b) 245{ 246 drmDevicePtr device_a, device_b; 247 int ret; 248 249 ret = drmGetDevice2(fd_a, 0, &device_a); 250 if (ret) 251 return false; 252 253 ret = drmGetDevice2(fd_b, 0, &device_b); 254 if (ret) { 255 drmFreeDevice(&device_a); 256 return false; 257 } 258 259 bool result = drmDevicesEqual(device_a, device_b); 260 261 drmFreeDevice(&device_a); 262 drmFreeDevice(&device_b); 263 264 return result; 265} 266 267bool 268wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd) 269{ 270 if (wsi->can_present_on_device) 271 return wsi->can_present_on_device(wsi->pdevice, drm_fd); 272 273 drmDevicePtr fd_device; 274 int ret = drmGetDevice2(drm_fd, 0, &fd_device); 275 if (ret) 276 return false; 277 278 bool match = false; 279 switch (fd_device->bustype) { 280 case DRM_BUS_PCI: 281 match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain && 282 wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus && 283 wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev && 284 wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func; 285 break; 286 287 default: 288 break; 289 } 290 291 drmFreeDevice(&fd_device); 292 293 return match; 294} 295 296static uint32_t 297prime_select_buffer_memory_type(const struct wsi_device *wsi, 298 uint32_t type_bits) 299{ 300 return wsi_select_memory_type(wsi, 0 /* req_props */, 301 VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, 302 type_bits); 303} 304 305static const struct VkDrmFormatModifierPropertiesEXT * 306get_modifier_props(const struct wsi_image_info *info, uint64_t modifier) 307{ 308 for (uint32_t i = 0; i < info->modifier_prop_count; i++) { 309 if (info->modifier_props[i].drmFormatModifier == modifier) 310 return &info->modifier_props[i]; 311 } 312 return NULL; 313} 314 315static VkResult 316wsi_create_native_image_mem(const struct wsi_swapchain *chain, 317 const struct wsi_image_info *info, 318 struct wsi_image *image); 319 320VkResult 321wsi_configure_native_image(const struct wsi_swapchain *chain, 322 const VkSwapchainCreateInfoKHR *pCreateInfo, 323 uint32_t num_modifier_lists, 324 const uint32_t *num_modifiers, 325 const uint64_t *const *modifiers, 326 struct wsi_image_info *info) 327{ 328 const struct wsi_device *wsi = chain->wsi; 329 330 VkExternalMemoryHandleTypeFlags handle_type = 331 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; 332 333 VkResult result = wsi_configure_image(chain, pCreateInfo, handle_type, info); 334 if (result != VK_SUCCESS) 335 return result; 336 337 if (num_modifier_lists == 0) { 338 /* If we don't have modifiers, fall back to the legacy "scanout" flag */ 339 info->wsi.scanout = true; 340 } else { 341 /* The winsys can't request modifiers if we don't support them. */ 342 assert(wsi->supports_modifiers); 343 struct VkDrmFormatModifierPropertiesListEXT modifier_props_list = { 344 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT, 345 }; 346 VkFormatProperties2 format_props = { 347 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2, 348 .pNext = &modifier_props_list, 349 }; 350 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, 351 pCreateInfo->imageFormat, 352 &format_props); 353 assert(modifier_props_list.drmFormatModifierCount > 0); 354 info->modifier_props = 355 vk_alloc(&chain->alloc, 356 sizeof(*info->modifier_props) * 357 modifier_props_list.drmFormatModifierCount, 358 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 359 if (info->modifier_props == NULL) 360 goto fail_oom; 361 362 modifier_props_list.pDrmFormatModifierProperties = info->modifier_props; 363 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice, 364 pCreateInfo->imageFormat, 365 &format_props); 366 367 /* Call GetImageFormatProperties with every modifier and filter the list 368 * down to those that we know work. 369 */ 370 info->modifier_prop_count = 0; 371 for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) { 372 VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = { 373 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT, 374 .drmFormatModifier = info->modifier_props[i].drmFormatModifier, 375 .sharingMode = pCreateInfo->imageSharingMode, 376 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount, 377 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices, 378 }; 379 VkPhysicalDeviceImageFormatInfo2 format_info = { 380 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2, 381 .format = pCreateInfo->imageFormat, 382 .type = VK_IMAGE_TYPE_2D, 383 .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT, 384 .usage = pCreateInfo->imageUsage, 385 .flags = info->create.flags, 386 }; 387 388 VkImageFormatListCreateInfo format_list; 389 if (info->create.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { 390 format_list = info->format_list; 391 format_list.pNext = NULL; 392 __vk_append_struct(&format_info, &format_list); 393 } 394 395 VkImageFormatProperties2 format_props = { 396 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2, 397 .pNext = NULL, 398 }; 399 __vk_append_struct(&format_info, &mod_info); 400 result = wsi->GetPhysicalDeviceImageFormatProperties2(wsi->pdevice, 401 &format_info, 402 &format_props); 403 if (result == VK_SUCCESS && 404 pCreateInfo->imageExtent.width <= format_props.imageFormatProperties.maxExtent.width && 405 pCreateInfo->imageExtent.height <= format_props.imageFormatProperties.maxExtent.height) 406 info->modifier_props[info->modifier_prop_count++] = info->modifier_props[i]; 407 } 408 409 uint32_t max_modifier_count = 0; 410 for (uint32_t l = 0; l < num_modifier_lists; l++) 411 max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]); 412 413 uint64_t *image_modifiers = 414 vk_alloc(&chain->alloc, sizeof(*image_modifiers) * max_modifier_count, 415 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 416 if (!image_modifiers) 417 goto fail_oom; 418 419 uint32_t image_modifier_count = 0; 420 for (uint32_t l = 0; l < num_modifier_lists; l++) { 421 /* Walk the modifier lists and construct a list of supported 422 * modifiers. 423 */ 424 for (uint32_t i = 0; i < num_modifiers[l]; i++) { 425 if (get_modifier_props(info, modifiers[l][i])) 426 image_modifiers[image_modifier_count++] = modifiers[l][i]; 427 } 428 429 /* We only want to take the modifiers from the first list */ 430 if (image_modifier_count > 0) 431 break; 432 } 433 434 if (image_modifier_count > 0) { 435 info->create.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; 436 info->drm_mod_list = (VkImageDrmFormatModifierListCreateInfoEXT) { 437 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT, 438 .drmFormatModifierCount = image_modifier_count, 439 .pDrmFormatModifiers = image_modifiers, 440 }; 441 image_modifiers = NULL; 442 __vk_append_struct(&info->create, &info->drm_mod_list); 443 } else { 444 vk_free(&chain->alloc, image_modifiers); 445 /* TODO: Add a proper error here */ 446 assert(!"Failed to find a supported modifier! This should never " 447 "happen because LINEAR should always be available"); 448 goto fail_oom; 449 } 450 } 451 452 info->create_mem = wsi_create_native_image_mem; 453 454 return VK_SUCCESS; 455 456fail_oom: 457 wsi_destroy_image_info(chain, info); 458 return VK_ERROR_OUT_OF_HOST_MEMORY; 459} 460 461static VkResult 462wsi_create_native_image_mem(const struct wsi_swapchain *chain, 463 const struct wsi_image_info *info, 464 struct wsi_image *image) 465{ 466 const struct wsi_device *wsi = chain->wsi; 467 VkResult result; 468 469 VkMemoryRequirements reqs; 470 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs); 471 472 const struct wsi_memory_allocate_info memory_wsi_info = { 473 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA, 474 .pNext = NULL, 475 .implicit_sync = true, 476 }; 477 const VkExportMemoryAllocateInfo memory_export_info = { 478 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO, 479 .pNext = &memory_wsi_info, 480 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 481 }; 482 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = { 483 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO, 484 .pNext = &memory_export_info, 485 .image = image->image, 486 .buffer = VK_NULL_HANDLE, 487 }; 488 const VkMemoryAllocateInfo memory_info = { 489 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, 490 .pNext = &memory_dedicated_info, 491 .allocationSize = reqs.size, 492 .memoryTypeIndex = 493 wsi_select_device_memory_type(wsi, reqs.memoryTypeBits), 494 }; 495 result = wsi->AllocateMemory(chain->device, &memory_info, 496 &chain->alloc, &image->memory); 497 if (result != VK_SUCCESS) 498 return result; 499 500 const VkMemoryGetFdInfoKHR memory_get_fd_info = { 501 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 502 .pNext = NULL, 503 .memory = image->memory, 504 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 505 }; 506 507 result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, 508 &image->dma_buf_fd); 509 if (result != VK_SUCCESS) 510 return result; 511 512 if (info->drm_mod_list.drmFormatModifierCount > 0) { 513 VkImageDrmFormatModifierPropertiesEXT image_mod_props = { 514 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT, 515 }; 516 result = wsi->GetImageDrmFormatModifierPropertiesEXT(chain->device, 517 image->image, 518 &image_mod_props); 519 if (result != VK_SUCCESS) 520 return result; 521 522 image->drm_modifier = image_mod_props.drmFormatModifier; 523 assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID); 524 525 const struct VkDrmFormatModifierPropertiesEXT *mod_props = 526 get_modifier_props(info, image->drm_modifier); 527 image->num_planes = mod_props->drmFormatModifierPlaneCount; 528 529 for (uint32_t p = 0; p < image->num_planes; p++) { 530 const VkImageSubresource image_subresource = { 531 .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p, 532 .mipLevel = 0, 533 .arrayLayer = 0, 534 }; 535 VkSubresourceLayout image_layout; 536 wsi->GetImageSubresourceLayout(chain->device, image->image, 537 &image_subresource, &image_layout); 538 image->sizes[p] = image_layout.size; 539 image->row_pitches[p] = image_layout.rowPitch; 540 image->offsets[p] = image_layout.offset; 541 } 542 } else { 543 const VkImageSubresource image_subresource = { 544 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, 545 .mipLevel = 0, 546 .arrayLayer = 0, 547 }; 548 VkSubresourceLayout image_layout; 549 wsi->GetImageSubresourceLayout(chain->device, image->image, 550 &image_subresource, &image_layout); 551 552 image->drm_modifier = DRM_FORMAT_MOD_INVALID; 553 image->num_planes = 1; 554 image->sizes[0] = reqs.size; 555 image->row_pitches[0] = image_layout.rowPitch; 556 image->offsets[0] = 0; 557 } 558 559 return VK_SUCCESS; 560} 561 562#define WSI_PRIME_LINEAR_STRIDE_ALIGN 256 563 564static VkResult 565wsi_create_prime_image_mem(const struct wsi_swapchain *chain, 566 const struct wsi_image_info *info, 567 struct wsi_image *image) 568{ 569 const struct wsi_device *wsi = chain->wsi; 570 VkResult result = 571 wsi_create_buffer_image_mem(chain, info, image, 572 VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 573 true); 574 if (result != VK_SUCCESS) 575 return result; 576 577 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = { 578 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR, 579 .pNext = NULL, 580 .memory = image->buffer.memory, 581 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT, 582 }; 583 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, 584 &image->dma_buf_fd); 585 if (result != VK_SUCCESS) 586 return result; 587 588 image->drm_modifier = info->prime_use_linear_modifier ? 589 DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID; 590 591 return VK_SUCCESS; 592} 593 594VkResult 595wsi_configure_prime_image(UNUSED const struct wsi_swapchain *chain, 596 const VkSwapchainCreateInfoKHR *pCreateInfo, 597 bool use_modifier, 598 struct wsi_image_info *info) 599{ 600 VkResult result = 601 wsi_configure_buffer_image(chain, pCreateInfo, 602 WSI_PRIME_LINEAR_STRIDE_ALIGN, 4096, 603 info); 604 if (result != VK_SUCCESS) 605 return result; 606 607 info->prime_use_linear_modifier = use_modifier; 608 609 info->create_mem = wsi_create_prime_image_mem; 610 info->select_buffer_memory_type = prime_select_buffer_memory_type; 611 info->select_image_memory_type = wsi_select_device_memory_type; 612 613 return VK_SUCCESS; 614} 615