[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.
This commit is contained in:
Jonah Williams 2025-01-29 20:14:38 -08:00 committed by GitHub
parent e6185c3471
commit 524325a2fd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 53 additions and 13 deletions

View File

@ -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)

View File

@ -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<TransactionInFlightData>();
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<TransactionInFlightData*>(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() //
);

View File

@ -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<ASurfaceTransaction*, UniqueASurfaceTransactionTraits>
fml::UniqueObject<WrappedSurfaceTransaction, UniqueASurfaceTransactionTraits>
transaction_;
};