Roll external/skia 1a049bb04380..25bcd6a6215e (4 commits)

https://skia.googlesource.com/skia.git/+log/1a049bb04380..25bcd6a6215e

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://skia-autoroll.corp.goog/r/android-master-autoroll
Please CC stani@google.com on the revert to ensure that a human
is aware of the problem.

To report a problem with the AutoRoller itself, please file a bug:
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+/master/autoroll/README.md

Test: Presubmit checks will test this change.
Change-Id: I68b81c463381c7dc956f6ded9fa865196d08830f
Exempt-From-Owner-Approval: The autoroll bot does not require owner approval.
diff --git a/Android.bp b/Android.bp
index ce0c43f..59bd2c0 100644
--- a/Android.bp
+++ b/Android.bp
@@ -788,7 +788,7 @@
           "src/gpu/ops/GrStrokeRectOp.cpp",
           "src/gpu/ops/GrTessellatingPathRenderer.cpp",
           "src/gpu/ops/GrTextureOp.cpp",
-          "src/gpu/tessellate/GrCoverShader.cpp",
+          "src/gpu/tessellate/GrFillPathShader.cpp",
           "src/gpu/tessellate/GrGpuTessellationPathRenderer.cpp",
           "src/gpu/tessellate/GrPathParser.cpp",
           "src/gpu/tessellate/GrStencilPathShader.cpp",
diff --git a/DEPS b/DEPS
index f03484b..b4b1603 100644
--- a/DEPS
+++ b/DEPS
@@ -7,7 +7,7 @@
 deps = {
   "buildtools"                            : "https://chromium.googlesource.com/chromium/buildtools.git@505de88083136eefd056e5ee4ca0f01fe9b33de8",
   "common"                                : "https://skia.googlesource.com/common.git@9737551d7a52c3db3262db5856e6bcd62c462b92",
-  "third_party/externals/angle2"          : "https://chromium.googlesource.com/angle/angle.git@2bc9cc12f0b091bc5d144d770adaa200d3f417c9",
+  "third_party/externals/angle2"          : "https://chromium.googlesource.com/angle/angle.git@ee07cb317579dfda40dabb5d6d9c209e0e9e0643",
   "third_party/externals/dawn"            : "https://dawn.googlesource.com/dawn.git@604072bc2ed01018eb03bcbbf9d94042f679af63",
   "third_party/externals/dng_sdk"         : "https://android.googlesource.com/platform/external/dng_sdk.git@c8d0c9b1d16bfda56f15165d39e0ffa360a11123",
   "third_party/externals/egl-registry"    : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@a0bca08de07c7d7651047bedc0b653cfaaa4f2ae",
@@ -31,13 +31,13 @@
   "third_party/externals/spirv-cross"     : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@53ab2144b90abede33be5161aec5dfc94ddc3caf",
   "third_party/externals/spirv-headers"   : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@29c11140baaf9f7fdaa39a583672c556bf1795a1",
   "third_party/externals/spirv-tools"     : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@0c4feb643b89d1792b02f7cbef315e9d95633bd7",
-  "third_party/externals/swiftshader"     : "https://swiftshader.googlesource.com/SwiftShader@6c3dc3581eaf4345c0507d5ac7bb013d55351547",
+  "third_party/externals/swiftshader"     : "https://swiftshader.googlesource.com/SwiftShader@430def835f9f85d52f4a96db9b715cd9a7403c9c",
   #"third_party/externals/v8"              : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4",
   "third_party/externals/wuffs"           : "https://skia.googlesource.com/external/github.com/google/wuffs.git@4080840928c0b05a80cda0d14ac2e2615f679f1a",
   "third_party/externals/zlib"            : "https://chromium.googlesource.com/chromium/src/third_party/zlib@47af7c547f8551bd25424e56354a2ae1e9062859",
 
   "../src": {
-    "url": "https://chromium.googlesource.com/chromium/src.git@243744c215b780cfd060040b037908636e62a8dc",
+    "url": "https://chromium.googlesource.com/chromium/src.git@fbfe7df1b1d42c3b640852e4afa9ba732e12a20d",
     "condition": "checkout_chromium",
   },
 }
diff --git a/gn/gpu.gni b/gn/gpu.gni
index 0dcd690..c36c167 100644
--- a/gn/gpu.gni
+++ b/gn/gpu.gni
@@ -418,12 +418,13 @@
   "$_src/gpu/gradients/generated/GrTiledGradientEffect.cpp",
   "$_src/gpu/gradients/generated/GrTiledGradientEffect.h",
 
-  "$_src/gpu/tessellate/GrCoverShader.cpp",
-  "$_src/gpu/tessellate/GrCoverShader.h",
+  "$_src/gpu/tessellate/GrFillPathShader.cpp",
+  "$_src/gpu/tessellate/GrFillPathShader.h",
   "$_src/gpu/tessellate/GrGpuTessellationPathRenderer.cpp",
   "$_src/gpu/tessellate/GrGpuTessellationPathRenderer.h",
   "$_src/gpu/tessellate/GrPathParser.cpp",
   "$_src/gpu/tessellate/GrPathParser.h",
+  "$_src/gpu/tessellate/GrPathShader.h",
   "$_src/gpu/tessellate/GrStencilPathShader.cpp",
   "$_src/gpu/tessellate/GrStencilPathShader.h",
   "$_src/gpu/tessellate/GrTessellatePathOp.cpp",
diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp
index db7b656..4985a6e 100644
--- a/src/gpu/GrPipeline.cpp
+++ b/src/gpu/GrPipeline.cpp
@@ -27,11 +27,7 @@
     }
 
     fWindowRectsState = hardClip.windowRectsState();
