ccpr: Add an MSAA atlas mode

Adds the option to use a multisampled (or mixed sampled) atlas, and
uses the sample mask and stencil buffer instead of coverage counts.

Bug: skia:
Change-Id: I9fb76d17895ae25208124f6c27e37977ac31b5eb
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/227428
Commit-Queue: Chris Dalton <csmartdalton@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/ccpr/GrCCFiller.cpp b/src/gpu/ccpr/GrCCFiller.cpp
index ba79a04..79fbc73 100644
--- a/src/gpu/ccpr/GrCCFiller.cpp
+++ b/src/gpu/ccpr/GrCCFiller.cpp
@@ -20,8 +20,10 @@
 using TriPointInstance = GrCCCoverageProcessor::TriPointInstance;
 using QuadPointInstance = GrCCCoverageProcessor::QuadPointInstance;
 
-GrCCFiller::GrCCFiller(int numPaths, int numSkPoints, int numSkVerbs, int numConicWeights)
-        : fGeometry(numSkPoints, numSkVerbs, numConicWeights)
+GrCCFiller::GrCCFiller(Algorithm algorithm, int numPaths, int numSkPoints, int numSkVerbs,
+                       int numConicWeights)
+        : fAlgorithm(algorithm)
+        , fGeometry(numSkPoints, numSkVerbs, numConicWeights)
         , fPathInfos(numPaths)
         , fScissorSubBatches(numPaths)
         , fTotalPrimitiveCounts{PrimitiveTallies(), PrimitiveTallies()} {
@@ -100,8 +102,9 @@
     int64_t tessellationWork = (int64_t)numVerbs * (32 - SkCLZ(numVerbs)); // N log N.
     int64_t fanningWork = (int64_t)clippedDevIBounds.height() * clippedDevIBounds.width();
     if (tessellationWork * (50*50) + (100*100) < fanningWork) { // Don't tessellate under 100x100.
-        fPathInfos.back().tessellateFan(fGeometry, currPathVerbsIdx, currPathPointsIdx,
-                                        clippedDevIBounds, &currPathPrimitiveCounts);
+        fPathInfos.back().tessellateFan(
+                fAlgorithm, path, fGeometry, currPathVerbsIdx, currPathPointsIdx, clippedDevIBounds,
+                &currPathPrimitiveCounts);
     }
 
     fTotalPrimitiveCounts[(int)scissorTest] += currPathPrimitiveCounts;
@@ -113,9 +116,10 @@
     }
 }
 
-void GrCCFiller::PathInfo::tessellateFan(const GrCCFillGeometry& geometry, int verbsIdx,
-                                         int ptsIdx, const SkIRect& clippedDevIBounds,
-                                         PrimitiveTallies* newTriangleCounts) {
+void GrCCFiller::PathInfo::tessellateFan(
+        Algorithm algorithm, const SkPath& originalPath, const GrCCFillGeometry& geometry,
+        int verbsIdx, int ptsIdx, const SkIRect& clippedDevIBounds,
+        PrimitiveTallies* newTriangleCounts) {
     using Verb = GrCCFillGeometry::Verb;
     SkASSERT(-1 == fFanTessellationCount);
     SkASSERT(!fFanTessellation);
@@ -126,11 +130,18 @@
     newTriangleCounts->fTriangles =
             newTriangleCounts->fWeightedTriangles = 0;
 
-    // Build an SkPath of the Redbook fan. We use "winding" fill type right now because we are
-    // producing a coverage count, and must fill in every region that has non-zero wind. The
-    // path processor will convert coverage count to the appropriate fill type later.
+    // Build an SkPath of the Redbook fan.
     SkPath fan;
-    fan.setFillType(SkPath::kWinding_FillType);
+    if (Algorithm::kCoverageCount == algorithm) {
+        // We use "winding" fill type right now because we are producing a coverage count, and must
+        // fill in every region that has non-zero wind. The path processor will convert coverage
+        // count to the appropriate fill type later.
+        fan.setFillType(SkPath::kWinding_FillType);
+    } else {
+        // When counting winding numbers in the stencil buffer, it works to just tessellate the
+        // Redbook fan with the same fill type as the path.
+        fan.setFillType(originalPath.getFillType());
+    }
     SkASSERT(Verb::kBeginPath == verbs[verbsIdx]);
     for (int i = verbsIdx + 1; i < verbs.count(); ++i) {
         switch (verbs[i]) {
@@ -192,10 +203,12 @@
             std::swap(vertices[i + 1].fPos, vertices[i + 2].fPos);
         }
 
-        if (1 == abs(tessWinding)) {
-            ++newTriangleCounts->fTriangles;
-        } else {
+        int weight = abs(tessWinding);
+        SkASSERT(SkPath::kEvenOdd_FillType != fan.getFillType() || weight == 1);
+        if (weight > 1 && Algorithm::kCoverageCount == algorithm) {
             ++newTriangleCounts->fWeightedTriangles;
+        } else {
+            newTriangleCounts->fTriangles += weight;
         }
     }
 
@@ -238,10 +251,10 @@
 // elements past the end for this method to use as scratch space.
 //
 // Returns the next triangle instance after the final one emitted.
-static TriPointInstance* emit_recursive_fan(const SkTArray<SkPoint, true>& pts,
-                                            SkTArray<int32_t, true>& indices, int firstIndex,
-                                            int indexCount, const Sk2f& devToAtlasOffset,
-                                            TriPointInstance out[]) {
+static TriPointInstance* emit_recursive_fan(
+        const SkTArray<SkPoint, true>& pts, SkTArray<int32_t, true>& indices, int firstIndex,
+        int indexCount, const Sk2f& devToAtlasOffset, TriPointInstance::Ordering ordering,
+        TriPointInstance out[]) {
     if (indexCount < 3) {
         return out;
     }
@@ -249,35 +262,42 @@
     int32_t oneThirdCount = indexCount / 3;
     int32_t twoThirdsCount = (2 * indexCount) / 3;
     out++->set(pts[indices[firstIndex]], pts[indices[firstIndex + oneThirdCount]],
-               pts[indices[firstIndex + twoThirdsCount]], devToAtlasOffset);
+               pts[indices[firstIndex + twoThirdsCount]], devToAtlasOffset, ordering);
 
-    out = emit_recursive_fan(pts, indices, firstIndex, oneThirdCount + 1, devToAtlasOffset, out);
-    out = emit_recursive_fan(pts, indices, firstIndex + oneThirdCount,
-                             twoThirdsCount - oneThirdCount + 1, devToAtlasOffset, out);
+    out = emit_recursive_fan(
+            pts, indices, firstIndex, oneThirdCount + 1, devToAtlasOffset, ordering, out);
+    out = emit_recursive_fan(
+            pts, indices, firstIndex + oneThirdCount, twoThirdsCount - oneThirdCount + 1,
+            devToAtlasOffset, ordering, out);
 
     int endIndex = firstIndex + indexCount;
     int32_t oldValue = indices[endIndex];
     indices[endIndex] = indices[firstIndex];
-    out = emit_recursive_fan(pts, indices, firstIndex + twoThirdsCount,
-                             indexCount - twoThirdsCount + 1, devToAtlasOffset, out);
+    out = emit_recursive_fan(
+            pts, indices, firstIndex + twoThirdsCount, indexCount - twoThirdsCount + 1,
+            devToAtlasOffset, ordering, out);
     indices[endIndex] = oldValue;
 
     return out;
 }
 
-static void emit_tessellated_fan(const GrTessellator::WindingVertex* vertices, int numVertices,
-                                 const Sk2f& devToAtlasOffset,
-                                 TriPointInstance* triPointInstanceData,
-                                 QuadPointInstance* quadPointInstanceData,
-                                 GrCCFillGeometry::PrimitiveTallies* indices) {
+void GrCCFiller::emitTessellatedFan(
+        const GrTessellator::WindingVertex* vertices, int numVertices, const Sk2f& devToAtlasOffset,
+        TriPointInstance::Ordering ordering, TriPointInstance* triPointInstanceData,
+        QuadPointInstance* quadPointInstanceData, GrCCFillGeometry::PrimitiveTallies* indices) {
     for (int i = 0; i < numVertices; i += 3) {
-        if (1 == abs(vertices[i].fWinding)) {
-            triPointInstanceData[indices->fTriangles++].set(vertices[i].fPos, vertices[i + 1].fPos,
-                                                            vertices[i + 2].fPos, devToAtlasOffset);
-        } else {
+        int weight = abs(vertices[i].fWinding);
+        SkASSERT(weight >= 1);
+        if (weight > 1 && Algorithm::kStencilWindingCount != fAlgorithm) {
             quadPointInstanceData[indices->fWeightedTriangles++].setW(
                     vertices[i].fPos, vertices[i+1].fPos, vertices[i + 2].fPos, devToAtlasOffset,
                     static_cast<float>(abs(vertices[i].fWinding)));
+        } else for (int j = 0; j < weight; ++j) {
+            // Unfortunately, there is not a way to increment stencil values by an amount larger
+            // than 1. Instead we draw the triangle 'weight' times.
+            triPointInstanceData[indices->fTriangles++].set(
+                    vertices[i].fPos, vertices[i + 1].fPos, vertices[i + 2].fPos, devToAtlasOffset,
+                    ordering);
         }
     }
 }
@@ -289,6 +309,10 @@
              fTotalPrimitiveCounts[(int)GrScissorTest::kDisabled]);
     SkASSERT(fBatches.back().fEndScissorSubBatchIdx == fScissorSubBatches.count());
 
+    auto triangleOrdering = (Algorithm::kCoverageCount == fAlgorithm)
+            ? TriPointInstance::Ordering::kXYTransposed
+            : TriPointInstance::Ordering::kXYInterleaved;
+
     // Here we build a single instance buffer to share with every internal batch.
     //
     // CCPR processs 3 different types of primitives: triangles, quadratics, cubics. Each primitive
@@ -359,9 +383,10 @@
                                         static_cast<float>(nextPathInfo->devToAtlasOffset().fY));
                 currFanIsTessellated = nextPathInfo->hasFanTessellation();
                 if (currFanIsTessellated) {
-                    emit_tessellated_fan(nextPathInfo->fanTessellation(),
-                                         nextPathInfo->fanTessellationCount(), devToAtlasOffset,
-                                         triPointInstanceData, quadPointInstanceData, currIndices);
+                    this->emitTessellatedFan(
+                            nextPathInfo->fanTessellation(), nextPathInfo->fanTessellationCount(),
+                            devToAtlasOffset, triangleOrdering, triPointInstanceData,
+                            quadPointInstanceData, currIndices);
                 }
                 ++nextPathInfo;
                 continue;
@@ -383,8 +408,8 @@
                 continue;
 
             case Verb::kMonotonicQuadraticTo:
-                triPointInstanceData[currIndices->fQuadratics++].set(&pts[ptsIdx],
-                                                                     devToAtlasOffset);
+                triPointInstanceData[currIndices->fQuadratics++].set(
+                        &pts[ptsIdx], devToAtlasOffset, TriPointInstance::Ordering::kXYTransposed);
                 ptsIdx += 2;
                 if (!currFanIsTessellated) {
                     SkASSERT(!currFan.empty());
@@ -393,8 +418,8 @@
                 continue;
 
             case Verb::kMonotonicCubicTo:
-                quadPointInstanceData[currIndices->fCubics++].set(&pts[ptsIdx], devToAtlasOffset[0],
-                                                                  devToAtlasOffset[1]);
+                quadPointInstanceData[currIndices->fCubics++].set(
+                        &pts[ptsIdx], devToAtlasOffset[0], devToAtlasOffset[1]);
                 ptsIdx += 3;
                 if (!currFanIsTessellated) {
                     SkASSERT(!currFan.empty());
@@ -427,9 +452,9 @@
                     // Reserve space for emit_recursive_fan. Technically this can grow to
                     // fanSize + log3(fanSize), but we approximate with log2.
                     currFan.push_back_n(SkNextLog2(fanSize));
-                    SkDEBUGCODE(TriPointInstance* end =)
-                            emit_recursive_fan(pts, currFan, 0, fanSize, devToAtlasOffset,
-                                               triPointInstanceData + currIndices->fTriangles);
+                    SkDEBUGCODE(TriPointInstance* end =) emit_recursive_fan(
+                            pts, currFan, 0, fanSize, devToAtlasOffset, triangleOrdering,
+                            triPointInstanceData + currIndices->fTriangles);
                     currIndices->fTriangles += fanSize - 2;
                     SkASSERT(triPointInstanceData + currIndices->fTriangles == end);
                 }
@@ -459,8 +484,9 @@
     return true;
 }
 
-void GrCCFiller::drawFills(GrOpFlushState* flushState, GrCCCoverageProcessor* proc,
-                           BatchID batchID, const SkIRect& drawBounds) const {
+void GrCCFiller::drawFills(
+        GrOpFlushState* flushState, GrCCCoverageProcessor* proc, const GrPipeline& pipeline,
+        BatchID batchID, const SkIRect& drawBounds) const {
     using PrimitiveType = GrCCCoverageProcessor::PrimitiveType;
 
     SkASSERT(fInstanceBuffer);
@@ -468,9 +494,6 @@
     GrResourceProvider* rp = flushState->resourceProvider();
     const PrimitiveTallies& batchTotalCounts = fBatches[batchID].fTotalPrimitiveCounts;
 
-    GrPipeline pipeline(GrScissorTest::kEnabled, SkBlendMode::kPlus,
-                        flushState->drawOpArgs().fOutputSwizzle);
-
     if (batchTotalCounts.fTriangles) {
         proc->reset(PrimitiveType::kTriangles, rp);
         this->drawPrimitives(
@@ -478,6 +501,7 @@
     }
 
     if (batchTotalCounts.fWeightedTriangles) {
+        SkASSERT(Algorithm::kStencilWindingCount != fAlgorithm);
         proc->reset(PrimitiveType::kWeightedTriangles, rp);
         this->drawPrimitives(
                 flushState, *proc, pipeline, batchID, &PrimitiveTallies::fWeightedTriangles,