Flutter Engine
 
Loading...
Searching...
No Matches
display_list_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#define FML_USED_ON_EMBEDDER
6
8
12#include "flutter/fml/macros.h"
13
14// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
15// NOLINTBEGIN(bugprone-unchecked-optional-access)
16
17namespace flutter {
18namespace testing {
19
21
22#ifndef NDEBUG
23TEST_F(DisplayListLayerTest, PaintBeforePrerollInvalidDisplayListDies) {
24 const DlPoint layer_offset = DlPoint(0.0f, 0.0f);
25 auto layer = std::make_shared<DisplayListLayer>(
26 layer_offset, sk_sp<DisplayList>(), false, false);
27
28 EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()), "display_list_");
29}
30
31TEST_F(DisplayListLayerTest, PaintBeforePrerollDies) {
32 const DlPoint layer_offset = DlPoint(0.0f, 0.0f);
33 const DlRect picture_bounds = DlRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
34 DisplayListBuilder builder;
35 builder.DrawRect(picture_bounds, DlPaint());
36 auto display_list = builder.Build();
37 auto layer = std::make_shared<DisplayListLayer>(layer_offset, display_list,
38 false, false);
39
40 EXPECT_EQ(layer->paint_bounds(), DlRect());
41 EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
42 "needs_painting\\(context\\)");
43}
44
45TEST_F(DisplayListLayerTest, PaintingEmptyLayerDies) {
46 const DlPoint layer_offset = DlPoint(0.0f, 0.0f);
47 const DlRect picture_bounds;
48 DisplayListBuilder builder;
49 builder.DrawRect(picture_bounds, DlPaint());
50 auto display_list = builder.Build();
51 auto layer = std::make_shared<DisplayListLayer>(layer_offset, display_list,
52 false, false);
53
54 layer->Preroll(preroll_context());
55 EXPECT_EQ(layer->paint_bounds(), DlRect());
56 EXPECT_FALSE(layer->needs_painting(paint_context()));
57
58 EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
59 "needs_painting\\(context\\)");
60}
61
62TEST_F(DisplayListLayerTest, InvalidDisplayListDies) {
63 const DlPoint layer_offset = DlPoint(0.0f, 0.0f);
64 auto layer = std::make_shared<DisplayListLayer>(
65 layer_offset, sk_sp<DisplayList>(), false, false);
66
67 // Crashes reading a nullptr.
68 EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context()), "");
69}
70#endif
71
72TEST_F(DisplayListLayerTest, SimpleDisplayList) {
73 const DlPoint layer_offset = DlPoint(1.5f, -0.5f);
74 const DlRect picture_bounds = DlRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
75 DisplayListBuilder builder;
76 builder.DrawRect(picture_bounds, DlPaint());
77 auto display_list = builder.Build();
78 auto layer = std::make_shared<DisplayListLayer>(layer_offset, display_list,
79 false, false);
80
81 layer->Preroll(preroll_context());
82 EXPECT_EQ(layer->paint_bounds(),
83 picture_bounds.Shift(layer_offset.x, layer_offset.y));
84 EXPECT_EQ(layer->display_list(), display_list.get());
85 EXPECT_TRUE(layer->needs_painting(paint_context()));
86
87 layer->Paint(display_list_paint_context());
88 DisplayListBuilder expected_builder;
89 /* (DisplayList)layer::Paint */ {
90 expected_builder.Save();
91 {
92 expected_builder.Translate(layer_offset.x, layer_offset.y);
93 expected_builder.DrawDisplayList(display_list);
94 }
95 expected_builder.Restore();
96 }
97 EXPECT_TRUE(
98 DisplayListsEQ_Verbose(this->display_list(), expected_builder.Build()));
99}
100
101TEST_F(DisplayListLayerTest, CachingDoesNotChangeCullRect) {
102 const DlPoint layer_offset = DlPoint(10, 10);
103 DisplayListBuilder builder;
104 builder.DrawRect(DlRect::MakeLTRB(10, 10, 20, 20), DlPaint());
105 auto display_list = builder.Build();
106 auto layer = std::make_shared<DisplayListLayer>(layer_offset, display_list,
107 true, false);
108
109 DlRect original_cull_rect = preroll_context()->state_stack.device_cull_rect();
110 use_mock_raster_cache();
111 layer->Preroll(preroll_context());
112 ASSERT_EQ(preroll_context()->state_stack.device_cull_rect(),
113 original_cull_rect);
114}
115
116TEST_F(DisplayListLayerTest, SimpleDisplayListOpacityInheritance) {
117 const DlPoint layer_offset = DlPoint(1.5f, -0.5f);
118 const DlRect picture_bounds = DlRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
119 DisplayListBuilder builder;
120 builder.DrawRect(picture_bounds, DlPaint());
121 auto display_list = builder.Build();
122 auto display_list_layer = std::make_shared<DisplayListLayer>(
123 layer_offset, display_list, false, false);
124 EXPECT_TRUE(display_list->can_apply_group_opacity());
125
126 auto context = preroll_context();
127 display_list_layer->Preroll(preroll_context());
128 EXPECT_EQ(context->renderable_state_flags,
130
131 int opacity_alpha = 0x7F;
132 DlScalar opacity = DlColor::toOpacity(opacity_alpha);
133 DlPoint opacity_offset = DlPoint(10, 10);
134 auto opacity_layer =
135 std::make_shared<OpacityLayer>(opacity_alpha, opacity_offset);
136 opacity_layer->Add(display_list_layer);
137 opacity_layer->Preroll(context);
138 EXPECT_TRUE(opacity_layer->children_can_accept_opacity());
139
140 DisplayListBuilder child_builder;
141 child_builder.DrawRect(picture_bounds, DlPaint());
142 auto child_display_list = child_builder.Build();
143
144 DisplayListBuilder expected_builder;
145 /* opacity_layer::Paint() */ {
146 expected_builder.Save();
147 {
148 expected_builder.Translate(opacity_offset.x, opacity_offset.y);
149 /* display_list_layer::Paint() */ {
150 expected_builder.Save();
151 {
152 expected_builder.Translate(layer_offset.x, layer_offset.y);
153 expected_builder.DrawDisplayList(child_display_list, opacity);
154 }
155 expected_builder.Restore();
156 }
157 }
158 expected_builder.Restore();
159 }
160
161 opacity_layer->Paint(display_list_paint_context());
162 EXPECT_TRUE(
163 DisplayListsEQ_Verbose(this->display_list(), expected_builder.Build()));
164}
165
166TEST_F(DisplayListLayerTest, IncompatibleDisplayListOpacityInheritance) {
167 const DlPoint layer_offset = DlPoint(1.5f, -0.5f);
168 const DlRect picture1_bounds = DlRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
169 const DlRect picture2_bounds = DlRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f);
170 DisplayListBuilder builder;
171 builder.DrawRect(picture1_bounds, DlPaint());
172 builder.DrawRect(picture2_bounds, DlPaint());
173 auto display_list = builder.Build();
174 auto display_list_layer = std::make_shared<DisplayListLayer>(
175 layer_offset, display_list, false, false);
176 EXPECT_FALSE(display_list->can_apply_group_opacity());
177
178 auto context = preroll_context();
179 display_list_layer->Preroll(preroll_context());
180 EXPECT_EQ(context->renderable_state_flags, 0);
181
182 int opacity_alpha = 0x7F;
183 DlPoint opacity_offset = DlPoint(10, 10);
184 auto opacity_layer =
185 std::make_shared<OpacityLayer>(opacity_alpha, opacity_offset);
186 opacity_layer->Add(display_list_layer);
187 opacity_layer->Preroll(context);
188 EXPECT_FALSE(opacity_layer->children_can_accept_opacity());
189
190 DisplayListBuilder child_builder;
191 child_builder.DrawRect(picture1_bounds, DlPaint());
192 child_builder.DrawRect(picture2_bounds, DlPaint());
193 auto child_display_list = child_builder.Build();
194
195 auto display_list_bounds = picture1_bounds.Union(picture2_bounds);
196 auto save_layer_bounds =
197 display_list_bounds.Shift(layer_offset.x, layer_offset.y);
198 DisplayListBuilder expected_builder;
199 /* opacity_layer::Paint() */ {
200 expected_builder.Save();
201 {
202 expected_builder.Translate(opacity_offset.x, opacity_offset.y);
203 expected_builder.SaveLayer(save_layer_bounds,
204 &DlPaint().setAlpha(opacity_alpha));
205 {
206 /* display_list_layer::Paint() */ {
207 expected_builder.Save();
208 {
209 expected_builder.Translate(layer_offset.x, layer_offset.y);
210 expected_builder.DrawDisplayList(child_display_list);
211 }
212 expected_builder.Restore();
213 }
214 }
215 expected_builder.Restore();
216 }
217 expected_builder.Restore();
218 }
219
220 opacity_layer->Paint(display_list_paint_context());
221 EXPECT_TRUE(
222 DisplayListsEQ_Verbose(this->display_list(), expected_builder.Build()));
223}
224
225TEST_F(DisplayListLayerTest, CachedIncompatibleDisplayListOpacityInheritance) {
226 const DlPoint layer_offset = DlPoint(1.5f, -0.5f);
227 const DlRect picture1_bounds = DlRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
228 const DlRect picture2_bounds = DlRect::MakeLTRB(10.0f, 15.0f, 30.0f, 35.0f);
229 DisplayListBuilder builder;
230 builder.DrawRect(picture1_bounds, DlPaint());
231 builder.DrawRect(picture2_bounds, DlPaint());
232 auto display_list = builder.Build();
233 auto display_list_layer = std::make_shared<DisplayListLayer>(
234 layer_offset, display_list, true, false);
235 EXPECT_FALSE(display_list->can_apply_group_opacity());
236
237 use_skia_raster_cache();
238
239 auto context = preroll_context();
240 display_list_layer->Preroll(preroll_context());
241 EXPECT_EQ(context->renderable_state_flags, 0);
242
243 // Pump the DisplayListLayer until it is ready to cache its DL
244 display_list_layer->Preroll(preroll_context());
245 display_list_layer->Preroll(preroll_context());
246 display_list_layer->Preroll(preroll_context());
247 LayerTree::TryToRasterCache(*preroll_context()->raster_cached_entries,
248 &paint_context(), false);
249
250 int opacity_alpha = 0x7F;
251 DlPoint opacity_offset = DlPoint(10.2, 10.2);
252 auto opacity_layer =
253 std::make_shared<OpacityLayer>(opacity_alpha, opacity_offset);
254 opacity_layer->Add(display_list_layer);
255 opacity_layer->Preroll(context);
256 EXPECT_TRUE(opacity_layer->children_can_accept_opacity());
257
258 auto opacity_integral_matrix = RasterCacheUtil::GetIntegralTransCTM(
259 DlMatrix::MakeTranslation(opacity_offset));
260 DlMatrix layer_offset_matrix =
261 DlMatrix::MakeTranslation(layer_offset) * opacity_integral_matrix;
262 auto layer_offset_integral_matrix =
263 RasterCacheUtil::GetIntegralTransCTM(layer_offset_matrix);
264 DisplayListBuilder expected(DlRect::MakeWH(1000, 1000));
265 /* opacity_layer::Paint() */ {
266 expected.Save();
267 {
268 expected.Translate(opacity_offset.x, opacity_offset.y);
269 expected.TransformReset();
270 expected.Transform(opacity_integral_matrix);
271 /* display_list_layer::Paint() */ {
272 expected.Save();
273 {
274 expected.Translate(layer_offset.x, layer_offset.y);
275 expected.TransformReset();
276 expected.Transform(layer_offset_integral_matrix);
277 context->raster_cache->Draw(display_list_layer->caching_key_id(),
278 expected,
279 &DlPaint().setAlpha(opacity_alpha));
280 }
281 expected.Restore();
282 }
283 }
284 expected.Restore();
285 }
286
287 opacity_layer->Paint(display_list_paint_context());
288 EXPECT_TRUE(DisplayListsEQ_Verbose(expected.Build(), this->display_list()));
289}
290
291TEST_F(DisplayListLayerTest, RasterCachePreservesRTree) {
292 const DlRect picture1_bounds = DlRect::MakeXYWH(10, 10, 10, 10);
293 const DlRect picture2_bounds = DlRect::MakeXYWH(15, 15, 10, 10);
294 DisplayListBuilder builder(true);
295 builder.DrawRect(picture1_bounds, DlPaint());
296 builder.DrawRect(picture2_bounds, DlPaint());
297 auto display_list = builder.Build();
298 auto display_list_layer = std::make_shared<DisplayListLayer>(
299 DlPoint(3, 3), display_list, true, false);
300
301 use_skia_raster_cache();
302
303 auto context = preroll_context();
304 {
305 auto mutator = context->state_stack.save();
306 mutator.transform(DlMatrix::MakeScale({2.0f, 2.0f, 1.0f}));
307 display_list_layer->Preroll(preroll_context());
308 EXPECT_EQ(context->renderable_state_flags, 0);
309
310 // Pump the DisplayListLayer until it is ready to cache its DL
311 display_list_layer->Preroll(preroll_context());
312 display_list_layer->Preroll(preroll_context());
313 display_list_layer->Preroll(preroll_context());
314 LayerTree::TryToRasterCache(*preroll_context()->raster_cached_entries,
315 &paint_context(), false);
316 }
317
318 DisplayListBuilder expected_root_canvas(true);
319 expected_root_canvas.Scale(2.0, 2.0);
320 ASSERT_TRUE(context->raster_cache->Draw(display_list_layer->caching_key_id(),
321 expected_root_canvas, nullptr,
322 false));
323 auto root_canvas_dl = expected_root_canvas.Build();
324 const auto root_canvas_rects =
325 root_canvas_dl->rtree()->searchAndConsolidateRects(kGiantRect, true);
326 std::list<DlRect> root_canvas_rects_expected = {
327 DlRect::MakeLTRB(26, 26, 56, 56),
328 };
329 EXPECT_EQ(root_canvas_rects_expected, root_canvas_rects);
330
331 DisplayListBuilder expected_overlay_canvas(true);
332 expected_overlay_canvas.Scale(2.0, 2.0);
333 ASSERT_TRUE(context->raster_cache->Draw(display_list_layer->caching_key_id(),
334 expected_overlay_canvas, nullptr,
335 true));
336 auto overlay_canvas_dl = expected_overlay_canvas.Build();
337 const auto overlay_canvas_rects =
338 overlay_canvas_dl->rtree()->searchAndConsolidateRects(kGiantRect, true);
339
340 // Same bounds as root canvas, but preserves individual rects.
341 std::list<DlRect> overlay_canvas_rects_expected = {
342 DlRect::MakeLTRB(26, 26, 46, 36),
343 DlRect::MakeLTRB(26, 36, 56, 46),
344 DlRect::MakeLTRB(36, 46, 56, 56),
345 };
346 EXPECT_EQ(overlay_canvas_rects_expected, overlay_canvas_rects);
347};
348
350
351TEST_F(DisplayListLayerDiffTest, SimpleDisplayList) {
352 auto display_list = CreateDisplayList(DlRect::MakeLTRB(10, 10, 60, 60));
353
354 MockLayerTree tree1;
355 tree1.root()->Add(CreateDisplayListLayer(display_list));
356
357 auto damage = DiffLayerTree(tree1, MockLayerTree());
358 EXPECT_EQ(damage.frame_damage, DlIRect::MakeLTRB(10, 10, 60, 60));
359
360 MockLayerTree tree2;
361 tree2.root()->Add(CreateDisplayListLayer(display_list));
362
363 damage = DiffLayerTree(tree2, tree1);
364 EXPECT_TRUE(damage.frame_damage.IsEmpty());
365
366 MockLayerTree tree3;
367 damage = DiffLayerTree(tree3, tree2);
368 EXPECT_EQ(damage.frame_damage, DlIRect::MakeLTRB(10, 10, 60, 60));
369}
370
371TEST_F(DisplayListLayerDiffTest, FractionalTranslation) {
372 auto display_list = CreateDisplayList(DlRect::MakeLTRB(10, 10, 60, 60));
373
374 MockLayerTree tree1;
375 tree1.root()->Add(CreateDisplayListLayer(display_list, DlPoint(0.5f, 0.5f)));
376
377 auto damage = DiffLayerTree(tree1, MockLayerTree(), DlIRect(), 0, 0,
378 /*use_raster_cache=*/false);
379 EXPECT_EQ(damage.frame_damage, DlIRect::MakeLTRB(10, 10, 61, 61));
380}
381
382TEST_F(DisplayListLayerDiffTest, FractionalTranslationWithRasterCache) {
383 auto display_list = CreateDisplayList(DlRect::MakeLTRB(10, 10, 60, 60));
384
385 MockLayerTree tree1;
386 tree1.root()->Add(CreateDisplayListLayer(display_list, DlPoint(0.5f, 0.5f)));
387
388 auto damage = DiffLayerTree(tree1, MockLayerTree(), DlIRect(), 0, 0,
389 /*use_raster_cache=*/true);
390 EXPECT_EQ(damage.frame_damage, DlIRect::MakeLTRB(11, 11, 61, 61));
391}
392
394 MockLayerTree tree1;
395 auto display_list1 =
396 CreateDisplayList(DlRect::MakeLTRB(10, 10, 60, 60), DlColor::kGreen());
397 tree1.root()->Add(CreateDisplayListLayer(display_list1));
398
399 auto damage = DiffLayerTree(tree1, MockLayerTree());
400 EXPECT_EQ(damage.frame_damage, DlIRect::MakeLTRB(10, 10, 60, 60));
401
402 MockLayerTree tree2;
403 // same DL, same offset
404 auto display_list2 =
405 CreateDisplayList(DlRect::MakeLTRB(10, 10, 60, 60), DlColor::kGreen());
406 tree2.root()->Add(CreateDisplayListLayer(display_list2));
407
408 damage = DiffLayerTree(tree2, tree1);
409 EXPECT_EQ(damage.frame_damage, DlIRect());
410
411 MockLayerTree tree3;
412 auto display_list3 =
413 CreateDisplayList(DlRect::MakeLTRB(10, 10, 60, 60), DlColor::kGreen());
414 // add offset
415 tree3.root()->Add(CreateDisplayListLayer(display_list3, DlPoint(10, 10)));
416
417 damage = DiffLayerTree(tree3, tree2);
418 EXPECT_EQ(damage.frame_damage, DlIRect::MakeLTRB(10, 10, 70, 70));
419
420 MockLayerTree tree4;
421 // different color
422 auto display_list4 =
423 CreateDisplayList(DlRect::MakeLTRB(10, 10, 60, 60), DlColor::kRed());
424 tree4.root()->Add(CreateDisplayListLayer(display_list4, DlPoint(10, 10)));
425
426 damage = DiffLayerTree(tree4, tree3);
427 EXPECT_EQ(damage.frame_damage, DlIRect::MakeLTRB(20, 20, 70, 70));
428}
429
430TEST_F(DisplayListLayerTest, DisplayListAccessCountDependsOnVisibility) {
431 const DlPoint layer_offset = DlPoint(1.5f, -0.5f);
432 const DlRect picture_bounds = DlRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
433 const DlRect missed_cull_rect = DlRect::MakeLTRB(100, 100, 200, 200);
434 const DlRect hit_cull_rect = DlRect::MakeLTRB(0, 0, 200, 200);
435 DisplayListBuilder builder;
436 builder.DrawRect(picture_bounds, DlPaint());
437 auto display_list = builder.Build();
438 auto layer = std::make_shared<DisplayListLayer>(layer_offset, display_list,
439 true, false);
440
441 auto raster_cache_item = layer->raster_cache_item();
442 use_mock_raster_cache();
443
444 // First Preroll the DisplayListLayer a few times where it does not intersect
445 // the cull rect. No caching progress should occur during this time, the
446 // access_count should remain 0 because the DisplayList was never "visible".
447 ASSERT_TRUE(preroll_context()->state_stack.is_empty());
448 preroll_context()->state_stack.set_preroll_delegate(missed_cull_rect);
449 for (int i = 0; i < 10; i++) {
450 preroll_context()->raster_cached_entries->clear();
451 layer->Preroll(preroll_context());
452 ASSERT_EQ(raster_cache_item->cache_state(), RasterCacheItem::kNone);
453 ASSERT_TRUE(raster_cache_item->GetId().has_value());
454 ASSERT_EQ(preroll_context()->raster_cache->GetAccessCount(
455 raster_cache_item->GetId().value(), SkMatrix::I()),
456 0);
457 ASSERT_EQ(preroll_context()->raster_cached_entries->size(), size_t(1));
458 ASSERT_EQ(preroll_context()->raster_cache->EstimatePictureCacheByteSize(),
459 size_t(0));
460 ASSERT_FALSE(raster_cache_item->TryToPrepareRasterCache(paint_context()));
461 ASSERT_FALSE(raster_cache_item->Draw(paint_context(), nullptr));
462 }
463
464 // Next Preroll the DisplayListLayer once where it does intersect
465 // the cull rect. No caching progress should occur during this time
466 // since this is the first frame in which it was visible, but the
467 // count should start incrementing.
468 ASSERT_TRUE(preroll_context()->state_stack.is_empty());
469 preroll_context()->state_stack.set_preroll_delegate(hit_cull_rect);
470 preroll_context()->raster_cached_entries->clear();
471 layer->Preroll(preroll_context());
472 ASSERT_EQ(raster_cache_item->cache_state(), RasterCacheItem::kNone);
473 ASSERT_TRUE(raster_cache_item->GetId().has_value());
474 ASSERT_EQ(preroll_context()->raster_cache->GetAccessCount(
475 raster_cache_item->GetId().value(), SkMatrix::I()),
476 1);
477 ASSERT_EQ(preroll_context()->raster_cached_entries->size(), size_t(1));
478 ASSERT_EQ(preroll_context()->raster_cache->EstimatePictureCacheByteSize(),
479 size_t(0));
480 ASSERT_FALSE(raster_cache_item->TryToPrepareRasterCache(paint_context()));
481 ASSERT_FALSE(raster_cache_item->Draw(paint_context(), nullptr));
482
483 // Now we can Preroll the DisplayListLayer again with a cull rect that
484 // it does not intersect and it should continue to count these operations
485 // even though it is not visible. No actual caching should occur yet,
486 // even though we will surpass its threshold.
487 ASSERT_TRUE(preroll_context()->state_stack.is_empty());
488 preroll_context()->state_stack.set_preroll_delegate(missed_cull_rect);
489 for (int i = 0; i < 10; i++) {
490 preroll_context()->raster_cached_entries->clear();
491 layer->Preroll(preroll_context());
492 ASSERT_EQ(raster_cache_item->cache_state(), RasterCacheItem::kNone);
493 ASSERT_TRUE(raster_cache_item->GetId().has_value());
494 ASSERT_EQ(preroll_context()->raster_cache->GetAccessCount(
495 raster_cache_item->GetId().value(), SkMatrix::I()),
496 i + 2);
497 ASSERT_EQ(preroll_context()->raster_cached_entries->size(), size_t(1));
498 ASSERT_EQ(preroll_context()->raster_cache->EstimatePictureCacheByteSize(),
499 size_t(0));
500 ASSERT_FALSE(raster_cache_item->TryToPrepareRasterCache(paint_context()));
501 ASSERT_FALSE(raster_cache_item->Draw(paint_context(), nullptr));
502 }
503
504 // Finally Preroll the DisplayListLayer again where it does intersect
505 // the cull rect. Since we should have exhausted our access count
506 // threshold in the loop above, these operations should result in the
507 // DisplayList being cached.
508 ASSERT_TRUE(preroll_context()->state_stack.is_empty());
509 preroll_context()->state_stack.set_preroll_delegate(hit_cull_rect);
510 preroll_context()->raster_cached_entries->clear();
511 layer->Preroll(preroll_context());
512 ASSERT_EQ(raster_cache_item->cache_state(), RasterCacheItem::kCurrent);
513 ASSERT_TRUE(raster_cache_item->GetId().has_value());
514 ASSERT_EQ(preroll_context()->raster_cache->GetAccessCount(
515 raster_cache_item->GetId().value(), SkMatrix::I()),
516 12);
517 ASSERT_EQ(preroll_context()->raster_cached_entries->size(), size_t(1));
518 ASSERT_EQ(preroll_context()->raster_cache->EstimatePictureCacheByteSize(),
519 size_t(0));
520 ASSERT_TRUE(raster_cache_item->TryToPrepareRasterCache(paint_context()));
521 ASSERT_GT(preroll_context()->raster_cache->EstimatePictureCacheByteSize(),
522 size_t(0));
523 ASSERT_TRUE(raster_cache_item->Draw(paint_context(), nullptr));
524}
525
526TEST_F(DisplayListLayerTest, OverflowCachedDisplayListOpacityInheritance) {
527 use_mock_raster_cache();
528 PrerollContext* context = preroll_context();
529 int per_frame =
531 int layer_count = per_frame + 1;
532 DlPoint opacity_offset = DlPoint(10, 10);
533 auto opacity_layer = std::make_shared<OpacityLayer>(0.5f, opacity_offset);
534 std::vector<std::shared_ptr<DisplayListLayer>> layers;
535 for (int i = 0; i < layer_count; i++) {
536 DisplayListBuilder builder(false);
537 builder.DrawRect(DlRect::MakeLTRB(0, 0, 100, 100), DlPaint());
538 builder.DrawRect(DlRect::MakeLTRB(50, 50, 100, 100), DlPaint());
539 auto display_list = builder.Build();
540 ASSERT_FALSE(display_list->can_apply_group_opacity());
541 DlPoint offset = DlPoint(i * 200.0f, 0);
542
543 layers.push_back(
544 std::make_shared<DisplayListLayer>(offset, display_list, true, false));
545 opacity_layer->Add(layers.back());
546 }
547 for (size_t j = 0; j < context->raster_cache->access_threshold(); j++) {
548 context->raster_cache->BeginFrame();
549 for (int i = 0; i < layer_count; i++) {
550 context->renderable_state_flags = 0;
551 layers[i]->Preroll(context);
552 ASSERT_EQ(context->renderable_state_flags, 0) << "pass " << (j + 1);
553 }
554 }
555 opacity_layer->Preroll(context);
556 ASSERT_FALSE(opacity_layer->children_can_accept_opacity());
557 LayerTree::TryToRasterCache(*context->raster_cached_entries, &paint_context(),
558 false);
559 context->raster_cached_entries->clear();
560 context->raster_cache->BeginFrame();
561 for (int i = 0; i < per_frame; i++) {
562 context->renderable_state_flags = 0;
563 layers[i]->Preroll(context);
564 ASSERT_EQ(context->renderable_state_flags,
566 << "layer " << (i + 1);
567 }
568 for (int i = per_frame; i < layer_count; i++) {
569 context->renderable_state_flags = 0;
570 layers[i]->Preroll(context);
571 ASSERT_EQ(context->renderable_state_flags, 0) << "layer " << (i + 1);
572 }
573 opacity_layer->Preroll(context);
574 ASSERT_FALSE(opacity_layer->children_can_accept_opacity());
575 LayerTree::TryToRasterCache(*context->raster_cached_entries, &paint_context(),
576 false);
577 context->raster_cached_entries->clear();
578 context->raster_cache->BeginFrame();
579 for (int i = 0; i < layer_count; i++) {
580 context->renderable_state_flags = 0;
581 layers[i]->Preroll(context);
582 ASSERT_EQ(context->renderable_state_flags,
584 << "layer " << (i + 1);
585 }
586 opacity_layer->Preroll(context);
587 ASSERT_TRUE(opacity_layer->children_can_accept_opacity());
588}
589
590} // namespace testing
591} // namespace flutter
592
593// NOLINTEND(bugprone-unchecked-optional-access)
virtual void Add(std::shared_ptr< Layer > layer)
void TransformReset() override
void SaveLayer(const std::optional< DlRect > &bounds, const DlPaint *paint=nullptr, const DlImageFilter *backdrop=nullptr, std::optional< int64_t > backdrop_id=std::nullopt) override
void Scale(DlScalar sx, DlScalar sy) override
void DrawDisplayList(const sk_sp< DisplayList > display_list, DlScalar opacity=SK_Scalar1) override
void Translate(DlScalar tx, DlScalar ty) override
sk_sp< DisplayList > Build()
Definition dl_builder.cc:66
void Transform(const DlMatrix &matrix) override
void DrawRect(const DlRect &rect, const DlPaint &paint) override
static constexpr int kCallerCanApplyOpacity
static void TryToRasterCache(const std::vector< RasterCacheItem * > &raster_cached_entries, const PaintContext *paint_context, bool ignore_raster_cache=false)
Definition layer_tree.cc:67
const FlutterLayer ** layers
TEST_F(DisplayListTest, Defaults)
LayerTestBase<::testing::Test > LayerTest
Definition layer_test.h:177
bool DisplayListsEQ_Verbose(const DisplayList *a, const DisplayList *b)
impeller::Scalar DlScalar
impeller::Rect DlRect
impeller::IRect32 DlIRect
static constexpr DlRect kGiantRect
Definition layer.h:40
impeller::Point DlPoint
static constexpr DlScalar toOpacity(uint8_t alpha)
Definition dl_color.h:65
static constexpr DlColor kRed()
Definition dl_color.h:71
static constexpr DlColor kGreen()
Definition dl_color.h:72
std::vector< RasterCacheItem * > * raster_cached_entries
Definition layer.h:75
static SkMatrix GetIntegralTransCTM(const SkMatrix &ctm)
Snap the translation components of the matrix to integers.
static constexpr int kDefaultPictureAndDisplayListCacheLimitPerFrame
A 4x4 matrix using column-major storage.
Definition matrix.h:37
static constexpr Matrix MakeTranslation(const Vector3 &t)
Definition matrix.h:95
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
static constexpr TRect MakeWH(Type width, Type height)
Definition rect.h:140
constexpr TRect Union(const TRect &o) const
Definition rect.h:513
static constexpr TRect MakeXYWH(Type x, Type y, Type width, Type height)
Definition rect.h:136
constexpr TRect< T > Shift(T dx, T dy) const
Returns a new rectangle translated by the given offset.
Definition rect.h:602
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129