Flutter Engine
The Flutter Engine
transform_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/transform_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
12namespace flutter {
13namespace testing {
14
16
17#ifndef NDEBUG
18TEST_F(TransformLayerTest, PaintingEmptyLayerDies) {
19 auto layer = std::make_shared<TransformLayer>(SkMatrix()); // identity
20
21 layer->Preroll(preroll_context());
22 EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
23 EXPECT_EQ(layer->child_paint_bounds(), SkRect::MakeEmpty());
24 EXPECT_FALSE(layer->needs_painting(paint_context()));
25
26 EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
27 "needs_painting\\(context\\)");
28}
29
30TEST_F(TransformLayerTest, PaintBeforePrerollDies) {
31 SkPath child_path;
32 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
33 auto mock_layer = std::make_shared<MockLayer>(child_path, DlPaint());
34 auto layer = std::make_shared<TransformLayer>(SkMatrix()); // identity
35 layer->Add(mock_layer);
36
37 EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
38 "needs_painting\\(context\\)");
39}
40#endif
41
43 SkPath child_path;
44 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
45 SkRect cull_rect = SkRect::MakeXYWH(2.0f, 2.0f, 14.0f, 14.0f);
46 auto mock_layer = std::make_shared<MockLayer>(child_path, DlPaint());
47 auto layer = std::make_shared<TransformLayer>(SkMatrix()); // identity
48 layer->Add(mock_layer);
49
50 preroll_context()->state_stack.set_preroll_delegate(cull_rect);
51 layer->Preroll(preroll_context());
52 EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
53 EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
54 EXPECT_EQ(layer->child_paint_bounds(), mock_layer->paint_bounds());
55 EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
56 EXPECT_TRUE(layer->needs_painting(paint_context()));
57 EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix()); // identity
58 EXPECT_EQ(mock_layer->parent_cull_rect(), cull_rect);
59 EXPECT_EQ(mock_layer->parent_mutators().stack_count(), 0u);
60 EXPECT_EQ(mock_layer->parent_mutators(), MutatorsStack());
61
62 layer->Paint(display_list_paint_context());
63 DisplayListBuilder expected_builder;
64 /* (Transform)layer::Paint */ {
65 expected_builder.Save();
66 {
67 expected_builder.Transform(SkMatrix());
68 /* mock_layer::Paint */ {
69 expected_builder.DrawPath(child_path, DlPaint());
70 }
71 }
72 expected_builder.Restore();
73 }
74 EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
75}
76
78 SkPath child_path;
79 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
80 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
81 SkRect local_cull_rect = SkRect::MakeXYWH(2.0f, 2.0f, 14.0f, 14.0f);
82 SkRect device_cull_rect = initial_transform.mapRect(local_cull_rect);
83 SkMatrix layer_transform = SkMatrix::Translate(2.5f, 2.5f);
84 SkMatrix inverse_layer_transform;
85 EXPECT_TRUE(layer_transform.invert(&inverse_layer_transform));
86
87 auto mock_layer = std::make_shared<MockLayer>(child_path, DlPaint());
88 auto layer = std::make_shared<TransformLayer>(layer_transform);
89 layer->Add(mock_layer);
90
91 preroll_context()->state_stack.set_preroll_delegate(device_cull_rect,
92 initial_transform);
93 layer->Preroll(preroll_context());
94 EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
95 EXPECT_EQ(layer->paint_bounds(),
96 layer_transform.mapRect(mock_layer->paint_bounds()));
97 EXPECT_EQ(layer->child_paint_bounds(), mock_layer->paint_bounds());
98 EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
99 EXPECT_TRUE(layer->needs_painting(paint_context()));
100 EXPECT_EQ(mock_layer->parent_matrix(),
101 SkMatrix::Concat(initial_transform, layer_transform));
102 EXPECT_EQ(mock_layer->parent_cull_rect(),
103 inverse_layer_transform.mapRect(local_cull_rect));
104 EXPECT_EQ(mock_layer->parent_mutators(),
105 std::vector({Mutator(layer_transform)}));
106
107 layer->Paint(display_list_paint_context());
108 DisplayListBuilder expected_builder;
109 /* (Transform)layer::Paint */ {
110 expected_builder.Save();
111 {
112 expected_builder.Transform(layer_transform);
113 /* mock_layer::Paint */ {
114 expected_builder.DrawPath(child_path, DlPaint());
115 }
116 }
117 expected_builder.Restore();
118 }
119 EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
120}
121
123 SkPath child_path;
124 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
125 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
126 SkRect local_cull_rect = SkRect::MakeXYWH(2.0f, 2.0f, 14.0f, 14.0f);
127 SkRect device_cull_rect = initial_transform.mapRect(local_cull_rect);
128 SkMatrix layer_transform = SkMatrix::Translate(2.5f, 3.5f);
129 SkMatrix inverse_layer_transform;
130 EXPECT_TRUE(layer_transform.invert(&inverse_layer_transform));
131
132 auto mock_layer = std::make_shared<MockLayer>(child_path, DlPaint());
133 auto layer = std::make_shared<TransformLayer>(SkM44::Translate(2.5f, 3.5f));
134 layer->Add(mock_layer);
135
136 preroll_context()->state_stack.set_preroll_delegate(device_cull_rect,
137 initial_transform);
138 layer->Preroll(preroll_context());
139 EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
140 EXPECT_EQ(layer->paint_bounds(),
141 layer_transform.mapRect(mock_layer->paint_bounds()));
142 EXPECT_EQ(layer->child_paint_bounds(), mock_layer->paint_bounds());
143 EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
144 EXPECT_TRUE(layer->needs_painting(paint_context()));
145 EXPECT_EQ(mock_layer->parent_matrix(),
146 SkMatrix::Concat(initial_transform, layer_transform));
147 EXPECT_EQ(mock_layer->parent_cull_rect(),
148 inverse_layer_transform.mapRect(local_cull_rect));
149 EXPECT_EQ(mock_layer->parent_mutators(),
150 std::vector({Mutator(layer_transform)}));
151
152 layer->Paint(display_list_paint_context());
153 DisplayListBuilder expected_builder;
154 /* (Transform)layer::Paint */ {
155 expected_builder.Save();
156 {
157 expected_builder.Transform(layer_transform);
158 /* mock_layer::Paint */ {
159 expected_builder.DrawPath(child_path, DlPaint());
160 }
161 }
162 expected_builder.Restore();
163 }
164 EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
165}
166
168 SkPath child_path;
169 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
170 SkMatrix initial_transform = SkMatrix::Translate(-2.0f, -2.0f);
171 SkRect local_cull_rect = SkRect::MakeXYWH(4.0f, 4.0f, 16.0f, 16.0f);
172 SkRect device_cull_rect = initial_transform.mapRect(local_cull_rect);
173 SkM44 layer_transform44 = SkM44();
174 layer_transform44.preTranslate(1.0f, 1.0f);
175 // 20 degrees around the X axis
176 layer_transform44.preConcat(SkM44::Rotate({1.0f, 0.0f, 0.0f}, M_PI / 9.0f));
177 // 10 degrees around the Y axis
178 layer_transform44.preConcat(SkM44::Rotate({0.0f, 1.0f, 0.0f}, M_PI / 18.0f));
179 SkM44 inverse_layer_transform44;
180 EXPECT_TRUE(layer_transform44.invert(&inverse_layer_transform44));
181 SkMatrix layer_transform = layer_transform44.asM33();
182 SkMatrix inverse_layer_transform = inverse_layer_transform44.asM33();
183
184 auto mock_layer = std::make_shared<MockLayer>(child_path, DlPaint());
185 auto layer = std::make_shared<TransformLayer>(layer_transform44);
186 layer->Add(mock_layer);
187
188 preroll_context()->state_stack.set_preroll_delegate(device_cull_rect,
189 initial_transform);
190 layer->Preroll(preroll_context());
191 EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
192 EXPECT_EQ(layer->paint_bounds(),
193 layer_transform.mapRect(mock_layer->paint_bounds()));
194 EXPECT_EQ(layer->child_paint_bounds(), mock_layer->paint_bounds());
195 EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
196 EXPECT_TRUE(layer->needs_painting(paint_context()));
197 EXPECT_EQ(mock_layer->parent_matrix(),
198 SkMatrix::Concat(initial_transform, layer_transform));
199
200 // Even having switched to binary-ieee friendly numbers for the
201 // initial conditions, these numbers which are based on a matrix
202 // concatenation and inversion still aren't exact, so we are using
203 // fuzzy float comparisons to check them.
204 SkRect parent_cull_rect = mock_layer->parent_cull_rect();
205 SkRect expect_parent_cull_rect =
206 inverse_layer_transform.mapRect(local_cull_rect);
207 EXPECT_FLOAT_EQ(parent_cull_rect.fLeft, expect_parent_cull_rect.fLeft);
208 EXPECT_FLOAT_EQ(parent_cull_rect.fTop, expect_parent_cull_rect.fTop);
209 EXPECT_FLOAT_EQ(parent_cull_rect.fRight, expect_parent_cull_rect.fRight);
210 EXPECT_FLOAT_EQ(parent_cull_rect.fBottom, expect_parent_cull_rect.fBottom);
211
212 EXPECT_EQ(mock_layer->parent_mutators(),
213 std::vector({Mutator(layer_transform)}));
214
215 layer->Paint(display_list_paint_context());
216 DisplayListBuilder expected_builder;
217 /* (Transform)layer::Paint */ {
218 expected_builder.Save();
219 {
220 expected_builder.Transform(layer_transform44);
221 /* mock_layer::Paint */ {
222 expected_builder.DrawPath(child_path, DlPaint());
223 }
224 }
225 expected_builder.Restore();
226 }
227 EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
228}
229
230TEST_F(TransformLayerTest, Nested) {
231 SkPath child_path;
232 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
233 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
234 SkRect local_cull_rect = SkRect::MakeXYWH(2.0f, 2.0f, 14.0f, 14.0f);
235 SkRect device_cull_rect = initial_transform.mapRect(local_cull_rect);
236 SkMatrix layer1_transform = SkMatrix::Translate(2.5f, 2.5f);
237 SkMatrix layer2_transform = SkMatrix::Translate(3.5f, 3.5f);
238 SkMatrix inverse_layer1_transform, inverse_layer2_transform;
239 EXPECT_TRUE(layer1_transform.invert(&inverse_layer1_transform));
240 EXPECT_TRUE(layer2_transform.invert(&inverse_layer2_transform));
241
242 auto mock_layer = std::make_shared<MockLayer>(child_path, DlPaint());
243 auto layer1 = std::make_shared<TransformLayer>(layer1_transform);
244 auto layer2 = std::make_shared<TransformLayer>(layer2_transform);
245 layer1->Add(layer2);
246 layer2->Add(mock_layer);
247
248 preroll_context()->state_stack.set_preroll_delegate(device_cull_rect,
249 initial_transform);
250 layer1->Preroll(preroll_context());
251 EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
252 EXPECT_EQ(layer2->paint_bounds(),
253 layer2_transform.mapRect(mock_layer->paint_bounds()));
254 EXPECT_EQ(layer2->child_paint_bounds(), mock_layer->paint_bounds());
255 EXPECT_EQ(layer1->paint_bounds(),
256 layer1_transform.mapRect(layer2->paint_bounds()));
257 EXPECT_EQ(layer1->child_paint_bounds(), layer2->paint_bounds());
258 EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
259 EXPECT_TRUE(layer2->needs_painting(paint_context()));
260 EXPECT_TRUE(layer1->needs_painting(paint_context()));
261 EXPECT_EQ(
262 mock_layer->parent_matrix(),
263 SkMatrix::Concat(SkMatrix::Concat(initial_transform, layer1_transform),
264 layer2_transform));
265 EXPECT_EQ(mock_layer->parent_cull_rect(),
266 inverse_layer2_transform.mapRect(
267 inverse_layer1_transform.mapRect(local_cull_rect)));
268 EXPECT_EQ(
269 mock_layer->parent_mutators(),
270 std::vector({Mutator(layer1_transform), Mutator(layer2_transform)}));
271
272 layer1->Paint(display_list_paint_context());
273 DisplayListBuilder expected_builder;
274 /* (Transform)layer1::Paint */ {
275 expected_builder.Save();
276 {
277 expected_builder.Transform(layer1_transform);
278 /* (Transform)layer1::Paint */ {
279 expected_builder.Save();
280 {
281 expected_builder.Transform(layer2_transform);
282 /* mock_layer::Paint */ {
283 expected_builder.DrawPath(child_path, DlPaint());
284 }
285 }
286 expected_builder.Restore();
287 }
288 }
289 expected_builder.Restore();
290 }
291 EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
292}
293
294TEST_F(TransformLayerTest, NestedSeparated) {
295 SkPath child_path;
296 child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
297 SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
298 SkRect local_cull_rect = SkRect::MakeXYWH(2.0f, 2.0f, 14.0f, 14.0f);
299 SkRect device_cull_rect = initial_transform.mapRect(local_cull_rect);
300 SkMatrix layer1_transform = SkMatrix::Translate(2.5f, 2.5f);
301 SkMatrix layer2_transform = SkMatrix::Translate(3.5f, 3.5f);
302 SkMatrix inverse_layer1_transform, inverse_layer2_transform;
303 EXPECT_TRUE(layer1_transform.invert(&inverse_layer1_transform));
304 EXPECT_TRUE(layer2_transform.invert(&inverse_layer2_transform));
305 DlPaint child_paint1(DlColor::kBlue());
306 DlPaint child_paint2(DlColor::kGreen());
307
308 auto mock_layer1 = std::make_shared<MockLayer>(child_path, child_paint1);
309 auto mock_layer2 = std::make_shared<MockLayer>(child_path, child_paint2);
310 auto layer1 = std::make_shared<TransformLayer>(layer1_transform);
311 auto layer2 = std::make_shared<TransformLayer>(layer2_transform);
312 layer1->Add(mock_layer1);
313 layer1->Add(layer2);
314 layer2->Add(mock_layer2);
315
316 preroll_context()->state_stack.set_preroll_delegate(device_cull_rect,
317 initial_transform);
318 layer1->Preroll(preroll_context());
319 SkRect layer1_child_bounds = layer2->paint_bounds();
320 layer1_child_bounds.join(mock_layer1->paint_bounds());
321 SkRect expected_layer1_bounds = layer1_child_bounds;
322 layer1_transform.mapRect(&expected_layer1_bounds);
323
324 EXPECT_EQ(mock_layer2->paint_bounds(), child_path.getBounds());
325 EXPECT_EQ(layer2->paint_bounds(),
326 layer2_transform.mapRect(mock_layer2->paint_bounds()));
327 EXPECT_EQ(layer2->child_paint_bounds(), mock_layer2->paint_bounds());
328 EXPECT_EQ(mock_layer1->paint_bounds(), child_path.getBounds());
329 EXPECT_EQ(layer1->paint_bounds(), expected_layer1_bounds);
330 EXPECT_EQ(layer1->child_paint_bounds(), layer1_child_bounds);
331 EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
332 EXPECT_TRUE(layer2->needs_painting(paint_context()));
333 EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
334 EXPECT_TRUE(layer1->needs_painting(paint_context()));
335 EXPECT_EQ(mock_layer1->parent_matrix(),
336 SkMatrix::Concat(initial_transform, layer1_transform));
337 EXPECT_EQ(
338 mock_layer2->parent_matrix(),
339 SkMatrix::Concat(SkMatrix::Concat(initial_transform, layer1_transform),
340 layer2_transform));
341 EXPECT_EQ(mock_layer1->parent_cull_rect(),
342 inverse_layer1_transform.mapRect(local_cull_rect));
343 EXPECT_EQ(mock_layer2->parent_cull_rect(),
344 inverse_layer2_transform.mapRect(
345 inverse_layer1_transform.mapRect(local_cull_rect)));
346 EXPECT_EQ(mock_layer1->parent_mutators(),
347 std::vector({Mutator(layer1_transform)}));
348 EXPECT_EQ(
349 mock_layer2->parent_mutators(),
350 std::vector({Mutator(layer1_transform), Mutator(layer2_transform)}));
351
352 layer1->Paint(display_list_paint_context());
353 DisplayListBuilder expected_builder;
354 /* (Transform)layer1::Paint */ {
355 expected_builder.Save();
356 {
357 expected_builder.Transform(layer1_transform);
358 /* mock_layer::Paint */ {
359 expected_builder.DrawPath(child_path, child_paint1);
360 }
361 /* (Transform)layer1::Paint */ {
362 expected_builder.Save();
363 {
364 expected_builder.Transform(layer2_transform);
365 /* mock_layer::Paint */ {
366 expected_builder.DrawPath(child_path, child_paint2);
367 }
368 }
369 expected_builder.Restore();
370 }
371 }
372 expected_builder.Restore();
373 }
374 EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
375}
376
377TEST_F(TransformLayerTest, OpacityInheritance) {
378 auto path1 = SkPath().addRect({10, 10, 30, 30});
380 auto transform1 = std::make_shared<TransformLayer>(SkMatrix::Scale(2, 2));
381 transform1->Add(mock1);
382
383 // TransformLayer will pass through compatibility from a compatible child
384 PrerollContext* context = preroll_context();
385 transform1->Preroll(context);
386 EXPECT_EQ(context->renderable_state_flags,
388
389 auto path2 = SkPath().addRect({40, 40, 50, 50});
391 transform1->Add(mock2);
392
393 // TransformLayer will pass through compatibility from multiple
394 // non-overlapping compatible children
395 transform1->Preroll(context);
396 EXPECT_EQ(context->renderable_state_flags,
398
399 auto path3 = SkPath().addRect({20, 20, 40, 40});
401 transform1->Add(mock3);
402
403 // TransformLayer will not pass through compatibility from multiple
404 // overlapping children even if they are individually compatible
405 transform1->Preroll(context);
406 EXPECT_EQ(context->renderable_state_flags, 0);
407
408 auto transform2 = std::make_shared<TransformLayer>(SkMatrix::Scale(2, 2));
409 transform2->Add(mock1);
410 transform2->Add(mock2);
411
412 // Double check first two children are compatible and non-overlapping
413 transform2->Preroll(context);
414 EXPECT_EQ(context->renderable_state_flags,
416
417 auto path4 = SkPath().addRect({60, 60, 70, 70});
418 auto mock4 = MockLayer::Make(path4);
419 transform2->Add(mock4);
420
421 // The third child is non-overlapping, but not compatible so the
422 // TransformLayer should end up incompatible
423 transform2->Preroll(context);
424 EXPECT_EQ(context->renderable_state_flags, 0);
425}
426
427TEST_F(TransformLayerTest, OpacityInheritancePainting) {
428 auto path1 = SkPath().addRect({10, 10, 30, 30});
430 auto path2 = SkPath().addRect({40, 40, 50, 50});
432 auto transform = SkMatrix::Scale(2, 2);
433 auto transform_layer = std::make_shared<TransformLayer>(transform);
434 transform_layer->Add(mock1);
435 transform_layer->Add(mock2);
436
437 // TransformLayer will pass through compatibility from multiple
438 // non-overlapping compatible children
439 PrerollContext* context = preroll_context();
440 transform_layer->Preroll(context);
441 EXPECT_EQ(context->renderable_state_flags,
443
444 int opacity_alpha = 0x7F;
445 SkPoint offset = SkPoint::Make(10, 10);
446 auto opacity_layer = std::make_shared<OpacityLayer>(opacity_alpha, offset);
447 opacity_layer->Add(transform_layer);
448 opacity_layer->Preroll(context);
449 EXPECT_TRUE(opacity_layer->children_can_accept_opacity());
450
451 DisplayListBuilder expected_builder;
452 /* opacity_layer paint */ {
453 expected_builder.Save();
454 {
455 expected_builder.Translate(offset.fX, offset.fY);
456 /* transform_layer paint */ {
457 expected_builder.Save();
458 expected_builder.Transform(transform);
459 /* child layer1 paint */ {
460 expected_builder.DrawPath(path1, DlPaint().setAlpha(opacity_alpha));
461 }
462 /* child layer2 paint */ {
463 expected_builder.DrawPath(path2, DlPaint().setAlpha(opacity_alpha));
464 }
465 expected_builder.Restore();
466 }
467 }
468 expected_builder.Restore();
469 }
470
471 opacity_layer->Paint(display_list_paint_context());
472 EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
473}
474
476
478 auto path1 = SkPath().addRect(SkRect::MakeLTRB(0, 0, 50, 50));
479 auto m1 = std::make_shared<MockLayer>(path1);
480
481 auto transform1 =
482 std::make_shared<TransformLayer>(SkMatrix::Translate(10, 10));
483 transform1->Add(m1);
484
485 MockLayerTree t1;
486 t1.root()->Add(transform1);
487
488 auto damage = DiffLayerTree(t1, MockLayerTree());
489 EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(10, 10, 60, 60));
490
491 auto transform2 =
492 std::make_shared<TransformLayer>(SkMatrix::Translate(20, 20));
493 transform2->Add(m1);
494 transform2->AssignOldLayer(transform1.get());
495
496 MockLayerTree t2;
497 t2.root()->Add(transform2);
498
499 damage = DiffLayerTree(t2, t1);
500 EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(10, 10, 70, 70));
501
502 auto transform3 =
503 std::make_shared<TransformLayer>(SkMatrix::Translate(20, 20));
504 transform3->Add(m1);
505 transform3->AssignOldLayer(transform2.get());
506
507 MockLayerTree t3;
508 t3.root()->Add(transform3);
509
510 damage = DiffLayerTree(t3, t2);
511 EXPECT_EQ(damage.frame_damage, SkIRect::MakeEmpty());
512}
513
515 auto path1 = SkPath().addRect(SkRect::MakeLTRB(0, 0, 50, 50));
516 auto m1 = CreateContainerLayer(std::make_shared<MockLayer>(path1));
517 auto m2 = CreateContainerLayer(std::make_shared<MockLayer>(path1));
518 auto m3 = CreateContainerLayer(std::make_shared<MockLayer>(path1));
519
520 auto transform1 = std::make_shared<TransformLayer>(SkMatrix::Scale(2.0, 2.0));
521
522 auto transform1_1 =
523 std::make_shared<TransformLayer>(SkMatrix::Translate(10, 10));
524 transform1_1->Add(m1);
525 transform1->Add(transform1_1);
526
527 auto transform1_2 =
528 std::make_shared<TransformLayer>(SkMatrix::Translate(100, 100));
529 transform1_2->Add(m2);
530 transform1->Add(transform1_2);
531
532 auto transform1_3 =
533 std::make_shared<TransformLayer>(SkMatrix::Translate(200, 200));
534 transform1_3->Add(m3);
535 transform1->Add(transform1_3);
536
537 MockLayerTree l1;
538 l1.root()->Add(transform1);
539
540 auto damage = DiffLayerTree(l1, MockLayerTree());
541 EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(20, 20, 500, 500));
542
543 auto transform2 = std::make_shared<TransformLayer>(SkMatrix::Scale(2.0, 2.0));
544
545 auto transform2_1 =
546 std::make_shared<TransformLayer>(SkMatrix::Translate(10, 10));
547 transform2_1->Add(m1);
548 transform2_1->AssignOldLayer(transform1_1.get());
549 transform2->Add(transform2_1);
550
551 // Offset 1px from transform1_2 so that they're not the same
552 auto transform2_2 =
553 std::make_shared<TransformLayer>(SkMatrix::Translate(100, 101));
554 transform2_2->Add(m2);
555 transform2_2->AssignOldLayer(transform1_2.get());
556 transform2->Add(transform2_2);
557
558 auto transform2_3 =
559 std::make_shared<TransformLayer>(SkMatrix::Translate(200, 200));
560 transform2_3->Add(m3);
561 transform2_3->AssignOldLayer(transform1_3.get());
562 transform2->Add(transform2_3);
563
564 MockLayerTree l2;
565 l2.root()->Add(transform2);
566
567 damage = DiffLayerTree(l2, l1);
568
569 // transform2 has not transform1 assigned as old layer, so it should be
570 // invalidated completely
571 EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(20, 20, 500, 500));
572
573 // now diff the tree properly, the only difference being transform2_2 and
574 // transform_2_1
575 transform2->AssignOldLayer(transform1.get());
576 damage = DiffLayerTree(l2, l1);
577
578 EXPECT_EQ(damage.frame_damage, SkIRect::MakeLTRB(200, 200, 300, 302));
579}
580
581} // namespace testing
582} // namespace flutter
#define M_PI
static SkPath path1()
static SkPath path4()
static SkPath path3()
static SkPath path2()
Definition: SkM44.h:150
static SkM44 Rotate(SkV3 axis, SkScalar radians)
Definition: SkM44.h:239
SkM44 & preConcat(const SkM44 &m)
Definition: SkM44.h:351
static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z=0)
Definition: SkM44.h:225
SkMatrix asM33() const
Definition: SkM44.h:409
bool invert(SkM44 *inverse) const
Definition: SkM44.cpp:247
SkM44 & preTranslate(SkScalar x, SkScalar y, SkScalar z=0)
Definition: SkM44.cpp:89
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static SkMatrix Translate(SkScalar dx, SkScalar dy)
Definition: SkMatrix.h:91
static SkMatrix Concat(const SkMatrix &a, const SkMatrix &b)
Definition: SkMatrix.h:1775
bool invert(SkMatrix *inverse) const
Definition: SkMatrix.h:1206
bool mapRect(SkRect *dst, const SkRect &src, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
Definition: SkMatrix.cpp:1141
Definition: SkPath.h:59
const SkRect & getBounds() const
Definition: SkPath.cpp:430
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition: SkPath.cpp:864
virtual void Add(std::shared_ptr< Layer > layer)
void Transform(const SkMatrix *matrix) override
Definition: dl_builder.cc:919
void DrawPath(const SkPath &path, const DlPaint &paint) override
Definition: dl_builder.cc:1204
sk_sp< DisplayList > Build()
Definition: dl_builder.cc:67
static constexpr int kCallerCanApplyOpacity
static std::shared_ptr< MockLayer > MakeOpacityCompatible(const SkPath &path)
Definition: mock_layer.h:35
static std::shared_ptr< MockLayer > Make(const SkPath &path, DlPaint paint=DlPaint())
Definition: mock_layer.h:30
TEST_F(DisplayListTest, Defaults)
LayerTestBase<::testing::Test > LayerTest
Definition: layer_test.h:210
bool DisplayListsEQ_Verbose(const DisplayList *a, const DisplayList *b)
skgpu::graphite::Transform Transform
flutter::DlPaint DlPaint
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
Definition: p3.cpp:47
SeparatedVector2 offset
static constexpr SkIRect MakeLTRB(int32_t l, int32_t t, int32_t r, int32_t b)
Definition: SkRect.h:91
static constexpr SkIRect MakeEmpty()
Definition: SkRect.h:45
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
static constexpr SkRect MakeEmpty()
Definition: SkRect.h:595
SkScalar fBottom
larger y-axis bounds
Definition: extension.cpp:17
SkScalar fLeft
smaller x-axis bounds
Definition: extension.cpp:14
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
SkScalar fRight
larger x-axis bounds
Definition: extension.cpp:16
void join(const SkRect &r)
Definition: SkRect.cpp:126
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
Definition: SkRect.h:646
SkScalar fTop
smaller y-axis bounds
Definition: extension.cpp:15
static constexpr DlColor kBlue()
Definition: dl_color.h:26
static constexpr DlColor kGreen()
Definition: dl_color.h:25
#define EXPECT_TRUE(handle)
Definition: unit_test.h:678