Flutter Engine
container_layer_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/container_layer.h"
6 
7 #include "flutter/flow/testing/diff_context_test.h"
8 #include "flutter/flow/testing/layer_test.h"
9 #include "flutter/flow/testing/mock_layer.h"
10 #include "flutter/fml/macros.h"
11 #include "flutter/testing/mock_canvas.h"
12 
13 namespace flutter {
14 namespace testing {
15 
17 
18 #ifndef NDEBUG
19 TEST_F(ContainerLayerTest, LayerWithParentHasPlatformView) {
20  auto layer = std::make_shared<ContainerLayer>();
21 
22  preroll_context()->has_platform_view = true;
23  EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context(), SkMatrix()),
24  "!context->has_platform_view");
25 }
26 
27 TEST_F(ContainerLayerTest, PaintingEmptyLayerDies) {
28  auto layer = std::make_shared<ContainerLayer>();
29 
30  layer->Preroll(preroll_context(), SkMatrix());
31  EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
32  EXPECT_FALSE(layer->needs_painting(paint_context()));
33 
34  EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
35  "needs_painting\\(context\\)");
36 }
37 
38 TEST_F(ContainerLayerTest, PaintBeforePrerollDies) {
39  SkPath child_path;
40  child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
41  auto mock_layer = std::make_shared<MockLayer>(child_path);
42  auto layer = std::make_shared<ContainerLayer>();
43  layer->Add(mock_layer);
44 
45  EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
46  EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
47  "needs_painting\\(context\\)");
48 }
49 #endif
50 
52  SkPath child_path;
53  child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
54  SkPaint child_paint(SkColors::kGreen);
55  SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
56 
57  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
58  auto layer = std::make_shared<ContainerLayer>();
59  layer->Add(mock_layer);
60 
61  layer->Preroll(preroll_context(), initial_transform);
62  EXPECT_FALSE(preroll_context()->has_platform_view);
63  EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
64  EXPECT_EQ(layer->paint_bounds(), child_path.getBounds());
65  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
66  EXPECT_TRUE(layer->needs_painting(paint_context()));
67  EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
68  EXPECT_EQ(mock_layer->parent_cull_rect(), kGiantRect);
69 
70  layer->Paint(paint_context());
71  EXPECT_EQ(mock_canvas().draw_calls(),
72  std::vector({MockCanvas::DrawCall{
73  0, MockCanvas::DrawPathData{child_path, child_paint}}}));
74 }
75 
77  SkPath child_path1;
78  child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
79  SkPath child_path2;
80  child_path2.addRect(8.0f, 2.0f, 16.5f, 14.5f);
81  SkPaint child_paint1(SkColors::kGray);
82  SkPaint child_paint2(SkColors::kGreen);
83  SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
84 
85  auto mock_layer1 = std::make_shared<MockLayer>(
86  child_path1, child_paint1, true /* fake_has_platform_view */);
87  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
88  auto layer = std::make_shared<ContainerLayer>();
89  layer->Add(mock_layer1);
90  layer->Add(mock_layer2);
91 
92  SkRect expected_total_bounds = child_path1.getBounds();
93  expected_total_bounds.join(child_path2.getBounds());
94  layer->Preroll(preroll_context(), initial_transform);
95  EXPECT_TRUE(preroll_context()->has_platform_view);
96  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
97  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
98  EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
99  EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
100  EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
101  EXPECT_TRUE(layer->needs_painting(paint_context()));
102  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
103  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
104  EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
105  EXPECT_EQ(mock_layer2->parent_cull_rect(),
106  kGiantRect); // Siblings are independent
107 
108  layer->Paint(paint_context());
109  EXPECT_EQ(
110  mock_canvas().draw_calls(),
111  std::vector({MockCanvas::DrawCall{
112  0, MockCanvas::DrawPathData{child_path1, child_paint1}},
114  child_path2, child_paint2}}}));
115 }
116 
117 TEST_F(ContainerLayerTest, MultipleWithEmpty) {
118  SkPath child_path1;
119  child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
120  SkPaint child_paint1(SkColors::kGray);
121  SkPaint child_paint2(SkColors::kGreen);
122  SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
123 
124  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
125  auto mock_layer2 = std::make_shared<MockLayer>(SkPath(), child_paint2);
126  auto layer = std::make_shared<ContainerLayer>();
127  layer->Add(mock_layer1);
128  layer->Add(mock_layer2);
129 
130  layer->Preroll(preroll_context(), initial_transform);
131  EXPECT_FALSE(preroll_context()->has_platform_view);
132  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
133  EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds());
134  EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds());
135  EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
136  EXPECT_FALSE(mock_layer2->needs_painting(paint_context()));
137  EXPECT_TRUE(layer->needs_painting(paint_context()));
138  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
139  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
140  EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
141  EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
142 
143  layer->Paint(paint_context());
144  EXPECT_EQ(mock_canvas().draw_calls(),
145  std::vector({MockCanvas::DrawCall{
146  0, MockCanvas::DrawPathData{child_path1, child_paint1}}}));
147 }
148 
149 TEST_F(ContainerLayerTest, NeedsSystemComposite) {
150  SkPath child_path1;
151  child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
152  SkPath child_path2;
153  child_path2.addRect(8.0f, 2.0f, 16.5f, 14.5f);
154  SkPaint child_paint1(SkColors::kGray);
155  SkPaint child_paint2(SkColors::kGreen);
156  SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
157 
158  auto mock_layer1 = std::make_shared<MockLayer>(
159  child_path1, child_paint1, false /* fake_has_platform_view */);
160  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
161  auto layer = std::make_shared<ContainerLayer>();
162  layer->Add(mock_layer1);
163  layer->Add(mock_layer2);
164 
165  SkRect expected_total_bounds = child_path1.getBounds();
166  expected_total_bounds.join(child_path2.getBounds());
167  layer->Preroll(preroll_context(), initial_transform);
168  EXPECT_FALSE(preroll_context()->has_platform_view);
169  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
170  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
171  EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
172  EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
173  EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
174  EXPECT_TRUE(layer->needs_painting(paint_context()));
175  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
176  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
177  EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
178  EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
179 
180  layer->Paint(paint_context());
181  EXPECT_EQ(
182  mock_canvas().draw_calls(),
183  std::vector({MockCanvas::DrawCall{
184  0, MockCanvas::DrawPathData{child_path1, child_paint1}},
186  child_path2, child_paint2}}}));
187 }
188 
189 TEST_F(ContainerLayerTest, MergedOneChild) {
190  SkPath child_path;
191  child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
192  SkPaint child_paint(SkColors::kGreen);
193  SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
194 
195  auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
196  auto layer = std::make_shared<MergedContainerLayer>();
197  layer->Add(mock_layer);
198 
199  layer->Preroll(preroll_context(), initial_transform);
200  EXPECT_FALSE(preroll_context()->has_platform_view);
201  EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
202  EXPECT_EQ(layer->paint_bounds(), child_path.getBounds());
203  EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
204  EXPECT_TRUE(layer->needs_painting(paint_context()));
205  EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
206  EXPECT_EQ(mock_layer->parent_cull_rect(), kGiantRect);
207 
208  layer->Paint(paint_context());
209  EXPECT_EQ(mock_canvas().draw_calls(),
210  std::vector({MockCanvas::DrawCall{
211  0, MockCanvas::DrawPathData{child_path, child_paint}}}));
212 }
213 
214 TEST_F(ContainerLayerTest, MergedMultipleChildren) {
215  SkPath child_path1;
216  child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
217  SkPath child_path2;
218  child_path2.addRect(58.0f, 2.0f, 16.5f, 14.5f);
219  SkPaint child_paint1(SkColors::kGray);
220  SkPaint child_paint2(SkColors::kGreen);
221  SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
222 
223  auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
224  auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
225  auto layer = std::make_shared<MergedContainerLayer>();
226  layer->Add(mock_layer1);
227  layer->Add(mock_layer2);
228 
229  SkRect expected_total_bounds = child_path1.getBounds();
230  expected_total_bounds.join(child_path2.getBounds());
231  layer->Preroll(preroll_context(), initial_transform);
232  EXPECT_FALSE(preroll_context()->has_platform_view);
233  EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
234  EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
235  EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
236  EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
237  EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
238  EXPECT_TRUE(layer->needs_painting(paint_context()));
239  EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
240  EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
241  EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
242  EXPECT_EQ(mock_layer2->parent_cull_rect(),
243  kGiantRect); // Siblings are independent
244 
245  layer->Paint(paint_context());
246  EXPECT_EQ(
247  mock_canvas().draw_calls(),
248  std::vector({MockCanvas::DrawCall{
249  0, MockCanvas::DrawPathData{child_path1, child_paint1}},
251  child_path2, child_paint2}}}));
252 }
253 
254 #ifdef FLUTTER_ENABLE_DIFF_CONTEXT
255 
256 using ContainerLayerDiffTest = DiffContextTest;
257 
258 // Insert PictureLayer amongst container layers
259 TEST_F(ContainerLayerDiffTest, PictureLayerInsertion) {
260  auto pic1 = CreatePicture(SkRect::MakeLTRB(0, 0, 50, 50), 1);
261  auto pic2 = CreatePicture(SkRect::MakeLTRB(100, 0, 150, 50), 1);
262  auto pic3 = CreatePicture(SkRect::MakeLTRB(200, 0, 250, 50), 1);
263 
264  MockLayerTree t1;
265 
266  auto t1_c1 = CreateContainerLayer(CreatePictureLayer(pic1));
267  t1.root()->Add(t1_c1);
268 
269  auto t1_c2 = CreateContainerLayer(CreatePictureLayer(pic2));
270  t1.root()->Add(t1_c2);
271 
272  auto damage = DiffLayerTree(t1, MockLayerTree());
273  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 150, 50));
274 
275  // Add in the middle
276 
277  MockLayerTree t2;
278  auto t2_c1 = CreateContainerLayer(CreatePictureLayer(pic1));
279  t2_c1->AssignOldLayer(t1_c1.get());
280  t2.root()->Add(t2_c1);
281 
282  t2.root()->Add(CreatePictureLayer(pic3));
283 
284  auto t2_c2 = CreateContainerLayer(CreatePictureLayer(pic2));
285  t2_c2->AssignOldLayer(t1_c2.get());
286  t2.root()->Add(t2_c2);
287 
288  damage = DiffLayerTree(t2, t1);
289  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 50));
290 
291  // Add in the beginning
292 
293  t2 = MockLayerTree();
294  t2.root()->Add(CreatePictureLayer(pic3));
295  t2.root()->Add(t2_c1);
296  t2.root()->Add(t2_c2);
297  damage = DiffLayerTree(t2, t1);
298  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 50));
299 
300  // Add at the end
301 
302  t2 = MockLayerTree();
303  t2.root()->Add(t2_c1);
304  t2.root()->Add(t2_c2);
305  t2.root()->Add(CreatePictureLayer(pic3));
306  damage = DiffLayerTree(t2, t1);
307  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 50));
308 }
309 
310 // Insert picture layer amongst other picture layers
311 TEST_F(ContainerLayerDiffTest, PictureInsertion) {
312  auto pic1 = CreatePicture(SkRect::MakeLTRB(0, 0, 50, 50), 1);
313  auto pic2 = CreatePicture(SkRect::MakeLTRB(100, 0, 150, 50), 1);
314  auto pic3 = CreatePicture(SkRect::MakeLTRB(200, 0, 250, 50), 1);
315 
316  MockLayerTree t1;
317  t1.root()->Add(CreatePictureLayer(pic1));
318  t1.root()->Add(CreatePictureLayer(pic2));
319 
320  auto damage = DiffLayerTree(t1, MockLayerTree());
321  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 150, 50));
322 
323  MockLayerTree t2;
324  t2.root()->Add(CreatePictureLayer(pic3));
325  t2.root()->Add(CreatePictureLayer(pic1));
326  t2.root()->Add(CreatePictureLayer(pic2));
327 
328  damage = DiffLayerTree(t2, t1);
329  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 50));
330 
331  MockLayerTree t3;
332  t3.root()->Add(CreatePictureLayer(pic1));
333  t3.root()->Add(CreatePictureLayer(pic3));
334  t3.root()->Add(CreatePictureLayer(pic2));
335 
336  damage = DiffLayerTree(t3, t1);
337  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 50));
338 
339  MockLayerTree t4;
340  t4.root()->Add(CreatePictureLayer(pic1));
341  t4.root()->Add(CreatePictureLayer(pic2));
342  t4.root()->Add(CreatePictureLayer(pic3));
343 
344  damage = DiffLayerTree(t4, t1);
345  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 50));
346 }
347 
348 TEST_F(ContainerLayerDiffTest, LayerDeletion) {
349  auto path1 = SkPath().addRect(SkRect::MakeLTRB(0, 0, 50, 50));
350  auto path2 = SkPath().addRect(SkRect::MakeLTRB(100, 0, 150, 50));
351  auto path3 = SkPath().addRect(SkRect::MakeLTRB(200, 0, 250, 50));
352 
353  auto c1 = CreateContainerLayer(std::make_shared<MockLayer>(path1));
354  auto c2 = CreateContainerLayer(std::make_shared<MockLayer>(path2));
355  auto c3 = CreateContainerLayer(std::make_shared<MockLayer>(path3));
356 
357  MockLayerTree t1;
358  t1.root()->Add(c1);
359  t1.root()->Add(c2);
360  t1.root()->Add(c3);
361 
362  auto damage = DiffLayerTree(t1, MockLayerTree());
363  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 250, 50));
364 
365  MockLayerTree t2;
366  t2.root()->Add(c2);
367  t2.root()->Add(c3);
368 
369  damage = DiffLayerTree(t2, t1);
370  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 50, 50));
371 
372  MockLayerTree t3;
373  t3.root()->Add(c1);
374  t3.root()->Add(c3);
375 
376  damage = DiffLayerTree(t3, t1);
377  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(100, 0, 150, 50));
378 
379  MockLayerTree t4;
380  t4.root()->Add(c1);
381  t4.root()->Add(c2);
382 
383  damage = DiffLayerTree(t4, t1);
384  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 50));
385 
386  MockLayerTree t5;
387  t5.root()->Add(c1);
388 
389  damage = DiffLayerTree(t5, t1);
390  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(100, 0, 250, 50));
391 
392  MockLayerTree t6;
393  t6.root()->Add(c2);
394 
395  damage = DiffLayerTree(t6, t1);
396  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 250, 50));
397 
398  MockLayerTree t7;
399  t7.root()->Add(c3);
400 
401  damage = DiffLayerTree(t7, t1);
402  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 150, 50));
403 }
404 
405 TEST_F(ContainerLayerDiffTest, ReplaceLayer) {
406  auto path1 = SkPath().addRect(SkRect::MakeLTRB(0, 0, 50, 50));
407  auto path2 = SkPath().addRect(SkRect::MakeLTRB(100, 0, 150, 50));
408  auto path3 = SkPath().addRect(SkRect::MakeLTRB(200, 0, 250, 50));
409 
410  auto path1a = SkPath().addRect(SkRect::MakeLTRB(0, 100, 50, 150));
411  auto path2a = SkPath().addRect(SkRect::MakeLTRB(100, 100, 150, 150));
412  auto path3a = SkPath().addRect(SkRect::MakeLTRB(200, 100, 250, 150));
413 
414  auto c1 = CreateContainerLayer(std::make_shared<MockLayer>(path1));
415  auto c2 = CreateContainerLayer(std::make_shared<MockLayer>(path2));
416  auto c3 = CreateContainerLayer(std::make_shared<MockLayer>(path3));
417 
418  MockLayerTree t1;
419  t1.root()->Add(c1);
420  t1.root()->Add(c2);
421  t1.root()->Add(c3);
422 
423  auto damage = DiffLayerTree(t1, MockLayerTree());
424  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 250, 50));
425 
426  MockLayerTree t2;
427  t2.root()->Add(c1);
428  t2.root()->Add(c2);
429  t2.root()->Add(c3);
430 
431  damage = DiffLayerTree(t2, t1);
432  EXPECT_TRUE(damage.frame_damage.isEmpty());
433 
434  MockLayerTree t3;
435  t3.root()->Add(CreateContainerLayer({std::make_shared<MockLayer>(path1a)}));
436  t3.root()->Add(c2);
437  t3.root()->Add(c3);
438 
439  damage = DiffLayerTree(t3, t1);
440  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(0, 0, 50, 150));
441 
442  MockLayerTree t4;
443  t4.root()->Add(c1);
444  t4.root()->Add(CreateContainerLayer(std::make_shared<MockLayer>(path2a)));
445  t4.root()->Add(c3);
446 
447  damage = DiffLayerTree(t4, t1);
448  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(100, 0, 150, 150));
449 
450  MockLayerTree t5;
451  t5.root()->Add(c1);
452  t5.root()->Add(c2);
453  t5.root()->Add(CreateContainerLayer(std::make_shared<MockLayer>(path3a)));
454 
455  damage = DiffLayerTree(t5, t1);
456  EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 0, 250, 150));
457 }
458 
459 #endif
460 
461 } // namespace testing
462 } // namespace flutter
static constexpr SkRect kGiantRect
Definition: layer.h:37
LayerTestBase<::testing::Test > LayerTest
Definition: layer_test.h:151
TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies)