Reland "Reland "Reland "Use conics with w=Inf to describe triangles for the tessellator"""

This is a reland of 99e6f0fcfb44ab9de58d927b30dd6ddd16dd861e

Original change's description:
> Reland "Reland "Use conics with w=Inf to describe triangles for the tessellator""
>
> This is a reland of ff515df5b4549673b4c7f04e41c62f2bd1d4ddc3
>
> Original change's description:
> > Reland "Use conics with w=Inf to describe triangles for the tessellator"
> >
> > This is a reland of 84f70136abfb0af3cddf2ec7e8e2405f154916b0
> >
> > Original change's description:
> > > Use conics with w=Inf to describe triangles for the tessellator
> > >
> > > Previously, only the indirect tessellator could draw triangles, and
> > > only with special index data. Using conics with w=Inf will allow us to
> > > draw triangles with the hardware tessellator as well, in addition to
> > > being able to wean the indirect tessellator off an index buffer.
> > >
> > > Bug: skia:10419
> > > Bug: chromium:1202607
> > > Change-Id: I180af9cb5410c0e0bb25a2edcfb01e17d4a2f590
> > > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/406977
> > > Commit-Queue: Chris Dalton <csmartdalton@google.com>
> > > Reviewed-by: Michael Ludwig <michaelludwig@google.com>
> >
> > Bug: skia:10419
> > Bug: chromium:1202607
> > Change-Id: Ic12b10eaa60fddd212c66757bf7100749ee58d49
> > Reviewed-on: https://skia-review.googlesource.com/c/skia/+/408096
> > Reviewed-by: Robert Phillips <robertphillips@google.com>
> > Commit-Queue: Chris Dalton <csmartdalton@google.com>
>
> TBR=robertphillips@google.com
>
> Bug: skia:10419
> Bug: chromium:1202607
> Change-Id: Id1f8dfa133f446b9f30f2bf8493a3a7b99072e59
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/408616
> Reviewed-by: Chris Dalton <csmartdalton@google.com>
> Commit-Queue: Chris Dalton <csmartdalton@google.com>

Bug: skia:10419
Bug: chromium:1202607
Change-Id: Iadc60aae395146d5da5bfaa725b980c963e6bead
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/408817
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/bench/TessellateBench.cpp b/bench/TessellateBench.cpp
index e4a3d4a..032cd81 100644
--- a/bench/TessellateBench.cpp
+++ b/bench/TessellateBench.cpp
@@ -200,7 +200,8 @@
     int baseVertex;
     GrVertexWriter vertexWriter = static_cast<SkPoint*>(fTarget->makeVertexSpace(
             sizeof(SkPoint), kNumCubicsInChalkboard, &buffer, &baseVertex));
-    GrMiddleOutPolygonTriangulator::WritePathInnerFan(&vertexWriter, 3, fPath);
+    GrMiddleOutPolygonTriangulator::WritePathInnerFan(
+            &vertexWriter, GrMiddleOutPolygonTriangulator::OutputType::kTriangles, fPath);
 }
 
 using PathStrokeList = GrStrokeTessellator::PathStrokeList;
