[graphite] Make stencil-and-cover stencil settings accessible

This is in preparation for additional tessellation-based RenderSteps.

Cq-Include-Trybots: luci.skia.skia.primary:Test-Mac12-Clang-MacBookPro16.2-GPU-IntelIrisPlus-x86_64-Debug-All-Graphite,Test-Mac11-Clang-MacMini9.1-GPU-AppleM1-arm64-Release-All-Graphite,Test-Mac11-Clang-MacMini9.1-GPU-AppleM1-arm64-Debug-All-ASAN_Graphite,Test-Mac10.15.7-Clang-MacBookPro11.5-GPU-RadeonHD8870M-x86_64-Debug-All-Graphite,Perf-Mac11-Clang-MacMini9.1-GPU-AppleM1-arm64-Release-All-Graphite,Perf-Mac10.15.7-Clang-MacBookPro11.5-GPU-RadeonHD8870M-x86_64-Release-All-Graphite,Build-Mac-Clang-x86_64-Release-Graphite,Build-Mac-Clang-x86_64-Debug-Graphite,Build-Mac-Clang-arm64-Release-iOS_Graphite,Build-Mac-Clang-arm64-Release-Graphite,Build-Mac-Clang-arm64-Debug-iOS_Graphite,Build-Mac-Clang-arm64-Debug-Graphite_NoGpu,Build-Mac-Clang-arm64-Debug-Graphite,Build-Mac-Clang-arm64-Debug-ASAN_Graphite
Bug: skia:12703
Change-Id: I497ea14802201be10535ee26147838b28ab6b34d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/521957
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/experimental/graphite/src/render/StencilAndCoverDSS.h b/experimental/graphite/src/render/StencilAndCoverDSS.h
new file mode 100644
index 0000000..a396ca8
--- /dev/null
+++ b/experimental/graphite/src/render/StencilAndCoverDSS.h
@@ -0,0 +1,128 @@
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef skgpu_render_StencilAndCoverDSS_DEFINED
+#define skgpu_render_StencilAndCoverDSS_DEFINED
+
+#include "experimental/graphite/src/DrawTypes.h"
+
+namespace skgpu {
+
+/**
+ * "stencil" pass DepthAndStencilSettings reusable for RenderSteps following some form of
+ * stencil-then-cover multi-pass algorithm.
+ */
+
+// Increments stencil value on clockwise triangles. Used for "winding" fill.
+constexpr DepthStencilSettings::Face kIncrementCW = {
+        /*stencilFail=*/   StencilOp::kKeep,
+        /*depthFail=*/     StencilOp::kKeep,
+        /*dsPass=*/        StencilOp::kIncWrap,
+        /*stencilCompare=*/CompareOp::kAlways,
+        /*readMask=*/      0xffffffff,
+        /*writeMask=*/     0xffffffff
+};
+
+// Decrements stencil value on counterclockwise triangles. Used for "winding" fill.
+constexpr DepthStencilSettings::Face kDecrementCCW = {
+        /*stencilFail=*/   StencilOp::kKeep,
+        /*depthFail=*/     StencilOp::kKeep,
+        /*dsPass=*/        StencilOp::kDecWrap,
+        /*stencilCompare=*/CompareOp::kAlways,
+        /*readMask=*/      0xffffffff,
+        /*writeMask=*/     0xffffffff
+};
+
+// Toggles the bottom stencil bit. Used for "even-odd" fill.
+constexpr DepthStencilSettings::Face kToggle = {
+        /*stencilFail=*/   StencilOp::kKeep,
+        /*depthFail=*/     StencilOp::kKeep,
+        /*dsPass=*/        StencilOp::kInvert,
+        /*stencilCompare=*/CompareOp::kAlways,
+        /*readMask=*/      0xffffffff,
+        /*writeMask=*/     0x00000001
+};
+
+// Stencil settings to use for a standard Redbook "stencil" pass corresponding to a "winding"
+// fill rule (regular or inverse is selected by a follow-up pass).
+constexpr DepthStencilSettings kWindingStencilPass = {
+        /*frontStencil=*/kIncrementCW,
+        /*backStencil=*/ kDecrementCCW,
+        /*refValue=*/    0,
+        /*stencilTest=*/ true,
+        /*depthCompare=*/CompareOp::kAlways, // TODO: kGreater once steps know the right depth value
+        /*depthTest=*/   true,
+        /*depthWrite=*/  false // The depth write will be handled by the covering pass
+};
+
+// Stencil settings to use for a standard Redbook "stencil" pass corresponding to an "even-odd"
+// fill rule (regular or inverse is selected by a follow-up pass).
+constexpr DepthStencilSettings kEvenOddStencilPass = {
+        /*frontStencil=*/kToggle,
+        /*backStencil=*/ kToggle,
+        /*refValue=*/    0,
+        /*stencilTest=*/ true,
+        /*depthCompare=*/CompareOp::kAlways, // TODO: kGreater once steps know the right depth value
+        /*depthTest=*/   true,
+        /*depthWrite=*/  false // The depth write will be handled by the covering pass
+};
+
+/**
+ * "cover" pass DepthAndStencilSettings reusable for RenderSteps following some form of
+ * stencil-then-cover multi-pass algorithm.
+ */
+
+// Resets non-zero bits to 0, passes when not zero. We set depthFail to kZero because if we
+// encounter that case, the kNotEqual=0 stencil test passed, so it does need to be set back to 0
+// and the dsPass op won't be run. In practice, since the stencil steps will fail the same depth
+// test, the stencil value will likely not be non-zero, but best to be explicit.
+constexpr DepthStencilSettings::Face kPassNonZero = {
+        /*stencilFail=*/   StencilOp::kKeep,
+        /*depthFail=*/     StencilOp::kZero,
+        /*dsPass=*/        StencilOp::kZero,
+        /*stencilCompare=*/CompareOp::kNotEqual,
+        /*readMask=*/      0xffffffff,
+        /*writeMask=*/     0xffffffff
+};
+
+ // Resets non-zero bits to 0, passes when zero.
+constexpr DepthStencilSettings::Face kPassZero = {
+        /*stencilFail=*/   StencilOp::kZero,
+        /*depthFail=*/     StencilOp::kKeep,
+        /*dsPass=*/        StencilOp::kKeep,
+        /*stencilCompare=*/CompareOp::kEqual,
+        /*readMask=*/      0xffffffff,
+        /*writeMask=*/     0xffffffff
+};
+
+// Stencil settings to use for a standard Redbook "cover" pass for a regular fill, assuming that the
+// stencil buffer has been modified by either kWindingStencilPass or kEvenOddStencilPass.
+constexpr DepthStencilSettings kRegularCoverPass = {
+        /*frontStencil=*/kPassNonZero,
+        /*frontStencil=*/kPassNonZero,
+        /*refValue=*/    0,
+        /*stencilTest=*/ true,
+        /*depthCompare=*/CompareOp::kAlways, // TODO: kGreater once steps know the right depth value
+        /*depthTest=*/   true,
+        /*depthWrite=*/  true
+};
+
+// Stencil settings to use for a standard Redbook "cover" pass for inverse fills, assuming that the
+// stencil buffer has been modified by either kWindingStencilPass or kEvenOddStencilPass.
+constexpr DepthStencilSettings kInverseCoverPass = {
+        /*frontStencil=*/kPassZero,
+        /*frontStencil=*/kPassZero,
+        /*refValue=*/    0,
+        /*stencilTest=*/ true,
+        /*depthCompare=*/CompareOp::kAlways, // TODO: kGreater once steps know the right depth value
+        /*depthTest=*/   true,
+        /*depthWrite=*/  true
+};
+
+}  // namespace skgpu
+
+#endif // skgpu_render_RedbookDepthAndStencilSettings
diff --git a/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp b/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp
index 26c6128..aedfd7e 100644
--- a/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp
+++ b/experimental/graphite/src/render/StencilAndFillPathRenderer.cpp
@@ -11,6 +11,7 @@
 #include "experimental/graphite/src/UniformManager.h"
 #include "experimental/graphite/src/geom/Shape.h"
 #include "experimental/graphite/src/geom/Transform_graphite.h"
