Revert "Refactor stencil clip mask generation into helper"

This reverts commit 8b3a8a5238f5be31c4408c212d867f4765e3e29a.

Reason for revert: GM assert failure

Original change's description:
> Refactor stencil clip mask generation into helper
> 
> Change-Id: If3dc80efde3b44e87ba8e7af3a258896ec5e78e6
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/288977
> Commit-Queue: Michael Ludwig <michaelludwig@google.com>
> Reviewed-by: Chris Dalton <csmartdalton@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,csmartdalton@google.com,michaelludwig@google.com

Change-Id: I16559f791601145f57d147cdae345c200af313f1
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/289237
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/GrStencilSettings.cpp b/src/gpu/GrStencilSettings.cpp
index f57b7a4..6b73c16 100644
--- a/src/gpu/GrStencilSettings.cpp
+++ b/src/gpu/GrStencilSettings.cpp
@@ -220,16 +220,170 @@
     static_assert(0 == (int)GrStencilOp::kKeep);
 }
 
-static constexpr GrUserStencilSettings gZeroStencilClipBit(
+////////////////////////////////////////////////////////////////////////////////
+// Stencil Rules for Merging user stencil space into clip
+//
+
+///////
+// Replace
+static constexpr GrUserStencilSettings gUserToClipReplace(
     GrUserStencilSettings::StaticInit<
         0x0000,
-        GrUserStencilTest::kAlways,
+        GrUserStencilTest::kNotEqual,
         0xffff,
-        GrUserStencilOp::kZeroClipBit,
+        GrUserStencilOp::kSetClipAndReplaceUserBits,
+        GrUserStencilOp::kZeroClipAndUserBits,
+        0xffff>()
+);
+
+static constexpr GrUserStencilSettings gInvUserToClipReplace(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kEqual,
+        0xffff,
+        GrUserStencilOp::kSetClipAndReplaceUserBits,
+        GrUserStencilOp::kZeroClipAndUserBits,
+        0xffff>()
+);
+
+///////
+// Intersect
+static constexpr GrUserStencilSettings gUserToClipIsect(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kLessIfInClip, // "0 < userBits" is equivalent to "0 != userBits".
+        0xffff,
+        GrUserStencilOp::kSetClipAndReplaceUserBits,
+        GrUserStencilOp::kZeroClipAndUserBits,
+        0xffff>()
+);
+
+///////
+// Difference
+static constexpr GrUserStencilSettings gUserToClipDiff(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kEqualIfInClip,
+        0xffff,
+        GrUserStencilOp::kSetClipAndReplaceUserBits,
+        GrUserStencilOp::kZeroClipAndUserBits,
+        0xffff>()
+);
+
+///////
+// Union
+static constexpr GrUserStencilSettings gUserToClipUnion(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kNotEqual,
+        0xffff,
+        GrUserStencilOp::kSetClipAndReplaceUserBits,
+        GrUserStencilOp::kKeep,
+        0xffff>()
+);
+
+static constexpr GrUserStencilSettings gInvUserToClipUnionPass0( // Does not zero user bits.
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kEqual,
+        0xffff,
+        GrUserStencilOp::kSetClipBit,
+        GrUserStencilOp::kKeep,
+        0x0000>()
+);
+
+///////
+// Xor
+static constexpr GrUserStencilSettings gUserToClipXorPass0( // Does not zero user bits.
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kNotEqual,
+        0xffff,
+        GrUserStencilOp::kInvertClipBit,
+        GrUserStencilOp::kKeep,
+        0x0000>()
+);
+
+static constexpr GrUserStencilSettings gInvUserToClipXorPass0( // Does not zero user bits.
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kEqual,
+        0xffff,
+        GrUserStencilOp::kInvertClipBit,
+        GrUserStencilOp::kKeep,
+        0x0000>()
+);
+
+///////
+// Reverse Diff
+static constexpr GrUserStencilSettings gUserToClipRDiffPass0( // Does not zero user bits.
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kNotEqual,
+        0xffff,
+        GrUserStencilOp::kInvertClipBit,
         GrUserStencilOp::kZeroClipBit,
         0x0000>()
 );
-static constexpr GrUserStencilSettings gSetStencilClipBit(
+
+static constexpr GrUserStencilSettings gInvUserToClipRDiffPass0( // Does not zero user bits.
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kEqual,
+        0xffff,
+        GrUserStencilOp::kInvertClipBit,
+        GrUserStencilOp::kZeroClipBit,
+        0x0000>()
+);
+
+///////
+// Second pass to clear user bits (only needed sometimes)
+static constexpr GrUserStencilSettings gZeroUserBits(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kNotEqual,
+        0xffff,
+        GrUserStencilOp::kZero,
+        GrUserStencilOp::kKeep,
+        0xffff>()
+);
+
+static constexpr const GrUserStencilSettings* gUserToClipTable[2][1 + SkRegion::kLastOp][3] = {
+    {  /* Normal fill. */
+        {&gUserToClipDiff,           nullptr,         nullptr},  // kDifference_Op.
+        {&gUserToClipIsect,          nullptr,         nullptr},  // kIntersect_Op.
+        {&gUserToClipUnion,          nullptr,         nullptr},  // kUnion_Op.
+        {&gUserToClipXorPass0,       &gZeroUserBits,  nullptr},  // kXOR_Op.
+        {&gUserToClipRDiffPass0,     &gZeroUserBits,  nullptr},  // kReverseDifference_Op.
+        {&gUserToClipReplace,        nullptr,         nullptr}   // kReplace_Op.
+
+    }, /* Inverse fill. */ {
+        {&gUserToClipIsect,          nullptr,         nullptr},  // ~diff (aka isect).
+        {&gUserToClipDiff,           nullptr,         nullptr},  // ~isect (aka diff).
+        {&gInvUserToClipUnionPass0,  &gZeroUserBits,  nullptr},  // ~union.
+        {&gInvUserToClipXorPass0,    &gZeroUserBits,  nullptr},  // ~xor.
+        {&gInvUserToClipRDiffPass0,  &gZeroUserBits,  nullptr},  // ~reverse diff.
+        {&gInvUserToClipReplace,     nullptr,         nullptr}   // ~replace.
+    }
+};
+
+static_assert(0 == SkRegion::kDifference_Op);
+static_assert(1 == SkRegion::kIntersect_Op);
+static_assert(2 == SkRegion::kUnion_Op);
+static_assert(3 == SkRegion::kXOR_Op);
+static_assert(4 == SkRegion::kReverseDifference_Op);
+static_assert(5 == SkRegion::kReplace_Op);
+
+///////
+// Direct to Stencil
+
+// We can render a clip element directly without first writing to the client
+// portion of the clip when the fill is not inverse and the set operation will
+// only modify the in/out status of samples covered by the clip element.
+
+// this one only works if used right after stencil clip was cleared.
+// Our clip mask creation code doesn't allow midstream replace ops.
+static constexpr GrUserStencilSettings gReplaceClip(
     GrUserStencilSettings::StaticInit<
         0x0000,
         GrUserStencilTest::kAlways,
@@ -239,8 +393,80 @@
         0x0000>()
 );
 
+static constexpr GrUserStencilSettings gUnionClip(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kAlwaysIfInClip,
+        0xffff,
+        GrUserStencilOp::kKeep,
+        GrUserStencilOp::kSetClipBit,
+        0x0000>()
+);
+
+static constexpr GrUserStencilSettings gXorClip(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kAlways,
+        0xffff,
+        GrUserStencilOp::kInvertClipBit,
+        GrUserStencilOp::kInvertClipBit,
+        0x0000>()
+);
+
+static constexpr GrUserStencilSettings gDiffClip(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kAlwaysIfInClip,
+        0xffff,
+        GrUserStencilOp::kZeroClipBit,
+        GrUserStencilOp::kKeep,
+        0x0000>()
+);
+
+static constexpr const GrUserStencilSettings* gDirectDrawTable[1 + SkRegion::kLastOp][2] = {
+    {&gDiffClip,     nullptr},  // kDifference_Op.
+    {nullptr,        nullptr},  // kIntersect_Op.
+    {&gUnionClip,    nullptr},  // kUnion_Op.
+    {&gXorClip,      nullptr},  // kXOR_Op.
+    {nullptr,        nullptr},  // kReverseDifference_Op.
+    {&gReplaceClip,  nullptr}   // kReplace_Op.
+};
+
+static_assert(0 == SkRegion::kDifference_Op);
+static_assert(1 == SkRegion::kIntersect_Op);
+static_assert(2 == SkRegion::kUnion_Op);
+static_assert(3 == SkRegion::kXOR_Op);
+static_assert(4 == SkRegion::kReverseDifference_Op);
+static_assert(5 == SkRegion::kReplace_Op);
+
+GrUserStencilSettings const* const* GrStencilSettings::GetClipPasses(SkRegion::Op op,
+                                                                     bool canBeDirect,
+                                                                     bool invertedFill,
+                                                                     bool* drawDirectToClip) {
+    SkASSERT((unsigned)op <= SkRegion::kLastOp);
+    if (canBeDirect && !invertedFill) { // TODO: inverse fill + intersect op can be direct.
+        GrUserStencilSettings const* const* directPass = gDirectDrawTable[op];
+        if (directPass[0]) {
+            *drawDirectToClip = true;
+            return directPass;
+        }
+    }
+    *drawDirectToClip = false;
+    return gUserToClipTable[invertedFill][op];
+}
+
+static constexpr GrUserStencilSettings gZeroStencilClipBit(
+    GrUserStencilSettings::StaticInit<
+        0x0000,
+        GrUserStencilTest::kAlways,
+        0xffff,
+        GrUserStencilOp::kZeroClipBit,
+        GrUserStencilOp::kZeroClipBit,
+        0x0000>()
+);
+
 const GrUserStencilSettings* GrStencilSettings::SetClipBitSettings(bool setToInside) {
-    return setToInside ? &gSetStencilClipBit : &gZeroStencilClipBit;
+    return setToInside ? &gReplaceClip : &gZeroStencilClipBit;
 }
 
 void GrStencilSettings::genKey(GrProcessorKeyBuilder* b, bool includeRefs) const {