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
43 struct dma_buf_export_sync_file_wsi {
44 __u32 flags;
45 __s32 fd;
46 };
47
48 struct 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
56 static VkResult
wsi_dma_buf_export_sync_file(int dma_buf_fd,int * sync_file_fd)57 wsi_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
83 static VkResult
wsi_dma_buf_import_sync_file(int dma_buf_fd,int sync_file_fd)84 wsi_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
108 static VkResult
prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain * chain,const struct wsi_image * image)109 prepare_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
146 VkResult
wsi_prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain * chain,const struct wsi_image * image)147 wsi_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
164 VkResult
wsi_signal_dma_buf_from_semaphore(const struct wsi_swapchain * chain,const struct wsi_image * image)165 wsi_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
186 static const struct vk_sync_type *
get_sync_file_sync_type(struct vk_device * device,enum vk_sync_features req_features)187 get_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
202 VkResult
wsi_create_sync_for_dma_buf_wait(const struct wsi_swapchain * chain,const struct wsi_image * image,enum vk_sync_features req_features,struct vk_sync ** sync_out)203 wsi_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
235 fail_destroy_sync:
236 vk_sync_destroy(device, sync);
237 fail_close_sync_file:
238 close(sync_file_fd);
239
240 return result;
241 }
242
243 bool
wsi_common_drm_devices_equal(int fd_a,int fd_b)244 wsi_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
267 bool
wsi_device_matches_drm_fd(const struct wsi_device * wsi,int drm_fd)268 wsi_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
296 static uint32_t
prime_select_buffer_memory_type(const struct wsi_device * wsi,uint32_t type_bits)297 prime_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
305 static const struct VkDrmFormatModifierPropertiesEXT *
get_modifier_props(const struct wsi_image_info * info,uint64_t modifier)306 get_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
315 static VkResult
316 wsi_create_native_image_mem(const struct wsi_swapchain *chain,
317 const struct wsi_image_info *info,
318 struct wsi_image *image);
319
320 VkResult
wsi_configure_native_image(const struct wsi_swapchain * chain,const VkSwapchainCreateInfoKHR * pCreateInfo,uint32_t num_modifier_lists,const uint32_t * num_modifiers,const uint64_t * const * modifiers,struct wsi_image_info * info)321 wsi_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
456 fail_oom:
457 wsi_destroy_image_info(chain, info);
458 return VK_ERROR_OUT_OF_HOST_MEMORY;
459 }
460
461 static VkResult
wsi_create_native_image_mem(const struct wsi_swapchain * chain,const struct wsi_image_info * info,struct wsi_image * image)462 wsi_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
564 static VkResult
wsi_create_prime_image_mem(const struct wsi_swapchain * chain,const struct wsi_image_info * info,struct wsi_image * image)565 wsi_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
594 VkResult
wsi_configure_prime_image(UNUSED const struct wsi_swapchain * chain,const VkSwapchainCreateInfoKHR * pCreateInfo,bool use_modifier,struct wsi_image_info * info)595 wsi_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