Make sure that 'BeginFrame' and 'EndFrame' of the 'ExternalViewEmbedder' are paired (flutter/engine#32058)

This commit is contained in:
ColdPaleLight 2022-03-25 05:25:03 +08:00 committed by GitHub
parent a80ab445ee
commit 5850d41dd0
4 changed files with 78 additions and 2 deletions

View File

@ -335,6 +335,19 @@ class ExternalViewEmbedder {
// embedder.
virtual void Teardown();
// Change the flag about whether it is used in this frame, it will be set to
// true when 'BeginFrame' and false when 'EndFrame'.
void SetUsedThisFrame(bool used_this_frame) {
used_this_frame_ = used_this_frame;
}
// Whether it is used in this frame, returns true between 'BeginFrame' and
// 'EndFrame', otherwise returns false.
bool GetUsedThisFrame() const { return used_this_frame_; }
private:
bool used_this_frame_ = false;
FML_DISALLOW_COPY_AND_ASSIGN(ExternalViewEmbedder);
}; // ExternalViewEmbedder

View File

@ -151,10 +151,11 @@ void Rasterizer::DrawLastLayerTree(
DrawToSurface(*frame_timings_recorder, *last_layer_tree_);
// EndFrame should perform cleanups for the external_view_embedder.
if (external_view_embedder_) {
if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) {
bool should_resubmit_frame = ShouldResubmitFrame(raster_status);
external_view_embedder_->EndFrame(should_resubmit_frame,
raster_thread_merger_);
external_view_embedder_->SetUsedThisFrame(false);
}
}
@ -208,9 +209,11 @@ RasterStatus Rasterizer::Draw(
}
// EndFrame should perform cleanups for the external_view_embedder.
if (surface_ && external_view_embedder_) {
if (surface_ && external_view_embedder_ &&
external_view_embedder_->GetUsedThisFrame()) {
external_view_embedder_->EndFrame(should_resubmit_frame,
raster_thread_merger_);
external_view_embedder_->SetUsedThisFrame(false);
}
// Consume as many pipeline items as possible. But yield the event loop
@ -521,6 +524,8 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
SkCanvas* embedder_root_canvas = nullptr;
if (external_view_embedder_) {
FML_DCHECK(!external_view_embedder_->GetUsedThisFrame());
external_view_embedder_->SetUsedThisFrame(true);
external_view_embedder_->BeginFrame(
layer_tree.frame_size(), surface_->GetContext(),
layer_tree.device_pixel_ratio(), raster_thread_merger_);

View File

@ -419,6 +419,60 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) {
latch.Wait();
}
TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) {
std::string test_name =
::testing::UnitTest::GetInstance()->current_test_info()->name();
ThreadHost thread_host("io.flutter.test." + test_name + ".",
ThreadHost::Type::Platform | ThreadHost::Type::RASTER |
ThreadHost::Type::IO | ThreadHost::Type::UI);
TaskRunners task_runners("test", thread_host.platform_thread->GetTaskRunner(),
thread_host.raster_thread->GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(),
thread_host.io_thread->GetTaskRunner());
MockDelegate delegate;
EXPECT_CALL(delegate, GetTaskRunners())
.WillRepeatedly(ReturnRef(task_runners));
auto rasterizer = std::make_unique<Rasterizer>(delegate);
auto surface = std::make_unique<MockSurface>();
EXPECT_CALL(*surface, MakeRenderContextCurrent())
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
std::make_shared<MockExternalViewEmbedder>();
rasterizer->SetExternalViewEmbedder(external_view_embedder);
rasterizer->Setup(std::move(surface));
EXPECT_CALL(*external_view_embedder,
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
/*device_pixel_ratio=*/2.0,
/*raster_thread_merger=*/_))
.Times(0);
EXPECT_CALL(
*external_view_embedder,
EndFrame(/*should_resubmit_frame=*/false,
/*raster_thread_merger=*/fml::RefPtr<fml::RasterThreadMerger>(
nullptr)))
.Times(0);
fml::AutoResetWaitableEvent latch;
thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
auto pipeline = std::make_shared<Pipeline<LayerTree>>(/*depth=*/10);
auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(),
/*device_pixel_ratio=*/2.0f);
PipelineProduceResult result =
pipeline->Produce().Complete(std::move(layer_tree));
EXPECT_TRUE(result.success);
// Always discard the layer tree.
auto discard_callback = [](LayerTree&) { return true; };
RasterStatus status = rasterizer->Draw(CreateFinishedBuildRecorder(),
pipeline, discard_callback);
EXPECT_EQ(status, RasterStatus::kDiscarded);
latch.Signal();
});
latch.Wait();
}
TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) {
std::string test_name =
::testing::UnitTest::GetInstance()->current_test_info()->name();

View File

@ -2396,6 +2396,8 @@ TEST_F(ShellTest, OnServiceProtocolEstimateRasterCacheMemoryWorks) {
// TODO(https://github.com/flutter/flutter/issues/100273): Disabled due to
// flakiness.
// TODO(https://github.com/flutter/flutter/issues/100299): Fix it when
// re-enabling.
TEST_F(ShellTest, DISABLED_DiscardLayerTreeOnResize) {
auto settings = CreateSettingsForFixture();
@ -2448,6 +2450,8 @@ TEST_F(ShellTest, DISABLED_DiscardLayerTreeOnResize) {
// TODO(https://github.com/flutter/flutter/issues/100273): Disabled due to
// flakiness.
// TODO(https://github.com/flutter/flutter/issues/100299): Fix it when
// re-enabling.
TEST_F(ShellTest, DISABLED_DiscardResubmittedLayerTreeOnResize) {
auto settings = CreateSettingsForFixture();