Allow checkerboarding raster cache entries for debugging purposes (can be toggled from Dart). (#3200)

diff --git a/flow/BUILD.gn b/flow/BUILD.gn
index cf444fa..f5a309e 100644
--- a/flow/BUILD.gn
+++ b/flow/BUILD.gn
@@ -42,6 +42,7 @@
   ]
 
   deps = [
+    "//flutter/common",
     "//flutter/glue",
     "//flutter/skia",
     "//flutter/synchronization",
diff --git a/flow/layers/layer_tree.cc b/flow/layers/layer_tree.cc
index c0262f0..9ed4b07 100644
--- a/flow/layers/layer_tree.cc
+++ b/flow/layers/layer_tree.cc
@@ -4,13 +4,16 @@
 
 #include "flutter/flow/layers/layer_tree.h"
 
-#include "flutter/glue/trace_event.h"
 #include "flutter/flow/layers/layer.h"
+#include "flutter/glue/trace_event.h"
 
 namespace flow {
 
 LayerTree::LayerTree()
-    : frame_size_{}, scene_version_(0), rasterizer_tracing_threshold_(0) {}
+    : frame_size_{},
+      scene_version_(0),
+      rasterizer_tracing_threshold_(0),
+      checkerboard_raster_cache_images_(0) {}
 
 LayerTree::~LayerTree() {}
 
diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h
index f1dfcdb..d8afe4b 100644
--- a/flow/layers/layer_tree.h
+++ b/flow/layers/layer_tree.h
@@ -66,13 +66,21 @@
     return rasterizer_tracing_threshold_;
   }
 
+  void set_checkerboard_raster_cache_images(bool checkerboard) {
+    checkerboard_raster_cache_images_ = checkerboard;
+  }
+
+  bool checkerboard_raster_cache_images() const {
+    return checkerboard_raster_cache_images_;
+  }
+
  private:
   SkISize frame_size_;  // Physical pixels.
   uint32_t scene_version_;
   std::unique_ptr<Layer> root_layer_;
-
   ftl::TimeDelta construction_time_;
   uint32_t rasterizer_tracing_threshold_;
+  bool checkerboard_raster_cache_images_;
 
   FTL_DISALLOW_COPY_AND_ASSIGN(LayerTree);
 };
diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc
index 8fcbc3b..b010378 100644
--- a/flow/raster_cache.cc
+++ b/flow/raster_cache.cc
@@ -4,6 +4,9 @@
 
 #include "flutter/flow/raster_cache.h"
 
+#include <vector>
+
+#include "flutter/common/threads.h"
 #include "flutter/glue/trace_event.h"
 #include "lib/ftl/logging.h"
 #include "third_party/skia/include/core/SkCanvas.h"
@@ -11,12 +14,8 @@
 #include "third_party/skia/include/core/SkPicture.h"
 #include "third_party/skia/include/core/SkSurface.h"
 
-#define ENABLE_RASTER_CACHE 1
-
 namespace flow {
 
-#if ENABLE_RASTER_CACHE
-
 static const int kRasterThreshold = 3;
 
 static bool isWorthRasterizing(SkPicture* picture) {
@@ -25,9 +24,43 @@
   return picture->approximateOpCount() > 10;
 }
 
-#endif
+static sk_sp<SkShader> CreateCheckerboardShader(SkColor c1,
+                                                SkColor c2,
+                                                int size) {
+  SkBitmap bm;
+  bm.allocN32Pixels(2 * size, 2 * size);
+  bm.eraseColor(c1);
+  bm.eraseArea(SkIRect::MakeLTRB(0, 0, size, size), c2);
+  bm.eraseArea(SkIRect::MakeLTRB(size, size, 2 * size, 2 * size), c2);
+  return SkShader::MakeBitmapShader(bm, SkShader::kRepeat_TileMode,
+                                    SkShader::kRepeat_TileMode);
+}
 
-RasterCache::RasterCache() {}
+static void DrawCheckerboard(SkCanvas* canvas,
+                             SkColor c1,
+                             SkColor c2,
+                             int size) {
+  SkPaint paint;
+  paint.setShader(CreateCheckerboardShader(c1, c2, size));
+  canvas->drawPaint(paint);
+}
+
+static void DrawCheckerboard(SkCanvas* canvas, const SkRect& rect) {
+  // Draw a checkerboard
+  canvas->save();
+  canvas->clipRect(rect);
+  DrawCheckerboard(canvas, 0x4400FF00, 0x00000000, 12);
+  canvas->restore();
+
+  // Stroke the drawn area
+  SkPaint debugPaint;
+  debugPaint.setStrokeWidth(3);
+  debugPaint.setColor(SK_ColorRED);
+  debugPaint.setStyle(SkPaint::kStroke_Style);
+  canvas->drawRect(rect, debugPaint);
+}
+
+RasterCache::RasterCache() : checkerboard_images_(false), weak_factory_(this) {}
 
 RasterCache::~RasterCache() {}
 
@@ -42,7 +75,6 @@
                                               const SkMatrix& ctm,
                                               bool is_complex,
                                               bool will_change) {
-#if ENABLE_RASTER_CACHE
   SkScalar scaleX = ctm.getScaleX();
   SkScalar scaleY = ctm.getScaleY();
 
@@ -86,15 +118,15 @@
         canvas->scale(scaleX, scaleY);
         canvas->translate(-rect.left(), -rect.top());
         canvas->drawPicture(picture);
+        if (checkerboard_images_) {
+          DrawCheckerboard(canvas, rect);
+        }
         entry.image = surface->makeImageSnapshot();
       }
     }
   }
 
   return entry.image;
