From 17cb12d9bdfc7367aae3cb00c735aa69aa58d41d Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Wed, 5 Feb 2025 13:07:34 -0800 Subject: [PATCH] [Android] wire up Java Transaction to AHB swapchain. (#162750) * When the opt in surface control setting is enabled (and the backend is impeller vulkan) - then use the external view embedder 2. * ALways create the SurfaceControl.Transaction in PlatformViewController2 and manage it in Java. This was done for ease of implementation. Rather than switching between SurfaceControl.Transaction objects created in the native heap or created in java, we always go through java. This also means that adding platform views shouldn't change this flow. * We may need to separate this after peformance profiling. One more PR to go to wire up the new message channels and add the integration_test. --- .../swapchain/ahb/ahb_swapchain_impl_vk.cc | 8 +++--- .../swapchain/ahb/ahb_swapchain_impl_vk.h | 6 +++++ .../vulkan/swapchain/ahb/ahb_swapchain_vk.cc | 5 +++- .../vulkan/swapchain/ahb/ahb_swapchain_vk.h | 5 ++++ .../backend/vulkan/swapchain/swapchain_vk.cc | 2 ++ .../backend/vulkan/swapchain/swapchain_vk.h | 6 +++++ .../android/android_surface_vk_impeller.cc | 8 +++++- .../external_view_embedder_2.cc | 26 +------------------ .../external_view_embedder_2.h | 7 ----- .../platform/android/platform_view_android.cc | 7 +++++ 10 files changed, 43 insertions(+), 37 deletions(-) diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc index 82681c525c..cab587ba1d 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.cc @@ -66,11 +66,12 @@ bool AHBFrameSynchronizerVK::WaitForFence(const vk::Device& device) { std::shared_ptr AHBSwapchainImplVK::Create( const std::weak_ptr& context, std::weak_ptr surface_control, + const CreateTransactionCB& cb, const ISize& size, bool enable_msaa, size_t swapchain_image_count) { auto impl = std::shared_ptr( - new AHBSwapchainImplVK(context, std::move(surface_control), size, + new AHBSwapchainImplVK(context, std::move(surface_control), cb, size, enable_msaa, swapchain_image_count)); return impl->IsValid() ? impl : nullptr; } @@ -78,10 +79,11 @@ std::shared_ptr AHBSwapchainImplVK::Create( AHBSwapchainImplVK::AHBSwapchainImplVK( const std::weak_ptr& context, std::weak_ptr surface_control, + const CreateTransactionCB& cb, const ISize& size, bool enable_msaa, size_t swapchain_image_count) - : surface_control_(std::move(surface_control)) { + : surface_control_(std::move(surface_control)), cb_(cb) { desc_ = android::HardwareBufferDescriptor::MakeForSwapchainImage(size); pool_ = std::make_shared(context, desc_, swapchain_image_count); @@ -201,7 +203,7 @@ bool AHBSwapchainImplVK::Present( return false; } - android::SurfaceTransaction transaction; + android::SurfaceTransaction transaction = cb_(); if (!transaction.SetContents(control.get(), // texture->GetBackingStore(), // present_ready->CreateFD() // diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.h index ef49af97e8..aedc6f5d88 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_impl_vk.h @@ -16,10 +16,13 @@ #include "impeller/renderer/surface.h" #include "impeller/toolkit/android/hardware_buffer.h" #include "impeller/toolkit/android/surface_control.h" +#include "impeller/toolkit/android/surface_transaction.h" #include "vulkan/vulkan_handles.hpp" namespace impeller { +using CreateTransactionCB = std::function; + static constexpr const size_t kMaxPendingPresents = 2u; struct AHBFrameSynchronizerVK { @@ -68,6 +71,7 @@ class AHBSwapchainImplVK final static std::shared_ptr Create( const std::weak_ptr& context, std::weak_ptr surface_control, + const CreateTransactionCB& cb, const ISize& size, bool enable_msaa, size_t swapchain_image_count); @@ -125,11 +129,13 @@ class AHBSwapchainImplVK final std::vector> frame_data_; size_t frame_index_ = 0; + CreateTransactionCB cb_; bool is_valid_ = false; explicit AHBSwapchainImplVK( const std::weak_ptr& context, std::weak_ptr surface_control, + const CreateTransactionCB& cb, const ISize& size, bool enable_msaa, size_t swapchain_image_count); diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc index 892f73cd0c..682a37b9aa 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.cc @@ -19,13 +19,15 @@ bool AHBSwapchainVK::IsAvailableOnPlatform() { AHBSwapchainVK::AHBSwapchainVK(const std::shared_ptr& context, ANativeWindow* window, + const CreateTransactionCB& cb, const vk::UniqueSurfaceKHR& surface, const ISize& size, bool enable_msaa) : context_(context), surface_control_( std::make_shared(window, "ImpellerSurface")), - enable_msaa_(enable_msaa) { + enable_msaa_(enable_msaa), + cb_(cb) { const auto [caps_result, surface_caps] = ContextVK::Cast(*context).GetPhysicalDevice().getSurfaceCapabilitiesKHR( *surface); @@ -80,6 +82,7 @@ void AHBSwapchainVK::UpdateSurfaceSize(const ISize& size) { TRACE_EVENT0("impeller", __FUNCTION__); auto impl = AHBSwapchainImplVK::Create(context_, // surface_control_, // + cb_, // size, // enable_msaa_, // swapchain_image_count_ // diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h index 7b0dcb42fd..40a700f215 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h @@ -9,9 +9,12 @@ #include "impeller/renderer/backend/vulkan/swapchain/swapchain_vk.h" #include "impeller/toolkit/android/native_window.h" #include "impeller/toolkit/android/surface_control.h" +#include "impeller/toolkit/android/surface_transaction.h" namespace impeller { +using CreateTransactionCB = std::function; + //------------------------------------------------------------------------------ /// @brief The implementation of a swapchain that uses hardware buffers /// presented to a given surface control on Android. @@ -57,10 +60,12 @@ class AHBSwapchainVK final : public SwapchainVK { std::shared_ptr surface_control_; const bool enable_msaa_; size_t swapchain_image_count_ = 3u; + CreateTransactionCB cb_; std::shared_ptr impl_; explicit AHBSwapchainVK(const std::shared_ptr& context, ANativeWindow* window, + const CreateTransactionCB& cb, const vk::UniqueSurfaceKHR& surface, const ISize& size, bool enable_msaa); diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.cc b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.cc index b15a4b47b5..26eda1dc14 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.cc +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.cc @@ -34,6 +34,7 @@ std::shared_ptr SwapchainVK::Create( std::shared_ptr SwapchainVK::Create( const std::shared_ptr& context, ANativeWindow* p_window, + const CreateTransactionCB& cb, bool enable_msaa) { TRACE_EVENT0("impeller", "CreateAndroidSwapchain"); if (!context) { @@ -63,6 +64,7 @@ std::shared_ptr SwapchainVK::Create( auto ahb_swapchain = std::shared_ptr(new AHBSwapchainVK( context, // window.GetHandle(), // + cb, // surface, // window.GetSize(), // enable_msaa // diff --git a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.h b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.h index 5cff164440..795b75847b 100644 --- a/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.h +++ b/engine/src/flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.h @@ -16,10 +16,15 @@ #if FML_OS_ANDROID #include "impeller/toolkit/android/native_window.h" +#include "impeller/toolkit/android/surface_transaction.h" #endif // FML_OS_ANDROID namespace impeller { +#if FML_OS_ANDROID +using CreateTransactionCB = std::function; +#endif // FML_OS_ANDROID + //------------------------------------------------------------------------------ /// @brief A swapchain that adapts to the underlying surface going out of /// date. If the caller cannot acquire the next drawable, it is due @@ -38,6 +43,7 @@ class SwapchainVK { static std::shared_ptr Create( const std::shared_ptr& context, ANativeWindow* window, + const CreateTransactionCB& cb, bool enable_msaa = true); #endif // FML_OS_ANDROID diff --git a/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc b/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc index c0338281db..86348fe355 100644 --- a/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc +++ b/engine/src/flutter/shell/platform/android/android_surface_vk_impeller.cc @@ -14,6 +14,7 @@ #include "flutter/impeller/renderer/backend/vulkan/swapchain/swapchain_vk.h" #include "flutter/shell/gpu/gpu_surface_vulkan_impeller.h" #include "flutter/vulkan/vulkan_native_surface_android.h" +#include "impeller/renderer/backend/vulkan/swapchain/ahb/ahb_swapchain_vk.h" namespace flutter { @@ -93,10 +94,15 @@ bool AndroidSurfaceVKImpeller::SetNativeWindow( return false; } + impeller::CreateTransactionCB cb = [jni_facade]() { + ASurfaceTransaction* tx = jni_facade->createTransaction(); + return impeller::android::SurfaceTransaction(tx); + }; + auto swapchain = impeller::SwapchainVK::Create( std::reinterpret_pointer_cast( surface_context_vk_->GetParent()), - window->handle()); + window->handle(), cb); if (surface_context_vk_->SetSwapchain(std::move(swapchain))) { native_window_ = std::move(window); diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc index cf87cd4f72..8a5efc7c13 100644 --- a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc +++ b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.cc @@ -4,7 +4,6 @@ #include "flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h" #include "flow/view_slicer.h" -#include "flutter/common/constants.h" #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/fml/trace_event.h" #include "fml/make_copyable.h" @@ -131,9 +130,7 @@ void AndroidExternalViewEmbedder2::SubmitFlutterView( for (int64_t view_id : composition_order) { SkRect view_rect = GetViewRect(view_id, view_params); const EmbeddedViewParams& params = view_params.at(view_id); - // Display the platform view. If it's already displayed, then it's - // just positioned and sized. - jni_facade->FlutterViewOnDisplayPlatformView( + jni_facade->onDisplayPlatformView2( view_id, // view_rect.x(), // view_rect.y(), // @@ -148,30 +145,9 @@ void AndroidExternalViewEmbedder2::SubmitFlutterView( surface_pool_->GetLayer(context, android_context_, jni_facade_, surface_factory_); } - jni_facade->FlutterViewEndFrame(); })); } -// |ExternalViewEmbedder| -std::unique_ptr -AndroidExternalViewEmbedder2::CreateSurfaceIfNeeded(GrDirectContext* context, - int64_t view_id, - EmbedderViewSlice* slice, - const SkRect& rect) { - std::shared_ptr layer = surface_pool_->GetLayer( - context, android_context_, jni_facade_, surface_factory_); - - std::unique_ptr frame = - layer->surface->AcquireFrame(frame_size_); - - DlCanvas* overlay_canvas = frame->Canvas(); - overlay_canvas->Clear(DlColor::kTransparent()); - // Offset the picture since its absolute position on the scene is determined - // by the position of the overlay view. - slice->render_into(overlay_canvas); - return frame; -} - // |ExternalViewEmbedder| PostPrerollResult AndroidExternalViewEmbedder2::PostPrerollAction( const fml::RefPtr& raster_thread_merger) { diff --git a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h index 2d8e91ef39..fe5dd0059f 100644 --- a/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h +++ b/engine/src/flutter/shell/platform/android/external_view_embedder/external_view_embedder_2.h @@ -145,13 +145,6 @@ class AndroidExternalViewEmbedder2 final : public ExternalViewEmbedder { // Whether the layer tree in the current frame has platform layers. bool FrameHasPlatformLayers(); - - // Creates a Surface when needed or recycles an existing one. - // Finally, draws the picture on the frame's canvas. - std::unique_ptr CreateSurfaceIfNeeded(GrDirectContext* context, - int64_t view_id, - EmbedderViewSlice* slice, - const SkRect& rect); }; } // namespace flutter diff --git a/engine/src/flutter/shell/platform/android/platform_view_android.cc b/engine/src/flutter/shell/platform/android/platform_view_android.cc index db8de490bf..7248a60d0e 100644 --- a/engine/src/flutter/shell/platform/android/platform_view_android.cc +++ b/engine/src/flutter/shell/platform/android/platform_view_android.cc @@ -8,6 +8,7 @@ #include #include +#include "common/settings.h" #include "flutter/common/graphics/texture.h" #include "flutter/fml/synchronization/waitable_event.h" #include "flutter/shell/common/shell_io_manager.h" @@ -132,6 +133,12 @@ PlatformViewAndroid::PlatformViewAndroid( delegate.OnPlatformViewGetSettings().enable_impeller // ); android_surface_ = surface_factory_->CreateSurface(); + // TODO(jonahwilliams): we need to expose the runtime check for the + // correct extensions and allowlist for this to work correctly. + android_use_new_platform_view_ = + android_context->RenderingApi() == + AndroidRenderingAPI::kImpellerVulkan && + delegate.OnPlatformViewGetSettings().enable_surface_control; FML_CHECK(android_surface_ && android_surface_->IsValid()) << "Could not create an OpenGL, Vulkan or Software surface to set up " "rendering.";