[graphite] Move DrawAtlasMgr to PathAtlas.

This will allow ComputePathAtlas to share it.

Bug: b/305696981
Change-Id: I11f059604fe11594b908e3fe92cf0b93d48d77af
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/839338
Reviewed-by: Arman Uguray <armansito@google.com>
Commit-Queue: Jim Van Verth <jvanverth@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/graphite/PathAtlas.cpp b/src/gpu/graphite/PathAtlas.cpp
index 211ed5d..750c132 100644
--- a/src/gpu/graphite/PathAtlas.cpp
+++ b/src/gpu/graphite/PathAtlas.cpp
@@ -9,8 +9,10 @@
 
 #include "include/gpu/graphite/Recorder.h"
 #include "src/gpu/graphite/Caps.h"
+#include "src/gpu/graphite/RasterPathUtils.h"
 #include "src/gpu/graphite/RecorderPriv.h"
 #include "src/gpu/graphite/RendererProvider.h"
+#include "src/gpu/graphite/TextureProxy.h"
 #include "src/gpu/graphite/geom/Transform_graphite.h"
 
 namespace skgpu::graphite {
@@ -69,4 +71,134 @@
     return std::make_pair(fRecorder->priv().rendererProvider()->coverageMask(), atlasMask);
 }
 
+/////////////////////////////////////////////////////////////////////////////////////////
+
+PathAtlas::DrawAtlasMgr::DrawAtlasMgr(size_t width, size_t height,
+                                      size_t plotWidth, size_t plotHeight,
+                                      std::string_view label,
+                                      const Caps* caps) {
+    static constexpr SkColorType colorType = kAlpha_8_SkColorType;
+
+    fDrawAtlas = DrawAtlas::Make(colorType,
+                                 SkColorTypeBytesPerPixel(colorType),
+                                 width, height,
+                                 plotWidth, plotHeight,
+                                 this,
+                                 caps->allowMultipleAtlasTextures() ?
+                                         DrawAtlas::AllowMultitexturing::kYes :
+                                         DrawAtlas::AllowMultitexturing::kNo,
+                                 this,
+                                 label);
+    SkASSERT(fDrawAtlas);
+    fKeyLists.resize(fDrawAtlas->numPlots() * fDrawAtlas->maxPages());
+    for (int i = 0; i < fKeyLists.size(); ++i) {
+        fKeyLists[i].reset();
+    }
+}
+
+namespace {
+uint32_t shape_key_list_index(const PlotLocator& locator, const DrawAtlas* drawAtlas) {
+    return locator.pageIndex() * drawAtlas->numPlots() + locator.plotIndex();
+}
+}  // namespace
+
+const TextureProxy* PathAtlas::DrawAtlasMgr::findOrCreateEntry(Recorder* recorder,
+                                                               const Shape& shape,
+                                                               const Transform& transform,
+                                                               const SkStrokeRec& strokeRec,
+                                                               skvx::half2 maskSize,
+                                                               skvx::half2* outPos) {
+    // Shapes must have a key to use this method
+    skgpu::UniqueKey maskKey = GeneratePathMaskKey(shape, transform, strokeRec, maskSize);
+    AtlasLocator* cachedLocator = fShapeCache.find(maskKey);
+    if (cachedLocator) {
+        SkIPoint topLeft = cachedLocator->topLeft();
+        *outPos = skvx::half2(topLeft.x() + kEntryPadding, topLeft.y() + kEntryPadding);
+        fDrawAtlas->setLastUseToken(*cachedLocator,
+                                    recorder->priv().tokenTracker()->nextFlushToken());
+        return fDrawAtlas->getProxies()[cachedLocator->pageIndex()].get();
+    }
+
+    AtlasLocator locator;
+    const TextureProxy* proxy = this->addToAtlas(recorder, shape, transform, strokeRec,
+                                                 maskSize, outPos, &locator);
+    if (!proxy) {
+        return nullptr;
+    }
+
+    // Add locator to ShapeCache.
+    fShapeCache.set(maskKey, locator);
+    // Add key to Plot's ShapeKeyList.
+    uint32_t index = shape_key_list_index(locator.plotLocator(), fDrawAtlas.get());
+    ShapeKeyEntry* keyEntry = new ShapeKeyEntry();
+    keyEntry->fKey = maskKey;
+    fKeyLists[index].addToTail(keyEntry);
+
+    return proxy;
+}
+
+const TextureProxy* PathAtlas::DrawAtlasMgr::addToAtlas(Recorder* recorder,
+                                                        const Shape& shape,
+                                                        const Transform& transform,
+                                                        const SkStrokeRec& strokeRec,
+                                                        skvx::half2 maskSize,
+                                                        skvx::half2* outPos,
+                                                        AtlasLocator* locator) {
+    // Render mask.
+    SkIRect iShapeBounds = SkIRect::MakeXYWH(0, 0, maskSize.x(), maskSize.y());
+    // Outset to take padding into account
+    SkIRect iAtlasBounds = iShapeBounds.makeOutset(kEntryPadding, kEntryPadding);
+
+    // Request space in DrawAtlas.
+    DrawAtlas::ErrorCode errorCode = fDrawAtlas->addRect(recorder,
+                                                         iAtlasBounds.width(),
+                                                         iAtlasBounds.height(),
+                                                         locator);
+    if (errorCode != DrawAtlas::ErrorCode::kSucceeded) {
+        return nullptr;
+    }
+    SkIPoint topLeft = locator->topLeft();
+    *outPos = skvx::half2(topLeft.x()+kEntryPadding, topLeft.y()+kEntryPadding);
+
+    // If the mask is empty, just return.
+    // TODO: this may not be needed if we can handle clipped out bounds with inverse fills
+    // another way. See PathAtlas::addShape().
+    if (!all(maskSize)) {
+        fDrawAtlas->setLastUseToken(*locator,
+                                    recorder->priv().tokenTracker()->nextFlushToken());
+        return fDrawAtlas->getProxies()[locator->pageIndex()].get();
+    }
+
+    if (!this->onAddToAtlas(shape, transform, strokeRec, iShapeBounds, *locator)) {
+        return nullptr;
+    }
+
+    fDrawAtlas->setLastUseToken(*locator,
+                                recorder->priv().tokenTracker()->nextFlushToken());
+
+    return fDrawAtlas->getProxies()[locator->pageIndex()].get();
+}
+
+bool PathAtlas::DrawAtlasMgr::recordUploads(DrawContext* dc, Recorder* recorder) {
+    return fDrawAtlas->recordUploads(dc, recorder);
+}
+
+void PathAtlas::DrawAtlasMgr::evict(PlotLocator plotLocator) {
+    // Remove all entries for this Plot from the ShapeCache
+    uint32_t index = shape_key_list_index(plotLocator, fDrawAtlas.get());
+    ShapeKeyList::Iter iter;
+    iter.init(fKeyLists[index], ShapeKeyList::Iter::kHead_IterStart);
+    ShapeKeyEntry* currEntry;
+    while ((currEntry = iter.get())) {
+        iter.next();
+        fShapeCache.remove(currEntry->fKey);
+        fKeyLists[index].remove(currEntry);
+        delete currEntry;
+    }
+}
+
+void PathAtlas::DrawAtlasMgr::postFlush(Recorder* recorder) {
+    fDrawAtlas->compact(recorder->priv().tokenTracker()->nextFlushToken());
+}
+
 }  // namespace skgpu::graphite
