Move GrPathRenderer and GrPathRendererChain to skgpu::v1 namespace

Bug: skia:11837
Change-Id: I42abcd3724ac1e2c71d3bd13ff6295a4683af5e0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/440261
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 5dfbe43..1d808aa 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -498,10 +498,6 @@
   "$_src/gpu/GrDrawOpTest.h",
   "$_src/gpu/GrOpsTask.cpp",
   "$_src/gpu/GrOpsTask.h",
-  "$_src/gpu/GrPathRenderer.cpp",
-  "$_src/gpu/GrPathRenderer.h",
-  "$_src/gpu/GrPathRendererChain.cpp",
-  "$_src/gpu/GrPathRendererChain.h",
 
   # Ops
   "$_src/gpu/ops/AAConvexPathRenderer.cpp",
@@ -590,6 +586,10 @@
   "$_src/gpu/v1/Device.cpp",
   "$_src/gpu/v1/Device_drawTexture.cpp",
   "$_src/gpu/v1/Device_v1.h",
+  "$_src/gpu/v1/PathRenderer.cpp",
+  "$_src/gpu/v1/PathRenderer.h",
+  "$_src/gpu/v1/PathRendererChain.cpp",
+  "$_src/gpu/v1/PathRendererChain.h",
   "$_src/gpu/v1/StencilClip.h",
   "$_src/gpu/v1/StencilMaskHelper.cpp",
   "$_src/gpu/v1/StencilMaskHelper.h",
diff --git a/src/gpu/GrDrawingManager.cpp b/src/gpu/GrDrawingManager.cpp
index 309aa4e..f536b86 100644
--- a/src/gpu/GrDrawingManager.cpp
+++ b/src/gpu/GrDrawingManager.cpp
@@ -51,7 +51,7 @@
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 #if SK_GPU_V1
 GrDrawingManager::GrDrawingManager(GrRecordingContext* rContext,
-                                   const GrPathRendererChain::Options& optionsForPathRendererChain,
+                                   const PathRendererChain::Options& optionsForPathRendererChain,
                                    bool reduceOpsTaskSplitting)
         : fContext(rContext)
         , fOptionsForPathRendererChain(optionsForPathRendererChain)
@@ -936,20 +936,21 @@
  * Due to its expense, the software path renderer has split out so it can
  * can be individually allowed/disallowed via the "allowSW" boolean.
  */
-GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
-                                                  bool allowSW,
-                                                  GrPathRendererChain::DrawType drawType,
-                                                  GrPathRenderer::StencilSupport* stencilSupport) {
+skgpu::v1::PathRenderer* GrDrawingManager::getPathRenderer(
+        const PathRenderer::CanDrawPathArgs& args,
+        bool allowSW,
+        PathRendererChain::DrawType drawType,
+        PathRenderer::StencilSupport* stencilSupport) {
 
     if (!fPathRendererChain) {
         fPathRendererChain =
-                std::make_unique<GrPathRendererChain>(fContext, fOptionsForPathRendererChain);
+                std::make_unique<PathRendererChain>(fContext, fOptionsForPathRendererChain);
     }
 
-    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
+    auto pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
     if (!pr && allowSW) {
         auto swPR = this->getSoftwarePathRenderer();
-        if (GrPathRenderer::CanDrawPath::kNo != swPR->canDrawPath(args)) {
+        if (PathRenderer::CanDrawPath::kNo != swPR->canDrawPath(args)) {
             pr = swPR;
         }
     }
@@ -963,7 +964,7 @@
     return pr;
 }
 
-GrPathRenderer* GrDrawingManager::getSoftwarePathRenderer() {
+skgpu::v1::PathRenderer* GrDrawingManager::getSoftwarePathRenderer() {
     if (!fSoftwarePathRenderer) {
         fSoftwarePathRenderer.reset(new skgpu::v1::SoftwarePathRenderer(
             fContext->priv().proxyProvider(), fOptionsForPathRendererChain.fAllowPathMaskCaching));
@@ -973,16 +974,16 @@
 
 skgpu::v1::AtlasPathRenderer* GrDrawingManager::getAtlasPathRenderer() {
     if (!fPathRendererChain) {
-        fPathRendererChain = std::make_unique<GrPathRendererChain>(fContext,
-                                                                   fOptionsForPathRendererChain);
+        fPathRendererChain = std::make_unique<PathRendererChain>(fContext,
+                                                                 fOptionsForPathRendererChain);
     }
     return fPathRendererChain->getAtlasPathRenderer();
 }
 
-GrPathRenderer* GrDrawingManager::getTessellationPathRenderer() {
+skgpu::v1::PathRenderer* GrDrawingManager::getTessellationPathRenderer() {
     if (!fPathRendererChain) {
-        fPathRendererChain = std::make_unique<GrPathRendererChain>(fContext,
-                                                                   fOptionsForPathRendererChain);
+        fPathRendererChain = std::make_unique<PathRendererChain>(fContext,
+                                                                 fOptionsForPathRendererChain);
     }
     return fPathRendererChain->getTessellationPathRenderer();
 }
diff --git a/src/gpu/GrDrawingManager.h b/src/gpu/GrDrawingManager.h
index c1d118f..30148a6 100644
--- a/src/gpu/GrDrawingManager.h
+++ b/src/gpu/GrDrawingManager.h
@@ -19,8 +19,8 @@
 #include "src/gpu/GrSurfaceProxy.h"
 
 #if SK_GPU_V1
-#include "src/gpu/GrPathRenderer.h"
-#include "src/gpu/GrPathRendererChain.h"
+#include "src/gpu/v1/PathRenderer.h"
+#include "src/gpu/v1/PathRendererChain.h"
 #endif
 
 // Enabling this will print out which path renderers are being chosen
@@ -111,12 +111,15 @@
     GrRecordingContext* getContext() { return fContext; }
 
 #if SK_GPU_V1
-    GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
-                                    bool allowSW,
-                                    GrPathRendererChain::DrawType drawType,
-                                    GrPathRenderer::StencilSupport* stencilSupport = nullptr);
+    using PathRenderer = skgpu::v1::PathRenderer;
+    using PathRendererChain = skgpu::v1::PathRendererChain;
 
-    GrPathRenderer* getSoftwarePathRenderer();
+    PathRenderer* getPathRenderer(const PathRenderer::CanDrawPathArgs&,
+                                  bool allowSW,
+                                  PathRendererChain::DrawType,
+                                  PathRenderer::StencilSupport* = nullptr);
+
+    PathRenderer* getSoftwarePathRenderer();
 
     // Returns a direct pointer to the atlas path renderer, or null if it is not supported and
     // turned on.
@@ -124,7 +127,7 @@
 
     // Returns a direct pointer to the tessellation path renderer, or null if it is not supported
     // and turned on.
-    GrPathRenderer* getTessellationPathRenderer();
+    PathRenderer* getTessellationPathRenderer();
 #endif
 
     void flushIfNecessary();
@@ -141,7 +144,7 @@
 #if GR_TEST_UTILS
     void testingOnly_removeOnFlushCallbackObject(GrOnFlushCallbackObject*);
 #if SK_GPU_V1
-    GrPathRendererChain::Options testingOnly_getOptionsForPathRendererChain() {
+    PathRendererChain::Options testingOnly_getOptionsForPathRendererChain() {
         return fOptionsForPathRendererChain;
     }
 #endif
@@ -159,7 +162,7 @@
 private:
 #if SK_GPU_V1
     GrDrawingManager(GrRecordingContext*,
-                     const GrPathRendererChain::Options&,
+                     const PathRendererChain::Options&,
                      bool reduceOpsTaskSplitting);
 #else
     GrDrawingManager(GrRecordingContext*, bool reduceOpsTaskSplitting);
@@ -219,8 +222,8 @@
     SkSTArray<4, sk_sp<GrRenderTask>>        fOnFlushRenderTasks;
 
 #if SK_GPU_V1
-    GrPathRendererChain::Options             fOptionsForPathRendererChain;
-    std::unique_ptr<GrPathRendererChain>     fPathRendererChain;
+    PathRendererChain::Options               fOptionsForPathRendererChain;
+    std::unique_ptr<PathRendererChain>       fPathRendererChain;
     sk_sp<skgpu::v1::SoftwarePathRenderer>   fSoftwarePathRenderer;
 #endif
 
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
deleted file mode 100644
index f0236df..0000000
--- a/src/gpu/GrPathRendererChain.cpp
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright 2011 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-
-#include "src/gpu/GrPathRendererChain.h"
-
-#include "include/gpu/GrDirectContext.h"
-#include "include/gpu/GrRecordingContext.h"
-#include "src/gpu/GrCaps.h"
-#include "src/gpu/GrDirectContextPriv.h"
-#include "src/gpu/GrGpu.h"
-#include "src/gpu/GrRecordingContextPriv.h"
-#include "src/gpu/GrShaderCaps.h"
-#include "src/gpu/geometry/GrStyledShape.h"
-#include "src/gpu/ops/AAConvexPathRenderer.h"
-#include "src/gpu/ops/AAHairLinePathRenderer.h"
-#include "src/gpu/ops/AALinearizingConvexPathRenderer.h"
-#include "src/gpu/ops/AtlasPathRenderer.h"
-#include "src/gpu/ops/DashLinePathRenderer.h"
-#include "src/gpu/ops/DefaultPathRenderer.h"
-#include "src/gpu/ops/SmallPathRenderer.h"
-#include "src/gpu/ops/TriangulatingPathRenderer.h"
-#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
-
-GrPathRendererChain::GrPathRendererChain(GrRecordingContext* context, const Options& options) {
-    const GrCaps& caps = *context->priv().caps();
-    if (options.fGpuPathRenderers & GpuPathRenderers::kDashLine) {
-        fChain.push_back(sk_make_sp<skgpu::v1::DashLinePathRenderer>());
-    }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kAAConvex) {
-        fChain.push_back(sk_make_sp<skgpu::v1::AAConvexPathRenderer>());
-    }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kAAHairline) {
-        fChain.push_back(sk_make_sp<skgpu::v1::AAHairLinePathRenderer>());
-    }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kAALinearizing) {
-        fChain.push_back(sk_make_sp<skgpu::v1::AALinearizingConvexPathRenderer>());
-    }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kAtlas) {
-        if (auto atlasPathRenderer = skgpu::v1::AtlasPathRenderer::Make(context)) {
-            fAtlasPathRenderer = atlasPathRenderer.get();
-            context->priv().addOnFlushCallbackObject(atlasPathRenderer.get());
-            fChain.push_back(std::move(atlasPathRenderer));
-        }
-    }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kSmall) {
-        fChain.push_back(sk_make_sp<skgpu::v1::SmallPathRenderer>());
-    }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kTriangulating) {
-        fChain.push_back(sk_make_sp<skgpu::v1::TriangulatingPathRenderer>());
-    }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kTessellation) {
-        if (GrTessellationPathRenderer::IsSupported(caps)) {
-            auto tess = sk_make_sp<GrTessellationPathRenderer>();
-            fTessellationPathRenderer = tess.get();
-            fChain.push_back(std::move(tess));
-        }
-    }
-
-    // We always include the default path renderer (as well as SW), so we can draw any path
-    fChain.push_back(sk_make_sp<skgpu::v1::DefaultPathRenderer>());
-}
-
-GrPathRenderer* GrPathRendererChain::getPathRenderer(
-        const GrPathRenderer::CanDrawPathArgs& args,
-        DrawType drawType,
-        GrPathRenderer::StencilSupport* stencilSupport) {
-    static_assert(GrPathRenderer::kNoSupport_StencilSupport <
-                  GrPathRenderer::kStencilOnly_StencilSupport);
-    static_assert(GrPathRenderer::kStencilOnly_StencilSupport <
-                  GrPathRenderer::kNoRestriction_StencilSupport);
-    GrPathRenderer::StencilSupport minStencilSupport;
-    if (DrawType::kStencil == drawType) {
-        minStencilSupport = GrPathRenderer::kStencilOnly_StencilSupport;
-    } else if (DrawType::kStencilAndColor == drawType) {
-        minStencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
-    } else {
-        minStencilSupport = GrPathRenderer::kNoSupport_StencilSupport;
-    }
-    if (minStencilSupport != GrPathRenderer::kNoSupport_StencilSupport) {
-        // We don't support (and shouldn't need) stenciling of non-fill paths.
-        if (!args.fShape->style().isSimpleFill()) {
-            return nullptr;
-        }
-    }
-
-    GrPathRenderer* bestPathRenderer = nullptr;
-    for (const sk_sp<GrPathRenderer>& pr : fChain) {
-        GrPathRenderer::StencilSupport support = GrPathRenderer::kNoSupport_StencilSupport;
-        if (GrPathRenderer::kNoSupport_StencilSupport != minStencilSupport) {
-            support = pr->getStencilSupport(*args.fShape);
-            if (support < minStencilSupport) {
-                continue;
-            }
-        }
-        GrPathRenderer::CanDrawPath canDrawPath = pr->canDrawPath(args);
-        if (GrPathRenderer::CanDrawPath::kNo == canDrawPath) {
-            continue;
-        }
-        if (GrPathRenderer::CanDrawPath::kAsBackup == canDrawPath && bestPathRenderer) {
-            continue;
-        }
-        if (stencilSupport) {
-            *stencilSupport = support;
-        }
-        bestPathRenderer = pr.get();
-        if (GrPathRenderer::CanDrawPath::kYes == canDrawPath) {
-            break;
-        }
-    }
-    return bestPathRenderer;
-}
diff --git a/src/gpu/GrRecordingContext.cpp b/src/gpu/GrRecordingContext.cpp
index 310797f..c1adcce 100644
--- a/src/gpu/GrRecordingContext.cpp
+++ b/src/gpu/GrRecordingContext.cpp
@@ -66,7 +66,7 @@
     }
 
 #if SK_GPU_V1
