[embedder] Compositor can specify that no backing stores be cached (flutter/engine#22780)

This commit is contained in:
Kaushik Iska 2020-12-02 11:01:46 -08:00 committed by GitHub
parent bc13e87a05
commit 9d46f7efef
7 changed files with 70 additions and 6 deletions

View File

@ -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<flutter::EmbedderExternalViewEmbedder>(
create_render_target_callback, present_callback),
avoid_backing_store_cache, create_render_target_callback,
present_callback),
false};
}

View File

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

View File

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

View File

@ -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_;

View File

@ -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_;
}

View File

@ -85,7 +85,7 @@ class EmbedderConfigBuilder {
void SetPlatformMessageCallback(
const std::function<void(const FlutterPlatformMessage*)>& callback);
void SetCompositor();
void SetCompositor(bool avoid_backing_store_cache = false);
FlutterCompositor& GetCompositor();

View File

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