Fix embedder_->EndFrame() not called in case of DrawLastLayerTree() (flutter/engine#29979)

This commit is contained in:
eggfly 2021-12-05 22:59:01 +08:00 committed by GitHub
parent 7a8a4357ac
commit fdfdd6dccb
4 changed files with 91 additions and 15 deletions

View File

@ -147,7 +147,15 @@ void Rasterizer::DrawLastLayerTree(
if (!last_layer_tree_ || !surface_) {
return;
}
DrawToSurface(*frame_timings_recorder, *last_layer_tree_);
RasterStatus raster_status =
DrawToSurface(*frame_timings_recorder, *last_layer_tree_);
// EndFrame should perform cleanups for the external_view_embedder.
if (external_view_embedder_) {
bool should_resubmit_frame = ShouldResubmitFrame(raster_status);
external_view_embedder_->EndFrame(should_resubmit_frame,
raster_thread_merger_);
}
}
RasterStatus Rasterizer::Draw(
@ -184,8 +192,7 @@ RasterStatus Rasterizer::Draw(
// if the raster status is to resubmit the frame, we push the frame to the
// front of the queue and also change the consume status to more available.
auto should_resubmit_frame = raster_status == RasterStatus::kResubmit ||
raster_status == RasterStatus::kSkipAndRetry;
bool should_resubmit_frame = ShouldResubmitFrame(raster_status);
if (should_resubmit_frame) {
auto front_continuation = pipeline->ProduceIfEmpty();
bool result =
@ -226,6 +233,11 @@ RasterStatus Rasterizer::Draw(
return raster_status;
}
bool Rasterizer::ShouldResubmitFrame(const RasterStatus& raster_status) {
return raster_status == RasterStatus::kResubmit ||
raster_status == RasterStatus::kSkipAndRetry;
}
namespace {
sk_sp<SkImage> DrawSnapshot(
sk_sp<SkSurface> surface,
@ -387,8 +399,7 @@ RasterStatus Rasterizer::DoDraw(
DrawToSurface(*frame_timings_recorder, *layer_tree);
if (raster_status == RasterStatus::kSuccess) {
last_layer_tree_ = std::move(layer_tree);
} else if (raster_status == RasterStatus::kResubmit ||
raster_status == RasterStatus::kSkipAndRetry) {
} else if (ShouldResubmitFrame(raster_status)) {
resubmitted_layer_tree_ = std::move(layer_tree);
return raster_status;
} else if (raster_status == RasterStatus::kDiscarded) {

View File

@ -483,6 +483,7 @@ class Rasterizer final : public SnapshotDelegate {
void FireNextFrameCallbackIfPresent();
static bool NoDiscard(const flutter::LayerTree& layer_tree) { return false; }
static bool ShouldResubmitFrame(const RasterStatus& raster_status);
Delegate& delegate_;
std::unique_ptr<Surface> surface_;

View File

@ -300,6 +300,80 @@ TEST(
rasterizer->Draw(CreateFinishedBuildRecorder(), pipeline, no_discard);
}
TEST(RasterizerTest,
drawLastLayerTreeWithThreadsMergedExternalViewEmbedderAndEndFrameCalled) {
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);
fml::MessageLoop::EnsureInitializedForCurrentThread();
TaskRunners task_runners("test",
fml::MessageLoop::GetCurrent().GetTaskRunner(),
fml::MessageLoop::GetCurrent().GetTaskRunner(),
thread_host.ui_thread->GetTaskRunner(),
thread_host.io_thread->GetTaskRunner());
MockDelegate delegate;
EXPECT_CALL(delegate, GetTaskRunners())
.WillRepeatedly(ReturnRef(task_runners));
EXPECT_CALL(delegate, OnFrameRasterized(_));
auto rasterizer = std::make_unique<Rasterizer>(delegate);
auto surface = std::make_unique<MockSurface>();
std::shared_ptr<MockExternalViewEmbedder> external_view_embedder =
std::make_shared<MockExternalViewEmbedder>();
rasterizer->SetExternalViewEmbedder(external_view_embedder);
SurfaceFrame::FramebufferInfo framebuffer_info;
framebuffer_info.supports_readback = true;
auto surface_frame1 = std::make_unique<SurfaceFrame>(
/*surface=*/nullptr, framebuffer_info,
/*submit_callback=*/[](const SurfaceFrame&, SkCanvas*) { return true; });
auto surface_frame2 = std::make_unique<SurfaceFrame>(
/*surface=*/nullptr, framebuffer_info,
/*submit_callback=*/[](const SurfaceFrame&, SkCanvas*) { return true; });
EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled())
.WillRepeatedly(Return(true));
// Prepare two frames for Draw() and DrawLastLayerTree().
EXPECT_CALL(*surface, AcquireFrame(SkISize()))
.WillOnce(Return(ByMove(std::move(surface_frame1))))
.WillOnce(Return(ByMove(std::move(surface_frame2))));
EXPECT_CALL(*surface, MakeRenderContextCurrent())
.WillOnce(Return(ByMove(std::make_unique<GLContextDefaultResult>(true))));
EXPECT_CALL(*external_view_embedder, SupportsDynamicThreadMerging)
.WillRepeatedly(Return(true));
EXPECT_CALL(*external_view_embedder,
BeginFrame(/*frame_size=*/SkISize(), /*context=*/nullptr,
/*device_pixel_ratio=*/2.0,
/*raster_thread_merger=*/_))
.Times(2);
EXPECT_CALL(*external_view_embedder, SubmitFrame).Times(2);
EXPECT_CALL(*external_view_embedder, EndFrame(/*should_resubmit_frame=*/false,
/*raster_thread_merger=*/_))
.Times(2);
rasterizer->Setup(std::move(surface));
auto pipeline = std::make_shared<Pipeline<LayerTree>>(/*depth=*/10);
auto layer_tree = std::make_unique<LayerTree>(/*frame_size=*/SkISize(),
/*device_pixel_ratio=*/2.0f);
bool result = pipeline->Produce().Complete(std::move(layer_tree));
EXPECT_TRUE(result);
auto no_discard = [](LayerTree&) { return false; };
// The Draw() will respectively call BeginFrame(), SubmitFrame() and
// EndFrame() one time.
rasterizer->Draw(CreateFinishedBuildRecorder(), pipeline, no_discard);
// The DrawLastLayerTree() will respectively call BeginFrame(), SubmitFrame()
// and EndFrame() one more time, totally 2 times.
rasterizer->DrawLastLayerTree(CreateFinishedBuildRecorder());
}
TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) {
std::string test_name =
::testing::UnitTest::GetInstance()->current_test_info()->name();

View File

@ -535,16 +535,6 @@ zip_bundle("flutter_jar_zip") {
]
deps = [ ":android_jar" ]
if (current_cpu == "x86" || current_cpu == "x64") {
files += [
{
source = "$root_build_dir/lib.stripped/libflutter.so"
destination = "libflutter.so"
},
]
deps += [ ":flutter_shell_native" ]
}
}
action("gen_android_javadoc") {