+#include "experimental/graphite/src/render/StencilAndCoverDSS.h"
 #include "include/core/SkPathTypes.h"
 #include "include/core/SkRect.h"
 #include "src/core/SkUniformData.h"
@@ -25,119 +26,13 @@
 
 namespace {
 
-// TODO: These settings are actually shared by tessellating path renderers, so will be exposed later
-
-// Returns the stencil settings to use for a standard Redbook "stencil" pass.
-constexpr DepthStencilSettings fillrule_settings(bool evenOdd) {
-    // Increments clockwise triangles and decrements counterclockwise. Used for "winding" fill.
-    constexpr DepthStencilSettings::Face kIncCW = {
-        /*stencilFail=*/   StencilOp::kKeep,
-        /*depthFail=*/     StencilOp::kKeep,
-        /*dsPass=*/        StencilOp::kIncWrap,
-        /*stencilCompare=*/CompareOp::kAlways,
-        /*readMask=*/      0xffffffff,
-        /*writeMask=*/     0xffffffff
-    };
-    constexpr DepthStencilSettings::Face kDecCCW = {
-        /*stencilFail=*/   StencilOp::kKeep,
-        /*depthFail=*/     StencilOp::kKeep,
-        /*dsPass=*/        StencilOp::kDecWrap,
-        /*stencilCompare=*/CompareOp::kAlways,
-        /*readMask=*/      0xffffffff,
-        /*writeMask=*/     0xffffffff
-    };
-
-    // Toggles the bottom stencil bit. Used for "even-odd" fill.
-    constexpr DepthStencilSettings::Face kToggle = {
-        /*stencilFail=*/   StencilOp::kKeep,
-        /*depthFail=*/     StencilOp::kKeep,
-        /*dsPass=*/        StencilOp::kInvert,
-        /*stencilCompare=*/CompareOp::kAlways,
-        /*readMask=*/      0xffffffff,
-        /*writeMask=*/     0x00000001
-    };
-
-    // Always use ref = 0, disable depths, but still use greater depth test.
-    constexpr DepthStencilSettings kWindingFill = {
-        /*frontStencil=*/kIncCW,
-        /*backStencil=*/ kDecCCW,
-        /*refValue=*/    0,
-        /*stencilTest=*/ true,
-        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
-        /*depthTest=*/   true,
-        /*depthWrite=*/  false
-    };
-    constexpr DepthStencilSettings kEvenOddFill = {
-        /*frontStencil=*/kToggle,
-        /*backStencil=*/ kToggle,
-        /*refValue=*/    0,
-        /*stencilTest=*/ true,
-        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
-        /*depthTest=*/   true,
-        /*depthWrite=*/  false
-    };
-
-    return evenOdd ? kEvenOddFill : kWindingFill;
-}
-
-// Returns the stencil settings to use for a standard Redbook "fill" pass. Allows non-zero
-// stencil values to pass and write a color, and resets the stencil value back to zero; discards
-// immediately on stencil values of zero (or does the inverse of these operations when the path
-// requires filling everything else).
-constexpr DepthStencilSettings cover_settings(bool inverse) {
-    // Resets non-zero bits to 0, passes when not zero. We set depthFail to kZero because if we
-    // encounter that case, the kNotEqual=0 stencil test passed, so it does need to be set back to 0
-    // and the dsPass op won't be run. In practice, since the stencil steps will fail the same depth
-    // test, the stencil value will likely not be non-zero, but best to be explicit.
-    constexpr DepthStencilSettings::Face kNormal = {
-        /*stencilFail=*/   StencilOp::kKeep,
-        /*depthFail=*/     StencilOp::kZero,
-        /*dsPass=*/        StencilOp::kZero,
-        /*stencilCompare=*/CompareOp::kNotEqual,
-        /*readMask=*/      0xffffffff,
-        /*writeMask=*/     0xffffffff
-    };
-
-    // Resets non-zero bits to 0, passes when zero
-    constexpr DepthStencilSettings::Face kInverted = {
-        /*stencilFail=*/   StencilOp::kZero,
-        /*depthFail=*/     StencilOp::kKeep,
-        /*dsPass=*/        StencilOp::kKeep,
-        /*stencilCompare=*/CompareOp::kEqual,
-        /*readMask=*/      0xffffffff,
-        /*writeMask=*/     0xffffffff
-    };
-
-    // Always use ref = 0, enabled depth writes, and greater depth test, both
-    // front and back use the same stencil settings.
-    constexpr DepthStencilSettings kNormalDSS = {
-        /*frontStencil=*/kNormal,
-        /*frontStencil=*/kNormal,
-        /*refValue=*/    0,
-        /*stencilTest=*/ true,
-        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
-        /*depthTest=*/   true,
-        /*depthWrite=*/  true
-    };
-    constexpr DepthStencilSettings kInvertedDSS = {
-        /*frontStencil=*/kInverted,
-        /*backStencil=*/ kInverted,
-        /*refValue=*/    0,
-        /*stencilTest=*/ true,
-        /*depthCompare=*/CompareOp::kAlways, // kGreater once steps know the right depth value
-        /*depthTest=*/   true,
-        /*depthWrite=*/  true
-    };
-    return inverse ? kInvertedDSS : kNormalDSS;
-}
-
 class StencilFanRenderStep final : public RenderStep {
 public:
     StencilFanRenderStep(bool evenOdd)
             : RenderStep(Flags::kRequiresMSAA,
                          /*uniforms=*/{},
                          PrimitiveType::kTriangles,
-                         fillrule_settings(evenOdd),
+                         evenOdd ? kEvenOddStencilPass : kWindingStencilPass,
                          /*vertexAttrs=*/{{"position",
                                            VertexAttribType::kFloat3,
                                            SkSLType::kFloat3}},
@@ -232,7 +127,7 @@
             : RenderStep(Flags::kRequiresMSAA,
                          /*uniforms=*/{},
                          PrimitiveType::kTriangles,
-                         fillrule_settings(evenOdd),
+                         evenOdd ? kEvenOddStencilPass : kWindingStencilPass,
                          /*vertexAttrs=*/  {{"resolveLevel_and_idx",
                                              VertexAttribType::kFloat2, SkSLType::kFloat2}},
                          /*instanceAttrs=*/{{"p01", VertexAttribType::kFloat4, SkSLType::kFloat4},
@@ -400,7 +295,7 @@
             : RenderStep(Flags::kPerformsShading,
                          /*uniforms=*/{},
                          PrimitiveType::kTriangles,
-                         cover_settings(inverseFill),
+                         inverseFill ? kInverseCoverPass : kRegularCoverPass,
                          /*vertexAttrs=*/{{"position",
                                            VertexAttribType::kFloat3,
                                            SkSLType::kFloat3}},
diff --git a/gn/graphite.gni b/gn/graphite.gni
index 4966437..d7df823 100644
--- a/gn/graphite.gni
+++ b/gn/graphite.gni
@@ -108,6 +108,7 @@
   "$_src/geom/Transform.cpp",
   "$_src/geom/Transform_graphite.h",
   "$_src/geom/VectorTypes.h",
+  "$_src/render/StencilAndCoverDSS.h",
   "$_src/render/StencilAndFillPathRenderer.cpp",
 ]