From 1de265f541f2b436f8d554a03f9eabe3b86cfab6 Mon Sep 17 00:00:00 2001 From: Kaushik Iska Date: Mon, 30 Nov 2020 14:17:38 -0600 Subject: [PATCH] [embedder] Compositor can specify that no backing stores be cached --- shell/platform/embedder/embedder.cc | 5 +- shell/platform/embedder/embedder.h | 2 + .../embedder_external_view_embedder.cc | 10 ++-- .../embedder_external_view_embedder.h | 7 +++ .../embedder/tests/embedder_config_builder.cc | 3 +- .../embedder/tests/embedder_config_builder.h | 2 +- .../embedder/tests/embedder_unittests_gl.cc | 47 +++++++++++++++++++ 7 files changed, 70 insertions(+), 6 deletions(-) diff --git a/shell/platform/embedder/embedder.cc b/shell/platform/embedder/embedder.cc index 726312a36f3d2..1dc3ea6b448ed 100644 --- a/shell/platform/embedder/embedder.cc +++ b/shell/platform/embedder/embedder.cc @@ -542,6 +542,8 @@ InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor) { SAFE_ACCESS(compositor, collect_backing_store_callback, nullptr); auto c_present_callback = SAFE_ACCESS(compositor, present_layers_callback, nullptr); + bool avoid_backing_store_cache = + SAFE_ACCESS(compositor, avoid_backing_store_cache, false); // Make sure the required callbacks are present if (!c_create_callback || !c_collect_callback || !c_present_callback) { @@ -568,7 +570,8 @@ InferExternalViewEmbedderFromArgs(const FlutterCompositor* compositor) { }; return {std::make_unique( - create_render_target_callback, present_callback), + avoid_backing_store_cache, create_render_target_callback, + present_callback), false}; } diff --git a/shell/platform/embedder/embedder.h b/shell/platform/embedder/embedder.h index f98f848e967b3..4819aa87fa611 100644 --- a/shell/platform/embedder/embedder.h +++ b/shell/platform/embedder/embedder.h @@ -937,6 +937,8 @@ typedef struct { /// Callback invoked by the engine to composite the contents of each layer /// onto the screen. FlutterLayersPresentCallback present_layers_callback; + /// Avoid caching backing stores provided by this compositor. + bool avoid_backing_store_cache; } FlutterCompositor; typedef struct { diff --git a/shell/platform/embedder/embedder_external_view_embedder.cc b/shell/platform/embedder/embedder_external_view_embedder.cc index fc6c2905331c9..3e1dd488240d8 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.cc +++ b/shell/platform/embedder/embedder_external_view_embedder.cc @@ -13,9 +13,11 @@ namespace flutter { EmbedderExternalViewEmbedder::EmbedderExternalViewEmbedder( + bool avoid_backing_store_cache, const CreateRenderTargetCallback& create_render_target_callback, const PresentCallback& present_callback) - : create_render_target_callback_(create_render_target_callback), + : avoid_backing_store_cache_(avoid_backing_store_cache), + create_render_target_callback_(create_render_target_callback), present_callback_(present_callback) { FML_DCHECK(create_render_target_callback_); FML_DCHECK(present_callback_); @@ -263,8 +265,10 @@ void EmbedderExternalViewEmbedder::SubmitFrame( // Hold all rendered layers in the render target cache for one frame to // see if they may be reused next frame. for (auto& render_target : matched_render_targets) { - render_target_cache_.CacheRenderTarget(render_target.first, - std::move(render_target.second)); + if (!avoid_backing_store_cache_) { + render_target_cache_.CacheRenderTarget(render_target.first, + std::move(render_target.second)); + } } frame->Submit(); diff --git a/shell/platform/embedder/embedder_external_view_embedder.h b/shell/platform/embedder/embedder_external_view_embedder.h index e668e6eb1d1f7..9796d92c64ea2 100644 --- a/shell/platform/embedder/embedder_external_view_embedder.h +++ b/shell/platform/embedder/embedder_external_view_embedder.h @@ -40,6 +40,11 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { /// @brief Creates an external view embedder used by the generic embedder /// API. /// + /// @param[in] avoid_backing_store_cache If set, create_render_target callback + /// will beinvoked every frame for every + /// engine composited layer. The result + /// will not cached. + /// /// @param[in] create_render_target_callback /// The render target callback used to /// request the render target for a layer. @@ -49,6 +54,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { /// embedder for presentation. /// EmbedderExternalViewEmbedder( + bool avoid_backing_store_cache, const CreateRenderTargetCallback& create_render_target_callback, const PresentCallback& present_callback); @@ -100,6 +106,7 @@ class EmbedderExternalViewEmbedder final : public ExternalViewEmbedder { SkCanvas* GetRootCanvas() override; private: + const bool avoid_backing_store_cache_; const CreateRenderTargetCallback create_render_target_callback_; const PresentCallback present_callback_; SurfaceTransformationCallback surface_transformation_callback_; diff --git a/shell/platform/embedder/tests/embedder_config_builder.cc b/shell/platform/embedder/tests/embedder_config_builder.cc index 93d4c6af916f2..3b8961cd8d477 100644 --- a/shell/platform/embedder/tests/embedder_config_builder.cc +++ b/shell/platform/embedder/tests/embedder_config_builder.cc @@ -249,7 +249,7 @@ void EmbedderConfigBuilder::SetPlatformMessageCallback( context_.SetPlatformMessageCallback(callback); } -void EmbedderConfigBuilder::SetCompositor() { +void EmbedderConfigBuilder::SetCompositor(bool avoid_backing_store_cache) { context_.SetupCompositor(); auto& compositor = context_.GetCompositor(); compositor_.struct_size = sizeof(compositor_); @@ -279,6 +279,7 @@ void EmbedderConfigBuilder::SetCompositor() { ); }; + compositor_.avoid_backing_store_cache = avoid_backing_store_cache; project_args_.compositor = &compositor_; } diff --git a/shell/platform/embedder/tests/embedder_config_builder.h b/shell/platform/embedder/tests/embedder_config_builder.h index 4c37d644bc7ac..808719def63f4 100644 --- a/shell/platform/embedder/tests/embedder_config_builder.h +++ b/shell/platform/embedder/tests/embedder_config_builder.h @@ -85,7 +85,7 @@ class EmbedderConfigBuilder { void SetPlatformMessageCallback( const std::function& callback); - void SetCompositor(); + void SetCompositor(bool avoid_backing_store_cache = false); FlutterCompositor& GetCompositor(); diff --git a/shell/platform/embedder/tests/embedder_unittests_gl.cc b/shell/platform/embedder/tests/embedder_unittests_gl.cc index d9b0ba79bb65a..0b7b4e3312a90 100644 --- a/shell/platform/embedder/tests/embedder_unittests_gl.cc +++ b/shell/platform/embedder/tests/embedder_unittests_gl.cc @@ -3352,5 +3352,52 @@ TEST_F(EmbedderTest, MultipleDisplaysWithSameDisplayIdIsInvalid) { latch.Wait(); } +TEST_F(EmbedderTest, CompositorRenderTargetsNotRecycledWhenAvoidsCacheSet) { + auto& context = GetEmbedderContext(ContextType::kOpenGLContext); + + EmbedderConfigBuilder builder(context); + builder.SetOpenGLRendererConfig(SkISize::Make(300, 200)); + builder.SetCompositor(/*avoid_backing_store_cache=*/true); + builder.SetDartEntrypoint("render_targets_are_recycled"); + builder.SetRenderTargetType( + EmbedderTestBackingStoreProducer::RenderTargetType::kOpenGLTexture); + + const unsigned num_frames = 8; + const unsigned num_engine_layers = 10; + const unsigned num_backing_stores = num_frames * num_engine_layers; + fml::CountDownLatch latch(1 + num_frames); // 1 for native test signal. + + context.AddNativeCallback("SignalNativeTest", + CREATE_NATIVE_ENTRY([&](Dart_NativeArguments args) { + latch.CountDown(); + })); + + context.GetCompositor().SetPresentCallback( + [&](const FlutterLayer** layers, size_t layers_count) { + ASSERT_EQ(layers_count, 20u); + latch.CountDown(); + }, + /*one_shot=*/false); + + auto engine = builder.LaunchEngine(); + ASSERT_TRUE(engine.is_valid()); + + FlutterWindowMetricsEvent event = {}; + event.struct_size = sizeof(event); + event.width = 300; + event.height = 200; + event.pixel_ratio = 1.0; + ASSERT_EQ(FlutterEngineSendWindowMetricsEvent(engine.get(), &event), + kSuccess); + + latch.Wait(); + + ASSERT_EQ(context.GetCompositor().GetBackingStoresCreatedCount(), + num_backing_stores); + // Killing the engine should collect all the frames. + engine.reset(); + ASSERT_EQ(context.GetCompositor().GetPendingBackingStoresCount(), 0u); +} + } // namespace testing } // namespace flutter