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 "util/macros.h"
26 #include "util/os_file.h"
27 #include "util/xmlconfig.h"
28 #include "vk_util.h"
29 #include "drm-uapi/drm_fourcc.h"
30
31 #include <time.h>
32 #include <unistd.h>
33 #include <stdlib.h>
34 #include <stdio.h>
35 #include <xf86drm.h>
36
37 bool
wsi_device_matches_drm_fd(const struct wsi_device * wsi,int drm_fd)38 wsi_device_matches_drm_fd(const struct wsi_device *wsi, int drm_fd)
39 {
40 drmDevicePtr fd_device;
41 int ret = drmGetDevice2(drm_fd, 0, &fd_device);
42 if (ret)
43 return false;
44
45 bool match = false;
46 switch (fd_device->bustype) {
47 case DRM_BUS_PCI:
48 match = wsi->pci_bus_info.pciDomain == fd_device->businfo.pci->domain &&
49 wsi->pci_bus_info.pciBus == fd_device->businfo.pci->bus &&
50 wsi->pci_bus_info.pciDevice == fd_device->businfo.pci->dev &&
51 wsi->pci_bus_info.pciFunction == fd_device->businfo.pci->func;
52 break;
53
54 default:
55 break;
56 }
57
58 drmFreeDevice(&fd_device);
59
60 return match;
61 }
62
63 static uint32_t
select_memory_type(const struct wsi_device * wsi,VkMemoryPropertyFlags props,uint32_t type_bits)64 select_memory_type(const struct wsi_device *wsi,
65 VkMemoryPropertyFlags props,
66 uint32_t type_bits)
67 {
68 for (uint32_t i = 0; i < wsi->memory_props.memoryTypeCount; i++) {
69 const VkMemoryType type = wsi->memory_props.memoryTypes[i];
70 if ((type_bits & (1 << i)) && (type.propertyFlags & props) == props)
71 return i;
72 }
73
74 unreachable("No memory type found");
75 }
76
77 static uint32_t
vk_format_size(VkFormat format)78 vk_format_size(VkFormat format)
79 {
80 switch (format) {
81 case VK_FORMAT_B8G8R8A8_UNORM:
82 case VK_FORMAT_B8G8R8A8_SRGB:
83 return 4;
84 default:
85 unreachable("Unknown WSI Format");
86 }
87 }
88
89 VkResult
wsi_create_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 * image)90 wsi_create_native_image(const struct wsi_swapchain *chain,
91 const VkSwapchainCreateInfoKHR *pCreateInfo,
92 uint32_t num_modifier_lists,
93 const uint32_t *num_modifiers,
94 const uint64_t *const *modifiers,
95 struct wsi_image *image)
96 {
97 const struct wsi_device *wsi = chain->wsi;
98 VkResult result;
99
100 memset(image, 0, sizeof(*image));
101 for (int i = 0; i < ARRAY_SIZE(image->fds); i++)
102 image->fds[i] = -1;
103
104 VkImageCreateInfo image_info = {
105 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
106 .flags = 0,
107 .imageType = VK_IMAGE_TYPE_2D,
108 .format = pCreateInfo->imageFormat,
109 .extent = {
110 .width = pCreateInfo->imageExtent.width,
111 .height = pCreateInfo->imageExtent.height,
112 .depth = 1,
113 },
114 .mipLevels = 1,
115 .arrayLayers = 1,
116 .samples = VK_SAMPLE_COUNT_1_BIT,
117 .tiling = VK_IMAGE_TILING_OPTIMAL,
118 .usage = pCreateInfo->imageUsage,
119 .sharingMode = pCreateInfo->imageSharingMode,
120 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
121 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
122 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
123 };
124
125 VkImageFormatListCreateInfoKHR image_format_list;
126 if (pCreateInfo->flags & VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR) {
127 image_info.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT |
128 VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
129
130 const VkImageFormatListCreateInfoKHR *format_list =
131 vk_find_struct_const(pCreateInfo->pNext,
132 IMAGE_FORMAT_LIST_CREATE_INFO_KHR);
133
134 #ifndef NDEBUG
135 assume(format_list && format_list->viewFormatCount > 0);
136 bool format_found = false;
137 for (int i = 0; i < format_list->viewFormatCount; i++)
138 if (pCreateInfo->imageFormat == format_list->pViewFormats[i])
139 format_found = true;
140 assert(format_found);
141 #endif
142
143 image_format_list = *format_list;
144 image_format_list.pNext = NULL;
145 __vk_append_struct(&image_info, &image_format_list);
146 }
147
148 struct wsi_image_create_info image_wsi_info;
149 VkImageDrmFormatModifierListCreateInfoEXT image_modifier_list;
150
151 uint32_t image_modifier_count = 0, modifier_prop_count = 0;
152 struct VkDrmFormatModifierPropertiesEXT *modifier_props = NULL;
153 uint64_t *image_modifiers = NULL;
154 if (num_modifier_lists == 0) {
155 /* If we don't have modifiers, fall back to the legacy "scanout" flag */
156 image_wsi_info = (struct wsi_image_create_info) {
157 .sType = VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
158 .scanout = true,
159 };
160 __vk_append_struct(&image_info, &image_wsi_info);
161 } else {
162 /* The winsys can't request modifiers if we don't support them. */
163 assert(wsi->supports_modifiers);
164 struct VkDrmFormatModifierPropertiesListEXT modifier_props_list = {
165 .sType = VK_STRUCTURE_TYPE_DRM_FORMAT_MODIFIER_PROPERTIES_LIST_EXT,
166 };
167 VkFormatProperties2 format_props = {
168 .sType = VK_STRUCTURE_TYPE_FORMAT_PROPERTIES_2,
169 .pNext = &modifier_props_list,
170 };
171 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
172 pCreateInfo->imageFormat,
173 &format_props);
174 assert(modifier_props_list.drmFormatModifierCount > 0);
175 modifier_props = vk_alloc(&chain->alloc,
176 sizeof(*modifier_props) *
177 modifier_props_list.drmFormatModifierCount,
178 8,
179 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
180 if (!modifier_props) {
181 result = VK_ERROR_OUT_OF_HOST_MEMORY;
182 goto fail;
183 }
184
185 modifier_props_list.pDrmFormatModifierProperties = modifier_props;
186 wsi->GetPhysicalDeviceFormatProperties2KHR(wsi->pdevice,
187 pCreateInfo->imageFormat,
188 &format_props);
189
190 /* Call GetImageFormatProperties with every modifier and filter the list
191 * down to those that we know work.
192 */
193 modifier_prop_count = 0;
194 for (uint32_t i = 0; i < modifier_props_list.drmFormatModifierCount; i++) {
195 VkPhysicalDeviceImageDrmFormatModifierInfoEXT mod_info = {
196 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_DRM_FORMAT_MODIFIER_INFO_EXT,
197 .drmFormatModifier = modifier_props[i].drmFormatModifier,
198 .sharingMode = pCreateInfo->imageSharingMode,
199 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
200 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
201 };
202 VkPhysicalDeviceImageFormatInfo2 format_info = {
203 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
204 .format = pCreateInfo->imageFormat,
205 .type = VK_IMAGE_TYPE_2D,
206 .tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
207 .usage = pCreateInfo->imageUsage,
208 .flags = image_info.flags,
209 };
210
211 VkImageFormatListCreateInfoKHR format_list;
212 if (image_info.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
213 format_list = image_format_list;
214 format_list.pNext = NULL;
215 __vk_append_struct(&format_info, &format_list);
216 }
217
218 VkImageFormatProperties2 format_props = {
219 .sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
220 .pNext = NULL,
221 };
222 __vk_append_struct(&format_info, &mod_info);
223 result = wsi->GetPhysicalDeviceImageFormatProperties2(wsi->pdevice,
224 &format_info,
225 &format_props);
226 if (result == VK_SUCCESS)
227 modifier_props[modifier_prop_count++] = modifier_props[i];
228 }
229
230 uint32_t max_modifier_count = 0;
231 for (uint32_t l = 0; l < num_modifier_lists; l++)
232 max_modifier_count = MAX2(max_modifier_count, num_modifiers[l]);
233
234 image_modifiers = vk_alloc(&chain->alloc,
235 sizeof(*image_modifiers) *
236 max_modifier_count,
237 8,
238 VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
239 if (!image_modifiers) {
240 result = VK_ERROR_OUT_OF_HOST_MEMORY;
241 goto fail;
242 }
243
244 image_modifier_count = 0;
245 for (uint32_t l = 0; l < num_modifier_lists; l++) {
246 /* Walk the modifier lists and construct a list of supported
247 * modifiers.
248 */
249 for (uint32_t i = 0; i < num_modifiers[l]; i++) {
250 for (uint32_t j = 0; j < modifier_prop_count; j++) {
251 if (modifier_props[j].drmFormatModifier == modifiers[l][i])
252 image_modifiers[image_modifier_count++] = modifiers[l][i];
253 }
254 }
255
256 /* We only want to take the modifiers from the first list */
257 if (image_modifier_count > 0)
258 break;
259 }
260
261 if (image_modifier_count > 0) {
262 image_modifier_list = (VkImageDrmFormatModifierListCreateInfoEXT) {
263 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
264 .drmFormatModifierCount = image_modifier_count,
265 .pDrmFormatModifiers = image_modifiers,
266 };
267 image_info.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
268 __vk_append_struct(&image_info, &image_modifier_list);
269 } else {
270 /* TODO: Add a proper error here */
271 assert(!"Failed to find a supported modifier! This should never "
272 "happen because LINEAR should always be available");
273 result = VK_ERROR_OUT_OF_HOST_MEMORY;
274 goto fail;
275 }
276 }
277
278 result = wsi->CreateImage(chain->device, &image_info,
279 &chain->alloc, &image->image);
280 if (result != VK_SUCCESS)
281 goto fail;
282
283 VkMemoryRequirements reqs;
284 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
285
286 const struct wsi_memory_allocate_info memory_wsi_info = {
287 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
288 .pNext = NULL,
289 .implicit_sync = true,
290 };
291 const VkExportMemoryAllocateInfo memory_export_info = {
292 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
293 .pNext = &memory_wsi_info,
294 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
295 };
296 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
297 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
298 .pNext = &memory_export_info,
299 .image = image->image,
300 .buffer = VK_NULL_HANDLE,
301 };
302 const VkMemoryAllocateInfo memory_info = {
303 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
304 .pNext = &memory_dedicated_info,
305 .allocationSize = reqs.size,
306 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
307 reqs.memoryTypeBits),
308 };
309 result = wsi->AllocateMemory(chain->device, &memory_info,
310 &chain->alloc, &image->memory);
311 if (result != VK_SUCCESS)
312 goto fail;
313
314 result = wsi->BindImageMemory(chain->device, image->image,
315 image->memory, 0);
316 if (result != VK_SUCCESS)
317 goto fail;
318
319 int fd = -1;
320 if (!wsi->sw) {
321 const VkMemoryGetFdInfoKHR memory_get_fd_info = {
322 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
323 .pNext = NULL,
324 .memory = image->memory,
325 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
326 };
327
328 result = wsi->GetMemoryFdKHR(chain->device, &memory_get_fd_info, &fd);
329 if (result != VK_SUCCESS)
330 goto fail;
331 }
332
333 if (!wsi->sw && num_modifier_lists > 0) {
334 VkImageDrmFormatModifierPropertiesEXT image_mod_props = {
335 .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_PROPERTIES_EXT,
336 };
337 result = wsi->GetImageDrmFormatModifierPropertiesEXT(chain->device,
338 image->image,
339 &image_mod_props);
340 if (result != VK_SUCCESS) {
341 close(fd);
342 goto fail;
343 }
344 image->drm_modifier = image_mod_props.drmFormatModifier;
345 assert(image->drm_modifier != DRM_FORMAT_MOD_INVALID);
346
347 for (uint32_t j = 0; j < modifier_prop_count; j++) {
348 if (modifier_props[j].drmFormatModifier == image->drm_modifier) {
349 image->num_planes = modifier_props[j].drmFormatModifierPlaneCount;
350 break;
351 }
352 }
353
354 for (uint32_t p = 0; p < image->num_planes; p++) {
355 const VkImageSubresource image_subresource = {
356 .aspectMask = VK_IMAGE_ASPECT_PLANE_0_BIT << p,
357 .mipLevel = 0,
358 .arrayLayer = 0,
359 };
360 VkSubresourceLayout image_layout;
361 wsi->GetImageSubresourceLayout(chain->device, image->image,
362 &image_subresource, &image_layout);
363 image->sizes[p] = image_layout.size;
364 image->row_pitches[p] = image_layout.rowPitch;
365 image->offsets[p] = image_layout.offset;
366 if (p == 0) {
367 image->fds[p] = fd;
368 } else {
369 image->fds[p] = os_dupfd_cloexec(fd);
370 if (image->fds[p] == -1) {
371 for (uint32_t i = 0; i < p; i++)
372 close(image->fds[i]);
373
374 result = VK_ERROR_OUT_OF_HOST_MEMORY;
375 goto fail;
376 }
377 }
378 }
379 } else {
380 const VkImageSubresource image_subresource = {
381 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
382 .mipLevel = 0,
383 .arrayLayer = 0,
384 };
385 VkSubresourceLayout image_layout;
386 wsi->GetImageSubresourceLayout(chain->device, image->image,
387 &image_subresource, &image_layout);
388
389 image->drm_modifier = DRM_FORMAT_MOD_INVALID;
390 image->num_planes = 1;
391 image->sizes[0] = reqs.size;
392 image->row_pitches[0] = image_layout.rowPitch;
393 image->offsets[0] = 0;
394 image->fds[0] = fd;
395 }
396
397 vk_free(&chain->alloc, modifier_props);
398 vk_free(&chain->alloc, image_modifiers);
399
400 return VK_SUCCESS;
401
402 fail:
403 vk_free(&chain->alloc, modifier_props);
404 vk_free(&chain->alloc, image_modifiers);
405 wsi_destroy_image(chain, image);
406
407 return result;
408 }
409
410 static inline uint32_t
align_u32(uint32_t v,uint32_t a)411 align_u32(uint32_t v, uint32_t a)
412 {
413 assert(a != 0 && a == (a & -a));
414 return (v + a - 1) & ~(a - 1);
415 }
416
417 #define WSI_PRIME_LINEAR_STRIDE_ALIGN 256
418
419 VkResult
wsi_create_prime_image(const struct wsi_swapchain * chain,const VkSwapchainCreateInfoKHR * pCreateInfo,bool use_modifier,struct wsi_image * image)420 wsi_create_prime_image(const struct wsi_swapchain *chain,
421 const VkSwapchainCreateInfoKHR *pCreateInfo,
422 bool use_modifier,
423 struct wsi_image *image)
424 {
425 const struct wsi_device *wsi = chain->wsi;
426 VkResult result;
427
428 memset(image, 0, sizeof(*image));
429
430 const uint32_t cpp = vk_format_size(pCreateInfo->imageFormat);
431 const uint32_t linear_stride = align_u32(pCreateInfo->imageExtent.width * cpp,
432 WSI_PRIME_LINEAR_STRIDE_ALIGN);
433
434 uint32_t linear_size = linear_stride * pCreateInfo->imageExtent.height;
435 linear_size = align_u32(linear_size, 4096);
436
437 const VkExternalMemoryBufferCreateInfo prime_buffer_external_info = {
438 .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_BUFFER_CREATE_INFO,
439 .pNext = NULL,
440 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
441 };
442 const VkBufferCreateInfo prime_buffer_info = {
443 .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
444 .pNext = &prime_buffer_external_info,
445 .size = linear_size,
446 .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT,
447 .sharingMode = VK_SHARING_MODE_EXCLUSIVE,
448 };
449 result = wsi->CreateBuffer(chain->device, &prime_buffer_info,
450 &chain->alloc, &image->prime.buffer);
451 if (result != VK_SUCCESS)
452 goto fail;
453
454 VkMemoryRequirements reqs;
455 wsi->GetBufferMemoryRequirements(chain->device, image->prime.buffer, &reqs);
456 assert(reqs.size <= linear_size);
457
458 const struct wsi_memory_allocate_info memory_wsi_info = {
459 .sType = VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
460 .pNext = NULL,
461 .implicit_sync = true,
462 };
463 const VkExportMemoryAllocateInfo prime_memory_export_info = {
464 .sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO,
465 .pNext = &memory_wsi_info,
466 .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
467 };
468 const VkMemoryDedicatedAllocateInfo prime_memory_dedicated_info = {
469 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
470 .pNext = &prime_memory_export_info,
471 .image = VK_NULL_HANDLE,
472 .buffer = image->prime.buffer,
473 };
474 const VkMemoryAllocateInfo prime_memory_info = {
475 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
476 .pNext = &prime_memory_dedicated_info,
477 .allocationSize = linear_size,
478 .memoryTypeIndex = select_memory_type(wsi, 0, reqs.memoryTypeBits),
479 };
480 result = wsi->AllocateMemory(chain->device, &prime_memory_info,
481 &chain->alloc, &image->prime.memory);
482 if (result != VK_SUCCESS)
483 goto fail;
484
485 result = wsi->BindBufferMemory(chain->device, image->prime.buffer,
486 image->prime.memory, 0);
487 if (result != VK_SUCCESS)
488 goto fail;
489
490 const VkImageCreateInfo image_info = {
491 .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
492 .pNext = NULL,
493 .flags = 0,
494 .imageType = VK_IMAGE_TYPE_2D,
495 .format = pCreateInfo->imageFormat,
496 .extent = {
497 .width = pCreateInfo->imageExtent.width,
498 .height = pCreateInfo->imageExtent.height,
499 .depth = 1,
500 },
501 .mipLevels = 1,
502 .arrayLayers = 1,
503 .samples = VK_SAMPLE_COUNT_1_BIT,
504 .tiling = VK_IMAGE_TILING_OPTIMAL,
505 .usage = pCreateInfo->imageUsage | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,
506 .sharingMode = pCreateInfo->imageSharingMode,
507 .queueFamilyIndexCount = pCreateInfo->queueFamilyIndexCount,
508 .pQueueFamilyIndices = pCreateInfo->pQueueFamilyIndices,
509 .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
510 };
511 result = wsi->CreateImage(chain->device, &image_info,
512 &chain->alloc, &image->image);
513 if (result != VK_SUCCESS)
514 goto fail;
515
516 wsi->GetImageMemoryRequirements(chain->device, image->image, &reqs);
517
518 const VkMemoryDedicatedAllocateInfo memory_dedicated_info = {
519 .sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
520 .pNext = NULL,
521 .image = image->image,
522 .buffer = VK_NULL_HANDLE,
523 };
524 const VkMemoryAllocateInfo memory_info = {
525 .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
526 .pNext = &memory_dedicated_info,
527 .allocationSize = reqs.size,
528 .memoryTypeIndex = select_memory_type(wsi, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
529 reqs.memoryTypeBits),
530 };
531 result = wsi->AllocateMemory(chain->device, &memory_info,
532 &chain->alloc, &image->memory);
533 if (result != VK_SUCCESS)
534 goto fail;
535
536 result = wsi->BindImageMemory(chain->device, image->image,
537 image->memory, 0);
538 if (result != VK_SUCCESS)
539 goto fail;
540
541 image->prime.blit_cmd_buffers =
542 vk_zalloc(&chain->alloc,
543 sizeof(VkCommandBuffer) * wsi->queue_family_count, 8,
544 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
545 if (!image->prime.blit_cmd_buffers) {
546 result = VK_ERROR_OUT_OF_HOST_MEMORY;
547 goto fail;
548 }
549
550 for (uint32_t i = 0; i < wsi->queue_family_count; i++) {
551 const VkCommandBufferAllocateInfo cmd_buffer_info = {
552 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
553 .pNext = NULL,
554 .commandPool = chain->cmd_pools[i],
555 .level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
556 .commandBufferCount = 1,
557 };
558 result = wsi->AllocateCommandBuffers(chain->device, &cmd_buffer_info,
559 &image->prime.blit_cmd_buffers[i]);
560 if (result != VK_SUCCESS)
561 goto fail;
562
563 const VkCommandBufferBeginInfo begin_info = {
564 .sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
565 };
566 wsi->BeginCommandBuffer(image->prime.blit_cmd_buffers[i], &begin_info);
567
568 struct VkBufferImageCopy buffer_image_copy = {
569 .bufferOffset = 0,
570 .bufferRowLength = linear_stride / cpp,
571 .bufferImageHeight = 0,
572 .imageSubresource = {
573 .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
574 .mipLevel = 0,
575 .baseArrayLayer = 0,
576 .layerCount = 1,
577 },
578 .imageOffset = { .x = 0, .y = 0, .z = 0 },
579 .imageExtent = {
580 .width = pCreateInfo->imageExtent.width,
581 .height = pCreateInfo->imageExtent.height,
582 .depth = 1,
583 },
584 };
585 wsi->CmdCopyImageToBuffer(image->prime.blit_cmd_buffers[i],
586 image->image,
587 VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
588 image->prime.buffer,
589 1, &buffer_image_copy);
590
591 result = wsi->EndCommandBuffer(image->prime.blit_cmd_buffers[i]);
592 if (result != VK_SUCCESS)
593 goto fail;
594 }
595
596 const VkMemoryGetFdInfoKHR linear_memory_get_fd_info = {
597 .sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR,
598 .pNext = NULL,
599 .memory = image->prime.memory,
600 .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
601 };
602 int fd;
603 result = wsi->GetMemoryFdKHR(chain->device, &linear_memory_get_fd_info, &fd);
604 if (result != VK_SUCCESS)
605 goto fail;
606
607 image->drm_modifier = use_modifier ? DRM_FORMAT_MOD_LINEAR : DRM_FORMAT_MOD_INVALID;
608 image->num_planes = 1;
609 image->sizes[0] = linear_size;
610 image->row_pitches[0] = linear_stride;
611 image->offsets[0] = 0;
612 image->fds[0] = fd;
613
614 return VK_SUCCESS;
615
616 fail:
617 wsi_destroy_image(chain, image);
618
619 return result;
620 }
621
622