diff --git a/src/gpu/graphite/PathAtlas.h b/src/gpu/graphite/PathAtlas.h
index b2f0043..ca32d33 100644
--- a/src/gpu/graphite/PathAtlas.h
+++ b/src/gpu/graphite/PathAtlas.h
@@ -9,6 +9,11 @@
 #define skgpu_graphite_PathAtlas_DEFINED
 
 #include "include/core/SkStrokeRec.h"
+#include "src/base/SkTInternalLList.h"
+#include "src/core/SkTHash.h"
+#include "src/gpu/AtlasTypes.h"
+#include "src/gpu/ResourceKey.h"
+#include "src/gpu/graphite/DrawAtlas.h"
 #include "src/gpu/graphite/geom/CoverageMaskShape.h"
 
 namespace skgpu::graphite {
@@ -104,6 +109,60 @@
                                            skvx::half2 maskSize,
                                            skvx::half2* outPos) = 0;
 
+    // Wrapper class to manage DrawAtlas and associated caching operations
+    class DrawAtlasMgr : public AtlasGenerationCounter, public PlotEvictionCallback {
+    public:
+        const TextureProxy* findOrCreateEntry(Recorder* recorder,
+                                              const Shape& shape,
+                                              const Transform& transform,
+                                              const SkStrokeRec& strokeRec,
+                                              skvx::half2 maskSize,
+                                              skvx::half2* outPos);
+        // Adds to DrawAtlas but not the cache
+        const TextureProxy* addToAtlas(Recorder* recorder,
+                                       const Shape& shape,
+                                       const Transform& transform,
+                                       const SkStrokeRec& strokeRec,
+                                       skvx::half2 maskSize,
+                                       skvx::half2* outPos,
+                                       AtlasLocator* locator);
+        bool recordUploads(DrawContext*, Recorder*);
+        void evict(PlotLocator) override;
+        void postFlush(Recorder*);
+
+    protected:
+        DrawAtlasMgr(size_t width, size_t height,
+                     size_t plotWidth, size_t plotHeight,
+                     std::string_view label, const Caps*);
+
+        bool virtual onAddToAtlas(const Shape&,
+                                  const Transform& transform,
+                                  const SkStrokeRec&,
+                                  SkIRect shapeBounds,
+                                  const AtlasLocator&) = 0;
+
+        std::unique_ptr<DrawAtlas> fDrawAtlas;
+
+    private:
+        // Tracks whether a shape is already in the DrawAtlas, and its location in the atlas
+        struct UniqueKeyHash {
+            uint32_t operator()(const skgpu::UniqueKey& key) const { return key.hash(); }
+        };
+        using ShapeCache = skia_private::THashMap<skgpu::UniqueKey, AtlasLocator, UniqueKeyHash>;
+        ShapeCache fShapeCache;
+
+        // List of stored keys per Plot, used to invalidate cache entries.
+        // When a Plot is invalidated via evict(), we'll get its index and Page index from the
+        // PlotLocator, index into the fKeyLists array to get the ShapeKeyList for that Plot,
+        // then iterate through the list and remove entries matching those keys from the ShapeCache.
+        struct ShapeKeyEntry {
+            skgpu::UniqueKey fKey;
+            SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeKeyEntry);
+        };
+        using ShapeKeyList = SkTInternalLList<ShapeKeyEntry>;
+        SkTDArray<ShapeKeyList> fKeyLists;
+    };
+
     // The Recorder that created and owns this Atlas.
     Recorder* fRecorder;
 
