Flutter Impeller
android_hardware_buffer_texture_source_vk.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter 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 
6 
7 #include <cstdint>
8 
10 
11 #ifdef FML_OS_ANDROID
12 
13 namespace impeller {
14 
15 namespace {
16 
17 bool GetHardwareBufferProperties(
18  const vk::Device& device,
19  struct AHardwareBuffer* hardware_buffer,
20  ::impeller::vk::AndroidHardwareBufferPropertiesANDROID* ahb_props,
21  ::impeller::vk::AndroidHardwareBufferFormatPropertiesANDROID*
22  ahb_format_props) {
23  FML_CHECK(ahb_format_props != nullptr);
24  FML_CHECK(ahb_props != nullptr);
25  ahb_props->pNext = ahb_format_props;
26  ::impeller::vk::Result result =
27  device.getAndroidHardwareBufferPropertiesANDROID(hardware_buffer,
28  ahb_props);
29  if (result != impeller::vk::Result::eSuccess) {
30  return false;
31  }
32  return true;
33 }
34 
35 vk::ExternalFormatANDROID MakeExternalFormat(
36  const vk::AndroidHardwareBufferFormatPropertiesANDROID& format_props) {
37  vk::ExternalFormatANDROID external_format;
38  external_format.pNext = nullptr;
39  external_format.externalFormat = 0;
40  if (format_props.format == vk::Format::eUndefined) {
41  external_format.externalFormat = format_props.externalFormat;
42  }
43  return external_format;
44 }
45 
46 // Returns -1 if not found.
47 int FindMemoryTypeIndex(
48  const vk::AndroidHardwareBufferPropertiesANDROID& props) {
49  uint32_t memory_type_bits = props.memoryTypeBits;
50  int32_t type_index = -1;
51  for (uint32_t i = 0; memory_type_bits;
52  memory_type_bits = memory_type_bits >> 0x1, ++i) {
53  if (memory_type_bits & 0x1) {
54  type_index = i;
55  break;
56  }
57  }
58  return type_index;
59 }
60 
61 } // namespace
62 
63 AndroidHardwareBufferTextureSourceVK::AndroidHardwareBufferTextureSourceVK(
64  TextureDescriptor desc,
65  const vk::Device& device,
66  struct AHardwareBuffer* hardware_buffer,
67  const AHardwareBuffer_Desc& hardware_buffer_desc)
68  : TextureSourceVK(desc), device_(device) {
69  vk::AndroidHardwareBufferFormatPropertiesANDROID ahb_format_props;
70  vk::AndroidHardwareBufferPropertiesANDROID ahb_props;
71  if (!GetHardwareBufferProperties(device, hardware_buffer, &ahb_props,
72  &ahb_format_props)) {
73  return;
74  }
75  vk::ExternalFormatANDROID external_format =
76  MakeExternalFormat(ahb_format_props);
77  vk::ExternalMemoryImageCreateInfo external_memory_image_info;
78  external_memory_image_info.pNext = &external_format;
79  external_memory_image_info.handleTypes =
80  vk::ExternalMemoryHandleTypeFlagBits::eAndroidHardwareBufferANDROID;
81  const int memory_type_index = FindMemoryTypeIndex(ahb_props);
82  if (memory_type_index < 0) {
83  FML_LOG(ERROR) << "Could not find memory type.";
84  return;
85  }
86 
87  vk::ImageCreateFlags image_create_flags;
88  vk::ImageUsageFlags image_usage_flags;
89  if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE) {
90  image_usage_flags |= impeller::vk::ImageUsageFlagBits::eSampled |
91  impeller::vk::ImageUsageFlagBits::eInputAttachment;
92  }
93  if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) {
94  image_usage_flags |= impeller::vk::ImageUsageFlagBits::eColorAttachment;
95  }
96  if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
97  image_create_flags |= impeller::vk::ImageCreateFlagBits::eProtected;
98  }
99 
100  vk::ImageCreateInfo image_create_info;
101  image_create_info.pNext = &external_memory_image_info;
102  image_create_info.imageType = vk::ImageType::e2D;
103  image_create_info.format = ahb_format_props.format;
104  image_create_info.extent.width = hardware_buffer_desc.width;
105  image_create_info.extent.height = hardware_buffer_desc.height;
106  image_create_info.extent.depth = 1;
107  image_create_info.mipLevels = 1;
108  image_create_info.arrayLayers = 1;
109  image_create_info.samples = vk::SampleCountFlagBits::e1;
110  image_create_info.tiling = vk::ImageTiling::eOptimal;
111  image_create_info.usage = image_usage_flags;
112  image_create_info.flags = image_create_flags;
113  image_create_info.sharingMode = vk::SharingMode::eExclusive;
114  image_create_info.initialLayout = vk::ImageLayout::eUndefined;
115 
116  vk::ResultValue<impeller::vk::Image> maybe_image =
117  device.createImage(image_create_info);
118  if (maybe_image.result != vk::Result::eSuccess) {
119  FML_LOG(ERROR) << "device.createImage failed: "
120  << static_cast<int>(maybe_image.result);
121  return;
122  }
123  vk::Image image = maybe_image.value;
124 
125  vk::ImportAndroidHardwareBufferInfoANDROID ahb_import_info;
126  ahb_import_info.pNext = nullptr;
127  ahb_import_info.buffer = hardware_buffer;
128 
129  vk::MemoryDedicatedAllocateInfo dedicated_alloc_info;
130  dedicated_alloc_info.pNext = &ahb_import_info;
131  dedicated_alloc_info.image = image;
132  dedicated_alloc_info.buffer = VK_NULL_HANDLE;
133 
134  vk::MemoryAllocateInfo mem_alloc_info;
135  mem_alloc_info.pNext = &dedicated_alloc_info;
136  mem_alloc_info.allocationSize = ahb_props.allocationSize;
137  mem_alloc_info.memoryTypeIndex = memory_type_index;
138 
139  vk::ResultValue<vk::DeviceMemory> allocate_result =
140  device.allocateMemory(mem_alloc_info);
141  if (allocate_result.result != vk::Result::eSuccess) {
142  FML_LOG(ERROR) << "vkAllocateMemory failed : "
143  << static_cast<int>(allocate_result.result);
144  device.destroyImage(image);
145  return;
146  }
147  vk::DeviceMemory device_memory = allocate_result.value;
148 
149  // Bind memory to the image object.
150  vk::Result bind_image_result =
151  device.bindImageMemory(image, device_memory, 0);
152  if (bind_image_result != vk::Result::eSuccess) {
153  FML_LOG(ERROR) << "vkBindImageMemory failed : "
154  << static_cast<int>(bind_image_result);
155  device.destroyImage(image);
156  device.freeMemory(device_memory);
157  return;
158  }
159  image_ = image;
160  device_memory_ = device_memory;
161 
162  // Create image view.
163  vk::ImageViewCreateInfo view_info;
164  view_info.image = image_;
165  view_info.viewType = vk::ImageViewType::e2D;
166  view_info.format = ToVKImageFormat(desc.format);
167  view_info.subresourceRange.aspectMask = vk::ImageAspectFlagBits::eColor;
168  view_info.subresourceRange.baseMipLevel = 0u;
169  view_info.subresourceRange.baseArrayLayer = 0u;
170  view_info.subresourceRange.levelCount = desc.mip_count;
171  view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type);
172  auto [view_result, view] = device.createImageViewUnique(view_info);
173  if (view_result != vk::Result::eSuccess) {
174  FML_LOG(ERROR) << "createImageViewUnique failed : "
175  << static_cast<int>(view_result);
176  return;
177  }
178  image_view_ = std::move(view);
179  is_valid_ = true;
180 }
181 
182 // |TextureSourceVK|
183 AndroidHardwareBufferTextureSourceVK::~AndroidHardwareBufferTextureSourceVK() {
184  device_.destroyImage(image_);
185  device_.freeMemory(device_memory_);
186 }
187 
188 bool AndroidHardwareBufferTextureSourceVK::IsValid() const {
189  return is_valid_;
190 }
191 
192 // |TextureSourceVK|
193 vk::Image AndroidHardwareBufferTextureSourceVK::GetImage() const {
194  FML_CHECK(IsValid());
195  return image_;
196 }
197 
198 // |TextureSourceVK|
199 vk::ImageView AndroidHardwareBufferTextureSourceVK::GetImageView() const {
200  FML_CHECK(IsValid());
201  return image_view_.get();
202 }
203 
204 } // namespace impeller
205 
206 #endif
android_hardware_buffer_texture_source_vk.h
texture_source_vk.h
impeller::ToArrayLayerCount
constexpr uint32_t ToArrayLayerCount(TextureType type)
Definition: formats_vk.h:594
impeller::ToVKImageFormat
constexpr vk::Format ToVKImageFormat(PixelFormat format)
Definition: formats_vk.h:136
impeller
Definition: aiks_context.cc:10