5#include "flutter/display_list/benchmarking/dl_complexity.h"
6#include "flutter/display_list/display_list.h"
7#include "flutter/display_list/dl_builder.h"
8#include "flutter/display_list/testing/dl_test_snippets.h"
9#include "flutter/flow/layers/container_layer.h"
10#include "flutter/flow/layers/display_list_layer.h"
11#include "flutter/flow/layers/image_filter_layer.h"
12#include "flutter/flow/layers/layer_tree.h"
13#include "flutter/flow/layers/transform_layer.h"
14#include "flutter/flow/raster_cache.h"
15#include "flutter/flow/raster_cache_item.h"
16#include "flutter/flow/testing/layer_test.h"
17#include "flutter/flow/testing/mock_raster_cache.h"
18#include "flutter/testing/assertions_skia.h"
19#include "gtest/gtest.h"
53 preroll_state_stack, &
cache, &raster_time, &ui_time);
55 paint_state_stack, &
cache, &raster_time, &ui_time);
65 display_list_item, preroll_context, paint_context,
matrix));
66 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
69 ASSERT_EQ(
cache.picture_metrics().total_count(), 0u);
70 ASSERT_EQ(
cache.picture_metrics().total_bytes(), 0u);
75 display_list_item, preroll_context, paint_context,
matrix));
76 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
79 ASSERT_EQ(
cache.picture_metrics().total_count(), 0u);
80 ASSERT_EQ(
cache.picture_metrics().total_bytes(), 0u);
85 display_list_item, preroll_context, paint_context,
matrix));
86 ASSERT_TRUE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
89 ASSERT_EQ(
cache.picture_metrics().total_count(), 1u);
91 ASSERT_EQ(
cache.picture_metrics().total_bytes(), 25624u);
113 preroll_state_stack, &
cache, &raster_time, &ui_time);
115 paint_state_stack, &
cache, &raster_time, &ui_time);
126 display_list_item, preroll_context, paint_context,
matrix));
127 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
134 display_list_item, preroll_context, paint_context,
matrix));
135 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
142 display_list_item, preroll_context, paint_context,
matrix));
143 ASSERT_TRUE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
147 size_t threshold = 0;
165 preroll_state_stack, &
cache, &raster_time, &ui_time);
167 paint_state_stack, &
cache, &raster_time, &ui_time);
176 display_list_item, preroll_context, paint_context,
matrix));
177 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
181 size_t picture_cache_limit_per_frame = 0;
199 preroll_state_stack, &
cache, &raster_time, &ui_time);
201 paint_state_stack, &
cache, &raster_time, &ui_time);
211 display_list_item, preroll_context, paint_context,
matrix));
212 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
215 display_list_item, preroll_context, paint_context,
matrix));
216 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
219 display_list_item, preroll_context, paint_context,
matrix));
220 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
224 size_t threshold = 1;
243 preroll_state_stack, &
cache, &raster_time, &ui_time);
245 paint_state_stack, &
cache, &raster_time, &ui_time);
257 cache.EvictUnusedCacheEntries();
258 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 0u);
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));
268 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 0u);
269 ASSERT_EQ(
cache.picture_metrics().total_count(), 0u);
270 ASSERT_EQ(
cache.picture_metrics().total_bytes(), 0u);
275 cache.EvictUnusedCacheEntries();
276 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 0u);
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));
286 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 51248u);
287 ASSERT_EQ(
cache.picture_metrics().total_count(), 2u);
288 ASSERT_EQ(
cache.picture_metrics().total_bytes(), 51248u);
292 cache.EvictUnusedCacheEntries();
293 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 25624u);
296 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 25624u);
297 ASSERT_TRUE(display_list_item_1.
Draw(paint_context, &dummy_canvas, &
paint));
300 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 25624u);
301 ASSERT_EQ(
cache.picture_metrics().total_count(), 1u);
302 ASSERT_EQ(
cache.picture_metrics().total_bytes(), 25624u);
305 cache.EvictUnusedCacheEntries();
306 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 0u);
309 ASSERT_EQ(
cache.EstimatePictureCacheByteSize(), 0u);
310 ASSERT_EQ(
cache.picture_metrics().total_count(), 0u);
311 ASSERT_EQ(
cache.picture_metrics().total_bytes(), 0u);
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));
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));
334 size_t threshold = 1;
356 preroll_state_stack, &
cache, &raster_time, &ui_time);
358 paint_state_stack, &
cache, &raster_time, &ui_time);
367 display_list_item, preroll_context, paint_context, ctm));
368 ASSERT_FALSE(display_list_item.
Draw(paint_context, &canvas, &
paint));
374 display_list_item, preroll_context, paint_context, ctm));
375 ASSERT_TRUE(display_list_item.
Draw(paint_context, &canvas, &
paint));
378 ASSERT_TRUE(
cache.Draw(display_list_item.
GetId().value(), canvas, &
paint));
379 ASSERT_TRUE(display_list_item.
Draw(paint_context, &canvas, &
paint));
383 size_t threshold = 1;
389 ASSERT_EQ(display_list->op_count(), 1u);
390 ASSERT_EQ(display_list->op_count(
true), 36u);
403 preroll_state_stack, &
cache, &raster_time, &ui_time);
405 paint_state_stack, &
cache, &raster_time, &ui_time);
415 display_list_item, preroll_context, paint_context,
matrix));
416 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
422 display_list_item, preroll_context, paint_context,
matrix));
423 ASSERT_TRUE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
430 size_t threshold = 1;
437 unsigned int complexity_score = calculator->
Compute(display_list.get());
439 ASSERT_EQ(complexity_score, 5u);
440 ASSERT_EQ(display_list->op_count(), 5u);
454 preroll_state_stack, &
cache, &raster_time, &ui_time);
456 paint_state_stack, &
cache, &raster_time, &ui_time);
466 display_list_item, preroll_context, paint_context,
matrix));
467 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
473 display_list_item, preroll_context, paint_context,
matrix));
474 ASSERT_FALSE(display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
478 complexity_score = calculator->
Compute(display_list.get());
480 ASSERT_EQ(complexity_score, 6u);
481 ASSERT_EQ(display_list->op_count(), 6u);
489 display_list_item_2, preroll_context, paint_context,
matrix));
490 ASSERT_FALSE(display_list_item_2.
Draw(paint_context, &dummy_canvas, &
paint));
496 display_list_item_2, preroll_context, paint_context,
matrix));
497 ASSERT_TRUE(display_list_item_2.
Draw(paint_context, &dummy_canvas, &
paint));
501 size_t threshold = 2;
509 int matrix_count =
sizeof(matrices) /
sizeof(matrices[0]);
524 preroll_state_stack, &
cache, &raster_time, &ui_time);
526 paint_state_stack, &
cache, &raster_time, &ui_time);
533 for (
int i = 0;
i < 10;
i++) {
536 for (
int j = 0; j < matrix_count; j++) {
539 display_list_item, preroll_context, paint_context, matrices[j]));
542 for (
int j = 0; j < matrix_count; j++) {
545 display_list_item.
Draw(paint_context, &dummy_canvas, &
paint));
558 auto blur_layer = std::make_shared<ImageFilterLayer>(blur_filter);
560 auto transform_layer = std::make_shared<TransformLayer>(
matrix);
563 child_layer->set_expected_paint_matrix(cache_matrix);
565 blur_layer->Add(child_layer);
566 transform_layer->Add(blur_layer);
568 size_t threshold = 2;
579 std::vector<RasterCacheItem*> cache_items;
584 preroll_state_stack, &
cache, &raster_time, &ui_time);
585 preroll_holder.preroll_context.raster_cached_entries = &cache_items;
586 transform_layer->Preroll(&preroll_holder.preroll_context);
589 &raster_time, &ui_time);
591 cache.EvictUnusedCacheEntries();
593 *preroll_holder.preroll_context.raster_cached_entries,
594 &paint_holder.paint_context);
601 auto hash_function =
map.hash_function();
610 auto layer_hash_code = hash_function(layer_key);
611 ASSERT_EQ(layer_hash_code, layer_cache_key_id.GetHash());
613 auto display_list_cache_key_id =
615 auto display_list_hash_code = hash_function(display_list_key);
616 ASSERT_EQ(display_list_hash_code, display_list_cache_key_id.GetHash());
618 auto layer_children_cache_key_id =
620 auto layer_children_hash_code = hash_function(layer_children_key);
621 ASSERT_EQ(layer_children_hash_code, layer_children_cache_key_id.GetHash());
632 map[layer_key] = 100;
633 map[display_list_key] = 300;
634 map[layer_children_key] = 400;
636 ASSERT_EQ(
map[layer_key], 100);
637 ASSERT_EQ(
map[display_list_key], 300);
638 ASSERT_EQ(
map[layer_children_key], 400);
649 map[layer_first_key] = 50;
650 map[layer_second_key] = 100;
651 map[layer_third_key] = 150;
652 ASSERT_EQ(
map[layer_first_key], 50);
653 ASSERT_EQ(
map[layer_second_key], 100);
654 ASSERT_EQ(
map[layer_third_key], 150);
660 map[picture_first_key] = 200;
661 map[picture_second_key] = 250;
662 map[picture_third_key] = 300;
663 ASSERT_EQ(
map[picture_first_key], 200);
664 ASSERT_EQ(
map[picture_second_key], 250);
665 ASSERT_EQ(
map[picture_third_key], 300);
671 map[display_list_first_key] = 350;
672 map[display_list_second_key] = 400;
673 map[display_list_third_key] = 450;
674 ASSERT_EQ(
map[display_list_first_key], 350);
675 ASSERT_EQ(
map[display_list_second_key], 400);
676 ASSERT_EQ(
map[display_list_third_key], 450);
688 map[layer_children_first_key] = 100;
689 map[layer_children_second_key] = 200;
690 map[layer_children_third_key] = 300;
691 ASSERT_EQ(
map[layer_children_first_key], 100);
692 ASSERT_EQ(
map[layer_children_second_key], 200);
693 ASSERT_EQ(
map[layer_children_third_key], 300);
702 ASSERT_NE(first, second);
703 ASSERT_NE(first, third);
704 ASSERT_NE(second, third);
712 ASSERT_NE(fourth, fifth);
713 ASSERT_NE(fifth, sixth);
721 std::size_t first_hash = first.
GetHash();
722 std::size_t second_hash = second.
GetHash();
731 std::size_t third_hash = third.
GetHash();
732 std::size_t fourth_hash = fourth.GetHash();
742 ASSERT_EQ(first_hash, first.
GetHash());
743 ASSERT_EQ(second_hash, second.
GetHash());
744 ASSERT_EQ(third_hash, third.
GetHash());
745 ASSERT_EQ(fourth_hash, fourth.GetHash());
751 auto layer = std::make_shared<ContainerLayer>();
754 auto mock_layer = std::make_shared<MockLayer>(child_path);
755 layer->Add(mock_layer);
758 auto display_list_layer = std::make_shared<DisplayListLayer>(
760 layer->Add(display_list_layer);
763 std::vector<RasterCacheKeyID> expected_ids;
764 expected_ids.emplace_back(
768 ASSERT_EQ(expected_ids[0], mock_layer->caching_key_id());
769 ASSERT_EQ(expected_ids[1], display_list_layer->caching_key_id());
770 ASSERT_EQ(ids, expected_ids);
773TEST(RasterCacheUtilsTest, SkMatrixIntegralTransCTM) {
774#define EXPECT_EQ_WITH_TRANSLATE(test, expected, expected_tx, expected_ty) \
776 EXPECT_EQ(test[SkMatrix::kMScaleX], expected[SkMatrix::kMScaleX]); \
777 EXPECT_EQ(test[SkMatrix::kMSkewX], expected[SkMatrix::kMSkewX]); \
778 EXPECT_EQ(test[SkMatrix::kMScaleY], expected[SkMatrix::kMScaleY]); \
779 EXPECT_EQ(test[SkMatrix::kMSkewY], expected[SkMatrix::kMSkewY]); \
780 EXPECT_EQ(test[SkMatrix::kMSkewX], expected[SkMatrix::kMSkewX]); \
781 EXPECT_EQ(test[SkMatrix::kMPersp0], expected[SkMatrix::kMPersp0]); \
782 EXPECT_EQ(test[SkMatrix::kMPersp1], expected[SkMatrix::kMPersp1]); \
783 EXPECT_EQ(test[SkMatrix::kMPersp2], expected[SkMatrix::kMPersp2]); \
784 EXPECT_EQ(test[SkMatrix::kMTransX], expected_tx); \
785 EXPECT_EQ(test[SkMatrix::kMTransY], expected_ty); \
788#define EXPECT_NON_INTEGER_TRANSLATION(matrix) \
789 EXPECT_TRUE(SkScalarFraction(matrix[SkMatrix::kMTransX]) != 0.0f || \
790 SkScalarFraction(matrix[SkMatrix::kMTransY]) != 0.0f)
816 EXPECT_EQ(
get, compute);
826 EXPECT_EQ(
get, compute);
836 EXPECT_EQ(
get, compute);
849 matrix.preTranslate(10.0f, 12.0f);
858 matrix.preTranslate(10.7f, 12.1f);
864 EXPECT_EQ(
get, compute);
877 matrix.preTranslate(10.7f, 12.1f);
895 matrix.preTranslate(10.7f, 12.1f);
915 matrix.preTranslate(10.7f, 12.1f);
935 matrix.preTranslate(10.7f, 12.1f);
963 matrix.preTranslate(10.7f, 12.1f);
970#undef EXPECT_NON_INTEGER_TRANSLATION
971#undef EXPECT_EQ_WITH_TRANSLATE
974TEST(RasterCacheUtilsTest, SkM44IntegralTransCTM) {
975#define EXPECT_EQ_WITH_TRANSLATE(test, expected, tx, ty, label) \
977 EXPECT_EQ(test.rc(0, 0), expected.rc(0, 0)) << label; \
978 EXPECT_EQ(test.rc(0, 1), expected.rc(0, 1)) << label; \
979 EXPECT_EQ(test.rc(0, 2), expected.rc(0, 2)) << label; \
980 EXPECT_EQ(test.rc(0, 3), tx) << label; \
981 EXPECT_EQ(test.rc(1, 0), expected.rc(1, 0)) << label; \
982 EXPECT_EQ(test.rc(1, 1), expected.rc(1, 1)) << label; \
983 EXPECT_EQ(test.rc(1, 2), expected.rc(1, 2)) << label; \
984 EXPECT_EQ(test.rc(1, 3), ty) << label; \
985 EXPECT_EQ(test.rc(2, 0), expected.rc(2, 0)) << label; \
986 EXPECT_EQ(test.rc(2, 1), expected.rc(2, 1)) << label; \
987 EXPECT_EQ(test.rc(2, 2), expected.rc(2, 2)) << label; \
988 EXPECT_EQ(test.rc(2, 3), expected.rc(2, 3)) << label; \
989 EXPECT_EQ(test.rc(3, 0), expected.rc(3, 0)) << label; \
990 EXPECT_EQ(test.rc(3, 1), expected.rc(3, 1)) << label; \
991 EXPECT_EQ(test.rc(3, 2), expected.rc(3, 2)) << label; \
992 EXPECT_EQ(test.rc(3, 3), expected.rc(3, 3)) << label; \
995#define EXPECT_NON_INTEGER_TRANSLATION(matrix) \
996 EXPECT_TRUE(SkScalarFraction(matrix.rc(0, 3)) != 0.0f || \
997 SkScalarFraction(matrix.rc(1, 3)) != 0.0f)
999 for (
int r = 0; r < 4; r++) {
1000 for (
int c = 0; c < 4; c++) {
1027 matrix.setRC(r, c, 0.5f);
1034 EXPECT_EQ(
get, compute) << label;
1044#undef EXPECT_NON_INTEGER_TRANSLATION
1045#undef EXPECT_EQ_WITH_TRANSLATE
static SkM44 Translate(SkScalar x, SkScalar y, SkScalar z=0)
static SkMatrix Scale(SkScalar sx, SkScalar sy)
static SkMatrix RotateDeg(SkScalar deg)
static SkMatrix Translate(SkScalar dx, SkScalar dy)
static SkMatrix MakeAll(SkScalar scaleX, SkScalar skewX, SkScalar transX, SkScalar skewY, SkScalar scaleY, SkScalar transY, SkScalar pers0, SkScalar pers1, SkScalar pers2)
static const SkMatrix & I()
SkMatrix & preConcat(const SkMatrix &other)
static SkMatrix Skew(SkScalar kx, SkScalar ky)
SkPath & addOval(const SkRect &oval, SkPathDirection dir=SkPathDirection::kCW)
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
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
Used for fixed refresh rate cases.
void set_preroll_delegate(const SkRect &cull_rect, const SkMatrix &matrix)
void set_delegate(DlCanvas *canvas)
static void TryToRasterCache(const std::vector< RasterCacheItem * > &raster_cached_entries, const PaintContext *paint_context, bool ignore_raster_cache=false)
void set_matrix(const SkMatrix &matrix)
virtual std::optional< RasterCacheKeyID > GetId() const
static constexpr uint64_t kDefaultUniqueID
std::size_t GetHash() const
static std::optional< std::vector< RasterCacheKeyID > > LayerChildrenIds(const Layer *layer)
std::unordered_map< RasterCacheKey, Value, Hash, Equal > Map
void Translate(SkScalar tx, SkScalar ty) override
void SetTransform(const SkMatrix *matrix) override
static std::shared_ptr< MockLayer > Make(const SkPath &path, DlPaint paint=DlPaint())
A RasterCache implementation that simulates the act of rendering a Layer or DisplayList without the o...
#define FML_UNREACHABLE()
unsigned useCenter Optional< SkMatrix > matrix
TEST_F(DisplayListTest, Defaults)
bool RasterCacheItemTryToRasterCache(DisplayListRasterCacheItem &display_list_item, PaintContext &paint_context)
LayerTestBase<::testing::Test > LayerTest
PrerollContextHolder GetSamplePrerollContextHolder(LayerStateStack &state_stack, RasterCache *raster_cache, FixedRefreshRateStopwatch *raster_time, FixedRefreshRateStopwatch *ui_time)
void RasterCacheItemPreroll(DisplayListRasterCacheItem &display_list_item, PrerollContext &context, const SkMatrix &matrix)
sk_sp< DisplayList > GetSampleDisplayList()
bool RasterCacheItemPrerollAndTryToRasterCache(DisplayListRasterCacheItem &display_list_item, PrerollContext &context, PaintContext &paint_context, const SkMatrix &matrix)
sk_sp< DisplayList > GetSampleNestedDisplayList()
PaintContextHolder GetSamplePaintContextHolder(LayerStateStack &state_stack, RasterCache *raster_cache, FixedRefreshRateStopwatch *raster_time, FixedRefreshRateStopwatch *ui_time)
TEST(DisplayListComplexity, EmptyDisplayList)
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace Enable an endless trace buffer The default is a ring buffer This is useful when very old events need to viewed For during application launch Memory usage will continue to grow indefinitely however Start app with an specific route defined on the framework flutter assets Path to the Flutter assets directory enable service port Allow the VM service to fallback to automatic port selection if binding to a specified port fails trace Trace early application lifecycle Automatically switches to an endless trace buffer trace skia Filters out all Skia trace event categories except those that are specified in this comma separated list dump skp on shader Automatically dump the skp that triggers new shader compilations This is useful for writing custom ShaderWarmUp to reduce jank By this is not enabled to reduce the overhead purge persistent cache
static constexpr SkRect kGiantRect
constexpr std::size_t HashCombine()
const myers::Point & get(const myers::Segment &)
SI auto map(std::index_sequence< I... >, Fn &&fn, const Args &... args) -> skvx::Vec< sizeof...(I), decltype(fn(args[0]...))>
static SkString to_string(int n)
#define EXPECT_NON_INTEGER_TRANSLATION(matrix)
#define EXPECT_EQ_WITH_TRANSLATE(test, expected, expected_tx, expected_ty)
static constexpr SkPoint Make(float x, float y)
static constexpr SkRect MakeWH(float w, float h)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
static constexpr DlColor kRed()
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)
PaintContext paint_context
PrerollContext preroll_context
#define EXPECT_TRUE(handle)