[DisplayList] benchmark DisplayList dispatch method (#54324)

We will be updating the DisplayList dispatching to support random access iteration through the records so we need a benchmark to set a baseline to track any impact on the default way to dispatch a DisplayList.
diff --git a/display_list/benchmarking/dl_builder_benchmarks.cc b/display_list/benchmarking/dl_builder_benchmarks.cc
index 2b17ce0..8f9f05e 100644
--- a/display_list/benchmarking/dl_builder_benchmarks.cc
+++ b/display_list/benchmarking/dl_builder_benchmarks.cc
@@ -4,6 +4,7 @@
 
 #include "flutter/benchmarking/benchmarking.h"
 #include "flutter/display_list/testing/dl_test_snippets.h"
+#include "flutter/display_list/utils/dl_receiver_utils.h"
 
 namespace flutter {
 
@@ -16,6 +17,9 @@
 static std::vector<testing::DisplayListInvocationGroup> allRenderingOps =
     testing::CreateAllRenderingOps();
 
+static std::vector<testing::DisplayListInvocationGroup> allOps =
+    testing::CreateAllGroups();
+
 enum class DisplayListBuilderBenchmarkType {
   kDefault,
   kBounds,
@@ -23,6 +27,12 @@
   kBoundsAndRtree,
 };
 
+enum class DisplayListDispatchBenchmarkType {
+  kDefaultNoRtree,
+  kDefaultWithRtree,
+  kCulledWithRtree,
+};
+
 static void InvokeAllRenderingOps(DisplayListBuilder& builder) {
   DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
   for (auto& group : allRenderingOps) {
@@ -33,6 +43,21 @@
   }
 }
 
+static void InvokeAllOps(DisplayListBuilder& builder) {
+  DlOpReceiver& receiver = DisplayListBuilderBenchmarkAccessor(builder);
+  for (auto& group : allOps) {
+    // Save/restore around each group so that the clip and transform
+    // test ops do not walk us out to infinity or prevent any future
+    // rendering ops.
+    receiver.save();
+    for (size_t i = 0; i < group.variants.size(); i++) {
+      auto& invocation = group.variants[i];
+      invocation.Invoke(receiver);
+    }
+    receiver.restore();
+  }
+}
+
 static void Complete(DisplayListBuilder& builder,
                      DisplayListBuilderBenchmarkType type) {
   auto display_list = builder.Build();
@@ -57,6 +82,10 @@
          type == DisplayListBuilderBenchmarkType::kBoundsAndRtree;
 }
 
+bool NeedPrepareRTree(DisplayListDispatchBenchmarkType type) {
+  return type != DisplayListDispatchBenchmarkType::kDefaultNoRtree;
+}
+
 }  // namespace
 
 static void BM_DisplayListBuilderDefault(benchmark::State& state,
@@ -171,6 +200,42 @@
   }
 }
 
+class DlOpReceiverIgnore : public IgnoreAttributeDispatchHelper,
+                           public IgnoreTransformDispatchHelper,
+                           public IgnoreClipDispatchHelper,
+                           public IgnoreDrawDispatchHelper {};
+
+static void BM_DisplayListDispatchDefault(
+    benchmark::State& state,
+    DisplayListDispatchBenchmarkType type) {
+  bool prepare_rtree = NeedPrepareRTree(type);
+  DisplayListBuilder builder(prepare_rtree);
+  for (int i = 0; i < 5; i++) {
+    InvokeAllOps(builder);
+  }
+  auto display_list = builder.Build();
+  DlOpReceiverIgnore receiver;
+  while (state.KeepRunning()) {
+    display_list->Dispatch(receiver);
+  }
+}
+
+static void BM_DisplayListDispatchCull(benchmark::State& state,
+                                       DisplayListDispatchBenchmarkType type) {
+  bool prepare_rtree = NeedPrepareRTree(type);
+  DisplayListBuilder builder(prepare_rtree);
+  for (int i = 0; i < 5; i++) {
+    InvokeAllOps(builder);
+  }
+  auto display_list = builder.Build();
+  SkRect rect = SkRect::MakeLTRB(0, 0, 100, 100);
+  EXPECT_FALSE(rect.contains(display_list->bounds()));
+  DlOpReceiverIgnore receiver;
+  while (state.KeepRunning()) {
+    display_list->Dispatch(receiver, rect);
+  }
+}
+
 BENCHMARK_CAPTURE(BM_DisplayListBuilderDefault,
                   kDefault,
                   DisplayListBuilderBenchmarkType::kDefault)
@@ -290,4 +355,19 @@
                   DisplayListBuilderBenchmarkType::kBoundsAndRtree)
     ->Unit(benchmark::kMicrosecond);
 
