From 566fb507f9a95fc46b973fab614ee1ff6c21b37a Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Wed, 24 Jan 2024 17:19:37 -0800 Subject: [PATCH 01/17] [Android] re-use already imported hardware buffers. --- impeller/renderer/backend/vulkan/context_vk.cc | 2 +- .../platform/android/image_external_texture_vk.cc | 8 ++++++++ .../platform/android/image_external_texture_vk.h | 2 ++ shell/platform/android/ndk_helpers.cc | 15 +++++++++++++++ shell/platform/android/ndk_helpers.h | 1 + 5 files changed, 27 insertions(+), 1 deletion(-) diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index e573d6aa5bfb9..bb0d3cb191004 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -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; diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index 714b9929def27..9f59621872656 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -45,6 +45,13 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, AHardwareBuffer_Desc hb_desc = {}; flutter::NDKHelpers::AHardwareBuffer_describe(latest_hardware_buffer, &hb_desc); + uint64_t id; + flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer, &id); + auto lookup = cache_.find(id); + if (lookup != cache_.end()) { + dl_image_ = lookup->second; + return; + } impeller::TextureDescriptor desc; desc.storage_mode = impeller::StorageMode::kDevicePrivate; @@ -88,6 +95,7 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, } dl_image_ = impeller::DlImageImpeller::Make(texture); + cache_[id] = dl_image_; CloseHardwareBuffer(hardware_buffer); // IMPORTANT: We only close the old image after texture stops referencing // it. diff --git a/shell/platform/android/image_external_texture_vk.h b/shell/platform/android/image_external_texture_vk.h index a6c531e07945e..9df208ea8bd13 100644 --- a/shell/platform/android/image_external_texture_vk.h +++ b/shell/platform/android/image_external_texture_vk.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_VK_H_ #define FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_VK_H_ +#include #include "flutter/shell/platform/android/image_external_texture.h" #include "flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h" @@ -33,6 +34,7 @@ class ImageExternalTextureVK : public ImageExternalTexture { const std::shared_ptr impeller_context_; fml::jni::ScopedJavaGlobalRef android_image_; + std::unordered_map> cache_; }; } // namespace flutter diff --git a/shell/platform/android/ndk_helpers.cc b/shell/platform/android/ndk_helpers.cc index 9ff5d4ea3b6d1..d62e754ffa537 100644 --- a/shell/platform/android/ndk_helpers.cc +++ b/shell/platform/android/ndk_helpers.cc @@ -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); @@ -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; @@ -61,6 +66,10 @@ void InitOnceCallback() { ->ResolveFunction( "AHardwareBuffer_release") .value_or(nullptr); + _AHardwareBuffer_getId = + android + ->ResolveFunction("AHardwareBuffer_getId") + .value_or(nullptr); _AHardwareBuffer_describe = android ->ResolveFunction( @@ -107,6 +116,12 @@ 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(); diff --git a/shell/platform/android/ndk_helpers.h b/shell/platform/android/ndk_helpers.h index f1c2592467dea..83ae51360af1a 100644 --- a/shell/platform/android/ndk_helpers.h +++ b/shell/platform/android/ndk_helpers.h @@ -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); From 50e8f8cfa311e1c3cd0976cfb289562ec3ec0add Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Wed, 24 Jan 2024 19:17:42 -0800 Subject: [PATCH 02/17] diy LRU --- .../renderer/backend/vulkan/context_vk.cc | 2 +- .../android/image_external_texture_vk.cc | 58 +++++++++++++++++-- .../android/image_external_texture_vk.h | 17 +++++- shell/platform/android/ndk_helpers.cc | 5 +- 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index bb0d3cb191004..d4bd9795aabd4 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -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 = false; //settings.enable_validation; + auto enable_validation = false; // settings.enable_validation; #if defined(FML_OS_ANDROID) && !defined(NDEBUG) enable_validation = true; diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index 9f59621872656..ac7fcabe425fe 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -1,5 +1,6 @@ #include "flutter/shell/platform/android/image_external_texture_vk.h" +#include #include "flutter/impeller/core/formats.h" #include "flutter/impeller/core/texture_descriptor.h" @@ -31,6 +32,50 @@ void ImageExternalTextureVK::Attach(PaintContext& context) { void ImageExternalTextureVK::Detach() {} +sk_sp 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 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(); @@ -45,11 +90,12 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, AHardwareBuffer_Desc hb_desc = {}; flutter::NDKHelpers::AHardwareBuffer_describe(latest_hardware_buffer, &hb_desc); - uint64_t id; - flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer, &id); - auto lookup = cache_.find(id); - if (lookup != cache_.end()) { - dl_image_ = lookup->second; + 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; } @@ -95,7 +141,7 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, } dl_image_ = impeller::DlImageImpeller::Make(texture); - cache_[id] = dl_image_; + AddImage(dl_image_, key); CloseHardwareBuffer(hardware_buffer); // IMPORTANT: We only close the old image after texture stops referencing // it. diff --git a/shell/platform/android/image_external_texture_vk.h b/shell/platform/android/image_external_texture_vk.h index 9df208ea8bd13..f1f0cd335c2ff 100644 --- a/shell/platform/android/image_external_texture_vk.h +++ b/shell/platform/android/image_external_texture_vk.h @@ -5,7 +5,9 @@ #ifndef FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_VK_H_ #define FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_VK_H_ +#include #include +#include #include "flutter/shell/platform/android/image_external_texture.h" #include "flutter/impeller/renderer/backend/vulkan/android_hardware_buffer_texture_source_vk.h" @@ -15,6 +17,8 @@ namespace flutter { +static constexpr size_t kImageReaderSwapchainSize = 3u; + class ImageExternalTextureVK : public ImageExternalTexture { public: ImageExternalTextureVK( @@ -31,10 +35,21 @@ class ImageExternalTextureVK : public ImageExternalTexture { void ProcessFrame(PaintContext& context, const SkRect& bounds) override; void Detach() override; + sk_sp FindImage(uint64_t key); + + void UpdateKey(uint64_t key); + + void AddImage(sk_sp image, uint64_t key); + const std::shared_ptr impeller_context_; fml::jni::ScopedJavaGlobalRef android_image_; - std::unordered_map> cache_; + + std::array>, + kImageReaderSwapchainSize> + images_ = {std::make_pair(0, nullptr), std::make_pair(0, nullptr), + std::make_pair(0, nullptr)}; + std::array keys_ = {0, 0, 0}; }; } // namespace flutter diff --git a/shell/platform/android/ndk_helpers.cc b/shell/platform/android/ndk_helpers.cc index d62e754ffa537..3b0d95cae081f 100644 --- a/shell/platform/android/ndk_helpers.cc +++ b/shell/platform/android/ndk_helpers.cc @@ -116,9 +116,10 @@ void NDKHelpers::AHardwareBuffer_describe(AHardwareBuffer* buffer, _AHardwareBuffer_describe(buffer, desc); } -void NDKHelpers::AHardwareBuffer_getId(AHardwareBuffer* buffer, uint64_t *outId) { +void NDKHelpers::AHardwareBuffer_getId(AHardwareBuffer* buffer, + uint64_t* outId) { NDKHelpers::Init(); - FML_CHECK(_AHardwareBuffer_getId!= nullptr); + FML_CHECK(_AHardwareBuffer_getId != nullptr); _AHardwareBuffer_getId(buffer, outId); } From d10c6bfaf9cf06b52b7db01543e9e3347a468e77 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Wed, 24 Jan 2024 19:36:16 -0800 Subject: [PATCH 03/17] close old image for early return case. --- shell/platform/android/image_external_texture_vk.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index ac7fcabe425fe..eae563259c6be 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -96,6 +96,11 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, auto existing_image = FindImage(key); if (existing_image != nullptr) { dl_image_ = existing_image; + + CloseHardwareBuffer(hardware_buffer); + // IMPORTANT: We only close the old image after texture stops referencing + // it. + CloseImage(old_android_image); return; } From 53822fdb3cafce023809dd04a16fcf619a7e05fc Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 10:23:16 -0800 Subject: [PATCH 04/17] Use lru for all hardware buffer implementations. --- .../android/image_external_texture.cc | 44 +++++++++ .../platform/android/image_external_texture.h | 17 ++++ .../android/image_external_texture_gl.cc | 95 +++++++++++++------ .../android/image_external_texture_gl.h | 3 - .../android/image_external_texture_vk.cc | 48 +--------- .../android/image_external_texture_vk.h | 15 --- shell/platform/android/ndk_helpers.cc | 7 +- shell/platform/android/ndk_helpers.h | 2 +- 8 files changed, 135 insertions(+), 96 deletions(-) diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index d045ca91ffd8a..ce5b3bf38b11f 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -59,6 +59,50 @@ void ImageExternalTexture::OnGrContextCreated() { state_ = AttachmentState::kUninitialized; } +sk_sp ImageExternalTexture::FindImage(uint64_t key) { + for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + if (images_[i].key == key) { + UpdateKey(key); + return images_[i].image; + } + } + return nullptr; +} + +void ImageExternalTexture::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 ImageExternalTexture::AddImage(const sk_sp& image, + uint64_t key) { + uint64_t lru_key = keys_[kImageReaderSwapchainSize - 1]; + bool updated_image = false; + for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + if (images_[i].key == lru_key) { + updated_image = true; + images_[i] = LRUImage{.key = key, .image = image}; + break; + } + } + if (!updated_image) { + keys_[0] = key; + images_[0] = LRUImage{.key = key, .image = image}; + } + UpdateKey(key); +} + // Implementing flutter::ContextListener. void ImageExternalTexture::OnGrContextDestroyed() { if (state_ == AttachmentState::kAttached) { diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index 3de077706fff4..705bba2d52ff1 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -15,6 +15,8 @@ namespace flutter { +static constexpr size_t kImageReaderSwapchainSize = 3u; + // External texture peered to a sequence of android.hardware.HardwareBuffers. // class ImageExternalTexture : public flutter::Texture { @@ -49,6 +51,15 @@ class ImageExternalTexture : public flutter::Texture { virtual void Detach() = 0; virtual void ProcessFrame(PaintContext& context, const SkRect& bounds) = 0; + sk_sp FindImage(uint64_t key); + void UpdateKey(uint64_t key); + void AddImage(const sk_sp& image, uint64_t key); + + struct LRUImage { + uint64_t key; + sk_sp image; + }; + JavaLocalRef AcquireLatestImage(); void CloseImage(const fml::jni::JavaRef& image); JavaLocalRef HardwareBufferFor(const fml::jni::JavaRef& image); @@ -62,6 +73,12 @@ class ImageExternalTexture : public flutter::Texture { enum class AttachmentState { kUninitialized, kAttached, kDetached }; AttachmentState state_ = AttachmentState::kUninitialized; bool new_frame_ready_ = false; + std::array images_ = { + LRUImage{.key = 0, .image = nullptr}, + LRUImage{.key = 0, .image = nullptr}, + LRUImage{.key = 0, .image = nullptr}, + }; + std::array keys_ = {0, 0, 0}; sk_sp dl_image_; diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index fd966c8a10ee6..85658c546a05b 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -51,27 +51,6 @@ void ImageExternalTextureGL::Detach() { egl_image_.reset(); } -bool ImageExternalTextureGL::MaybeSwapImages() { - JavaLocalRef image = AcquireLatestImage(); - if (image.is_null()) { - return false; - } - // NOTE: In the following code it is important that old_android_image is - // not closed until after the update of egl_image_ otherwise the image might - // be closed before the old EGLImage referencing it has been deleted. After - // an image is closed the underlying HardwareBuffer may be recycled and used - // for a future frame. - JavaLocalRef old_android_image(android_image_); - android_image_.Reset(image); - JavaLocalRef hardware_buffer = HardwareBufferFor(image); - egl_image_ = CreateEGLImage(AHardwareBufferFor(hardware_buffer)); - CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We only close the old image after egl_image_ stops referencing - // it. - CloseImage(old_android_image); - return true; -} - impeller::UniqueEGLImageKHR ImageExternalTextureGL::CreateEGLImage( AHardwareBuffer* hardware_buffer) { if (hardware_buffer == nullptr) { @@ -123,13 +102,45 @@ void ImageExternalTextureGLSkia::Detach() { void ImageExternalTextureGLSkia::ProcessFrame(PaintContext& context, const SkRect& bounds) { - const bool swapped = MaybeSwapImages(); - if (!swapped && !egl_image_.is_valid()) { - // Nothing to do. + JavaLocalRef image = AcquireLatestImage(); + if (image.is_null()) { + return; + } + + // NOTE: In the following code it is important that old_android_image is + // not closed until after the update of egl_image_ otherwise the image might + // be closed before the old EGLImage referencing it has been deleted. After + // an image is closed the underlying HardwareBuffer may be recycled and used + // for a future frame. + JavaLocalRef old_android_image(android_image_); + android_image_.Reset(image); + JavaLocalRef hardware_buffer = HardwareBufferFor(image); + AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); + auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); + auto existing_image = FindImage(key); + if (existing_image != nullptr) { + dl_image_ = existing_image; + + CloseHardwareBuffer(hardware_buffer); + // IMPORTANT: We only close the old image after texture stops referencing + // it. + CloseImage(old_android_image); return; } + + egl_image_ = CreateEGLImage(latest_hardware_buffer); + CloseHardwareBuffer(hardware_buffer); + // IMPORTANT: We only close the old image after egl_image_ stops referencing + // it. + CloseImage(old_android_image); + + if (!egl_image_.is_valid()) { + return; + } + BindImageToTexture(egl_image_, texture_.get().texture_name); dl_image_ = CreateDlImage(context, bounds); + AddImage(dl_image_, key); } void ImageExternalTextureGLSkia::BindImageToTexture( @@ -173,12 +184,42 @@ void ImageExternalTextureGLImpeller::Attach(PaintContext& context) { void ImageExternalTextureGLImpeller::ProcessFrame(PaintContext& context, const SkRect& bounds) { - const bool swapped = MaybeSwapImages(); - if (!swapped && !egl_image_.is_valid()) { - // Nothing to do. + JavaLocalRef image = AcquireLatestImage(); + if (image.is_null()) { return; } + // NOTE: In the following code it is important that old_android_image is + // not closed until after the update of egl_image_ otherwise the image might + // be closed before the old EGLImage referencing it has been deleted. After + // an image is closed the underlying HardwareBuffer may be recycled and used + // for a future frame. + JavaLocalRef old_android_image(android_image_); + android_image_.Reset(image); + JavaLocalRef hardware_buffer = HardwareBufferFor(image); + AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); + auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); + auto existing_image = FindImage(key); + if (existing_image != nullptr) { + dl_image_ = existing_image; + + CloseHardwareBuffer(hardware_buffer); + // IMPORTANT: We only close the old image after texture stops referencing + // it. + CloseImage(old_android_image); + return; + } + + egl_image_ = CreateEGLImage(latest_hardware_buffer); + CloseHardwareBuffer(hardware_buffer); + // IMPORTANT: We only close the old image after egl_image_ stops referencing + // it. + CloseImage(old_android_image); + if (!egl_image_.is_valid()) { + return; + } + dl_image_ = CreateDlImage(context, bounds); + AddImage(dl_image_, key); } sk_sp ImageExternalTextureGLImpeller::CreateDlImage( diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index bdaa50ac605df..97159c15ebae2 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -31,9 +31,6 @@ class ImageExternalTextureGL : public ImageExternalTexture { void Attach(PaintContext& context) override; void Detach() override; - // Returns true if a new image was acquired and android_image_ and egl_image_ - // were updated. - bool MaybeSwapImages(); impeller::UniqueEGLImageKHR CreateEGLImage(AHardwareBuffer* buffer); fml::jni::ScopedJavaGlobalRef android_image_; diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index eae563259c6be..2165730a75b8a 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -32,50 +32,6 @@ void ImageExternalTextureVK::Attach(PaintContext& context) { void ImageExternalTextureVK::Detach() {} -sk_sp 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 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(); @@ -90,9 +46,7 @@ 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 key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); auto existing_image = FindImage(key); if (existing_image != nullptr) { dl_image_ = existing_image; diff --git a/shell/platform/android/image_external_texture_vk.h b/shell/platform/android/image_external_texture_vk.h index f1f0cd335c2ff..16655eb118727 100644 --- a/shell/platform/android/image_external_texture_vk.h +++ b/shell/platform/android/image_external_texture_vk.h @@ -6,7 +6,6 @@ #define FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_VK_H_ #include -#include #include #include "flutter/shell/platform/android/image_external_texture.h" @@ -17,8 +16,6 @@ namespace flutter { -static constexpr size_t kImageReaderSwapchainSize = 3u; - class ImageExternalTextureVK : public ImageExternalTexture { public: ImageExternalTextureVK( @@ -35,21 +32,9 @@ class ImageExternalTextureVK : public ImageExternalTexture { void ProcessFrame(PaintContext& context, const SkRect& bounds) override; void Detach() override; - sk_sp FindImage(uint64_t key); - - void UpdateKey(uint64_t key); - - void AddImage(sk_sp image, uint64_t key); - const std::shared_ptr impeller_context_; fml::jni::ScopedJavaGlobalRef android_image_; - - std::array>, - kImageReaderSwapchainSize> - images_ = {std::make_pair(0, nullptr), std::make_pair(0, nullptr), - std::make_pair(0, nullptr)}; - std::array keys_ = {0, 0, 0}; }; } // namespace flutter diff --git a/shell/platform/android/ndk_helpers.cc b/shell/platform/android/ndk_helpers.cc index 3b0d95cae081f..1c20cccd8896c 100644 --- a/shell/platform/android/ndk_helpers.cc +++ b/shell/platform/android/ndk_helpers.cc @@ -116,11 +116,12 @@ void NDKHelpers::AHardwareBuffer_describe(AHardwareBuffer* buffer, _AHardwareBuffer_describe(buffer, desc); } -void NDKHelpers::AHardwareBuffer_getId(AHardwareBuffer* buffer, - uint64_t* outId) { +uint64_t NDKHelpers::AHardwareBuffer_getId(AHardwareBuffer* buffer) { NDKHelpers::Init(); FML_CHECK(_AHardwareBuffer_getId != nullptr); - _AHardwareBuffer_getId(buffer, outId); + uint64_t outId; + _AHardwareBuffer_getId(buffer, &outId); + return outId; } EGLClientBuffer NDKHelpers::eglGetNativeClientBufferANDROID( diff --git a/shell/platform/android/ndk_helpers.h b/shell/platform/android/ndk_helpers.h index 83ae51360af1a..505470128e4cf 100644 --- a/shell/platform/android/ndk_helpers.h +++ b/shell/platform/android/ndk_helpers.h @@ -27,7 +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 uint64_t AHardwareBuffer_getId(AHardwareBuffer* buffer); static EGLClientBuffer eglGetNativeClientBufferANDROID( AHardwareBuffer* buffer); From 164d8d97e83bcf7fde2c3771f0c5139d7c0a0371 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 15:31:56 -0800 Subject: [PATCH 05/17] wip changes. --- .../android/image_external_texture.cc | 33 +++++++++++-------- .../platform/android/image_external_texture.h | 11 +++++-- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index ce5b3bf38b11f..1cc410e02bf59 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -60,36 +60,37 @@ void ImageExternalTexture::OnGrContextCreated() { } sk_sp ImageExternalTexture::FindImage(uint64_t key) { - for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { if (images_[i].key == key) { - UpdateKey(key); - return images_[i].image; + auto result = images_[i].image; + UpdateKey(result, key); + return result; } } return nullptr; } -void ImageExternalTexture::UpdateKey(uint64_t key) { - if (keys_[0] == key) { +void ImageExternalTexture::UpdateKey(const sk_sp& image, + uint64_t key) { + if (images_[0].key == key) { return; } - auto i = 1u; + size_t i = 1u; for (; i < kImageReaderSwapchainSize; i++) { - if (keys_[i] == key) { + if (images_[i].key == key) { break; } } for (auto j = i; j > 0; j--) { - keys_[j] = keys_[j - 1]; + images_[j] = images_[j - 1]; } - keys_[0] = key; } void ImageExternalTexture::AddImage(const sk_sp& image, uint64_t key) { - uint64_t lru_key = keys_[kImageReaderSwapchainSize - 1]; + uint64_t lru_key = images_[kImageReaderSwapchainSize - 1].key; bool updated_image = false; - for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { if (images_[i].key == lru_key) { updated_image = true; images_[i] = LRUImage{.key = key, .image = image}; @@ -97,16 +98,22 @@ void ImageExternalTexture::AddImage(const sk_sp& image, } } if (!updated_image) { - keys_[0] = key; images_[0] = LRUImage{.key = key, .image = image}; } - UpdateKey(key); + UpdateKey(image, key); +} + +void ImageExternalTexture::ResetCache() { + for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { + images_[i] = {.key = 0u, .image = nullptr}; + } } // Implementing flutter::ContextListener. void ImageExternalTexture::OnGrContextDestroyed() { if (state_ == AttachmentState::kAttached) { dl_image_.reset(); + ResetCache(); Detach(); } state_ = AttachmentState::kDetached; diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index 705bba2d52ff1..0cf692f5e747f 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -15,7 +15,12 @@ namespace flutter { -static constexpr size_t kImageReaderSwapchainSize = 3u; +// This value needs to be larger than the number of swapchain images +// that a typical image reader will produce to ensure that we effectively +// cache. If the value is too small, we will unnecessarily churn through +// images, while if it is too large we may retain images longer than +// necessary. +static constexpr size_t kImageReaderSwapchainSize = 6u; // External texture peered to a sequence of android.hardware.HardwareBuffers. // @@ -52,8 +57,9 @@ class ImageExternalTexture : public flutter::Texture { virtual void ProcessFrame(PaintContext& context, const SkRect& bounds) = 0; sk_sp FindImage(uint64_t key); - void UpdateKey(uint64_t key); + void UpdateKey(const sk_sp& image, uint64_t key); void AddImage(const sk_sp& image, uint64_t key); + void ResetCache(); struct LRUImage { uint64_t key; @@ -78,7 +84,6 @@ class ImageExternalTexture : public flutter::Texture { LRUImage{.key = 0, .image = nullptr}, LRUImage{.key = 0, .image = nullptr}, }; - std::array keys_ = {0, 0, 0}; sk_sp dl_image_; From 8e7937626a62b6a139f795ade1d78d3240ba4ee3 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 17:02:13 -0800 Subject: [PATCH 06/17] combine implementations. --- .../android/image_external_texture_gl.cc | 126 ++++++------------ .../android/image_external_texture_gl.h | 10 +- .../android/image_external_texture_vk.cc | 8 +- 3 files changed, 53 insertions(+), 91 deletions(-) diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index 85658c546a05b..d1b3529cca7e3 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -47,6 +47,48 @@ void ImageExternalTextureGL::Attach(PaintContext& context) { } } +void ImageExternalTextureGL::ProcessFrame(PaintContext& context, + const SkRect& bounds) { + JavaLocalRef image = AcquireLatestImage(); + if (image.is_null()) { + return; + } + + // NOTE: In the following code it is important that old_android_image is + // not closed until after the update of egl_image_ otherwise the image might + // be closed before the old EGLImage referencing it has been deleted. After + // an image is closed the underlying HardwareBuffer may be recycled and used + // for a future frame. + JavaLocalRef old_android_image(android_image_); + android_image_.Reset(image); + JavaLocalRef hardware_buffer = HardwareBufferFor(image); + AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); + auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); + auto existing_image = FindImage(key); + if (existing_image != nullptr) { + dl_image_ = existing_image; + + CloseHardwareBuffer(hardware_buffer); + // IMPORTANT: We have just received a new frame to display so close the + // previous Java Image so that it is recycled and used for a future frame. + CloseImage(old_android_image); + return; + } + + egl_image_ = CreateEGLImage(latest_hardware_buffer); + CloseHardwareBuffer(hardware_buffer); + // IMPORTANT: We have just received a new frame to display so close the + // previous Java Image so that it is recycled and used for a future frame. + CloseImage(old_android_image); + + if (!egl_image_.is_valid()) { + return; + } + + dl_image_ = CreateDlImage(context, bounds); + AddImage(dl_image_, key); +} + void ImageExternalTextureGL::Detach() { egl_image_.reset(); } @@ -100,49 +142,6 @@ void ImageExternalTextureGLSkia::Detach() { texture_.reset(); } -void ImageExternalTextureGLSkia::ProcessFrame(PaintContext& context, - const SkRect& bounds) { - JavaLocalRef image = AcquireLatestImage(); - if (image.is_null()) { - return; - } - - // NOTE: In the following code it is important that old_android_image is - // not closed until after the update of egl_image_ otherwise the image might - // be closed before the old EGLImage referencing it has been deleted. After - // an image is closed the underlying HardwareBuffer may be recycled and used - // for a future frame. - JavaLocalRef old_android_image(android_image_); - android_image_.Reset(image); - JavaLocalRef hardware_buffer = HardwareBufferFor(image); - AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); - auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); - auto existing_image = FindImage(key); - if (existing_image != nullptr) { - dl_image_ = existing_image; - - CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We only close the old image after texture stops referencing - // it. - CloseImage(old_android_image); - return; - } - - egl_image_ = CreateEGLImage(latest_hardware_buffer); - CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We only close the old image after egl_image_ stops referencing - // it. - CloseImage(old_android_image); - - if (!egl_image_.is_valid()) { - return; - } - - BindImageToTexture(egl_image_, texture_.get().texture_name); - dl_image_ = CreateDlImage(context, bounds); - AddImage(dl_image_, key); -} - void ImageExternalTextureGLSkia::BindImageToTexture( const impeller::UniqueEGLImageKHR& image, GLuint tex) { @@ -157,6 +156,7 @@ void ImageExternalTextureGLSkia::BindImageToTexture( sk_sp ImageExternalTextureGLSkia::CreateDlImage( PaintContext& context, const SkRect& bounds) { + BindImageToTexture(egl_image_, texture_.get().texture_name); GrGLTextureInfo textureInfo = {GL_TEXTURE_EXTERNAL_OES, texture_.get().texture_name, GL_RGBA8_OES}; auto backendTexture = @@ -182,46 +182,6 @@ void ImageExternalTextureGLImpeller::Attach(PaintContext& context) { } } -void ImageExternalTextureGLImpeller::ProcessFrame(PaintContext& context, - const SkRect& bounds) { - JavaLocalRef image = AcquireLatestImage(); - if (image.is_null()) { - return; - } - // NOTE: In the following code it is important that old_android_image is - // not closed until after the update of egl_image_ otherwise the image might - // be closed before the old EGLImage referencing it has been deleted. After - // an image is closed the underlying HardwareBuffer may be recycled and used - // for a future frame. - JavaLocalRef old_android_image(android_image_); - android_image_.Reset(image); - JavaLocalRef hardware_buffer = HardwareBufferFor(image); - AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); - auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); - auto existing_image = FindImage(key); - if (existing_image != nullptr) { - dl_image_ = existing_image; - - CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We only close the old image after texture stops referencing - // it. - CloseImage(old_android_image); - return; - } - - egl_image_ = CreateEGLImage(latest_hardware_buffer); - CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We only close the old image after egl_image_ stops referencing - // it. - CloseImage(old_android_image); - if (!egl_image_.is_valid()) { - return; - } - - dl_image_ = CreateDlImage(context, bounds); - AddImage(dl_image_, key); -} - sk_sp ImageExternalTextureGLImpeller::CreateDlImage( PaintContext& context, const SkRect& bounds) { diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index 97159c15ebae2..9efccae7a9bd1 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -30,6 +30,10 @@ class ImageExternalTextureGL : public ImageExternalTexture { protected: void Attach(PaintContext& context) override; void Detach() override; + void ProcessFrame(PaintContext& context, const SkRect& bounds) override; + + virtual sk_sp CreateDlImage(PaintContext& context, + const SkRect& bounds) = 0; impeller::UniqueEGLImageKHR CreateEGLImage(AHardwareBuffer* buffer); @@ -50,11 +54,10 @@ class ImageExternalTextureGLSkia : public ImageExternalTextureGL { private: void Attach(PaintContext& context) override; void Detach() override; - void ProcessFrame(PaintContext& context, const SkRect& bounds) override; void BindImageToTexture(const impeller::UniqueEGLImageKHR& image, GLuint tex); sk_sp CreateDlImage(PaintContext& context, - const SkRect& bounds); + const SkRect& bounds) override; impeller::UniqueGLTexture texture_; @@ -72,11 +75,10 @@ class ImageExternalTextureGLImpeller : public ImageExternalTextureGL { private: void Attach(PaintContext& context) override; - void ProcessFrame(PaintContext& context, const SkRect& bounds) override; void Detach() override; sk_sp CreateDlImage(PaintContext& context, - const SkRect& bounds); + const SkRect& bounds) override; const std::shared_ptr impeller_context_; diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index 2165730a75b8a..abd19b4befe55 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -52,8 +52,8 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, dl_image_ = existing_image; CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We only close the old image after texture stops referencing - // it. + // IMPORTANT: We have just received a new frame to display so close the + // previous Java Image so that it is recycled and used for a future frame. CloseImage(old_android_image); return; } @@ -102,8 +102,8 @@ 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. + // IMPORTANT: We have just received a new frame to display so close the + // previous Java Image so that it is recycled and used for a future frame. CloseImage(old_android_image); } From bd9c66ecf2421cf37b73fa7977e6be0bd8ba4b9e Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 17:14:23 -0800 Subject: [PATCH 07/17] turn validation back on. --- impeller/renderer/backend/vulkan/context_vk.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/impeller/renderer/backend/vulkan/context_vk.cc b/impeller/renderer/backend/vulkan/context_vk.cc index d4bd9795aabd4..e573d6aa5bfb9 100644 --- a/impeller/renderer/backend/vulkan/context_vk.cc +++ b/impeller/renderer/backend/vulkan/context_vk.cc @@ -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 = false; // settings.enable_validation; + auto enable_validation = settings.enable_validation; #if defined(FML_OS_ANDROID) && !defined(NDEBUG) enable_validation = true; From fb136967d257d3843b4856a63b2c8ad17a156e62 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 20:03:03 -0800 Subject: [PATCH 08/17] make less jank --- .../android/image_external_texture.cc | 7 ++-- .../platform/android/image_external_texture.h | 4 +-- .../android/image_external_texture_gl.cc | 32 ++++++++++++------- .../android/image_external_texture_gl.h | 21 ++++++++---- 4 files changed, 42 insertions(+), 22 deletions(-) diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index 1a0776ba27900..84e931dd45d6b 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -85,7 +85,7 @@ void ImageExternalTexture::UpdateKey(const sk_sp& image, images_[0] = LRUImage{.key = key, .image = image}; } -void ImageExternalTexture::AddImage(const sk_sp& image, + uint64_t ImageExternalTexture::AddImage(const sk_sp& image, uint64_t key) { uint64_t lru_key = images_[kImageReaderSwapchainSize - 1].key; bool updated_image = false; @@ -100,9 +100,10 @@ void ImageExternalTexture::AddImage(const sk_sp& image, images_[0] = LRUImage{.key = key, .image = image}; } UpdateKey(image, key); + return lru_key; } -void ImageExternalTexture::ResetCache() { +void ImageExternalTexture::Clear() { for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { images_[i] = {.key = 0u, .image = nullptr}; } @@ -112,7 +113,7 @@ void ImageExternalTexture::ResetCache() { void ImageExternalTexture::OnGrContextDestroyed() { if (state_ == AttachmentState::kAttached) { dl_image_.reset(); - ResetCache(); + Clear(); Detach(); } state_ = AttachmentState::kDetached; diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index cb8db4ef45eee..ad8b98aebb5aa 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -58,8 +58,8 @@ class ImageExternalTexture : public flutter::Texture { sk_sp FindImage(uint64_t key); void UpdateKey(const sk_sp& image, uint64_t key); - void AddImage(const sk_sp& image, uint64_t key); - void ResetCache(); + uint64_t AddImage(const sk_sp& image, uint64_t key); + void Clear(); struct LRUImage { uint64_t key; diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index 77504f3512747..3bda0dc6b7b05 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -78,12 +78,13 @@ void ImageExternalTextureGL::ProcessFrame(PaintContext& context, return; } - dl_image_ = CreateDlImage(context, bounds, egl_image); - AddImage(dl_image_, key); + dl_image_ = CreateDlImage(context, bounds, key, std::move(egl_image)); + gl_entry_.erase(AddImage(dl_image_, key)); } void ImageExternalTextureGL::Detach() { // TODO: should we clear the cache in detach? + gl_entry_.clear(); } impeller::UniqueEGLImageKHR ImageExternalTextureGL::CreateEGLImage( @@ -124,15 +125,11 @@ void ImageExternalTextureGLSkia::Attach(PaintContext& context) { // After this call state_ will be AttachmentState::kAttached and egl_image_ // will have been created if we still have an Image associated with us. ImageExternalTextureGL::Attach(context); - GLuint texture_name; - glGenTextures(1, &texture_name); - texture_.reset(impeller::GLTexture{texture_name}); } } void ImageExternalTextureGLSkia::Detach() { ImageExternalTextureGL::Detach(); - texture_.reset(); } void ImageExternalTextureGLSkia::BindImageToTexture( @@ -149,12 +146,21 @@ void ImageExternalTextureGLSkia::BindImageToTexture( sk_sp ImageExternalTextureGLSkia::CreateDlImage( PaintContext& context, const SkRect& bounds, - impeller::UniqueEGLImageKHR& egl_image) { - BindImageToTexture(egl_image, texture_.get().texture_name); - GrGLTextureInfo textureInfo = {GL_TEXTURE_EXTERNAL_OES, - texture_.get().texture_name, GL_RGBA8_OES}; + uint64_t id, + impeller::UniqueEGLImageKHR&& egl_image) { + GLuint texture_name; + glGenTextures(1, &texture_name); + auto gl_texture = impeller::GLTexture{texture_name}; + impeller::UniqueGLTexture unique_texture; + unique_texture.reset(gl_texture); + + BindImageToTexture(egl_image, unique_texture.get().texture_name); + GrGLTextureInfo textureInfo = { + GL_TEXTURE_EXTERNAL_OES, unique_texture.get().texture_name, GL_RGBA8_OES}; auto backendTexture = GrBackendTextures::MakeGL(1, 1, skgpu::Mipmapped::kNo, textureInfo); + gl_entry_[id] = GlEntry{.egl_image = std::move(egl_image), + .texture = std::move(unique_texture)}; return DlImage::Make(SkImages::BorrowTextureFrom( context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)); @@ -179,7 +185,8 @@ void ImageExternalTextureGLImpeller::Attach(PaintContext& context) { sk_sp ImageExternalTextureGLImpeller::CreateDlImage( PaintContext& context, const SkRect& bounds, - impeller::UniqueEGLImageKHR& egl_image) { + uint64_t id, + impeller::UniqueEGLImageKHR&& egl_image) { impeller::TextureDescriptor desc; desc.type = impeller::TextureType::kTextureExternalOES; desc.storage_mode = impeller::StorageMode::kDevicePrivate; @@ -198,6 +205,9 @@ sk_sp ImageExternalTextureGLImpeller::CreateDlImage( // Associate the hardware buffer image with the texture. glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)egl_image.get().image); + gl_entry_[id] = GlEntry{ + .egl_image = std::move(egl_image), + }; return impeller::DlImageImpeller::Make(texture); } diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index 188aaef62b076..fc10112684851 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -5,6 +5,7 @@ #ifndef FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_GL_H_ #define FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_GL_H_ +#include #include "flutter/fml/platform/android/scoped_java_ref.h" #include "flutter/shell/platform/android/image_external_texture.h" @@ -35,12 +36,19 @@ class ImageExternalTextureGL : public ImageExternalTexture { virtual sk_sp CreateDlImage( PaintContext& context, const SkRect& bounds, - impeller::UniqueEGLImageKHR& egl_image) = 0; + uint64_t id, + impeller::UniqueEGLImageKHR&& egl_image) = 0; impeller::UniqueEGLImageKHR CreateEGLImage(AHardwareBuffer* buffer); fml::jni::ScopedJavaGlobalRef android_image_; - // impeller::UniqueEGLImageKHR egl_image_; + + struct GlEntry { + impeller::UniqueEGLImageKHR egl_image; + impeller::UniqueGLTexture texture; + }; + + std::unordered_map gl_entry_; FML_DISALLOW_COPY_AND_ASSIGN(ImageExternalTextureGL); }; @@ -58,12 +66,12 @@ class ImageExternalTextureGLSkia : public ImageExternalTextureGL { void Detach() override; void BindImageToTexture(const impeller::UniqueEGLImageKHR& image, GLuint tex); + sk_sp CreateDlImage( PaintContext& context, const SkRect& bounds, - impeller::UniqueEGLImageKHR& egl_image) override; - - impeller::UniqueGLTexture texture_; + uint64_t id, + impeller::UniqueEGLImageKHR&& egl_image) override; FML_DISALLOW_COPY_AND_ASSIGN(ImageExternalTextureGLSkia); }; @@ -84,7 +92,8 @@ class ImageExternalTextureGLImpeller : public ImageExternalTextureGL { sk_sp CreateDlImage( PaintContext& context, const SkRect& bounds, - impeller::UniqueEGLImageKHR& egl_image) override; + uint64_t id, + impeller::UniqueEGLImageKHR&& egl_image) override; const std::shared_ptr impeller_context_; From 7f02c53ba6eac56c4f39d9b9b66be3e894953080 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 20:03:47 -0800 Subject: [PATCH 09/17] ++ --- shell/platform/android/image_external_texture.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index 84e931dd45d6b..b3084916bfe70 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -85,8 +85,8 @@ void ImageExternalTexture::UpdateKey(const sk_sp& image, images_[0] = LRUImage{.key = key, .image = image}; } - uint64_t ImageExternalTexture::AddImage(const sk_sp& image, - uint64_t key) { +uint64_t ImageExternalTexture::AddImage(const sk_sp& image, + uint64_t key) { uint64_t lru_key = images_[kImageReaderSwapchainSize - 1].key; bool updated_image = false; for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { From c182e8aa0309f716ae175fe02e9bc51a5a715ec3 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 21:56:55 -0800 Subject: [PATCH 10/17] come on tests, lets get them tests. --- shell/platform/android/BUILD.gn | 3 + .../android/image_external_texture.cc | 54 +---------------- .../platform/android/image_external_texture.h | 23 +------ .../android/image_external_texture_gl.cc | 4 +- .../android/image_external_texture_vk.cc | 4 +- shell/platform/android/image_lru.cc | 60 +++++++++++++++++++ shell/platform/android/image_lru.h | 54 +++++++++++++++++ shell/platform/android/image_lru_unittests.cc | 57 ++++++++++++++++++ 8 files changed, 181 insertions(+), 78 deletions(-) create mode 100644 shell/platform/android/image_lru.cc create mode 100644 shell/platform/android/image_lru.h create mode 100644 shell/platform/android/image_lru_unittests.cc diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index f1fdf7c4ae75b..52e33e975c089 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -48,6 +48,7 @@ executable("flutter_shell_native_unittests") { "apk_asset_provider_unittests.cc", "flutter_shell_native_unittests.cc", "platform_view_android_unittests.cc", + "image_lru_unittests.cc", ] public_configs = [ "//flutter:config" ] deps = [ @@ -111,6 +112,8 @@ source_set("flutter_shell_native_src") { "image_external_texture_gl.h", "image_external_texture_vk.cc", "image_external_texture_vk.h", + "image_lru.h", + "image_lru.cc", "library_loader.cc", "ndk_helpers.cc", "ndk_helpers.h", diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index b3084916bfe70..86e0f69031fb8 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -57,63 +57,11 @@ void ImageExternalTexture::OnGrContextCreated() { state_ = AttachmentState::kUninitialized; } -sk_sp ImageExternalTexture::FindImage(uint64_t key) { - for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { - if (images_[i].key == key) { - auto result = images_[i].image; - UpdateKey(result, key); - return result; - } - } - return nullptr; -} - -void ImageExternalTexture::UpdateKey(const sk_sp& image, - uint64_t key) { - if (images_[0].key == key) { - return; - } - size_t i = 1u; - for (; i < kImageReaderSwapchainSize; i++) { - if (images_[i].key == key) { - break; - } - } - for (auto j = i; j > 0; j--) { - images_[j] = images_[j - 1]; - } - images_[0] = LRUImage{.key = key, .image = image}; -} - -uint64_t ImageExternalTexture::AddImage(const sk_sp& image, - uint64_t key) { - uint64_t lru_key = images_[kImageReaderSwapchainSize - 1].key; - bool updated_image = false; - for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { - if (images_[i].key == lru_key) { - updated_image = true; - images_[i] = LRUImage{.key = key, .image = image}; - break; - } - } - if (!updated_image) { - images_[0] = LRUImage{.key = key, .image = image}; - } - UpdateKey(image, key); - return lru_key; -} - -void ImageExternalTexture::Clear() { - for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { - images_[i] = {.key = 0u, .image = nullptr}; - } -} - // Implementing flutter::ContextListener. void ImageExternalTexture::OnGrContextDestroyed() { if (state_ == AttachmentState::kAttached) { dl_image_.reset(); - Clear(); + image_lru_.Clear(); Detach(); } state_ = AttachmentState::kDetached; diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index ad8b98aebb5aa..b6f68fdc3bac1 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -9,19 +9,13 @@ #include "flutter/fml/logging.h" #include "flutter/shell/platform/android/jni/platform_view_android_jni.h" #include "flutter/shell/platform/android/platform_view_android_jni_impl.h" +#include "flutter/shell/platform/android/image_lru.h" #include #include namespace flutter { -// This value needs to be larger than the number of swapchain images -// that a typical image reader will produce to ensure that we effectively -// cache. If the value is too small, we will unnecessarily churn through -// images, while if it is too large we may retain images longer than -// necessary. -static constexpr size_t kImageReaderSwapchainSize = 6u; - // External texture peered to a sequence of android.hardware.HardwareBuffers. // class ImageExternalTexture : public flutter::Texture { @@ -56,16 +50,6 @@ class ImageExternalTexture : public flutter::Texture { virtual void Detach() = 0; virtual void ProcessFrame(PaintContext& context, const SkRect& bounds) = 0; - sk_sp FindImage(uint64_t key); - void UpdateKey(const sk_sp& image, uint64_t key); - uint64_t AddImage(const sk_sp& image, uint64_t key); - void Clear(); - - struct LRUImage { - uint64_t key; - sk_sp image; - }; - JavaLocalRef AcquireLatestImage(); void CloseImage(const fml::jni::JavaRef& image); JavaLocalRef HardwareBufferFor(const fml::jni::JavaRef& image); @@ -79,11 +63,8 @@ class ImageExternalTexture : public flutter::Texture { enum class AttachmentState { kUninitialized, kAttached, kDetached }; AttachmentState state_ = AttachmentState::kUninitialized; bool new_frame_ready_ = false; - std::array images_ = { - LRUImage{0, nullptr}, LRUImage{0, nullptr}, LRUImage{0, nullptr}, - LRUImage{0, nullptr}, LRUImage{0, nullptr}, LRUImage{0, nullptr}, - }; sk_sp dl_image_; + ImageLRU image_lru_ = ImageLRU(); FML_DISALLOW_COPY_AND_ASSIGN(ImageExternalTexture); }; diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index 3bda0dc6b7b05..41695e2e19132 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -57,7 +57,7 @@ void ImageExternalTextureGL::ProcessFrame(PaintContext& context, JavaLocalRef hardware_buffer = HardwareBufferFor(image); AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); - auto existing_image = FindImage(key); + auto existing_image = image_lru_.FindImage(key); if (existing_image != nullptr) { dl_image_ = existing_image; @@ -79,7 +79,7 @@ void ImageExternalTextureGL::ProcessFrame(PaintContext& context, } dl_image_ = CreateDlImage(context, bounds, key, std::move(egl_image)); - gl_entry_.erase(AddImage(dl_image_, key)); + gl_entry_.erase(image_lru_.AddImage(dl_image_, key)); } void ImageExternalTextureGL::Detach() { diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index abd19b4befe55..6065fbef6941e 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -47,7 +47,7 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, flutter::NDKHelpers::AHardwareBuffer_describe(latest_hardware_buffer, &hb_desc); auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); - auto existing_image = FindImage(key); + auto existing_image = image_lru_.FindImage(key); if (existing_image != nullptr) { dl_image_ = existing_image; @@ -100,7 +100,7 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, } dl_image_ = impeller::DlImageImpeller::Make(texture); - AddImage(dl_image_, key); + image_lru_.AddImage(dl_image_, key); CloseHardwareBuffer(hardware_buffer); // IMPORTANT: We have just received a new frame to display so close the // previous Java Image so that it is recycled and used for a future frame. diff --git a/shell/platform/android/image_lru.cc b/shell/platform/android/image_lru.cc new file mode 100644 index 0000000000000..992b582dccbd3 --- /dev/null +++ b/shell/platform/android/image_lru.cc @@ -0,0 +1,60 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/android/image_lru.h" + +namespace flutter { + +sk_sp ImageLRU::FindImage(uint64_t key) { + for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { + if (images_[i].key == key) { + auto result = images_[i].value; + UpdateKey(result, key); + return result; + } + } + return nullptr; +} + +void ImageLRU::UpdateKey(const sk_sp& image, uint64_t key) { + if (images_[0].key == key) { + return; + } + size_t i = 1u; + for (; i < kImageReaderSwapchainSize; i++) { + if (images_[i].key == key) { + break; + } + } + for (auto j = i; j > 0; j--) { + images_[j] = images_[j - 1]; + } + images_[0] = Data{.key = key, .value = image}; +} + +uint64_t ImageLRU::AddImage(const sk_sp& image, + uint64_t key) { + uint64_t lru_key = images_[kImageReaderSwapchainSize - 1].key; + bool updated_image = false; + for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { + if (images_[i].key == lru_key) { + updated_image = true; + images_[i] = Data{.key = key, .value = image}; + break; + } + } + if (!updated_image) { + images_[0] = Data{.key = key, .value = image}; + } + UpdateKey(image, key); + return lru_key; +} + +void ImageLRU::Clear() { + for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { + images_[i] = Data{.key = 0u, .value = nullptr}; + } +} + +} // namespace flutter diff --git a/shell/platform/android/image_lru.h b/shell/platform/android/image_lru.h new file mode 100644 index 0000000000000..8ae0dda5b82e4 --- /dev/null +++ b/shell/platform/android/image_lru.h @@ -0,0 +1,54 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_LRU_H_ +#define FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_LRU_H_ + +#include +#include + +#include "display_list/image/dl_image.h" + +namespace flutter { + +// This value needs to be larger than the number of swapchain images +// that a typical image reader will produce to ensure that we effectively +// cache. If the value is too small, we will unnecessarily churn through +// images, while if it is too large we may retain images longer than +// necessary. +static constexpr size_t kImageReaderSwapchainSize = 6u; + +class ImageLRU { + public: + ImageLRU() { Clear(); } + + ~ImageLRU() = default; + + /// @brief Retrieve the image associated with the given [key], or nullptr. + sk_sp FindImage(uint64_t key); + + /// @brief Add a new image to the cache with a key, returning the key of the + /// LRU entry that was removed. + /// + /// The value may be `0`, in which case nothing was removed. + uint64_t AddImage(const sk_sp& image, uint64_t key); + + /// @brief Remove all entires from the image cache. + void Clear(); + + private: + /// @brief Marks [key] as the most recently used. + void UpdateKey(const sk_sp& image, uint64_t key); + + struct Data { + uint64_t key; + sk_sp value; + }; + + std::array images_; +}; + +} // namespace flutter + +#endif // FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_LRU_H_ diff --git a/shell/platform/android/image_lru_unittests.cc b/shell/platform/android/image_lru_unittests.cc new file mode 100644 index 0000000000000..d97edfdffc5f7 --- /dev/null +++ b/shell/platform/android/image_lru_unittests.cc @@ -0,0 +1,57 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/shell/platform/android/image_lru.h" +#include "gtest/gtest.h" + +namespace flutter { +namespace testing { + +TEST(ImageLRU, CanStoreSingleImage) { + auto image = DlImage::Make(nullptr); + ImageLRU image_lru; + + EXPECT_EQ(image_lru.FindImage(1), nullptr); + + image_lru.AddImage(image, 1); + + EXPECT_EQ(image_lru.FindImage(1), image); +} + +TEST(ImageLRU, EvictsLRU) { + auto image = DlImage::Make(nullptr); + ImageLRU image_lru; + + // Fill up the cache, nothing is removed + for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + EXPECT_EQ(image_lru.AddImage(image, i + 1), 0u); + } + // Confirm each image is in the cache. This should keep the LRU + // order the same. + for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + EXPECT_EQ(image_lru.FindImage(i + 1), image); + } + + // Insert new image and verify least recently used was removed. + EXPECT_EQ(image_lru.AddImage(image, 100), 1u); +} + +TEST(ImageLRU, CanClear) { + auto image = DlImage::Make(nullptr); + ImageLRU image_lru; + + // Fill up the cache, nothing is removed + for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + EXPECT_EQ(image_lru.AddImage(image, i + 1), 0u); + } + image_lru.Clear(); + + // Expect no cache entries. + for (auto i = 0u; i < kImageReaderSwapchainSize; i++) { + EXPECT_EQ(image_lru.FindImage(i + 1), nullptr); + } +} + +} // namespace testing +} // namespace flutter From 9700b00ba6099e821e9d9cd22101c1367ad3e044 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 21:57:24 -0800 Subject: [PATCH 11/17] ++ --- shell/platform/android/BUILD.gn | 4 ++-- shell/platform/android/image_external_texture.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/platform/android/BUILD.gn b/shell/platform/android/BUILD.gn index 52e33e975c089..f850d83ab8f0b 100644 --- a/shell/platform/android/BUILD.gn +++ b/shell/platform/android/BUILD.gn @@ -47,8 +47,8 @@ executable("flutter_shell_native_unittests") { "android_shell_holder_unittests.cc", "apk_asset_provider_unittests.cc", "flutter_shell_native_unittests.cc", - "platform_view_android_unittests.cc", "image_lru_unittests.cc", + "platform_view_android_unittests.cc", ] public_configs = [ "//flutter:config" ] deps = [ @@ -112,8 +112,8 @@ source_set("flutter_shell_native_src") { "image_external_texture_gl.h", "image_external_texture_vk.cc", "image_external_texture_vk.h", - "image_lru.h", "image_lru.cc", + "image_lru.h", "library_loader.cc", "ndk_helpers.cc", "ndk_helpers.h", diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index b6f68fdc3bac1..40162460d755f 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -7,9 +7,9 @@ #include "flutter/common/graphics/texture.h" #include "flutter/fml/logging.h" +#include "flutter/shell/platform/android/image_lru.h" #include "flutter/shell/platform/android/jni/platform_view_android_jni.h" #include "flutter/shell/platform/android/platform_view_android_jni_impl.h" -#include "flutter/shell/platform/android/image_lru.h" #include #include From 7bca7c77760892b66ea4d5d5f5e4fd1d9f6c93ff Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 22:28:10 -0800 Subject: [PATCH 12/17] code review. --- shell/platform/android/image_external_texture_gl.cc | 7 ++++--- shell/platform/android/image_external_texture_gl.h | 11 +++++++---- shell/platform/android/image_lru.cc | 11 ++++++----- shell/platform/android/image_lru.h | 12 +++++++----- shell/platform/android/ndk_helpers.cc | 4 ++-- shell/platform/android/ndk_helpers.h | 4 +++- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index 41695e2e19132..c8c9e133fb9ca 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -56,7 +56,8 @@ void ImageExternalTextureGL::ProcessFrame(PaintContext& context, android_image_.Reset(image); JavaLocalRef hardware_buffer = HardwareBufferFor(image); AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); - auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); + HardwareBufferKey key = + flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); auto existing_image = image_lru_.FindImage(key); if (existing_image != nullptr) { dl_image_ = existing_image; @@ -146,7 +147,7 @@ void ImageExternalTextureGLSkia::BindImageToTexture( sk_sp ImageExternalTextureGLSkia::CreateDlImage( PaintContext& context, const SkRect& bounds, - uint64_t id, + HardwareBufferKey id, impeller::UniqueEGLImageKHR&& egl_image) { GLuint texture_name; glGenTextures(1, &texture_name); @@ -185,7 +186,7 @@ void ImageExternalTextureGLImpeller::Attach(PaintContext& context) { sk_sp ImageExternalTextureGLImpeller::CreateDlImage( PaintContext& context, const SkRect& bounds, - uint64_t id, + HardwareBufferKey id, impeller::UniqueEGLImageKHR&& egl_image) { impeller::TextureDescriptor desc; desc.type = impeller::TextureType::kTextureExternalOES; diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index fc10112684851..d372233a9841f 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -36,7 +36,7 @@ class ImageExternalTextureGL : public ImageExternalTexture { virtual sk_sp CreateDlImage( PaintContext& context, const SkRect& bounds, - uint64_t id, + HardwareBufferKey id, impeller::UniqueEGLImageKHR&& egl_image) = 0; impeller::UniqueEGLImageKHR CreateEGLImage(AHardwareBuffer* buffer); @@ -48,7 +48,10 @@ class ImageExternalTextureGL : public ImageExternalTexture { impeller::UniqueGLTexture texture; }; - std::unordered_map gl_entry_; + // Each GL entry is keyed off of the currently active + // hardware buffers and evicted when the hardware buffer + // is removed from the LRU cache. + std::unordered_map gl_entry_; FML_DISALLOW_COPY_AND_ASSIGN(ImageExternalTextureGL); }; @@ -70,7 +73,7 @@ class ImageExternalTextureGLSkia : public ImageExternalTextureGL { sk_sp CreateDlImage( PaintContext& context, const SkRect& bounds, - uint64_t id, + HardwareBufferKey id, impeller::UniqueEGLImageKHR&& egl_image) override; FML_DISALLOW_COPY_AND_ASSIGN(ImageExternalTextureGLSkia); @@ -92,7 +95,7 @@ class ImageExternalTextureGLImpeller : public ImageExternalTextureGL { sk_sp CreateDlImage( PaintContext& context, const SkRect& bounds, - uint64_t id, + HardwareBufferKey id, impeller::UniqueEGLImageKHR&& egl_image) override; const std::shared_ptr impeller_context_; diff --git a/shell/platform/android/image_lru.cc b/shell/platform/android/image_lru.cc index 992b582dccbd3..2d0317d8cfd0a 100644 --- a/shell/platform/android/image_lru.cc +++ b/shell/platform/android/image_lru.cc @@ -6,7 +6,7 @@ namespace flutter { -sk_sp ImageLRU::FindImage(uint64_t key) { +sk_sp ImageLRU::FindImage(HardwareBufferKey key) { for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { if (images_[i].key == key) { auto result = images_[i].value; @@ -17,7 +17,8 @@ sk_sp ImageLRU::FindImage(uint64_t key) { return nullptr; } -void ImageLRU::UpdateKey(const sk_sp& image, uint64_t key) { +void ImageLRU::UpdateKey(const sk_sp& image, + HardwareBufferKey key) { if (images_[0].key == key) { return; } @@ -33,9 +34,9 @@ void ImageLRU::UpdateKey(const sk_sp& image, uint64_t key) { images_[0] = Data{.key = key, .value = image}; } -uint64_t ImageLRU::AddImage(const sk_sp& image, - uint64_t key) { - uint64_t lru_key = images_[kImageReaderSwapchainSize - 1].key; +HardwareBufferKey ImageLRU::AddImage(const sk_sp& image, + HardwareBufferKey key) { + HardwareBufferKey lru_key = images_[kImageReaderSwapchainSize - 1].key; bool updated_image = false; for (size_t i = 0u; i < kImageReaderSwapchainSize; i++) { if (images_[i].key == lru_key) { diff --git a/shell/platform/android/image_lru.h b/shell/platform/android/image_lru.h index 8ae0dda5b82e4..ac9391b0406e0 100644 --- a/shell/platform/android/image_lru.h +++ b/shell/platform/android/image_lru.h @@ -9,6 +9,7 @@ #include #include "display_list/image/dl_image.h" +#include "shell/platform/android/ndk_helpers.h" namespace flutter { @@ -21,28 +22,29 @@ static constexpr size_t kImageReaderSwapchainSize = 6u; class ImageLRU { public: - ImageLRU() { Clear(); } + ImageLRU() = default; ~ImageLRU() = default; /// @brief Retrieve the image associated with the given [key], or nullptr. - sk_sp FindImage(uint64_t key); + sk_sp FindImage(HardwareBufferKey key); /// @brief Add a new image to the cache with a key, returning the key of the /// LRU entry that was removed. /// /// The value may be `0`, in which case nothing was removed. - uint64_t AddImage(const sk_sp& image, uint64_t key); + HardwareBufferKey AddImage(const sk_sp& image, + HardwareBufferKey key); /// @brief Remove all entires from the image cache. void Clear(); private: /// @brief Marks [key] as the most recently used. - void UpdateKey(const sk_sp& image, uint64_t key); + void UpdateKey(const sk_sp& image, HardwareBufferKey key); struct Data { - uint64_t key; + HardwareBufferKey key = 0u; sk_sp value; }; diff --git a/shell/platform/android/ndk_helpers.cc b/shell/platform/android/ndk_helpers.cc index 1c20cccd8896c..2c7db68ccf8b0 100644 --- a/shell/platform/android/ndk_helpers.cc +++ b/shell/platform/android/ndk_helpers.cc @@ -116,10 +116,10 @@ void NDKHelpers::AHardwareBuffer_describe(AHardwareBuffer* buffer, _AHardwareBuffer_describe(buffer, desc); } -uint64_t NDKHelpers::AHardwareBuffer_getId(AHardwareBuffer* buffer) { +HardwareBufferKey NDKHelpers::AHardwareBuffer_getId(AHardwareBuffer* buffer) { NDKHelpers::Init(); FML_CHECK(_AHardwareBuffer_getId != nullptr); - uint64_t outId; + HardwareBufferKey outId; _AHardwareBuffer_getId(buffer, &outId); return outId; } diff --git a/shell/platform/android/ndk_helpers.h b/shell/platform/android/ndk_helpers.h index 505470128e4cf..56db0e478c0b2 100644 --- a/shell/platform/android/ndk_helpers.h +++ b/shell/platform/android/ndk_helpers.h @@ -14,6 +14,8 @@ namespace flutter { +using HardwareBufferKey = uint64_t; + // A collection of NDK functions that are available depending on the version of // the Android SDK we are linked with at runtime. class NDKHelpers { @@ -27,7 +29,7 @@ class NDKHelpers { static void AHardwareBuffer_release(AHardwareBuffer* buffer); static void AHardwareBuffer_describe(AHardwareBuffer* buffer, AHardwareBuffer_Desc* desc); - static uint64_t AHardwareBuffer_getId(AHardwareBuffer* buffer); + static HardwareBufferKey AHardwareBuffer_getId(AHardwareBuffer* buffer); static EGLClientBuffer eglGetNativeClientBufferANDROID( AHardwareBuffer* buffer); From 2c920d8c39569d244fa702e2bd2216d994abee76 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 22:31:17 -0800 Subject: [PATCH 13/17] remove unused field. --- shell/platform/android/image_external_texture.h | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index 40162460d755f..02ccdd91394db 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -62,7 +62,6 @@ class ImageExternalTexture : public flutter::Texture { enum class AttachmentState { kUninitialized, kAttached, kDetached }; AttachmentState state_ = AttachmentState::kUninitialized; - bool new_frame_ready_ = false; sk_sp dl_image_; ImageLRU image_lru_ = ImageLRU(); From 221e0daf10fe2bd5b7512fee9112d525d3ce2325 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Thu, 25 Jan 2024 22:32:09 -0800 Subject: [PATCH 14/17] ++ --- shell/platform/android/image_external_texture_vk.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index 6065fbef6941e..70a03986af90b 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -46,7 +46,8 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, AHardwareBuffer_Desc hb_desc = {}; flutter::NDKHelpers::AHardwareBuffer_describe(latest_hardware_buffer, &hb_desc); - auto key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); + HardwareBufferKey key = + flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); auto existing_image = image_lru_.FindImage(key); if (existing_image != nullptr) { dl_image_ = existing_image; From 26d6c1d99e31d04682605436b325c7abdfd325cf Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 26 Jan 2024 09:57:47 -0800 Subject: [PATCH 15/17] clear gl cache and restore on attach. --- ci/licenses_golden/excluded_files | 1 + ci/licenses_golden/licenses_flutter | 4 +++ .../android/image_external_texture.cc | 1 + .../platform/android/image_external_texture.h | 1 + .../android/image_external_texture_gl.cc | 33 +++++++++++++++---- .../android/image_external_texture_gl.h | 2 +- 6 files changed, 35 insertions(+), 7 deletions(-) diff --git a/ci/licenses_golden/excluded_files b/ci/licenses_golden/excluded_files index 44c5a060fe4b5..47d59fca4b1a0 100644 --- a/ci/licenses_golden/excluded_files +++ b/ci/licenses_golden/excluded_files @@ -282,6 +282,7 @@ ../../../flutter/shell/platform/android/external_view_embedder/surface_pool_unittests.cc ../../../flutter/shell/platform/android/flutter_shell_native_unittests.cc ../../../flutter/shell/platform/android/gradle.properties +../../../flutter/shell/platform/android/image_lru_unittests.cc ../../../flutter/shell/platform/android/jni/jni_mock_unittest.cc ../../../flutter/shell/platform/android/platform_view_android_delegate/platform_view_android_delegate_unittests.cc ../../../flutter/shell/platform/android/platform_view_android_unittests.cc diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 9836b81f49751..ec69356c3241d 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -6347,6 +6347,8 @@ ORIGIN: ../../../flutter/shell/platform/android/image_external_texture.h + ../.. ORIGIN: ../../../flutter/shell/platform/android/image_external_texture_gl.cc + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/image_external_texture_gl.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/image_external_texture_vk.h + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/image_lru.cc + ../../../flutter/LICENSE +ORIGIN: ../../../flutter/shell/platform/android/image_lru.h + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/BuildConfig.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/FlutterInjector.java + ../../../flutter/LICENSE ORIGIN: ../../../flutter/shell/platform/android/io/flutter/Log.java + ../../../flutter/LICENSE @@ -9203,6 +9205,8 @@ FILE: ../../../flutter/shell/platform/android/image_external_texture_gl.cc FILE: ../../../flutter/shell/platform/android/image_external_texture_gl.h FILE: ../../../flutter/shell/platform/android/image_external_texture_vk.cc FILE: ../../../flutter/shell/platform/android/image_external_texture_vk.h +FILE: ../../../flutter/shell/platform/android/image_lru.cc +FILE: ../../../flutter/shell/platform/android/image_lru.h FILE: ../../../flutter/shell/platform/android/io/flutter/BuildConfig.java FILE: ../../../flutter/shell/platform/android/io/flutter/FlutterInjector.java FILE: ../../../flutter/shell/platform/android/io/flutter/Log.java diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index 86e0f69031fb8..ba0f25f5a0016 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -25,6 +25,7 @@ void ImageExternalTexture::Paint(PaintContext& context, if (state_ == AttachmentState::kDetached) { return; } + last_bounds_ = bounds; Attach(context); const bool should_process_frame = !freeze; if (should_process_frame) { diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index 02ccdd91394db..34ca3585d122f 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -59,6 +59,7 @@ class ImageExternalTexture : public flutter::Texture { fml::jni::ScopedJavaGlobalRef image_texture_entry_; std::shared_ptr jni_facade_; + SkRect last_bounds_ = SkRect::MakeEmpty(); enum class AttachmentState { kUninitialized, kAttached, kDetached }; AttachmentState state_ = AttachmentState::kUninitialized; diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index c8c9e133fb9ca..eb07e56ab2780 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -36,6 +36,27 @@ ImageExternalTextureGL::ImageExternalTextureGL( void ImageExternalTextureGL::Attach(PaintContext& context) { if (state_ == AttachmentState::kUninitialized) { + if (!android_image_.is_null() && !last_bounds_.isEmpty()) { + // After detach the cache of textures will have been cleared. If + // there is an android image we must populate it now so that the + // first frame isn't blank. + JavaLocalRef hardware_buffer = HardwareBufferFor(android_image_); + AHardwareBuffer* latest_hardware_buffer = + AHardwareBufferFor(hardware_buffer); + HardwareBufferKey key = + flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); + + auto egl_image = CreateEGLImage(latest_hardware_buffer); + CloseHardwareBuffer(hardware_buffer); + + if (!egl_image.is_valid()) { + return; + } + + dl_image_ = + CreateDlImage(context, last_bounds_, key, std::move(egl_image)); + gl_entries_.erase(image_lru_.AddImage(dl_image_, key)); + } state_ = AttachmentState::kAttached; } } @@ -80,12 +101,12 @@ void ImageExternalTextureGL::ProcessFrame(PaintContext& context, } dl_image_ = CreateDlImage(context, bounds, key, std::move(egl_image)); - gl_entry_.erase(image_lru_.AddImage(dl_image_, key)); + gl_entries_.erase(image_lru_.AddImage(dl_image_, key)); } void ImageExternalTextureGL::Detach() { - // TODO: should we clear the cache in detach? - gl_entry_.clear(); + image_lru_.Clear(); + gl_entries_.clear(); } impeller::UniqueEGLImageKHR ImageExternalTextureGL::CreateEGLImage( @@ -160,8 +181,8 @@ sk_sp ImageExternalTextureGLSkia::CreateDlImage( GL_TEXTURE_EXTERNAL_OES, unique_texture.get().texture_name, GL_RGBA8_OES}; auto backendTexture = GrBackendTextures::MakeGL(1, 1, skgpu::Mipmapped::kNo, textureInfo); - gl_entry_[id] = GlEntry{.egl_image = std::move(egl_image), - .texture = std::move(unique_texture)}; + gl_entries_[id] = GlEntry{.egl_image = std::move(egl_image), + .texture = std::move(unique_texture)}; return DlImage::Make(SkImages::BorrowTextureFrom( context.gr_context, backendTexture, kTopLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, kPremul_SkAlphaType, nullptr)); @@ -206,7 +227,7 @@ sk_sp ImageExternalTextureGLImpeller::CreateDlImage( // Associate the hardware buffer image with the texture. glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, (GLeglImageOES)egl_image.get().image); - gl_entry_[id] = GlEntry{ + gl_entries_[id] = GlEntry{ .egl_image = std::move(egl_image), }; return impeller::DlImageImpeller::Make(texture); diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index d372233a9841f..448378081906c 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -51,7 +51,7 @@ class ImageExternalTextureGL : public ImageExternalTexture { // Each GL entry is keyed off of the currently active // hardware buffers and evicted when the hardware buffer // is removed from the LRU cache. - std::unordered_map gl_entry_; + std::unordered_map gl_entries_; FML_DISALLOW_COPY_AND_ASSIGN(ImageExternalTextureGL); }; From e458f52153c1817ca05b030e39754860e9729b1e Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 26 Jan 2024 14:34:16 -0800 Subject: [PATCH 16/17] refactor --- .../android/image_external_texture.cc | 2 +- .../platform/android/image_external_texture.h | 3 +- .../android/image_external_texture_gl.cc | 75 +++++++------------ .../android/image_external_texture_gl.h | 4 +- .../android/image_external_texture_vk.cc | 6 +- .../android/image_external_texture_vk.h | 2 - 6 files changed, 34 insertions(+), 58 deletions(-) diff --git a/shell/platform/android/image_external_texture.cc b/shell/platform/android/image_external_texture.cc index ba0f25f5a0016..da6f55832672e 100644 --- a/shell/platform/android/image_external_texture.cc +++ b/shell/platform/android/image_external_texture.cc @@ -25,7 +25,7 @@ void ImageExternalTexture::Paint(PaintContext& context, if (state_ == AttachmentState::kDetached) { return; } - last_bounds_ = bounds; + latest_bounds_ = bounds; Attach(context); const bool should_process_frame = !freeze; if (should_process_frame) { diff --git a/shell/platform/android/image_external_texture.h b/shell/platform/android/image_external_texture.h index 34ca3585d122f..6193c7b86baea 100644 --- a/shell/platform/android/image_external_texture.h +++ b/shell/platform/android/image_external_texture.h @@ -59,7 +59,8 @@ class ImageExternalTexture : public flutter::Texture { fml::jni::ScopedJavaGlobalRef image_texture_entry_; std::shared_ptr jni_facade_; - SkRect last_bounds_ = SkRect::MakeEmpty(); + SkRect latest_bounds_ = SkRect::MakeEmpty(); + fml::jni::ScopedJavaGlobalRef latest_android_image_; enum class AttachmentState { kUninitialized, kAttached, kDetached }; AttachmentState state_ = AttachmentState::kUninitialized; diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index eb07e56ab2780..da675823e1e95 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -8,20 +8,13 @@ #include #include "flutter/common/graphics/texture.h" -#include "flutter/display_list/effects/dl_color_source.h" -#include "flutter/flow/layers/layer.h" #include "flutter/impeller/core/formats.h" #include "flutter/impeller/display_list/dl_image_impeller.h" -#include "flutter/impeller/renderer/backend/gles/texture_gles.h" #include "flutter/impeller/toolkit/egl/image.h" #include "flutter/impeller/toolkit/gles/texture.h" #include "flutter/shell/platform/android/ndk_helpers.h" #include "third_party/skia/include/core/SkAlphaType.h" -#include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkColorType.h" -#include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/gpu/GrBackendSurface.h" -#include "third_party/skia/include/gpu/GrDirectContext.h" #include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" #include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" #include "third_party/skia/include/gpu/gl/GrGLTypes.h" @@ -36,74 +29,58 @@ ImageExternalTextureGL::ImageExternalTextureGL( void ImageExternalTextureGL::Attach(PaintContext& context) { if (state_ == AttachmentState::kUninitialized) { - if (!android_image_.is_null() && !last_bounds_.isEmpty()) { + if (!latest_android_image_.is_null() && !latest_bounds_.isEmpty()) { // After detach the cache of textures will have been cleared. If // there is an android image we must populate it now so that the // first frame isn't blank. - JavaLocalRef hardware_buffer = HardwareBufferFor(android_image_); - AHardwareBuffer* latest_hardware_buffer = - AHardwareBufferFor(hardware_buffer); - HardwareBufferKey key = - flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); - - auto egl_image = CreateEGLImage(latest_hardware_buffer); + JavaLocalRef hardware_buffer = HardwareBufferFor(latest_android_image_); + UpdateImage(hardware_buffer, context); CloseHardwareBuffer(hardware_buffer); - - if (!egl_image.is_valid()) { - return; - } - - dl_image_ = - CreateDlImage(context, last_bounds_, key, std::move(egl_image)); - gl_entries_.erase(image_lru_.AddImage(dl_image_, key)); } state_ = AttachmentState::kAttached; } } -void ImageExternalTextureGL::ProcessFrame(PaintContext& context, - const SkRect& bounds) { - JavaLocalRef image = AcquireLatestImage(); - if (image.is_null()) { - return; - } - - // NOTE: In the following code it is important that old_android_image is - // not closed until after the update of egl_image_ otherwise the image might - // be closed before the old EGLImage referencing it has been deleted. After - // an image is closed the underlying HardwareBuffer may be recycled and used - // for a future frame. - JavaLocalRef old_android_image(android_image_); - android_image_.Reset(image); - JavaLocalRef hardware_buffer = HardwareBufferFor(image); +void ImageExternalTextureGL::UpdateImage(JavaLocalRef hardware_buffer, + PaintContext& context) { AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); HardwareBufferKey key = flutter::NDKHelpers::AHardwareBuffer_getId(latest_hardware_buffer); auto existing_image = image_lru_.FindImage(key); if (existing_image != nullptr) { dl_image_ = existing_image; - - CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We have just received a new frame to display so close the - // previous Java Image so that it is recycled and used for a future frame. - CloseImage(old_android_image); return; } auto egl_image = CreateEGLImage(latest_hardware_buffer); - CloseHardwareBuffer(hardware_buffer); - // IMPORTANT: We have just received a new frame to display so close the - // previous Java Image so that it is recycled and used for a future frame. - CloseImage(old_android_image); - if (!egl_image.is_valid()) { return; } - dl_image_ = CreateDlImage(context, bounds, key, std::move(egl_image)); + dl_image_ = CreateDlImage(context, latest_bounds_, key, std::move(egl_image)); gl_entries_.erase(image_lru_.AddImage(dl_image_, key)); } +void ImageExternalTextureGL::ProcessFrame(PaintContext& context, + const SkRect& bounds) { + JavaLocalRef image = AcquireLatestImage(); + if (image.is_null()) { + return; + } + JavaLocalRef hardware_buffer = HardwareBufferFor(image); + UpdateImage(hardware_buffer, context); + CloseHardwareBuffer(hardware_buffer); + + // NOTE: In the following code it is important that old_android_image is + // not closed until after the update of egl_image_ otherwise the image might + // be closed before the old EGLImage referencing it has been deleted. After + // an image is closed the underlying HardwareBuffer may be recycled and used + // for a future frame. + JavaLocalRef old_android_image(latest_android_image_); + latest_android_image_.Reset(image); + CloseImage(old_android_image); +} + void ImageExternalTextureGL::Detach() { image_lru_.Clear(); gl_entries_.clear(); diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index 448378081906c..58c0707dcdcd1 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -6,6 +6,7 @@ #define FLUTTER_SHELL_PLATFORM_ANDROID_IMAGE_EXTERNAL_TEXTURE_GL_H_ #include + #include "flutter/fml/platform/android/scoped_java_ref.h" #include "flutter/shell/platform/android/image_external_texture.h" @@ -32,6 +33,7 @@ class ImageExternalTextureGL : public ImageExternalTexture { void Attach(PaintContext& context) override; void Detach() override; void ProcessFrame(PaintContext& context, const SkRect& bounds) override; + void UpdateImage(JavaLocalRef hardware_buffer, PaintContext& context); virtual sk_sp CreateDlImage( PaintContext& context, @@ -41,8 +43,6 @@ class ImageExternalTextureGL : public ImageExternalTexture { impeller::UniqueEGLImageKHR CreateEGLImage(AHardwareBuffer* buffer); - fml::jni::ScopedJavaGlobalRef android_image_; - struct GlEntry { impeller::UniqueEGLImageKHR egl_image; impeller::UniqueGLTexture texture; diff --git a/shell/platform/android/image_external_texture_vk.cc b/shell/platform/android/image_external_texture_vk.cc index 70a03986af90b..660e69192a4a3 100644 --- a/shell/platform/android/image_external_texture_vk.cc +++ b/shell/platform/android/image_external_texture_vk.cc @@ -38,9 +38,9 @@ void ImageExternalTextureVK::ProcessFrame(PaintContext& context, if (image.is_null()) { return; } - JavaLocalRef old_android_image(android_image_); - android_image_.Reset(image); - JavaLocalRef hardware_buffer = HardwareBufferFor(android_image_); + JavaLocalRef old_android_image(latest_android_image_); + latest_android_image_.Reset(image); + JavaLocalRef hardware_buffer = HardwareBufferFor(latest_android_image_); AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); AHardwareBuffer_Desc hb_desc = {}; diff --git a/shell/platform/android/image_external_texture_vk.h b/shell/platform/android/image_external_texture_vk.h index 16655eb118727..e3d240145aacc 100644 --- a/shell/platform/android/image_external_texture_vk.h +++ b/shell/platform/android/image_external_texture_vk.h @@ -33,8 +33,6 @@ class ImageExternalTextureVK : public ImageExternalTexture { void Detach() override; const std::shared_ptr impeller_context_; - - fml::jni::ScopedJavaGlobalRef android_image_; }; } // namespace flutter From dffddcbac244b34728bfcf13923c9ee3aaa96324 Mon Sep 17 00:00:00 2001 From: jonahwilliams Date: Fri, 26 Jan 2024 15:53:52 -0800 Subject: [PATCH 17/17] ++ --- shell/platform/android/image_external_texture_gl.cc | 2 +- shell/platform/android/image_external_texture_gl.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/platform/android/image_external_texture_gl.cc b/shell/platform/android/image_external_texture_gl.cc index da675823e1e95..4acc3598be2a8 100644 --- a/shell/platform/android/image_external_texture_gl.cc +++ b/shell/platform/android/image_external_texture_gl.cc @@ -41,7 +41,7 @@ void ImageExternalTextureGL::Attach(PaintContext& context) { } } -void ImageExternalTextureGL::UpdateImage(JavaLocalRef hardware_buffer, +void ImageExternalTextureGL::UpdateImage(JavaLocalRef& hardware_buffer, PaintContext& context) { AHardwareBuffer* latest_hardware_buffer = AHardwareBufferFor(hardware_buffer); HardwareBufferKey key = diff --git a/shell/platform/android/image_external_texture_gl.h b/shell/platform/android/image_external_texture_gl.h index 58c0707dcdcd1..656f790f10434 100644 --- a/shell/platform/android/image_external_texture_gl.h +++ b/shell/platform/android/image_external_texture_gl.h @@ -33,7 +33,7 @@ class ImageExternalTextureGL : public ImageExternalTexture { void Attach(PaintContext& context) override; void Detach() override; void ProcessFrame(PaintContext& context, const SkRect& bounds) override; - void UpdateImage(JavaLocalRef hardware_buffer, PaintContext& context); + void UpdateImage(JavaLocalRef& hardware_buffer, PaintContext& context); virtual sk_sp CreateDlImage( PaintContext& context,