Flutter Engine
checkerboard_layertree_unittests.cc
Go to the documentation of this file.
1 // Copyright 2013 The Flutter Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "flutter/flow/layers/clip_path_layer.h"
6 #include "flutter/flow/layers/clip_rect_layer.h"
7 #include "flutter/flow/layers/clip_rrect_layer.h"
8 #include "flutter/flow/layers/physical_shape_layer.h"
9 
10 #include "flutter/flow/testing/layer_test.h"
11 #include "flutter/flow/testing/mock_layer.h"
12 #include "flutter/fml/macros.h"
13 #include "flutter/testing/mock_canvas.h"
14 
15 namespace flutter {
16 namespace testing {
17 
19 
20 #ifndef NDEBUG
21 TEST_F(CheckerBoardLayerTest, ClipRectSaveLayerNotCheckBoard) {
22  const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f);
23  const SkRect cull_bounds = SkRect::MakeXYWH(0.0, 0.0, 2.0, 4.0);
24  const SkRect child_bounds = SkRect::MakeXYWH(2.5, 5.0, 4.5, 4.0);
25  const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
26  const SkPath child_path = SkPath().addRect(child_bounds);
27  const SkPaint child_paint = SkPaint(SkColors::kYellow);
28  const SkPaint clip_paint;
29 
30  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
31  auto layer = std::make_shared<ClipRectLayer>(layer_bounds,
33  layer->Add(mock_layer);
34 
35  SkRect intersect_bounds = layer_bounds;
36  SkRect child_intersect_bounds = layer_bounds;
37  intersect_bounds.intersect(cull_bounds);
38  child_intersect_bounds.intersect(child_bounds);
39  preroll_context()->cull_rect = cull_bounds; // Cull child
40 
41  layer->Preroll(preroll_context(), initial_matrix);
42  EXPECT_EQ(preroll_context()->cull_rect, cull_bounds); // Untouched
43  EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
44  EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
45  EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
46  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
47  EXPECT_TRUE(layer->needs_painting(paint_context()));
48  EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
49  EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
50  EXPECT_EQ(mock_layer->parent_mutators(),
51  std::vector({Mutator(layer_bounds)}));
52 
53  layer->Paint(paint_context());
54 
55  EXPECT_EQ(
56  mock_canvas().draw_calls(),
57  std::vector(
60  1, MockCanvas::ClipRectData{layer_bounds, SkClipOp::kIntersect,
61  MockCanvas::kSoft_ClipEdgeStyle}},
63  1,
64  MockCanvas::SaveLayerData{layer_bounds, clip_paint, nullptr, 2}},
66  2, MockCanvas::DrawPathData{child_path, child_paint}},
69 }
70 
71 TEST_F(CheckerBoardLayerTest, ClipRectSaveLayerCheckBoard) {
72  const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f);
73  const SkRect cull_bounds = SkRect::MakeXYWH(0.0, 0.0, 2.0, 4.0);
74  const SkRect child_bounds = SkRect::MakeXYWH(2.5, 5.0, 4.5, 4.0);
75  const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
76  const SkPath child_path = SkPath().addRect(child_bounds);
77  const SkPaint child_paint = SkPaint(SkColors::kYellow);
78  const SkPaint clip_paint;
79 
80  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
81  auto layer = std::make_shared<ClipRectLayer>(layer_bounds,
83  layer->Add(mock_layer);
84 
85  SkRect intersect_bounds = layer_bounds;
86  SkRect child_intersect_bounds = layer_bounds;
87  intersect_bounds.intersect(cull_bounds);
88  child_intersect_bounds.intersect(child_bounds);
89  preroll_context()->cull_rect = cull_bounds; // Cull child
90 
91  layer->Preroll(preroll_context(), initial_matrix);
92  EXPECT_EQ(preroll_context()->cull_rect, cull_bounds); // Untouched
93  EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
94  EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
95  EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
96  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
97  EXPECT_TRUE(layer->needs_painting(paint_context()));
98  EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
99  EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
100  EXPECT_EQ(mock_layer->parent_mutators(),
101  std::vector({Mutator(layer_bounds)}));
102 
103  layer->Paint(check_board_context());
104 
105  EXPECT_NE(
106  mock_canvas().draw_calls(),
107  std::vector(
110  1, MockCanvas::ClipRectData{layer_bounds, SkClipOp::kIntersect,
111  MockCanvas::kSoft_ClipEdgeStyle}},
113  1,
114  MockCanvas::SaveLayerData{layer_bounds, clip_paint, nullptr, 2}},
116  2, MockCanvas::DrawPathData{child_path, child_paint}},
119 }
120 
121 TEST_F(CheckerBoardLayerTest, ClipPathSaveLayerNotCheckBoard) {
122  const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f);
123  const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0);
124  const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
125  const SkPath child_path = SkPath().addRect(child_bounds);
126  const SkPath layer_path = SkPath().addRect(layer_bounds);
127  const SkPaint child_paint = SkPaint(SkColors::kYellow);
128  const SkPaint clip_paint;
129  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
130  auto layer =
131  std::make_shared<ClipPathLayer>(layer_path, Clip::antiAliasWithSaveLayer);
132  layer->Add(mock_layer);
133 
134  layer->Preroll(preroll_context(), initial_matrix);
135  EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched
136  EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
137  EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
138  EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
139  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
140  EXPECT_TRUE(layer->needs_painting(paint_context()));
141  EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
142  EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
143  EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)}));
144 
145  layer->Paint(paint_context());
146  EXPECT_EQ(
147  mock_canvas().draw_calls(),
148  std::vector(
151  1, MockCanvas::ClipRectData{layer_bounds, SkClipOp::kIntersect,
152  MockCanvas::kSoft_ClipEdgeStyle}},
154  1,
155  MockCanvas::SaveLayerData{child_bounds, clip_paint, nullptr, 2}},
157  2, MockCanvas::DrawPathData{child_path, child_paint}},
160 }
161 
162 TEST_F(CheckerBoardLayerTest, ClipPathSaveLayerCheckBoard) {
163  const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f);
164  const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0);
165  const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
166  const SkPath child_path = SkPath().addRect(child_bounds);
167  const SkPath layer_path = SkPath().addRect(layer_bounds);
168  const SkPaint child_paint = SkPaint(SkColors::kYellow);
169  const SkPaint clip_paint;
170  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
171  auto layer =
172  std::make_shared<ClipPathLayer>(layer_path, Clip::antiAliasWithSaveLayer);
173  layer->Add(mock_layer);
174 
175  layer->Preroll(preroll_context(), initial_matrix);
176  EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched
177  EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
178  EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
179  EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
180  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
181  EXPECT_TRUE(layer->needs_painting(paint_context()));
182  EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
183  EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
184  EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)}));
185 
186  layer->Paint(check_board_context());
187  EXPECT_NE(
188  mock_canvas().draw_calls(),
189  std::vector(
192  1, MockCanvas::ClipRectData{layer_bounds, SkClipOp::kIntersect,
193  MockCanvas::kSoft_ClipEdgeStyle}},
195  1,
196  MockCanvas::SaveLayerData{child_bounds, clip_paint, nullptr, 2}},
198  2, MockCanvas::DrawPathData{child_path, child_paint}},
201 }
202 
203 TEST_F(CheckerBoardLayerTest, ClipRRectSaveLayerNotCheckBoard) {
204  const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f);
205  const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0);
206  const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
207  const SkPath child_path = SkPath().addRect(child_bounds);
208  const SkRRect layer_rrect = SkRRect::MakeRect(layer_bounds);
209  const SkPaint child_paint = SkPaint(SkColors::kYellow);
210  const SkPaint clip_paint;
211  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
212  auto layer = std::make_shared<ClipRRectLayer>(layer_rrect,
214  layer->Add(mock_layer);
215 
216  layer->Preroll(preroll_context(), initial_matrix);
217  EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched
218  EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
219  EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
220  EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
221  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
222  EXPECT_TRUE(layer->needs_painting(paint_context()));
223  EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
224  EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
225  EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)}));
226 
227  layer->Paint(paint_context());
228  EXPECT_EQ(
229  mock_canvas().draw_calls(),
230  std::vector(
233  1, MockCanvas::ClipRectData{layer_bounds, SkClipOp::kIntersect,
234  MockCanvas::kSoft_ClipEdgeStyle}},
236  1,
237  MockCanvas::SaveLayerData{child_bounds, clip_paint, nullptr, 2}},
239  2, MockCanvas::DrawPathData{child_path, child_paint}},
242 }
243 
244 TEST_F(CheckerBoardLayerTest, ClipRRectSaveLayerCheckBoard) {
245  const SkMatrix initial_matrix = SkMatrix::Translate(0.5f, 1.0f);
246  const SkRect child_bounds = SkRect::MakeXYWH(1.0, 2.0, 2.0, 2.0);
247  const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
248  const SkPath child_path = SkPath().addRect(child_bounds);
249  const SkRRect layer_rrect = SkRRect::MakeRect(layer_bounds);
250  const SkPaint child_paint = SkPaint(SkColors::kYellow);
251  const SkPaint clip_paint;
252  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
253  auto layer = std::make_shared<ClipRRectLayer>(layer_rrect,
255  layer->Add(mock_layer);
256 
257  layer->Preroll(preroll_context(), initial_matrix);
258  EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched
259  EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
260  EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
261  EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
262  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
263  EXPECT_TRUE(layer->needs_painting(paint_context()));
264  EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
265  EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
266  EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)}));
267 
268  layer->Paint(check_board_context());
269  EXPECT_NE(
270  mock_canvas().draw_calls(),
271  std::vector(
274  1, MockCanvas::ClipRectData{layer_bounds, SkClipOp::kIntersect,
275  MockCanvas::kSoft_ClipEdgeStyle}},
277  1,
278  MockCanvas::SaveLayerData{child_bounds, clip_paint, nullptr, 2}},
280  2, MockCanvas::DrawPathData{child_path, child_paint}},
283 }
284 
285 TEST_F(CheckerBoardLayerTest, PhysicalSaveLayerNotCheckBoard) {
286  constexpr float initial_elevation = 20.0f;
287  SkPath layer_path;
288  layer_path.addRect(0, 0, 8, 8).close();
289  auto layer = std::make_shared<PhysicalShapeLayer>(
290  SK_ColorGREEN, SK_ColorBLACK, initial_elevation, layer_path,
292 
293  layer->Preroll(preroll_context(), SkMatrix());
294  // The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
295  // their shadows , so we do not do any painting there.
296  EXPECT_EQ(layer->paint_bounds(),
298  layer_path, initial_elevation, 1.0f, SkMatrix()));
299  EXPECT_TRUE(layer->needs_painting(paint_context()));
300  EXPECT_EQ(layer->elevation(), initial_elevation);
301 
302  const SkRect paint_bounds = SkRect::MakeXYWH(0, 0, 8, 8);
303  const SkPaint clip_paint;
304  SkPaint layer_paint;
305  layer_paint.setColor(SK_ColorGREEN);
306  layer_paint.setAntiAlias(true);
307  layer->Paint(paint_context());
308  EXPECT_EQ(
309  mock_canvas().draw_calls(),
310  std::vector(
314  1, MockCanvas::ClipRectData{paint_bounds, SkClipOp::kIntersect,
315  MockCanvas::kSoft_ClipEdgeStyle}},
317  1, MockCanvas::SaveLayerData{layer->paint_bounds(), clip_paint,
318  nullptr, 2}},
322 }
323 
324 TEST_F(CheckerBoardLayerTest, PhysicalSaveLayerCheckBoard) {
325  constexpr float initial_elevation = 20.0f;
326  SkPath layer_path;
327  layer_path.addRect(0, 0, 8, 8).close();
328  auto layer = std::make_shared<PhysicalShapeLayer>(
329  SK_ColorGREEN, SK_ColorBLACK, initial_elevation, layer_path,
331 
332  layer->Preroll(preroll_context(), SkMatrix());
333  // The Fuchsia system compositor handles all elevated PhysicalShapeLayers and
334  // their shadows , so we do not do any painting there.
335  EXPECT_EQ(layer->paint_bounds(),
337  layer_path, initial_elevation, 1.0f, SkMatrix()));
338  EXPECT_TRUE(layer->needs_painting(paint_context()));
339  EXPECT_EQ(layer->elevation(), initial_elevation);
340 
341  const SkRect paint_bounds = SkRect::MakeXYWH(0, 0, 8, 8);
342  const SkPaint clip_paint;
343  SkPaint layer_paint;
344  layer_paint.setColor(SK_ColorGREEN);
345  layer_paint.setAntiAlias(true);
346  layer->Paint(check_board_context());
347  EXPECT_NE(
348  mock_canvas().draw_calls(),
349  std::vector(
353  1, MockCanvas::ClipRectData{paint_bounds, SkClipOp::kIntersect,
354  MockCanvas::kSoft_ClipEdgeStyle}},
356  1, MockCanvas::SaveLayerData{layer->paint_bounds(), clip_paint,
357  nullptr, 2}},
361 }
362 
363 #endif
364 } // namespace testing
365 } // namespace flutter
static SkRect ComputeShadowBounds(const SkPath &path, float elevation, SkScalar dpr, const SkMatrix &ctm)
static constexpr SkRect kGiantRect
Definition: layer.h:37
LayerTestBase<::testing::Test > LayerTest
Definition: layer_test.h:151
TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies)