diff --git a/flow/layers/backdrop_filter_layer.cc b/flow/layers/backdrop_filter_layer.cc index ce86db3deaad7..e853a7783fe30 100644 --- a/flow/layers/backdrop_filter_layer.cc +++ b/flow/layers/backdrop_filter_layer.cc @@ -18,7 +18,7 @@ void BackdropFilterLayer::Preroll(PrerollContext* context, void BackdropFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "BackdropFilterLayer::Paint"); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create( context, diff --git a/flow/layers/backdrop_filter_layer_unittests.cc b/flow/layers/backdrop_filter_layer_unittests.cc index 47f7b66e35771..5fff33ecc17ef 100644 --- a/flow/layers/backdrop_filter_layer_unittests.cc +++ b/flow/layers/backdrop_filter_layer_unittests.cc @@ -22,11 +22,11 @@ TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(BackdropFilterLayerTest, PaintBeforePrerollDies) { @@ -38,7 +38,7 @@ TEST_F(BackdropFilterLayerTest, PaintBeforePrerollDies) { EXPECT_EQ(layer->paint_bounds(), kEmptyRect); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -53,7 +53,7 @@ TEST_F(BackdropFilterLayerTest, EmptyFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), child_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); layer->Paint(paint_context()); @@ -79,7 +79,7 @@ TEST_F(BackdropFilterLayerTest, SimpleFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), child_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); layer->Paint(paint_context()); @@ -114,9 +114,9 @@ TEST_F(BackdropFilterLayerTest, MultipleChildren) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), children_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); @@ -158,10 +158,10 @@ TEST_F(BackdropFilterLayerTest, Nested) { EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer1->paint_bounds(), children_bounds); EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds()); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer1->needs_painting()); - EXPECT_TRUE(layer2->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer1->needs_painting(paint_context())); + EXPECT_TRUE(layer2->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); diff --git a/flow/layers/checkerboard_layertree_unittests.cc b/flow/layers/checkerboard_layertree_unittests.cc index 337094ae983dd..72bde305ffee5 100644 --- a/flow/layers/checkerboard_layertree_unittests.cc +++ b/flow/layers/checkerboard_layertree_unittests.cc @@ -43,8 +43,8 @@ TEST_F(CheckerBoardLayerTest, ClipRectSaveLayerNotCheckBoard) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), @@ -93,8 +93,8 @@ TEST_F(CheckerBoardLayerTest, ClipRectSaveLayerCheckBoard) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), @@ -136,8 +136,8 @@ TEST_F(CheckerBoardLayerTest, ClipPathSaveLayerNotCheckBoard) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)})); @@ -177,8 +177,8 @@ TEST_F(CheckerBoardLayerTest, ClipPathSaveLayerCheckBoard) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)})); @@ -218,8 +218,8 @@ TEST_F(CheckerBoardLayerTest, ClipRRectSaveLayerNotCheckBoard) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)})); @@ -259,8 +259,8 @@ TEST_F(CheckerBoardLayerTest, ClipRRectSaveLayerCheckBoard) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)})); @@ -296,7 +296,7 @@ TEST_F(CheckerBoardLayerTest, PhysicalSaveLayerNotCheckBoard) { EXPECT_EQ(layer->paint_bounds(), PhysicalShapeLayer::ComputeShadowBounds(layer_path.getBounds(), initial_elevation, 1.0f)); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_EQ(layer->elevation(), initial_elevation); @@ -340,7 +340,7 @@ TEST_F(CheckerBoardLayerTest, PhysicalSaveLayerCheckBoard) { EXPECT_EQ(layer->paint_bounds(), PhysicalShapeLayer::ComputeShadowBounds(layer_path.getBounds(), initial_elevation, 1.0f)); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_EQ(layer->elevation(), initial_elevation); diff --git a/flow/layers/clip_path_layer.cc b/flow/layers/clip_path_layer.cc index 0b714392b60f5..3e6cf4570a842 100644 --- a/flow/layers/clip_path_layer.cc +++ b/flow/layers/clip_path_layer.cc @@ -21,21 +21,18 @@ void ClipPathLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkRect previous_cull_rect = context->cull_rect; SkRect clip_path_bounds = clip_path_.getBounds(); - children_inside_clip_ = context->cull_rect.intersect(clip_path_bounds); - if (children_inside_clip_) { - TRACE_EVENT_INSTANT0("flutter", "children inside clip rect"); - - Layer::AutoPrerollSaveLayerState save = - Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); - context->mutators_stack.PushClipPath(clip_path_); - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, matrix, &child_paint_bounds); - - if (child_paint_bounds.intersect(clip_path_bounds)) { - set_paint_bounds(child_paint_bounds); - } - context->mutators_stack.Pop(); + context->cull_rect.intersect(clip_path_bounds); + Layer::AutoPrerollSaveLayerState save = + Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); + context->mutators_stack.PushClipPath(clip_path_); + + SkRect child_paint_bounds = SkRect::MakeEmpty(); + PrerollChildren(context, matrix, &child_paint_bounds); + if (child_paint_bounds.intersect(clip_path_bounds)) { + set_paint_bounds(child_paint_bounds); } + + context->mutators_stack.Pop(); context->cull_rect = previous_cull_rect; } @@ -54,12 +51,7 @@ void ClipPathLayer::UpdateScene(std::shared_ptr context) { void ClipPathLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipPathLayer::Paint"); - FML_DCHECK(needs_painting()); - - if (!children_inside_clip_) { - TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping"); - return; - } + FML_DCHECK(needs_painting(context)); SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipPath(clip_path_, diff --git a/flow/layers/clip_path_layer.h b/flow/layers/clip_path_layer.h index eac015db9e5d1..c2af6ce3ffd62 100644 --- a/flow/layers/clip_path_layer.h +++ b/flow/layers/clip_path_layer.h @@ -28,7 +28,6 @@ class ClipPathLayer : public ContainerLayer { private: SkPath clip_path_; Clip clip_behavior_; - bool children_inside_clip_ = false; FML_DISALLOW_COPY_AND_ASSIGN(ClipPathLayer); }; diff --git a/flow/layers/clip_path_layer_unittests.cc b/flow/layers/clip_path_layer_unittests.cc index 6491fe5b40db7..4d1d0a9c48626 100644 --- a/flow/layers/clip_path_layer_unittests.cc +++ b/flow/layers/clip_path_layer_unittests.cc @@ -28,10 +28,10 @@ TEST_F(ClipPathLayerTest, PaintingEmptyLayerDies) { EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ClipPathLayerTest, PaintBeforePrerollDies) { @@ -39,37 +39,41 @@ TEST_F(ClipPathLayerTest, PaintBeforePrerollDies) { const SkPath layer_path = SkPath().addRect(layer_bounds); auto layer = std::make_shared(layer_path, Clip::hardEdge); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ClipPathLayerTest, PaintingCulledLayerDies) { const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f); const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0); const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); + const SkRect distant_bounds = SkRect::MakeXYWH(100.0, 100.0, 10.0, 10.0); const SkPath child_path = SkPath().addRect(child_bounds); const SkPath layer_path = SkPath().addRect(layer_bounds); auto mock_layer = std::make_shared(child_path); auto layer = std::make_shared(layer_path, Clip::hardEdge); layer->Add(mock_layer); - preroll_context()->cull_rect = kEmptyRect; // Cull everything + preroll_context()->cull_rect = distant_bounds; // Cull these children layer->Preroll(preroll_context(), initial_matrix); - EXPECT_EQ(preroll_context()->cull_rect, kEmptyRect); // Untouched + EXPECT_EQ(preroll_context()->cull_rect, distant_bounds); // Untouched EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched - EXPECT_EQ(mock_layer->paint_bounds(), kEmptyRect); - EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(mock_layer->needs_painting()); - EXPECT_FALSE(layer->needs_painting()); - EXPECT_EQ(mock_layer->parent_cull_rect(), kEmptyRect); - EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix()); - EXPECT_EQ(mock_layer->parent_mutators(), std::vector()); + EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); + EXPECT_EQ(layer->paint_bounds(), child_bounds); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); + EXPECT_EQ(mock_layer->parent_cull_rect(), distant_bounds); + EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); + EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)})); + paint_context().internal_nodes_canvas->clipRect(distant_bounds, false); + EXPECT_FALSE(mock_layer->needs_painting(paint_context())); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -96,8 +100,8 @@ TEST_F(ClipPathLayerTest, ChildOutsideBounds) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)})); @@ -131,8 +135,8 @@ TEST_F(ClipPathLayerTest, FullyContainedChild) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)})); @@ -173,8 +177,8 @@ TEST_F(ClipPathLayerTest, PartiallyContainedChild) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)})); diff --git a/flow/layers/clip_rect_layer.cc b/flow/layers/clip_rect_layer.cc index cd4443b5c0198..b95a340f33dae 100644 --- a/flow/layers/clip_rect_layer.cc +++ b/flow/layers/clip_rect_layer.cc @@ -16,21 +16,18 @@ void ClipRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { TRACE_EVENT0("flutter", "ClipRectLayer::Preroll"); SkRect previous_cull_rect = context->cull_rect; - children_inside_clip_ = context->cull_rect.intersect(clip_rect_); - if (children_inside_clip_) { - TRACE_EVENT_INSTANT0("flutter", "children inside clip rect"); - - Layer::AutoPrerollSaveLayerState save = - Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); - context->mutators_stack.PushClipRect(clip_rect_); - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, matrix, &child_paint_bounds); - - if (child_paint_bounds.intersect(clip_rect_)) { - set_paint_bounds(child_paint_bounds); - } - context->mutators_stack.Pop(); + context->cull_rect.intersect(clip_rect_); + Layer::AutoPrerollSaveLayerState save = + Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); + context->mutators_stack.PushClipRect(clip_rect_); + + SkRect child_paint_bounds = SkRect::MakeEmpty(); + PrerollChildren(context, matrix, &child_paint_bounds); + if (child_paint_bounds.intersect(clip_rect_)) { + set_paint_bounds(child_paint_bounds); } + + context->mutators_stack.Pop(); context->cull_rect = previous_cull_rect; } @@ -49,12 +46,7 @@ void ClipRectLayer::UpdateScene(std::shared_ptr context) { void ClipRectLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipRectLayer::Paint"); - FML_DCHECK(needs_painting()); - - if (!children_inside_clip_) { - TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping"); - return; - } + FML_DCHECK(needs_painting(context)); SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRect(clip_rect_, diff --git a/flow/layers/clip_rect_layer.h b/flow/layers/clip_rect_layer.h index 9c57861d87fe2..17917b232992e 100644 --- a/flow/layers/clip_rect_layer.h +++ b/flow/layers/clip_rect_layer.h @@ -27,7 +27,6 @@ class ClipRectLayer : public ContainerLayer { private: SkRect clip_rect_; Clip clip_behavior_; - bool children_inside_clip_ = false; FML_DISALLOW_COPY_AND_ASSIGN(ClipRectLayer); }; diff --git a/flow/layers/clip_rect_layer_unittests.cc b/flow/layers/clip_rect_layer_unittests.cc index 70decfa154e34..eb938b0522aa2 100644 --- a/flow/layers/clip_rect_layer_unittests.cc +++ b/flow/layers/clip_rect_layer_unittests.cc @@ -28,46 +28,51 @@ TEST_F(ClipRectLayerTest, PaintingEmptyLayerDies) { EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ClipRectLayerTest, PaintBeforePrerollDies) { const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); auto layer = std::make_shared(layer_bounds, Clip::hardEdge); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ClipRectLayerTest, PaintingCulledLayerDies) { const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f); const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0); const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); + const SkRect distant_bounds = SkRect::MakeXYWH(100.0, 100.0, 10.0, 10.0); const SkPath child_path = SkPath().addRect(child_bounds); auto mock_layer = std::make_shared(child_path); auto layer = std::make_shared(layer_bounds, Clip::hardEdge); layer->Add(mock_layer); - preroll_context()->cull_rect = kEmptyRect; // Cull everything + preroll_context()->cull_rect = distant_bounds; // Cull these children layer->Preroll(preroll_context(), initial_matrix); - EXPECT_EQ(preroll_context()->cull_rect, kEmptyRect); // Untouched + EXPECT_EQ(preroll_context()->cull_rect, distant_bounds); // Untouched EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched - EXPECT_EQ(mock_layer->paint_bounds(), kEmptyRect); - EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(mock_layer->needs_painting()); - EXPECT_FALSE(layer->needs_painting()); - EXPECT_EQ(mock_layer->parent_cull_rect(), kEmptyRect); - EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix()); - EXPECT_EQ(mock_layer->parent_mutators(), std::vector()); + EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); + EXPECT_EQ(layer->paint_bounds(), child_bounds); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); + EXPECT_EQ(mock_layer->parent_cull_rect(), distant_bounds); + EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); + EXPECT_EQ(mock_layer->parent_mutators(), + std::vector({Mutator(layer_bounds)})); + paint_context().internal_nodes_canvas->clipRect(distant_bounds, false); + EXPECT_FALSE(mock_layer->needs_painting(paint_context())); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -93,8 +98,8 @@ TEST_F(ClipRectLayerTest, ChildOutsideBounds) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), @@ -128,8 +133,8 @@ TEST_F(ClipRectLayerTest, FullyContainedChild) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), @@ -170,8 +175,8 @@ TEST_F(ClipRectLayerTest, PartiallyContainedChild) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), diff --git a/flow/layers/clip_rrect_layer.cc b/flow/layers/clip_rrect_layer.cc index 32ed1a39096ab..39b838be28478 100644 --- a/flow/layers/clip_rrect_layer.cc +++ b/flow/layers/clip_rrect_layer.cc @@ -17,21 +17,18 @@ void ClipRRectLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { SkRect previous_cull_rect = context->cull_rect; SkRect clip_rrect_bounds = clip_rrect_.getBounds(); - children_inside_clip_ = context->cull_rect.intersect(clip_rrect_bounds); - if (children_inside_clip_) { - TRACE_EVENT_INSTANT0("flutter", "children inside clip rect"); - - Layer::AutoPrerollSaveLayerState save = - Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); - context->mutators_stack.PushClipRRect(clip_rrect_); - SkRect child_paint_bounds = SkRect::MakeEmpty(); - PrerollChildren(context, matrix, &child_paint_bounds); - - if (child_paint_bounds.intersect(clip_rrect_bounds)) { - set_paint_bounds(child_paint_bounds); - } - context->mutators_stack.Pop(); + context->cull_rect.intersect(clip_rrect_bounds); + Layer::AutoPrerollSaveLayerState save = + Layer::AutoPrerollSaveLayerState::Create(context, UsesSaveLayer()); + context->mutators_stack.PushClipRRect(clip_rrect_); + + SkRect child_paint_bounds = SkRect::MakeEmpty(); + PrerollChildren(context, matrix, &child_paint_bounds); + if (child_paint_bounds.intersect(clip_rrect_bounds)) { + set_paint_bounds(child_paint_bounds); } + + context->mutators_stack.Pop(); context->cull_rect = previous_cull_rect; } @@ -50,12 +47,7 @@ void ClipRRectLayer::UpdateScene(std::shared_ptr context) { void ClipRRectLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ClipRRectLayer::Paint"); - FML_DCHECK(needs_painting()); - - if (!children_inside_clip_) { - TRACE_EVENT_INSTANT0("flutter", "children not inside clip rect, skipping"); - return; - } + FML_DCHECK(needs_painting(context)); SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->clipRRect(clip_rrect_, diff --git a/flow/layers/clip_rrect_layer.h b/flow/layers/clip_rrect_layer.h index 1422615c5c6b3..c308f21c7bfdd 100644 --- a/flow/layers/clip_rrect_layer.h +++ b/flow/layers/clip_rrect_layer.h @@ -28,7 +28,6 @@ class ClipRRectLayer : public ContainerLayer { private: SkRRect clip_rrect_; Clip clip_behavior_; - bool children_inside_clip_ = false; FML_DISALLOW_COPY_AND_ASSIGN(ClipRRectLayer); }; diff --git a/flow/layers/clip_rrect_layer_unittests.cc b/flow/layers/clip_rrect_layer_unittests.cc index 39d40b72221ee..485d616679f59 100644 --- a/flow/layers/clip_rrect_layer_unittests.cc +++ b/flow/layers/clip_rrect_layer_unittests.cc @@ -30,10 +30,10 @@ TEST_F(ClipRRectLayerTest, PaintingEmptyLayerDies) { EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ClipRRectLayerTest, PaintBeforePreollDies) { @@ -41,16 +41,17 @@ TEST_F(ClipRRectLayerTest, PaintBeforePreollDies) { const SkRRect layer_rrect = SkRRect::MakeRect(layer_bounds); auto layer = std::make_shared(layer_rrect, Clip::hardEdge); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ClipRRectLayerTest, PaintingCulledLayerDies) { const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f); const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0); const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0); + const SkRect distant_bounds = SkRect::MakeXYWH(100.0, 100.0, 10.0, 10.0); const SkPath child_path = SkPath().addRect(child_bounds); const SkRRect layer_rrect = SkRRect::MakeRect(layer_bounds); const SkPaint child_paint = SkPaint(SkColors::kYellow); @@ -58,21 +59,24 @@ TEST_F(ClipRRectLayerTest, PaintingCulledLayerDies) { auto layer = std::make_shared(layer_rrect, Clip::hardEdge); layer->Add(mock_layer); - preroll_context()->cull_rect = kEmptyRect; // Cull everything + preroll_context()->cull_rect = distant_bounds; // Cull these children layer->Preroll(preroll_context(), initial_matrix); - EXPECT_EQ(preroll_context()->cull_rect, kEmptyRect); // Untouched + EXPECT_EQ(preroll_context()->cull_rect, distant_bounds); // Untouched EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched - EXPECT_EQ(mock_layer->paint_bounds(), kEmptyRect); - EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(mock_layer->needs_painting()); - EXPECT_FALSE(layer->needs_painting()); - EXPECT_EQ(mock_layer->parent_cull_rect(), kEmptyRect); - EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix()); - EXPECT_EQ(mock_layer->parent_mutators(), std::vector()); + EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); + EXPECT_EQ(layer->paint_bounds(), child_bounds); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); + EXPECT_EQ(mock_layer->parent_cull_rect(), distant_bounds); + EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); + EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)})); + paint_context().internal_nodes_canvas->clipRect(distant_bounds, false); + EXPECT_FALSE(mock_layer->needs_painting(paint_context())); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -99,8 +103,8 @@ TEST_F(ClipRRectLayerTest, ChildOutsideBounds) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)})); @@ -134,8 +138,8 @@ TEST_F(ClipRRectLayerTest, FullyContainedChild) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)})); @@ -176,8 +180,8 @@ TEST_F(ClipRRectLayerTest, PartiallyContainedChild) { EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds); EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)})); diff --git a/flow/layers/color_filter_layer.cc b/flow/layers/color_filter_layer.cc index b212720da581d..17ff3e6d5547b 100644 --- a/flow/layers/color_filter_layer.cc +++ b/flow/layers/color_filter_layer.cc @@ -18,7 +18,7 @@ void ColorFilterLayer::Preroll(PrerollContext* context, void ColorFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ColorFilterLayer::Paint"); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); SkPaint paint; paint.setColorFilter(filter_); diff --git a/flow/layers/color_filter_layer_unittests.cc b/flow/layers/color_filter_layer_unittests.cc index 5c16f8c0cb1f0..0932700044e4d 100644 --- a/flow/layers/color_filter_layer_unittests.cc +++ b/flow/layers/color_filter_layer_unittests.cc @@ -22,11 +22,11 @@ TEST_F(ColorFilterLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ColorFilterLayerTest, PaintBeforePrerollDies) { @@ -38,7 +38,7 @@ TEST_F(ColorFilterLayerTest, PaintBeforePrerollDies) { EXPECT_EQ(layer->paint_bounds(), kEmptyRect); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -53,7 +53,7 @@ TEST_F(ColorFilterLayerTest, EmptyFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), child_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); SkPaint filter_paint; @@ -82,7 +82,7 @@ TEST_F(ColorFilterLayerTest, SimpleFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), child_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); SkPaint filter_paint; @@ -120,9 +120,9 @@ TEST_F(ColorFilterLayerTest, MultipleChildren) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), children_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); @@ -168,10 +168,10 @@ TEST_F(ColorFilterLayerTest, Nested) { EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer1->paint_bounds(), children_bounds); EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds()); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer1->needs_painting()); - EXPECT_TRUE(layer2->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer1->needs_painting(paint_context())); + EXPECT_TRUE(layer2->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); diff --git a/flow/layers/container_layer.cc b/flow/layers/container_layer.cc index a6ad98ba1aae4..5bbbb438c9d79 100644 --- a/flow/layers/container_layer.cc +++ b/flow/layers/container_layer.cc @@ -23,7 +23,7 @@ void ContainerLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { } void ContainerLayer::Paint(PaintContext& context) const { - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); PaintChildren(context); } @@ -72,12 +72,16 @@ void ContainerLayer::PrerollChildren(PrerollContext* context, } void ContainerLayer::PaintChildren(PaintContext& context) const { - FML_DCHECK(needs_painting()); + // We can no longer call FML_DCHECK here on the needs_painting(context) + // condition as that test is only valid for the PaintContext that + // is initially handed to a layer's Paint() method. By the time the + // layer calls PaintChildren(), though, it may have modified the + // PaintContext so the test doesn't work in this "context". // Intentionally not tracing here as there should be no self-time // and the trace event on this common function has a small overhead. for (auto& layer : layers_) { - if (layer->needs_painting()) { + if (layer->needs_painting(context)) { layer->Paint(context); } } diff --git a/flow/layers/container_layer_unittests.cc b/flow/layers/container_layer_unittests.cc index 65c2ff365fa0c..a8111c2920450 100644 --- a/flow/layers/container_layer_unittests.cc +++ b/flow/layers/container_layer_unittests.cc @@ -28,11 +28,11 @@ TEST_F(ContainerLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ContainerLayerTest, PaintBeforePreollDies) { @@ -44,7 +44,7 @@ TEST_F(ContainerLayerTest, PaintBeforePreollDies) { EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -62,8 +62,8 @@ TEST_F(ContainerLayerTest, Simple) { EXPECT_FALSE(preroll_context()->has_platform_view); EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer->paint_bounds(), child_path.getBounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(mock_layer->needs_system_composite()); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); @@ -98,9 +98,9 @@ TEST_F(ContainerLayerTest, Multiple) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_total_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(mock_layer1->needs_system_composite()); EXPECT_FALSE(mock_layer2->needs_system_composite()); EXPECT_FALSE(layer->needs_system_composite()); @@ -137,9 +137,9 @@ TEST_F(ContainerLayerTest, MultipleWithEmpty) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds()); EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds()); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_FALSE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_FALSE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(mock_layer1->needs_system_composite()); EXPECT_FALSE(mock_layer2->needs_system_composite()); EXPECT_FALSE(layer->needs_system_composite()); @@ -178,9 +178,9 @@ TEST_F(ContainerLayerTest, NeedsSystemComposite) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_total_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_TRUE(mock_layer1->needs_system_composite()); EXPECT_FALSE(mock_layer2->needs_system_composite()); EXPECT_TRUE(layer->needs_system_composite()); @@ -212,8 +212,8 @@ TEST_F(ContainerLayerTest, MergedOneChild) { EXPECT_FALSE(preroll_context()->has_platform_view); EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer->paint_bounds(), child_path.getBounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(mock_layer->needs_system_composite()); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); @@ -247,9 +247,9 @@ TEST_F(ContainerLayerTest, MergedMultipleChildren) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_total_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(mock_layer1->needs_system_composite()); EXPECT_FALSE(mock_layer2->needs_system_composite()); EXPECT_FALSE(layer->needs_system_composite()); diff --git a/flow/layers/image_filter_layer.cc b/flow/layers/image_filter_layer.cc index 6f2d7aa59e407..96986bb43deba 100644 --- a/flow/layers/image_filter_layer.cc +++ b/flow/layers/image_filter_layer.cc @@ -63,7 +63,7 @@ void ImageFilterLayer::Preroll(PrerollContext* context, void ImageFilterLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ImageFilterLayer::Paint"); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); if (context.raster_cache) { if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas)) { diff --git a/flow/layers/image_filter_layer_unittests.cc b/flow/layers/image_filter_layer_unittests.cc index bcc2d8e08e8b0..610d328789619 100644 --- a/flow/layers/image_filter_layer_unittests.cc +++ b/flow/layers/image_filter_layer_unittests.cc @@ -21,11 +21,11 @@ TEST_F(ImageFilterLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ImageFilterLayerTest, PaintBeforePrerollDies) { @@ -37,7 +37,7 @@ TEST_F(ImageFilterLayerTest, PaintBeforePrerollDies) { EXPECT_EQ(layer->paint_bounds(), kEmptyRect); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -52,7 +52,7 @@ TEST_F(ImageFilterLayerTest, EmptyFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), child_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); SkPaint filter_paint; @@ -85,7 +85,7 @@ TEST_F(ImageFilterLayerTest, SimpleFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), child_rounded_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); SkPaint filter_paint; @@ -118,7 +118,7 @@ TEST_F(ImageFilterLayerTest, SimpleFilterBounds) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), filter_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); SkPaint filter_paint; @@ -159,9 +159,9 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), children_rounded_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); @@ -212,10 +212,10 @@ TEST_F(ImageFilterLayerTest, Nested) { EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer1->paint_bounds(), children_rounded_bounds); EXPECT_EQ(layer2->paint_bounds(), mock_layer2_rounded_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer1->needs_painting()); - EXPECT_TRUE(layer2->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer1->needs_painting(paint_context())); + EXPECT_TRUE(layer2->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); diff --git a/flow/layers/layer.h b/flow/layers/layer.h index 0c7ef6568e6ce..4ab93ce86903e 100644 --- a/flow/layers/layer.h +++ b/flow/layers/layer.h @@ -163,15 +163,40 @@ class Layer { needs_system_composite_ = value; } + // Returns the paint bounds in the layer's local coordinate system + // as determined during Preroll(). The bounds should include any + // transform, clip or distortions performed by the layer itself, + // but not any similar modifications inherited from its ancestors. const SkRect& paint_bounds() const { return paint_bounds_; } // This must be set by the time Preroll() returns otherwise the layer will // be assumed to have empty paint bounds (paints no content). + // The paint bounds should be independent of the context outside of this + // layer as the layer may be painted under different conditions than + // the Preroll context. The most common example of this condition is + // that we might Preroll the layer with a cull_rect established by a + // clip layer above it but then we might be asked to paint anyway if + // another layer above us needs to cache its children. During the + // paint operation that arises due to the caching, the clip will + // be the bounds of the layer needing caching, not the cull_rect + // that we saw in the overall Preroll operation. void set_paint_bounds(const SkRect& paint_bounds) { paint_bounds_ = paint_bounds; } - bool needs_painting() const { return !paint_bounds_.isEmpty(); } + // Determines if the layer has any content. + bool is_empty() const { return paint_bounds_.isEmpty(); } + + // Determines if the Paint() method is necessary based on the properties + // of the indicated PaintContext object. + bool needs_painting(PaintContext& context) const { + // Workaround for Skia bug (quickReject does not reject empty bounds). + // https://bugs.chromium.org/p/skia/issues/detail?id=10951 + if (paint_bounds_.isEmpty()) { + return false; + } + return !context.internal_nodes_canvas->quickReject(paint_bounds_); + } uint64_t unique_id() const { return unique_id_; } diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc index d669591da1654..8169e8bf6ba2e 100644 --- a/flow/layers/layer_tree.cc +++ b/flow/layers/layer_tree.cc @@ -79,7 +79,7 @@ void LayerTree::UpdateScene(std::shared_ptr context) { if (root_layer_->needs_system_composite()) { root_layer_->UpdateScene(context); } - if (root_layer_->needs_painting()) { + if (!root_layer_->is_empty()) { frame.AddPaintLayer(root_layer_.get()); } context->root_node().AddChild(transform.entity_node()); @@ -117,7 +117,7 @@ void LayerTree::Paint(CompositorContext::ScopedFrame& frame, checkerboard_offscreen_layers_, device_pixel_ratio_}; - if (root_layer_->needs_painting()) { + if (root_layer_->needs_painting(context)) { root_layer_->Paint(context); } } @@ -176,7 +176,7 @@ sk_sp LayerTree::Flatten(const SkRect& bounds) { if (root_layer_) { root_layer_->Preroll(&preroll_context, root_surface_transformation); // The needs painting flag may be set after the preroll. So check it after. - if (root_layer_->needs_painting()) { + if (root_layer_->needs_painting(paint_context)) { root_layer_->Paint(paint_context); } } diff --git a/flow/layers/layer_tree_unittests.cc b/flow/layers/layer_tree_unittests.cc index 7045497692afe..98ce10d26831d 100644 --- a/flow/layers/layer_tree_unittests.cc +++ b/flow/layers/layer_tree_unittests.cc @@ -46,7 +46,7 @@ TEST_F(LayerTreeTest, PaintingEmptyLayerDies) { layer_tree().set_root_layer(layer); layer_tree().Preroll(frame()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_TRUE(layer->is_empty()); layer_tree().Paint(frame()); } @@ -62,8 +62,8 @@ TEST_F(LayerTreeTest, PaintBeforePreollDies) { layer_tree().set_root_layer(layer); EXPECT_EQ(mock_layer->paint_bounds(), kEmptyRect); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(mock_layer->needs_painting()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->is_empty()); + EXPECT_TRUE(layer->is_empty()); layer_tree().Paint(frame()); EXPECT_EQ(mock_canvas().draw_calls(), std::vector()); @@ -81,8 +81,8 @@ TEST_F(LayerTreeTest, Simple) { layer_tree().Preroll(frame()); EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_FALSE(mock_layer->is_empty()); + EXPECT_FALSE(layer->is_empty()); EXPECT_EQ(mock_layer->parent_matrix(), root_transform()); layer_tree().Paint(frame()); @@ -110,9 +110,9 @@ TEST_F(LayerTreeTest, Multiple) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_total_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_FALSE(mock_layer1->is_empty()); + EXPECT_FALSE(mock_layer2->is_empty()); + EXPECT_FALSE(layer->is_empty()); EXPECT_FALSE(mock_layer1->needs_system_composite()); EXPECT_FALSE(mock_layer2->needs_system_composite()); EXPECT_FALSE(layer->needs_system_composite()); @@ -146,9 +146,9 @@ TEST_F(LayerTreeTest, MultipleWithEmpty) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds()); EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds()); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_FALSE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_FALSE(mock_layer1->is_empty()); + EXPECT_TRUE(mock_layer2->is_empty()); + EXPECT_FALSE(layer->is_empty()); EXPECT_FALSE(mock_layer1->needs_system_composite()); EXPECT_FALSE(mock_layer2->needs_system_composite()); EXPECT_FALSE(layer->needs_system_composite()); @@ -183,9 +183,9 @@ TEST_F(LayerTreeTest, NeedsSystemComposite) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_total_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_FALSE(mock_layer1->is_empty()); + EXPECT_FALSE(mock_layer2->is_empty()); + EXPECT_FALSE(layer->is_empty()); EXPECT_TRUE(mock_layer1->needs_system_composite()); EXPECT_FALSE(mock_layer2->needs_system_composite()); EXPECT_TRUE(layer->needs_system_composite()); diff --git a/flow/layers/opacity_layer.cc b/flow/layers/opacity_layer.cc index b8922bff18b10..cc9ec4a42f152 100644 --- a/flow/layers/opacity_layer.cc +++ b/flow/layers/opacity_layer.cc @@ -46,7 +46,7 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { void OpacityLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "OpacityLayer::Paint"); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); SkPaint paint; paint.setAlpha(alpha_); diff --git a/flow/layers/opacity_layer_unittests.cc b/flow/layers/opacity_layer_unittests.cc index b8238cc8da45c..17a500832f836 100644 --- a/flow/layers/opacity_layer_unittests.cc +++ b/flow/layers/opacity_layer_unittests.cc @@ -34,11 +34,11 @@ TEST_F(OpacityLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(mock_layer->paint_bounds(), SkPath().getBounds()); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_FALSE(mock_layer->needs_painting()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(mock_layer->needs_painting(paint_context())); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(OpacityLayerTest, PaintBeforePreollDies) { @@ -50,7 +50,7 @@ TEST_F(OpacityLayerTest, PaintBeforePreollDies) { layer->Add(mock_layer); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -156,8 +156,8 @@ TEST_F(OpacityLayerTest, FullyOpaque) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_layer_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix::Concat(initial_transform, layer_transform)); EXPECT_EQ(mock_layer->parent_mutators(), @@ -206,8 +206,8 @@ TEST_F(OpacityLayerTest, FullyTransparent) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_layer_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix::Concat(initial_transform, layer_transform)); EXPECT_EQ( @@ -225,8 +225,6 @@ TEST_F(OpacityLayerTest, FullyTransparent) { MockCanvas::DrawCall{ 2, MockCanvas::ClipRectData{kEmptyRect, SkClipOp::kIntersect, MockCanvas::kHard_ClipEdgeStyle}}, - MockCanvas::DrawCall{2, - MockCanvas::DrawPathData{child_path, child_paint}}, MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}}, MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}); layer->Paint(paint_context()); @@ -254,8 +252,8 @@ TEST_F(OpacityLayerTest, HalfTransparent) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer->paint_bounds(), expected_layer_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix::Concat(initial_transform, layer_transform)); EXPECT_EQ(mock_layer->parent_mutators(), @@ -329,11 +327,11 @@ TEST_F(OpacityLayerTest, Nested) { EXPECT_EQ(mock_layer3->paint_bounds(), child3_path.getBounds()); EXPECT_EQ(layer1->paint_bounds(), expected_layer1_bounds); EXPECT_EQ(layer2->paint_bounds(), expected_layer2_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(mock_layer3->needs_painting()); - EXPECT_TRUE(layer1->needs_painting()); - EXPECT_TRUE(layer2->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer3->needs_painting(paint_context())); + EXPECT_TRUE(layer1->needs_painting(paint_context())); + EXPECT_TRUE(layer2->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), SkMatrix::Concat(initial_transform, layer1_transform)); // EXPECT_EQ(mock_layer1->parent_mutators(), diff --git a/flow/layers/performance_overlay_layer_unittests.cc b/flow/layers/performance_overlay_layer_unittests.cc index 7a010fd4e703c..37432714e2479 100644 --- a/flow/layers/performance_overlay_layer_unittests.cc +++ b/flow/layers/performance_overlay_layer_unittests.cc @@ -126,7 +126,7 @@ TEST_F(PerformanceOverlayLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); // Crashes reading a nullptr. EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), ""); @@ -143,7 +143,7 @@ TEST_F(PerformanceOverlayLayerTest, InvalidOptions) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), layer_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); // Nothing is drawn if options are invalid (0). layer->Paint(paint_context()); @@ -161,7 +161,7 @@ TEST_F(PerformanceOverlayLayerTest, SimpleRasterizerStatistics) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), layer_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); layer->Paint(paint_context()); auto overlay_text = PerformanceOverlayLayer::MakeStatisticsText( diff --git a/flow/layers/physical_shape_layer.cc b/flow/layers/physical_shape_layer.cc index 534962fff0a40..8f8ecbb5e91cd 100644 --- a/flow/layers/physical_shape_layer.cc +++ b/flow/layers/physical_shape_layer.cc @@ -45,7 +45,7 @@ void PhysicalShapeLayer::Preroll(PrerollContext* context, void PhysicalShapeLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "PhysicalShapeLayer::Paint"); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); if (elevation_ != 0) { DrawShadow(context.leaf_nodes_canvas, path_, shadow_color_, elevation_, diff --git a/flow/layers/physical_shape_layer_unittests.cc b/flow/layers/physical_shape_layer_unittests.cc index bb5d0acfad757..e6bf25ad82996 100644 --- a/flow/layers/physical_shape_layer_unittests.cc +++ b/flow/layers/physical_shape_layer_unittests.cc @@ -23,11 +23,11 @@ TEST_F(PhysicalShapeLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(PhysicalShapeLayerTest, PaintBeforePreollDies) { @@ -41,7 +41,7 @@ TEST_F(PhysicalShapeLayerTest, PaintBeforePreollDies) { layer->Add(mock_layer); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -54,7 +54,7 @@ TEST_F(PhysicalShapeLayerTest, NonEmptyLayer) { layer_path, Clip::none); layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); SkPaint layer_paint; @@ -93,7 +93,7 @@ TEST_F(PhysicalShapeLayerTest, ChildrenLargerThanPath) { child_paint_bounds.join(child2->paint_bounds()); EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds()); EXPECT_NE(layer->paint_bounds(), child_paint_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); SkPaint layer_paint; @@ -129,7 +129,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationSimple) { EXPECT_EQ(layer->paint_bounds(), PhysicalShapeLayer::ComputeShadowBounds(layer_path.getBounds(), initial_elevation, 1.0f)); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_EQ(layer->elevation(), initial_elevation); @@ -184,7 +184,7 @@ TEST_F(PhysicalShapeLayerTest, ElevationComplex) { (PhysicalShapeLayer::ComputeShadowBounds( layer_path.getBounds(), initial_elevations[i], 1.0f /* pixel_ratio */))); - EXPECT_TRUE(layers[i]->needs_painting()); + EXPECT_TRUE(layers[i]->needs_painting(paint_context())); EXPECT_FALSE(layers[i]->needs_system_composite()); } diff --git a/flow/layers/picture_layer.cc b/flow/layers/picture_layer.cc index 6df2c9e34bf30..f28c47045c65e 100644 --- a/flow/layers/picture_layer.cc +++ b/flow/layers/picture_layer.cc @@ -45,7 +45,7 @@ void PictureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { void PictureLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "PictureLayer::Paint"); FML_DCHECK(picture_.get()); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); SkAutoCanvasRestore save(context.leaf_nodes_canvas, true); context.leaf_nodes_canvas->translate(offset_.x(), offset_.y()); diff --git a/flow/layers/picture_layer_unittests.cc b/flow/layers/picture_layer_unittests.cc index dc9e6080c1508..8add7ffffa931 100644 --- a/flow/layers/picture_layer_unittests.cc +++ b/flow/layers/picture_layer_unittests.cc @@ -39,7 +39,7 @@ TEST_F(PictureLayerTest, PaintBeforePreollDies) { EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(PictureLayerTest, PaintingEmptyLayerDies) { @@ -51,11 +51,11 @@ TEST_F(PictureLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -81,7 +81,7 @@ TEST_F(PictureLayerTest, SimplePicture) { EXPECT_EQ(layer->paint_bounds(), picture_bounds.makeOffset(layer_offset.fX, layer_offset.fY)); EXPECT_EQ(layer->picture(), mock_picture.get()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); layer->Paint(paint_context()); diff --git a/flow/layers/platform_view_layer_unittests.cc b/flow/layers/platform_view_layer_unittests.cc index 98393651e27f0..5387abc7b7ed3 100644 --- a/flow/layers/platform_view_layer_unittests.cc +++ b/flow/layers/platform_view_layer_unittests.cc @@ -26,7 +26,7 @@ TEST_F(PlatformViewLayerTest, NullViewEmbedderDoesntPrerollCompositeOrPaint) { EXPECT_EQ(layer->paint_bounds(), SkRect::MakeSize(layer_size) .makeOffset(layer_offset.fX, layer_offset.fY)); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); #if defined(LEGACY_FUCHSIA_EMBEDDER) EXPECT_TRUE(layer->needs_system_composite()); #else diff --git a/flow/layers/shader_mask_layer.cc b/flow/layers/shader_mask_layer.cc index a03edfd504879..091b447ac31c0 100644 --- a/flow/layers/shader_mask_layer.cc +++ b/flow/layers/shader_mask_layer.cc @@ -23,7 +23,7 @@ void ShaderMaskLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { void ShaderMaskLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "ShaderMaskLayer::Paint"); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); Layer::AutoSaveLayer save = Layer::AutoSaveLayer::Create(context, paint_bounds(), nullptr); diff --git a/flow/layers/shader_mask_layer_unittests.cc b/flow/layers/shader_mask_layer_unittests.cc index a4118ce2dbc75..4336ed1f3b8e3 100644 --- a/flow/layers/shader_mask_layer_unittests.cc +++ b/flow/layers/shader_mask_layer_unittests.cc @@ -23,10 +23,10 @@ TEST_F(ShaderMaskLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(ShaderMaskLayerTest, PaintBeforePreollDies) { @@ -39,7 +39,7 @@ TEST_F(ShaderMaskLayerTest, PaintBeforePreollDies) { EXPECT_EQ(layer->paint_bounds(), kEmptyRect); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -57,8 +57,8 @@ TEST_F(ShaderMaskLayerTest, EmptyFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(mock_layer->paint_bounds(), child_bounds); EXPECT_EQ(layer->paint_bounds(), child_bounds); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); SkPaint filter_paint; @@ -98,7 +98,7 @@ TEST_F(ShaderMaskLayerTest, SimpleFilter) { layer->Preroll(preroll_context(), initial_transform); EXPECT_EQ(layer->paint_bounds(), child_bounds); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), initial_transform); SkPaint filter_paint; @@ -147,9 +147,9 @@ TEST_F(ShaderMaskLayerTest, MultipleChildren) { EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds()); EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer->paint_bounds(), children_bounds); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); @@ -207,10 +207,10 @@ TEST_F(ShaderMaskLayerTest, Nested) { EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds()); EXPECT_EQ(layer1->paint_bounds(), children_bounds); EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds()); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer1->needs_painting()); - EXPECT_TRUE(layer2->needs_painting()); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer1->needs_painting(paint_context())); + EXPECT_TRUE(layer2->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform); EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform); diff --git a/flow/layers/texture_layer.cc b/flow/layers/texture_layer.cc index e5775149a8d7a..4c29955f8a09c 100644 --- a/flow/layers/texture_layer.cc +++ b/flow/layers/texture_layer.cc @@ -32,6 +32,7 @@ void TextureLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { void TextureLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "TextureLayer::Paint"); + FML_DCHECK(needs_painting(context)); std::shared_ptr texture = context.texture_registry.GetTexture(texture_id_); diff --git a/flow/layers/texture_layer_unittests.cc b/flow/layers/texture_layer_unittests.cc index 525239a8e0f5f..23115052e1257 100644 --- a/flow/layers/texture_layer_unittests.cc +++ b/flow/layers/texture_layer_unittests.cc @@ -25,12 +25,13 @@ TEST_F(TextureLayerTest, InvalidTexture) { EXPECT_EQ(layer->paint_bounds(), (SkRect::MakeSize(layer_size) .makeOffset(layer_offset.fX, layer_offset.fY))); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); layer->Paint(paint_context()); EXPECT_EQ(mock_canvas().draw_calls(), std::vector()); } +#ifndef NDEBUG TEST_F(TextureLayerTest, PaintingEmptyLayerDies) { const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); const SkSize layer_size = SkSize::Make(0.0f, 0.0f); @@ -44,15 +45,27 @@ TEST_F(TextureLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), kEmptyRect); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); - layer->Paint(paint_context()); - EXPECT_EQ(mock_texture->paint_calls(), - std::vector({MockTexture::PaintCall{ - mock_canvas(), layer->paint_bounds(), false, nullptr, - kNone_SkFilterQuality}})); - EXPECT_EQ(mock_canvas().draw_calls(), std::vector()); + EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), + "needs_painting\\(context\\)"); +} + +TEST_F(TextureLayerTest, PaintBeforePreollDies) { + const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); + const SkSize layer_size = SkSize::Make(8.0f, 8.0f); + const int64_t texture_id = 0; + auto mock_texture = std::make_shared(texture_id); + auto layer = std::make_shared( + layer_offset, layer_size, texture_id, false, kLow_SkFilterQuality); + + // Ensure the texture is located by the Layer. + preroll_context()->texture_registry.RegisterTexture(mock_texture); + + EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), + "needs_painting\\(context\\)"); } +#endif TEST_F(TextureLayerTest, PaintingWithLowFilterQuality) { const SkPoint layer_offset = SkPoint::Make(0.0f, 0.0f); @@ -69,7 +82,7 @@ TEST_F(TextureLayerTest, PaintingWithLowFilterQuality) { EXPECT_EQ(layer->paint_bounds(), (SkRect::MakeSize(layer_size) .makeOffset(layer_offset.fX, layer_offset.fY))); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); layer->Paint(paint_context()); EXPECT_EQ(mock_texture->paint_calls(), diff --git a/flow/layers/transform_layer.cc b/flow/layers/transform_layer.cc index 3e26e525ac637..839fbe05af292 100644 --- a/flow/layers/transform_layer.cc +++ b/flow/layers/transform_layer.cc @@ -70,7 +70,7 @@ void TransformLayer::UpdateScene(std::shared_ptr context) { void TransformLayer::Paint(PaintContext& context) const { TRACE_EVENT0("flutter", "TransformLayer::Paint"); - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); SkAutoCanvasRestore save(context.internal_nodes_canvas, true); context.internal_nodes_canvas->concat(transform_); diff --git a/flow/layers/transform_layer_unittests.cc b/flow/layers/transform_layer_unittests.cc index 5820e021055c5..ea11eb71cc015 100644 --- a/flow/layers/transform_layer_unittests.cc +++ b/flow/layers/transform_layer_unittests.cc @@ -20,10 +20,10 @@ TEST_F(TransformLayerTest, PaintingEmptyLayerDies) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty()); - EXPECT_FALSE(layer->needs_painting()); + EXPECT_FALSE(layer->needs_painting(paint_context())); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(TransformLayerTest, PaintBeforePreollDies) { @@ -34,7 +34,7 @@ TEST_F(TransformLayerTest, PaintBeforePreollDies) { layer->Add(mock_layer); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -50,8 +50,8 @@ TEST_F(TransformLayerTest, Identity) { layer->Preroll(preroll_context(), SkMatrix()); EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds()); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix()); // identity EXPECT_EQ(mock_layer->parent_cull_rect(), cull_rect); EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(SkMatrix())})); @@ -80,8 +80,8 @@ TEST_F(TransformLayerTest, Simple) { EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer->paint_bounds(), layer_transform.mapRect(mock_layer->paint_bounds())); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix::Concat(initial_transform, layer_transform)); EXPECT_EQ(mock_layer->parent_cull_rect(), @@ -124,9 +124,9 @@ TEST_F(TransformLayerTest, Nested) { layer2_transform.mapRect(mock_layer->paint_bounds())); EXPECT_EQ(layer1->paint_bounds(), layer1_transform.mapRect(layer2->paint_bounds())); - EXPECT_TRUE(mock_layer->needs_painting()); - EXPECT_TRUE(layer2->needs_painting()); - EXPECT_TRUE(layer1->needs_painting()); + EXPECT_TRUE(mock_layer->needs_painting(paint_context())); + EXPECT_TRUE(layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer1->needs_painting(paint_context())); EXPECT_EQ( mock_layer->parent_matrix(), SkMatrix::Concat(SkMatrix::Concat(initial_transform, layer1_transform), @@ -184,10 +184,10 @@ TEST_F(TransformLayerTest, NestedSeparated) { layer2_transform.mapRect(mock_layer2->paint_bounds())); EXPECT_EQ(mock_layer1->paint_bounds(), child_path.getBounds()); EXPECT_EQ(layer1->paint_bounds(), expected_layer1_bounds); - EXPECT_TRUE(mock_layer2->needs_painting()); - EXPECT_TRUE(layer2->needs_painting()); - EXPECT_TRUE(mock_layer1->needs_painting()); - EXPECT_TRUE(layer1->needs_painting()); + EXPECT_TRUE(mock_layer2->needs_painting(paint_context())); + EXPECT_TRUE(layer2->needs_painting(paint_context())); + EXPECT_TRUE(mock_layer1->needs_painting(paint_context())); + EXPECT_TRUE(layer1->needs_painting(paint_context())); EXPECT_EQ(mock_layer1->parent_matrix(), SkMatrix::Concat(initial_transform, layer1_transform)); EXPECT_EQ( diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 6db5a8103f30b..b959438291112 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -171,7 +171,7 @@ std::unique_ptr RasterCache::RasterizeLayer( context->has_platform_view ? nullptr : context->raster_cache, context->checkerboard_offscreen_layers, context->frame_device_pixel_ratio}; - if (layer->needs_painting()) { + if (layer->needs_painting(paintContext)) { layer->Paint(paintContext); } }); diff --git a/flow/scene_update_context.cc b/flow/scene_update_context.cc index 461b0914433a2..d96e959cb300a 100644 --- a/flow/scene_update_context.cc +++ b/flow/scene_update_context.cc @@ -338,7 +338,7 @@ SceneUpdateContext::Frame::~Frame() { } void SceneUpdateContext::Frame::AddPaintLayer(Layer* layer) { - FML_DCHECK(layer->needs_painting()); + FML_DCHECK(!layer->is_empty()); paint_layers_.push_back(layer); paint_bounds_.join(layer->paint_bounds()); } diff --git a/flow/testing/mock_layer.cc b/flow/testing/mock_layer.cc index b32bdb23abc09..5fc9f60ee840e 100644 --- a/flow/testing/mock_layer.cc +++ b/flow/testing/mock_layer.cc @@ -33,7 +33,7 @@ void MockLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) { } void MockLayer::Paint(PaintContext& context) const { - FML_DCHECK(needs_painting()); + FML_DCHECK(needs_painting(context)); context.leaf_nodes_canvas->drawPath(fake_paint_path_, fake_paint_); } diff --git a/flow/testing/mock_layer_unittests.cc b/flow/testing/mock_layer_unittests.cc index ebb837ca8b8dd..99705b81d1053 100644 --- a/flow/testing/mock_layer_unittests.cc +++ b/flow/testing/mock_layer_unittests.cc @@ -19,7 +19,7 @@ TEST_F(MockLayerTest, PaintBeforePreollDies) { auto layer = std::make_shared(path, SkPaint()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } TEST_F(MockLayerTest, PaintingEmptyLayerDies) { @@ -29,7 +29,7 @@ TEST_F(MockLayerTest, PaintingEmptyLayerDies) { EXPECT_EQ(layer->paint_bounds(), SkPath().getBounds()); EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), - "needs_painting\\(\\)"); + "needs_painting\\(context\\)"); } #endif @@ -48,7 +48,7 @@ TEST_F(MockLayerTest, SimpleParams) { layer->Preroll(preroll_context(), start_matrix); EXPECT_EQ(preroll_context()->has_platform_view, false); EXPECT_EQ(layer->paint_bounds(), path.getBounds()); - EXPECT_TRUE(layer->needs_painting()); + EXPECT_TRUE(layer->needs_painting(paint_context())); EXPECT_FALSE(layer->needs_system_composite()); EXPECT_EQ(layer->parent_mutators(), std::vector{Mutator(scale_matrix)}); EXPECT_EQ(layer->parent_matrix(), start_matrix);