Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
2 changes: 1 addition & 1 deletion impeller/renderer/backend/vulkan/context_vk.cc
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ void ContextVK::Setup(Settings settings) {
// 1. The user has explicitly enabled it.
// 2. We are in a combination of debug mode, and running on Android.
// (It's possible 2 is overly conservative and we can simplify this)
auto enable_validation = settings.enable_validation;
auto enable_validation = false; // settings.enable_validation;

#if defined(FML_OS_ANDROID) && !defined(NDEBUG)
enable_validation = true;
Expand Down
54 changes: 54 additions & 0 deletions shell/platform/android/image_external_texture_vk.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include "flutter/shell/platform/android/image_external_texture_vk.h"
#include <cstdint>

#include "flutter/impeller/core/formats.h"
#include "flutter/impeller/core/texture_descriptor.h"
Expand Down Expand Up @@ -31,6 +32,50 @@ void ImageExternalTextureVK::Attach(PaintContext& context) {

void ImageExternalTextureVK::Detach() {}

sk_sp<flutter::DlImage> ImageExternalTextureVK::FindImage(uint64_t key) {
for (auto i = 0u; i < kImageReaderSwapchainSize; i++) {
if (images_[i].first == key) {
UpdateKey(key);
return images_[i].second;
}
}
return nullptr;
}

void ImageExternalTextureVK::UpdateKey(uint64_t key) {
if (keys_[0] == key) {
return;
}
auto i = 1u;
for (; i < kImageReaderSwapchainSize; i++) {
if (keys_[i] == key) {
break;
}
}
for (auto j = i; j > 0; j--) {
keys_[j] = keys_[j - 1];
}
keys_[0] = key;
}

void ImageExternalTextureVK::AddImage(sk_sp<flutter::DlImage> image,
uint64_t key) {
uint64_t lru_key = keys_[2];
bool updated_image = false;
for (auto i = 0u; i < kImageReaderSwapchainSize; i++) {
if (images_[i].first == lru_key) {
updated_image = true;
images_[i] = std::make_pair(key, image);
break;
}
}
if (!updated_image) {
keys_[0] = key;
images_[0] = std::make_pair(key, image);
}
UpdateKey(key);
}

void ImageExternalTextureVK::ProcessFrame(PaintContext& context,
const SkRect& bounds) {
JavaLocalRef image = AcquireLatestImage();
Expand All @@ -45,6 +90,14 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context,
AHardwareBuffer_Desc hb_desc = {};
flutter::NDKHelpers::AHardwareBuffer_describe(latest_hardware_buffer,
&hb_desc);
uint64_t key;
flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer, &key);

auto existing_image = FindImage(key);
if (existing_image != nullptr) {
dl_image_ = existing_image;
return;
}

impeller::TextureDescriptor desc;
desc.storage_mode = impeller::StorageMode::kDevicePrivate;
Expand Down Expand Up @@ -88,6 +141,7 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context,
}

dl_image_ = impeller::DlImageImpeller::Make(texture);
AddImage(dl_image_, key);
CloseHardwareBuffer(hardware_buffer);
// IMPORTANT: We only close the old image after texture stops referencing
// it.
Expand Down
17 changes: 17 additions & 0 deletions shell/platform/android/image_external_texture_vk.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_VK_H_
#define FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_VK_H_

#include <cstdint>
#include <unordered_map>
#include <utility>
#include "flutter/shell/platform/android/image_external_texture.h"

#include "flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h"
Expand All @@ -14,6 +17,8 @@

namespace flutter {

static constexpr size_t kImageReaderSwapchainSize = 3u;

class ImageExternalTextureVK : public ImageExternalTexture {
public:
ImageExternalTextureVK(
Expand All @@ -30,9 +35,21 @@ class ImageExternalTextureVK : public ImageExternalTexture {
void ProcessFrame(PaintContext& context, const SkRect& bounds) override;
void Detach() override;

sk_sp<flutter::DlImage> FindImage(uint64_t key);

void UpdateKey(uint64_t key);

void AddImage(sk_sp<flutter::DlImage> image, uint64_t key);

const std::shared_ptr<impeller::ContextVK> impeller_context_;

fml::jni::ScopedJavaGlobalRef<jobject> android_image_;

std::array<std::pair<uint64_t, sk_sp<flutter::DlImage>>,
kImageReaderSwapchainSize>
images_ = {std::make_pair(0, nullptr), std::make_pair(0, nullptr),
std::make_pair(0, nullptr)};
std::array<uint64_t, kImageReaderSwapchainSize> keys_ = {0, 0, 0};
};

} // namespace flutter
Expand Down
16 changes: 16 additions & 0 deletions shell/platform/android/ndk_helpers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ typedef void (*fp_AHardwareBuffer_acquire)(AHardwareBuffer* buffer);
typedef void (*fp_AHardwareBuffer_release)(AHardwareBuffer* buffer);
typedef void (*fp_AHardwareBuffer_describe)(AHardwareBuffer* buffer,
AHardwareBuffer_Desc* desc);
typedef void (*fp_AHardwareBuffer_getId)(AHardwareBuffer* buffer,
uint64_t* outId);

typedef EGLClientBuffer (*fp_eglGetNativeClientBufferANDROID)(
AHardwareBuffer* buffer);

Expand All @@ -32,6 +35,8 @@ void (*_AHardwareBuffer_acquire)(AHardwareBuffer* buffer) = nullptr;
void (*_AHardwareBuffer_release)(AHardwareBuffer* buffer) = nullptr;
void (*_AHardwareBuffer_describe)(AHardwareBuffer* buffer,
AHardwareBuffer_Desc* desc) = nullptr;
void (*_AHardwareBuffer_getId)(AHardwareBuffer* buffer,
uint64_t* outId) = nullptr;
EGLClientBuffer (*_eglGetNativeClientBufferANDROID)(AHardwareBuffer* buffer) =
nullptr;

Expand Down Expand Up @@ -61,6 +66,10 @@ void InitOnceCallback() {
->ResolveFunction<fp_AHardwareBuffer_release>(
"AHardwareBuffer_release")
.value_or(nullptr);
_AHardwareBuffer_getId =
android
->ResolveFunction<fp_AHardwareBuffer_getId>("AHardwareBuffer_getId")
.value_or(nullptr);
_AHardwareBuffer_describe =
android
->ResolveFunction<fp_AHardwareBuffer_describe>(
Expand Down Expand Up @@ -107,6 +116,13 @@ void NDKHelpers::AHardwareBuffer_describe(AHardwareBuffer* buffer,
_AHardwareBuffer_describe(buffer, desc);
}

void NDKHelpers::AHardwareBuffer_getId(AHardwareBuffer* buffer,
uint64_t* outId) {
NDKHelpers::Init();
FML_CHECK(_AHardwareBuffer_getId != nullptr);
_AHardwareBuffer_getId(buffer, outId);
}

EGLClientBuffer NDKHelpers::eglGetNativeClientBufferANDROID(
AHardwareBuffer* buffer) {
NDKHelpers::Init();
Expand Down
1 change: 1 addition & 0 deletions shell/platform/android/ndk_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class NDKHelpers {
static void AHardwareBuffer_release(AHardwareBuffer* buffer);
static void AHardwareBuffer_describe(AHardwareBuffer* buffer,
AHardwareBuffer_Desc* desc);
static void AHardwareBuffer_getId(AHardwareBuffer* buffer, uint64_t* outId);
static EGLClientBuffer eglGetNativeClientBufferANDROID(
AHardwareBuffer* buffer);

Expand Down