Skip to content

Commit 6445507

Browse files
Support for Android Platform Views under Impeller/Vulkan (flutter#44571)
- Introduce AndroidHardwareBufferTextureSourceVK. - Enable the necessary Vulkan extensions to support AndroidHardwareBufferTextureSourceVK. - Refactor HardwareBufferExternalTextureGL into a base class and a GL and VK specializations. - Switch ImageReaderPlatformView to use the PRIVATE image format (enables DRM'd content to be captured in the texture). - Add a AHardwareBuffer_describe to NDKHelpers. - Misc cleanups.
1 parent f53ad9c commit 6445507

18 files changed

+624
-152
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1500,6 +1500,8 @@ ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h
15001500
ORIGIN: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm + ../../../flutter/LICENSE
15011501
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc + ../../../flutter/LICENSE
15021502
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h + ../../../flutter/LICENSE
1503+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.cc + ../../../flutter/LICENSE
1504+
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h + ../../../flutter/LICENSE
15031505
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.cc + ../../../flutter/LICENSE
15041506
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.h + ../../../flutter/LICENSE
15051507
ORIGIN: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc + ../../../flutter/LICENSE
@@ -2338,8 +2340,10 @@ ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/surface_p
23382340
ORIGIN: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.h + ../../../flutter/LICENSE
23392341
ORIGIN: ../../../flutter/shell/platform/android/flutter_main.cc + ../../../flutter/LICENSE
23402342
ORIGIN: ../../../flutter/shell/platform/android/flutter_main.h + ../../../flutter/LICENSE
2343+
ORIGIN: ../../../flutter/shell/platform/android/hardware_buffer_external_texture.h + ../../../flutter/LICENSE
23412344
ORIGIN: ../../../flutter/shell/platform/android/hardware_buffer_external_texture_gl.cc + ../../../flutter/LICENSE
23422345
ORIGIN: ../../../flutter/shell/platform/android/hardware_buffer_external_texture_gl.h + ../../../flutter/LICENSE
2346+
ORIGIN: ../../../flutter/shell/platform/android/hardware_buffer_external_texture_vk.h + ../../../flutter/LICENSE
23432347
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/FlutterInjector.java + ../../../flutter/LICENSE
23442348
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/Log.java + ../../../flutter/LICENSE
23452349
ORIGIN: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivity.java + ../../../flutter/LICENSE
@@ -4218,6 +4222,8 @@ FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.h
42184222
FILE: ../../../flutter/impeller/renderer/backend/metal/vertex_descriptor_mtl.mm
42194223
FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.cc
42204224
FILE: ../../../flutter/impeller/renderer/backend/vulkan/allocator_vk.h
4225+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.cc
4226+
FILE: ../../../flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h
42214227
FILE: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.cc
42224228
FILE: ../../../flutter/impeller/renderer/backend/vulkan/barrier_vk.h
42234229
FILE: ../../../flutter/impeller/renderer/backend/vulkan/blit_command_vk.cc
@@ -5061,8 +5067,12 @@ FILE: ../../../flutter/shell/platform/android/external_view_embedder/surface_poo
50615067
FILE: ../../../flutter/shell/platform/android/external_view_embedder/surface_pool.h
50625068
FILE: ../../../flutter/shell/platform/android/flutter_main.cc
50635069
FILE: ../../../flutter/shell/platform/android/flutter_main.h
5070+
FILE: ../../../flutter/shell/platform/android/hardware_buffer_external_texture.cc
5071+
FILE: ../../../flutter/shell/platform/android/hardware_buffer_external_texture.h
50645072
FILE: ../../../flutter/shell/platform/android/hardware_buffer_external_texture_gl.cc
50655073
FILE: ../../../flutter/shell/platform/android/hardware_buffer_external_texture_gl.h
5074+
FILE: ../../../flutter/shell/platform/android/hardware_buffer_external_texture_vk.cc
5075+
FILE: ../../../flutter/shell/platform/android/hardware_buffer_external_texture_vk.h
50665076
FILE: ../../../flutter/shell/platform/android/io/flutter/FlutterInjector.java
50675077
FILE: ../../../flutter/shell/platform/android/io/flutter/Log.java
50685078
FILE: ../../../flutter/shell/platform/android/io/flutter/app/FlutterActivity.java

impeller/core/platform.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ namespace impeller {
1414
constexpr size_t DefaultUniformAlignment() {
1515
#if FML_OS_IOS && !TARGET_OS_SIMULATOR
1616
return 16u;
17-
#elif FML_OS_MACOSX
18-
return 256u;
1917
#else
20-
return 0x40;
18+
return 256u;
2119
#endif
2220
}
2321

impeller/renderer/backend/vulkan/BUILD.gn

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ impeller_component("vulkan") {
2424
sources = [
2525
"allocator_vk.cc",
2626
"allocator_vk.h",
27+
"android_hardware_buffer_texture_source_vk.cc",
28+
"android_hardware_buffer_texture_source_vk.h",
2729
"barrier_vk.cc",
2830
"barrier_vk.h",
2931
"blit_command_vk.cc",
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
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+
5+
#include "impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h"
6+
#include "impeller/renderer/backend/vulkan/texture_source_vk.h"
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
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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+
5+
#pragma once
6+
7+
#include "flutter/fml/build_config.h"
8+
#include "vulkan/vulkan_core.h"
9+
10+
#ifdef FML_OS_ANDROID
11+
12+
#include "flutter/fml/macros.h"
13+
#include "impeller/geometry/size.h"
14+
#include "impeller/renderer/backend/vulkan/formats_vk.h"
15+
#include "impeller/renderer/backend/vulkan/texture_source_vk.h"
16+
#include "impeller/renderer/backend/vulkan/vk.h"
17+
18+
#include <android/hardware_buffer.h>
19+
#include <android/hardware_buffer_jni.h>
20+
21+
namespace impeller {
22+
23+
class AndroidHardwareBufferTextureSourceVK final : public TextureSourceVK {
24+
public:
25+
AndroidHardwareBufferTextureSourceVK(
26+
TextureDescriptor desc,
27+
const vk::Device& device,
28+
struct AHardwareBuffer* hardware_buffer,
29+
const AHardwareBuffer_Desc& hardware_buffer_desc);
30+
31+
// |TextureSourceVK|
32+
~AndroidHardwareBufferTextureSourceVK() override;
33+
34+
// |TextureSourceVK|
35+
vk::Image GetImage() const override;
36+
37+
// |TextureSourceVK|
38+
vk::ImageView GetImageView() const override;
39+
40+
bool IsValid() const;
41+
42+
private:
43+
const vk::Device& device_;
44+
vk::Image image_ = VK_NULL_HANDLE;
45+
vk::UniqueImageView image_view_ = {};
46+
vk::DeviceMemory device_memory_ = VK_NULL_HANDLE;
47+
48+
bool is_valid_ = false;
49+
50+
FML_DISALLOW_COPY_AND_ASSIGN(AndroidHardwareBufferTextureSourceVK);
51+
};
52+
53+
} // namespace impeller
54+
55+
#endif

impeller/renderer/backend/vulkan/capabilities_vk.cc

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,18 @@ CapabilitiesVK::GetEnabledDeviceExtensions(
206206
enabled.push_back("VK_KHR_portability_subset");
207207
}
208208

209+
#ifdef FML_OS_ANDROID
210+
if (exts->find("VK_ANDROID_external_memory_android_hardware_buffer") ==
211+
exts->end()) {
212+
VALIDATION_LOG
213+
<< "Device does not support "
214+
"VK_ANDROID_external_memory_android_hardware_buffer extension.";
215+
return std::nullopt;
216+
}
217+
enabled.push_back("VK_ANDROID_external_memory_android_hardware_buffer");
218+
enabled.push_back("VK_EXT_queue_family_foreign");
219+
#endif
220+
209221
// Enable all optional extensions if the device supports it.
210222
IterateOptionalDeviceExtensions([&](auto ext) {
211223
auto ext_name = GetDeviceExtensionName(ext);

shell/platform/android/BUILD.gn

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,12 @@ source_set("flutter_shell_native_src") {
9898
"apk_asset_provider.h",
9999
"flutter_main.cc",
100100
"flutter_main.h",
101+
"hardware_buffer_external_texture.cc",
102+
"hardware_buffer_external_texture.h",
101103
"hardware_buffer_external_texture_gl.cc",
102104
"hardware_buffer_external_texture_gl.h",
105+
"hardware_buffer_external_texture_vk.cc",
106+
"hardware_buffer_external_texture_vk.h",
103107
"library_loader.cc",
104108
"ndk_helpers.cc",
105109
"ndk_helpers.h",

0 commit comments

Comments
 (0)