Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions flow/embedded_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
9 changes: 7 additions & 2 deletions shell/common/rasterizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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_);
Expand Down
54 changes: 54 additions & 0 deletions shell/common/rasterizer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
4 changes: 4 additions & 0 deletions shell/common/shell_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();

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

Expand Down