mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix embedder_->EndFrame() not called in case of DrawLastLayerTree() (flutter/engine#29979)
This commit is contained in:
parent
7a8a4357ac
commit
fdfdd6dccb
@ -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) {
|
||||
|
||||
@ -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_;
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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") {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user