From 524325a2fd149db6e8e49c872eb2e654710e2f5e Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Wed, 29 Jan 2025 20:14:38 -0800 Subject: [PATCH] [Android] SurfaceTransaction updates for HC++. (#162405) Adds but does not use the ability to use imported Java SurfaceTransactions in the AHB swapchain. When an imported SurfaceTransaction is used, the Swapchain will not apply the transaction and instead will rely on the PlatformViewController to do so. --- .../impeller/toolkit/android/proc_table.h | 4 +++ .../toolkit/android/surface_transaction.cc | 27 ++++++++++---- .../toolkit/android/surface_transaction.h | 35 +++++++++++++++---- 3 files changed, 53 insertions(+), 13 deletions(-) diff --git a/engine/src/flutter/impeller/toolkit/android/proc_table.h b/engine/src/flutter/impeller/toolkit/android/proc_table.h index 9e639603b9..6e90b7fe86 100644 --- a/engine/src/flutter/impeller/toolkit/android/proc_table.h +++ b/engine/src/flutter/impeller/toolkit/android/proc_table.h @@ -21,6 +21,9 @@ namespace impeller::android { +ASurfaceTransaction* ASurfaceTransaction_fromJava(JNIEnv* env, + jobject transaction); + //------------------------------------------------------------------------------ /// @brief The Android procs along with the device API level on which these /// will be available. There is no checking of the actual API level @@ -61,6 +64,7 @@ namespace impeller::android { INVOKE(ASurfaceTransaction_setColor, 29) \ INVOKE(ASurfaceTransaction_setOnComplete, 29) \ INVOKE(ASurfaceTransactionStats_getPreviousReleaseFenceFd, 29) \ + INVOKE(ASurfaceTransaction_fromJava, 34) \ INVOKE(ATrace_isEnabled, 23) \ INVOKE(eglGetNativeClientBufferANDROID, 0) diff --git a/engine/src/flutter/impeller/toolkit/android/surface_transaction.cc b/engine/src/flutter/impeller/toolkit/android/surface_transaction.cc index 557dedb3cb..0e1b035296 100644 --- a/engine/src/flutter/impeller/toolkit/android/surface_transaction.cc +++ b/engine/src/flutter/impeller/toolkit/android/surface_transaction.cc @@ -11,7 +11,12 @@ namespace impeller::android { SurfaceTransaction::SurfaceTransaction() - : transaction_(GetProcTable().ASurfaceTransaction_create()) {} + : transaction_( + WrappedSurfaceTransaction{GetProcTable().ASurfaceTransaction_create(), + /*owned=*/true}) {} + +SurfaceTransaction::SurfaceTransaction(ASurfaceTransaction* transaction) + : transaction_(WrappedSurfaceTransaction{transaction, /*owned=*/false}) {} SurfaceTransaction::~SurfaceTransaction() = default; @@ -37,14 +42,22 @@ bool SurfaceTransaction::Apply(OnCompleteCallback callback) { auto data = std::make_unique(); data->callback = callback; proc_table.ASurfaceTransaction_setOnComplete( - transaction_.get(), // - data.release(), // + transaction_.get().tx, // + data.release(), // [](void* context, ASurfaceTransactionStats* stats) -> void { auto data = reinterpret_cast(context); data->callback(stats); delete data; }); - proc_table.ASurfaceTransaction_apply(transaction_.get()); + // If the transaction was created in Java, then it must be applied in + // the Java PlatformViewController and not as a part of the engine render + // loop. + if (!transaction_.get().owned) { + transaction_.reset(); + return true; + } + + proc_table.ASurfaceTransaction_apply(transaction_.get().tx); // Transactions may not be applied over and over. transaction_.reset(); @@ -59,7 +72,7 @@ bool SurfaceTransaction::SetContents(const SurfaceControl* control, return false; } GetProcTable().ASurfaceTransaction_setBuffer( - transaction_.get(), // + transaction_.get().tx, // control->GetHandle(), // buffer->GetHandle(), // acquire_fence.is_valid() ? acquire_fence.release() : -1 // @@ -72,7 +85,7 @@ bool SurfaceTransaction::SetBackgroundColor(const SurfaceControl& control, if (!IsValid() || !control.IsValid()) { return false; } - GetProcTable().ASurfaceTransaction_setColor(transaction_.get(), // + GetProcTable().ASurfaceTransaction_setColor(transaction_.get().tx, // control.GetHandle(), // color.red, // color.green, // @@ -92,7 +105,7 @@ bool SurfaceTransaction::SetParent(const SurfaceControl& control, return false; } GetProcTable().ASurfaceTransaction_reparent( - transaction_.get(), // + transaction_.get().tx, // control.GetHandle(), // new_parent == nullptr ? nullptr : new_parent->GetHandle() // ); diff --git a/engine/src/flutter/impeller/toolkit/android/surface_transaction.h b/engine/src/flutter/impeller/toolkit/android/surface_transaction.h index 83bb09ce19..85fcdcfacd 100644 --- a/engine/src/flutter/impeller/toolkit/android/surface_transaction.h +++ b/engine/src/flutter/impeller/toolkit/android/surface_transaction.h @@ -18,6 +18,25 @@ namespace impeller::android { class SurfaceControl; class HardwareBuffer; +/// @brief A wrapper class that indicates whether a SurfaceTransaction was +/// created by the flutter engine or was borrowed from Java for platform +/// interop. +struct WrappedSurfaceTransaction { + ASurfaceTransaction* tx = nullptr; + + /// Whether this SurfaceTransaction was created by the engine or imported from + /// Java. + bool owned = true; + + constexpr bool operator==(const WrappedSurfaceTransaction& other) const { + return other.tx == tx; + } + + constexpr bool operator!=(const WrappedSurfaceTransaction& other) const { + return !(*this == other); + } +}; + //------------------------------------------------------------------------------ /// @brief A wrapper for ASurfaceTransaction. /// https://developer.android.com/ndk/reference/group/native-activity#asurfacetransaction @@ -48,6 +67,8 @@ class SurfaceTransaction { SurfaceTransaction& operator=(const SurfaceTransaction&) = delete; + explicit SurfaceTransaction(ASurfaceTransaction* transaction); + bool IsValid() const; //---------------------------------------------------------------------------- @@ -119,18 +140,20 @@ class SurfaceTransaction { private: struct UniqueASurfaceTransactionTraits { - static ASurfaceTransaction* InvalidValue() { return nullptr; } + static WrappedSurfaceTransaction InvalidValue() { return {}; } - static bool IsValid(ASurfaceTransaction* value) { - return value != InvalidValue(); + static bool IsValid(const WrappedSurfaceTransaction& value) { + return value.tx != nullptr; } - static void Free(ASurfaceTransaction* value) { - GetProcTable().ASurfaceTransaction_delete(value); + static void Free(const WrappedSurfaceTransaction& value) { + if (value.owned && value.tx) { + GetProcTable().ASurfaceTransaction_delete(value.tx); + } } }; - fml::UniqueObject + fml::UniqueObject transaction_; };