Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Fix high FPS screen flicker of Platform Views when using ImageReaderPlatformViewRenderTarget #46724

Merged
merged 1 commit into from
Oct 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 41 additions & 35 deletions shell/platform/android/hardware_buffer_external_texture.cc
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include <android/hardware_buffer_jni.h>
#include <android/sensor.h>

#include "flutter/shell/platform/android/jni/platform_view_android_jni.h"
#include "flutter/shell/platform/android/ndk_helpers.h"

namespace flutter {
Expand All @@ -23,6 +25,7 @@ void HardwareBufferExternalTexture::Paint(PaintContext& context,
if (state_ == AttachmentState::kDetached) {
return;
}
Attach(context);
const bool should_process_frame =
(!freeze && new_frame_ready_) || dl_image_ == nullptr;
if (should_process_frame) {
Expand All @@ -39,7 +42,7 @@ void HardwareBufferExternalTexture::Paint(PaintContext& context,
flutter::DlCanvas::SrcRectConstraint::kStrict // enforce edges
);
} else {
FML_LOG(WARNING)
FML_LOG(ERROR)
<< "No DlImage available for HardwareBufferExternalTexture to paint.";
}
}
Expand All @@ -57,53 +60,56 @@ void HardwareBufferExternalTexture::OnGrContextCreated() {
state_ = AttachmentState::kUninitialized;
}

AHardwareBuffer* HardwareBufferExternalTexture::GetLatestHardwareBuffer() {
// Implementing flutter::ContextListener.
void HardwareBufferExternalTexture::OnGrContextDestroyed() {
if (state_ == AttachmentState::kAttached) {
dl_image_.reset();
Detach();
}
state_ = AttachmentState::kDetached;
}

JavaLocalRef HardwareBufferExternalTexture::AcquireLatestImage() {
JNIEnv* env = fml::jni::AttachCurrentThread();
FML_CHECK(env != nullptr);

// ImageTextureEntry.acquireLatestImage.
JavaLocalRef image_java = jni_facade_->ImageTextureEntryAcquireLatestImage(
JavaLocalRef(image_texture_entry_));
if (image_java.obj() == nullptr) {
return nullptr;
}
return image_java;
}

// Image.getHardwareBuffer.
JavaLocalRef hardware_buffer_java =
jni_facade_->ImageGetHardwareBuffer(image_java);
if (hardware_buffer_java.obj() == nullptr) {
jni_facade_->ImageClose(image_java);
return nullptr;
void HardwareBufferExternalTexture::CloseImage(
const fml::jni::JavaRef<jobject>& image) {
if (image.obj() == nullptr) {
return;
}
jni_facade_->ImageClose(JavaLocalRef(image));
}

// Convert into NDK HardwareBuffer.
AHardwareBuffer* latest_hardware_buffer =
NDKHelpers::AHardwareBuffer_fromHardwareBuffer(
env, hardware_buffer_java.obj());
if (latest_hardware_buffer == nullptr) {
jni_facade_->HardwareBufferClose(hardware_buffer_java);
jni_facade_->ImageClose(image_java);
return nullptr;
void HardwareBufferExternalTexture::CloseHardwareBuffer(
const fml::jni::JavaRef<jobject>& hardware_buffer) {
if (hardware_buffer.obj() == nullptr) {
return;
}

// Keep hardware buffer alive.
NDKHelpers::AHardwareBuffer_acquire(latest_hardware_buffer);

// Now that we have referenced the native hardware buffer, close the Java
// Image and HardwareBuffer objects.
jni_facade_->HardwareBufferClose(hardware_buffer_java);
jni_facade_->ImageClose(image_java);

return latest_hardware_buffer;
jni_facade_->HardwareBufferClose(JavaLocalRef(hardware_buffer));
}

// Implementing flutter::ContextListener.
void HardwareBufferExternalTexture::OnGrContextDestroyed() {
if (state_ == AttachmentState::kAttached) {
dl_image_.reset();
Detach();
JavaLocalRef HardwareBufferExternalTexture::HardwareBufferFor(
const fml::jni::JavaRef<jobject>& image) {
if (image.obj() == nullptr) {
return JavaLocalRef();
}
state_ = AttachmentState::kDetached;
// Image.getHardwareBuffer.
return jni_facade_->ImageGetHardwareBuffer(JavaLocalRef(image));
}

AHardwareBuffer* HardwareBufferExternalTexture::AHardwareBufferFor(
const fml::jni::JavaRef<jobject>& hardware_buffer) {
JNIEnv* env = fml::jni::AttachCurrentThread();
FML_CHECK(env != nullptr);
return NDKHelpers::AHardwareBuffer_fromHardwareBuffer(env,
hardware_buffer.obj());
}

} // namespace flutter
16 changes: 12 additions & 4 deletions shell/platform/android/hardware_buffer_external_texture.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include "flutter/common/graphics/texture.h"
#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 <android/hardware_buffer.h>
Expand All @@ -20,10 +21,11 @@ class HardwareBufferExternalTexture : public flutter::Texture {
public:
explicit HardwareBufferExternalTexture(
int64_t id,
const fml::jni::ScopedJavaGlobalRef<jobject>&
hardware_buffer_texture_entry,
const fml::jni::ScopedJavaGlobalRef<jobject>& image_texture_entry,
const std::shared_ptr<PlatformViewAndroidJNI>& jni_facade);

virtual ~HardwareBufferExternalTexture() = default;

// |flutter::Texture|.
void Paint(PaintContext& context,
const SkRect& bounds,
Expand All @@ -43,10 +45,16 @@ class HardwareBufferExternalTexture : public flutter::Texture {
void OnGrContextDestroyed() override;

protected:
virtual void ProcessFrame(PaintContext& context, const SkRect& bounds) = 0;
virtual void Attach(PaintContext& context) = 0;
virtual void Detach() = 0;
virtual void ProcessFrame(PaintContext& context, const SkRect& bounds) = 0;

AHardwareBuffer* GetLatestHardwareBuffer();
JavaLocalRef AcquireLatestImage();
void CloseImage(const fml::jni::JavaRef<jobject>& image);
JavaLocalRef HardwareBufferFor(const fml::jni::JavaRef<jobject>& image);
void CloseHardwareBuffer(const fml::jni::JavaRef<jobject>& hardware_buffer);
AHardwareBuffer* AHardwareBufferFor(
const fml::jni::JavaRef<jobject>& hardware_buffer);

fml::jni::ScopedJavaGlobalRef<jobject> image_texture_entry_;
std::shared_ptr<PlatformViewAndroidJNI> jni_facade_;
Expand Down
Loading