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 
7 
8 #ifdef FML_OS_ANDROID
9 
10 namespace impeller {
11 
12 namespace {
13 
14 bool GetHardwareBufferProperties(
15  const vk::Device& device,
16  struct AHardwareBuffer* hardware_buffer,
17  ::impeller::vk::AndroidHardwareBufferPropertiesANDROID* ahb_props,
18  ::impeller::vk::AndroidHardwareBufferFormatPropertiesANDROID*
19  ahb_format_props) {
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,
25  ahb_props);
26  if (result != impeller::vk::Result::eSuccess) {
27  return false;
28  }
29  return true;
30 }
31 
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;
39  }
40  return external_format;
41 }
42 
43 // Returns -1 if not found.
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) {
51  type_index = i;
52  break;
53  }
54  }
55  return type_index;
56 }
57 
58 } // namespace
59 
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,
69  &ahb_format_props)) {
70  return;
71  }
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.";
81  return;
82  }
83 
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;
89  }
90  if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT) {
91  image_usage_flags |= impeller::vk::ImageUsageFlagBits::eColorAttachment;
92  }
93  if (hardware_buffer_desc.usage & AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT) {
94  image_create_flags |= impeller::vk::ImageCreateFlagBits::eProtected;
95  }
96 
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;
112 
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);
118  return;
119  }
120  vk::Image image = maybe_image.value;
121 
122  vk::ImportAndroidHardwareBufferInfoANDROID ahb_import_info;
123  ahb_import_info.pNext = nullptr;
124  ahb_import_info.buffer = hardware_buffer;
125 
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;
130 
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;
135 
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);
142  return;
143  }
144  vk::DeviceMemory device_memory = allocate_result.value;
145 
146  // Bind memory to the image object.
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);
154  return;
155  }
156  image_ = image;
157  device_memory_ = device_memory;
158 
159  // Create image view.
160  vk::ImageViewCreateInfo view_info;
161  view_info.image = image_;
162  view_info.viewType = vk::ImageViewType::e2D;
163  view_info.format = ToVKImageFormat(desc.format);
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;
168  view_info.subresourceRange.layerCount = ToArrayLayerCount(desc.type);
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);
173  return;
174  }
175  image_view_ = std::move(view);
176  is_valid_ = true;
177 }
178 
179 // |TextureSourceVK|
180 AndroidHardwareBufferTextureSourceVK::~AndroidHardwareBufferTextureSourceVK() {
181  device_.destroyImage(image_);
182  device_.freeMemory(device_memory_);
183 }
184 
185 bool AndroidHardwareBufferTextureSourceVK::IsValid() const {
186  return is_valid_;
187 }
188 
189 // |TextureSourceVK|
190 vk::Image AndroidHardwareBufferTextureSourceVK::GetImage() const {
191  FML_CHECK(IsValid());
192  return image_;
193 }
194 
195 // |TextureSourceVK|
196 vk::ImageView AndroidHardwareBufferTextureSourceVK::GetImageView() const {
197  FML_CHECK(IsValid());
198  return image_view_.get();
199 }
200 
201 } // namespace impeller
202 
203 #endif
android_hardware_buffer_texture_source_vk.h
texture_source_vk.h
impeller::ToArrayLayerCount
constexpr uint32_t ToArrayLayerCount(TextureType type)
Definition: formats_vk.h:591
impeller::ToVKImageFormat
constexpr vk::Format ToVKImageFormat(PixelFormat format)
Definition: formats_vk.h:136
impeller
Definition: aiks_context.cc:10