-#else
-  return nullptr;
-#endif
 }
 
 void RasterCache::SweepAfterFrame() {
@@ -115,4 +147,20 @@
   cache_.clear();
 }
 
+void RasterCache::SetCheckboardCacheImages(bool checkerboard) {
+  if (checkerboard_images_ == checkerboard) {
+    return;
+  }
+
+  checkerboard_images_ = checkerboard;
+
+  // Clear all existing entries so previously rasterized items (with or without
+  // a checkerboard) will be refreshed in subsequent passes.
+  blink::Threads::Gpu()->PostTask([self = weak_factory_.GetWeakPtr()]() {
+    if (self) {
+      self->Clear();
+    }
+  });
+}
+
 }  // namespace flow
diff --git a/flow/raster_cache.h b/flow/raster_cache.h
index 6c98840..13b08e8 100644
--- a/flow/raster_cache.h
+++ b/flow/raster_cache.h
@@ -10,6 +10,7 @@
 
 #include "flutter/flow/instrumentation.h"
 #include "lib/ftl/macros.h"
+#include "lib/ftl/memory/weak_ptr.h"
 #include "third_party/skia/include/core/SkImage.h"
 #include "third_party/skia/include/core/SkSize.h"
 
@@ -29,6 +30,8 @@
 
   void Clear();
 
+  void SetCheckboardCacheImages(bool checkerboard);
+
  private:
   struct Entry {
     Entry();
@@ -41,7 +44,10 @@
   };
 
   using Cache = std::unordered_map<uint32_t, Entry>;
+
   Cache cache_;
+  bool checkerboard_images_;
+  ftl::WeakPtrFactory<RasterCache> weak_factory_;
 
   FTL_DISALLOW_COPY_AND_ASSIGN(RasterCache);
 };
diff --git a/lib/ui/compositing/scene.cc b/lib/ui/compositing/scene.cc
index ab80b07..57d0902 100644
--- a/lib/ui/compositing/scene.cc
+++ b/lib/ui/compositing/scene.cc
@@ -4,9 +4,9 @@
 
 #include "flutter/lib/ui/compositing/scene.h"
 
+#include "lib/tonic/converter/dart_converter.h"
 #include "lib/tonic/dart_args.h"
 #include "lib/tonic/dart_binding_macros.h"
-#include "lib/tonic/converter/dart_converter.h"
 #include "lib/tonic/dart_library_natives.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkPictureRecorder.h"
@@ -20,16 +20,21 @@
 DART_BIND_ALL(Scene, FOR_EACH_BINDING)
 
 ftl::RefPtr<Scene> Scene::create(std::unique_ptr<flow::Layer> rootLayer,
-                                 uint32_t rasterizerTracingThreshold) {
+                                 uint32_t rasterizerTracingThreshold,
+                                 bool checkerboardRasterCacheImages) {
   return ftl::MakeRefCounted<Scene>(std::move(rootLayer),
-                                    rasterizerTracingThreshold);
+                                    rasterizerTracingThreshold,
+                                    checkerboardRasterCacheImages);
 }
 
 Scene::Scene(std::unique_ptr<flow::Layer> rootLayer,
-             uint32_t rasterizerTracingThreshold)
+             uint32_t rasterizerTracingThreshold,
+             bool checkerboardRasterCacheImages)
     : m_layerTree(new flow::LayerTree()) {
   m_layerTree->set_root_layer(std::move(rootLayer));
   m_layerTree->set_rasterizer_tracing_threshold(rasterizerTracingThreshold);
+  m_layerTree->set_checkerboard_raster_cache_images(
+      checkerboardRasterCacheImages);
 }
 
 Scene::~Scene() {}
diff --git a/lib/ui/compositing/scene.h b/lib/ui/compositing/scene.h
index a9c7eaf..815b763 100644
--- a/lib/ui/compositing/scene.h
+++ b/lib/ui/compositing/scene.h
@@ -26,7 +26,8 @@
  public:
   ~Scene() override;
   static ftl::RefPtr<Scene> create(std::unique_ptr<flow::Layer> rootLayer,
-                                   uint32_t rasterizerTracingThreshold);
+                                   uint32_t rasterizerTracingThreshold,
+                                   bool checkerboardRasterCacheImages);
 
   std::unique_ptr<flow::LayerTree> takeLayerTree();
 
@@ -36,7 +37,8 @@
 
  private:
   explicit Scene(std::unique_ptr<flow::Layer> rootLayer,
-                 uint32_t rasterizerTracingThreshold);
+                 uint32_t rasterizerTracingThreshold,
+                 bool checkerboardRasterCacheImages);
 
   std::unique_ptr<flow::LayerTree> m_layerTree;
 };
