[graphite] Stub in SmallPathAtlas.

Prep work for adding small path support.

Bug: b/294378744
Change-Id: Icb11ea1c6acbbceeea933f847edc48b843d3ecae
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/811257
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/gn/graphite.gni b/gn/graphite.gni
index 25511dd..24b6f5e 100644
--- a/gn/graphite.gni
+++ b/gn/graphite.gni
@@ -137,6 +137,8 @@
   "$_src/ShaderCodeDictionary.h",
   "$_src/SharedContext.cpp",
   "$_src/SharedContext.h",
+  "$_src/SmallPathAtlas.cpp",
+  "$_src/SmallPathAtlas.h",
   "$_src/SpecialImage_Graphite.cpp",
   "$_src/Surface_Graphite.cpp",
   "$_src/Surface_Graphite.h",
diff --git a/src/gpu/graphite/RasterPathAtlas.h b/src/gpu/graphite/RasterPathAtlas.h
index 8cba746..65c720f 100644
--- a/src/gpu/graphite/RasterPathAtlas.h
+++ b/src/gpu/graphite/RasterPathAtlas.h
@@ -22,9 +22,9 @@
  * When a new shape gets added, its path is rasterized in preparation for upload. These
  * uploads are recorded by `recordUploads()` and subsequently added to an UploadTask.
  *
- * After a successful call to `recordUploads()`, the client is free to call `reset()` and start
- * adding new shapes for a future atlas render.
- * TODO: We should cache Shapes for future frames to avoid the cost of raster pipeline rendering.
+ * Shapes are cached for future frames to avoid the cost of raster pipeline rendering. Multiple
+ * textures (or Pages) are used to cache masks, so if the atlas is full we can reset a Page and
+ * start adding new shapes for a future atlas render.
  */
 class RasterPathAtlas : public PathAtlas {
 public:
diff --git a/src/gpu/graphite/SmallPathAtlas.cpp b/src/gpu/graphite/SmallPathAtlas.cpp
new file mode 100644
index 0000000..6084a948
--- /dev/null
+++ b/src/gpu/graphite/SmallPathAtlas.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/graphite/SmallPathAtlas.h"
+
+#include "include/core/SkColorSpace.h"
+#include "include/gpu/graphite/Recorder.h"
+#include "src/core/SkBlitter_A8.h"
+#include "src/core/SkDrawBase.h"
+#include "src/core/SkIPoint16.h"
+#include "src/core/SkRasterClip.h"
+#include "src/gpu/graphite/AtlasProvider.h"
+#include "src/gpu/graphite/DrawContext.h"
+#include "src/gpu/graphite/Log.h"
+#include "src/gpu/graphite/RecorderPriv.h"
+#include "src/gpu/graphite/TextureProxy.h"
+
+namespace skgpu::graphite {
+
+SmallPathAtlas::SmallPathAtlas()
+        : PathAtlas(kDefaultAtlasDim, kDefaultAtlasDim) {
+}
+
+const TextureProxy* SmallPathAtlas::onAddShape(Recorder* recorder,
+                                               const Shape& shape,
+                                               const Transform& transform,
+                                               const SkStrokeRec& strokeRec,
+                                               skvx::half2 maskSize,
+                                               skvx::half2* outPos) {
+    return nullptr;
+}
+
+}  // namespace skgpu::graphite
diff --git a/src/gpu/graphite/SmallPathAtlas.h b/src/gpu/graphite/SmallPathAtlas.h
new file mode 100644
index 0000000..1e9ad85
--- /dev/null
+++ b/src/gpu/graphite/SmallPathAtlas.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2024 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skgpu_graphite_SmallPathAtlas_DEFINED
+#define skgpu_graphite_SmallPathAtlas_DEFINED
+
+#include "src/base/SkTInternalLList.h"
+#include "src/core/SkTHash.h"
+#include "src/gpu/ResourceKey.h"
+#include "src/gpu/graphite/DrawAtlas.h"
+#include "src/gpu/graphite/PathAtlas.h"
+
+namespace skgpu::graphite {
+
+class UploadList;
+
+/**
+ * PathAtlas class that rasterizes coverage masks on the CPU and caches them in a
+ * DrawAtlas. Only masks below a certain size will be stored in this atlas; larger
+ * masks should be stored in the RasterPathAtlas.
+ *
+ * When a new shape gets added, its path is rasterized in preparation for upload. These
+ * uploads are recorded by `recordUploads()` and subsequently added to an UploadTask.
+ *
+ */
+class SmallPathAtlas : public PathAtlas {
+public:
+    SmallPathAtlas();
+    ~SmallPathAtlas() override {}
+
+    bool recordUploads(UploadList*) { /*TODO*/ return false; }
+
+protected:
+    const TextureProxy* onAddShape(Recorder* recorder,
+                                   const Shape&,
+                                   const Transform& transform,
+                                   const SkStrokeRec&,
+                                   skvx::half2 maskSize,
+                                   skvx::half2* outPos) override;
+
+private:
+    // TODO: select atlas size dynamically? Take ContextOptions::fMaxTextureAtlasSize into account?
+    static constexpr int kDefaultAtlasDim = 2048;
+
+    std::unique_ptr<DrawAtlas> fDrawAtlas;
+};
+
+}  // namespace skgpu::graphite
+
+#endif  // skgpu_graphite_SmallPathAtlas_DEFINED