-    GrPathRendererChain::Options prcOptions;
+    skgpu::v1::PathRendererChain::Options prcOptions;
     prcOptions.fAllowPathMaskCaching = this->options().fAllowPathMaskCaching;
 #if GR_TEST_UTILS
     prcOptions.fGpuPathRenderers = this->options().fGpuPathRenderers;
diff --git a/src/gpu/ops/AAConvexPathRenderer.cpp b/src/gpu/ops/AAConvexPathRenderer.cpp
index a71beaa..fde56ce 100644
--- a/src/gpu/ops/AAConvexPathRenderer.cpp
+++ b/src/gpu/ops/AAConvexPathRenderer.cpp
@@ -910,7 +910,7 @@
 
 namespace skgpu::v1 {
 
-GrPathRenderer::CanDrawPath AAConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath AAConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     // This check requires convexity and known direction, since the direction is used to build
     // the geometry segments. Degenerate convex paths will fall through to some other path renderer.
     if (args.fCaps->shaderCaps()->shaderDerivativeSupport() &&
diff --git a/src/gpu/ops/AAConvexPathRenderer.h b/src/gpu/ops/AAConvexPathRenderer.h
index 6963fd6..5acaa0e 100644
--- a/src/gpu/ops/AAConvexPathRenderer.h
+++ b/src/gpu/ops/AAConvexPathRenderer.h
@@ -8,11 +8,11 @@
 #ifndef AAConvexPathRenderer_DEFINED
 #define AAConvexPathRenderer_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 namespace skgpu::v1 {
 
-class AAConvexPathRenderer final : public GrPathRenderer {
+class AAConvexPathRenderer final : public PathRenderer {
 public:
     AAConvexPathRenderer() = default;
 
@@ -22,8 +22,6 @@
     CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
 
     bool onDrawPath(const DrawPathArgs&) override;
-
-    using INHERITED = GrPathRenderer;
 };
 
 } // namespace skgpu::v1
diff --git a/src/gpu/ops/AAHairLinePathRenderer.cpp b/src/gpu/ops/AAHairLinePathRenderer.cpp
index 1643b8e..a008e87 100644
--- a/src/gpu/ops/AAHairLinePathRenderer.cpp
+++ b/src/gpu/ops/AAHairLinePathRenderer.cpp
@@ -1285,8 +1285,7 @@
 
 namespace skgpu::v1 {
 
-GrPathRenderer::CanDrawPath
-AAHairLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath AAHairLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     if (GrAAType::kCoverage != args.fAAType) {
         return CanDrawPath::kNo;
     }
diff --git a/src/gpu/ops/AAHairLinePathRenderer.h b/src/gpu/ops/AAHairLinePathRenderer.h
index 39c5646..9d69e40 100644
--- a/src/gpu/ops/AAHairLinePathRenderer.h
+++ b/src/gpu/ops/AAHairLinePathRenderer.h
@@ -8,11 +8,11 @@
 #ifndef AAHairLinePathRenderer_DEFINED
 #define AAHairLinePathRenderer_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 namespace skgpu::v1 {
 
-class AAHairLinePathRenderer final : public GrPathRenderer {
+class AAHairLinePathRenderer final : public PathRenderer {
 public:
     AAHairLinePathRenderer() = default;
 
@@ -22,8 +22,6 @@
     CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
 
     bool onDrawPath(const DrawPathArgs&) override;
-
-    using INHERITED = GrPathRenderer;
 };
 
 } // namespace skgpu::v1
diff --git a/src/gpu/ops/AALinearizingConvexPathRenderer.cpp b/src/gpu/ops/AALinearizingConvexPathRenderer.cpp
index 19e7c4e..584d7e6 100644
--- a/src/gpu/ops/AALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/AALinearizingConvexPathRenderer.cpp
@@ -375,7 +375,7 @@
 
 namespace skgpu::v1 {
 
-GrPathRenderer::CanDrawPath
+PathRenderer::CanDrawPath
 AALinearizingConvexPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     if (GrAAType::kCoverage != args.fAAType) {
         return CanDrawPath::kNo;
diff --git a/src/gpu/ops/AALinearizingConvexPathRenderer.h b/src/gpu/ops/AALinearizingConvexPathRenderer.h
index b047087..cd0a871 100644
--- a/src/gpu/ops/AALinearizingConvexPathRenderer.h
+++ b/src/gpu/ops/AALinearizingConvexPathRenderer.h
@@ -8,11 +8,11 @@
 #ifndef AALinearizingConvexPathRenderer_DEFINED
 #define AALinearizingConvexPathRenderer_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 namespace skgpu::v1 {
 
-class AALinearizingConvexPathRenderer final : public GrPathRenderer {
+class AALinearizingConvexPathRenderer final : public PathRenderer {
 public:
     AALinearizingConvexPathRenderer() = default;
 
@@ -22,8 +22,6 @@
     CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
 
     bool onDrawPath(const DrawPathArgs&) override;
-
-    using INHERITED = GrPathRenderer;
 };
 
 } // namespace skgpu::v1
diff --git a/src/gpu/ops/AtlasPathRenderer.cpp b/src/gpu/ops/AtlasPathRenderer.cpp
index a52db9a..88e5f85 100644
--- a/src/gpu/ops/AtlasPathRenderer.cpp
+++ b/src/gpu/ops/AtlasPathRenderer.cpp
@@ -254,7 +254,7 @@
     return true;
 }
 
-GrPathRenderer::CanDrawPath AtlasPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath AtlasPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
 #ifdef SK_DEBUG
     if (!fAtlasRenderTasks.empty()) {
         // args.fPaint should NEVER reference our current atlas. If it does, it means somebody
diff --git a/src/gpu/ops/AtlasPathRenderer.h b/src/gpu/ops/AtlasPathRenderer.h
index b9a0cfe..026b7b1 100644
--- a/src/gpu/ops/AtlasPathRenderer.h
+++ b/src/gpu/ops/AtlasPathRenderer.h
@@ -14,7 +14,7 @@
 #include "src/gpu/GrDynamicAtlas.h"
 #include "src/gpu/GrFragmentProcessor.h"
 #include "src/gpu/GrOnFlushResourceProvider.h"
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 class GrAtlasRenderTask;
 class GrOp;
@@ -23,7 +23,7 @@
 namespace skgpu::v1 {
 
 // Draws paths by first rendering their coverage mask into an offscreen atlas.
-class AtlasPathRenderer final : public GrPathRenderer, public GrOnFlushCallbackObject {
+class AtlasPathRenderer final : public PathRenderer, public GrOnFlushCallbackObject {
 public:
     static bool IsSupported(GrRecordingContext*);
 
diff --git a/src/gpu/ops/DashLinePathRenderer.cpp b/src/gpu/ops/DashLinePathRenderer.cpp
index 27992aa..d9e51125 100644
--- a/src/gpu/ops/DashLinePathRenderer.cpp
+++ b/src/gpu/ops/DashLinePathRenderer.cpp
@@ -16,7 +16,7 @@
 
 namespace skgpu::v1 {
 
-GrPathRenderer::CanDrawPath DashLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath DashLinePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     SkPoint pts[2];
     bool inverted;
     if (args.fShape->style().isDashed() && args.fShape->asLine(pts, &inverted)) {
diff --git a/src/gpu/ops/DashLinePathRenderer.h b/src/gpu/ops/DashLinePathRenderer.h
index ef4a885..fa1134b 100644
--- a/src/gpu/ops/DashLinePathRenderer.h
+++ b/src/gpu/ops/DashLinePathRenderer.h
@@ -8,13 +8,13 @@
 #ifndef DashLinePathRenderer_DEFINED
 #define DashLinePathRenderer_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 class GrGpu;
 
 namespace skgpu::v1 {
 
-class DashLinePathRenderer final : public GrPathRenderer {
+class DashLinePathRenderer final : public PathRenderer {
 public:
     DashLinePathRenderer() = default;
 
@@ -30,8 +30,6 @@
     bool onDrawPath(const DrawPathArgs&) override;
 
     sk_sp<GrGpu> fGpu;
-
-    using INHERITED = GrPathRenderer;
 };
 
 } // namespace skgpu::v1
diff --git a/src/gpu/ops/DefaultPathRenderer.cpp b/src/gpu/ops/DefaultPathRenderer.cpp
index 2f69421..dcb9112 100644
--- a/src/gpu/ops/DefaultPathRenderer.cpp
+++ b/src/gpu/ops/DefaultPathRenderer.cpp
@@ -27,6 +27,7 @@
 #include "src/gpu/geometry/GrPathUtils.h"
 #include "src/gpu/geometry/GrStyledShape.h"
 #include "src/gpu/ops/GrMeshDrawOp.h"
+#include "src/gpu/ops/GrPathStencilSettings.h"
 #include "src/gpu/ops/GrSimpleMeshDrawOpHelperWithStencil.h"
 #include "src/gpu/v1/SurfaceDrawContext_v1.h"
 
@@ -759,16 +760,16 @@
 }
 
 
-GrPathRenderer::StencilSupport
+PathRenderer::StencilSupport
 DefaultPathRenderer::onGetStencilSupport(const GrStyledShape& shape) const {
     if (single_pass_shape(shape)) {
-        return GrPathRenderer::kNoRestriction_StencilSupport;
+        return kNoRestriction_StencilSupport;
     } else {
-        return GrPathRenderer::kStencilOnly_StencilSupport;
+        return kStencilOnly_StencilSupport;
     }
 }
 
-GrPathRenderer::CanDrawPath DefaultPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath DefaultPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     bool isHairline = GrIsStrokeHairlineOrEquivalent(
             args.fShape->style(), *args.fViewMatrix, nullptr);
     // If we aren't a single_pass_shape or hairline, we require stencil buffers.
diff --git a/src/gpu/ops/DefaultPathRenderer.h b/src/gpu/ops/DefaultPathRenderer.h
index 974c3dd..afbe17f 100644
--- a/src/gpu/ops/DefaultPathRenderer.h
+++ b/src/gpu/ops/DefaultPathRenderer.h
@@ -8,9 +8,7 @@
 #ifndef DefaultPathRenderer_DEFINED
 #define DefaultPathRenderer_DEFINED
 
-#include "include/core/SkTypes.h"
-#include "src/gpu/GrPathRenderer.h"
-#include "src/gpu/ops/GrPathStencilSettings.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 namespace skgpu::v1 {
 
@@ -18,7 +16,7 @@
  *  Subclass that renders the path using the stencil buffer to resolve fill rules
  * (e.g. winding, even-odd)
  */
-class DefaultPathRenderer final : public GrPathRenderer {
+class DefaultPathRenderer final : public PathRenderer {
 public:
     DefaultPathRenderer() = default;
 
@@ -33,7 +31,7 @@
 
     void onStencilPath(const StencilPathArgs&) override;
 
-    bool internalDrawPath(skgpu::v1::SurfaceDrawContext*,
+    bool internalDrawPath(SurfaceDrawContext*,
                           GrPaint&&,
                           GrAAType,
                           const GrUserStencilSettings&,
@@ -41,8 +39,6 @@
                           const SkMatrix& viewMatrix,
                           const GrStyledShape&,
                           bool stencilOnly);
-
-    using INHERITED = GrPathRenderer;
 };
 
 } // namespace skgpu::v1
diff --git a/src/gpu/ops/SmallPathRenderer.cpp b/src/gpu/ops/SmallPathRenderer.cpp
index a8b8f3b..bc3c8c7 100644
--- a/src/gpu/ops/SmallPathRenderer.cpp
+++ b/src/gpu/ops/SmallPathRenderer.cpp
@@ -668,7 +668,7 @@
 
 namespace skgpu::v1 {
 
-GrPathRenderer::CanDrawPath SmallPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath SmallPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     if (!args.fCaps->shaderCaps()->shaderDerivativeSupport()) {
         return CanDrawPath::kNo;
     }
diff --git a/src/gpu/ops/SmallPathRenderer.h b/src/gpu/ops/SmallPathRenderer.h
index cb93b34..09a359f 100644
--- a/src/gpu/ops/SmallPathRenderer.h
+++ b/src/gpu/ops/SmallPathRenderer.h
@@ -8,15 +8,13 @@
 #ifndef SmallPathRenderer_DEFINED
 #define SmallPathRenderer_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
-class GrDrawOp;
-class GrRecordingContext;
 class GrStyledShape;
 
 namespace skgpu::v1 {
 
-class SmallPathRenderer final : public GrPathRenderer {
+class SmallPathRenderer final : public PathRenderer {
 public:
     SmallPathRenderer() = default;
 
@@ -24,14 +22,12 @@
 
 private:
     StencilSupport onGetStencilSupport(const GrStyledShape&) const override {
-        return GrPathRenderer::kNoSupport_StencilSupport;
+        return PathRenderer::kNoSupport_StencilSupport;
     }
 
     CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
 
     bool onDrawPath(const DrawPathArgs&) override;
-
-    using INHERITED = GrPathRenderer;
 };
 
 } // namespace skgpu::v1
diff --git a/src/gpu/ops/SoftwarePathRenderer.cpp b/src/gpu/ops/SoftwarePathRenderer.cpp
index 9c8b8a6..b2270c7 100644
--- a/src/gpu/ops/SoftwarePathRenderer.cpp
+++ b/src/gpu/ops/SoftwarePathRenderer.cpp
@@ -104,7 +104,7 @@
 namespace skgpu::v1 {
 
 ////////////////////////////////////////////////////////////////////////////////
-GrPathRenderer::CanDrawPath SoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath SoftwarePathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
     // Pass on any style that applies. The caller will apply the style if a suitable renderer is
     // not found and try again with the new GrStyledShape.
     if (!args.fShape->style().applies() && SkToBool(fProxyProvider) &&
diff --git a/src/gpu/ops/SoftwarePathRenderer.h b/src/gpu/ops/SoftwarePathRenderer.h
index 169bcdd..de1dc8c 100644
--- a/src/gpu/ops/SoftwarePathRenderer.h
+++ b/src/gpu/ops/SoftwarePathRenderer.h
@@ -8,8 +8,8 @@
 #ifndef SoftwarePathRenderer_DEFINED
 #define SoftwarePathRenderer_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
 #include "src/gpu/GrSurfaceProxyView.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 class GrProxyProvider;
 
@@ -19,7 +19,7 @@
  * This class uses the software side to render a path to an SkBitmap and
  * then uploads the result to the gpu
  */
-class SoftwarePathRenderer final : public GrPathRenderer {
+class SoftwarePathRenderer final : public PathRenderer {
 public:
     const char* name() const override { return "SW"; }
 
@@ -65,7 +65,7 @@
                                           const SkIRect& deviceSpaceRectToDraw);
 
     StencilSupport onGetStencilSupport(const GrStyledShape&) const override {
-        return GrPathRenderer::kNoSupport_StencilSupport;
+        return PathRenderer::kNoSupport_StencilSupport;
     }
 
     CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
@@ -75,8 +75,6 @@
 private:
     GrProxyProvider* fProxyProvider;
     bool             fAllowCaching;
-
-    using INHERITED = GrPathRenderer;
 };
 
 } // namespace skgpu::v1
diff --git a/src/gpu/ops/TriangulatingPathRenderer.cpp b/src/gpu/ops/TriangulatingPathRenderer.cpp
index 15e450f..c958f00 100644
--- a/src/gpu/ops/TriangulatingPathRenderer.cpp
+++ b/src/gpu/ops/TriangulatingPathRenderer.cpp
@@ -572,8 +572,9 @@
     : fMaxVerbCount(GR_AA_TESSELLATOR_MAX_VERB_COUNT) {
 }
 
-GrPathRenderer::CanDrawPath
-TriangulatingPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
+PathRenderer::CanDrawPath TriangulatingPathRenderer::onCanDrawPath(
+        const CanDrawPathArgs& args) const {
+
     // Don't use this path renderer with dynamic MSAA. DMSAA tries to not rely on caching.
     if (args.fSurfaceProps->flags() & SkSurfaceProps::kDynamicMSAA_Flag) {
         return CanDrawPath::kNo;
diff --git a/src/gpu/ops/TriangulatingPathRenderer.h b/src/gpu/ops/TriangulatingPathRenderer.h
index db73792..93d3fce 100644
--- a/src/gpu/ops/TriangulatingPathRenderer.h
+++ b/src/gpu/ops/TriangulatingPathRenderer.h
@@ -8,7 +8,7 @@
 #ifndef TriangulatingPathRenderer_DEFINED
 #define TriangulatingPathRenderer_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 namespace skgpu::v1 {
 
@@ -16,7 +16,7 @@
  *  Subclass that renders the path by converting to screen-space trapezoids plus
  *  extra 1-pixel geometry for AA.
  */
-class TriangulatingPathRenderer final : public GrPathRenderer {
+class TriangulatingPathRenderer final : public PathRenderer {
 public:
     TriangulatingPathRenderer();
 #if GR_TEST_UTILS
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.cpp b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
index 06a6cd0..7334cfb 100644
--- a/src/gpu/tessellate/GrTessellationPathRenderer.cpp
+++ b/src/gpu/tessellate/GrTessellationPathRenderer.cpp
@@ -27,7 +27,7 @@
            !caps.disableTessellationPathRenderer();
 }
 
-GrPathRenderer::StencilSupport GrTessellationPathRenderer::onGetStencilSupport(
+skgpu::v1::PathRenderer::StencilSupport GrTessellationPathRenderer::onGetStencilSupport(
         const GrStyledShape& shape) const {
     if (!shape.style().isSimpleFill() || shape.inverseFilled()) {
         // Don't bother with stroke stencilling or inverse fills yet. The Skia API doesn't support
@@ -37,7 +37,7 @@
     return shape.knownToBeConvex() ? kNoRestriction_StencilSupport : kStencilOnly_StencilSupport;
 }
 
-GrPathRenderer::CanDrawPath GrTessellationPathRenderer::onCanDrawPath(
+skgpu::v1::PathRenderer::CanDrawPath GrTessellationPathRenderer::onCanDrawPath(
         const CanDrawPathArgs& args) const {
     const GrStyledShape& shape = *args.fShape;
     if (args.fAAType == GrAAType::kCoverage ||
diff --git a/src/gpu/tessellate/GrTessellationPathRenderer.h b/src/gpu/tessellate/GrTessellationPathRenderer.h
index 6a97f0e..b5921e6 100644
--- a/src/gpu/tessellate/GrTessellationPathRenderer.h
+++ b/src/gpu/tessellate/GrTessellationPathRenderer.h
@@ -9,7 +9,7 @@
 #define GrTessellationPathRenderer_DEFINED
 
 #include "include/gpu/GrTypes.h"
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 class GrCaps;
 
@@ -17,7 +17,7 @@
 // paths using a hybrid Red Book "stencil, then cover" method. Curves get linearized by GPU
 // tessellation shaders. This path renderer doesn't apply analytic AA, so it requires MSAA if AA is
 // desired.
-class GrTessellationPathRenderer final : public GrPathRenderer {
+class GrTessellationPathRenderer final : public skgpu::v1::PathRenderer {
 public:
     static bool IsSupported(const GrCaps&);
 
diff --git a/src/gpu/GrPathRenderer.cpp b/src/gpu/v1/PathRenderer.cpp
similarity index 83%
rename from src/gpu/GrPathRenderer.cpp
rename to src/gpu/v1/PathRenderer.cpp
index c2d5a9c..c9a40ae 100644
--- a/src/gpu/GrPathRenderer.cpp
+++ b/src/gpu/v1/PathRenderer.cpp
@@ -5,7 +5,7 @@
  * found in the LICENSE file.
  */
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 #include "include/gpu/GrRecordingContext.h"
 #include "src/core/SkDrawProcs.h"
@@ -14,10 +14,14 @@
 #include "src/gpu/GrRecordingContextPriv.h"
 #include "src/gpu/GrUserStencilSettings.h"
 #include "src/gpu/geometry/GrStyledShape.h"
+#ifdef SK_DEBUG
 #include "src/gpu/v1/SurfaceDrawContext_v1.h"
+#endif
+
+namespace skgpu::v1 {
 
 #ifdef SK_DEBUG
-void GrPathRenderer::StencilPathArgs::validate() const {
+void PathRenderer::StencilPathArgs::validate() const {
     SkASSERT(fContext);
     SkASSERT(fSurfaceDrawContext);
     SkASSERT(fClipConservativeBounds);
@@ -32,9 +36,7 @@
 
 //////////////////////////////////////////////////////////////////////////////
 
-GrPathRenderer::GrPathRenderer() {}
-
-GrPathRenderer::StencilSupport GrPathRenderer::getStencilSupport(const GrStyledShape& shape) const {
+PathRenderer::StencilSupport PathRenderer::getStencilSupport(const GrStyledShape& shape) const {
     SkDEBUGCODE(SkPath path;)
     SkDEBUGCODE(shape.asPath(&path);)
     SkASSERT(shape.style().isSimpleFill());
@@ -42,7 +44,7 @@
     return this->onGetStencilSupport(shape);
 }
 
-bool GrPathRenderer::drawPath(const DrawPathArgs& args) {
+bool PathRenderer::drawPath(const DrawPathArgs& args) {
 #ifdef SK_DEBUG
     args.validate();
     CanDrawPathArgs canArgs;
@@ -68,10 +70,10 @@
     return this->onDrawPath(args);
 }
 
-void GrPathRenderer::GetPathDevBounds(const SkPath& path,
-                                      SkISize devSize,
-                                      const SkMatrix& matrix,
-                                      SkRect* bounds) {
+void PathRenderer::GetPathDevBounds(const SkPath& path,
+                                    SkISize devSize,
+                                    const SkMatrix& matrix,
+                                    SkRect* bounds) {
     if (path.isInverseFillType()) {
         *bounds = SkRect::Make(devSize);
         return;
@@ -80,7 +82,7 @@
     matrix.mapRect(bounds);
 }
 
-void GrPathRenderer::onStencilPath(const StencilPathArgs& args) {
+void PathRenderer::onStencilPath(const StencilPathArgs& args) {
     static constexpr GrUserStencilSettings kIncrementStencil(
             GrUserStencilSettings::StaticInit<
                     0xffff,
@@ -104,3 +106,5 @@
                           false};
     this->drawPath(drawArgs);
 }
+
+} // namespace skgpu::v1
diff --git a/src/gpu/GrPathRenderer.h b/src/gpu/v1/PathRenderer.h
similarity index 84%
rename from src/gpu/GrPathRenderer.h
rename to src/gpu/v1/PathRenderer.h
index 5d3ef9e..290c495 100644
--- a/src/gpu/GrPathRenderer.h
+++ b/src/gpu/v1/PathRenderer.h
@@ -5,8 +5,8 @@
  * found in the LICENSE file.
  */
 
-#ifndef GrPathRenderer_DEFINED
-#define GrPathRenderer_DEFINED
+#ifndef PathRenderer_DEFINED
+#define PathRenderer_DEFINED
 
 #include "include/core/SkRefCnt.h"
 #include "include/private/GrTypesPriv.h"
@@ -17,7 +17,6 @@
 class GrHardClip;
 class GrPaint;
 class GrRecordingContext;
-namespace skgpu { namespace v1 { class SurfaceDrawContext; }}
 class GrRenderTargetProxy;
 class GrStyledShape;
 class GrStyle;
@@ -27,12 +26,16 @@
 class SkPath;
 class SkSurfaceProps;
 
+namespace skgpu::v1 {
+
+class SurfaceDrawContext;
+
 /**
  *  Base class for drawing paths into a GrOpsTask.
  */
-class GrPathRenderer : public SkRefCnt {
+class PathRenderer : public SkRefCnt {
 public:
-    GrPathRenderer();
+    PathRenderer() = default;
 
     virtual const char* name() const = 0;
 
@@ -43,7 +46,7 @@
      * covered by bounding geometry but outside the path. These exterior pixels would still be
      * rendered into the stencil.
      *
-     * A GrPathRenderer can provide three levels of support for stenciling paths:
+     * A PathRenderer can provide three levels of support for stenciling paths:
      * 1) kNoRestriction: This is the most general. The caller passes a GrPaint and calls drawPath().
      *                    The path is rendered exactly as the draw state indicates including support
      *                    for simultaneous color and stenciling with arbitrary stenciling rules.
@@ -113,16 +116,16 @@
     }
 
     struct DrawPathArgs {
-        GrRecordingContext*            fContext;
-        GrPaint&&                      fPaint;
-        const GrUserStencilSettings*   fUserStencilSettings;
-        skgpu::v1::SurfaceDrawContext* fSurfaceDrawContext;
-        const GrClip*                  fClip;
-        const SkIRect*                 fClipConservativeBounds;
-        const SkMatrix*                fViewMatrix;
-        const GrStyledShape*           fShape;
-        GrAAType                       fAAType;
-        bool                           fGammaCorrect;
+        GrRecordingContext*          fContext;
+        GrPaint&&                    fPaint;
+        const GrUserStencilSettings* fUserStencilSettings;
+        SurfaceDrawContext*          fSurfaceDrawContext;
+        const GrClip*                fClip;
+        const SkIRect*               fClipConservativeBounds;
+        const SkMatrix*              fViewMatrix;
+        const GrStyledShape*         fShape;
+        GrAAType                     fAAType;
+        bool                         fGammaCorrect;
 #ifdef SK_DEBUG
         void validate() const {
             SkASSERT(fContext);
@@ -146,13 +149,13 @@
     struct StencilPathArgs {
         SkDEBUGCODE(StencilPathArgs() { memset(this, 0, sizeof(*this)); }) // For validation.
 
-        GrRecordingContext*            fContext;
-        skgpu::v1::SurfaceDrawContext* fSurfaceDrawContext;
-        const GrHardClip*              fClip;
-        const SkIRect*                 fClipConservativeBounds;
-        const SkMatrix*                fViewMatrix;
-        const GrStyledShape*           fShape;
-        GrAA                           fDoStencilMSAA;
+        GrRecordingContext*  fContext;
+        SurfaceDrawContext*  fSurfaceDrawContext;
+        const GrHardClip*    fClip;
+        const SkIRect*       fClipConservativeBounds;
+        const SkMatrix*      fViewMatrix;
+        const GrStyledShape* fShape;
+        GrAA                 fDoStencilMSAA;
 
         SkDEBUGCODE(void validate() const);
     };
@@ -202,4 +205,6 @@
     using INHERITED = SkRefCnt;
 };
 
-#endif
+} // namespace skgpu::v1
+
+#endif // PathRenderer_DEFINED
diff --git a/src/gpu/v1/PathRendererChain.cpp b/src/gpu/v1/PathRendererChain.cpp
new file mode 100644
index 0000000..55b2696
--- /dev/null
+++ b/src/gpu/v1/PathRendererChain.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2011 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+
+#include "src/gpu/v1/PathRendererChain.h"
+
+#include "include/gpu/GrDirectContext.h"
+#include "include/gpu/GrRecordingContext.h"
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrDirectContextPriv.h"
+#include "src/gpu/GrGpu.h"
+#include "src/gpu/GrRecordingContextPriv.h"
+#include "src/gpu/GrShaderCaps.h"
+#include "src/gpu/geometry/GrStyledShape.h"
+#include "src/gpu/ops/AAConvexPathRenderer.h"
+#include "src/gpu/ops/AAHairLinePathRenderer.h"
+#include "src/gpu/ops/AALinearizingConvexPathRenderer.h"
+#include "src/gpu/ops/AtlasPathRenderer.h"
+#include "src/gpu/ops/DashLinePathRenderer.h"
+#include "src/gpu/ops/DefaultPathRenderer.h"
+#include "src/gpu/ops/SmallPathRenderer.h"
+#include "src/gpu/ops/TriangulatingPathRenderer.h"
+#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
+
+namespace skgpu::v1 {
+
+PathRendererChain::PathRendererChain(GrRecordingContext* context, const Options& options) {
+    const GrCaps& caps = *context->priv().caps();
+    if (options.fGpuPathRenderers & GpuPathRenderers::kDashLine) {
+        fChain.push_back(sk_make_sp<DashLinePathRenderer>());
+    }
+    if (options.fGpuPathRenderers & GpuPathRenderers::kAAConvex) {
+        fChain.push_back(sk_make_sp<AAConvexPathRenderer>());
+    }
+    if (options.fGpuPathRenderers & GpuPathRenderers::kAAHairline) {
+        fChain.push_back(sk_make_sp<AAHairLinePathRenderer>());
+    }
+    if (options.fGpuPathRenderers & GpuPathRenderers::kAALinearizing) {
+        fChain.push_back(sk_make_sp<AALinearizingConvexPathRenderer>());
+    }
+    if (options.fGpuPathRenderers & GpuPathRenderers::kAtlas) {
+        if (auto atlasPathRenderer = AtlasPathRenderer::Make(context)) {
+            fAtlasPathRenderer = atlasPathRenderer.get();
+            context->priv().addOnFlushCallbackObject(atlasPathRenderer.get());
+            fChain.push_back(std::move(atlasPathRenderer));
+        }
+    }
+    if (options.fGpuPathRenderers & GpuPathRenderers::kSmall) {
+        fChain.push_back(sk_make_sp<SmallPathRenderer>());
+    }
+    if (options.fGpuPathRenderers & GpuPathRenderers::kTriangulating) {
+        fChain.push_back(sk_make_sp<TriangulatingPathRenderer>());
+    }
+    if (options.fGpuPathRenderers & GpuPathRenderers::kTessellation) {
+        if (GrTessellationPathRenderer::IsSupported(caps)) {
+            auto tess = sk_make_sp<GrTessellationPathRenderer>();
+            fTessellationPathRenderer = tess.get();
+            fChain.push_back(std::move(tess));
+        }
+    }
+
+    // We always include the default path renderer (as well as SW), so we can draw any path
+    fChain.push_back(sk_make_sp<DefaultPathRenderer>());
+}
+
+PathRenderer* PathRendererChain::getPathRenderer(const PathRenderer::CanDrawPathArgs& args,
+                                                 DrawType drawType,
+                                                 PathRenderer::StencilSupport* stencilSupport) {
+    static_assert(PathRenderer::kNoSupport_StencilSupport <
+                  PathRenderer::kStencilOnly_StencilSupport);
+    static_assert(PathRenderer::kStencilOnly_StencilSupport <
+                  PathRenderer::kNoRestriction_StencilSupport);
+    PathRenderer::StencilSupport minStencilSupport;
+    if (DrawType::kStencil == drawType) {
+        minStencilSupport = PathRenderer::kStencilOnly_StencilSupport;
+    } else if (DrawType::kStencilAndColor == drawType) {
+        minStencilSupport = PathRenderer::kNoRestriction_StencilSupport;
+    } else {
+        minStencilSupport = PathRenderer::kNoSupport_StencilSupport;
+    }
+    if (minStencilSupport != PathRenderer::kNoSupport_StencilSupport) {
+        // We don't support (and shouldn't need) stenciling of non-fill paths.
+        if (!args.fShape->style().isSimpleFill()) {
+            return nullptr;
+        }
+    }
+
+    PathRenderer* bestPathRenderer = nullptr;
+    for (const sk_sp<PathRenderer>& pr : fChain) {
+        PathRenderer::StencilSupport support = PathRenderer::kNoSupport_StencilSupport;
+        if (PathRenderer::kNoSupport_StencilSupport != minStencilSupport) {
+            support = pr->getStencilSupport(*args.fShape);
+            if (support < minStencilSupport) {
+                continue;
+            }
+        }
+        PathRenderer::CanDrawPath canDrawPath = pr->canDrawPath(args);
+        if (PathRenderer::CanDrawPath::kNo == canDrawPath) {
+            continue;
+        }
+        if (PathRenderer::CanDrawPath::kAsBackup == canDrawPath && bestPathRenderer) {
+            continue;
+        }
+        if (stencilSupport) {
+            *stencilSupport = support;
+        }
+        bestPathRenderer = pr.get();
+        if (PathRenderer::CanDrawPath::kYes == canDrawPath) {
+            break;
+        }
+    }
+    return bestPathRenderer;
+}
+
+} // namespace skgpu::v1
diff --git a/src/gpu/GrPathRendererChain.h b/src/gpu/v1/PathRendererChain.h
similarity index 71%
rename from src/gpu/GrPathRendererChain.h
rename to src/gpu/v1/PathRendererChain.h
index 8310aca..c25de35 100644
--- a/src/gpu/GrPathRendererChain.h
+++ b/src/gpu/v1/PathRendererChain.h
@@ -5,10 +5,10 @@
  * found in the LICENSE file.
  */
 
-#ifndef GrPathRendererChain_DEFINED
-#define GrPathRendererChain_DEFINED
+#ifndef PathRendererChain_DEFINED
+#define PathRendererChain_DEFINED
 
-#include "src/gpu/GrPathRenderer.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 #include "include/core/SkTypes.h"
 #include "include/private/GrTypesPriv.h"
@@ -18,19 +18,21 @@
 namespace skgpu { namespace v1 { class AtlasPathRenderer; }}
 class GrTessellationPathRenderer;
 
+namespace skgpu::v1 {
+
 /**
  * Keeps track of an ordered list of path renderers. When a path needs to be
  * drawn this list is scanned to find the most preferred renderer. To add your
  * path renderer to the list implement the GrPathRenderer::AddPathRenderers
  * function.
  */
-class GrPathRendererChain : public SkNoncopyable {
+class PathRendererChain : public SkNoncopyable {
 public:
     struct Options {
         bool fAllowPathMaskCaching = false;
         GpuPathRenderers fGpuPathRenderers = GpuPathRenderers::kDefault;
     };
-    GrPathRendererChain(GrRecordingContext* context, const Options&);
+    PathRendererChain(GrRecordingContext*, const Options&);
 
     /** Documents how the caller plans to use a GrPathRenderer to draw a path. It affects the PR
         returned by getPathRenderer */
@@ -44,9 +46,9 @@
         is drawing the path to the stencil buffer then stencilSupport can be used to determine
         whether the path can be rendered with arbitrary stencil rules or not. See comments on
         StencilSupport in GrPathRenderer.h. */
-    GrPathRenderer* getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
-                                    DrawType drawType,
-                                    GrPathRenderer::StencilSupport* stencilSupport);
+    PathRenderer* getPathRenderer(const PathRenderer::CanDrawPathArgs&,
+                                  DrawType,
+                                  PathRenderer::StencilSupport*);
 
     /** Returns a direct pointer to the atlas path renderer, or null if it is not in the
         chain. */
@@ -56,7 +58,7 @@
 
     /** Returns a direct pointer to the tessellation path renderer, or null if it is not in the
         chain. */
-    GrPathRenderer* getTessellationPathRenderer() {
+    PathRenderer* getTessellationPathRenderer() {
         return fTessellationPathRenderer;
     }
 
@@ -64,9 +66,11 @@
     enum {
         kPreAllocCount = 8,
     };
-    SkSTArray<kPreAllocCount, sk_sp<GrPathRenderer>> fChain;
-    skgpu::v1::AtlasPathRenderer*                    fAtlasPathRenderer = nullptr;
-    GrPathRenderer*                                  fTessellationPathRenderer = nullptr;
+    SkSTArray<kPreAllocCount, sk_sp<PathRenderer>> fChain;
+    AtlasPathRenderer*                             fAtlasPathRenderer = nullptr;
+    PathRenderer*                                  fTessellationPathRenderer = nullptr;
 };
 
-#endif
+} // namespace skgpu::v1
+
+#endif // PathRendererChain_DEFINED
diff --git a/src/gpu/v1/StencilMaskHelper.cpp b/src/gpu/v1/StencilMaskHelper.cpp
index 3e398c7..8ebe3e0 100644
--- a/src/gpu/v1/StencilMaskHelper.cpp
+++ b/src/gpu/v1/StencilMaskHelper.cpp
@@ -255,11 +255,11 @@
 // This returns a null-terminated list of const GrUserStencilSettings*
 GrUserStencilSettings const* const* get_stencil_passes(
         SkRegion::Op op,
-        GrPathRenderer::StencilSupport stencilSupport,
+        skgpu::v1::PathRenderer::StencilSupport stencilSupport,
         bool fillInverted,
         bool* drawDirectToClip) {
     bool canRenderDirectToStencil =
-            GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport;
+            skgpu::v1::PathRenderer::kNoRestriction_StencilSupport == stencilSupport;
 
     // TODO: inverse fill + intersect op can be direct.
     // TODO: this can be greatly simplified when we only need intersect and difference ops and
@@ -288,39 +288,40 @@
 
 void draw_path(GrRecordingContext* rContext,
                skgpu::v1::SurfaceDrawContext* sdc,
-               GrPathRenderer* pr,
+               skgpu::v1::PathRenderer* pr,
                const GrHardClip& clip,
                const SkIRect& bounds,
                const GrUserStencilSettings* ss,
                const SkMatrix& matrix,
-               const GrStyledShape& shape, GrAA aa) {
+               const GrStyledShape& shape,
+               GrAA aa) {
     GrPaint paint;
     paint.setXPFactory(GrDisableColorXPFactory::Get());
 
     // kMSAA is the only type of AA that's possible on a stencil buffer.
     GrAAType pathAAType = aa == GrAA::kYes ? GrAAType::kMSAA : GrAAType::kNone;
 
-    GrPathRenderer::DrawPathArgs args{rContext,
-                                      std::move(paint),
-                                      ss,
-                                      sdc,
-                                      &clip,
-                                      &bounds,
-                                      &matrix,
-                                      &shape,
-                                      pathAAType,
-                                      false};
+    skgpu::v1::PathRenderer::DrawPathArgs args{rContext,
+                                               std::move(paint),
+                                               ss,
+                                               sdc,
+                                               &clip,
+                                               &bounds,
+                                               &matrix,
+                                               &shape,
+                                               pathAAType,
+                                               false};
     pr->drawPath(args);
 }
 
 void stencil_path(GrRecordingContext* rContext,
                   skgpu::v1::SurfaceDrawContext* sdc,
-                  GrPathRenderer* pr,
+                  skgpu::v1::PathRenderer* pr,
                   const GrFixedClip& clip,
                   const SkMatrix& matrix,
                   const GrStyledShape& shape,
                   GrAA aa) {
-    GrPathRenderer::StencilPathArgs args;
+    skgpu::v1::PathRenderer::StencilPathArgs args;
     args.fContext = rContext;
     args.fSurfaceDrawContext = sdc;
     args.fClip = &clip;
@@ -373,8 +374,8 @@
     }
 
     bool drawDirectToClip;
-    auto passes = get_stencil_passes(op, GrPathRenderer::kNoRestriction_StencilSupport, false,
-                                     &drawDirectToClip);
+    auto passes = get_stencil_passes(op, PathRenderer::kNoRestriction_StencilSupport,
+                                     false, &drawDirectToClip);
     aa = supported_aa(fSDC, aa);
 
     if (!drawDirectToClip) {
@@ -411,7 +412,7 @@
 
     // This will be used to determine whether the clip shape can be rendered into the
     // stencil with arbitrary stencil settings.
-    GrPathRenderer::StencilSupport stencilSupport;
+    PathRenderer::StencilSupport stencilSupport;
 
     // Make path canonical with regards to fill type (inverse handled by stencil settings).
     bool fillInverted = path.isInverseFillType();
@@ -423,7 +424,7 @@
     GrStyledShape shape(*clipPath, GrStyle::SimpleFill());
     SkASSERT(!shape.inverseFilled());
 
-    GrPathRenderer::CanDrawPathArgs canDrawArgs;
+    PathRenderer::CanDrawPathArgs canDrawArgs;
     canDrawArgs.fCaps = fContext->priv().caps();
     canDrawArgs.fProxy = fSDC->asRenderTargetProxy();
     canDrawArgs.fClipConservativeBounds = &fClip.fixedClip().scissorRect();
@@ -434,8 +435,8 @@
     canDrawArgs.fAAType = pathAAType;
     canDrawArgs.fHasUserStencilSettings = false;
 
-    GrPathRenderer* pr =  fContext->priv().drawingManager()->getPathRenderer(
-            canDrawArgs, false, GrPathRendererChain::DrawType::kStencil, &stencilSupport);
+    auto pr =  fContext->priv().drawingManager()->getPathRenderer(
+            canDrawArgs, false, PathRendererChain::DrawType::kStencil, &stencilSupport);
     if (!pr) {
         return false;
     }
@@ -445,7 +446,7 @@
 
     // Write to client bits if necessary
     if (!drawDirectToClip) {
-        if (stencilSupport == GrPathRenderer::kNoRestriction_StencilSupport) {
+        if (stencilSupport == PathRenderer::kNoRestriction_StencilSupport) {
             draw_path(fContext, fSDC, pr, fClip.fixedClip(), fClip.fixedClip().scissorRect(),
                       &gDrawToStencil, matrix, shape, aa);
         } else {
diff --git a/src/gpu/v1/SurfaceDrawContext.cpp b/src/gpu/v1/SurfaceDrawContext.cpp
index 7df3cfc..b756b2b 100644
--- a/src/gpu/v1/SurfaceDrawContext.cpp
+++ b/src/gpu/v1/SurfaceDrawContext.cpp
@@ -37,7 +37,6 @@
 #include "src/gpu/GrImageContextPriv.h"
 #include "src/gpu/GrImageInfo.h"
 #include "src/gpu/GrMemoryPool.h"
-#include "src/gpu/GrPathRenderer.h"
 #include "src/gpu/GrProxyProvider.h"
 #include "src/gpu/GrRenderTarget.h"
 #include "src/gpu/GrResourceProvider.h"
@@ -69,6 +68,7 @@
 #include "src/gpu/ops/GrTextureOp.h"
 #include "src/gpu/text/GrSDFTControl.h"
 #include "src/gpu/text/GrTextBlobCache.h"
+#include "src/gpu/v1/PathRenderer.h"
 
 #define ASSERT_OWNED_RESOURCE(R) SkASSERT(!(R) || (R)->getContext() == this->drawingManager()->getContext())
 #define ASSERT_SINGLE_OWNER        GR_ASSERT_SINGLE_OWNER(this->singleOwner())
@@ -925,7 +925,7 @@
                               : SkIRect::MakeSize(this->dimensions());
     GrStyledShape shape(path, GrStyledShape::DoSimplify::kNo);
 
-    GrPathRenderer::CanDrawPathArgs canDrawArgs;
+    PathRenderer::CanDrawPathArgs canDrawArgs;
     canDrawArgs.fCaps = fContext->priv().caps();
     canDrawArgs.fProxy = this->asRenderTargetProxy();
     canDrawArgs.fClipConservativeBounds = &clipBounds;
@@ -935,14 +935,15 @@
     canDrawArgs.fSurfaceProps = &fSurfaceProps;
     canDrawArgs.fAAType = (doStencilMSAA == GrAA::kYes) ? GrAAType::kMSAA : GrAAType::kNone;
     canDrawArgs.fHasUserStencilSettings = false;
-    GrPathRenderer* pr = this->drawingManager()->getPathRenderer(
-            canDrawArgs, false, GrPathRendererChain::DrawType::kStencil);
+    auto pr = this->drawingManager()->getPathRenderer(canDrawArgs,
+                                                      false,
+                                                      PathRendererChain::DrawType::kStencil);
     if (!pr) {
         SkDebugf("WARNING: No path renderer to stencil path.\n");
         return false;
     }
 
-    GrPathRenderer::StencilPathArgs args;
+    PathRenderer::StencilPathArgs args;
     args.fContext = fContext;
     args.fSurfaceDrawContext = this;
     args.fClip = clip;
@@ -1629,7 +1630,7 @@
     paint.setCoverageSetOpXPFactory(op, invert);
 
     GrStyledShape shape(path, GrStyle::SimpleFill());
-    GrPathRenderer::CanDrawPathArgs canDrawArgs;
+    PathRenderer::CanDrawPathArgs canDrawArgs;
     canDrawArgs.fCaps = this->caps();
     canDrawArgs.fProxy = this->asRenderTargetProxy();
     canDrawArgs.fViewMatrix = &viewMatrix;
@@ -1640,23 +1641,26 @@
     canDrawArgs.fAAType = aaType;
     canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings;
 
+    using DrawType = PathRendererChain::DrawType;
+
     // Don't allow the SW renderer
-    GrPathRenderer* pr = this->drawingManager()->getPathRenderer(
-            canDrawArgs, false, GrPathRendererChain::DrawType::kStencilAndColor);
+    auto pr = this->drawingManager()->getPathRenderer(canDrawArgs,
+                                                      false,
+                                                      DrawType::kStencilAndColor);
     if (!pr) {
         return false;
     }
 
-    GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
-                                      std::move(paint),
-                                      ss,
-                                      this,
-                                      clip,
-                                      &clipConservativeBounds,
-                                      &viewMatrix,
-                                      &shape,
-                                      aaType,
-                                      this->colorInfo().isLinearlyBlended()};
+    PathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
+                                    std::move(paint),
+                                    ss,
+                                    this,
+                                    clip,
+                                    &clipConservativeBounds,
+                                    &viewMatrix,
+                                    &shape,
+                                    aaType,
+                                    this->colorInfo().isLinearlyBlended()};
     pr->drawPath(args);
     return true;
 }
@@ -1801,7 +1805,7 @@
     // Always allow paths to trigger DMSAA.
     GrAAType aaType = fCanUseDynamicMSAA ? GrAAType::kMSAA : this->chooseAAType(aa);
 
-    GrPathRenderer::CanDrawPathArgs canDrawArgs;
+    PathRenderer::CanDrawPathArgs canDrawArgs;
     canDrawArgs.fCaps = this->caps();
     canDrawArgs.fProxy = this->asRenderTargetProxy();
     canDrawArgs.fViewMatrix = &viewMatrix;
@@ -1814,14 +1818,14 @@
 
     constexpr static bool kDisallowSWPathRenderer = false;
     constexpr static bool kAllowSWPathRenderer = true;
-    using DrawType = GrPathRendererChain::DrawType;
+    using DrawType = PathRendererChain::DrawType;
 
-    GrPathRenderer* pr = nullptr;
+    PathRenderer* pr = nullptr;
 
     if (!shape.style().strokeRec().isFillStyle() && !shape.isEmpty()) {
         // Give the tessellation path renderer a chance to claim this stroke before we simplify it.
-        GrPathRenderer* tess = this->drawingManager()->getTessellationPathRenderer();
-        if (tess && tess->canDrawPath(canDrawArgs) == GrPathRenderer::CanDrawPath::kYes) {
+        PathRenderer* tess = this->drawingManager()->getTessellationPathRenderer();
+        if (tess && tess->canDrawPath(canDrawArgs) == PathRenderer::CanDrawPath::kYes) {
             pr = tess;
         }
     }
@@ -1886,16 +1890,16 @@
         return;
     }
 
-    GrPathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
-                                      std::move(paint),
-                                      &GrUserStencilSettings::kUnused,
-                                      this,
-                                      clip,
-                                      &clipConservativeBounds,
-                                      &viewMatrix,
-                                      canDrawArgs.fShape,
-                                      aaType,
-                                      this->colorInfo().isLinearlyBlended()};
+    PathRenderer::DrawPathArgs args{this->drawingManager()->getContext(),
+                                    std::move(paint),
+                                    &GrUserStencilSettings::kUnused,
+                                    this,
+                                    clip,
+                                    &clipConservativeBounds,
+                                    &viewMatrix,
+                                    canDrawArgs.fShape,
+                                    aaType,
+                                    this->colorInfo().isLinearlyBlended()};
     pr->drawPath(args);
 }
 
diff --git a/tests/PathRendererCacheTests.cpp b/tests/PathRendererCacheTests.cpp
index c602bbe..70cc02e 100644
--- a/tests/PathRendererCacheTests.cpp
+++ b/tests/PathRendererCacheTests.cpp
@@ -33,7 +33,7 @@
 static void draw_path(GrRecordingContext* rContext,
                       skgpu::v1::SurfaceDrawContext* sdc,
                       const SkPath& path,
-                      GrPathRenderer* pr,
+                      skgpu::v1::PathRenderer* pr,
                       GrAAType aaType,
                       const GrStyle& style,
                       float scaleX = 1.f) {
@@ -48,16 +48,16 @@
     }
     SkMatrix matrix = SkMatrix::I();
     matrix.setScaleX(scaleX);
-    GrPathRenderer::DrawPathArgs args{rContext,
-                                      std::move(paint),
-                                      &GrUserStencilSettings::kUnused,
-                                      sdc,
-                                      nullptr,
-                                      &clipConservativeBounds,
-                                      &matrix,
-                                      &shape,
-                                      aaType,
-                                      false};
+    skgpu::v1::PathRenderer::DrawPathArgs args{rContext,
+                                               std::move(paint),
+                                               &GrUserStencilSettings::kUnused,
+                                               sdc,
+                                               nullptr,
+                                               &clipConservativeBounds,
+                                               &matrix,
+                                               &shape,
+                                               aaType,
+                                               false};
     pr->drawPath(args);
 }
 
@@ -73,7 +73,7 @@
 
 static void test_path(skiatest::Reporter* reporter,
                       std::function<SkPath(void)> createPath,
-                      std::function<GrPathRenderer*(GrRecordingContext*)> createPathRenderer,
+                      std::function<skgpu::v1::PathRenderer*(GrRecordingContext*)> makePathRenderer,
                       int expected,
                       bool checkListeners,
                       GrAAType aaType = GrAAType::kNone,
@@ -90,7 +90,7 @@
         return;
     }
 
-    sk_sp<GrPathRenderer> pathRenderer(createPathRenderer(dContext.get()));
+    sk_sp<skgpu::v1::PathRenderer> pathRenderer(makePathRenderer(dContext.get()));
     SkPath path = createPath();
 
     // Initially, cache only has the render target context
diff --git a/tests/TriangulatingPathRendererTests.cpp b/tests/TriangulatingPathRendererTests.cpp
index 715d0a9..cef34a6 100644
--- a/tests/TriangulatingPathRendererTests.cpp
+++ b/tests/TriangulatingPathRendererTests.cpp
@@ -727,16 +727,16 @@
     SkIRect clipConservativeBounds = SkIRect::MakeWH(sdc->width(), sdc->height());
     GrStyle style(SkStrokeRec::kFill_InitStyle);
     GrStyledShape shape(path, style);
-    GrPathRenderer::DrawPathArgs args{rContext,
-                                      std::move(paint),
-                                      &GrUserStencilSettings::kUnused,
-                                      sdc,
-                                      nullptr,
-                                      &clipConservativeBounds,
-                                      &matrix,
-                                      &shape,
-                                      aaType,
-                                      false};
+    skgpu::v1::PathRenderer::DrawPathArgs args{rContext,
+                                               std::move(paint),
+                                               &GrUserStencilSettings::kUnused,
+                                               sdc,
+                                               nullptr,
+                                               &clipConservativeBounds,
+                                               &matrix,
+                                               &shape,
+                                               aaType,
+                                               false};
     pr.drawPath(args);
 }