diff --git a/lib/ui/compositing/scene_builder.cc b/lib/ui/compositing/scene_builder.cc
index 78a121a..2fb8ef5 100644
--- a/lib/ui/compositing/scene_builder.cc
+++ b/lib/ui/compositing/scene_builder.cc
@@ -36,20 +36,21 @@
 
 IMPLEMENT_WRAPPERTYPEINFO(ui, SceneBuilder);
 
-#define FOR_EACH_BINDING(V)                      \
-  V(SceneBuilder, pushTransform)                 \
-  V(SceneBuilder, pushClipRect)                  \
-  V(SceneBuilder, pushClipRRect)                 \
-  V(SceneBuilder, pushClipPath)                  \
-  V(SceneBuilder, pushOpacity)                   \
-  V(SceneBuilder, pushColorFilter)               \
-  V(SceneBuilder, pushBackdropFilter)            \
-  V(SceneBuilder, pushShaderMask)                \
-  V(SceneBuilder, pop)                           \
-  V(SceneBuilder, addPicture)                    \
-  V(SceneBuilder, addChildScene)                 \
-  V(SceneBuilder, addPerformanceOverlay)         \
-  V(SceneBuilder, setRasterizerTracingThreshold) \
+#define FOR_EACH_BINDING(V)                         \
+  V(SceneBuilder, pushTransform)                    \
+  V(SceneBuilder, pushClipRect)                     \
+  V(SceneBuilder, pushClipRRect)                    \
+  V(SceneBuilder, pushClipPath)                     \
+  V(SceneBuilder, pushOpacity)                      \
+  V(SceneBuilder, pushColorFilter)                  \
+  V(SceneBuilder, pushBackdropFilter)               \
+  V(SceneBuilder, pushShaderMask)                   \
+  V(SceneBuilder, pop)                              \
+  V(SceneBuilder, addPicture)                       \
+  V(SceneBuilder, addChildScene)                    \
+  V(SceneBuilder, addPerformanceOverlay)            \
+  V(SceneBuilder, setRasterizerTracingThreshold)    \
+  V(SceneBuilder, setCheckerboardRasterCacheImages) \
   V(SceneBuilder, build)
 
 FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
@@ -61,7 +62,9 @@
 }
 
 SceneBuilder::SceneBuilder()
-    : m_currentLayer(nullptr), m_currentRasterizerTracingThreshold(0) {
+    : m_currentLayer(nullptr),
+      m_currentRasterizerTracingThreshold(0),
+      m_checkerboardRasterCacheImages(false) {
   m_cullRects.push(SkRect::MakeLargest());
 }
 
@@ -230,11 +233,16 @@
   m_currentRasterizerTracingThreshold = frameInterval;
 }
 
+void SceneBuilder::setCheckerboardRasterCacheImages(bool checkerboard) {
+  m_checkerboardRasterCacheImages = checkerboard;
+}
+
 ftl::RefPtr<Scene> SceneBuilder::build() {
   m_currentLayer = nullptr;
   int32_t threshold = m_currentRasterizerTracingThreshold;
   m_currentRasterizerTracingThreshold = 0;
-  ftl::RefPtr<Scene> scene = Scene::create(std::move(m_rootLayer), threshold);
+  ftl::RefPtr<Scene> scene = Scene::create(std::move(m_rootLayer), threshold,
+                                           m_checkerboardRasterCacheImages);
   ClearDartWrapper();
   return scene;
 }
diff --git a/lib/ui/compositing/scene_builder.h b/lib/ui/compositing/scene_builder.h
index 5d530f7..3c42808 100644
--- a/lib/ui/compositing/scene_builder.h
+++ b/lib/ui/compositing/scene_builder.h
@@ -5,9 +5,9 @@
 #ifndef FLUTTER_LIB_UI_COMPOSITING_SCENE_BUILDER_H_
 #define FLUTTER_LIB_UI_COMPOSITING_SCENE_BUILDER_H_
 
-#include <stack>
 #include <stdint.h>
 #include <memory>
+#include <stack>
 
 #include "flutter/flow/layers/container_layer.h"
 #include "flutter/lib/ui/compositing/scene.h"
@@ -63,18 +63,22 @@
 
   void setRasterizerTracingThreshold(uint32_t frameInterval);
 
+  void setCheckerboardRasterCacheImages(bool checkerboard);
+
   ftl::RefPtr<Scene> build();
 
   static void RegisterNatives(tonic::DartLibraryNatives* natives);
 
  private:
-  explicit SceneBuilder();
+  SceneBuilder();
 
-  void addLayer(std::unique_ptr<flow::ContainerLayer> layer, const SkRect& cullRect);
+  void addLayer(std::unique_ptr<flow::ContainerLayer> layer,
+                const SkRect& cullRect);
 
   std::unique_ptr<flow::ContainerLayer> m_rootLayer;
   flow::ContainerLayer* m_currentLayer;
   int32_t m_currentRasterizerTracingThreshold;
+  bool m_checkerboardRasterCacheImages;
   std::stack<SkRect> m_cullRects;
 };