+BENCHMARK_CAPTURE(BM_DisplayListDispatchDefault,
+                  kDefaultNoRtree,
+                  DisplayListDispatchBenchmarkType::kDefaultNoRtree)
+    ->Unit(benchmark::kMicrosecond);
+
+BENCHMARK_CAPTURE(BM_DisplayListDispatchDefault,
+                  kDefaultWithRtree,
+                  DisplayListDispatchBenchmarkType::kDefaultWithRtree)
+    ->Unit(benchmark::kMicrosecond);
+
+BENCHMARK_CAPTURE(BM_DisplayListDispatchCull,
+                  kCulledWithRtree,
+                  DisplayListDispatchBenchmarkType::kCulledWithRtree)
+    ->Unit(benchmark::kMicrosecond);
+
 }  // namespace flutter
diff --git a/display_list/testing/dl_test_snippets.cc b/display_list/testing/dl_test_snippets.cc
index 25d9330..5dc341c 100644
--- a/display_list/testing/dl_test_snippets.cc
+++ b/display_list/testing/dl_test_snippets.cc
@@ -50,11 +50,15 @@
       {"SetAntiAlias",
        {
            {0, 8, 0, [](DlOpReceiver& r) { r.setAntiAlias(true); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0, [](DlOpReceiver& r) { r.setAntiAlias(false); }},
        }},
       {"SetInvertColors",
        {
            {0, 8, 0, [](DlOpReceiver& r) { r.setInvertColors(true); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0, [](DlOpReceiver& r) { r.setInvertColors(false); }},
        }},
       {"SetStrokeCap",
@@ -63,6 +67,8 @@
             [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kRound); }},
            {0, 8, 0,
             [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kSquare); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0,
             [](DlOpReceiver& r) { r.setStrokeCap(DlStrokeCap::kButt); }},
        }},
@@ -72,6 +78,8 @@
             [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kBevel); }},
            {0, 8, 0,
             [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kRound); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0,
             [](DlOpReceiver& r) { r.setStrokeJoin(DlStrokeJoin::kMiter); }},
        }},
@@ -83,6 +91,8 @@
             [](DlOpReceiver& r) {
               r.setDrawStyle(DlDrawStyle::kStrokeAndFill);
             }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0,
             [](DlOpReceiver& r) { r.setDrawStyle(DlDrawStyle::kFill); }},
        }},
@@ -90,12 +100,16 @@
        {
            {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeWidth(1.0); }},
            {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeWidth(5.0); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0, [](DlOpReceiver& r) { r.setStrokeWidth(0.0); }},
        }},
       {"SetStrokeMiter",
        {
            {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeMiter(0.0); }},
            {0, 8, 0, [](DlOpReceiver& r) { r.setStrokeMiter(5.0); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0, [](DlOpReceiver& r) { r.setStrokeMiter(4.0); }},
        }},
       {"SetColor",
@@ -104,6 +118,8 @@
             [](DlOpReceiver& r) { r.setColor(DlColor(SK_ColorGREEN)); }},
            {0, 8, 0,
             [](DlOpReceiver& r) { r.setColor(DlColor(SK_ColorBLUE)); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0,
             [](DlOpReceiver& r) { r.setColor(DlColor(SK_ColorBLACK)); }},
        }},
@@ -113,6 +129,8 @@
             [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcIn); }},
            {0, 8, 0,
             [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kDstIn); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0,
             [](DlOpReceiver& r) { r.setBlendMode(DlBlendMode::kSrcOver); }},
        }},
@@ -128,6 +146,8 @@
             [](DlOpReceiver& r) { r.setColorSource(kTestSource4.get()); }},
            {0, 80 + 6 * 4, 0,
             [](DlOpReceiver& r) { r.setColorSource(kTestSource5.get()); }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0, [](DlOpReceiver& r) { r.setColorSource(nullptr); }},
        }},
       {"SetImageFilter",
@@ -186,7 +206,6 @@
             [](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter1); }},
            {0, 24, 0,
             [](DlOpReceiver& r) { r.setImageFilter(&kTestCFImageFilter2); }},
-           {0, 0, 0, [](DlOpReceiver& r) { r.setImageFilter(nullptr); }},
            {0, 24, 0,
             [](DlOpReceiver& r) {
               r.setImageFilter(
@@ -194,6 +213,9 @@
                       .makeWithLocalMatrix(SkMatrix::Translate(2, 2))
                       .get());
             }},
+
+           // Reset attribute to default as last entry
+           {0, 0, 0, [](DlOpReceiver& r) { r.setImageFilter(nullptr); }},
        }},
       {"SetColorFilter",
        {
@@ -219,6 +241,8 @@
             [](DlOpReceiver& r) {
               r.setColorFilter(DlLinearToSrgbGammaColorFilter::kInstance.get());
             }},
+
+           // Reset attribute to default as last entry
            {0, 0, 0, [](DlOpReceiver& r) { r.setColorFilter(nullptr); }},
        }},
       {"SetMaskFilter",
@@ -238,6 +262,8 @@
            {0, 32, 0,
             [](DlOpReceiver& r) { r.setMaskFilter(&kTestMaskFilter5); }, 0u,
             2u},
+
+           // Reset attribute to default as last entry
            {0, 0, 0, [](DlOpReceiver& r) { r.setMaskFilter(nullptr); }, 0u, 1u},
        }},
   };