14 bool GetHardwareBufferProperties(
15 const vk::Device& device,
16 struct AHardwareBuffer* hardware_buffer,
17 ::impeller::vk::AndroidHardwareBufferPropertiesANDROID* ahb_props,
18 ::impeller::vk::AndroidHardwareBufferFormatPropertiesANDROID*
20 FML_CHECK(ahb_format_props !=
nullptr);
21 FML_CHECK(ahb_props !=
nullptr);
22 ahb_props->pNext = ahb_format_props;
23 ::impeller::vk::Result result =
24 device.getAndroidHardwareBufferPropertiesANDROID(hardware_buffer,
26 if (result != impeller::vk::Result::eSuccess) {
32 vk::ExternalFormatANDROID MakeExternalFormat(
33 const vk::AndroidHardwareBufferFormatPropertiesANDROID& format_props) {
34 vk::ExternalFormatANDROID external_format;
35 external_format.pNext =
nullptr;
36 external_format.externalFormat = 0;
37 if (format_props.format == vk::Format::eUndefined) {
38 external_format.externalFormat = format_props.externalFormat;
40 return external_format;
44 int FindMemoryTypeIndex(
45 const vk::AndroidHardwareBufferPropertiesANDROID& props) {
46 uint32_t memory_type_bits = props.memoryTypeBits;
47 int32_t type_index = -1;
48 for (uint32_t i = 0; memory_type_bits;
49 memory_type_bits = memory_type_bits >> 0x1, ++i) {
50 if (memory_type_bits & 0x1) {
60 AndroidHardwareBufferTextureSourceVK::AndroidHardwareBufferTextureSourceVK(
61 TextureDescriptor desc,
62 const vk::Device& device,
63 struct AHardwareBuffer* hardware_buffer,
64 const AHardwareBuffer_Desc& hardware_buffer_desc)
65 : TextureSourceVK(desc), device_(device) {
66 vk::AndroidHardwareBufferFormatPropertiesANDROID ahb_format_props;
67 vk::AndroidHardwareBufferPropertiesANDROID ahb_props;
68 if (!GetHardwareBufferProperties(device, hardware_buffer, &ahb_props,
72 vk::ExternalFormatANDROID external_format =
73 MakeExternalFormat(ahb_format_props);
74 vk::ExternalMemoryImageCreateInfo external_memory_image_info;
75 external_memory_image_info.pNext = &external_format;
76 external_memory_image_info.handleTypes =
77 vk::ExternalMemoryHandleTypeFlagBits::eAndroidHardwareBufferANDROID;
78 const int memory_type_index = FindMemoryTypeIndex(ahb_props);
79 if (memory_type_index < 0) {
80 FML_LOG(ERROR) <<
"Could not find memory type.";
84 vk::ImageCreateFlags image_create_flags;
85 vk::ImageUsageFlags image_usage_flags;
86 if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
87 image_usage_flags |= impeller::vk::ImageUsageFlagBits::eSampled |
88 impeller::vk::ImageUsageFlagBits::eInputAttachment;
90 if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) {
91 image_usage_flags |= impeller::vk::ImageUsageFlagBits::eColorAttachment;
93 if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
94 image_create_flags |= impeller::vk::ImageCreateFlagBits::eProtected;
97 vk::ImageCreateInfo image_create_info;
98 image_create_info.pNext = &external_memory_image_info;
99 image_create_info.imageType = vk::ImageType::e2D;
100 image_create_info.format = ahb_format_props.format;
101 image_create_info.extent.width = hardware_buffer_desc.width;
102 image_create_info.extent.height = hardware_buffer_desc.height;
103 image_create_info.extent.depth = 1;
104 image_create_info.mipLevels = 1;
105 image_create_info.arrayLayers = 1;
106 image_create_info.samples = vk::SampleCountFlagBits::e1;
107 image_create_info.tiling = vk::ImageTiling::eOptimal;
108 image_create_info.usage = image_usage_flags;
109 image_create_info.flags = image_create_flags;
110 image_create_info.sharingMode = vk::SharingMode::eExclusive;
111 image_create_info.initialLayout = vk::ImageLayout::eUndefined;
113 vk::ResultValue<impeller::vk::Image> maybe_image =
114 device.createImage(image_create_info);
115 if (maybe_image.result != vk::Result::eSuccess) {
116 FML_LOG(ERROR) <<
"device.createImage failed: "
117 <<
static_cast<int>(maybe_image.result);
120 vk::Image image = maybe_image.value;
122 vk::ImportAndroidHardwareBufferInfoANDROID ahb_import_info;
123 ahb_import_info.pNext =
nullptr;
124 ahb_import_info.buffer = hardware_buffer;
126 vk::MemoryDedicatedAllocateInfo dedicated_alloc_info;
127 dedicated_alloc_info.pNext = &ahb_import_info;
128 dedicated_alloc_info.image = image;
129 dedicated_alloc_info.buffer = VK_NULL_HANDLE;
131 vk::MemoryAllocateInfo mem_alloc_info;
132 mem_alloc_info.pNext = &dedicated_alloc_info;
133 mem_alloc_info.allocationSize = ahb_props.allocationSize;
134 mem_alloc_info.memoryTypeIndex = memory_type_index;
136 vk::ResultValue<vk::DeviceMemory> allocate_result =
137 device.allocateMemory(mem_alloc_info);
138 if (allocate_result.result != vk::Result::eSuccess) {
139 FML_LOG(ERROR) <<
"vkAllocateMemory failed : "
140 <<
static_cast<int>(allocate_result.result);
141 device.destroyImage(image);
144 vk::DeviceMemory device_memory = allocate_result.value;
147 vk::Result bind_image_result =
148 device.bindImageMemory(image, device_memory, 0);
149 if (bind_image_result != vk::Result::eSuccess) {
150 FML_LOG(ERROR) <<
"vkBindImageMemory failed : "
151 <<
static_cast<int>(bind_image_result);
152 device.destroyImage(image);
153 device.freeMemory(device_memory);
157 device_memory_ = device_memory;
160 vk::ImageViewCreateInfo view_info;
161 view_info.image = image_;
162 view_info.viewType = vk::ImageViewType::e2D;
164 view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
165 view_info.subresourceRange.baseMipLevel = 0u;
166 view_info.subresourceRange.baseArrayLayer = 0u;
167 view_info.subresourceRange.levelCount = desc.mip_count;
169 auto [view_result, view] = device.createImageViewUnique(view_info);
170 if (view_result != vk::Result::eSuccess) {
171 FML_LOG(ERROR) <<
"createImageViewUnique failed : "
172 <<
static_cast<int>(view_result);
175 image_view_ = std::move(view);
180 AndroidHardwareBufferTextureSourceVK::~AndroidHardwareBufferTextureSourceVK() {
181 device_.destroyImage(image_);
182 device_.freeMemory(device_memory_);
185 bool AndroidHardwareBufferTextureSourceVK::IsValid()
const {
190 vk::Image AndroidHardwareBufferTextureSourceVK::GetImage()
const {
191 FML_CHECK(IsValid());
196 vk::ImageView AndroidHardwareBufferTextureSourceVK::GetImageView()
const {
197 FML_CHECK(IsValid());
198 return image_view_.get();