[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.
This commit is contained in:
Jonah Williams 2025-02-05 13:07:34 -08:00 committed by GitHub
parent 1fecd2bd79
commit 17cb12d9bd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 43 additions and 37 deletions

View File

@ -66,11 +66,12 @@ bool AHBFrameSynchronizerVK::WaitForFence(const vk::Device& device) {
std::shared_ptr<AHBSwapchainImplVK> AHBSwapchainImplVK::Create(
const std::weak_ptr<Context>& context,
std::weak_ptr<android::SurfaceControl> surface_control,
const CreateTransactionCB& cb,
const ISize& size,
bool enable_msaa,
size_t swapchain_image_count) {
auto impl = std::shared_ptr<AHBSwapchainImplVK>(
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> AHBSwapchainImplVK::Create(
AHBSwapchainImplVK::AHBSwapchainImplVK(
const std::weak_ptr<Context>& context,
std::weak_ptr<android::SurfaceControl> 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<AHBTexturePoolVK>(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() //

View File

@ -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<android::SurfaceTransaction()>;
static constexpr const size_t kMaxPendingPresents = 2u;
struct AHBFrameSynchronizerVK {
@ -68,6 +71,7 @@ class AHBSwapchainImplVK final
static std::shared_ptr<AHBSwapchainImplVK> Create(
const std::weak_ptr<Context>& context,
std::weak_ptr<android::SurfaceControl> 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<std::unique_ptr<AHBFrameSynchronizerVK>> frame_data_;
size_t frame_index_ = 0;
CreateTransactionCB cb_;
bool is_valid_ = false;
explicit AHBSwapchainImplVK(
const std::weak_ptr<Context>& context,
std::weak_ptr<android::SurfaceControl> surface_control,
const CreateTransactionCB& cb,
const ISize& size,
bool enable_msaa,
size_t swapchain_image_count);

View File

@ -19,13 +19,15 @@ bool AHBSwapchainVK::IsAvailableOnPlatform() {
AHBSwapchainVK::AHBSwapchainVK(const std::shared_ptr<Context>& context,
ANativeWindow* window,
const CreateTransactionCB& cb,
const vk::UniqueSurfaceKHR& surface,
const ISize& size,
bool enable_msaa)
: context_(context),
surface_control_(
std::make_shared<android::SurfaceControl>(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_ //

View File

@ -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<android::SurfaceTransaction()>;
//------------------------------------------------------------------------------
/// @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<android::SurfaceControl> surface_control_;
const bool enable_msaa_;
size_t swapchain_image_count_ = 3u;
CreateTransactionCB cb_;
std::shared_ptr<AHBSwapchainImplVK> impl_;
explicit AHBSwapchainVK(const std::shared_ptr<Context>& context,
ANativeWindow* window,
const CreateTransactionCB& cb,
const vk::UniqueSurfaceKHR& surface,
const ISize& size,
bool enable_msaa);

View File

@ -34,6 +34,7 @@ std::shared_ptr<SwapchainVK> SwapchainVK::Create(
std::shared_ptr<SwapchainVK> SwapchainVK::Create(
const std::shared_ptr<Context>& context,
ANativeWindow* p_window,
const CreateTransactionCB& cb,
bool enable_msaa) {
TRACE_EVENT0("impeller", "CreateAndroidSwapchain");
if (!context) {
@ -63,6 +64,7 @@ std::shared_ptr<SwapchainVK> SwapchainVK::Create(
auto ahb_swapchain = std::shared_ptr<AHBSwapchainVK>(new AHBSwapchainVK(
context, //
window.GetHandle(), //
cb, //
surface, //
window.GetSize(), //
enable_msaa //

View File

@ -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<android::SurfaceTransaction()>;
#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<SwapchainVK> Create(
const std::shared_ptr<Context>& context,
ANativeWindow* window,
const CreateTransactionCB& cb,
bool enable_msaa = true);
#endif // FML_OS_ANDROID

View File

@ -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<impeller::Context>(
surface_context_vk_->GetParent()),
window->handle());
window->handle(), cb);
if (surface_context_vk_->SetSwapchain(std::move(swapchain))) {
native_window_ = std::move(window);

View File

@ -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<SurfaceFrame>
AndroidExternalViewEmbedder2::CreateSurfaceIfNeeded(GrDirectContext* context,
int64_t view_id,
EmbedderViewSlice* slice,
const SkRect& rect) {
std::shared_ptr<OverlayLayer> layer = surface_pool_->GetLayer(
context, android_context_, jni_facade_, surface_factory_);
std::unique_ptr<SurfaceFrame> 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<fml::RasterThreadMerger>& raster_thread_merger) {

View File

@ -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<SurfaceFrame> CreateSurfaceIfNeeded(GrDirectContext* context,
int64_t view_id,
EmbedderViewSlice* slice,
const SkRect& rect);
};
} // namespace flutter

View File

@ -8,6 +8,7 @@
#include <memory>
#include <utility>
#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.";