Implement stroking with GPU tessellation

Bootstraps tessellated stroking using GrStrokeGeometry mostly as
written. Strokes get decomposed into tessellation patches that
represent either a "cubic" (single stroked bezier curve with butt
caps) or a "join". The patches get drawn directly to the canvas
without any intermediate stencil steps. For the first revision, only
opaque, constant-color strokes are supported.

Bug: skia:10419
Change-Id: I601289189b93ebdf2f1efecd08628a6e0d9acb01
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/299142
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/tessellate/GrTessellateStrokeShader.h b/src/gpu/tessellate/GrTessellateStrokeShader.h
new file mode 100644
index 0000000..715e9f2
--- /dev/null
+++ b/src/gpu/tessellate/GrTessellateStrokeShader.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrTessellateStrokeShader_DEFINED
+#define GrTessellateStrokeShader_DEFINED
+
+#include "src/gpu/tessellate/GrPathShader.h"
+
+#include "src/gpu/tessellate/GrTessellationPathRenderer.h"
+
+class GrGLSLUniformHandler;
+
+// Tessellates a batch of stroke patches directly to the canvas. A patch is either a "cubic"
+// (single stroked bezier curve with butt caps) or a "join". A patch is defined by 5 points as
+// follows:
+//
+//   P0..P3      : Represent the cubic control points.
+//   (P4.x == 0) : The patch is a cubic and the shader decides how many linear segments to produce.
+//   (P4.x < 0)  : The patch is still a cubic, but will be linearized into exactly |P4.x| segments.
+//   (P4.x == 1) : The patch is an outer bevel join.
+//   (P4.x == 2) : The patch is an outer miter join.
+//   (P4.x == 3) : The patch is an outer round join.
+//   (P4.x == 4) : The patch is an inner and outer round join.
+//   P4.y        : Represents the stroke radius.
+//
+// If a patch is a join, P0 must equal P3, P1 must equal the control point coming into the junction,
+// and P2 must equal the control point going out. It's imperative that a junction's control points
+// match the control points of their neighbor cubics exactly, or the rasterization might not be
+// water tight. (Also note that if P1==P0 or P2==P3, the junction needs to be given its neighbor's
+// opposite cubic control point.)
+//
+// To use this shader, construct a GrProgramInfo with a primitiveType of "kPatches" and a
+// tessellationPatchVertexCount of 5.
+class GrTessellateStrokeShader : public GrPathShader {
+public:
+    GrTessellateStrokeShader(const SkMatrix& viewMatrix, float miterLimit, SkPMColor4f color)
+            : GrPathShader(kTessellate_GrTessellateStrokeShader_ClassID, viewMatrix,
+                           GrPrimitiveType::kPatches, 5)
+            , fMiterLimit(miterLimit)
+            , fColor(color) {
+        constexpr static Attribute kInputPointAttrib{"inputPoint", kFloat2_GrVertexAttribType,
+                                                     kFloat2_GrSLType};
+        this->setVertexAttributes(&kInputPointAttrib, 1);
+    }
+
+private:
+    const char* name() const override { return "GrTessellateStrokeShader"; }
+    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override {
+        b->add32(this->viewMatrix().isIdentity());
+    }
+    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
+
+    SkString getTessControlShaderGLSL(const GrGLSLPrimitiveProcessor*,
+                                      const char* versionAndExtensionDecls,
+                                      const GrGLSLUniformHandler&,
+                                      const GrShaderCaps&) const override;
+    SkString getTessEvaluationShaderGLSL(const GrGLSLPrimitiveProcessor*,
+                                         const char* versionAndExtensionDecls,
+                                         const GrGLSLUniformHandler&,
+                                         const GrShaderCaps&) const override;
+
+    const float fMiterLimit;
+    const SkPMColor4f fColor;
+
+    class Impl;
+};
+
+#endif