mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[embedder] Compositor can specify that no backing stores be cached (flutter/engine#22780)
This commit is contained in:
parent
bc13e87a05
commit
9d46f7efef
@ -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};
|
||||
}
|
||||
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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_;
|
||||
}
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user