1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "gpu/vulkan/vulkan_image.h"
6 
7 #include "gpu/vulkan/vulkan_device_queue.h"
8 
9 namespace gpu {
10 
InitializeFromGpuMemoryBufferHandle(VulkanDeviceQueue * device_queue,gfx::GpuMemoryBufferHandle gmb_handle,const gfx::Size & size,VkFormat format,VkImageUsageFlags usage,VkImageCreateFlags flags,VkImageTiling image_tiling)11 bool VulkanImage::InitializeFromGpuMemoryBufferHandle(
12     VulkanDeviceQueue* device_queue,
13     gfx::GpuMemoryBufferHandle gmb_handle,
14     const gfx::Size& size,
15     VkFormat format,
16     VkImageUsageFlags usage,
17     VkImageCreateFlags flags,
18     VkImageTiling image_tiling) {
19   if (gmb_handle.type != gfx::GpuMemoryBufferType::NATIVE_PIXMAP) {
20     DLOG(ERROR) << "GpuMemoryBuffer is not supported. type:" << gmb_handle.type;
21     return false;
22   }
23 
24   auto& native_pixmap_handle = gmb_handle.native_pixmap_handle;
25   DCHECK_EQ(native_pixmap_handle.planes.size(), 1u);
26 
27   auto& scoped_fd = native_pixmap_handle.planes[0].fd;
28   if (!scoped_fd.is_valid()) {
29     DLOG(ERROR) << "GpuMemoryBufferHandle doesn't have a valid fd.";
30     return false;
31   }
32 
33   bool using_modifier =
34       native_pixmap_handle.modifier != gfx::NativePixmapHandle::kNoModifier &&
35       gfx::HasExtension(device_queue->enabled_extensions(),
36                         VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME);
37 
38   // If the driver doesn't support modifier or the native_pixmap_handle doesn't
39   // have modifier, VK_IMAGE_TILING_OPTIMAL will be used.
40   DCHECK_EQ(image_tiling, VK_IMAGE_TILING_OPTIMAL);
41   if (using_modifier)
42     image_tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT;
43 
44   VkExternalMemoryImageCreateInfoKHR external_image_create_info = {
45       .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR,
46       .pNext = nullptr,
47       .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
48   };
49   VkImageDrmFormatModifierListCreateInfoEXT modifier_info = {
50       .sType = VK_STRUCTURE_TYPE_IMAGE_DRM_FORMAT_MODIFIER_LIST_CREATE_INFO_EXT,
51       .pNext = nullptr,
52       .drmFormatModifierCount = 1,
53       .pDrmFormatModifiers = &native_pixmap_handle.modifier,
54   };
55   if (using_modifier)
56     external_image_create_info.pNext = &modifier_info;
57 
58   VkImportMemoryFdInfoKHR import_memory_fd_info = {
59       .sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_FD_INFO_KHR,
60       .pNext = nullptr,
61       .handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT,
62       .fd = scoped_fd.get(),
63   };
64 
65   VkMemoryRequirements* requirements = nullptr;
66   bool result = Initialize(device_queue, size, format, usage, flags,
67                            image_tiling, &external_image_create_info,
68                            &import_memory_fd_info, requirements);
69   // If Initialize successfully, the fd in scoped_fd should be owned by vulkan.
70   if (result)
71     ignore_result(scoped_fd.release());
72 
73   return result;
74 }
75 
76 }  // namespace gpu
77