mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Skip LayerTree::Preroll LayerTree::Paint & Swapbuffer when frame_damage is empty (flutter/engine#32351)
This commit is contained in:
parent
1c5491a601
commit
1dbe7a6cd5
@ -12,6 +12,7 @@ namespace flutter {
|
||||
|
||||
std::optional<SkRect> FrameDamage::ComputeClipRect(
|
||||
flutter::LayerTree& layer_tree) {
|
||||
TRACE_EVENT0("flutter", "FrameDamage::ComputeClipRect");
|
||||
if (layer_tree.root_layer()) {
|
||||
PaintRegionMap empty_paint_region_map;
|
||||
DiffContext context(layer_tree.frame_size(),
|
||||
@ -118,6 +119,10 @@ RasterStatus CompositorContext::ScopedFrame::Raster(
|
||||
std::optional<SkRect> clip_rect =
|
||||
frame_damage ? frame_damage->ComputeClipRect(layer_tree) : std::nullopt;
|
||||
|
||||
if (frame_damage && frame_damage->GetFrameDamage() &&
|
||||
frame_damage->GetFrameDamage()->isEmpty()) {
|
||||
return RasterStatus::kDiscarded;
|
||||
}
|
||||
bool root_needs_readback = layer_tree.Preroll(
|
||||
*this, ignore_raster_cache, clip_rect ? *clip_rect : kGiantRect);
|
||||
bool needs_save_layer = root_needs_readback && !surface_supports_readback();
|
||||
|
||||
@ -287,6 +287,7 @@ if (enable_unittests) {
|
||||
"//flutter/shell/profiling:profiling_unittests",
|
||||
"//flutter/shell/version",
|
||||
"//flutter/testing:fixture_test",
|
||||
"//flutter/testing:skia",
|
||||
"//third_party/googletest:gmock",
|
||||
]
|
||||
|
||||
|
||||
@ -601,7 +601,8 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe(
|
||||
damage.get() // frame damage
|
||||
);
|
||||
if (raster_status == RasterStatus::kFailed ||
|
||||
raster_status == RasterStatus::kSkipAndRetry) {
|
||||
raster_status == RasterStatus::kSkipAndRetry ||
|
||||
raster_status == RasterStatus::kDiscarded) {
|
||||
return raster_status;
|
||||
}
|
||||
|
||||
|
||||
@ -13,6 +13,9 @@
|
||||
#include "flutter/shell/common/thread_host.h"
|
||||
#include "flutter/testing/testing.h"
|
||||
|
||||
#include "flow/layers/container_layer.h"
|
||||
#include "flow/layers/physical_shape_layer.h"
|
||||
#include "flutter/testing/mock_canvas.h"
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
using testing::_;
|
||||
@ -726,4 +729,138 @@ TEST(
|
||||
latch.Wait();
|
||||
}
|
||||
|
||||
TEST(RasterizerTest, drawWithFrameDamageIsEmpty) {
|
||||
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());
|
||||
fml::AutoResetWaitableEvent latch;
|
||||
thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
|
||||
CompositorContext compositor_context;
|
||||
flutter::testing::MockCanvas canvas;
|
||||
auto compositor_frame = compositor_context.AcquireFrame(
|
||||
nullptr, &canvas, nullptr, SkMatrix(), false, true, nullptr, nullptr);
|
||||
auto last_layer_tree =
|
||||
std::make_unique<LayerTree>(/*frame_size=*/SkISize::Make(100, 100),
|
||||
/*device_pixel_ratio=*/2.0f);
|
||||
// Use container as the root layer and PhysicalShapeLayer as the child
|
||||
// layer. Frame size is 100 x 100 PhysicalShapeLayer's size is 50 x 50 The
|
||||
// frame_damage is 50,50 in the first frame, and the frame_damage is empty
|
||||
// in the second frame
|
||||
auto last_root_layer = std::make_shared<ContainerLayer>();
|
||||
auto last_child = std::make_shared<PhysicalShapeLayer>(
|
||||
SK_ColorBLACK, SK_ColorBLACK,
|
||||
0.0f, // elevation
|
||||
SkPath::Rect(SkRect::MakeIWH(50, 50), SkPathDirection::kCCW, 0),
|
||||
Clip::none);
|
||||
last_root_layer.get()->Add(last_child);
|
||||
last_layer_tree->set_root_layer(last_root_layer);
|
||||
|
||||
auto layer_tree = std::make_unique<LayerTree>(
|
||||
/*frame_size=*/SkISize::Make(100, 100), /*device_pixel_ratio=*/2.0f);
|
||||
auto cur_root_layer = std::make_shared<ContainerLayer>();
|
||||
auto cur_child = std::make_shared<PhysicalShapeLayer>(
|
||||
SK_ColorBLACK, SK_ColorBLACK,
|
||||
0.0f, // elevation
|
||||
SkPath::Rect(SkRect::MakeIWH(50, 50), SkPathDirection::kCCW, 0),
|
||||
Clip::none);
|
||||
cur_child.get()->AssignOldLayer(last_child.get());
|
||||
cur_root_layer.get()->Add(cur_child);
|
||||
layer_tree->set_root_layer(cur_root_layer);
|
||||
|
||||
// Draw Last Frame
|
||||
std::unique_ptr<FrameDamage> last_damage = std::make_unique<FrameDamage>();
|
||||
RasterStatus last_raster_status =
|
||||
compositor_frame->Raster(*last_layer_tree.get(), // layer tree
|
||||
false, // ignore raster cache
|
||||
last_damage.get() // frame damage
|
||||
);
|
||||
EXPECT_EQ(last_raster_status, RasterStatus::kSuccess);
|
||||
|
||||
// Draw Current Frame
|
||||
std::unique_ptr<FrameDamage> cur_damage = std::make_unique<FrameDamage>();
|
||||
cur_damage->SetPreviousLayerTree(last_layer_tree.get());
|
||||
cur_damage->AddAdditonalDamage(SkIRect());
|
||||
RasterStatus cur_raster_status =
|
||||
compositor_frame->Raster(*layer_tree.get(), // layer tree
|
||||
false, // ignore raster cache
|
||||
cur_damage.get() // frame damage
|
||||
);
|
||||
EXPECT_EQ(cur_raster_status, RasterStatus::kDiscarded);
|
||||
latch.Signal();
|
||||
});
|
||||
latch.Wait();
|
||||
}
|
||||
|
||||
TEST(RasterizerTest, drawWithFrameDamageIsNotEmpty) {
|
||||
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());
|
||||
fml::AutoResetWaitableEvent latch;
|
||||
thread_host.raster_thread->GetTaskRunner()->PostTask([&] {
|
||||
CompositorContext compositor_context;
|
||||
flutter::testing::MockCanvas canvas;
|
||||
auto compositor_frame = compositor_context.AcquireFrame(
|
||||
nullptr, &canvas, nullptr, SkMatrix(), false, true, nullptr, nullptr);
|
||||
auto last_layer_tree =
|
||||
std::make_unique<LayerTree>(/*frame_size=*/SkISize::Make(100, 100),
|
||||
/*device_pixel_ratio=*/2.0f);
|
||||
// Use container as the root layer and PhysicalShapeLayer as the child
|
||||
// layer. Frame size is 100 x 100 PhysicalShapeLayer's size is 50 x 50 The
|
||||
// frame_damage is 50,50 in the first frame, and the frame_damage is 50,50
|
||||
// in the second frame
|
||||
auto last_root_layer = std::make_shared<ContainerLayer>();
|
||||
auto last_child = std::make_shared<PhysicalShapeLayer>(
|
||||
SK_ColorBLACK, SK_ColorBLACK,
|
||||
0.0f, // elevation
|
||||
SkPath::Rect(SkRect::MakeIWH(50, 50), SkPathDirection::kCCW, 0),
|
||||
Clip::none);
|
||||
last_root_layer.get()->Add(last_child);
|
||||
last_layer_tree->set_root_layer(last_root_layer);
|
||||
|
||||
auto layer_tree = std::make_unique<LayerTree>(
|
||||
/*frame_size=*/SkISize::Make(100, 100), /*device_pixel_ratio=*/2.0f);
|
||||
auto cur_root_layer = std::make_shared<ContainerLayer>();
|
||||
auto cur_child = std::make_shared<PhysicalShapeLayer>(
|
||||
SK_ColorBLACK, SK_ColorBLACK,
|
||||
0.0f, // elevation
|
||||
SkPath::Rect(SkRect::MakeIWH(50, 50), SkPathDirection::kCCW, 0),
|
||||
Clip::none);
|
||||
cur_root_layer.get()->Add(cur_child);
|
||||
layer_tree->set_root_layer(cur_root_layer);
|
||||
|
||||
// Draw Last Frame
|
||||
std::unique_ptr<FrameDamage> last_damage = std::make_unique<FrameDamage>();
|
||||
RasterStatus last_raster_status =
|
||||
compositor_frame->Raster(*last_layer_tree.get(), // layer tree
|
||||
false, // ignore raster cache
|
||||
last_damage.get() // frame damage
|
||||
);
|
||||
EXPECT_EQ(last_raster_status, RasterStatus::kSuccess);
|
||||
|
||||
// Draw Current Frame
|
||||
std::unique_ptr<FrameDamage> cur_damage = std::make_unique<FrameDamage>();
|
||||
cur_damage->SetPreviousLayerTree(last_layer_tree.get());
|
||||
RasterStatus cur_raster_status =
|
||||
compositor_frame->Raster(*layer_tree.get(), // layer tree
|
||||
false, // ignore raster cache
|
||||
cur_damage.get() // frame damage
|
||||
);
|
||||
EXPECT_EQ(cur_raster_status, RasterStatus::kSuccess);
|
||||
latch.Signal();
|
||||
});
|
||||
latch.Wait();
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user