Flutter Engine
 
Loading...
Searching...
No Matches
raster_cache_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
19#include "gtest/gtest.h"
20#include "third_party/skia/include/core/SkMatrix.h"
21#include "third_party/skia/include/core/SkPoint.h"
22
23// TODO(zanderso): https://github.com/flutter/flutter/issues/127701
24// NOLINTBEGIN(bugprone-unchecked-optional-access)
25
26namespace flutter {
27namespace testing {
28
29TEST(RasterCache, SimpleInitialization) {
31 ASSERT_TRUE(true);
32}
33
34TEST(RasterCache, MetricsOmitUnpopulatedEntries) {
35 size_t threshold = 2;
36 flutter::RasterCache cache(threshold);
37
38 DlMatrix matrix;
39
40 auto display_list = GetSampleDisplayList();
41
42 DisplayListBuilder dummy_canvas(1000, 1000);
43 DlPaint paint;
44
45 LayerStateStack preroll_state_stack;
46 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
47 LayerStateStack paint_state_stack;
48 preroll_state_stack.set_delegate(&dummy_canvas);
49
50 FixedRefreshRateStopwatch raster_time;
53 preroll_state_stack, &cache, &raster_time, &ui_time);
55 paint_state_stack, &cache, &raster_time, &ui_time);
56 auto& preroll_context = preroll_context_holder.preroll_context;
57 auto& paint_context = paint_context_holder.paint_context;
58
59 cache.BeginFrame();
60 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), true,
61 false);
62
63 // 1st access.
65 display_list_item, preroll_context, paint_context, matrix));
66 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
67
68 cache.EndFrame();
69 ASSERT_EQ(cache.picture_metrics().total_count(), 0u);
70 ASSERT_EQ(cache.picture_metrics().total_bytes(), 0u);
71 cache.BeginFrame();
72
73 // 2nd access.
75 display_list_item, preroll_context, paint_context, matrix));
76 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
77
78 cache.EndFrame();
79 ASSERT_EQ(cache.picture_metrics().total_count(), 0u);
80 ASSERT_EQ(cache.picture_metrics().total_bytes(), 0u);
81 cache.BeginFrame();
82
83 // Now Prepare should cache it.
85 display_list_item, preroll_context, paint_context, matrix));
86 ASSERT_TRUE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
87
88 cache.EndFrame();
89 ASSERT_EQ(cache.picture_metrics().total_count(), 1u);
90 // 80w * 80h * 4bpp + image object overhead
91 ASSERT_EQ(cache.picture_metrics().total_bytes(), 25624u);
92}
93
94TEST(RasterCache, ThresholdIsRespectedForDisplayList) {
95 size_t threshold = 2;
96 flutter::RasterCache cache(threshold);
97
98 DlMatrix matrix;
99
100 auto display_list = GetSampleDisplayList();
101
102 DisplayListBuilder dummy_canvas(1000, 1000);
103 DlPaint paint;
104
105 LayerStateStack preroll_state_stack;
106 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
107 LayerStateStack paint_state_stack;
108 preroll_state_stack.set_delegate(&dummy_canvas);
109
110 FixedRefreshRateStopwatch raster_time;
113 preroll_state_stack, &cache, &raster_time, &ui_time);
114 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
115 paint_state_stack, &cache, &raster_time, &ui_time);
116 auto& preroll_context = preroll_context_holder.preroll_context;
117 auto& paint_context = paint_context_holder.paint_context;
118
119 cache.BeginFrame();
120
121 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), true,
122 false);
123
124 // 1st access.
126 display_list_item, preroll_context, paint_context, matrix));
127 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
128
129 cache.EndFrame();
130 cache.BeginFrame();
131
132 // 2nd access.
134 display_list_item, preroll_context, paint_context, matrix));
135 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
136
137 cache.EndFrame();
138 cache.BeginFrame();
139
140 // Now Prepare should cache it.
142 display_list_item, preroll_context, paint_context, matrix));
143 ASSERT_TRUE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
144}
145
146TEST(RasterCache, AccessThresholdOfZeroDisablesCachingForDisplayList) {
147 size_t threshold = 0;
148 flutter::RasterCache cache(threshold);
149
150 DlMatrix matrix;
151
152 auto display_list = GetSampleDisplayList();
153
154 DisplayListBuilder dummy_canvas(1000, 1000);
155 DlPaint paint;
156
157 LayerStateStack preroll_state_stack;
158 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
159 LayerStateStack paint_state_stack;
160 preroll_state_stack.set_delegate(&dummy_canvas);
161
162 FixedRefreshRateStopwatch raster_time;
165 preroll_state_stack, &cache, &raster_time, &ui_time);
166 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
167 paint_state_stack, &cache, &raster_time, &ui_time);
168 auto& preroll_context = preroll_context_holder.preroll_context;
169 auto& paint_context = paint_context_holder.paint_context;
170
171 cache.BeginFrame();
172
173 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), true,
174 false);
176 display_list_item, preroll_context, paint_context, matrix));
177 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
178}
179
180TEST(RasterCache, PictureCacheLimitPerFrameIsRespectedWhenZeroForDisplayList) {
181 size_t picture_cache_limit_per_frame = 0;
182 flutter::RasterCache cache(3, picture_cache_limit_per_frame);
183
184 DlMatrix matrix;
185
186 auto display_list = GetSampleDisplayList();
187
188 DisplayListBuilder dummy_canvas(1000, 1000);
189 DlPaint paint;
190
191 LayerStateStack preroll_state_stack;
192 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
193 LayerStateStack paint_state_stack;
194 preroll_state_stack.set_delegate(&dummy_canvas);
195
196 FixedRefreshRateStopwatch raster_time;
199 preroll_state_stack, &cache, &raster_time, &ui_time);
200 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
201 paint_state_stack, &cache, &raster_time, &ui_time);
202 auto& preroll_context = preroll_context_holder.preroll_context;
203 auto& paint_context = paint_context_holder.paint_context;
204
205 cache.BeginFrame();
206
207 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), true,
208 false);
209 // 1st access.
211 display_list_item, preroll_context, paint_context, matrix));
212 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
213 // 2nd access.
215 display_list_item, preroll_context, paint_context, matrix));
216 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
217 // the picture_cache_limit_per_frame = 0, so don't cache it
219 display_list_item, preroll_context, paint_context, matrix));
220 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
221}
222
223TEST(RasterCache, EvictUnusedCacheEntries) {
224 size_t threshold = 1;
225 flutter::RasterCache cache(threshold);
226
227 DlMatrix matrix;
228
229 auto display_list_1 = GetSampleDisplayList();
230 auto display_list_2 = GetSampleDisplayList();
231
232 DisplayListBuilder dummy_canvas(1000, 1000);
233 DlPaint paint;
234
235 LayerStateStack preroll_state_stack;
236 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
237 LayerStateStack paint_state_stack;
238 preroll_state_stack.set_delegate(&dummy_canvas);
239
240 FixedRefreshRateStopwatch raster_time;
243 preroll_state_stack, &cache, &raster_time, &ui_time);
244 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
245 paint_state_stack, &cache, &raster_time, &ui_time);
246 auto& preroll_context = preroll_context_holder.preroll_context;
247 auto& paint_context = paint_context_holder.paint_context;
248
249 DisplayListRasterCacheItem display_list_item_1(display_list_1, SkPoint(),
250 true, false);
251 DisplayListRasterCacheItem display_list_item_2(display_list_2, SkPoint(),
252 true, false);
253
254 cache.BeginFrame();
255 RasterCacheItemPreroll(display_list_item_1, preroll_context, matrix);
256 RasterCacheItemPreroll(display_list_item_2, preroll_context, matrix);
258 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 0u);
259 ASSERT_FALSE(
260 RasterCacheItemTryToRasterCache(display_list_item_1, paint_context));
261 ASSERT_FALSE(
262 RasterCacheItemTryToRasterCache(display_list_item_2, paint_context));
263 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 0u);
264 ASSERT_FALSE(display_list_item_1.Draw(paint_context, &dummy_canvas, &paint));
265 ASSERT_FALSE(display_list_item_2.Draw(paint_context, &dummy_canvas, &paint));
266 cache.EndFrame();
267
268 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 0u);
269 ASSERT_EQ(cache.picture_metrics().total_count(), 0u);
270 ASSERT_EQ(cache.picture_metrics().total_bytes(), 0u);
271
272 cache.BeginFrame();
273 RasterCacheItemPreroll(display_list_item_1, preroll_context, matrix);
274 RasterCacheItemPreroll(display_list_item_2, preroll_context, matrix);
276 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 0u);
277 ASSERT_TRUE(
278 RasterCacheItemTryToRasterCache(display_list_item_1, paint_context));
279 ASSERT_TRUE(
280 RasterCacheItemTryToRasterCache(display_list_item_2, paint_context));
281 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 51248u);
282 ASSERT_TRUE(display_list_item_1.Draw(paint_context, &dummy_canvas, &paint));
283 ASSERT_TRUE(display_list_item_2.Draw(paint_context, &dummy_canvas, &paint));
284 cache.EndFrame();
285
286 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 51248u);
287 ASSERT_EQ(cache.picture_metrics().total_count(), 2u);
288 ASSERT_EQ(cache.picture_metrics().total_bytes(), 51248u);
289
290 cache.BeginFrame();
291 RasterCacheItemPreroll(display_list_item_1, preroll_context, matrix);
293 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 25624u);
294 ASSERT_TRUE(
295 RasterCacheItemTryToRasterCache(display_list_item_1, paint_context));
296 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 25624u);
297 ASSERT_TRUE(display_list_item_1.Draw(paint_context, &dummy_canvas, &paint));
298 cache.EndFrame();
299
300 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 25624u);
301 ASSERT_EQ(cache.picture_metrics().total_count(), 1u);
302 ASSERT_EQ(cache.picture_metrics().total_bytes(), 25624u);
303
304 cache.BeginFrame();
306 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 0u);
307 cache.EndFrame();
308
309 ASSERT_EQ(cache.EstimatePictureCacheByteSize(), 0u);
310 ASSERT_EQ(cache.picture_metrics().total_count(), 0u);
311 ASSERT_EQ(cache.picture_metrics().total_bytes(), 0u);
312
313 cache.BeginFrame();
314 ASSERT_FALSE(
315 cache.Draw(display_list_item_1.GetId().value(), dummy_canvas, &paint));
316 ASSERT_FALSE(display_list_item_1.Draw(paint_context, &dummy_canvas, &paint));
317 ASSERT_FALSE(
318 cache.Draw(display_list_item_2.GetId().value(), dummy_canvas, &paint));
319 ASSERT_FALSE(display_list_item_2.Draw(paint_context, &dummy_canvas, &paint));
320 cache.EndFrame();
321}
322
323TEST(RasterCache, ComputeDeviceRectBasedOnFractionalTranslation) {
324 SkRect logical_rect = SkRect::MakeLTRB(0, 0, 300.2, 300.3);
325 SkMatrix ctm = SkMatrix::MakeAll(2.0, 0, 0, 0, 2.0, 0, 0, 0, 1);
326 auto result = RasterCacheUtil::GetDeviceBounds(logical_rect, ctm);
327 ASSERT_EQ(result, SkRect::MakeLTRB(0.0, 0.0, 600.4, 600.6));
328}
329
330// Construct a cache result whose device target rectangle rounds out to be one
331// pixel wider than the cached image. Verify that it can be drawn without
332// triggering any assertions.
333TEST(RasterCache, DeviceRectRoundOutForDisplayList) {
334 size_t threshold = 1;
335 flutter::RasterCache cache(threshold);
336
337 DlRect logical_rect = DlRect::MakeLTRB(28, 0, 354.56731, 310.288);
338 DisplayListBuilder builder(logical_rect);
339 builder.DrawRect(logical_rect, DlPaint(DlColor::kRed()));
340 sk_sp<DisplayList> display_list = builder.Build();
341
342 // clang-format off
343 DlMatrix ctm(
344 1.3312, 0, 0, 0,
345 0, 1.3312, 0, 0,
346 0, 0, 1, 0,
347 233, 206, 0, 1
348 );
349 // clang-format on
350 DlPaint paint;
351
352 DisplayListBuilder canvas(1000, 1000);
353 canvas.SetTransform(ctm);
354
355 LayerStateStack preroll_state_stack;
356 preroll_state_stack.set_preroll_delegate(kGiantRect, ctm);
357 LayerStateStack paint_state_stack;
358 preroll_state_stack.set_delegate(&canvas);
359
360 FixedRefreshRateStopwatch raster_time;
363 preroll_state_stack, &cache, &raster_time, &ui_time);
364 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
365 paint_state_stack, &cache, &raster_time, &ui_time);
366 auto& preroll_context = preroll_context_holder.preroll_context;
367 auto& paint_context = paint_context_holder.paint_context;
368
369 cache.BeginFrame();
370 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), true,
371 false);
372
374 display_list_item, preroll_context, paint_context, ctm));
375 ASSERT_FALSE(display_list_item.Draw(paint_context, &canvas, &paint));
376
377 cache.EndFrame();
378 cache.BeginFrame();
379
381 display_list_item, preroll_context, paint_context, ctm));
382 ASSERT_TRUE(display_list_item.Draw(paint_context, &canvas, &paint));
383
384 canvas.Translate(248, 0);
385 ASSERT_TRUE(cache.Draw(display_list_item.GetId().value(), canvas, &paint));
386 ASSERT_TRUE(display_list_item.Draw(paint_context, &canvas, &paint));
387}
388
389TEST(RasterCache, NestedOpCountMetricUsedForDisplayList) {
390 size_t threshold = 1;
391 flutter::RasterCache cache(threshold);
392
393 DlMatrix matrix;
394
395 auto display_list = GetSampleNestedDisplayList();
396 ASSERT_EQ(display_list->op_count(), 1u);
397 ASSERT_EQ(display_list->op_count(true), 36u);
398
399 DisplayListBuilder dummy_canvas(1000, 1000);
400 DlPaint paint;
401
402 LayerStateStack preroll_state_stack;
403 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
404 LayerStateStack paint_state_stack;
405 preroll_state_stack.set_delegate(&dummy_canvas);
406
407 FixedRefreshRateStopwatch raster_time;
410 preroll_state_stack, &cache, &raster_time, &ui_time);
411 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
412 paint_state_stack, &cache, &raster_time, &ui_time);
413 auto& preroll_context = preroll_context_holder.preroll_context;
414 auto& paint_context = paint_context_holder.paint_context;
415
416 cache.BeginFrame();
417
418 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), false,
419 false);
420
422 display_list_item, preroll_context, paint_context, matrix));
423 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
424
425 cache.EndFrame();
426 cache.BeginFrame();
427
429 display_list_item, preroll_context, paint_context, matrix));
430 ASSERT_TRUE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
431}
432
433TEST(RasterCache, NaiveComplexityScoringDisplayList) {
436
437 size_t threshold = 1;
438 flutter::RasterCache cache(threshold);
439
440 DlMatrix matrix;
441
442 // Five raster ops will not be cached
443 auto display_list = GetSampleDisplayList(5);
444 unsigned int complexity_score = calculator->Compute(display_list.get());
445
446 ASSERT_EQ(complexity_score, 5u);
447 ASSERT_EQ(display_list->op_count(), 5u);
448 ASSERT_FALSE(calculator->ShouldBeCached(complexity_score));
449
450 DisplayListBuilder dummy_canvas(1000, 1000);
451 DlPaint paint;
452
453 LayerStateStack preroll_state_stack;
454 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
455 LayerStateStack paint_state_stack;
456 preroll_state_stack.set_delegate(&dummy_canvas);
457
458 FixedRefreshRateStopwatch raster_time;
461 preroll_state_stack, &cache, &raster_time, &ui_time);
462 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
463 paint_state_stack, &cache, &raster_time, &ui_time);
464 auto& preroll_context = preroll_context_holder.preroll_context;
465 auto& paint_context = paint_context_holder.paint_context;
466
467 cache.BeginFrame();
468
469 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), false,
470 false);
471
473 display_list_item, preroll_context, paint_context, matrix));
474 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
475
476 cache.EndFrame();
477 cache.BeginFrame();
478
480 display_list_item, preroll_context, paint_context, matrix));
481 ASSERT_FALSE(display_list_item.Draw(paint_context, &dummy_canvas, &paint));
482
483 // Six raster ops should be cached
484 display_list = GetSampleDisplayList(6);
485 complexity_score = calculator->Compute(display_list.get());
486
487 ASSERT_EQ(complexity_score, 6u);
488 ASSERT_EQ(display_list->op_count(), 6u);
489 ASSERT_TRUE(calculator->ShouldBeCached(complexity_score));
490
491 DisplayListRasterCacheItem display_list_item_2 =
492 DisplayListRasterCacheItem(display_list, SkPoint(), false, false);
493 cache.BeginFrame();
494
496 display_list_item_2, preroll_context, paint_context, matrix));
497 ASSERT_FALSE(display_list_item_2.Draw(paint_context, &dummy_canvas, &paint));
498
499 cache.EndFrame();
500 cache.BeginFrame();
501
503 display_list_item_2, preroll_context, paint_context, matrix));
504 ASSERT_TRUE(display_list_item_2.Draw(paint_context, &dummy_canvas, &paint));
505}
506
507TEST(RasterCache, DisplayListWithSingularMatrixIsNotCached) {
508 size_t threshold = 2;
509 flutter::RasterCache cache(threshold);
510
511 DlMatrix matrices[] = {
512 DlMatrix::MakeScale({0.0f, 1.0f, 1.0f}),
513 DlMatrix::MakeScale({1.0f, 0.0f, 1.0f}),
514 DlMatrix::MakeSkew(1, 1),
515 };
516 int matrix_count = sizeof(matrices) / sizeof(matrices[0]);
517
518 auto display_list = GetSampleDisplayList();
519
520 DisplayListBuilder dummy_canvas(1000, 1000);
521 DlPaint paint;
522
523 LayerStateStack preroll_state_stack;
524 preroll_state_stack.set_preroll_delegate(kGiantRect, DlMatrix());
525 LayerStateStack paint_state_stack;
526 preroll_state_stack.set_delegate(&dummy_canvas);
527
528 FixedRefreshRateStopwatch raster_time;
531 preroll_state_stack, &cache, &raster_time, &ui_time);
532 PaintContextHolder paint_context_holder = GetSamplePaintContextHolder(
533 paint_state_stack, &cache, &raster_time, &ui_time);
534 auto& preroll_context = preroll_context_holder.preroll_context;
535 auto& paint_context = paint_context_holder.paint_context;
536
537 DisplayListRasterCacheItem display_list_item(display_list, SkPoint(), true,
538 false);
539
540 for (int i = 0; i < 10; i++) {
541 cache.BeginFrame();
542
543 for (int j = 0; j < matrix_count; j++) {
544 display_list_item.set_matrix(matrices[j]);
546 display_list_item, preroll_context, paint_context, matrices[j]));
547 }
548
549 for (int j = 0; j < matrix_count; j++) {
550 dummy_canvas.SetTransform(matrices[j]);
551 ASSERT_FALSE(
552 display_list_item.Draw(paint_context, &dummy_canvas, &paint));
553 }
554
555 cache.EndFrame();
556 }
557}
558
559TEST(RasterCache, PrepareLayerTransform) {
560 DlRect child_bounds = DlRect::MakeLTRB(10, 10, 50, 50);
561 DlPath child_path = DlPath::MakeOval(child_bounds);
562 auto child_layer = MockLayer::Make(child_path);
563 auto blur_filter = DlBlurImageFilter::Make(5, 5, DlTileMode::kClamp);
564 auto blur_layer = std::make_shared<ImageFilterLayer>(blur_filter);
565 DlMatrix matrix = DlMatrix::MakeScale({2.0f, 2.0f, 1.0f});
566 auto transform_layer = std::make_shared<TransformLayer>(matrix);
567 DlMatrix cache_matrix = DlMatrix::MakeTranslation({-20.0f, -20.0f}) * matrix;
568 child_layer->set_expected_paint_matrix(cache_matrix);
569
570 blur_layer->Add(child_layer);
571 transform_layer->Add(blur_layer);
572
573 size_t threshold = 2;
574 MockRasterCache cache(threshold);
575 DisplayListBuilder dummy_canvas(1000, 1000);
576
577 LayerStateStack preroll_state_stack;
578 preroll_state_stack.set_preroll_delegate(kGiantRect, matrix);
579 LayerStateStack paint_state_stack;
580 preroll_state_stack.set_delegate(&dummy_canvas);
581
582 FixedRefreshRateStopwatch raster_time;
584 std::vector<RasterCacheItem*> cache_items;
585
586 cache.BeginFrame();
587
588 auto preroll_holder = GetSamplePrerollContextHolder(
589 preroll_state_stack, &cache, &raster_time, &ui_time);
590 preroll_holder.preroll_context.raster_cached_entries = &cache_items;
591 transform_layer->Preroll(&preroll_holder.preroll_context);
592
593 auto paint_holder = GetSamplePaintContextHolder(paint_state_stack, &cache,
594 &raster_time, &ui_time);
595
598 *preroll_holder.preroll_context.raster_cached_entries,
599 &paint_holder.paint_context);
600
601 // Condition tested inside MockLayer::Paint against expected paint matrix.
602}
603
604TEST(RasterCache, RasterCacheKeyHashFunction) {
606 auto hash_function = map.hash_function();
607 SkMatrix matrix = SkMatrix::I();
608 uint64_t id = 5;
609 RasterCacheKey layer_key(id, RasterCacheKeyType::kLayer, matrix);
610 RasterCacheKey display_list_key(id, RasterCacheKeyType::kDisplayList, matrix);
612 matrix);
613
614 auto layer_cache_key_id = RasterCacheKeyID(id, RasterCacheKeyType::kLayer);
615 auto layer_hash_code = hash_function(layer_key);
616 ASSERT_EQ(layer_hash_code, layer_cache_key_id.GetHash());
617
618 auto display_list_cache_key_id =
620 auto display_list_hash_code = hash_function(display_list_key);
621 ASSERT_EQ(display_list_hash_code, display_list_cache_key_id.GetHash());
622
623 auto layer_children_cache_key_id =
625 auto layer_children_hash_code = hash_function(layer_children_key);
626 ASSERT_EQ(layer_children_hash_code, layer_children_cache_key_id.GetHash());
627}
628
629TEST(RasterCache, RasterCacheKeySameID) {
631 SkMatrix matrix = SkMatrix::I();
632 uint64_t id = 5;
633 RasterCacheKey layer_key(id, RasterCacheKeyType::kLayer, matrix);
634 RasterCacheKey display_list_key(id, RasterCacheKeyType::kDisplayList, matrix);
636 matrix);
637 map[layer_key] = 100;
638 map[display_list_key] = 300;
639 map[layer_children_key] = 400;
640
641 ASSERT_EQ(map[layer_key], 100);
642 ASSERT_EQ(map[display_list_key], 300);
643 ASSERT_EQ(map[layer_children_key], 400);
644}
645
646TEST(RasterCache, RasterCacheKeySameType) {
648 SkMatrix matrix = SkMatrix::I();
649
651 RasterCacheKey layer_first_key(5, type, matrix);
652 RasterCacheKey layer_second_key(10, type, matrix);
653 RasterCacheKey layer_third_key(15, type, matrix);
654 map[layer_first_key] = 50;
655 map[layer_second_key] = 100;
656 map[layer_third_key] = 150;
657 ASSERT_EQ(map[layer_first_key], 50);
658 ASSERT_EQ(map[layer_second_key], 100);
659 ASSERT_EQ(map[layer_third_key], 150);
660
662 RasterCacheKey picture_first_key(20, type, matrix);
663 RasterCacheKey picture_second_key(25, type, matrix);
664 RasterCacheKey picture_third_key(30, type, matrix);
665 map[picture_first_key] = 200;
666 map[picture_second_key] = 250;
667 map[picture_third_key] = 300;
668 ASSERT_EQ(map[picture_first_key], 200);
669 ASSERT_EQ(map[picture_second_key], 250);
670 ASSERT_EQ(map[picture_third_key], 300);
671
673 RasterCacheKey display_list_first_key(35, type, matrix);
674 RasterCacheKey display_list_second_key(40, type, matrix);
675 RasterCacheKey display_list_third_key(45, type, matrix);
676 map[display_list_first_key] = 350;
677 map[display_list_second_key] = 400;
678 map[display_list_third_key] = 450;
679 ASSERT_EQ(map[display_list_first_key], 350);
680 ASSERT_EQ(map[display_list_second_key], 400);
681 ASSERT_EQ(map[display_list_third_key], 450);
682
687 RasterCacheKey layer_children_first_key(
688 RasterCacheKeyID({foo, bar, baz}, type), matrix);
689 RasterCacheKey layer_children_second_key(
690 RasterCacheKeyID({foo, baz, bar}, type), matrix);
691 RasterCacheKey layer_children_third_key(
692 RasterCacheKeyID({baz, bar, foo}, type), matrix);
693 map[layer_children_first_key] = 100;
694 map[layer_children_second_key] = 200;
695 map[layer_children_third_key] = 300;
696 ASSERT_EQ(map[layer_children_first_key], 100);
697 ASSERT_EQ(map[layer_children_second_key], 200);
698 ASSERT_EQ(map[layer_children_third_key], 300);
699}
700
701TEST(RasterCache, RasterCacheKeyIDEqual) {
704 RasterCacheKeyID third =
706
707 ASSERT_NE(first, second);
708 ASSERT_NE(first, third);
709 ASSERT_NE(second, third);
710
711 RasterCacheKeyID fourth =
713 RasterCacheKeyID fifth =
715 RasterCacheKeyID sixth =
717 ASSERT_NE(fourth, fifth);
718 ASSERT_NE(fifth, sixth);
719}
720
721TEST(RasterCache, RasterCacheKeyIDHashCode) {
722 uint64_t foo = 1;
723 uint64_t bar = 2;
726 std::size_t first_hash = first.GetHash();
727 std::size_t second_hash = second.GetHash();
728
729 ASSERT_EQ(first_hash, fml::HashCombine(foo, RasterCacheKeyType::kLayer));
730 ASSERT_EQ(second_hash, fml::HashCombine(bar, RasterCacheKeyType::kLayer));
731
732 RasterCacheKeyID third =
734 RasterCacheKeyID fourth =
736 std::size_t third_hash = third.GetHash();
737 std::size_t fourth_hash = fourth.GetHash();
738
741 first.GetHash(), second.GetHash()));
744 second.GetHash(), first.GetHash()));
745
746 // Verify that the cached hash code is correct.
747 ASSERT_EQ(first_hash, first.GetHash());
748 ASSERT_EQ(second_hash, second.GetHash());
749 ASSERT_EQ(third_hash, third.GetHash());
750 ASSERT_EQ(fourth_hash, fourth.GetHash());
751}
752
754
755TEST_F(RasterCacheTest, RasterCacheKeyIDLayerChildrenIds) {
756 auto layer = std::make_shared<ContainerLayer>();
757
758 const DlPath child_path = DlPath::MakeRect(DlRect::MakeWH(5.0f, 5.0f));
759 auto mock_layer = std::make_shared<MockLayer>(child_path);
760 layer->Add(mock_layer);
761
762 auto display_list = GetSampleDisplayList();
763 auto display_list_layer =
764 std::make_shared<DisplayListLayer>(DlPoint(), display_list, false, false);
765 layer->Add(display_list_layer);
766
767 auto ids = RasterCacheKeyID::LayerChildrenIds(layer.get()).value();
768 std::vector<RasterCacheKeyID> expected_ids;
769 expected_ids.emplace_back(
770 RasterCacheKeyID(mock_layer->unique_id(), RasterCacheKeyType::kLayer));
771 expected_ids.emplace_back(RasterCacheKeyID(display_list->unique_id(),
773 ASSERT_EQ(expected_ids[0], mock_layer->caching_key_id());
774 ASSERT_EQ(expected_ids[1], display_list_layer->caching_key_id());
775 ASSERT_EQ(ids, expected_ids);
776}
777
778TEST(RasterCacheUtilsTest, SkMatrixIntegralTransCTM) {
779#define EXPECT_EQ_WITH_TRANSLATE(test, expected, expected_tx, expected_ty) \
780 do { \
781 EXPECT_EQ(test[SkMatrix::kMScaleX], expected[SkMatrix::kMScaleX]); \
782 EXPECT_EQ(test[SkMatrix::kMSkewX], expected[SkMatrix::kMSkewX]); \
783 EXPECT_EQ(test[SkMatrix::kMScaleY], expected[SkMatrix::kMScaleY]); \
784 EXPECT_EQ(test[SkMatrix::kMSkewY], expected[SkMatrix::kMSkewY]); \
785 EXPECT_EQ(test[SkMatrix::kMSkewX], expected[SkMatrix::kMSkewX]); \
786 EXPECT_EQ(test[SkMatrix::kMPersp0], expected[SkMatrix::kMPersp0]); \
787 EXPECT_EQ(test[SkMatrix::kMPersp1], expected[SkMatrix::kMPersp1]); \
788 EXPECT_EQ(test[SkMatrix::kMPersp2], expected[SkMatrix::kMPersp2]); \
789 EXPECT_EQ(test[SkMatrix::kMTransX], expected_tx); \
790 EXPECT_EQ(test[SkMatrix::kMTransY], expected_ty); \
791 } while (0)
792
793#define EXPECT_NON_INTEGER_TRANSLATION(matrix) \
794 EXPECT_TRUE(SkScalarFraction(matrix[SkMatrix::kMTransX]) != 0.0f || \
795 SkScalarFraction(matrix[SkMatrix::kMTransY]) != 0.0f)
796
797 {
798 // Identity
799 SkMatrix matrix = SkMatrix::I();
800 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
801 SkMatrix compute;
802 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
803 EXPECT_EQ(get, matrix);
804 }
805 {
806 // Integer translate
807 SkMatrix matrix = SkMatrix::Translate(10.0f, 12.0f);
808 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
809 SkMatrix compute;
810 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
811 EXPECT_EQ(get, matrix);
812 }
813 {
814 // Fractional x translate
815 SkMatrix matrix = SkMatrix::Translate(10.2f, 12.0f);
817 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
818 SkMatrix compute;
819 EXPECT_TRUE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
820 EXPECT_EQ_WITH_TRANSLATE(get, matrix, 10.0f, 12.0f);
821 EXPECT_EQ(get, compute);
822 }
823 {
824 // Fractional y translate
825 SkMatrix matrix = SkMatrix::Translate(10.0f, 12.3f);
827 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
828 SkMatrix compute;
829 EXPECT_TRUE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
830 EXPECT_EQ_WITH_TRANSLATE(get, matrix, 10.0f, 12.0f);
831 EXPECT_EQ(get, compute);
832 }
833 {
834 // Fractional x & y translate
835 SkMatrix matrix = SkMatrix::Translate(10.7f, 12.3f);
837 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
838 SkMatrix compute;
839 EXPECT_TRUE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
840 EXPECT_EQ_WITH_TRANSLATE(get, matrix, 11.0f, 12.0f);
841 EXPECT_EQ(get, compute);
842 }
843 {
844 // Scale
845 SkMatrix matrix = SkMatrix::Scale(2.0f, 3.0f);
846 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
847 SkMatrix compute;
848 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
849 EXPECT_EQ(get, matrix);
850 }
851 {
852 // Scale, Integer translate
853 SkMatrix matrix = SkMatrix::Scale(2.0f, 3.0f);
854 matrix.preTranslate(10.0f, 12.0f);
855 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
856 SkMatrix compute;
857 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
858 EXPECT_EQ(get, matrix);
859 }
860 {
861 // Scale, Fractional translate
862 SkMatrix matrix = SkMatrix::Scale(2.0f, 3.0f);
863 matrix.preTranslate(10.7f, 12.1f);
865 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
866 SkMatrix compute;
867 EXPECT_TRUE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
868 EXPECT_EQ_WITH_TRANSLATE(get, matrix, 21.0f, 36.0f);
869 EXPECT_EQ(get, compute);
870 }
871 {
872 // Skew
873 SkMatrix matrix = SkMatrix::Skew(0.5f, 0.1f);
874 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
875 SkMatrix compute;
876 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
877 EXPECT_EQ(get, matrix);
878 }
879 {
880 // Skew, Fractional translate - should be NOP
881 SkMatrix matrix = SkMatrix::Skew(0.5f, 0.1f);
882 matrix.preTranslate(10.7f, 12.1f);
884 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
885 SkMatrix compute;
886 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
887 EXPECT_EQ(get, matrix);
888 }
889 {
890 // Rotate
891 SkMatrix matrix = SkMatrix::RotateDeg(45);
892 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
893 SkMatrix compute;
894 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
895 EXPECT_EQ(get, matrix);
896 }
897 {
898 // Rotate, Fractional Translate - should be NOP
899 SkMatrix matrix = SkMatrix::RotateDeg(45);
900 matrix.preTranslate(10.7f, 12.1f);
902 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
903 SkMatrix compute;
904 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
905 EXPECT_EQ(get, matrix);
906 }
907 {
908 // Perspective x
909 SkMatrix matrix = SkMatrix::I();
910 matrix.setPerspX(0.1);
911 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
912 SkMatrix compute;
913 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
914 EXPECT_EQ(get, matrix);
915 }
916 {
917 // Perspective x, Fractional Translate - should be NOP
918 SkMatrix matrix = SkMatrix::I();
919 matrix.setPerspX(0.1);
920 matrix.preTranslate(10.7f, 12.1f);
922 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
923 SkMatrix compute;
924 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
925 EXPECT_EQ(get, matrix);
926 }
927 {
928 // Perspective y
929 SkMatrix matrix = SkMatrix::I();
930 matrix.setPerspY(0.1);
931 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
932 SkMatrix compute;
933 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
934 EXPECT_EQ(get, matrix);
935 }
936 {
937 // Perspective y, Fractional Translate - should be NOP
938 SkMatrix matrix = SkMatrix::I();
939 matrix.setPerspY(0.1);
940 matrix.preTranslate(10.7f, 12.1f);
942 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
943 SkMatrix compute;
944 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
945 EXPECT_EQ(get, matrix);
946 }
947 {
948 // Perspective weight
949 // clang-format off
950 SkMatrix matrix = SkMatrix::MakeAll(
951 1.0f, 0.0f, 0.0f,
952 0.0f, 1.0f, 0.0f,
953 0.0f, 0.0f, 0.9f);
954 // clang-format on
955 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
956 SkMatrix compute;
957 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
958 EXPECT_EQ(get, matrix);
959 }
960 {
961 // Perspective weight, Fractional Translate - should be NOP
962 // clang-format off
963 SkMatrix matrix = SkMatrix::MakeAll(
964 1.0f, 0.0f, 0.0f,
965 0.0f, 1.0f, 0.0f,
966 0.0f, 0.0f, 0.9f);
967 // clang-format on
968 matrix.preTranslate(10.7f, 12.1f);
970 SkMatrix get = RasterCacheUtil::GetIntegralTransCTM(matrix);
971 SkMatrix compute;
972 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute));
973 EXPECT_EQ(get, matrix);
974 }
975#undef EXPECT_NON_INTEGER_TRANSLATION
976#undef EXPECT_EQ_WITH_TRANSLATE
977}
978
979TEST(RasterCacheUtilsTest, SkM44IntegralTransCTM) {
980#define EXPECT_EQ_WITH_TRANSLATE(test, expected, tx, ty, label) \
981 do { \
982 EXPECT_EQ(test.rc(0, 0), expected.rc(0, 0)) << label; \
983 EXPECT_EQ(test.rc(0, 1), expected.rc(0, 1)) << label; \
984 EXPECT_EQ(test.rc(0, 2), expected.rc(0, 2)) << label; \
985 EXPECT_EQ(test.rc(0, 3), tx) << label; \
986 EXPECT_EQ(test.rc(1, 0), expected.rc(1, 0)) << label; \
987 EXPECT_EQ(test.rc(1, 1), expected.rc(1, 1)) << label; \
988 EXPECT_EQ(test.rc(1, 2), expected.rc(1, 2)) << label; \
989 EXPECT_EQ(test.rc(1, 3), ty) << label; \
990 EXPECT_EQ(test.rc(2, 0), expected.rc(2, 0)) << label; \
991 EXPECT_EQ(test.rc(2, 1), expected.rc(2, 1)) << label; \
992 EXPECT_EQ(test.rc(2, 2), expected.rc(2, 2)) << label; \
993 EXPECT_EQ(test.rc(2, 3), expected.rc(2, 3)) << label; \
994 EXPECT_EQ(test.rc(3, 0), expected.rc(3, 0)) << label; \
995 EXPECT_EQ(test.rc(3, 1), expected.rc(3, 1)) << label; \
996 EXPECT_EQ(test.rc(3, 2), expected.rc(3, 2)) << label; \
997 EXPECT_EQ(test.rc(3, 3), expected.rc(3, 3)) << label; \
998 } while (0)
999
1000#define EXPECT_NON_INTEGER_TRANSLATION(matrix) \
1001 EXPECT_TRUE(SkScalarFraction(matrix.rc(0, 3)) != 0.0f || \
1002 SkScalarFraction(matrix.rc(1, 3)) != 0.0f)
1003
1004 for (int r = 0; r < 4; r++) {
1005 for (int c = 0; c < 4; c++) {
1006 bool snaps;
1007 switch (r) {
1008 case 0: // X equation
1009 if (c == 3) {
1010 continue; // TranslateX, the value we are testing, skip
1011 }
1012 snaps = (c == 0); // X Scale value yes, Skew by Y or Z no
1013 break;
1014 case 1: // Y equation
1015 if (c == 3) {
1016 continue; // TranslateY, the value we are testing, skip
1017 }
1018 snaps = (c == 1); // Y Scale value yes, Skew by X or Z no
1019 break;
1020 case 2: // Z equation, ignored, will snap
1021 snaps = true;
1022 break;
1023 case 3: // W equation, modifications prevent snapping
1024 snaps = false;
1025 break;
1026 default:
1028 }
1029 auto label = std::to_string(r) + ", " + std::to_string(c);
1030 SkM44 matrix = SkM44::Translate(10.7f, 12.1f);
1031 EXPECT_NON_INTEGER_TRANSLATION(matrix) << label;
1032 matrix.setRC(r, c, 0.5f);
1033 if (snaps) {
1034 SkM44 compute;
1035 SkM44 get = RasterCacheUtil::GetIntegralTransCTM(matrix);
1036 EXPECT_TRUE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute))
1037 << label;
1038 EXPECT_EQ_WITH_TRANSLATE(get, matrix, 11.0f, 12.0f, label);
1039 EXPECT_EQ(get, compute) << label;
1040 } else {
1041 SkM44 compute;
1042 SkM44 get = RasterCacheUtil::GetIntegralTransCTM(matrix);
1043 EXPECT_FALSE(RasterCacheUtil::ComputeIntegralTransCTM(matrix, &compute))
1044 << label;
1045 EXPECT_EQ(get, matrix) << label;
1046 }
1047 }
1048 }
1049#undef EXPECT_NON_INTEGER_TRANSLATION
1050#undef EXPECT_EQ_WITH_TRANSLATE
1051}
1052
1053} // namespace testing
1054} // namespace flutter
1055
1056// NOLINTEND(bugprone-unchecked-optional-access)
GLenum type
void SetTransform(const DlMatrix &matrix) override
Definition dl_builder.h:93
void Translate(DlScalar tx, DlScalar ty) override
sk_sp< DisplayList > Build()
Definition dl_builder.cc:66
void DrawRect(const DlRect &rect, const DlPaint &paint) override
virtual bool ShouldBeCached(unsigned int complexity_score)=0
virtual unsigned int Compute(const DisplayList *display_list)=0
static DisplayListComplexityCalculator * GetInstance()
bool Draw(const PaintContext &context, const DlPaint *paint) const override
static std::shared_ptr< DlImageFilter > Make(DlScalar sigma_x, DlScalar sigma_y, DlTileMode tile_mode)
static DlPath MakeRect(const DlRect &rect)
Definition dl_path.cc:39
static DlPath MakeOval(const DlRect &bounds)
Definition dl_path.cc:57
Used for fixed refresh rate cases.
Definition stopwatch.h:80
void set_delegate(DlCanvas *canvas)
void set_preroll_delegate(const DlRect &cull_rect, const DlMatrix &matrix)
static void TryToRasterCache(const std::vector< RasterCacheItem * > &raster_cached_entries, const PaintContext *paint_context, bool ignore_raster_cache=false)
Definition layer_tree.cc:67
bool Draw(const RasterCacheKeyID &id, DlCanvas &canvas, const DlPaint *paint, bool preserve_rtree=false) const
const RasterCacheMetrics & picture_metrics() const
size_t EstimatePictureCacheByteSize() const
Estimate how much memory is used by picture raster cache entries in bytes.
void set_matrix(const DlMatrix &matrix)
virtual std::optional< RasterCacheKeyID > GetId() const
std::unordered_map< RasterCacheKey, Value, Hash, Equal > Map
static constexpr uint64_t kDefaultUniqueID
std::size_t GetHash() const
static std::optional< std::vector< RasterCacheKeyID > > LayerChildrenIds(const Layer *layer)
static std::shared_ptr< MockLayer > Make(const DlPath &path, DlPaint paint=DlPaint())
Definition mock_layer.h:30
A RasterCache implementation that simulates the act of rendering a Layer or DisplayList without the o...
#define FML_UNREACHABLE()
Definition logging.h:128
TEST_F(DisplayListTest, Defaults)
bool RasterCacheItemTryToRasterCache(DisplayListRasterCacheItem &display_list_item, PaintContext &paint_context)
LayerTestBase<::testing::Test > LayerTest
Definition layer_test.h:177
PrerollContextHolder GetSamplePrerollContextHolder(LayerStateStack &state_stack, RasterCache *raster_cache, FixedRefreshRateStopwatch *raster_time, FixedRefreshRateStopwatch *ui_time)
sk_sp< DisplayList > GetSampleDisplayList()
void RasterCacheItemPreroll(DisplayListRasterCacheItem &display_list_item, PrerollContext &context, const DlMatrix &matrix)
TEST(NativeAssetsManagerTest, NoAvailableAssets)
sk_sp< DisplayList > GetSampleNestedDisplayList()
PaintContextHolder GetSamplePaintContextHolder(LayerStateStack &state_stack, RasterCache *raster_cache, FixedRefreshRateStopwatch *raster_time, FixedRefreshRateStopwatch *ui_time)
bool RasterCacheItemPrerollAndTryToRasterCache(DisplayListRasterCacheItem &display_list_item, PrerollContext &context, PaintContext &paint_context, const DlMatrix &matrix)
impeller::Matrix DlMatrix
static constexpr DlRect kGiantRect
Definition layer.h:40
impeller::Point DlPoint
constexpr std::size_t HashCombine()
#define EXPECT_NON_INTEGER_TRANSLATION(matrix)
#define EXPECT_EQ_WITH_TRANSLATE(test, expected, expected_tx, expected_ty)
static constexpr DlColor kRed()
Definition dl_color.h:71
static bool ComputeIntegralTransCTM(const SkMatrix &in, SkMatrix *out)
Snap the translation components of the |in| matrix to integers and store the snapped matrix in |out|.
static SkMatrix GetIntegralTransCTM(const SkMatrix &ctm)
Snap the translation components of the matrix to integers.
static SkRect GetDeviceBounds(const SkRect &rect, const SkMatrix &ctm)
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 MakeSkew(Scalar sx, Scalar sy)
Definition matrix.h:127
static constexpr Matrix MakeScale(const Vector3 &s)
Definition matrix.h:104
static constexpr TRect MakeWH(Type width, Type height)
Definition rect.h:140
static constexpr TRect MakeLTRB(Type left, Type top, Type right, Type bottom)
Definition rect.h:129