mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix premature LayerStateStack layer culling (flutter/engine#38159)
* remove premature opacity culling * remove premature clip culling
This commit is contained in:
parent
865c2b0a2e
commit
f2fd4d7f0e
@ -6,8 +6,10 @@
|
||||
|
||||
#include "flutter/flow/layers/layer_tree.h"
|
||||
#include "flutter/flow/layers/opacity_layer.h"
|
||||
#include "flutter/flow/layers/platform_view_layer.h"
|
||||
#include "flutter/flow/raster_cache_item.h"
|
||||
#include "flutter/flow/testing/layer_test.h"
|
||||
#include "flutter/flow/testing/mock_embedder.h"
|
||||
#include "flutter/flow/testing/mock_layer.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/testing/mock_canvas.h"
|
||||
@ -533,5 +535,30 @@ TEST_F(ClipPathLayerTest, LayerCached) {
|
||||
cache_canvas, &paint));
|
||||
}
|
||||
|
||||
TEST_F(ClipPathLayerTest, EmptyClipDoesNotCullPlatformView) {
|
||||
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
|
||||
const SkSize view_size = SkSize::Make(8.0f, 8.0f);
|
||||
const int64_t view_id = 42;
|
||||
auto platform_view =
|
||||
std::make_shared<PlatformViewLayer>(view_offset, view_size, view_id);
|
||||
|
||||
auto layer_clip = SkPath().addRect(kEmptyRect);
|
||||
auto clip =
|
||||
std::make_shared<ClipPathLayer>(layer_clip, Clip::antiAliasWithSaveLayer);
|
||||
clip->Add(platform_view);
|
||||
|
||||
auto embedder = MockViewEmbedder();
|
||||
SkCanvas fake_overlay_canvas;
|
||||
embedder.AddCanvas(&fake_overlay_canvas);
|
||||
preroll_context()->view_embedder = &embedder;
|
||||
paint_context().view_embedder = &embedder;
|
||||
|
||||
clip->Preroll(preroll_context());
|
||||
EXPECT_EQ(embedder.prerolled_views(), std::vector<int64_t>({view_id}));
|
||||
|
||||
clip->Paint(paint_context());
|
||||
EXPECT_EQ(embedder.painted_views(), std::vector<int64_t>({view_id}));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -6,7 +6,9 @@
|
||||
|
||||
#include "flutter/flow/layers/layer_tree.h"
|
||||
#include "flutter/flow/layers/opacity_layer.h"
|
||||
#include "flutter/flow/layers/platform_view_layer.h"
|
||||
#include "flutter/flow/testing/layer_test.h"
|
||||
#include "flutter/flow/testing/mock_embedder.h"
|
||||
#include "flutter/flow/testing/mock_layer.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/testing/mock_canvas.h"
|
||||
@ -514,5 +516,28 @@ TEST_F(ClipRectLayerTest, LayerCached) {
|
||||
cache_canvas, &paint));
|
||||
}
|
||||
|
||||
TEST_F(ClipRectLayerTest, EmptyClipDoesNotCullPlatformView) {
|
||||
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
|
||||
const SkSize view_size = SkSize::Make(8.0f, 8.0f);
|
||||
const int64_t view_id = 42;
|
||||
auto platform_view =
|
||||
std::make_shared<PlatformViewLayer>(view_offset, view_size, view_id);
|
||||
|
||||
auto clip = std::make_shared<ClipRectLayer>(kEmptyRect, Clip::hardEdge);
|
||||
clip->Add(platform_view);
|
||||
|
||||
auto embedder = MockViewEmbedder();
|
||||
SkCanvas fake_overlay_canvas;
|
||||
embedder.AddCanvas(&fake_overlay_canvas);
|
||||
preroll_context()->view_embedder = &embedder;
|
||||
paint_context().view_embedder = &embedder;
|
||||
|
||||
clip->Preroll(preroll_context());
|
||||
EXPECT_EQ(embedder.prerolled_views(), std::vector<int64_t>({view_id}));
|
||||
|
||||
clip->Paint(paint_context());
|
||||
EXPECT_EQ(embedder.painted_views(), std::vector<int64_t>({view_id}));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -6,7 +6,9 @@
|
||||
|
||||
#include "flutter/flow/layers/layer_tree.h"
|
||||
#include "flutter/flow/layers/opacity_layer.h"
|
||||
#include "flutter/flow/layers/platform_view_layer.h"
|
||||
#include "flutter/flow/testing/layer_test.h"
|
||||
#include "flutter/flow/testing/mock_embedder.h"
|
||||
#include "flutter/flow/testing/mock_layer.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/testing/mock_canvas.h"
|
||||
@ -562,5 +564,29 @@ TEST_F(ClipRRectLayerTest, NoSaveLayerShouldNotCache) {
|
||||
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
|
||||
}
|
||||
|
||||
TEST_F(ClipRRectLayerTest, EmptyClipDoesNotCullPlatformView) {
|
||||
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
|
||||
const SkSize view_size = SkSize::Make(8.0f, 8.0f);
|
||||
const int64_t view_id = 42;
|
||||
auto platform_view =
|
||||
std::make_shared<PlatformViewLayer>(view_offset, view_size, view_id);
|
||||
|
||||
SkRRect clip_rrect = SkRRect::MakeRectXY(kEmptyRect, 20, 20);
|
||||
auto clip = std::make_shared<ClipRRectLayer>(clip_rrect, Clip::antiAlias);
|
||||
clip->Add(platform_view);
|
||||
|
||||
auto embedder = MockViewEmbedder();
|
||||
SkCanvas fake_overlay_canvas;
|
||||
embedder.AddCanvas(&fake_overlay_canvas);
|
||||
preroll_context()->view_embedder = &embedder;
|
||||
paint_context().view_embedder = &embedder;
|
||||
|
||||
clip->Preroll(preroll_context());
|
||||
EXPECT_EQ(embedder.prerolled_views(), std::vector<int64_t>({view_id}));
|
||||
|
||||
clip->Paint(paint_context());
|
||||
EXPECT_EQ(embedder.painted_views(), std::vector<int64_t>({view_id}));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -78,9 +78,6 @@ class ClipShapeLayer : public CacheableContainerLayer {
|
||||
|
||||
auto mutator = context.state_stack.save();
|
||||
ApplyClip(mutator);
|
||||
if (context.state_stack.content_culled(child_paint_bounds())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!UsesSaveLayer()) {
|
||||
PaintChildren(context);
|
||||
|
||||
@ -87,9 +87,7 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
}
|
||||
}
|
||||
|
||||
if (!context.state_stack.painting_is_nop()) {
|
||||
PaintChildren(context);
|
||||
}
|
||||
PaintChildren(context);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -7,10 +7,12 @@
|
||||
#include "flutter/flow/layers/clip_rect_layer.h"
|
||||
#include "flutter/flow/layers/image_filter_layer.h"
|
||||
#include "flutter/flow/layers/layer_tree.h"
|
||||
#include "flutter/flow/layers/platform_view_layer.h"
|
||||
#include "flutter/flow/layers/transform_layer.h"
|
||||
#include "flutter/flow/raster_cache_util.h"
|
||||
#include "flutter/flow/testing/diff_context_test.h"
|
||||
#include "flutter/flow/testing/layer_test.h"
|
||||
#include "flutter/flow/testing/mock_embedder.h"
|
||||
#include "flutter/flow/testing/mock_layer.h"
|
||||
#include "flutter/fml/macros.h"
|
||||
#include "flutter/testing/display_list_testing.h"
|
||||
@ -274,11 +276,16 @@ TEST_F(OpacityLayerTest, FullyTransparent) {
|
||||
mock_layer->parent_mutators(),
|
||||
std::vector({Mutator(layer_transform), Mutator(SK_AlphaTRANSPARENT)}));
|
||||
|
||||
auto expected_draw_calls =
|
||||
std::vector({MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
|
||||
MockCanvas::DrawCall{
|
||||
1, MockCanvas::ConcatMatrixData{SkM44(layer_transform)}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
|
||||
auto expected_draw_calls = std::vector(
|
||||
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
|
||||
MockCanvas::DrawCall{
|
||||
1, MockCanvas::ConcatMatrixData{SkM44(layer_transform)}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::SaveData{2}},
|
||||
MockCanvas::DrawCall{
|
||||
2, MockCanvas::ClipRectData{kEmptyRect, SkClipOp::kIntersect,
|
||||
MockCanvas::kHard_ClipEdgeStyle}},
|
||||
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
|
||||
layer->Paint(paint_context());
|
||||
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
|
||||
}
|
||||
@ -686,5 +693,30 @@ TEST_F(OpacityLayerTest, FullyOpaqueWithFractionalValues) {
|
||||
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
|
||||
}
|
||||
|
||||
TEST_F(OpacityLayerTest, FullyTransparentDoesNotCullPlatformView) {
|
||||
const SkPoint opacity_offset = SkPoint::Make(0.5f, 1.5f);
|
||||
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
|
||||
const SkSize view_size = SkSize::Make(8.0f, 8.0f);
|
||||
const int64_t view_id = 42;
|
||||
auto platform_view =
|
||||
std::make_shared<PlatformViewLayer>(view_offset, view_size, view_id);
|
||||
|
||||
auto opacity =
|
||||
std::make_shared<OpacityLayer>(SK_AlphaTRANSPARENT, opacity_offset);
|
||||
opacity->Add(platform_view);
|
||||
|
||||
auto embedder = MockViewEmbedder();
|
||||
SkCanvas fake_overlay_canvas;
|
||||
embedder.AddCanvas(&fake_overlay_canvas);
|
||||
preroll_context()->view_embedder = &embedder;
|
||||
paint_context().view_embedder = &embedder;
|
||||
|
||||
opacity->Preroll(preroll_context());
|
||||
EXPECT_EQ(embedder.prerolled_views(), std::vector<int64_t>({view_id}));
|
||||
|
||||
opacity->Paint(paint_context());
|
||||
EXPECT_EQ(embedder.painted_views(), std::vector<int64_t>({view_id}));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace flutter
|
||||
|
||||
@ -76,6 +76,11 @@ TEST_F(PlatformViewLayerTest, ClippedPlatformViewPrerollsAndPaintsNothing) {
|
||||
MockCanvas::DrawCall{
|
||||
1, MockCanvas::ClipRectData{parent_clip, SkClipOp::kIntersect,
|
||||
MockCanvas::kHard_ClipEdgeStyle}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::SaveData{2}},
|
||||
MockCanvas::DrawCall{
|
||||
2, MockCanvas::ClipRectData{child_clip, SkClipOp::kIntersect,
|
||||
MockCanvas::kHard_ClipEdgeStyle}},
|
||||
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
|
||||
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,9 @@ void MockViewEmbedder::BeginFrame(
|
||||
// |ExternalViewEmbedder|
|
||||
void MockViewEmbedder::PrerollCompositeEmbeddedView(
|
||||
int view_id,
|
||||
std::unique_ptr<EmbeddedViewParams> params) {}
|
||||
std::unique_ptr<EmbeddedViewParams> params) {
|
||||
prerolled_views_.emplace_back(view_id);
|
||||
}
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
std::vector<SkCanvas*> MockViewEmbedder::GetCurrentCanvases() {
|
||||
@ -52,6 +54,7 @@ std::vector<DisplayListBuilder*> MockViewEmbedder::GetCurrentBuilders() {
|
||||
|
||||
// |ExternalViewEmbedder|
|
||||
EmbedderPaintContext MockViewEmbedder::CompositeEmbeddedView(int view_id) {
|
||||
painted_views_.emplace_back(view_id);
|
||||
EmbedderPaintContext context = contexts_.front();
|
||||
contexts_.pop_front();
|
||||
return context;
|
||||
|
||||
@ -46,8 +46,13 @@ class MockViewEmbedder : public ExternalViewEmbedder {
|
||||
// |ExternalViewEmbedder|
|
||||
EmbedderPaintContext CompositeEmbeddedView(int view_id) override;
|
||||
|
||||
std::vector<int64_t> prerolled_views() const { return prerolled_views_; }
|
||||
std::vector<int64_t> painted_views() const { return painted_views_; }
|
||||
|
||||
private:
|
||||
std::deque<EmbedderPaintContext> contexts_;
|
||||
std::vector<int64_t> prerolled_views_;
|
||||
std::vector<int64_t> painted_views_;
|
||||
};
|
||||
|
||||
} // namespace testing
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user