-    if (!args.fUserStencil->isDisabled(fFlags & Flags::kHasStencilClip)) {
-        fFlags |= Flags::kStencilEnabled;
-    }
-
-    fUserStencilSettings = args.fUserStencil;
+    this->setUserStencil(args.fUserStencil);
 
     fXferProcessor = std::move(xferProcessor);
 
@@ -76,16 +72,13 @@
                        const GrSwizzle& outputSwizzle, InputFlags inputFlags,
                        const GrUserStencilSettings* userStencil)
         : fWindowRectsState()
-        , fUserStencilSettings(userStencil)
         , fFlags((Flags)inputFlags)
         , fXferProcessor(std::move(xp))
         , fOutputSwizzle(outputSwizzle) {
     if (GrScissorTest::kEnabled == scissorTest) {
         fFlags |= Flags::kScissorEnabled;
     }
-    if (!userStencil->isDisabled(false)) {
-        fFlags |= Flags::kStencilEnabled;
-    }
+    this->setUserStencil(userStencil);
 }
 
 void GrPipeline::genKey(GrProcessorKeyBuilder* b, const GrCaps& caps) const {
diff --git a/src/gpu/GrPipeline.h b/src/gpu/GrPipeline.h
index c057051..a444c74 100644
--- a/src/gpu/GrPipeline.h
+++ b/src/gpu/GrPipeline.h
@@ -187,6 +187,12 @@
     /// @}
 
     const GrUserStencilSettings* getUserStencil() const { return fUserStencilSettings; }
+    void setUserStencil(const GrUserStencilSettings* stencil) {
+        fUserStencilSettings = stencil;
+        if (!fUserStencilSettings->isDisabled(fFlags & Flags::kHasStencilClip)) {
+            fFlags |= Flags::kStencilEnabled;
+        }
+    }
 
     bool isScissorEnabled() const {
         return SkToBool(fFlags & Flags::kScissorEnabled);
diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h
index f3ae030..384b8e1 100644
--- a/src/gpu/GrProcessor.h
+++ b/src/gpu/GrProcessor.h
@@ -100,7 +100,6 @@
         kGrConicEffect_ClassID,
         kGrConstColorProcessor_ClassID,
         kGrConvexPolyEffect_ClassID,
-        kGrCoverShader_ClassID,
         kGrDeviceSpaceTextureDecalFragmentProcessor_ClassID,
         kGrDiffuseLightingEffect_ClassID,
         kGrDisplacementMapEffect_ClassID,
@@ -160,6 +159,9 @@
         kSwizzleFragmentProcessor_ClassID,
         kTessellationTestTriShader_ClassID,
         kTessellationTestRectShader_ClassID,
+        kTessellate_GrFillBoundingBoxShader_ClassID,
+        kTessellate_GrFillCubicHullShader_ClassID,
+        kTessellate_GrFillTriangleShader_ClassID,
         kTessellate_GrStencilCubicShader_ClassID,
         kTessellate_GrStencilTriangleShader_ClassID,
         kTessellate_GrStencilWedgeShader_ClassID,
diff --git a/src/gpu/tessellate/GrCoverShader.cpp b/src/gpu/tessellate/GrCoverShader.cpp
deleted file mode 100644
index 936fea7..0000000
--- a/src/gpu/tessellate/GrCoverShader.cpp
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2019 Google LLC.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "src/gpu/tessellate/GrCoverShader.h"
-
-#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
-#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
-#include "src/gpu/glsl/GrGLSLVarying.h"
-#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
-
-class GrCoverShader::Impl : public GrGLSLGeometryProcessor {
-    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) final {
-        const char* viewMatrix;
-        fViewMatrixUniform = args.fUniformHandler->addUniform(
-                kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix);
-
-        const char* pathBounds;
-        fPathBoundsUniform = args.fUniformHandler->addUniform(
-                kVertex_GrShaderFlag, kFloat4_GrSLType, "path_bounds", &pathBounds);
-
-        const char* color;
-        fColorUniform = args.fUniformHandler->addUniform(
-                kFragment_GrShaderFlag, kHalf4_GrSLType, "color", &color);
-
-        args.fVaryingHandler->emitAttributes(args.fGP.cast<GrCoverShader>());
-
-        args.fVertBuilder->codeAppendf(R"(
-                // Use sk_VertexID and uniforms (instead of vertex data) to find vertex positions.
-                float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1);
-                float2 localcoord = mix(%s.xy, %s.zw, T);
-                float2 vertexpos = (%s * float3(localcoord, 1)).xy;
-
-                // Outset to avoid possible T-junctions with extreme edges of the path.
-                float2x2 M2 = float2x2(%s);
-                float2 devoutset = .25 * sign(M2 * (T - .5));
-                vertexpos += devoutset;
-                localcoord += inverse(M2) * devoutset;)",
-                pathBounds, pathBounds, viewMatrix, viewMatrix);
-
-        this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler,
-                             GrShaderVar("localcoord", kFloat2_GrSLType),
-                             args.fFPCoordTransformHandler);
-
-        gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
-
-        args.fFragBuilder->codeAppendf(R"(
-                %s = %s;
-                %s = half4(1);)",
-                args.fOutputColor, color, args.fOutputCoverage);
-    }
-
-    void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
-                 const CoordTransformRange& transformRange) override {
-        const GrCoverShader& shader = primProc.cast<GrCoverShader>();
-        const SkRect& b = shader.fPathBounds;
-        const SkPMColor4f& color = shader.fColor;
-        pdman.setSkMatrix(fViewMatrixUniform, shader.fViewMatrix);
-        pdman.set4f(fPathBoundsUniform, b.left(), b.top(), b.right(), b.bottom());
-        pdman.set4f(fColorUniform, color.fR, color.fG, color.fB, color.fA);
-        this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
-    }
-
-    GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
-    GrGLSLUniformHandler::UniformHandle fPathBoundsUniform;
-    GrGLSLUniformHandler::UniformHandle fColorUniform;
-};
-
-GrGLSLPrimitiveProcessor* GrCoverShader::createGLSLInstance(const GrShaderCaps&) const {
-    return new Impl;
-}
diff --git a/src/gpu/tessellate/GrCoverShader.h b/src/gpu/tessellate/GrCoverShader.h
deleted file mode 100644
index c39cf9e..0000000
--- a/src/gpu/tessellate/GrCoverShader.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright 2019 Google LLC.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrCoverShader_DEFINED
-#define GrCoverShader_DEFINED
-
-#include "src/gpu/GrGeometryProcessor.h"
-
-// Draws a path's bounding box, with a subpixel outset to avoid possible T-junctions with extreme
-// edges of the path. This class is used for the "cover" pass of stencil-then-cover path rendering.
-// NOTE: The emitted geometry may not be axis-aligned, depending on the view matrix.
-class GrCoverShader : public GrGeometryProcessor {
-public:
-    GrCoverShader(const SkMatrix& viewMatrix, const SkRect& pathBounds, const SkPMColor4f& color)
-            : GrGeometryProcessor(kGrCoverShader_ClassID)
-            , fViewMatrix(viewMatrix)
-            , fPathBounds(pathBounds)
-            , fColor(color) {}
-
-    const char* name() const override { return "GrCoverShader"; }
-    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {}
-    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
-
-private:
-    const SkMatrix fViewMatrix;
-    const SkRect fPathBounds;
-    const SkPMColor4f fColor;
-
-    class Impl;
-};
-
-#endif
diff --git a/src/gpu/tessellate/GrFillPathShader.cpp b/src/gpu/tessellate/GrFillPathShader.cpp
new file mode 100644
index 0000000..1e12cf2
--- /dev/null
+++ b/src/gpu/tessellate/GrFillPathShader.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2020 Google LLC.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/tessellate/GrFillPathShader.h"
+
+#include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
+#include "src/gpu/glsl/GrGLSLGeometryProcessor.h"
+#include "src/gpu/glsl/GrGLSLVarying.h"
+#include "src/gpu/glsl/GrGLSLVertexGeoBuilder.h"
+
+class GrFillPathShader::Impl : public GrGLSLGeometryProcessor {
+public:
+    void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
+        auto& shader = args.fGP.cast<GrFillPathShader>();
+
+        const char* viewMatrix;
+        fViewMatrixUniform = args.fUniformHandler->addUniform(
+                kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix);
+
+        args.fVaryingHandler->emitAttributes(shader);
+
+        args.fVertBuilder->codeAppend("float2 localcoord, vertexpos;");
+        shader.emitVertexCode(this, args.fVertBuilder, viewMatrix, args.fUniformHandler);
+
+        this->emitTransforms(args.fVertBuilder, args.fVaryingHandler, args.fUniformHandler,
+                             GrShaderVar("localcoord", kFloat2_GrSLType),
+                             args.fFPCoordTransformHandler);
+
+        gpArgs->fPositionVar.set(kFloat2_GrSLType, "vertexpos");
+
+        const char* color;
+        fColorUniform = args.fUniformHandler->addUniform(
+                kFragment_GrShaderFlag, kHalf4_GrSLType, "color", &color);
+
+        args.fFragBuilder->codeAppendf("%s = %s;", args.fOutputColor, color);
+        args.fFragBuilder->codeAppendf("%s = half4(1);", args.fOutputCoverage);
+    }
+
+    void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
+                 const CoordTransformRange& transformRange) override {
+        const GrFillPathShader& shader = primProc.cast<GrFillPathShader>();
+        pdman.setSkMatrix(fViewMatrixUniform, shader.viewMatrix());
+
+        const SkPMColor4f& color = shader.fColor;
+        pdman.set4f(fColorUniform, color.fR, color.fG, color.fB, color.fA);
+
+        if (fPathBoundsUniform.isValid()) {
+            const SkRect& b = primProc.cast<GrFillBoundingBoxShader>().pathBounds();
+            pdman.set4f(fPathBoundsUniform, b.left(), b.top(), b.right(), b.bottom());
+        }
+
+        this->setTransformDataHelper(SkMatrix::I(), pdman, transformRange);
+    }
+
+    GrGLSLUniformHandler::UniformHandle fViewMatrixUniform;
+    GrGLSLUniformHandler::UniformHandle fColorUniform;
+    GrGLSLUniformHandler::UniformHandle fPathBoundsUniform;
+};
+
+GrGLSLPrimitiveProcessor* GrFillPathShader::createGLSLInstance(const GrShaderCaps&) const {
+    return new Impl;
+}
+
+void GrFillTriangleShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix,
+                                          GrGLSLUniformHandler* uniformHandler) const {
+    v->codeAppendf(R"(
+            localcoord = input_point;
+            vertexpos = (%s * float3(localcoord, 1)).xy;)", viewMatrix);
+}
+
+void GrFillCubicHullShader::emitVertexCode(Impl*, GrGLSLVertexBuilder* v, const char* viewMatrix,
+                                           GrGLSLUniformHandler* uniformHandler) const {
+    v->codeAppend(R"(
+            float4x2 P = float4x2(input_points_0_1, input_points_2_3);
+
+            // Translate the points to v0..3 where v0=0.
+            float2 v1 = P[1] - P[0], v2 = P[2] - P[0], v3 = P[3] - P[0];
+
+            // Reorder the points so v2 bisects v1 and v3.
+            if (sign(determinant(float2x2(v2,v1))) == sign(determinant(float2x2(v2,v3)))) {
+                float2 tmp = P[2];
+                if (sign(determinant(float2x2(v1,v2))) != sign(determinant(float2x2(v1,v3)))) {
+                    P[2] = P[1];  // swap(P2, P1)
+                    P[1] = tmp;
+                } else {
+                    P[2] = P[3];  // swap(P2, P3)
+                    P[3] = tmp;
+                }
+            }
+
+            // Find the "turn direction" of each corner and net turn direction.
+            float4 dir;
+            float netdir = 0.0;
+            for (int i = 0; i < 4; ++i) {
+                float2 prev = P[i] - P[(i + 3) & 3], next = P[(i + 1) & 3] - P[i];
+                dir[i] = sign(determinant(float2x2(prev, next)));
+                netdir += dir[i];
+            }
+
+            // sk_VertexID comes in fan order. Convert to strip order.
+            int vertexidx = sk_VertexID;
+            vertexidx ^= vertexidx >> 1;
+
+            // Remove the non-convex vertex, if any.
+            if (dir[vertexidx] != sign(netdir)) {
+                vertexidx = (vertexidx + 1) & 3;
+            }
+
+            localcoord = P[vertexidx];)");
+
+    v->codeAppendf("vertexpos = (%s * float3(localcoord, 1)).xy;", viewMatrix);
+}
+
+void GrFillBoundingBoxShader::emitVertexCode(Impl* impl, GrGLSLVertexBuilder* v,
+                                             const char* viewMatrix,
+                                             GrGLSLUniformHandler* uniformHandler) const {
+    const char* pathBounds;
+    impl->fPathBoundsUniform = uniformHandler->addUniform(
+            kVertex_GrShaderFlag, kFloat4_GrSLType, "path_bounds", &pathBounds);
+
+    v->codeAppendf(R"(
+            // Use sk_VertexID and uniforms (instead of vertex data) to find vertex positions.
+            float2 T = float2(sk_VertexID & 1, sk_VertexID >> 1);
+            localcoord = mix(%s.xy, %s.zw, T);
+            vertexpos = (%s * float3(localcoord, 1)).xy;
+
+            // Outset to avoid possible T-junctions with extreme edges of the path.
+            float2x2 M2 = float2x2(%s);
+            float2 devoutset = .25 * sign(M2 * (T - .5));
+            localcoord += inverse(M2) * devoutset;
+            vertexpos += devoutset;)", pathBounds, pathBounds, viewMatrix, viewMatrix);
+}
diff --git a/src/gpu/tessellate/GrFillPathShader.h b/src/gpu/tessellate/GrFillPathShader.h
new file mode 100644
index 0000000..1373a14
--- /dev/null
+++ b/src/gpu/tessellate/GrFillPathShader.h
@@ -0,0 +1,94 @@
+/*
+ * 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 GrFillPathShader_DEFINED
+#define GrFillPathShader_DEFINED
+
+#include "src/gpu/tessellate/GrPathShader.h"
+
+class GrGLSLUniformHandler;
+class GrGLSLVertexBuilder;
+
+// This is the base class for shaders that fill a path's pixels in the final render target.
+class GrFillPathShader : public GrPathShader {
+public:
+    GrFillPathShader(ClassID classID, const SkMatrix& viewMatrix, SkPMColor4f color,
+                     GrPrimitiveType primitiveType)
+            : GrPathShader(classID, viewMatrix, primitiveType, 0)
+            , fColor(color) {
+    }
+
+    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override {}
+    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
+
+protected:
+    class Impl;
+
+    virtual void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
+                                GrGLSLUniformHandler*) const = 0;
+
+private:
+    const SkPMColor4f fColor;
+};
+
+// Fills a simple array of triangles.
+class GrFillTriangleShader : public GrFillPathShader {
+public:
+    GrFillTriangleShader(const SkMatrix& viewMatrix, SkPMColor4f color)
+            : GrFillPathShader(kTessellate_GrFillTriangleShader_ClassID, viewMatrix, color,
+                               GrPrimitiveType::kTriangles) {
+        static constexpr Attribute kPtAttrib = {
+                "input_point", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
+        this->setVertexAttributes(&kPtAttrib, 1);
+    }
+
+private:
+    const char* name() const override { return "GrFillTriangleShader"; }
+    void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
+                        GrGLSLUniformHandler*) const override;
+};
+
+// Fills an array of convex hulls surrounding 4-point cubic instances.
+class GrFillCubicHullShader : public GrFillPathShader {
+public:
+    GrFillCubicHullShader(const SkMatrix& viewMatrix, SkPMColor4f color)
+            : GrFillPathShader(kTessellate_GrFillCubicHullShader_ClassID, viewMatrix, color,
+                               GrPrimitiveType::kTriangleStrip) {
+        static constexpr Attribute kPtsAttribs[] = {
+                {"input_points_0_1", kFloat4_GrVertexAttribType, kFloat4_GrSLType},
+                {"input_points_2_3", kFloat4_GrVertexAttribType, kFloat4_GrSLType}};
+        this->setInstanceAttributes(kPtsAttribs, SK_ARRAY_COUNT(kPtsAttribs));
+    }
+
+private:
+    const char* name() const override { return "GrFillCubicHullShader"; }
+    void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
+                        GrGLSLUniformHandler*) const override;
+};
+
+// Fills a path's bounding box, with subpixel outset to avoid possible T-junctions with extreme
+// edges of the path.
+// NOTE: The emitted geometry may not be axis-aligned, depending on the view matrix.
+class GrFillBoundingBoxShader : public GrFillPathShader {
+public:
+    GrFillBoundingBoxShader(const SkMatrix& viewMatrix, SkPMColor4f color, const SkRect& pathBounds)
+            : GrFillPathShader(kTessellate_GrFillBoundingBoxShader_ClassID, viewMatrix, color,
+                               GrPrimitiveType::kTriangleStrip)
+            , fPathBounds(pathBounds) {
+    }
+
+    const SkRect& pathBounds() const { return fPathBounds; }
+
+private:
+    const char* name() const override { return "GrFillBoundingBoxShader"; }
+    void emitVertexCode(Impl*, GrGLSLVertexBuilder*, const char* viewMatrix,
+                        GrGLSLUniformHandler*) const override;
+
+    const SkRect fPathBounds;
+};
+
+#endif
diff --git a/src/gpu/tessellate/GrPathShader.h b/src/gpu/tessellate/GrPathShader.h
new file mode 100644
index 0000000..1443c77
--- /dev/null
+++ b/src/gpu/tessellate/GrPathShader.h
@@ -0,0 +1,64 @@
+/*
+ * 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 GrPathShader_DEFINED
+#define GrPathShader_DEFINED
+
+#include "src/gpu/GrGeometryProcessor.h"
+#include "src/gpu/GrOpFlushState.h"
+#include "src/gpu/GrOpsRenderPass.h"
+#include "src/gpu/GrProgramInfo.h"
+
+ // This is a common base class for shaders in the GPU tessellator.
+class GrPathShader : public GrGeometryProcessor {
+public:
+    GrPathShader(ClassID classID, const SkMatrix& viewMatrix, GrPrimitiveType primitiveType,
+                 int tessellationPatchVertexCount)
+            : GrGeometryProcessor(classID)
+            , fViewMatrix(viewMatrix)
+            , fPrimitiveType(primitiveType)
+            , fTessellationPatchVertexCount(tessellationPatchVertexCount) {
+        if (fTessellationPatchVertexCount) {
+            this->setWillUseTessellationShaders();
+        }
+    }
+
+    const SkMatrix& viewMatrix() const { return fViewMatrix; }
+    GrPrimitiveType primitiveType() const { return fPrimitiveType; }
+    int tessellationPatchVertexCount() const { return fTessellationPatchVertexCount; }
+
+    void issueDraw(GrOpFlushState* state, const GrPipeline* pipeline,
+                   const GrPipeline::FixedDynamicState* fixedDynamicState,
+                   sk_sp<const GrBuffer> vertexBuffer, int vertexCount, int baseVertex,
+                   const SkRect& bounds) {
+        GrMesh mesh(fPrimitiveType, fTessellationPatchVertexCount);
+        mesh.setNonIndexedNonInstanced(vertexCount);
+        mesh.setVertexData(std::move(vertexBuffer), baseVertex);
+        this->issueDraw(state, pipeline, fixedDynamicState, mesh, bounds);
+    }
+
+    void issueDraw(GrOpFlushState* state, const GrPipeline* pipeline,
+                   const GrPipeline::FixedDynamicState* fixedDynamicState, const GrMesh& mesh,
+                   const SkRect& bounds) {
+        SkASSERT(mesh.primitiveType() == fPrimitiveType);
+        SkASSERT(mesh.tessellationPatchVertexCount() == fTessellationPatchVertexCount);
+        GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
+                                  state->proxy()->backendFormat(), state->view()->origin(),
+                                  pipeline, this, fixedDynamicState, nullptr, 0,
+                                  fPrimitiveType, fTessellationPatchVertexCount);
+        state->opsRenderPass()->draw(programInfo, &mesh, 1, bounds);
+    }
+
+private:
+    const SkMatrix fViewMatrix;
+    const GrPrimitiveType fPrimitiveType;
+    const int fTessellationPatchVertexCount;
+
+    class Impl;
+};
+
+#endif
diff --git a/src/gpu/tessellate/GrStencilPathShader.cpp b/src/gpu/tessellate/GrStencilPathShader.cpp
index cf17222..cc31dea 100644
--- a/src/gpu/tessellate/GrStencilPathShader.cpp
+++ b/src/gpu/tessellate/GrStencilPathShader.cpp
@@ -40,7 +40,7 @@
         args.fVaryingHandler->emitAttributes(shader);
 
         GrShaderVar vertexPos = (*shader.vertexAttributes().begin()).asShaderVar();
-        if (!shader.fViewMatrix.isIdentity()) {
+        if (!shader.viewMatrix().isIdentity()) {
             const char* viewMatrix;
             fViewMatrixUniform = args.fUniformHandler->addUniform(
                     kVertex_GrShaderFlag, kFloat3x3_GrSLType, "view_matrix", &viewMatrix);
@@ -63,8 +63,8 @@
     void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& primProc,
                  const CoordTransformRange& transformRange) override {
         const auto& shader = primProc.cast<GrStencilPathShader>();
-        if (!shader.fViewMatrix.isIdentity()) {
-            pdman.setSkMatrix(fViewMatrixUniform, shader.fViewMatrix);
+        if (!shader.viewMatrix().isIdentity()) {
+            pdman.setSkMatrix(fViewMatrixUniform, shader.viewMatrix());
         }
     }
 
diff --git a/src/gpu/tessellate/GrStencilPathShader.h b/src/gpu/tessellate/GrStencilPathShader.h
index f3ea703..0aa0b59 100644
--- a/src/gpu/tessellate/GrStencilPathShader.h
+++ b/src/gpu/tessellate/GrStencilPathShader.h
@@ -8,36 +8,25 @@
 #ifndef GrStencilPathShader_DEFINED
 #define GrStencilPathShader_DEFINED
 
-#include "src/gpu/GrGeometryProcessor.h"
+#include "src/gpu/tessellate/GrPathShader.h"
 
 // This is the base class for shaders that stencil path elements, namely, triangles, standalone
 // cubics, and wedges.
-class GrStencilPathShader : public GrGeometryProcessor {
+class GrStencilPathShader : public GrPathShader {
 public:
     GrStencilPathShader(ClassID classID, const SkMatrix& viewMatrix, GrPrimitiveType primitiveType,
                         int tessellationPatchVertexCount = 0)
-            : GrGeometryProcessor(classID)
-            , fViewMatrix(viewMatrix)
-            , fPrimitiveType(primitiveType)
-            , fTessellationPatchVertexCount(tessellationPatchVertexCount) {
+            : GrPathShader(classID, viewMatrix, primitiveType, tessellationPatchVertexCount) {
         constexpr static Attribute kPointAttrib = {
                 "point", kFloat2_GrVertexAttribType, kFloat2_GrSLType};
         this->setVertexAttributes(&kPointAttrib, 1);
-        if (fTessellationPatchVertexCount) {
-            this->setWillUseTessellationShaders();
-        }
     }
-    GrPrimitiveType primitiveType() const { return fPrimitiveType; }
-    int tessellationPatchVertexCount() const { return fTessellationPatchVertexCount; }
-    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {
-        b->add32(fViewMatrix.isIdentity());
-    }
-    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
 
 private:
-    const SkMatrix fViewMatrix;
-    const GrPrimitiveType fPrimitiveType;
-    const int fTessellationPatchVertexCount;
+    void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const final {
+        b->add32(this->viewMatrix().isIdentity());
+    }
+    GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const final;
 
     class Impl;
 };
diff --git a/src/gpu/tessellate/GrTessellatePathOp.cpp b/src/gpu/tessellate/GrTessellatePathOp.cpp
index a4ce3f1..53e8382 100644
--- a/src/gpu/tessellate/GrTessellatePathOp.cpp
+++ b/src/gpu/tessellate/GrTessellatePathOp.cpp
@@ -10,9 +10,8 @@
 #include "src/gpu/GrEagerVertexAllocator.h"
 #include "src/gpu/GrGpu.h"
 #include "src/gpu/GrOpFlushState.h"
-#include "src/gpu/GrOpsRenderPass.h"
-#include "src/gpu/GrProgramInfo.h"
-#include "src/gpu/tessellate/GrCoverShader.h"
+#include "src/gpu/GrTessellator.h"
+#include "src/gpu/tessellate/GrFillPathShader.h"
 #include "src/gpu/tessellate/GrPathParser.h"
 #include "src/gpu/tessellate/GrStencilPathShader.h"
 
@@ -29,24 +28,66 @@
     GrEagerDynamicVertexAllocator cubicInstanceAllocator(state, &fCubicInstanceBuffer,
                                                          &fBaseCubicInstance);
 
-    // First see if we should split up inner polygon triangles and curves, and triangulate the inner
+    // First check if the path is large and/or simple enough that we can actually tessellate the
+    // inner polygon(s) on the CPU. This is our fastest approach. It allows us to stencil only the
+    // curves, and then draw the internal polygons directly to the final render target, thus filling
+    // in the majority of pixels in a single render pass.
+    SkScalar scales[2];
+    SkAssertResult(fViewMatrix.getMinMaxScales(scales));  // Will fail if perspective.
+    const SkRect& bounds = fPath.getBounds();
+    int numVerbs = fPath.countVerbs();
+    if (numVerbs <= 0) {
+        return;
+    }
+    float gpuFragmentWork = bounds.height() * scales[0] * bounds.width() * scales[1];
+    float cpuTessellationWork = (float)numVerbs * SkNextLog2(numVerbs);  // N log N.
+    if (cpuTessellationWork * 500 + (256 * 256) < gpuFragmentWork) {  // Don't try below 256x256.
+        bool pathIsLinear;
+        // PathToTriangles(..kSimpleInnerPolygon..) will fail if the inner polygon is not simple.
+        if ((fPathVertexCount = GrTessellator::PathToTriangles(
+                fPath, 0, SkRect::MakeEmpty(), &pathVertexAllocator,
+                GrTessellator::Mode::kSimpleInnerPolygons, &pathIsLinear))) {
+            if (((Flags::kStencilOnly | Flags::kWireframe) & fFlags) ||
+                GrAAType::kCoverage == fAAType ||
+                (state->appliedClip() && state->appliedClip()->hasStencilClip())) {
+                // If we have certain flags, mixed samples, or a stencil clip then we unfortunately
+                // can't fill the inner polygon directly. Create a stencil shader here to ensure we
+                // still stencil the entire path.
+                fStencilPathShader = state->allocator()->make<GrStencilTriangleShader>(fViewMatrix);
+            }
+            if (!(Flags::kStencilOnly & fFlags)) {
+                fFillPathShader = state->allocator()->make<GrFillTriangleShader>(
+                        fViewMatrix, fColor);
+            }
+            if (!pathIsLinear) {
+                fCubicInstanceCount = GrPathParser::EmitCubicInstances(
+                        fPath, &cubicInstanceAllocator);
+                SkASSERT(fCubicInstanceCount);
+            }
+            return;
+        }
+    }
+
+    // Next see if we can split up inner polygon triangles and curves, and triangulate the inner
     // polygon(s) more efficiently. This causes greater CPU overhead due to the extra shaders and
     // draw calls, but the better triangulation can reduce the rasterizer load by a great deal on
     // complex paths.
-    const SkRect& bounds = fPath.getBounds();
-    float scale = fViewMatrix.getMaxScale();
-    // Raster-edge work is 1-dimensional, so we sum height and width rather than multiplying them.
-    float rasterEdgeWork = (bounds.height() + bounds.width()) * scale * fPath.countVerbs();
+    // NOTE: Raster-edge work is 1-dimensional, so we sum height and width instead of multiplying.
+    float rasterEdgeWork = (bounds.height() + bounds.width()) * scales[1] * fPath.countVerbs();
     if (rasterEdgeWork > 1000 * 1000) {
-        fPathShader = state->allocator()->make<GrStencilTriangleShader>(fViewMatrix);
-        fPathVertexCount = GrPathParser::EmitInnerPolygonTriangles(fPath, &pathVertexAllocator);
+        if ((fPathVertexCount =
+                GrPathParser::EmitInnerPolygonTriangles(fPath, &pathVertexAllocator))) {
+            fStencilPathShader = state->allocator()->make<GrStencilTriangleShader>(fViewMatrix);
+        }
         fCubicInstanceCount = GrPathParser::EmitCubicInstances(fPath, &cubicInstanceAllocator);
         return;
     }
 
     // Fastest CPU approach: emit one cubic wedge per verb, fanning out from the center.
-    fPathShader = state->allocator()->make<GrStencilWedgeShader>(fViewMatrix);
-    fPathVertexCount = GrPathParser::EmitCenterWedgePatches(fPath, &pathVertexAllocator);
+
+    if ((fPathVertexCount = GrPathParser::EmitCenterWedgePatches(fPath, &pathVertexAllocator))) {
+        fStencilPathShader = state->allocator()->make<GrStencilWedgeShader>(fViewMatrix);
+    }
 }
 
 void GrTessellatePathOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
@@ -100,33 +141,19 @@
 
     GrPipeline pipeline(initArgs, GrDisableColorXPFactory::MakeXferProcessor(), hardClip);
 
-    if (fPathVertexBuffer) {
-        GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
-                                  state->proxy()->backendFormat(), state->view()->origin(),
-                                  &pipeline, fPathShader, fixedDynamicState, nullptr, 0,
-                                  fPathShader->primitiveType(),
-                                  fPathShader->tessellationPatchVertexCount());
-
-        GrMesh mesh(fPathShader->primitiveType(), fPathShader->tessellationPatchVertexCount());
-        mesh.setNonIndexedNonInstanced(fPathVertexCount);
-        mesh.setVertexData(fPathVertexBuffer, fBasePathVertex);
-
-        state->opsRenderPass()->draw(programInfo, &mesh, 1, this->bounds());
+    if (fStencilPathShader) {
+        SkASSERT(fPathVertexBuffer);
+        fStencilPathShader->issueDraw(state, &pipeline, fixedDynamicState, fPathVertexBuffer,
+                                      fPathVertexCount, fBasePathVertex, this->bounds());
     }
 
     if (fCubicInstanceBuffer) {
-        // Here we treat the cubic instance buffer as tessellation patches.
-        GrStencilCubicShader shader(fViewMatrix);
-        GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
-                                  state->proxy()->backendFormat(), state->view()->origin(),
-                                  &pipeline, &shader, fixedDynamicState, nullptr, 0,
-                                  GrPrimitiveType::kPatches, 4);
-
+        // Here we treat the cubic instance buffer as tessellation patches to stencil the curves.
         GrMesh mesh(GrPrimitiveType::kPatches, 4);
         mesh.setNonIndexedNonInstanced(fCubicInstanceCount * 4);
         mesh.setVertexData(fCubicInstanceBuffer, fBaseCubicInstance * 4);
-
-        state->opsRenderPass()->draw(programInfo, &mesh, 1, this->bounds());
+        GrStencilCubicShader(fViewMatrix).issueDraw(
+                state, &pipeline, fixedDynamicState, mesh, this->bounds());
     }
 
     // http://skbug.com/9739
@@ -162,20 +189,74 @@
             initArgs.fInputFlags |= GrPipeline::InputFlags::kConservativeRaster;
         }
     }
-    initArgs.fUserStencil = &kTestAndResetStencil;
     initArgs.fCaps = &state->caps();
     initArgs.fDstProxyView = state->drawOpArgs().dstProxyView();
     initArgs.fOutputSwizzle = state->drawOpArgs().outputSwizzle();
 
     GrPipeline pipeline(initArgs, std::move(fProcessors), std::move(clip));
-    GrCoverShader shader(fViewMatrix, fPath.getBounds(), fColor);
-    GrProgramInfo programInfo(state->proxy()->numSamples(), state->proxy()->numStencilSamples(),
-                              state->proxy()->backendFormat(), state->view()->origin(), &pipeline,
-                              &shader, fixedDynamicState, nullptr, 0,
-                              GrPrimitiveType::kTriangleStrip);
 
-    GrMesh mesh(GrPrimitiveType::kTriangleStrip);
-    mesh.setNonIndexedNonInstanced(4);
+    if (fFillPathShader) {
+        SkASSERT(fPathVertexBuffer);
 
-    state->opsRenderPass()->draw(programInfo, &mesh, 1, this->bounds());
+        // These are a twist on the standard red book stencil settings that allow us to draw the
+        // inner polygon directly to the final render target. At this point, the curves are already
+        // stencilled in. So if the stencil value is zero, then it means the path at our sample is
+        // not affected by any curves and we fill the path in directly. If the stencil value is
+        // nonzero, then we don't fill and instead continue the standard red book stencil process.
+        //
+        // NOTE: These settings are currently incompatible with a stencil clip.
+        constexpr static GrUserStencilSettings kFillOrIncrDecrStencil(
+            GrUserStencilSettings::StaticInitSeparate<
+                0x0000,                        0x0000,
+                GrUserStencilTest::kEqual,     GrUserStencilTest::kEqual,
+                0xffff,                        0xffff,
+                GrUserStencilOp::kKeep,        GrUserStencilOp::kKeep,
+                GrUserStencilOp::kIncWrap,     GrUserStencilOp::kDecWrap,
+                0xffff,                        0xffff>());
+
+        constexpr static GrUserStencilSettings kFillOrInvertStencil(
+            GrUserStencilSettings::StaticInit<
+                0x0000,
+                GrUserStencilTest::kEqual,
+                0xffff,
+                GrUserStencilOp::kKeep,
+                GrUserStencilOp::kZero,
+                0xffff>());
+
+        if (fStencilPathShader) {
+            // The path was already stencilled. Here we just need to do a cover pass.
+            pipeline.setUserStencil(&kTestAndResetStencil);
+        } else if (!fCubicInstanceBuffer) {
+            // There are no curves, so we can just ignore stencil and fill the path directly.
+            pipeline.setUserStencil(&GrUserStencilSettings::kUnused);
+        } else if (SkPathFillType::kWinding == fPath.getFillType()) {
+            // Fill in the path pixels not touched by curves, incr/decr stencil otherwise.
+            SkASSERT(!pipeline.hasStencilClip());
+            pipeline.setUserStencil(&kFillOrIncrDecrStencil);
+        } else {
+            // Fill in the path pixels not touched by curves, invert stencil otherwise.
+            SkASSERT(!pipeline.hasStencilClip());
+            pipeline.setUserStencil(&kFillOrInvertStencil);
+        }
+        fFillPathShader->issueDraw(state, &pipeline, fixedDynamicState, fPathVertexBuffer,
+                                   fPathVertexCount, fBasePathVertex, this->bounds());
+
+        if (fCubicInstanceBuffer) {
+            // At this point, every pixel is filled in except the ones touched by curves. Issue a
+            // final cover pass over the curves by drawing their convex hulls. This will fill in any
+            // remaining samples and reset the stencil buffer.
+            GrMesh mesh(GrPrimitiveType::kTriangleStrip);
+            mesh.setInstanced(fCubicInstanceBuffer, fCubicInstanceCount, fBaseCubicInstance, 4);
+            pipeline.setUserStencil(&kTestAndResetStencil);
+            GrFillCubicHullShader(fViewMatrix, fColor).issueDraw(
+                    state, &pipeline, fixedDynamicState, mesh, this->bounds());
+        }
+    } else {
+        // There is not a fill shader for the path. Just draw a bounding box.
+        GrMesh mesh(GrPrimitiveType::kTriangleStrip);
+        mesh.setNonIndexedNonInstanced(4);
+        pipeline.setUserStencil(&kTestAndResetStencil);
+        GrFillBoundingBoxShader(fViewMatrix, fColor, fPath.getBounds()).issueDraw(
+                state, &pipeline, fixedDynamicState, mesh, this->bounds());
+    }
 }
diff --git a/src/gpu/tessellate/GrTessellatePathOp.h b/src/gpu/tessellate/GrTessellatePathOp.h
index cd0e37b..e080a1d 100644
--- a/src/gpu/tessellate/GrTessellatePathOp.h
+++ b/src/gpu/tessellate/GrTessellatePathOp.h
@@ -11,6 +11,7 @@
 #include "src/gpu/ops/GrDrawOp.h"
 
 class GrAppliedHardClip;
+class GrFillPathShader;
 class GrStencilPathShader;
 
 // Renders paths using the classic Red Book "stencil, then cover" method. Curves get linearized by
@@ -67,12 +68,25 @@
     SkPMColor4f fColor;
     GrProcessorSet fProcessors;
 
-    // The "path shader" draws the below path geometry.
-    GrStencilPathShader* fPathShader;
+    // These path shaders get created during onPrepare for drawing the below path vertex data.
+    //
+    // If fFillPathShader is null, then we just stencil the full path using fStencilPathShader and
+    // fCubicInstanceBuffer, and then fill it using a simple bounding box.
+    //
+    // If fFillPathShader is not null, then we fill the path using it plus cubic hulls from
+    // fCubicInstanceBuffer instead of a bounding box.
+    //
+    // If fFillPathShader is not null and fStencilPathShader *is* null, then the vertex data
+    // contains non-overlapping path geometry that can be drawn directly to the final render target.
+    // We only need to stencil curves from fCubicInstanceBuffer, and then draw the rest of the path
+    // directly.
+    GrStencilPathShader* fStencilPathShader = nullptr;
+    GrFillPathShader* fFillPathShader = nullptr;
 
-    // The "path vertex buffer" is made up of either inner polygon triangles (see
-    // GrPathParser::EmitInnerPolygonTriangles) or cubic wedge patches (see
-    // GrPathParser::EmitCenterWedgePatches).
+    // The "path vertex data" is made up of cubic wedges or inner polygon triangles (either red book
+    // style or fully tessellated). The geometry is generated by
+    // GrPathParser::EmitCenterWedgePatches, GrPathParser::EmitInnerPolygonTriangles,
+    // or GrTessellator::PathToTriangles.
     sk_sp<const GrBuffer> fPathVertexBuffer;
     int fBasePathVertex;
     int fPathVertexCount;