diff --git a/src/gpu/graphite/RasterPathAtlas.cpp b/src/gpu/graphite/RasterPathAtlas.cpp
index f58c018..1dd9de3 100644
--- a/src/gpu/graphite/RasterPathAtlas.cpp
+++ b/src/gpu/graphite/RasterPathAtlas.cpp
@@ -15,7 +15,6 @@
 #include "src/gpu/graphite/Log.h"
 #include "src/gpu/graphite/RasterPathUtils.h"
 #include "src/gpu/graphite/RecorderPriv.h"
-#include "src/gpu/graphite/TextureProxy.h"
 
 namespace skgpu::graphite {
 
@@ -86,143 +85,27 @@
 
 /////////////////////////////////////////////////////////////////////////////////////////
 
-RasterPathAtlas::DrawAtlasMgr::DrawAtlasMgr(size_t width, size_t height,
-                                            size_t plotWidth, size_t plotHeight,
-                                            const Caps* caps) {
-    static constexpr SkColorType colorType = kAlpha_8_SkColorType;
-
-
-    fDrawAtlas = DrawAtlas::Make(colorType,
-                                 SkColorTypeBytesPerPixel(colorType),
-                                 width, height,
-                                 plotWidth, plotHeight,
-                                 this,
-                                 caps->allowMultipleAtlasTextures() ?
-                                         DrawAtlas::AllowMultitexturing::kYes :
-                                         DrawAtlas::AllowMultitexturing::kNo,
-                                 this,
-                                 /*label=*/"RasterPathAtlas");
-    SkASSERT(fDrawAtlas);
-    fKeyLists.resize(fDrawAtlas->numPlots() * fDrawAtlas->maxPages());
-    for (int i = 0; i < fKeyLists.size(); ++i) {
-        fKeyLists[i].reset();
-    }
-}
-
-namespace {
-uint32_t shape_key_list_index(const PlotLocator& locator, const DrawAtlas* drawAtlas) {
-    return locator.pageIndex() * drawAtlas->numPlots() + locator.plotIndex();
-}
-}  // namespace
-
-const TextureProxy* RasterPathAtlas::DrawAtlasMgr::findOrCreateEntry(Recorder* recorder,
-                                                                    const Shape& shape,
-                                                                    const Transform& transform,
-                                                                    const SkStrokeRec& strokeRec,
-                                                                    skvx::half2 maskSize,
-                                                                    skvx::half2* outPos) {
-    // Shapes must have a key to use this method
-    skgpu::UniqueKey maskKey = GeneratePathMaskKey(shape, transform, strokeRec, maskSize);
-    AtlasLocator* cachedLocator = fShapeCache.find(maskKey);
-    if (cachedLocator) {
-        SkIPoint topLeft = cachedLocator->topLeft();
-        *outPos = skvx::half2(topLeft.x() + kEntryPadding, topLeft.y() + kEntryPadding);
-        fDrawAtlas->setLastUseToken(*cachedLocator,
-                                    recorder->priv().tokenTracker()->nextFlushToken());
-        return fDrawAtlas->getProxies()[cachedLocator->pageIndex()].get();
-    }
-
-    AtlasLocator locator;
-    const TextureProxy* proxy = this->addToAtlas(recorder, shape, transform, strokeRec,
-                                                 maskSize, outPos, &locator);
-    if (!proxy) {
-        return nullptr;
-    }
-
-    // Add locator to ShapeCache.
-    fShapeCache.set(maskKey, locator);
-    // Add key to Plot's ShapeKeyList.
-    uint32_t index = shape_key_list_index(locator.plotLocator(), fDrawAtlas.get());
-    ShapeKeyEntry* keyEntry = new ShapeKeyEntry();
-    keyEntry->fKey = maskKey;
-    fKeyLists[index].addToTail(keyEntry);
-
-    return proxy;
-}
-
-const TextureProxy* RasterPathAtlas::DrawAtlasMgr::addToAtlas(Recorder* recorder,
-                                                              const Shape& shape,
-                                                              const Transform& transform,
-                                                              const SkStrokeRec& strokeRec,
-                                                              skvx::half2 maskSize,
-                                                              skvx::half2* outPos,
-                                                              AtlasLocator* locator) {
-    // Render mask.
-    SkIRect iShapeBounds = SkIRect::MakeXYWH(0, 0, maskSize.x(), maskSize.y());
-    // Outset to take padding into account
-    SkIRect iAtlasBounds = iShapeBounds.makeOutset(kEntryPadding, kEntryPadding);
-
-    // Request space in DrawAtlas.
-    DrawAtlas::ErrorCode errorCode = fDrawAtlas->addRect(recorder,
-                                                         iAtlasBounds.width(),
-                                                         iAtlasBounds.height(),
-                                                         locator);
-    if (errorCode != DrawAtlas::ErrorCode::kSucceeded) {
-        return nullptr;
-    }
-    SkIPoint topLeft = locator->topLeft();
-    *outPos = skvx::half2(topLeft.x()+kEntryPadding, topLeft.y()+kEntryPadding);
-
-    // If the mask is empty, just return.
-    // TODO: this may not be needed if we can handle clipped out bounds with inverse fills
-    // another way. See PathAtlas::addShape().
-    if (!all(maskSize)) {
-        fDrawAtlas->setLastUseToken(*locator,
-                                    recorder->priv().tokenTracker()->nextFlushToken());
-        return fDrawAtlas->getProxies()[locator->pageIndex()].get();
-    }
-
+bool RasterPathAtlas::RasterAtlasMgr::onAddToAtlas(const Shape& shape,
+                                                   const Transform& transform,
+                                                   const SkStrokeRec& strokeRec,
+                                                   SkIRect shapeBounds,
+                                                   const AtlasLocator& locator) {
     // Rasterize path to backing pixmap.
     // This pixmap will be the size of the Plot that contains the given rect, not the entire atlas,
     // and hence the position we render at will be relative to that Plot.
     // The value of outPos is relative to the entire texture, to be used for texture coords.
     SkAutoPixmapStorage dst;
-    SkIPoint renderPos = fDrawAtlas->prepForRender(*locator, &dst);
+    SkIPoint renderPos = fDrawAtlas->prepForRender(locator, &dst);
 
     RasterMaskHelper helper(&dst);
     if (!helper.init(fDrawAtlas->plotSize())) {
-        return nullptr;
+        return false;
     }
     // Offset to plot location and draw
-    iShapeBounds.offset(renderPos.x()+kEntryPadding, renderPos.y()+kEntryPadding);
-    helper.drawShape(shape, transform, strokeRec, iShapeBounds);
+    shapeBounds.offset(renderPos.x()+kEntryPadding, renderPos.y()+kEntryPadding);
+    helper.drawShape(shape, transform, strokeRec, shapeBounds);
 
-    fDrawAtlas->setLastUseToken(*locator,
-                                recorder->priv().tokenTracker()->nextFlushToken());
-
-    return fDrawAtlas->getProxies()[locator->pageIndex()].get();
-}
-
-bool RasterPathAtlas::DrawAtlasMgr::recordUploads(DrawContext* dc, Recorder* recorder) {
-    return fDrawAtlas->recordUploads(dc, recorder);
-}
-
-void RasterPathAtlas::DrawAtlasMgr::evict(PlotLocator plotLocator) {
-    // Remove all entries for this Plot from the ShapeCache
-    uint32_t index = shape_key_list_index(plotLocator, fDrawAtlas.get());
-    ShapeKeyList::Iter iter;
-    iter.init(fKeyLists[index], ShapeKeyList::Iter::kHead_IterStart);
-    ShapeKeyEntry* currEntry;
-    while ((currEntry = iter.get())) {
-        iter.next();
-        fShapeCache.remove(currEntry->fKey);
-        fKeyLists[index].remove(currEntry);
-        delete currEntry;
-    }
-}
-
-void RasterPathAtlas::DrawAtlasMgr::postFlush(Recorder* recorder) {
-    fDrawAtlas->compact(recorder->priv().tokenTracker()->nextFlushToken());
+    return true;
 }
 
 }  // namespace skgpu::graphite
diff --git a/src/gpu/graphite/RasterPathAtlas.h b/src/gpu/graphite/RasterPathAtlas.h
index f6f4404..a26833d 100644
--- a/src/gpu/graphite/RasterPathAtlas.h
+++ b/src/gpu/graphite/RasterPathAtlas.h
@@ -8,11 +8,6 @@
 #ifndef skgpu_graphite_RasterPathAtlas_DEFINED
 #define skgpu_graphite_RasterPathAtlas_DEFINED
 
-#include "src/base/SkTInternalLList.h"
-#include "src/core/SkTHash.h"
-#include "src/gpu/AtlasTypes.h"
-#include "src/gpu/ResourceKey.h"
-#include "src/gpu/graphite/DrawAtlas.h"
 #include "src/gpu/graphite/PathAtlas.h"
 
 namespace skgpu::graphite {
@@ -46,57 +41,25 @@
                                    skvx::half2 maskSize,
                                    skvx::half2* outPos) override;
 private:
-    // Wrapper class to manage DrawAtlas and associated caching operations
-    class DrawAtlasMgr : public AtlasGenerationCounter, public PlotEvictionCallback {
+    class RasterAtlasMgr : public PathAtlas::DrawAtlasMgr {
     public:
-        DrawAtlasMgr(size_t width, size_t height,
-                     size_t plotWidth, size_t plotHeight,
-                     const Caps*);
+        RasterAtlasMgr(size_t width, size_t height,
+                       size_t plotWidth, size_t plotHeight,
+                       const Caps* caps)
+            : PathAtlas::DrawAtlasMgr(width, height, plotWidth, plotHeight,
+                                      /*label=*/"RasterPathAtlas", caps) {}
 
-        const TextureProxy* findOrCreateEntry(Recorder* recorder,
-                                              const Shape& shape,
-                                              const Transform& transform,
-                                              const SkStrokeRec& strokeRec,
-                                              skvx::half2 maskSize,
-                                              skvx::half2* outPos);
-        // Adds to DrawAtlas but not the cache
-        const TextureProxy* addToAtlas(Recorder* recorder,
-                                       const Shape& shape,
-                                       const Transform& transform,
-                                       const SkStrokeRec& strokeRec,
-                                       skvx::half2 maskSize,
-                                       skvx::half2* outPos,
-                                       AtlasLocator* locator);
-        bool recordUploads(DrawContext*, Recorder*);
-        void evict(PlotLocator) override;
-        void postFlush(Recorder*);
-
-    private:
-
-        std::unique_ptr<DrawAtlas> fDrawAtlas;
-
-        // Tracks whether a shape is already in the DrawAtlas, and its location in the atlas
-        struct UniqueKeyHash {
-            uint32_t operator()(const skgpu::UniqueKey& key) const { return key.hash(); }
-        };
-        using ShapeCache = skia_private::THashMap<skgpu::UniqueKey, AtlasLocator, UniqueKeyHash>;
-        ShapeCache fShapeCache;
-
-        // List of stored keys per Plot, used to invalidate cache entries.
-        // When a Plot is invalidated via evict(), we'll get its index and Page index from the
-        // PlotLocator, index into the fKeyLists array to get the ShapeKeyList for that Plot,
-        // then iterate through the list and remove entries matching those keys from the ShapeCache.
-        struct ShapeKeyEntry {
-            skgpu::UniqueKey fKey;
-            SK_DECLARE_INTERNAL_LLIST_INTERFACE(ShapeKeyEntry);
-        };
-        using ShapeKeyList = SkTInternalLList<ShapeKeyEntry>;
-        SkTDArray<ShapeKeyList> fKeyLists;
+    protected:
+        bool onAddToAtlas(const Shape&,
+                          const Transform& transform,
+                          const SkStrokeRec&,
+                          SkIRect shapeBounds,
+                          const AtlasLocator&) override;
     };
 
-    DrawAtlasMgr fCachedAtlasMgr;
-    DrawAtlasMgr fSmallPathAtlasMgr;
-    DrawAtlasMgr fUncachedAtlasMgr;
+    RasterAtlasMgr fCachedAtlasMgr;
+    RasterAtlasMgr fSmallPathAtlasMgr;
+    RasterAtlasMgr fUncachedAtlasMgr;
 };
 
 }  // namespace skgpu::graphite