diff --git a/BUILD.gn b/BUILD.gn index 0417f9e9974c9..a4dd6ca59ce58 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -126,6 +126,7 @@ group("flutter") { if (enable_unittests && !is_win && !is_fuchsia) { public_deps += [ "//flutter/display_list:display_list_benchmarks", + "//flutter/display_list:display_list_builder_benchmarks", "//flutter/fml:fml_benchmarks", "//flutter/lib/ui:ui_benchmarks", "//flutter/shell/common:shell_benchmarks", diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 2c1b9c9718ef6..61d66b1b429d3 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -55,6 +55,7 @@ FILE: ../../../flutter/display_list/display_list_blend_mode.cc FILE: ../../../flutter/display_list/display_list_blend_mode.h FILE: ../../../flutter/display_list/display_list_builder.cc FILE: ../../../flutter/display_list/display_list_builder.h +FILE: ../../../flutter/display_list/display_list_builder_benchmarks.cc FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.cc FILE: ../../../flutter/display_list/display_list_canvas_dispatcher.h FILE: ../../../flutter/display_list/display_list_canvas_recorder.cc diff --git a/display_list/BUILD.gn b/display_list/BUILD.gn index 218ac86ba227f..0724e4a997d6b 100644 --- a/display_list/BUILD.gn +++ b/display_list/BUILD.gn @@ -154,6 +154,20 @@ if (enable_unittests) { [ "${fuchsia_sdk_path}/arch/${target_cpu}/sysroot/lib/libzircon.so" ] } } + + executable("display_list_builder_benchmarks") { + testonly = true + + sources = [ "display_list_builder_benchmarks.cc" ] + + deps = [ + ":display_list", + ":display_list_fixtures", + ":display_list_testing", + "//flutter/benchmarking", + "//flutter/testing:testing_lib", + ] + } } fixtures_location("display_list_benchmarks_fixtures") { diff --git a/display_list/display_list_builder_benchmarks.cc b/display_list/display_list_builder_benchmarks.cc new file mode 100644 index 0000000000000..4ebadb4521bc6 --- /dev/null +++ b/display_list/display_list_builder_benchmarks.cc @@ -0,0 +1,235 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "flutter/benchmarking/benchmarking.h" +#include "flutter/display_list/display_list_test_utils.h" + +namespace flutter { +namespace { + +static std::vector allRenderingOps = + testing::CreateAllRenderingOps(); + +enum class DisplayListBuilderBenchmarkType { + kDefault, + kBounds, + kRtree, + kBoundsAndRtree, +}; + +static void InvokeAllRenderingOps(DisplayListBuilder& builder) { + for (auto& group : allRenderingOps) { + for (size_t i = 0; i < group.variants.size(); i++) { + auto& invocation = group.variants[i]; + invocation.Invoke(builder); + } + } +} + +static void Complete(DisplayListBuilder& builder, + DisplayListBuilderBenchmarkType type) { + auto display_list = builder.Build(); + switch (type) { + case DisplayListBuilderBenchmarkType::kBounds: + display_list->bounds(); + break; + case DisplayListBuilderBenchmarkType::kRtree: + display_list->rtree(); + break; + case DisplayListBuilderBenchmarkType::kBoundsAndRtree: + display_list->bounds(); + display_list->rtree(); + break; + case DisplayListBuilderBenchmarkType::kDefault: + break; + } +} + +} // namespace + +static void BM_DisplayListBuiderDefault(benchmark::State& state, + DisplayListBuilderBenchmarkType type) { + while (state.KeepRunning()) { + DisplayListBuilder builder; + InvokeAllRenderingOps(builder); + Complete(builder, type); + } +} + +static void BM_DisplayListBuiderWithScaleAndTranslate( + benchmark::State& state, + DisplayListBuilderBenchmarkType type) { + while (state.KeepRunning()) { + DisplayListBuilder builder; + builder.scale(3.5, 3.5); + builder.translate(10.3, 6.9); + InvokeAllRenderingOps(builder); + Complete(builder, type); + } +} + +static void BM_DisplayListBuiderWithPerspective( + benchmark::State& state, + DisplayListBuilderBenchmarkType type) { + while (state.KeepRunning()) { + DisplayListBuilder builder; + builder.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, 0, + 0, 0, 12); + InvokeAllRenderingOps(builder); + Complete(builder, type); + } +} + +static void BM_DisplayListBuiderWithClipRect( + benchmark::State& state, + DisplayListBuilderBenchmarkType type) { + SkRect clip_bounds = SkRect::MakeLTRB(6.5, 7.3, 90.2, 85.7); + while (state.KeepRunning()) { + DisplayListBuilder builder; + builder.clipRect(clip_bounds, SkClipOp::kIntersect, true); + InvokeAllRenderingOps(builder); + Complete(builder, type); + } +} + +static void BM_DisplayListBuiderWithSaveLayer( + benchmark::State& state, + DisplayListBuilderBenchmarkType type) { + while (state.KeepRunning()) { + DisplayListBuilder builder; + for (auto& group : allRenderingOps) { + for (size_t i = 0; i < group.variants.size(); i++) { + auto& invocation = group.variants[i]; + builder.saveLayer(nullptr, false); + invocation.Invoke(builder); + builder.restore(); + } + } + Complete(builder, type); + } +} + +static void BM_DisplayListBuiderWithSaveLayerAndImageFilter( + benchmark::State& state, + DisplayListBuilderBenchmarkType type) { + DlPaint layer_paint; + layer_paint.setImageFilter(&testing::kTestBlurImageFilter1); + SkRect layer_bounds = SkRect::MakeLTRB(6.5, 7.3, 35.2, 42.7); + while (state.KeepRunning()) { + DisplayListBuilder builder; + for (auto& group : allRenderingOps) { + for (size_t i = 0; i < group.variants.size(); i++) { + auto& invocation = group.variants[i]; + builder.saveLayer(&layer_bounds, &layer_paint); + invocation.Invoke(builder); + builder.restore(); + } + } + Complete(builder, type); + } +} + +BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, + kDefault, + DisplayListBuilderBenchmarkType::kDefault) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, + kBounds, + DisplayListBuilderBenchmarkType::kBounds) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, + kRtree, + DisplayListBuilderBenchmarkType::kRtree) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderDefault, + kBoundsAndRtree, + DisplayListBuilderBenchmarkType::kBoundsAndRtree) + ->Unit(benchmark::kMillisecond); + +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, + kDefault, + DisplayListBuilderBenchmarkType::kDefault) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, + kBounds, + DisplayListBuilderBenchmarkType::kBounds) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, + kRtree, + DisplayListBuilderBenchmarkType::kRtree) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithScaleAndTranslate, + kBoundsAndRtree, + DisplayListBuilderBenchmarkType::kBoundsAndRtree) + ->Unit(benchmark::kMillisecond); + +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, + kDefault, + DisplayListBuilderBenchmarkType::kDefault) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, + kBounds, + DisplayListBuilderBenchmarkType::kBounds) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, + kRtree, + DisplayListBuilderBenchmarkType::kRtree) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithPerspective, + kBoundsAndRtree, + DisplayListBuilderBenchmarkType::kBoundsAndRtree) + ->Unit(benchmark::kMillisecond); + +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, + kDefault, + DisplayListBuilderBenchmarkType::kDefault) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, + kBounds, + DisplayListBuilderBenchmarkType::kBounds) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, + kRtree, + DisplayListBuilderBenchmarkType::kRtree) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithClipRect, + kBoundsAndRtree, + DisplayListBuilderBenchmarkType::kBoundsAndRtree) + ->Unit(benchmark::kMillisecond); + +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, + kDefault, + DisplayListBuilderBenchmarkType::kDefault) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, + kBounds, + DisplayListBuilderBenchmarkType::kBounds) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, + kRtree, + DisplayListBuilderBenchmarkType::kRtree) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayer, + kBoundsAndRtree, + DisplayListBuilderBenchmarkType::kBoundsAndRtree) + ->Unit(benchmark::kMillisecond); + +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, + kDefault, + DisplayListBuilderBenchmarkType::kDefault) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, + kBounds, + DisplayListBuilderBenchmarkType::kBounds) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, + kRtree, + DisplayListBuilderBenchmarkType::kRtree) + ->Unit(benchmark::kMillisecond); +BENCHMARK_CAPTURE(BM_DisplayListBuiderWithSaveLayerAndImageFilter, + kBoundsAndRtree, + DisplayListBuilderBenchmarkType::kBoundsAndRtree) + ->Unit(benchmark::kMillisecond); + +} // namespace flutter diff --git a/display_list/display_list_test_utils.cc b/display_list/display_list_test_utils.cc index 0d5c025cdfd41..ebf4c465ba092 100644 --- a/display_list/display_list_test_utils.cc +++ b/display_list/display_list_test_utils.cc @@ -36,5 +36,1085 @@ sk_sp GetSampleDisplayList(int ops) { return builder.Build(); } +// --------------- +// Test Suite data +// --------------- + +std::vector CreateAllAttributesOps() { + return { + {"SetAntiAlias", + { + {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setAntiAlias(true); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setAntiAlias(false); }}, + }}, + {"SetDither", + { + {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setDither(true); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setDither(false); }}, + }}, + {"SetInvertColors", + { + {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setInvertColors(true); }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setInvertColors(false); }}, + }}, + {"SetStrokeCap", + { + {0, 8, 0, 0, + [](DisplayListBuilder& b) { b.setStrokeCap(DlStrokeCap::kRound); }}, + {0, 8, 0, 0, + [](DisplayListBuilder& b) { + b.setStrokeCap(DlStrokeCap::kSquare); + }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setStrokeCap(DlStrokeCap::kButt); }}, + }}, + {"SetStrokeJoin", + { + {0, 8, 0, 0, + [](DisplayListBuilder& b) { + b.setStrokeJoin(DlStrokeJoin::kBevel); + }}, + {0, 8, 0, 0, + [](DisplayListBuilder& b) { + b.setStrokeJoin(DlStrokeJoin::kRound); + }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { + b.setStrokeJoin(DlStrokeJoin::kMiter); + }}, + }}, + {"SetStyle", + { + {0, 8, 0, 0, + [](DisplayListBuilder& b) { b.setStyle(DlDrawStyle::kStroke); }}, + {0, 8, 0, 0, + [](DisplayListBuilder& b) { + b.setStyle(DlDrawStyle::kStrokeAndFill); + }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setStyle(DlDrawStyle::kFill); }}, + }}, + {"SetStrokeWidth", + { + {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeWidth(1.0); }}, + {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeWidth(5.0); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setStrokeWidth(0.0); }}, + }}, + {"SetStrokeMiter", + { + {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeMiter(0.0); }}, + {0, 8, 0, 0, [](DisplayListBuilder& b) { b.setStrokeMiter(5.0); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setStrokeMiter(4.0); }}, + }}, + {"SetColor", + { + {0, 8, 0, 0, + [](DisplayListBuilder& b) { b.setColor(SK_ColorGREEN); }}, + {0, 8, 0, 0, + [](DisplayListBuilder& b) { b.setColor(SK_ColorBLUE); }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setColor(SK_ColorBLACK); }}, + }}, + {"SetBlendModeOrBlender", + { + {0, 8, 0, 0, + [](DisplayListBuilder& b) { b.setBlendMode(DlBlendMode::kSrcIn); }}, + {0, 8, 0, 0, + [](DisplayListBuilder& b) { b.setBlendMode(DlBlendMode::kDstIn); }}, + {0, 16, 0, 0, + [](DisplayListBuilder& b) { b.setBlender(kTestBlender1); }}, + {0, 16, 0, 0, + [](DisplayListBuilder& b) { b.setBlender(kTestBlender2); }}, + {0, 16, 0, 0, + [](DisplayListBuilder& b) { b.setBlender(kTestBlender3); }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { + b.setBlendMode(DlBlendMode::kSrcOver); + }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.setBlender(nullptr); }}, + }}, + {"SetColorSource", + { + {0, 96, 0, 0, + [](DisplayListBuilder& b) { b.setColorSource(&kTestSource1); }}, + // stop_count * (sizeof(float) + sizeof(uint32_t)) = 80 + {0, 80 + 6 * 4, 0, 0, + [](DisplayListBuilder& b) { + b.setColorSource(kTestSource2.get()); + }}, + {0, 80 + 6 * 4, 0, 0, + [](DisplayListBuilder& b) { + b.setColorSource(kTestSource3.get()); + }}, + {0, 88 + 6 * 4, 0, 0, + [](DisplayListBuilder& b) { + b.setColorSource(kTestSource4.get()); + }}, + {0, 80 + 6 * 4, 0, 0, + [](DisplayListBuilder& b) { + b.setColorSource(kTestSource5.get()); + }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setColorSource(nullptr); }}, + }}, + {"SetImageFilter", + { + {0, 32, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestBlurImageFilter1); + }}, + {0, 32, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestBlurImageFilter2); + }}, + {0, 32, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestBlurImageFilter3); + }}, + {0, 32, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestBlurImageFilter4); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestDilateImageFilter1); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestDilateImageFilter2); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestDilateImageFilter3); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestErodeImageFilter1); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestErodeImageFilter2); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestErodeImageFilter3); + }}, + {0, 64, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestMatrixImageFilter1); + }}, + {0, 64, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestMatrixImageFilter2); + }}, + {0, 64, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestMatrixImageFilter3); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestComposeImageFilter1); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestComposeImageFilter2); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestComposeImageFilter3); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestCFImageFilter1); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setImageFilter(&kTestCFImageFilter2); + }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setImageFilter(nullptr); }}, + }}, + {"SetColorFilter", + { + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setColorFilter(&kTestBlendColorFilter1); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setColorFilter(&kTestBlendColorFilter2); + }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { + b.setColorFilter(&kTestBlendColorFilter3); + }}, + {0, 96, 0, 0, + [](DisplayListBuilder& b) { + b.setColorFilter(&kTestMatrixColorFilter1); + }}, + {0, 96, 0, 0, + [](DisplayListBuilder& b) { + b.setColorFilter(&kTestMatrixColorFilter2); + }}, + {0, 16, 0, 0, + [](DisplayListBuilder& b) { + b.setColorFilter(DlSrgbToLinearGammaColorFilter::instance.get()); + }}, + {0, 16, 0, 0, + [](DisplayListBuilder& b) { + b.setColorFilter(DlLinearToSrgbGammaColorFilter::instance.get()); + }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setColorFilter(nullptr); }}, + }}, + {"SetPathEffect", + { + // sizeof(DlDashPathEffect) + 2 * sizeof(SkScalar) + {0, 32, 0, 0, + [](DisplayListBuilder& b) { + b.setPathEffect(kTestPathEffect1.get()); + }}, + {0, 32, 0, 0, + [](DisplayListBuilder& b) { + b.setPathEffect(kTestPathEffect2.get()); + }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setPathEffect(nullptr); }}, + }}, + {"SetMaskFilter", + { + {0, 24, 0, 0, + [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter1); }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter2); }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter3); }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter4); }}, + {0, 24, 0, 0, + [](DisplayListBuilder& b) { b.setMaskFilter(&kTestMaskFilter5); }}, + {0, 0, 0, 0, + [](DisplayListBuilder& b) { b.setMaskFilter(nullptr); }}, + }}, + }; +} + +std::vector CreateAllSaveRestoreOps() { + return { + {"Save(Layer)+Restore", + { + {5, 104, 5, 104, + [](DisplayListBuilder& b) { + b.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, + &kTestCFImageFilter1); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + // There are many reasons that save and restore can elide content, + // including whether or not there are any draw operations between + // them, whether or not there are any state changes to restore, and + // whether group rendering (opacity) optimizations can allow + // attributes to be distributed to the children. To prevent those + // cases we include at least one clip operation and 2 overlapping + // rendering primitives between each save/restore pair. + {5, 88, 5, 88, + [](DisplayListBuilder& b) { + b.save(); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + {5, 88, 5, 88, + [](DisplayListBuilder& b) { + b.saveLayer(nullptr, false); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + {5, 88, 5, 88, + [](DisplayListBuilder& b) { + b.saveLayer(nullptr, true); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + {5, 104, 5, 104, + [](DisplayListBuilder& b) { + b.saveLayer(&kTestBounds, false); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + {5, 104, 5, 104, + [](DisplayListBuilder& b) { + b.saveLayer(&kTestBounds, true); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + // backdrop variants - using the TestCFImageFilter because it can be + // reconstituted in the DL->SkCanvas->DL stream + // {5, 104, 5, 104, [](DisplayListBuilder& b) { + // b.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, + // &kTestCFImageFilter1); b.clipRect({0, 0, 25, 25}, + // SkClipOp::kIntersect, true); b.drawRect({5, 5, 15, 15}); + // b.drawRect({10, 10, 20, 20}); + // b.restore(); + // }}, + {5, 104, 5, 104, + [](DisplayListBuilder& b) { + b.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, + &kTestCFImageFilter1); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + {5, 120, 5, 120, + [](DisplayListBuilder& b) { + b.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes, + &kTestCFImageFilter1); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + {5, 120, 5, 120, + [](DisplayListBuilder& b) { + b.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes, + &kTestCFImageFilter1); + b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); + b.drawRect({5, 5, 15, 15}); + b.drawRect({10, 10, 20, 20}); + b.restore(); + }}, + }}, + }; +} + +std::vector CreateAllTransformOps() { + return { + {"Translate", + { + // cv.translate(0, 0) is ignored + {1, 16, 1, 16, [](DisplayListBuilder& b) { b.translate(10, 10); }}, + {1, 16, 1, 16, [](DisplayListBuilder& b) { b.translate(10, 15); }}, + {1, 16, 1, 16, [](DisplayListBuilder& b) { b.translate(15, 10); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.translate(0, 0); }}, + }}, + {"Scale", + { + // cv.scale(1, 1) is ignored + {1, 16, 1, 16, [](DisplayListBuilder& b) { b.scale(2, 2); }}, + {1, 16, 1, 16, [](DisplayListBuilder& b) { b.scale(2, 3); }}, + {1, 16, 1, 16, [](DisplayListBuilder& b) { b.scale(3, 2); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.scale(1, 1); }}, + }}, + {"Rotate", + { + // cv.rotate(0) is ignored, otherwise expressed as concat(rotmatrix) + {1, 8, 1, 32, [](DisplayListBuilder& b) { b.rotate(30); }}, + {1, 8, 1, 32, [](DisplayListBuilder& b) { b.rotate(45); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.rotate(0); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.rotate(360); }}, + }}, + {"Skew", + { + // cv.skew(0, 0) is ignored, otherwise expressed as + // concat(skewmatrix) + {1, 16, 1, 32, [](DisplayListBuilder& b) { b.skew(0.1, 0.1); }}, + {1, 16, 1, 32, [](DisplayListBuilder& b) { b.skew(0.1, 0.2); }}, + {1, 16, 1, 32, [](DisplayListBuilder& b) { b.skew(0.2, 0.1); }}, + {0, 0, 0, 0, [](DisplayListBuilder& b) { b.skew(0, 0); }}, + }}, + {"Transform2DAffine", + { + {1, 32, 1, 32, + [](DisplayListBuilder& b) { + b.transform2DAffine(0, 1, 12, 1, 0, 33); + }}, + // b.transform(identity) is ignored + {0, 0, 0, 0, + [](DisplayListBuilder& b) { + b.transform2DAffine(1, 0, 0, 0, 1, 0); + }}, + }}, + {"TransformFullPerspective", + { + {1, 72, 1, 72, + [](DisplayListBuilder& b) { + b.transformFullPerspective(0, 1, 0, 12, 1, 0, 0, 33, 3, 2, 5, 29, + 0, 0, 0, 12); + }}, + // b.transform(2D affine) is reduced to 2x3 + {1, 32, 1, 32, + [](DisplayListBuilder& b) { + b.transformFullPerspective(2, 1, 0, 4, 1, 3, 0, 5, 0, 0, 1, 0, 0, + 0, 0, 1); + }}, + // b.transform(identity) is ignored + {0, 0, 0, 0, + [](DisplayListBuilder& b) { + b.transformFullPerspective(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, + 0, 0, 1); + }}, + }}, + }; +} + +std::vector CreateAllClipOps() { + return { + {"ClipRect", + { + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipRect(kTestBounds, SkClipOp::kIntersect, true); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipRect(kTestBounds.makeOffset(1, 1), SkClipOp::kIntersect, + true); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipRect(kTestBounds, SkClipOp::kIntersect, false); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipRect(kTestBounds, SkClipOp::kDifference, true); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipRect(kTestBounds, SkClipOp::kDifference, false); + }}, + }}, + {"ClipRRect", + { + {1, 64, 1, 64, + [](DisplayListBuilder& b) { + b.clipRRect(kTestRRect, SkClipOp::kIntersect, true); + }}, + {1, 64, 1, 64, + [](DisplayListBuilder& b) { + b.clipRRect(kTestRRect.makeOffset(1, 1), SkClipOp::kIntersect, + true); + }}, + {1, 64, 1, 64, + [](DisplayListBuilder& b) { + b.clipRRect(kTestRRect, SkClipOp::kIntersect, false); + }}, + {1, 64, 1, 64, + [](DisplayListBuilder& b) { + b.clipRRect(kTestRRect, SkClipOp::kDifference, true); + }}, + {1, 64, 1, 64, + [](DisplayListBuilder& b) { + b.clipRRect(kTestRRect, SkClipOp::kDifference, false); + }}, + }}, + {"ClipPath", + { + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipPath(kTestPath1, SkClipOp::kIntersect, true); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipPath(kTestPath2, SkClipOp::kIntersect, true); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipPath(kTestPath3, SkClipOp::kIntersect, true); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipPath(kTestPath1, SkClipOp::kIntersect, false); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipPath(kTestPath1, SkClipOp::kDifference, true); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipPath(kTestPath1, SkClipOp::kDifference, false); + }}, + // clipPath(rect) becomes clipRect + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.clipPath(kTestPathRect, SkClipOp::kIntersect, true); + }}, + // clipPath(oval) becomes clipRRect + {1, 64, 1, 64, + [](DisplayListBuilder& b) { + b.clipPath(kTestPathOval, SkClipOp::kIntersect, true); + }}, + }}, + }; +} + +std::vector CreateAllRenderingOps() { + return { + {"DrawPaint", + { + {1, 8, 1, 8, [](DisplayListBuilder& b) { b.drawPaint(); }}, + }}, + {"DrawColor", + { + // cv.drawColor becomes cv.drawPaint(paint) + {1, 16, 1, 24, + [](DisplayListBuilder& b) { + b.drawColor(SK_ColorBLUE, DlBlendMode::kSrcIn); + }}, + {1, 16, 1, 24, + [](DisplayListBuilder& b) { + b.drawColor(SK_ColorBLUE, DlBlendMode::kDstIn); + }}, + {1, 16, 1, 24, + [](DisplayListBuilder& b) { + b.drawColor(SK_ColorCYAN, DlBlendMode::kSrcIn); + }}, + }}, + {"DrawLine", + { + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawLine({0, 0}, {10, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawLine({0, 1}, {10, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawLine({0, 0}, {20, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawLine({0, 0}, {10, 20}); + }}, + }}, + {"DrawRect", + { + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawRect({0, 0, 10, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawRect({0, 1, 10, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawRect({0, 0, 20, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawRect({0, 0, 10, 20}); + }}, + }}, + {"DrawOval", + { + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawOval({0, 0, 10, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawOval({0, 1, 10, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawOval({0, 0, 20, 10}); + }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { + b.drawOval({0, 0, 10, 20}); + }}, + }}, + {"DrawCircle", + { + // cv.drawCircle becomes cv.drawOval + {1, 16, 1, 24, + [](DisplayListBuilder& b) { + b.drawCircle({0, 0}, 10); + }}, + {1, 16, 1, 24, + [](DisplayListBuilder& b) { + b.drawCircle({0, 5}, 10); + }}, + {1, 16, 1, 24, + [](DisplayListBuilder& b) { + b.drawCircle({0, 0}, 20); + }}, + }}, + {"DrawRRect", + { + {1, 56, 1, 56, + [](DisplayListBuilder& b) { b.drawRRect(kTestRRect); }}, + {1, 56, 1, 56, + [](DisplayListBuilder& b) { + b.drawRRect(kTestRRect.makeOffset(5, 5)); + }}, + }}, + {"DrawDRRect", + { + {1, 112, 1, 112, + [](DisplayListBuilder& b) { + b.drawDRRect(kTestRRect, kTestInnerRRect); + }}, + {1, 112, 1, 112, + [](DisplayListBuilder& b) { + b.drawDRRect(kTestRRect.makeOffset(5, 5), + kTestInnerRRect.makeOffset(4, 4)); + }}, + }}, + {"DrawPath", + { + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawPath(kTestPath1); }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawPath(kTestPath2); }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawPath(kTestPath3); }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawPath(kTestPathRect); }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawPath(kTestPathOval); }}, + }}, + {"DrawArc", + { + {1, 32, 1, 32, + [](DisplayListBuilder& b) { + b.drawArc(kTestBounds, 45, 270, false); + }}, + {1, 32, 1, 32, + [](DisplayListBuilder& b) { + b.drawArc(kTestBounds.makeOffset(1, 1), 45, 270, false); + }}, + {1, 32, 1, 32, + [](DisplayListBuilder& b) { + b.drawArc(kTestBounds, 30, 270, false); + }}, + {1, 32, 1, 32, + [](DisplayListBuilder& b) { + b.drawArc(kTestBounds, 45, 260, false); + }}, + {1, 32, 1, 32, + [](DisplayListBuilder& b) { + b.drawArc(kTestBounds, 45, 270, true); + }}, + }}, + {"DrawPoints", + { + {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, + [](DisplayListBuilder& b) { + b.drawPoints(SkCanvas::kPoints_PointMode, TestPointCount, + TestPoints); + }}, + {1, 8 + (TestPointCount - 1) * 8, 1, 8 + (TestPointCount - 1) * 8, + [](DisplayListBuilder& b) { + b.drawPoints(SkCanvas::kPoints_PointMode, TestPointCount - 1, + TestPoints); + }}, + {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, + [](DisplayListBuilder& b) { + b.drawPoints(SkCanvas::kLines_PointMode, TestPointCount, + TestPoints); + }}, + {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, + [](DisplayListBuilder& b) { + b.drawPoints(SkCanvas::kPolygon_PointMode, TestPointCount, + TestPoints); + }}, + }}, + {"DrawVertices", + { + {1, 112, 1, 16, + [](DisplayListBuilder& b) { + b.drawVertices(TestVertices1, DlBlendMode::kSrcIn); + }}, + {1, 112, 1, 16, + [](DisplayListBuilder& b) { + b.drawVertices(TestVertices1, DlBlendMode::kDstIn); + }}, + {1, 112, 1, 16, + [](DisplayListBuilder& b) { + b.drawVertices(TestVertices2, DlBlendMode::kSrcIn); + }}, + }}, + {"DrawImage", + { + {1, 24, -1, 48, + [](DisplayListBuilder& b) { + b.drawImage(TestImage1, {10, 10}, kNearestSampling, false); + }}, + {1, 24, -1, 48, + [](DisplayListBuilder& b) { + b.drawImage(TestImage1, {10, 10}, kNearestSampling, true); + }}, + {1, 24, -1, 48, + [](DisplayListBuilder& b) { + b.drawImage(TestImage1, {20, 10}, kNearestSampling, false); + }}, + {1, 24, -1, 48, + [](DisplayListBuilder& b) { + b.drawImage(TestImage1, {10, 20}, kNearestSampling, false); + }}, + {1, 24, -1, 48, + [](DisplayListBuilder& b) { + b.drawImage(TestImage1, {10, 10}, kLinearSampling, false); + }}, + {1, 24, -1, 48, + [](DisplayListBuilder& b) { + b.drawImage(TestImage2, {10, 10}, kNearestSampling, false); + }}, + }}, + {"DrawImageRect", + { + {1, 56, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kNearestSampling, false); + }}, + {1, 56, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kNearestSampling, true); + }}, + {1, 56, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageRect( + TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kNearestSampling, false, + SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint); + }}, + {1, 56, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageRect(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, + kNearestSampling, false); + }}, + {1, 56, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, + kNearestSampling, false); + }}, + {1, 56, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + kLinearSampling, false); + }}, + {1, 56, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageRect(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, + kNearestSampling, false); + }}, + }}, + {"DrawImageNine", + { + // SkVanvas::drawImageNine is immediately converted to + // drawImageLattice + {1, 48, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + DlFilterMode::kNearest, false); + }}, + {1, 48, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + DlFilterMode::kNearest, true); + }}, + {1, 48, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, + DlFilterMode::kNearest, false); + }}, + {1, 48, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, + DlFilterMode::kNearest, false); + }}, + {1, 48, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, + DlFilterMode::kLinear, false); + }}, + {1, 48, -1, 80, + [](DisplayListBuilder& b) { + b.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, + DlFilterMode::kNearest, false); + }}, + }}, + {"DrawImageLattice", + { + // Lattice: + // const int* fXDivs; //!< x-axis values dividing bitmap + // const int* fYDivs; //!< y-axis values dividing bitmap + // const RectType* fRectTypes; //!< array of fill types + // int fXCount; //!< number of x-coordinates + // int fYCount; //!< number of y-coordinates + // const SkIRect* fBounds; //!< source bounds to draw from + // const SkColor* fColors; //!< array of colors + // size = 64 + fXCount * 4 + fYCount * 4 + // if fColors and fRectTypes are not null, add (fXCount + 1) * + // (fYCount + 1) * 5 + {1, 88, -1, 88, + [](DisplayListBuilder& b) { + b.drawImageLattice( + TestImage1, + {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, + {10, 10, 40, 40}, DlFilterMode::kNearest, false); + }}, + {1, 88, -1, 88, + [](DisplayListBuilder& b) { + b.drawImageLattice( + TestImage1, + {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, + {10, 10, 40, 45}, DlFilterMode::kNearest, false); + }}, + {1, 88, -1, 88, + [](DisplayListBuilder& b) { + b.drawImageLattice( + TestImage1, + {kTestDivs2, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, + {10, 10, 40, 40}, DlFilterMode::kNearest, false); + }}, + // One less yDiv does not change the allocation due to 8-byte + // alignment + {1, 88, -1, 88, + [](DisplayListBuilder& b) { + b.drawImageLattice( + TestImage1, + {kTestDivs1, kTestDivs1, nullptr, 3, 2, nullptr, nullptr}, + {10, 10, 40, 40}, DlFilterMode::kNearest, false); + }}, + {1, 88, -1, 88, + [](DisplayListBuilder& b) { + b.drawImageLattice( + TestImage1, + {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, + {10, 10, 40, 40}, DlFilterMode::kLinear, false); + }}, + {1, 96, -1, 96, + [](DisplayListBuilder& b) { + b.setColor(SK_ColorMAGENTA); + b.drawImageLattice( + TestImage1, + {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, + {10, 10, 40, 40}, DlFilterMode::kNearest, true); + }}, + {1, 88, -1, 88, + [](DisplayListBuilder& b) { + b.drawImageLattice( + TestImage2, + {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, + {10, 10, 40, 40}, DlFilterMode::kNearest, false); + }}, + // Supplying fBounds does not change size because the Op record + // always includes it + {1, 88, -1, 88, + [](DisplayListBuilder& b) { + b.drawImageLattice(TestImage1, + {kTestDivs1, kTestDivs1, nullptr, 3, 3, + &kTestLatticeSrcRect, nullptr}, + {10, 10, 40, 40}, DlFilterMode::kNearest, + false); + }}, + {1, 128, -1, 128, + [](DisplayListBuilder& b) { + b.drawImageLattice(TestImage1, + {kTestDivs3, kTestDivs3, kTestRTypes, 2, 2, + nullptr, kTestLatticeColors}, + {10, 10, 40, 40}, DlFilterMode::kNearest, + false); + }}, + }}, + {"DrawAtlas", + { + {1, 48 + 32 + 8, -1, 48 + 32 + 32, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kNearestSampling, nullptr, + false); + }}, + {1, 48 + 32 + 8, -1, 48 + 32 + 32, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kNearestSampling, nullptr, true); + }}, + {1, 48 + 32 + 8, -1, 48 + 32 + 32, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{0, 1, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kNearestSampling, nullptr, + false); + }}, + {1, 48 + 32 + 8, -1, 48 + 32 + 32, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 25, 30, 30}}; + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kNearestSampling, nullptr, + false); + }}, + {1, 48 + 32 + 8, -1, 48 + 32 + 32, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kLinearSampling, nullptr, false); + }}, + {1, 48 + 32 + 8, -1, 48 + 32 + 32, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, + DlBlendMode::kDstIn, kNearestSampling, nullptr, + false); + }}, + {1, 64 + 32 + 8, -1, 64 + 32 + 32, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + static SkRect cullRect = {0, 0, 200, 200}; + b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, + DlBlendMode::kSrcIn, kNearestSampling, &cullRect, + false); + }}, + {1, 48 + 32 + 8 + 8, -1, 48 + 32 + 32 + 8, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()}; + b.drawAtlas(TestImage1, xforms, texs, colors, 2, + DlBlendMode::kSrcIn, kNearestSampling, nullptr, + false); + }}, + {1, 64 + 32 + 8 + 8, -1, 64 + 32 + 32 + 8, + [](DisplayListBuilder& b) { + static SkRSXform xforms[] = {{1, 0, 0, 0}, {0, 1, 0, 0}}; + static SkRect texs[] = {{10, 10, 20, 20}, {20, 20, 30, 30}}; + static DlColor colors[] = {DlColor::kBlue(), DlColor::kGreen()}; + static SkRect cullRect = {0, 0, 200, 200}; + b.drawAtlas(TestImage1, xforms, texs, colors, 2, + DlBlendMode::kSrcIn, kNearestSampling, &cullRect, + false); + }}, + }}, + {"DrawPicture", + { + // cv.drawPicture cannot be compared as SkCanvas may inline it + {1, 16, -1, 16, + [](DisplayListBuilder& b) { + b.drawPicture(TestPicture1, nullptr, false); + }}, + {1, 16, -1, 16, + [](DisplayListBuilder& b) { + b.drawPicture(TestPicture2, nullptr, false); + }}, + {1, 16, -1, 16, + [](DisplayListBuilder& b) { + b.drawPicture(TestPicture1, nullptr, true); + }}, + {1, 56, -1, 56, + [](DisplayListBuilder& b) { + b.drawPicture(TestPicture1, &kTestMatrix1, false); + }}, + {1, 56, -1, 56, + [](DisplayListBuilder& b) { + b.drawPicture(TestPicture1, &kTestMatrix2, false); + }}, + {1, 56, -1, 56, + [](DisplayListBuilder& b) { + b.drawPicture(TestPicture1, &kTestMatrix1, true); + }}, + }}, + {"DrawDisplayList", + { + // cv.drawDL does not exist + {1, 16, -1, 16, + [](DisplayListBuilder& b) { b.drawDisplayList(TestDisplayList1); }}, + {1, 16, -1, 16, + [](DisplayListBuilder& b) { b.drawDisplayList(TestDisplayList2); }}, + }}, + {"DrawTextBlob", + { + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob1, 10, 10); }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob1, 20, 10); }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob1, 10, 20); }}, + {1, 24, 1, 24, + [](DisplayListBuilder& b) { b.drawTextBlob(TestBlob2, 10, 10); }}, + }}, + // The -1 op counts below are to indicate to the framework not to test + // SkCanvas conversion of these ops as it converts the operation into a + // format that is not exposed publicly and so we cannot recapture the + // operation. + // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 + {"DrawShadow", + { + // cv shadows are turned into an opaque ShadowRec which is not + // exposed + {1, 32, -1, 32, + [](DisplayListBuilder& b) { + b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 1.0); + }}, + {1, 32, -1, 32, + [](DisplayListBuilder& b) { + b.drawShadow(kTestPath2, SK_ColorGREEN, 1.0, false, 1.0); + }}, + {1, 32, -1, 32, + [](DisplayListBuilder& b) { + b.drawShadow(kTestPath1, SK_ColorBLUE, 1.0, false, 1.0); + }}, + {1, 32, -1, 32, + [](DisplayListBuilder& b) { + b.drawShadow(kTestPath1, SK_ColorGREEN, 2.0, false, 1.0); + }}, + {1, 32, -1, 32, + [](DisplayListBuilder& b) { + b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, true, 1.0); + }}, + {1, 32, -1, 32, + [](DisplayListBuilder& b) { + b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 2.5); + }}, + }}, + }; +} + +std::vector CreateAllGroups() { + std::vector result; + auto allAttributesOps = CreateAllAttributesOps(); + std::move(allAttributesOps.begin(), allAttributesOps.end(), + std::back_inserter(result)); + auto allSaveRestoreOps = CreateAllSaveRestoreOps(); + std::move(allSaveRestoreOps.begin(), allSaveRestoreOps.end(), + std::back_inserter(result)); + auto allTransformOps = CreateAllTransformOps(); + std::move(allTransformOps.begin(), allTransformOps.end(), + std::back_inserter(result)); + auto allClipOps = CreateAllClipOps(); + std::move(allClipOps.begin(), allClipOps.end(), std::back_inserter(result)); + auto allRenderingOps = CreateAllRenderingOps(); + std::move(allRenderingOps.begin(), allRenderingOps.end(), + std::back_inserter(result)); + return result; +} + } // namespace testing } // namespace flutter diff --git a/display_list/display_list_test_utils.h b/display_list/display_list_test_utils.h index f420427ddf30a..72d82b68faf82 100644 --- a/display_list/display_list_test_utils.h +++ b/display_list/display_list_test_utils.h @@ -9,6 +9,12 @@ #include "flutter/display_list/display_list_builder.h" #include "third_party/skia/include/core/SkPicture.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "third_party/skia/include/effects/SkBlenders.h" +#include "third_party/skia/include/effects/SkDashPathEffect.h" +#include "third_party/skia/include/effects/SkGradientShader.h" +#include "third_party/skia/include/effects/SkImageFilters.h" namespace flutter { namespace testing { @@ -17,6 +23,313 @@ sk_sp GetSampleDisplayList(); sk_sp GetSampleDisplayList(int ops); sk_sp GetSampleNestedDisplayList(); +typedef const std::function DlInvoker; + +constexpr SkPoint kEndPoints[] = { + {0, 0}, + {100, 100}, +}; +const DlColor kColors[] = { + DlColor::kGreen(), + DlColor::kYellow(), + DlColor::kBlue(), +}; +constexpr float kStops[] = { + 0.0, + 0.5, + 1.0, +}; +static std::vector color_vector(kColors, kColors + 3); +static std::vector stops_vector(kStops, kStops + 3); + +// clang-format off +constexpr float kRotateColorMatrix[20] = { + 0, 1, 0, 0, 0, + 0, 0, 1, 0, 0, + 1, 0, 0, 0, 0, + 0, 0, 0, 1, 0, +}; +constexpr float kInvertColorMatrix[20] = { + -1.0, 0, 0, 1.0, 0, + 0, -1.0, 0, 1.0, 0, + 0, 0, -1.0, 1.0, 0, + 1.0, 1.0, 1.0, 1.0, 0, +}; +// clang-format on + +const SkScalar kTestDashes1[] = {4.0, 2.0}; +const SkScalar kTestDashes2[] = {1.0, 1.5}; + +constexpr SkPoint TestPoints[] = { + {10, 10}, + {20, 20}, + {10, 20}, + {20, 10}, +}; +#define TestPointCount sizeof(TestPoints) / (sizeof(TestPoints[0])) + +static DlImageSampling kNearestSampling = DlImageSampling::kNearestNeighbor; +static DlImageSampling kLinearSampling = DlImageSampling::kLinear; + +static sk_sp MakeTestImage(int w, int h, int checker_size) { + sk_sp surface = SkSurface::MakeRasterN32Premul(w, h); + SkCanvas* canvas = surface->getCanvas(); + SkPaint p0, p1; + p0.setStyle(SkPaint::kFill_Style); + p0.setColor(SK_ColorGREEN); + p1.setStyle(SkPaint::kFill_Style); + p1.setColor(SK_ColorBLUE); + p1.setAlpha(128); + for (int y = 0; y < w; y += checker_size) { + for (int x = 0; x < h; x += checker_size) { + SkPaint& cellp = ((x + y) & 1) == 0 ? p0 : p1; + canvas->drawRect(SkRect::MakeXYWH(x, y, checker_size, checker_size), + cellp); + } + } + return DlImage::Make(surface->makeImageSnapshot()); +} + +static auto TestImage1 = MakeTestImage(40, 40, 5); +static auto TestImage2 = MakeTestImage(50, 50, 5); + +static const sk_sp kTestBlender1 = + SkBlenders::Arithmetic(0.2, 0.2, 0.2, 0.2, false); +static const sk_sp kTestBlender2 = + SkBlenders::Arithmetic(0.2, 0.2, 0.2, 0.2, true); +static const sk_sp kTestBlender3 = + SkBlenders::Arithmetic(0.3, 0.3, 0.3, 0.3, true); +static const DlImageColorSource kTestSource1(TestImage1->skia_image(), + DlTileMode::kClamp, + DlTileMode::kMirror, + kLinearSampling); +static const std::shared_ptr kTestSource2 = + DlColorSource::MakeLinear(kEndPoints[0], + kEndPoints[1], + 3, + kColors, + kStops, + DlTileMode::kMirror); +static const std::shared_ptr kTestSource3 = + DlColorSource::MakeRadial(kEndPoints[0], + 10.0, + 3, + kColors, + kStops, + DlTileMode::kMirror); +static const std::shared_ptr kTestSource4 = + DlColorSource::MakeConical(kEndPoints[0], + 10.0, + kEndPoints[1], + 200.0, + 3, + kColors, + kStops, + DlTileMode::kDecal); +static const std::shared_ptr kTestSource5 = + DlColorSource::MakeSweep(kEndPoints[0], + 0.0, + 360.0, + 3, + kColors, + kStops, + DlTileMode::kDecal); +static const DlBlendColorFilter kTestBlendColorFilter1(DlColor::kRed(), + DlBlendMode::kDstATop); +static const DlBlendColorFilter kTestBlendColorFilter2(DlColor::kBlue(), + DlBlendMode::kDstATop); +static const DlBlendColorFilter kTestBlendColorFilter3(DlColor::kRed(), + DlBlendMode::kDstIn); +static const DlMatrixColorFilter kTestMatrixColorFilter1(kRotateColorMatrix); +static const DlMatrixColorFilter kTestMatrixColorFilter2(kInvertColorMatrix); +static const DlBlurImageFilter kTestBlurImageFilter1(5.0, + 5.0, + DlTileMode::kClamp); +static const DlBlurImageFilter kTestBlurImageFilter2(6.0, + 5.0, + DlTileMode::kClamp); +static const DlBlurImageFilter kTestBlurImageFilter3(5.0, + 6.0, + DlTileMode::kClamp); +static const DlBlurImageFilter kTestBlurImageFilter4(5.0, + 5.0, + DlTileMode::kDecal); +static const DlDilateImageFilter kTestDilateImageFilter1(5.0, 5.0); +static const DlDilateImageFilter kTestDilateImageFilter2(6.0, 5.0); +static const DlDilateImageFilter kTestDilateImageFilter3(5.0, 6.0); +static const DlErodeImageFilter kTestErodeImageFilter1(5.0, 5.0); +static const DlErodeImageFilter kTestErodeImageFilter2(6.0, 5.0); +static const DlErodeImageFilter kTestErodeImageFilter3(5.0, 6.0); +static const DlMatrixImageFilter kTestMatrixImageFilter1( + SkMatrix::RotateDeg(45), + kNearestSampling); +static const DlMatrixImageFilter kTestMatrixImageFilter2( + SkMatrix::RotateDeg(85), + kNearestSampling); +static const DlMatrixImageFilter kTestMatrixImageFilter3( + SkMatrix::RotateDeg(45), + kLinearSampling); +static const DlComposeImageFilter kTestComposeImageFilter1( + kTestBlurImageFilter1, + kTestMatrixImageFilter1); +static const DlComposeImageFilter kTestComposeImageFilter2( + kTestBlurImageFilter2, + kTestMatrixImageFilter1); +static const DlComposeImageFilter kTestComposeImageFilter3( + kTestBlurImageFilter1, + kTestMatrixImageFilter2); +static const DlColorFilterImageFilter kTestCFImageFilter1( + kTestBlendColorFilter1); +static const DlColorFilterImageFilter kTestCFImageFilter2( + kTestBlendColorFilter2); +static const std::shared_ptr kTestPathEffect1 = + DlDashPathEffect::Make(kTestDashes1, 2, 0.0f); +static const std::shared_ptr kTestPathEffect2 = + DlDashPathEffect::Make(kTestDashes2, 2, 0.0f); +static const DlBlurMaskFilter kTestMaskFilter1(kNormal_SkBlurStyle, 3.0); +static const DlBlurMaskFilter kTestMaskFilter2(kNormal_SkBlurStyle, 5.0); +static const DlBlurMaskFilter kTestMaskFilter3(kSolid_SkBlurStyle, 3.0); +static const DlBlurMaskFilter kTestMaskFilter4(kInner_SkBlurStyle, 3.0); +static const DlBlurMaskFilter kTestMaskFilter5(kOuter_SkBlurStyle, 3.0); +constexpr SkRect kTestBounds = SkRect::MakeLTRB(10, 10, 50, 60); +static const SkRRect kTestRRect = SkRRect::MakeRectXY(kTestBounds, 5, 5); +static const SkRRect kTestRRectRect = SkRRect::MakeRect(kTestBounds); +static const SkRRect kTestInnerRRect = + SkRRect::MakeRectXY(kTestBounds.makeInset(5, 5), 2, 2); +static const SkPath kTestPathRect = SkPath::Rect(kTestBounds); +static const SkPath kTestPathOval = SkPath::Oval(kTestBounds); +static const SkPath kTestPath1 = + SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, true); +static const SkPath kTestPath2 = + SkPath::Polygon({{0, 0}, {10, 10}, {0, 10}, {10, 0}}, true); +static const SkPath kTestPath3 = + SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, false); +static const SkMatrix kTestMatrix1 = SkMatrix::Scale(2, 2); +static const SkMatrix kTestMatrix2 = SkMatrix::RotateDeg(45); + +static std::shared_ptr TestVertices1 = + DlVertices::Make(DlVertexMode::kTriangles, // + 3, + TestPoints, + nullptr, + kColors); +static std::shared_ptr TestVertices2 = + DlVertices::Make(DlVertexMode::kTriangleFan, // + 3, + TestPoints, + nullptr, + kColors); + +static constexpr int kTestDivs1[] = {10, 20, 30}; +static constexpr int kTestDivs2[] = {15, 20, 25}; +static constexpr int kTestDivs3[] = {15, 25}; +static constexpr SkCanvas::Lattice::RectType kTestRTypes[] = { + SkCanvas::Lattice::RectType::kDefault, + SkCanvas::Lattice::RectType::kTransparent, + SkCanvas::Lattice::RectType::kFixedColor, + SkCanvas::Lattice::RectType::kDefault, + SkCanvas::Lattice::RectType::kTransparent, + SkCanvas::Lattice::RectType::kFixedColor, + SkCanvas::Lattice::RectType::kDefault, + SkCanvas::Lattice::RectType::kTransparent, + SkCanvas::Lattice::RectType::kFixedColor, +}; +static constexpr SkColor kTestLatticeColors[] = { + SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, + SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, + SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, +}; +static constexpr SkIRect kTestLatticeSrcRect = {1, 1, 39, 39}; + +static sk_sp MakeTestPicture(int w, int h, SkColor color) { + SkPictureRecorder recorder; + SkRTreeFactory rtree_factory; + SkCanvas* cv = recorder.beginRecording(kTestBounds, &rtree_factory); + SkPaint paint; + paint.setColor(color); + paint.setStyle(SkPaint::kFill_Style); + cv->drawRect(SkRect::MakeWH(w, h), paint); + return recorder.finishRecordingAsPicture(); +} +static sk_sp TestPicture1 = MakeTestPicture(20, 20, SK_ColorGREEN); +static sk_sp TestPicture2 = MakeTestPicture(25, 25, SK_ColorBLUE); + +static sk_sp MakeTestDisplayList(int w, int h, SkColor color) { + DisplayListBuilder builder; + builder.setColor(color); + builder.drawRect(SkRect::MakeWH(w, h)); + return builder.Build(); +} +static sk_sp TestDisplayList1 = + MakeTestDisplayList(20, 20, SK_ColorGREEN); +static sk_sp TestDisplayList2 = + MakeTestDisplayList(25, 25, SK_ColorBLUE); + +static sk_sp MakeTextBlob(std::string string) { + return SkTextBlob::MakeFromText(string.c_str(), string.size(), SkFont(), + SkTextEncoding::kUTF8); +} +static sk_sp TestBlob1 = MakeTextBlob("TestBlob1"); +static sk_sp TestBlob2 = MakeTextBlob("TestBlob2"); + +struct DisplayListInvocation { + unsigned int op_count_; + size_t byte_count_; + + // in some cases, running the sequence through an SkCanvas will result + // in fewer ops/bytes. Attribute invocations are recorded in an SkPaint + // and not forwarded on, and SkCanvas culls unused save/restore/transforms. + int sk_op_count_; + size_t sk_byte_count_; + + DlInvoker invoker; + bool supports_group_opacity_ = false; + + bool sk_version_matches() { + return (static_cast(op_count_) == sk_op_count_ && + byte_count_ == sk_byte_count_); + } + + // A negative sk_op_count means "do not test this op". + // Used mainly for these cases: + // - we cannot encode a DrawShadowRec (Skia private header) + // - SkCanvas cannot receive a DisplayList + // - SkCanvas may or may not inline an SkPicture + bool sk_testing_invalid() { return sk_op_count_ < 0; } + + bool is_empty() { return byte_count_ == 0; } + + bool supports_group_opacity() { return supports_group_opacity_; } + + unsigned int op_count() { return op_count_; } + // byte count for the individual ops, no DisplayList overhead + size_t raw_byte_count() { return byte_count_; } + // byte count for the ops with DisplayList overhead, comparable + // to |DisplayList.byte_count(). + size_t byte_count() { return sizeof(DisplayList) + byte_count_; } + + int sk_op_count() { return sk_op_count_; } + // byte count for the ops with DisplayList overhead as translated + // through an SkCanvas interface, comparable to |DisplayList.byte_count(). + size_t sk_byte_count() { return sizeof(DisplayList) + sk_byte_count_; } + + void Invoke(DisplayListBuilder& builder) { invoker(builder); } + + sk_sp Build() { + DisplayListBuilder builder; + invoker(builder); + return builder.Build(); + } +}; + +struct DisplayListInvocationGroup { + std::string op_name; + std::vector variants; +}; + +std::vector CreateAllRenderingOps(); +std::vector CreateAllGroups(); + } // namespace testing } // namespace flutter diff --git a/display_list/display_list_unittests.cc b/display_list/display_list_unittests.cc index 2a6b01d396b6a..a4711bcfd5c67 100644 --- a/display_list/display_list_unittests.cc +++ b/display_list/display_list_unittests.cc @@ -9,883 +9,17 @@ #include "flutter/display_list/display_list_builder.h" #include "flutter/display_list/display_list_canvas_recorder.h" #include "flutter/display_list/display_list_rtree.h" +#include "flutter/display_list/display_list_test_utils.h" #include "flutter/display_list/display_list_utils.h" #include "flutter/fml/math.h" #include "flutter/testing/display_list_testing.h" #include "flutter/testing/testing.h" -#include "third_party/skia/include/core/SkPictureRecorder.h" -#include "third_party/skia/include/core/SkSurface.h" -#include "third_party/skia/include/effects/SkBlenders.h" -#include "third_party/skia/include/effects/SkDashPathEffect.h" -#include "third_party/skia/include/effects/SkGradientShader.h" -#include "third_party/skia/include/effects/SkImageFilters.h" namespace flutter { namespace testing { -constexpr SkPoint kEndPoints[] = { - {0, 0}, - {100, 100}, -}; -const DlColor kColors[] = { - DlColor::kGreen(), - DlColor::kYellow(), - DlColor::kBlue(), -}; -constexpr float kStops[] = { - 0.0, - 0.5, - 1.0, -}; -std::vector color_vector(kColors, kColors + 3); -std::vector stops_vector(kStops, kStops + 3); - -// clang-format off -constexpr float kRotateColorMatrix[20] = { - 0, 1, 0, 0, 0, - 0, 0, 1, 0, 0, - 1, 0, 0, 0, 0, - 0, 0, 0, 1, 0, -}; -constexpr float kInvertColorMatrix[20] = { - -1.0, 0, 0, 1.0, 0, - 0, -1.0, 0, 1.0, 0, - 0, 0, -1.0, 1.0, 0, - 1.0, 1.0, 1.0, 1.0, 0, -}; -// clang-format on - -const SkScalar kTestDashes1[] = {4.0, 2.0}; -const SkScalar kTestDashes2[] = {1.0, 1.5}; - -constexpr SkPoint TestPoints[] = { - {10, 10}, - {20, 20}, - {10, 20}, - {20, 10}, -}; -#define TestPointCount sizeof(TestPoints) / (sizeof(TestPoints[0])) - -static DlImageSampling kNearestSampling = DlImageSampling::kNearestNeighbor; -static DlImageSampling kLinearSampling = DlImageSampling::kLinear; - -static sk_sp MakeTestImage(int w, int h, int checker_size) { - sk_sp surface = SkSurface::MakeRasterN32Premul(w, h); - SkCanvas* canvas = surface->getCanvas(); - SkPaint p0, p1; - p0.setStyle(SkPaint::kFill_Style); - p0.setColor(SK_ColorGREEN); - p1.setStyle(SkPaint::kFill_Style); - p1.setColor(SK_ColorBLUE); - p1.setAlpha(128); - for (int y = 0; y < w; y += checker_size) { - for (int x = 0; x < h; x += checker_size) { - SkPaint& cellp = ((x + y) & 1) == 0 ? p0 : p1; - canvas->drawRect(SkRect::MakeXYWH(x, y, checker_size, checker_size), - cellp); - } - } - return DlImage::Make(surface->makeImageSnapshot()); -} - -static auto TestImage1 = MakeTestImage(40, 40, 5); -static auto TestImage2 = MakeTestImage(50, 50, 5); - -static const sk_sp kTestBlender1 = - SkBlenders::Arithmetic(0.2, 0.2, 0.2, 0.2, false); -static const sk_sp kTestBlender2 = - SkBlenders::Arithmetic(0.2, 0.2, 0.2, 0.2, true); -static const sk_sp kTestBlender3 = - SkBlenders::Arithmetic(0.3, 0.3, 0.3, 0.3, true); -static const DlImageColorSource kTestSource1(TestImage1->skia_image(), - DlTileMode::kClamp, - DlTileMode::kMirror, - kLinearSampling); -static const std::shared_ptr kTestSource2 = - DlColorSource::MakeLinear(kEndPoints[0], - kEndPoints[1], - 3, - kColors, - kStops, - DlTileMode::kMirror); -static const std::shared_ptr kTestSource3 = - DlColorSource::MakeRadial(kEndPoints[0], - 10.0, - 3, - kColors, - kStops, - DlTileMode::kMirror); -static const std::shared_ptr kTestSource4 = - DlColorSource::MakeConical(kEndPoints[0], - 10.0, - kEndPoints[1], - 200.0, - 3, - kColors, - kStops, - DlTileMode::kDecal); -static const std::shared_ptr kTestSource5 = - DlColorSource::MakeSweep(kEndPoints[0], - 0.0, - 360.0, - 3, - kColors, - kStops, - DlTileMode::kDecal); -static const DlBlendColorFilter kTestBlendColorFilter1(DlColor::kRed(), - DlBlendMode::kDstATop); -static const DlBlendColorFilter kTestBlendColorFilter2(DlColor::kBlue(), - DlBlendMode::kDstATop); -static const DlBlendColorFilter kTestBlendColorFilter3(DlColor::kRed(), - DlBlendMode::kDstIn); -static const DlMatrixColorFilter kTestMatrixColorFilter1(kRotateColorMatrix); -static const DlMatrixColorFilter kTestMatrixColorFilter2(kInvertColorMatrix); -static const DlBlurImageFilter kTestBlurImageFilter1(5.0, - 5.0, - DlTileMode::kClamp); -static const DlBlurImageFilter kTestBlurImageFilter2(6.0, - 5.0, - DlTileMode::kClamp); -static const DlBlurImageFilter kTestBlurImageFilter3(5.0, - 6.0, - DlTileMode::kClamp); -static const DlBlurImageFilter kTestBlurImageFilter4(5.0, - 5.0, - DlTileMode::kDecal); -static const DlDilateImageFilter kTestDilateImageFilter1(5.0, 5.0); -static const DlDilateImageFilter kTestDilateImageFilter2(6.0, 5.0); -static const DlDilateImageFilter kTestDilateImageFilter3(5.0, 6.0); -static const DlErodeImageFilter kTestErodeImageFilter1(5.0, 5.0); -static const DlErodeImageFilter kTestErodeImageFilter2(6.0, 5.0); -static const DlErodeImageFilter kTestErodeImageFilter3(5.0, 6.0); -static const DlMatrixImageFilter kTestMatrixImageFilter1( - SkMatrix::RotateDeg(45), - kNearestSampling); -static const DlMatrixImageFilter kTestMatrixImageFilter2( - SkMatrix::RotateDeg(85), - kNearestSampling); -static const DlMatrixImageFilter kTestMatrixImageFilter3( - SkMatrix::RotateDeg(45), - kLinearSampling); -static const DlComposeImageFilter kTestComposeImageFilter1( - kTestBlurImageFilter1, - kTestMatrixImageFilter1); -static const DlComposeImageFilter kTestComposeImageFilter2( - kTestBlurImageFilter2, - kTestMatrixImageFilter1); -static const DlComposeImageFilter kTestComposeImageFilter3( - kTestBlurImageFilter1, - kTestMatrixImageFilter2); -static const DlColorFilterImageFilter kTestCFImageFilter1( - kTestBlendColorFilter1); -static const DlColorFilterImageFilter kTestCFImageFilter2( - kTestBlendColorFilter2); -static const std::shared_ptr kTestPathEffect1 = - DlDashPathEffect::Make(kTestDashes1, 2, 0.0f); -static const std::shared_ptr kTestPathEffect2 = - DlDashPathEffect::Make(kTestDashes2, 2, 0.0f); -static const DlBlurMaskFilter kTestMaskFilter1(kNormal_SkBlurStyle, 3.0); -static const DlBlurMaskFilter kTestMaskFilter2(kNormal_SkBlurStyle, 5.0); -static const DlBlurMaskFilter kTestMaskFilter3(kSolid_SkBlurStyle, 3.0); -static const DlBlurMaskFilter kTestMaskFilter4(kInner_SkBlurStyle, 3.0); -static const DlBlurMaskFilter kTestMaskFilter5(kOuter_SkBlurStyle, 3.0); -constexpr SkRect kTestBounds = SkRect::MakeLTRB(10, 10, 50, 60); -static const SkRRect kTestRRect = SkRRect::MakeRectXY(kTestBounds, 5, 5); -static const SkRRect kTestRRectRect = SkRRect::MakeRect(kTestBounds); -static const SkRRect kTestInnerRRect = - SkRRect::MakeRectXY(kTestBounds.makeInset(5, 5), 2, 2); -static const SkPath kTestPathRect = SkPath::Rect(kTestBounds); -static const SkPath kTestPathOval = SkPath::Oval(kTestBounds); -static const SkPath kTestPath1 = - SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, true); -static const SkPath kTestPath2 = - SkPath::Polygon({{0, 0}, {10, 10}, {0, 10}, {10, 0}}, true); -static const SkPath kTestPath3 = - SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, false); -static const SkMatrix kTestMatrix1 = SkMatrix::Scale(2, 2); -static const SkMatrix kTestMatrix2 = SkMatrix::RotateDeg(45); - -static std::shared_ptr TestVertices1 = - DlVertices::Make(DlVertexMode::kTriangles, // - 3, - TestPoints, - nullptr, - kColors); -static std::shared_ptr TestVertices2 = - DlVertices::Make(DlVertexMode::kTriangleFan, // - 3, - TestPoints, - nullptr, - kColors); - -static constexpr int kTestDivs1[] = {10, 20, 30}; -static constexpr int kTestDivs2[] = {15, 20, 25}; -static constexpr int kTestDivs3[] = {15, 25}; -static constexpr SkCanvas::Lattice::RectType kTestRTypes[] = { - SkCanvas::Lattice::RectType::kDefault, - SkCanvas::Lattice::RectType::kTransparent, - SkCanvas::Lattice::RectType::kFixedColor, - SkCanvas::Lattice::RectType::kDefault, - SkCanvas::Lattice::RectType::kTransparent, - SkCanvas::Lattice::RectType::kFixedColor, - SkCanvas::Lattice::RectType::kDefault, - SkCanvas::Lattice::RectType::kTransparent, - SkCanvas::Lattice::RectType::kFixedColor, -}; -static constexpr SkColor kTestLatticeColors[] = { - SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, - SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, - SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW, -}; -static constexpr SkIRect kTestLatticeSrcRect = {1, 1, 39, 39}; - -static sk_sp MakeTestPicture(int w, int h, SkColor color) { - SkPictureRecorder recorder; - SkRTreeFactory rtree_factory; - SkCanvas* cv = recorder.beginRecording(kTestBounds, &rtree_factory); - SkPaint paint; - paint.setColor(color); - paint.setStyle(SkPaint::kFill_Style); - cv->drawRect(SkRect::MakeWH(w, h), paint); - return recorder.finishRecordingAsPicture(); -} -static sk_sp TestPicture1 = MakeTestPicture(20, 20, SK_ColorGREEN); -static sk_sp TestPicture2 = MakeTestPicture(25, 25, SK_ColorBLUE); - -static sk_sp MakeTestDisplayList(int w, int h, SkColor color) { - DisplayListBuilder builder; - builder.setColor(color); - builder.drawRect(SkRect::MakeWH(w, h)); - return builder.Build(); -} -static sk_sp TestDisplayList1 = - MakeTestDisplayList(20, 20, SK_ColorGREEN); -static sk_sp TestDisplayList2 = - MakeTestDisplayList(25, 25, SK_ColorBLUE); - -static sk_sp MakeTextBlob(std::string string) { - return SkTextBlob::MakeFromText(string.c_str(), string.size(), SkFont(), - SkTextEncoding::kUTF8); -} -static sk_sp TestBlob1 = MakeTextBlob("TestBlob1"); -static sk_sp TestBlob2 = MakeTextBlob("TestBlob2"); - -// --------------- -// Test Suite data -// --------------- - -typedef const std::function DlInvoker; - -struct DisplayListInvocation { - unsigned int op_count_; - size_t byte_count_; - - // in some cases, running the sequence through an SkCanvas will result - // in fewer ops/bytes. Attribute invocations are recorded in an SkPaint - // and not forwarded on, and SkCanvas culls unused save/restore/transforms. - int sk_op_count_; - size_t sk_byte_count_; - - DlInvoker invoker; - bool supports_group_opacity_ = false; - - bool sk_version_matches() { - return (static_cast(op_count_) == sk_op_count_ && - byte_count_ == sk_byte_count_); - } - - // A negative sk_op_count means "do not test this op". - // Used mainly for these cases: - // - we cannot encode a DrawShadowRec (Skia private header) - // - SkCanvas cannot receive a DisplayList - // - SkCanvas may or may not inline an SkPicture - bool sk_testing_invalid() { return sk_op_count_ < 0; } - - bool is_empty() { return byte_count_ == 0; } - - bool supports_group_opacity() { return supports_group_opacity_; } - - unsigned int op_count() { return op_count_; } - // byte count for the individual ops, no DisplayList overhead - size_t raw_byte_count() { return byte_count_; } - // byte count for the ops with DisplayList overhead, comparable - // to |DisplayList.byte_count(). - size_t byte_count() { return sizeof(DisplayList) + byte_count_; } - - int sk_op_count() { return sk_op_count_; } - // byte count for the ops with DisplayList overhead as translated - // through an SkCanvas interface, comparable to |DisplayList.byte_count(). - size_t sk_byte_count() { return sizeof(DisplayList) + sk_byte_count_; } - - sk_sp Build() { - DisplayListBuilder builder; - invoker(builder); - return builder.Build(); - } -}; - -struct DisplayListInvocationGroup { - std::string op_name; - std::vector variants; -}; - -std::vector allGroups = { - { "SetAntiAlias", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setAntiAlias(true);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setAntiAlias(false);}}, - } - }, - { "SetDither", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setDither(true);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setDither(false);}}, - } - }, - { "SetInvertColors", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setInvertColors(true);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setInvertColors(false);}}, - } - }, - { "SetStrokeCap", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeCap(DlStrokeCap::kRound);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeCap(DlStrokeCap::kSquare);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setStrokeCap(DlStrokeCap::kButt);}}, - } - }, - { "SetStrokeJoin", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeJoin(DlStrokeJoin::kBevel);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeJoin(DlStrokeJoin::kRound);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setStrokeJoin(DlStrokeJoin::kMiter);}}, - } - }, - { "SetStyle", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStyle(DlDrawStyle::kStroke);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStyle(DlDrawStyle::kStrokeAndFill);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setStyle(DlDrawStyle::kFill);}}, - } - }, - { "SetStrokeWidth", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeWidth(1.0);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeWidth(5.0);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setStrokeWidth(0.0);}}, - } - }, - { "SetStrokeMiter", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeMiter(0.0);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setStrokeMiter(5.0);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setStrokeMiter(4.0);}}, - } - }, - { "SetColor", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setColor(SK_ColorGREEN);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setColor(SK_ColorBLUE);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setColor(SK_ColorBLACK);}}, - } - }, - { "SetBlendModeOrBlender", { - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kSrcIn);}}, - {0, 8, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kDstIn);}}, - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(kTestBlender1);}}, - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(kTestBlender2);}}, - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setBlender(kTestBlender3);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlendMode(DlBlendMode::kSrcOver);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setBlender(nullptr);}}, - } - }, - { "SetColorSource", { - {0, 96, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(&kTestSource1);}}, - // stop_count * (sizeof(float) + sizeof(uint32_t)) = 80 - {0, 80 + 6 * 4, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(kTestSource2.get());}}, - {0, 80 + 6 * 4, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(kTestSource3.get());}}, - {0, 88 + 6 * 4, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(kTestSource4.get());}}, - {0, 80 + 6 * 4, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(kTestSource5.get());}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setColorSource(nullptr);}}, - } - }, - { "SetImageFilter", { - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestBlurImageFilter1);}}, - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestBlurImageFilter2);}}, - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestBlurImageFilter3);}}, - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestBlurImageFilter4);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestDilateImageFilter1);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestDilateImageFilter2);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestDilateImageFilter3);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestErodeImageFilter1);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestErodeImageFilter2);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestErodeImageFilter3);}}, - {0, 64, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestMatrixImageFilter1);}}, - {0, 64, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestMatrixImageFilter2);}}, - {0, 64, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestMatrixImageFilter3);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestComposeImageFilter1);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestComposeImageFilter2);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestComposeImageFilter3);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestCFImageFilter1);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(&kTestCFImageFilter2);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setImageFilter(nullptr);}}, - } - }, - { "SetColorFilter", { - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(&kTestBlendColorFilter1);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(&kTestBlendColorFilter2);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(&kTestBlendColorFilter3);}}, - {0, 96, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(&kTestMatrixColorFilter1);}}, - {0, 96, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(&kTestMatrixColorFilter2);}}, - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(DlSrgbToLinearGammaColorFilter::instance.get());}}, - {0, 16, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(DlLinearToSrgbGammaColorFilter::instance.get());}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setColorFilter(nullptr);}}, - } - }, - { "SetPathEffect", { - // sizeof(DlDashPathEffect) + 2 * sizeof(SkScalar) - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(kTestPathEffect1.get());}}, - {0, 32, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(kTestPathEffect2.get());}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setPathEffect(nullptr);}}, - } - }, - { "SetMaskFilter", { - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(&kTestMaskFilter1);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(&kTestMaskFilter2);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(&kTestMaskFilter3);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(&kTestMaskFilter4);}}, - {0, 24, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(&kTestMaskFilter5);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.setMaskFilter(nullptr);}}, - } - }, - { "Save(Layer)+Restore", { - {5, 104, 5, 104, [](DisplayListBuilder& b) { - b.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - // There are many reasons that save and restore can elide content, including - // whether or not there are any draw operations between them, whether or not - // there are any state changes to restore, and whether group rendering (opacity) - // optimizations can allow attributes to be distributed to the children. - // To prevent those cases we include at least one clip operation and 2 overlapping - // rendering primitives between each save/restore pair. - {5, 88, 5, 88, [](DisplayListBuilder& b) { - b.save(); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - {5, 88, 5, 88, [](DisplayListBuilder& b) { - b.saveLayer(nullptr, false); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - {5, 88, 5, 88, [](DisplayListBuilder& b) { - b.saveLayer(nullptr, true); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - {5, 104, 5, 104, [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, false); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - {5, 104, 5, 104, [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, true); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - // backdrop variants - using the TestCFImageFilter because it can be - // reconstituted in the DL->SkCanvas->DL stream - // {5, 104, 5, 104, [](DisplayListBuilder& b) { - // b.saveLayer(nullptr, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); - // b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - // b.drawRect({5, 5, 15, 15}); - // b.drawRect({10, 10, 20, 20}); - // b.restore(); - // }}, - {5, 104, 5, 104, [](DisplayListBuilder& b) { - b.saveLayer(nullptr, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - {5, 120, 5, 120, [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, SaveLayerOptions::kNoAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - {5, 120, 5, 120, [](DisplayListBuilder& b) { - b.saveLayer(&kTestBounds, SaveLayerOptions::kWithAttributes, &kTestCFImageFilter1); - b.clipRect({0, 0, 25, 25}, SkClipOp::kIntersect, true); - b.drawRect({5, 5, 15, 15}); - b.drawRect({10, 10, 20, 20}); - b.restore(); - }}, - } - }, - { "Translate", { - // cv.translate(0, 0) is ignored - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.translate(10, 10);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.translate(10, 15);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.translate(15, 10);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.translate(0, 0);}}, - } - }, - { "Scale", { - // cv.scale(1, 1) is ignored - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.scale(2, 2);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.scale(2, 3);}}, - {1, 16, 1, 16, [](DisplayListBuilder& b) {b.scale(3, 2);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.scale(1, 1);}}, - } - }, - { "Rotate", { - // cv.rotate(0) is ignored, otherwise expressed as concat(rotmatrix) - {1, 8, 1, 32, [](DisplayListBuilder& b) {b.rotate(30);}}, - {1, 8, 1, 32, [](DisplayListBuilder& b) {b.rotate(45);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.rotate(0);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.rotate(360);}}, - } - }, - { "Skew", { - // cv.skew(0, 0) is ignored, otherwise expressed as concat(skewmatrix) - {1, 16, 1, 32, [](DisplayListBuilder& b) {b.skew(0.1, 0.1);}}, - {1, 16, 1, 32, [](DisplayListBuilder& b) {b.skew(0.1, 0.2);}}, - {1, 16, 1, 32, [](DisplayListBuilder& b) {b.skew(0.2, 0.1);}}, - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.skew(0, 0);}}, - } - }, - { "Transform2DAffine", { - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.transform2DAffine(0, 1, 12, 1, 0, 33);}}, - // b.transform(identity) is ignored - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.transform2DAffine(1, 0, 0, 0, 1, 0);}}, - } - }, - { "TransformFullPerspective", { - {1, 72, 1, 72, [](DisplayListBuilder& b) {b.transformFullPerspective(0, 1, 0, 12, - 1, 0, 0, 33, - 3, 2, 5, 29, - 0, 0, 0, 12);}}, - // b.transform(2D affine) is reduced to 2x3 - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.transformFullPerspective(2, 1, 0, 4, - 1, 3, 0, 5, - 0, 0, 1, 0, - 0, 0, 0, 1);}}, - // b.transform(identity) is ignored - {0, 0, 0, 0, [](DisplayListBuilder& b) {b.transformFullPerspective(1, 0, 0, 0, - 0, 1, 0, 0, - 0, 0, 1, 0, - 0, 0, 0, 1);}}, - } - }, - { "ClipRect", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(kTestBounds, SkClipOp::kIntersect, true);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(kTestBounds.makeOffset(1, 1), - SkClipOp::kIntersect, true);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(kTestBounds, SkClipOp::kIntersect, false);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(kTestBounds, SkClipOp::kDifference, true);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipRect(kTestBounds, SkClipOp::kDifference, false);}}, - } - }, - { "ClipRRect", { - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(kTestRRect, SkClipOp::kIntersect, true);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(kTestRRect.makeOffset(1, 1), - SkClipOp::kIntersect, true);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(kTestRRect, SkClipOp::kIntersect, false);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(kTestRRect, SkClipOp::kDifference, true);}}, - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipRRect(kTestRRect, SkClipOp::kDifference, false);}}, - } - }, - { "ClipPath", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(kTestPath1, SkClipOp::kIntersect, true);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(kTestPath2, SkClipOp::kIntersect, true);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(kTestPath3, SkClipOp::kIntersect, true);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(kTestPath1, SkClipOp::kIntersect, false);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(kTestPath1, SkClipOp::kDifference, true);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(kTestPath1, SkClipOp::kDifference, false);}}, - // clipPath(rect) becomes clipRect - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.clipPath(kTestPathRect, SkClipOp::kIntersect, true);}}, - // clipPath(oval) becomes clipRRect - {1, 64, 1, 64, [](DisplayListBuilder& b) {b.clipPath(kTestPathOval, SkClipOp::kIntersect, true);}}, - } - }, - { "DrawPaint", { - {1, 8, 1, 8, [](DisplayListBuilder& b) {b.drawPaint();}}, - } - }, - { "DrawColor", { - // cv.drawColor becomes cv.drawPaint(paint) - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, DlBlendMode::kSrcIn);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorBLUE, DlBlendMode::kDstIn);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawColor(SK_ColorCYAN, DlBlendMode::kSrcIn);}}, - } - }, - { "DrawLine", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 0}, {10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 1}, {10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 0}, {20, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawLine({0, 0}, {10, 20});}}, - } - }, - { "DrawRect", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 0, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 1, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 0, 20, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawRect({0, 0, 10, 20});}}, - } - }, - { "DrawOval", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 0, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 1, 10, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 0, 20, 10});}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawOval({0, 0, 10, 20});}}, - } - }, - { "DrawCircle", { - // cv.drawCircle becomes cv.drawOval - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawCircle({0, 0}, 10);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawCircle({0, 5}, 10);}}, - {1, 16, 1, 24, [](DisplayListBuilder& b) {b.drawCircle({0, 0}, 20);}}, - } - }, - { "DrawRRect", { - {1, 56, 1, 56, [](DisplayListBuilder& b) {b.drawRRect(kTestRRect);}}, - {1, 56, 1, 56, [](DisplayListBuilder& b) {b.drawRRect(kTestRRect.makeOffset(5, 5));}}, - } - }, - { "DrawDRRect", { - {1, 112, 1, 112, [](DisplayListBuilder& b) {b.drawDRRect(kTestRRect, kTestInnerRRect);}}, - {1, 112, 1, 112, [](DisplayListBuilder& b) {b.drawDRRect(kTestRRect.makeOffset(5, 5), - kTestInnerRRect.makeOffset(4, 4));}}, - } - }, - { "DrawPath", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(kTestPath1);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(kTestPath2);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(kTestPath3);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(kTestPathRect);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawPath(kTestPathOval);}}, - } - }, - { "DrawArc", { - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(kTestBounds, 45, 270, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(kTestBounds.makeOffset(1, 1), - 45, 270, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(kTestBounds, 30, 270, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(kTestBounds, 45, 260, false);}}, - {1, 32, 1, 32, [](DisplayListBuilder& b) {b.drawArc(kTestBounds, 45, 270, true);}}, - } - }, - { "DrawPoints", { - {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kPoints_PointMode, - TestPointCount, - TestPoints);}}, - {1, 8 + (TestPointCount - 1) * 8, 1, 8 + (TestPointCount - 1) * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kPoints_PointMode, - TestPointCount - 1, - TestPoints);}}, - {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kLines_PointMode, - TestPointCount, - TestPoints);}}, - {1, 8 + TestPointCount * 8, 1, 8 + TestPointCount * 8, - [](DisplayListBuilder& b) {b.drawPoints(SkCanvas::kPolygon_PointMode, - TestPointCount, - TestPoints);}}, - } - }, - { "DrawVertices", { - {1, 112, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, DlBlendMode::kSrcIn);}}, - {1, 112, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices1, DlBlendMode::kDstIn);}}, - {1, 112, 1, 16, [](DisplayListBuilder& b) {b.drawVertices(TestVertices2, DlBlendMode::kSrcIn);}}, - } - }, - { "DrawImage", { - {1, 24, -1, 48, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {10, 10}, kNearestSampling, false);}}, - {1, 24, -1, 48, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {10, 10}, kNearestSampling, true);}}, - {1, 24, -1, 48, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {20, 10}, kNearestSampling, false);}}, - {1, 24, -1, 48, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {10, 20}, kNearestSampling, false);}}, - {1, 24, -1, 48, [](DisplayListBuilder& b) {b.drawImage(TestImage1, {10, 10}, kLinearSampling, false);}}, - {1, 24, -1, 48, [](DisplayListBuilder& b) {b.drawImage(TestImage2, {10, 10}, kNearestSampling, false);}}, - } - }, - { "DrawImageRect", { - {1, 56, -1, 80, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kNearestSampling, false);}}, - {1, 56, -1, 80, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kNearestSampling, true);}}, - {1, 56, -1, 80, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kNearestSampling, false, - SkCanvas::SrcRectConstraint::kStrict_SrcRectConstraint);}}, - {1, 56, -1, 80, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, - kNearestSampling, false);}}, - {1, 56, -1, 80, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, - kNearestSampling, false);}}, - {1, 56, -1, 80, [](DisplayListBuilder& b) {b.drawImageRect(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - kLinearSampling, false);}}, - {1, 56, -1, 80, [](DisplayListBuilder& b) {b.drawImageRect(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, - kNearestSampling, false);}}, - } - }, - { "DrawImageNine", { - // SkVanvas::drawImageNine is immediately converted to drawImageLattice - {1, 48, -1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - DlFilterMode::kNearest, false);}}, - {1, 48, -1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - DlFilterMode::kNearest, true);}}, - {1, 48, -1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 25, 20}, {10, 10, 80, 80}, - DlFilterMode::kNearest, false);}}, - {1, 48, -1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 85, 80}, - DlFilterMode::kNearest, false);}}, - {1, 48, -1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage1, {10, 10, 20, 20}, {10, 10, 80, 80}, - DlFilterMode::kLinear, false);}}, - {1, 48, -1, 80, [](DisplayListBuilder& b) {b.drawImageNine(TestImage2, {10, 10, 15, 15}, {10, 10, 80, 80}, - DlFilterMode::kNearest, false);}}, - } - }, - { "DrawImageLattice", { - // Lattice: - // const int* fXDivs; //!< x-axis values dividing bitmap - // const int* fYDivs; //!< y-axis values dividing bitmap - // const RectType* fRectTypes; //!< array of fill types - // int fXCount; //!< number of x-coordinates - // int fYCount; //!< number of y-coordinates - // const SkIRect* fBounds; //!< source bounds to draw from - // const SkColor* fColors; //!< array of colors - // size = 64 + fXCount * 4 + fYCount * 4 - // if fColors and fRectTypes are not null, add (fXCount + 1) * (fYCount + 1) * 5 - {1, 88, -1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, DlFilterMode::kNearest, false);}}, - {1, 88, -1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 45}, DlFilterMode::kNearest, false);}}, - {1, 88, -1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {kTestDivs2, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, DlFilterMode::kNearest, false);}}, - // One less yDiv does not change the allocation due to 8-byte alignment - {1, 88, -1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {kTestDivs1, kTestDivs1, nullptr, 3, 2, nullptr, nullptr}, - {10, 10, 40, 40}, DlFilterMode::kNearest, false);}}, - {1, 88, -1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, DlFilterMode::kLinear, false);}}, - {1, 96, -1, 96, [](DisplayListBuilder& b) {b.setColor(SK_ColorMAGENTA); - b.drawImageLattice(TestImage1, - {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, DlFilterMode::kNearest, true);}}, - {1, 88, -1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage2, - {kTestDivs1, kTestDivs1, nullptr, 3, 3, nullptr, nullptr}, - {10, 10, 40, 40}, DlFilterMode::kNearest, false);}}, - // Supplying fBounds does not change size because the Op record always includes it - {1, 88, -1, 88, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {kTestDivs1, kTestDivs1, nullptr, 3, 3, &kTestLatticeSrcRect, nullptr}, - {10, 10, 40, 40}, DlFilterMode::kNearest, false);}}, - {1, 128, -1, 128, [](DisplayListBuilder& b) {b.drawImageLattice(TestImage1, - {kTestDivs3, kTestDivs3, kTestRTypes, 2, 2, nullptr, kTestLatticeColors}, - {10, 10, 40, 40}, DlFilterMode::kNearest, false);}}, - } - }, - { "DrawAtlas", { - {1, 48 + 32 + 8, -1, 48 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, - kNearestSampling, nullptr, false);}}, - {1, 48 + 32 + 8, -1, 48 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, - kNearestSampling, nullptr, true);}}, - {1, 48 + 32 + 8, -1, 48 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {0, 1, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, - kNearestSampling, nullptr, false);}}, - {1, 48 + 32 + 8, -1, 48 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 25, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, - kNearestSampling, nullptr, false);}}, - {1, 48 + 32 + 8, -1, 48 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, - kLinearSampling, nullptr, false);}}, - {1, 48 + 32 + 8, -1, 48 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - b.drawAtlas(TestImage1, xforms, texs, nullptr, 2, DlBlendMode::kDstIn, - kNearestSampling, nullptr, false);}}, - {1, 64 + 32 + 8, -1, 64 + 32 + 32, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - static SkRect cullRect = { 0, 0, 200, 200 }; - b.drawAtlas(TestImage2, xforms, texs, nullptr, 2, DlBlendMode::kSrcIn, - kNearestSampling, &cullRect, false);}}, - {1, 48 + 32 + 8 + 8, -1, 48 + 32 + 32 + 8, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - static DlColor colors[] = { DlColor::kBlue(), DlColor::kGreen() }; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn, - kNearestSampling, nullptr, false);}}, - {1, 64 + 32 + 8 + 8, -1, 64 + 32 + 32 + 8, [](DisplayListBuilder& b) { - static SkRSXform xforms[] = { {1, 0, 0, 0}, {0, 1, 0, 0} }; - static SkRect texs[] = { { 10, 10, 20, 20 }, {20, 20, 30, 30} }; - static DlColor colors[] = { DlColor::kBlue(), DlColor::kGreen() }; - static SkRect cullRect = { 0, 0, 200, 200 }; - b.drawAtlas(TestImage1, xforms, texs, colors, 2, DlBlendMode::kSrcIn, - kNearestSampling, &cullRect, false);}}, - } - }, - { "DrawPicture", { - // cv.drawPicture cannot be compared as SkCanvas may inline it - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, nullptr, false);}}, - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawPicture(TestPicture2, nullptr, false);}}, - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, nullptr, true);}}, - {1, 56, -1, 56, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, &kTestMatrix1, false);}}, - {1, 56, -1, 56, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, &kTestMatrix2, false);}}, - {1, 56, -1, 56, [](DisplayListBuilder& b) {b.drawPicture(TestPicture1, &kTestMatrix1, true);}}, - } - }, - { "DrawDisplayList", { - // cv.drawDL does not exist - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawDisplayList(TestDisplayList1);}}, - {1, 16, -1, 16, [](DisplayListBuilder& b) {b.drawDisplayList(TestDisplayList2);}}, - } - }, - { "DrawTextBlob", { - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob1, 10, 10);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob1, 20, 10);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob1, 10, 20);}}, - {1, 24, 1, 24, [](DisplayListBuilder& b) {b.drawTextBlob(TestBlob2, 10, 10);}}, - } - }, - // The -1 op counts below are to indicate to the framework not to test - // SkCanvas conversion of these ops as it converts the operation into a - // format that is not exposed publicly and so we cannot recapture the - // operation. - // See: https://bugs.chromium.org/p/skia/issues/detail?id=12125 - { "DrawShadow", { - // cv shadows are turned into an opaque ShadowRec which is not exposed - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 1.0);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(kTestPath2, SK_ColorGREEN, 1.0, false, 1.0);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(kTestPath1, SK_ColorBLUE, 1.0, false, 1.0);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(kTestPath1, SK_ColorGREEN, 2.0, false, 1.0);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, true, 1.0);}}, - {1, 32, -1, 32, [](DisplayListBuilder& b) {b.drawShadow(kTestPath1, SK_ColorGREEN, 1.0, false, 2.5);}}, - } - }, -}; +static std::vector allGroups = + CreateAllGroups(); TEST(DisplayList, SingleOpSizes) { for (auto& group : allGroups) { diff --git a/testing/benchmark/generate_metrics.sh b/testing/benchmark/generate_metrics.sh index cef9672b228bd..0ea0e590b29ed 100644 --- a/testing/benchmark/generate_metrics.sh +++ b/testing/benchmark/generate_metrics.sh @@ -13,4 +13,5 @@ set -ex ./fml_benchmarks --benchmark_format=json > fml_benchmarks.json ./shell_benchmarks --benchmark_format=json > shell_benchmarks.json ./ui_benchmarks --benchmark_format=json > ui_benchmarks.json +./display_list_builder_benchmarks --benchmark_format=json > display_list_builder_benchmarks.json diff --git a/testing/run_tests.py b/testing/run_tests.py index 5ccf6dc37972d..a954a991e859a 100755 --- a/testing/run_tests.py +++ b/testing/run_tests.py @@ -440,6 +440,10 @@ def RunEngineBenchmarks(build_dir, filter): RunEngineExecutable(build_dir, 'ui_benchmarks', filter, icu_flags) + RunEngineExecutable( + build_dir, 'display_list_builder_benchmarks', filter, icu_flags + ) + if IsLinux(): RunEngineExecutable(build_dir, 'txt_benchmarks', filter, icu_flags)