diff --git a/src/gpu/GrVertexWriter.h b/src/gpu/GrVertexWriter.h
index 4ca8b6b..110b351 100644
--- a/src/gpu/GrVertexWriter.h
+++ b/src/gpu/GrVertexWriter.h
@@ -23,6 +23,8 @@
  * thereof.
  */
 struct GrVertexWriter {
+    constexpr static uint32_t kIEEE_32_infinity = 0x7f800000;
+
     void* fPtr;
 
     GrVertexWriter() = default;
diff --git a/src/gpu/tessellate/GrFillPathShader.cpp b/src/gpu/tessellate/GrFillPathShader.cpp
index 6274845..71fd72d 100644
--- a/src/gpu/tessellate/GrFillPathShader.cpp
+++ b/src/gpu/tessellate/GrFillPathShader.cpp
@@ -72,16 +72,20 @@
                                            GrGLSLUniformHandler* uniformHandler) const {
     v->codeAppend(R"(
     float4x2 P = float4x2(input_points_0_1, input_points_2_3);
-    if (isinf(P[3].y)) {
-        // This curve is actually a conic. Convert the control points to a trapeziodal hull
-        // that circumcscribes the conic.
+    if (isinf(P[3].y)) {  // Is the curve a conic?
         float w = P[3].x;
-        float2 p1w = P[1] * w;
-        float T = .51;  // Bias outward a bit to ensure we cover the outermost samples.
-        float2 c1 = mix(P[0], p1w, T);
-        float2 c2 = mix(P[2], p1w, T);
-        float iw = 1 / mix(1, w, T);
-        P = float4x2(P[0], c1 * iw, c2 * iw, P[2]);
+        if (isinf(w)) {
+            // A conic with w=Inf is an exact triangle.
+            P = float4x2(P[0], P[1], P[2], P[2]);
+        } else {
+            // Convert the control points to a trapeziodal hull that circumcscribes the conic.
+            float2 p1w = P[1] * w;
+            float T = .51;  // Bias outward a bit to ensure we cover the outermost samples.
+            float2 c1 = mix(P[0], p1w, T);
+            float2 c2 = mix(P[2], p1w, T);
+            float iw = 1 / mix(1, w, T);
+            P = float4x2(P[0], c1 * iw, c2 * iw, P[2]);
+        }
     }
 
     // Translate the points to v0..3 where v0=0.
diff --git a/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h b/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h
index 6129dbb..79b80b3 100644
--- a/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h
+++ b/src/gpu/tessellate/GrMiddleOutPolygonTriangulator.h
@@ -43,10 +43,15 @@
 // recursion, we manipulate an O(log N) stack to determine the correct middle-out triangulation.
 class GrMiddleOutPolygonTriangulator {
 public:
-    GrMiddleOutPolygonTriangulator(GrVertexWriter* vertexWriter, int perTriangleVertexAdvance,
+    enum class OutputType : bool {
+        kTriangles,  // Output 3-vertex triangles.
+        kConicsWithInfiniteWeight  // Output 4-vertex conics with w=Inf.
+    };
+
+    GrMiddleOutPolygonTriangulator(GrVertexWriter* vertexWriter, OutputType outputType,
                                    int maxPushVertexCalls)
             : fVertexWriter(vertexWriter)
-            , fPaddingLength(std::max(perTriangleVertexAdvance - 3, 0)) {
+            , fOutputType(outputType) {
         // Determine the deepest our stack can ever go.
         int maxStackDepth = SkNextLog2(maxPushVertexCalls) + 1;
         if (maxStackDepth > kStackPreallocCount) {
@@ -118,10 +123,9 @@
         SkASSERT(fTop->fVertexIdxDelta == 0);  // Ensure we are in the initial stack state.
     }
 
-    static int WritePathInnerFan(GrVertexWriter* vertexWriter, int perTriangleVertexAdvance,
+    static int WritePathInnerFan(GrVertexWriter* vertexWriter, OutputType outputType,
                                  const SkPath& path) {
-        GrMiddleOutPolygonTriangulator middleOut(vertexWriter, perTriangleVertexAdvance,
-                                                 path.countVerbs());
+        GrMiddleOutPolygonTriangulator middleOut(vertexWriter, outputType, path.countVerbs());
         for (auto [verb, pts, w] : SkPathPriv::Iterate(path)) {
             switch (verb) {
                 case SkPathVerb::kMove:
@@ -165,8 +169,9 @@
         SkASSERT(fTop > fVertexStack);  // We should never pop the starting point.
         --fTop;
         fVertexWriter->write(fTop[0].fPoint, fTop[1].fPoint, lastPt);
-        if (fPaddingLength) {
-            fVertexWriter->fill(SkPoint{0,0}, fPaddingLength);
+        if (fOutputType == OutputType::kConicsWithInfiniteWeight) {
+            // Output a 4-point conic with w=Inf.
+            fVertexWriter->fill(GrVertexWriter::kIEEE_32_infinity, 2);
         }
     }
 
@@ -175,8 +180,8 @@
     SkDEBUGCODE(int fStackAllocCount;)
     StackVertex* fTop;
     GrVertexWriter* fVertexWriter;
-    int fPaddingLength;
     int fTotalClosedTriangleCount = 0;
+    OutputType fOutputType;
 };
 
 #endif
diff --git a/src/gpu/tessellate/GrPathShader.h b/src/gpu/tessellate/GrPathShader.h
index 345cf54..2784112 100644
--- a/src/gpu/tessellate/GrPathShader.h
+++ b/src/gpu/tessellate/GrPathShader.h
@@ -15,7 +15,6 @@
 #include "src/gpu/GrProgramInfo.h"
 #include "src/gpu/GrVertexWriter.h"
 #include "src/gpu/ops/GrSimpleMeshDrawOpHelper.h"
-#include <limits>
 
  // This is a common base class for shaders in the GPU tessellator.
 class GrPathShader : public GrGeometryProcessor {
@@ -58,7 +57,7 @@
         // Write out the 3 conic points to patch[0..2], the weight to patch[3].x, and then set
         // patch[3].y as NaN to flag this patch as a conic.
         writer->writeArray(pts, 3);
-        writer->write(w, std::numeric_limits<float>::infinity());
+        writer->write(w, GrVertexWriter::kIEEE_32_infinity);
     }
     static void WriteConicPatch(const SkPoint pts[3], float w, SkPoint patch[4]) {
         GrVertexWriter writer(patch);
diff --git a/src/gpu/tessellate/GrPathStencilFillOp.cpp b/src/gpu/tessellate/GrPathStencilFillOp.cpp
index 77b6c07..1e3d7cd 100644
--- a/src/gpu/tessellate/GrPathStencilFillOp.cpp
+++ b/src/gpu/tessellate/GrPathStencilFillOp.cpp
@@ -145,7 +145,8 @@
         int maxFanTriangles = fPath.countVerbs() - 2;  // n - 2 triangles make an n-gon.
         GrVertexWriter triangleVertexWriter = vertexAlloc.lock<SkPoint>(maxFanTriangles * 3);
         fFanVertexCount = GrMiddleOutPolygonTriangulator::WritePathInnerFan(
-                &triangleVertexWriter, 3/*perTriangleVertexAdvance*/, fPath) * 3;
+                &triangleVertexWriter, GrMiddleOutPolygonTriangulator::OutputType::kTriangles,
+                fPath) * 3;
         SkASSERT(fFanVertexCount <= maxFanTriangles * 3);
         vertexAlloc.unlock(fFanVertexCount);
     }
diff --git a/src/gpu/tessellate/GrPathTessellator.cpp b/src/gpu/tessellate/GrPathTessellator.cpp
index 586eb42..722cd41 100644
--- a/src/gpu/tessellate/GrPathTessellator.cpp
+++ b/src/gpu/tessellate/GrPathTessellator.cpp
@@ -73,11 +73,13 @@
         return;
     }
 
-    // Write out any triangles at the beginning of the cubic data.
+    // Write out any triangles at the beginning of the cubic data. Since this shader draws curves,
+    // output the triangles as conics with w=infinity (which is equivalent to a triangle).
     int numTrianglesAtBeginningOfData = 0;
     if (fDrawInnerFan) {
         numTrianglesAtBeginningOfData = GrMiddleOutPolygonTriangulator::WritePathInnerFan(
-                &instanceWriter, 4/*stride*/, path);
+                &instanceWriter,
+                GrMiddleOutPolygonTriangulator::OutputType::kConicsWithInfiniteWeight, path);
     }
     if (breadcrumbTriangleList) {
         SkDEBUGCODE(int count = 0;)
@@ -91,8 +93,8 @@
                 continue;
             }
             instanceWriter.writeArray(p, 3);
-            // Duplicate the final point since it will also be used by the convex hull shader.
-            instanceWriter.write(p[2]);
+            // Mark this instance as a triangle by setting it to a conic with w=Inf.
+            instanceWriter.fill(GrVertexWriter::kIEEE_32_infinity, 2);
             ++numTrianglesAtBeginningOfData;
         }
         SkASSERT(count == breadcrumbTriangleList->count());
diff --git a/src/gpu/tessellate/GrStencilPathShader.cpp b/src/gpu/tessellate/GrStencilPathShader.cpp
index 85b1f42..2959886 100644
--- a/src/gpu/tessellate/GrStencilPathShader.cpp
+++ b/src/gpu/tessellate/GrStencilPathShader.cpp
@@ -374,8 +374,8 @@
         args.fVertBuilder->insertFunction(kEvalRationalCubicFn);
         args.fVertBuilder->codeAppend(R"(
         float2 pos;
-        if (sk_VertexID > kMaxVertexID) {
-            // This is a special index value that instructs us to emit a specific point.
+        if (isinf(inputPoints_2_3.z)) {
+            // A conic with w=Inf is an exact triangle.
             pos = ((sk_VertexID & 3) == 0) ? inputPoints_0_1.xy :
                   ((sk_VertexID & 2) == 0) ? inputPoints_0_1.zw : inputPoints_2_3.xy;
         } else {