Remove PLS path renderer

Change-Id: Ib727b0749a5a7da95832970e79804417e8b6a247
Reviewed-on: https://skia-review.googlesource.com/9300
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/GrDrawOpTest.cpp b/src/gpu/GrDrawOpTest.cpp
index 5d0aa56..fcf70e0 100644
--- a/src/gpu/GrDrawOpTest.cpp
+++ b/src/gpu/GrDrawOpTest.cpp
@@ -32,7 +32,6 @@
 DRAW_OP_TEST_EXTERN(EllipseOp);
 DRAW_OP_TEST_EXTERN(GrDrawAtlasOp);
 DRAW_OP_TEST_EXTERN(NonAAStrokeRectOp);
-DRAW_OP_TEST_EXTERN(PLSPathOp);
 DRAW_OP_TEST_EXTERN(RRectOp);
 DRAW_OP_TEST_EXTERN(TesselatingPathOp);
 DRAW_OP_TEST_EXTERN(TextBlobOp);
@@ -56,8 +55,6 @@
         DRAW_OP_TEST_ENTRY(EllipseOp),
         DRAW_OP_TEST_ENTRY(GrDrawAtlasOp),
         DRAW_OP_TEST_ENTRY(NonAAStrokeRectOp),
-        // This currently hits an assert when the GrDisableColorXPFactory is randomly selected.
-        // DRAW_OP_TEST_ENTRY(PLSPathOp),
         DRAW_OP_TEST_ENTRY(RRectOp),
         DRAW_OP_TEST_ENTRY(TesselatingPathOp),
         DRAW_OP_TEST_ENTRY(TextBlobOp),
diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h
index 3abe8f8..5b69ead 100644
--- a/src/gpu/GrGpu.h
+++ b/src/gpu/GrGpu.h
@@ -376,7 +376,7 @@
             const GrGpuCommandBuffer::LoadAndStoreInfo& stencilInfo) = 0;
 
     // Called by GrOpList when flushing.
-    // Provides a hook for post-flush actions (e.g. PLS reset and Vulkan command buffer submits).
+    // Provides a hook for post-flush actions (e.g. Vulkan command buffer submits).
     virtual void finishOpList() {}
 
     virtual GrFence SK_WARN_UNUSED_RESULT insertFence() = 0;
diff --git a/src/gpu/GrPLSGeometryProcessor.h b/src/gpu/GrPLSGeometryProcessor.h
deleted file mode 100644
index 0640af6..0000000
--- a/src/gpu/GrPLSGeometryProcessor.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrPLSGeometryProcessor_DEFINED
-#define GrPLSGeometryProcessor_DEFINED
-
-#include "GrGeometryProcessor.h"
-
-/**
- * A minor extension to GrGeometryProcessor that adds bounds tracking for pixel local storage
- * purposes.
- */
-class GrPLSGeometryProcessor : public GrGeometryProcessor {
-public:
-    GrPixelLocalStorageState getPixelLocalStorageState() const override {
-        return GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState;
-    }
-
-    const SkRect& getBounds() const {
-       return fBounds;
-    }
-
-    void setBounds(SkRect& bounds) {
-       fBounds = bounds;
-    }
-
-private:
-    SkRect fBounds;
-};
-
-#endif
diff --git a/src/gpu/GrPathRendererChain.cpp b/src/gpu/GrPathRendererChain.cpp
index b371c3e..6c8177f 100644
--- a/src/gpu/GrPathRendererChain.cpp
+++ b/src/gpu/GrPathRendererChain.cpp
@@ -21,7 +21,6 @@
 #include "ops/GrDashLinePathRenderer.h"
 #include "ops/GrDefaultPathRenderer.h"
 #include "ops/GrMSAAPathRenderer.h"
-#include "ops/GrPLSPathRenderer.h"
 #include "ops/GrStencilAndCoverPathRenderer.h"
 #include "ops/GrTessellatingPathRenderer.h"
 
@@ -54,11 +53,6 @@
     if (options.fGpuPathRenderers & GpuPathRenderers::kAALinearizing) {
         fChain.push_back(sk_make_sp<GrAALinearizingConvexPathRenderer>());
     }
-    if (options.fGpuPathRenderers & GpuPathRenderers::kPLS) {
-        if (caps.shaderCaps()->plsPathRenderingSupport()) {
-            fChain.push_back(sk_make_sp<GrPLSPathRenderer>());
-        }
-    }
     if (options.fGpuPathRenderers & GpuPathRenderers::kDistanceField) {
         fChain.push_back(sk_make_sp<GrAADistanceFieldPathRenderer>());
     }
diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h
index b9fe7b2..f5b8fe9 100644
--- a/src/gpu/GrPrimitiveProcessor.h
+++ b/src/gpu/GrPrimitiveProcessor.h
@@ -35,16 +35,6 @@
 
 struct GrInitInvariantOutput;
 
-// Describes the state of pixel local storage with respect to the current draw.
-enum GrPixelLocalStorageState {
-    // The draw is actively updating PLS.
-    kDraw_GrPixelLocalStorageState,
-    // The draw is a "finish" operation which is reading from PLS and writing color.
-    kFinish_GrPixelLocalStorageState,
-    // The draw does not use PLS.
-    kDisabled_GrPixelLocalStorageState
-};
-
 /*
  * This class allows the GrPipeline to communicate information about the pipeline to a GrOp which
  * inform its decisions for GrPrimitiveProcessor setup. These are not properly part of the pipeline
@@ -167,10 +157,6 @@
 
     virtual bool isPathRendering() const { return false; }
 
-    virtual GrPixelLocalStorageState getPixelLocalStorageState() const {
-        return kDisabled_GrPixelLocalStorageState;
-    }
-
     /**
      * If non-null, overrides the dest color returned by GrGLSLFragmentShaderBuilder::dstColor().
      */
diff --git a/src/gpu/GrProcessorSet.cpp b/src/gpu/GrProcessorSet.cpp
index c61fe8b..e5beca0 100644
--- a/src/gpu/GrProcessorSet.cpp
+++ b/src/gpu/GrProcessorSet.cpp
@@ -38,11 +38,9 @@
 void GrProcessorSet::FragmentProcessorAnalysis::internalReset(const GrPipelineInput& colorInput,
                                                               const GrPipelineInput coverageInput,
                                                               const GrProcessorSet& processors,
-                                                              bool usesPLSDstRead,
                                                               const GrFragmentProcessor* clipFP,
                                                               const GrCaps& caps) {
     GrProcOptInfo colorInfo(colorInput);
-    fUsesPLSDstRead = usesPLSDstRead;
     fCompatibleWithCoverageAsAlpha = !coverageInput.isLCDCoverage();
 
     const GrFragmentProcessor* const* fps = processors.fFragmentProcessors.get();
@@ -91,15 +89,14 @@
 void GrProcessorSet::FragmentProcessorAnalysis::reset(const GrPipelineInput& colorInput,
                                                       const GrPipelineInput coverageInput,
                                                       const GrProcessorSet& processors,
-                                                      bool usesPLSDstRead,
                                                       const GrAppliedClip& appliedClip,
                                                       const GrCaps& caps) {
-    this->internalReset(colorInput, coverageInput, processors, usesPLSDstRead,
+    this->internalReset(colorInput, coverageInput, processors,
                         appliedClip.clipCoverageFragmentProcessor(), caps);
 }
 
 GrProcessorSet::FragmentProcessorAnalysis::FragmentProcessorAnalysis(
         const GrPipelineInput& colorInput, const GrPipelineInput coverageInput, const GrCaps& caps)
         : FragmentProcessorAnalysis() {
-    this->internalReset(colorInput, coverageInput, GrProcessorSet(GrPaint()), false, nullptr, caps);
+    this->internalReset(colorInput, coverageInput, GrProcessorSet(GrPaint()), nullptr, caps);
 }
diff --git a/src/gpu/GrProcessorSet.h b/src/gpu/GrProcessorSet.h
index 722bc04..de8bd69 100644
--- a/src/gpu/GrProcessorSet.h
+++ b/src/gpu/GrProcessorSet.h
@@ -56,12 +56,12 @@
     class FragmentProcessorAnalysis {
     public:
         FragmentProcessorAnalysis() = default;
-        // This version is used by a unit test that assumes no clip, no processors, and no PLS.
+        // This version is used by a unit test that assumes no clip and no fragment processors.
         FragmentProcessorAnalysis(const GrPipelineInput& colorInput,
                                   const GrPipelineInput coverageInput, const GrCaps&);
 
         void reset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
-                   const GrProcessorSet&, bool usesPLSDstRead, const GrAppliedClip&, const GrCaps&);
+                   const GrProcessorSet&, const GrAppliedClip&, const GrCaps&);
 
         int initialColorProcessorsToEliminate(GrColor* newInputColor) const {
             if (fInitialColorProcessorsToEliminate > 0) {
@@ -70,7 +70,6 @@
             return fInitialColorProcessorsToEliminate;
         }
 
-        bool usesPLSDstRead() const { return fUsesPLSDstRead; }
         bool usesLocalCoords() const { return fUsesLocalCoords; }
         bool isCompatibleWithCoverageAsAlpha() const { return fCompatibleWithCoverageAsAlpha; }
         bool isOutputColorOpaque() const {
@@ -89,13 +88,11 @@
 
     private:
         void internalReset(const GrPipelineInput& colorInput, const GrPipelineInput coverageInput,
-                           const GrProcessorSet&, bool usesPLSDstRead,
-                           const GrFragmentProcessor* clipFP, const GrCaps&);
+                           const GrProcessorSet&, const GrFragmentProcessor* clipFP, const GrCaps&);
 
         enum class ColorType { kUnknown, kOpaqueConstant, kConstant, kOpaque };
         enum class CoverageType { kNone, kSingleChannel, kLCD };
 
-        bool fUsesPLSDstRead = false;
         bool fCompatibleWithCoverageAsAlpha = true;
         bool fUsesLocalCoords = false;
         CoverageType fCoverageType = CoverageType::kNone;
diff --git a/src/gpu/GrRenderTargetOpList.cpp b/src/gpu/GrRenderTargetOpList.cpp
index 6edab11..6a7f757 100644
--- a/src/gpu/GrRenderTargetOpList.cpp
+++ b/src/gpu/GrRenderTargetOpList.cpp
@@ -298,18 +298,6 @@
     }
     args.fCaps = this->caps();
     args.fAnalysis = &analysis;
-    if (analysis.usesPLSDstRead()) {
-        int width = renderTargetContext->width();
-        int height = renderTargetContext->height();
-        SkIRect ibounds;
-        ibounds.fLeft = SkTPin(SkScalarFloorToInt(op->bounds().fLeft), 0, width);
-        ibounds.fTop = SkTPin(SkScalarFloorToInt(op->bounds().fTop), 0, height);
-        ibounds.fRight = SkTPin(SkScalarCeilToInt(op->bounds().fRight), 0, width);
-        ibounds.fBottom = SkTPin(SkScalarCeilToInt(op->bounds().fBottom), 0, height);
-        if (!appliedClip.addScissor(ibounds)) {
-            return;
-        }
-    }
 
     if (!renderTargetContext->accessRenderTarget()) {
         return;
diff --git a/src/gpu/GrShaderCaps.cpp b/src/gpu/GrShaderCaps.cpp
index 69af070..e3e6b07 100644
--- a/src/gpu/GrShaderCaps.cpp
+++ b/src/gpu/GrShaderCaps.cpp
@@ -47,7 +47,6 @@
     fTexelBufferSupport = false;
     fImageLoadStoreSupport = false;
     fShaderPrecisionVaries = false;
-    fPLSPathRenderingSupport = false;
     fDropsTileOnZeroDivide = false;
     fFBFetchSupport = false;
     fFBFetchNeedsCustomOutput = false;
@@ -67,8 +66,6 @@
     fExternalTextureSupport = false;
     fTexelFetchSupport = false;
 
-    fPixelLocalStorageSize = 0;
-
     fVersionDeclString = nullptr;
     fShaderDerivativeExtensionString = nullptr;
     fFragCoordConventionsExtensionString = nullptr;
diff --git a/src/gpu/GrXferProcessor.cpp b/src/gpu/GrXferProcessor.cpp
index a926812..3b8a2bf 100644
--- a/src/gpu/GrXferProcessor.cpp
+++ b/src/gpu/GrXferProcessor.cpp
@@ -188,7 +188,7 @@
                                      const GrProcessorSet::FragmentProcessorAnalysis& analysis) {
     bool result;
     if (factory) {
-        result = !analysis.usesPLSDstRead() && !caps.shaderCaps()->dstReadInShaderSupport() &&
+        result = !caps.shaderCaps()->dstReadInShaderSupport() &&
                  factory->willReadDstInShader(caps, analysis);
     } else {
         result = GrPorterDuffXPFactory::WillSrcOverNeedDstTexture(caps, analysis);
@@ -197,14 +197,6 @@
     return result;
 }
 
-bool GrXPFactory::willReadDstInShader(const GrCaps& caps,
-                                      const FragmentProcessorAnalysis& analysis) const {
-    if (analysis.usesPLSDstRead()) {
-        return true;
-    }
-    return this->onWillReadDstInShader(caps, analysis);
-}
-
 GrXferProcessor* GrXPFactory::createXferProcessor(const FragmentProcessorAnalysis& analysis,
                                                   bool hasMixedSamples,
                                                   const DstTexture* dstTexture,
diff --git a/src/gpu/GrXferProcessor.h b/src/gpu/GrXferProcessor.h
index c00bcbe..d6d6fa3 100644
--- a/src/gpu/GrXferProcessor.h
+++ b/src/gpu/GrXferProcessor.h
@@ -325,14 +325,11 @@
                                                    bool hasMixedSamples,
                                                    const DstTexture*) const = 0;
 
-    bool willReadDstInShader(const GrCaps& caps, const FragmentProcessorAnalysis& analysis) const;
-
     /**
      *  Returns true if the XP generated by this factory will explicitly read dst in the fragment
-     *  shader. This will not be called for draws that read from PLS since the dst color is always
-     *  available in such draws.
+     *  shader.
      */
-    virtual bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const = 0;
+    virtual bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const = 0;
 };
 #if defined(__GNUC__) || defined(__clang)
 #pragma GCC diagnostic pop
diff --git a/src/gpu/effects/GrCoverageSetOpXP.cpp b/src/gpu/effects/GrCoverageSetOpXP.cpp
index d86467e..52ebaad 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.cpp
+++ b/src/gpu/effects/GrCoverageSetOpXP.cpp
@@ -142,94 +142,6 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-class ShaderCSOXferProcessor : public GrXferProcessor {
-public:
-    ShaderCSOXferProcessor(const DstTexture* dstTexture,
-                           bool hasMixedSamples,
-                           SkRegion::Op regionOp,
-                           bool invertCoverage)
-        : INHERITED(dstTexture, true, hasMixedSamples)
-        , fRegionOp(regionOp)
-        , fInvertCoverage(invertCoverage) {
-        this->initClassID<ShaderCSOXferProcessor>();
-    }
-
-    const char* name() const override { return "Coverage Set Op Shader"; }
-
-    GrGLSLXferProcessor* createGLSLInstance() const override;
-
-    SkRegion::Op regionOp() const { return fRegionOp; }
-    bool invertCoverage() const { return fInvertCoverage; }
-
-private:
-    GrXferProcessor::OptFlags onGetOptimizations(const FragmentProcessorAnalysis&) const override {
-        // We never look at the color input
-        return GrXferProcessor::kIgnoreColor_OptFlag;
-    }
-
-    void onGetGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
-
-    bool onIsEqual(const GrXferProcessor& xpBase) const override {
-        const ShaderCSOXferProcessor& xp = xpBase.cast<ShaderCSOXferProcessor>();
-        return (fRegionOp == xp.fRegionOp &&
-                fInvertCoverage == xp.fInvertCoverage);
-    }
-
-    SkRegion::Op fRegionOp;
-    bool         fInvertCoverage;
-
-    typedef GrXferProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-class GLShaderCSOXferProcessor : public GrGLSLXferProcessor {
-public:
-    static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) {
-        const ShaderCSOXferProcessor& xp = processor.cast<ShaderCSOXferProcessor>();
-        b->add32(xp.regionOp());
-        uint32_t key = xp.invertCoverage() ?  0x0 : 0x1;
-        b->add32(key);
-    }
-
-private:
-    void emitBlendCodeForDstRead(GrGLSLXPFragmentBuilder* fragBuilder,
-                                 GrGLSLUniformHandler* uniformHandler,
-                                 const char* srcColor,
-                                 const char* srcCoverage,
-                                 const char* dstColor,
-                                 const char* outColor,
-                                 const char* outColorSecondary,
-                                 const GrXferProcessor& proc) override {
-        const ShaderCSOXferProcessor& xp = proc.cast<ShaderCSOXferProcessor>();
-
-        if (xp.invertCoverage()) {
-            fragBuilder->codeAppendf("%s = 1.0 - %s;", outColor, srcCoverage);
-        } else {
-            fragBuilder->codeAppendf("%s = %s;", outColor, srcCoverage);
-        }
-
-        GrGLSLBlend::AppendRegionOp(fragBuilder, outColor, dstColor, outColor, xp.regionOp());
-    }
-
-    void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) override {}
-
-    typedef GrGLSLXferProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-void ShaderCSOXferProcessor::onGetGLSLProcessorKey(const GrShaderCaps&,
-                                                   GrProcessorKeyBuilder* b) const {
-    GLShaderCSOXferProcessor::GenKey(*this, b);
-}
-
-GrGLSLXferProcessor* ShaderCSOXferProcessor::createGLSLInstance() const {
-    return new GLShaderCSOXferProcessor;
-}
-
-///////////////////////////////////////////////////////////////////////////////
-//
 constexpr GrCoverageSetOpXPFactory::GrCoverageSetOpXPFactory(SkRegion::Op regionOp,
                                                              bool invertCoverage)
         : fRegionOp(regionOp), fInvertCoverage(invertCoverage) {}
@@ -328,9 +240,6 @@
         return nullptr;
     }
 
-    if (analysis.usesPLSDstRead()) {
-        return new ShaderCSOXferProcessor(dst, hasMixedSamples, fRegionOp, fInvertCoverage);
-    }
     return CoverageSetOpXP::Create(fRegionOp, fInvertCoverage);
 }
 
diff --git a/src/gpu/effects/GrCoverageSetOpXP.h b/src/gpu/effects/GrCoverageSetOpXP.h
index ed6b9aa..02db11b 100644
--- a/src/gpu/effects/GrCoverageSetOpXP.h
+++ b/src/gpu/effects/GrCoverageSetOpXP.h
@@ -41,7 +41,7 @@
                                            bool hasMixedSamples,
                                            const DstTexture*) const override;
 
-    bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
+    bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
         return false;
     }
 
diff --git a/src/gpu/effects/GrCustomXfermode.cpp b/src/gpu/effects/GrCustomXfermode.cpp
index ccbab73..8895d7c 100644
--- a/src/gpu/effects/GrCustomXfermode.cpp
+++ b/src/gpu/effects/GrCustomXfermode.cpp
@@ -52,16 +52,11 @@
 #undef EQ_OFFSET
 }
 
-static bool can_use_hw_blend_equation(GrBlendEquation equation,
-                                      bool usePLSRead,
-                                      bool isLCDCoverage,
+static bool can_use_hw_blend_equation(GrBlendEquation equation, bool isLCDCoverage,
                                       const GrCaps& caps) {
     if (!caps.advancedBlendEquationSupport()) {
         return false;
     }
-    if (usePLSRead) {
-        return false;
-    }
     if (isLCDCoverage) {
         return false; // LCD coverage must be applied after the blend equation.
     }
@@ -334,7 +329,7 @@
 
     bool willReadsDst(const FragmentProcessorAnalysis&) const override { return true; }
 
-    bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
+    bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
 
     GR_DECLARE_XP_FACTORY_TEST;
 
@@ -352,20 +347,16 @@
                                                         bool hasMixedSamples,
                                                         const DstTexture* dstTexture) const {
     SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
-    if (can_use_hw_blend_equation(fHWBlendEquation, analysis.usesPLSDstRead(),
-                                  analysis.hasLCDCoverage(), caps)) {
+    if (can_use_hw_blend_equation(fHWBlendEquation, analysis.hasLCDCoverage(), caps)) {
         SkASSERT(!dstTexture || !dstTexture->texture());
         return new CustomXP(fMode, fHWBlendEquation);
     }
     return new CustomXP(dstTexture, hasMixedSamples, fMode);
 }
 
-bool CustomXPFactory::onWillReadDstInShader(const GrCaps& caps,
-                                            const FragmentProcessorAnalysis& analysis) const {
-    // This should not be called if we're using PLS dst read.
-    static constexpr bool kUsesPLSRead = false;
-    return !can_use_hw_blend_equation(fHWBlendEquation, kUsesPLSRead, analysis.hasLCDCoverage(),
-                                      caps);
+bool CustomXPFactory::willReadDstInShader(const GrCaps& caps,
+                                          const FragmentProcessorAnalysis& analysis) const {
+    return !can_use_hw_blend_equation(fHWBlendEquation, analysis.hasLCDCoverage(), caps);
 }
 
 GR_DEFINE_XP_FACTORY_TEST(CustomXPFactory);
diff --git a/src/gpu/effects/GrDisableColorXP.cpp b/src/gpu/effects/GrDisableColorXP.cpp
index 6bdf188..f95cd9b 100644
--- a/src/gpu/effects/GrDisableColorXP.cpp
+++ b/src/gpu/effects/GrDisableColorXP.cpp
@@ -90,7 +90,6 @@
         const FragmentProcessorAnalysis& analysis,
         bool hasMixedSamples,
         const DstTexture* dst) const {
-    SkASSERT(!analysis.usesPLSDstRead());
     return DisableColorXP::Create();
 }
 
diff --git a/src/gpu/effects/GrDisableColorXP.h b/src/gpu/effects/GrDisableColorXP.h
index b4cd00a..6a9f2ad 100644
--- a/src/gpu/effects/GrDisableColorXP.h
+++ b/src/gpu/effects/GrDisableColorXP.h
@@ -28,7 +28,7 @@
 
     constexpr GrDisableColorXPFactory() {}
 
-    bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
+    bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override {
         return false;
     }
 
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.cpp b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
index 7378874..c7e61ca 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.cpp
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.cpp
@@ -735,9 +735,6 @@
         const FragmentProcessorAnalysis& analysis,
         bool hasMixedSamples,
         const DstTexture* dstTexture) const {
-    if (analysis.usesPLSDstRead()) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, fBlendMode);
-    }
     BlendFormula blendFormula;
     if (analysis.hasLCDCoverage()) {
         if (SkBlendMode::kSrcOver == fBlendMode && analysis.hasKnownOutputColor() &&
@@ -768,8 +765,8 @@
     return (colorFormula.usesDstColor() || analysis.hasCoverage());
 }
 
-bool GrPorterDuffXPFactory::onWillReadDstInShader(const GrCaps& caps,
-                                                  const FragmentProcessorAnalysis& analysis) const {
+bool GrPorterDuffXPFactory::willReadDstInShader(const GrCaps& caps,
+                                                const FragmentProcessorAnalysis& analysis) const {
     if (caps.shaderCaps()->dualSourceBlendingSupport()) {
         return false;
     }
@@ -830,9 +827,6 @@
         const FragmentProcessorAnalysis& analysis,
         bool hasMixedSamples,
         const GrXferProcessor::DstTexture* dstTexture) {
-    if (analysis.usesPLSDstRead()) {
-        return new ShaderPDXferProcessor(dstTexture, hasMixedSamples, SkBlendMode::kSrcOver);
-    }
 
     // We want to not make an xfer processor if possible. Thus for the simple case where we are not
     // doing lcd blending we will just use our global SimpleSrcOverXP. This slightly differs from
diff --git a/src/gpu/effects/GrPorterDuffXferProcessor.h b/src/gpu/effects/GrPorterDuffXferProcessor.h
index 6d7dc90..b82c106 100644
--- a/src/gpu/effects/GrPorterDuffXferProcessor.h
+++ b/src/gpu/effects/GrPorterDuffXferProcessor.h
@@ -52,7 +52,7 @@
                                            bool hasMixedSamples,
                                            const DstTexture*) const override;
 
-    bool onWillReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
+    bool willReadDstInShader(const GrCaps&, const FragmentProcessorAnalysis&) const override;
 
     GR_DECLARE_XP_FACTORY_TEST;
     static void TestGetXPOutputTypes(const GrXferProcessor*, int* outPrimary, int* outSecondary);
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 0bcb7e8..d2e1899 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -290,17 +290,6 @@
             ctxInfo.glslGeneration() >= k330_GrGLSLGeneration; // We use this value for GLSL ES 3.0.
     }
 
-    if (ctxInfo.hasExtension("GL_EXT_shader_pixel_local_storage")) {
-        #define GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT 0x8F63
-        GR_GL_GetIntegerv(gli, GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT,
-                          &shaderCaps->fPixelLocalStorageSize);
-        shaderCaps->fPLSPathRenderingSupport = shaderCaps->fFBFetchSupport;
-    }
-    else {
-        shaderCaps->fPixelLocalStorageSize = 0;
-        shaderCaps->fPLSPathRenderingSupport = false;
-    }
-
     // Protect ourselves against tracking huge amounts of texture state.
     static const uint8_t kMaxSaneSamplers = 32;
     GrGLint maxSamplers;
diff --git a/src/gpu/gl/GrGLGpu.cpp b/src/gpu/gl/GrGLGpu.cpp
index cfbef9f..bda1c16 100644
--- a/src/gpu/gl/GrGLGpu.cpp
+++ b/src/gpu/gl/GrGLGpu.cpp
@@ -16,7 +16,6 @@
 #include "GrGLTextureRenderTarget.h"
 #include "GrGpuResourcePriv.h"
 #include "GrMesh.h"
-#include "GrPLSGeometryProcessor.h"
 #include "GrPipeline.h"
 #include "GrRenderTargetPriv.h"
 #include "GrShaderCaps.h"
@@ -32,7 +31,6 @@
 #include "SkTemplates.h"
 #include "SkTypes.h"
 #include "builders/GrGLShaderStringBuilder.h"
-#include "glsl/GrGLSLPLSPathRendering.h"
 #include "instanced/GLInstancedRendering.h"
 
 #define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
@@ -206,8 +204,6 @@
     , fTempDstFBOID(0)
     , fStencilClearFBOID(0)
     , fHWMaxUsedBufferTextureUnit(-1)
-    , fHWPLSEnabled(false)
-    , fPLSHasBeenUsed(false)
     , fHWMinSampleShading(0.0) {
     for (size_t i = 0; i < SK_ARRAY_COUNT(fCopyPrograms); ++i) {
         fCopyPrograms[i].fProgram = 0;
@@ -216,7 +212,6 @@
         fMipmapPrograms[i].fProgram = 0;
     }
     fWireRectProgram.fProgram = 0;
-    fPLSSetupProgram.fProgram = 0;
 
     SkASSERT(ctx);
     fCaps.reset(SkRef(ctx->caps()));
@@ -274,7 +269,6 @@
     fCopyProgramArrayBuffer.reset();
     fMipmapProgramArrayBuffer.reset();
     fWireRectArrayBuffer.reset();
-    fPLSSetupProgram.fArrayBuffer.reset();
 
     if (0 != fHWProgramID) {
         // detach the current program so there is no confusion on OpenGL's part
@@ -308,129 +302,9 @@
         GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
     }
 
-    if (0 != fPLSSetupProgram.fProgram) {
-        GL_CALL(DeleteProgram(fPLSSetupProgram.fProgram));
-    }
-
     delete fProgramCache;
 }
 
-bool GrGLGpu::createPLSSetupProgram() {
-    if (!fPLSSetupProgram.fArrayBuffer) {
-        static const GrGLfloat vdata[] = {
-            0, 0,
-            0, 1,
-            1, 0,
-            1, 1
-        };
-        fPLSSetupProgram.fArrayBuffer.reset(GrGLBuffer::Create(this, sizeof(vdata),
-                                                               kVertex_GrBufferType,
-                                                               kStatic_GrAccessPattern, vdata));
-        if (!fPLSSetupProgram.fArrayBuffer) {
-            return false;
-        }
-    }
-
-    SkASSERT(!fPLSSetupProgram.fProgram);
-    GL_CALL_RET(fPLSSetupProgram.fProgram, CreateProgram());
-    if (!fPLSSetupProgram.fProgram) {
-        return false;
-    }
-
-    const GrShaderCaps* shaderCaps = this->caps()->shaderCaps();
-    const char* version = shaderCaps->versionDeclString();
-
-    GrShaderVar aVertex("a_vertex", kVec2f_GrSLType, GrShaderVar::kIn_TypeModifier);
-    GrShaderVar uTexCoordXform("u_texCoordXform", kVec4f_GrSLType,
-                               GrShaderVar::kUniform_TypeModifier);
-    GrShaderVar uPosXform("u_posXform", kVec4f_GrSLType, GrShaderVar::kUniform_TypeModifier);
-    GrShaderVar uTexture("u_texture", kTexture2DSampler_GrSLType,
-                         GrShaderVar::kUniform_TypeModifier);
-    GrShaderVar vTexCoord("v_texCoord", kVec2f_GrSLType, GrShaderVar::kOut_TypeModifier);
-
-    SkString vshaderTxt(version);
-    if (shaderCaps->noperspectiveInterpolationSupport()) {
-        if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
-            vshaderTxt.appendf("#extension %s : require\n", extension);
-        }
-        vTexCoord.addModifier("noperspective");
-    }
-    aVertex.appendDecl(shaderCaps, &vshaderTxt);
-    vshaderTxt.append(";");
-    uTexCoordXform.appendDecl(shaderCaps, &vshaderTxt);
-    vshaderTxt.append(";");
-    uPosXform.appendDecl(shaderCaps, &vshaderTxt);
-    vshaderTxt.append(";");
-    vTexCoord.appendDecl(shaderCaps, &vshaderTxt);
-    vshaderTxt.append(";");
-
-    vshaderTxt.append(
-        "// PLS Setup Program VS\n"
-        "void main() {"
-        "  gl_Position.xy = a_vertex * u_posXform.xy + u_posXform.zw;"
-        "  gl_Position.zw = vec2(0, 1);"
-        "}"
-    );
-
-    SkString fshaderTxt(version);
-    if (shaderCaps->noperspectiveInterpolationSupport()) {
-        if (const char* extension = shaderCaps->noperspectiveInterpolationExtensionString()) {
-            fshaderTxt.appendf("#extension %s : require\n", extension);
-        }
-    }
-    fshaderTxt.append("#extension ");
-    fshaderTxt.append(shaderCaps->fbFetchExtensionString());
-    fshaderTxt.append(" : require\n");
-    fshaderTxt.append("#extension GL_EXT_shader_pixel_local_storage : require\n");
-    GrGLSLAppendDefaultFloatPrecisionDeclaration(kDefault_GrSLPrecision, *shaderCaps, &fshaderTxt);
-    vTexCoord.setTypeModifier(GrShaderVar::kIn_TypeModifier);
-    vTexCoord.appendDecl(shaderCaps, &fshaderTxt);
-    fshaderTxt.append(";");
-    uTexture.appendDecl(shaderCaps, &fshaderTxt);
-    fshaderTxt.append(";");
-
-    fshaderTxt.appendf(
-        "// PLS Setup Program FS\n"
-        GR_GL_PLS_PATH_DATA_DECL
-        "void main() {\n"
-        "    " GR_GL_PLS_DSTCOLOR_NAME " = gl_LastFragColorARM;\n"
-        "    pls.windings = ivec4(0, 0, 0, 0);\n"
-        "}"
-    );
-
-    const char* str;
-    GrGLint length;
-
-    str = vshaderTxt.c_str();
-    length = SkToInt(vshaderTxt.size());
-    SkSL::Program::Settings settings;
-    settings.fCaps = shaderCaps;
-    SkSL::Program::Inputs inputs;
-    GrGLuint vshader = GrGLCompileAndAttachShader(*fGLContext, fPLSSetupProgram.fProgram,
-                                                  GR_GL_VERTEX_SHADER, &str, &length, 1, &fStats,
-                                                  settings, &inputs);
-    SkASSERT(inputs.isEmpty());
-
-    str = fshaderTxt.c_str();
-    length = SkToInt(fshaderTxt.size());
-    GrGLuint fshader = GrGLCompileAndAttachShader(*fGLContext, fPLSSetupProgram.fProgram,
-                                                  GR_GL_FRAGMENT_SHADER, &str, &length, 1, &fStats,
-                                                  settings, &inputs);
-    SkASSERT(inputs.isEmpty());
-
-    GL_CALL(LinkProgram(fPLSSetupProgram.fProgram));
-
-    GL_CALL_RET(fPLSSetupProgram.fPosXformUniform, GetUniformLocation(fPLSSetupProgram.fProgram,
-                                                                  "u_posXform"));
-
-    GL_CALL(BindAttribLocation(fPLSSetupProgram.fProgram, 0, "a_vertex"));
-
-    GL_CALL(DeleteShader(vshader));
-    GL_CALL(DeleteShader(fshader));
-
-    return true;
-}
-
 void GrGLGpu::disconnect(DisconnectType type) {
     INHERITED::disconnect(type);
     if (DisconnectType::kCleanup == type) {
@@ -459,9 +333,6 @@
         if (fWireRectProgram.fProgram) {
             GL_CALL(DeleteProgram(fWireRectProgram.fProgram));
         }
-        if (fPLSSetupProgram.fProgram) {
-            GL_CALL(DeleteProgram(fPLSSetupProgram.fProgram));
-        }
     } else {
         if (fProgramCache) {
             fProgramCache->abandon();
@@ -485,8 +356,6 @@
     }
     fWireRectProgram.fProgram = 0;
     fWireRectArrayBuffer.reset();
-    fPLSSetupProgram.fProgram = 0;
-    fPLSSetupProgram.fArrayBuffer.reset();
     if (this->glCaps().shaderCaps()->pathRenderingSupport()) {
         this->glPathRendering()->disconnect(type);
     }
@@ -2672,25 +2541,6 @@
     return new GrGLGpuCommandBuffer(this);
 }
 
-void GrGLGpu::finishOpList() {
-    if (fPLSHasBeenUsed) {
-        /* There is an ARM driver bug where if we use PLS, and then draw a frame which does not
-         * use PLS, it leaves garbage all over the place. As a workaround, we use PLS in a
-         * trivial way every frame. And since we use it every frame, there's never a point at which
-         * it becomes safe to stop using this workaround once we start.
-         */
-        this->disableScissor();
-        this->disableWindowRectangles();
-        // using PLS in the presence of MSAA results in GL_INVALID_OPERATION
-        this->flushHWAAState(nullptr, false, false);
-        SkASSERT(!fHWPLSEnabled);
-        SkASSERT(fMSAAEnabled != kYes_TriState);
-        GL_CALL(Enable(GR_GL_SHADER_PIXEL_LOCAL_STORAGE));
-        this->stampPLSSetupRect(SkRect::MakeXYWH(-100.0f, -100.0f, 0.01f, 0.01f));
-        GL_CALL(Disable(GR_GL_SHADER_PIXEL_LOCAL_STORAGE));
-    }
-}
-
 void GrGLGpu::flushRenderTarget(GrGLRenderTarget* target, const SkIRect* bounds, bool disableSRGB) {
     SkASSERT(target);
 
@@ -2786,16 +2636,6 @@
     if (!this->flushGLState(pipeline, primProc, hasPoints)) {
         return;
     }
-    GrPixelLocalStorageState plsState = primProc.getPixelLocalStorageState();
-    if (!fHWPLSEnabled && plsState !=
-        GrPixelLocalStorageState::kDisabled_GrPixelLocalStorageState) {
-        GL_CALL(Enable(GR_GL_SHADER_PIXEL_LOCAL_STORAGE));
-        this->setupPixelLocalStorage(pipeline, primProc);
-        fHWPLSEnabled = true;
-    }
-    if (plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState) {
-        this->disableStencil();
-    }
 
     for (int i = 0; i < meshCount; ++i) {
         if (GrXferBarrierType barrierType = pipeline.xferBarrierType(*this->caps())) {
@@ -2840,16 +2680,6 @@
         } while ((nonInstMesh = iter.next()));
     }
 
-    if (fHWPLSEnabled && plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState) {
-        // PLS draws always involve multiple draws, finishing up with a non-PLS
-        // draw that writes to the color buffer. That draw ends up here; we wait
-        // until after it is complete to actually disable PLS.
-        GL_CALL(Disable(GR_GL_SHADER_PIXEL_LOCAL_STORAGE));
-        fHWPLSEnabled = false;
-        this->disableScissor();
-        this->disableWindowRectangles();
-    }
-
 #if SWAP_PER_DRAW
     glFlush();
     #if defined(SK_BUILD_FOR_MAC)
@@ -2864,65 +2694,6 @@
 #endif
 }
 
-void GrGLGpu::stampPLSSetupRect(const SkRect& bounds) {
-    SkASSERT(this->caps()->shaderCaps()->plsPathRenderingSupport());
-
-    if (!fPLSSetupProgram.fProgram) {
-        if (!this->createPLSSetupProgram()) {
-            SkDebugf("Failed to create PLS setup program.\n");
-            return;
-        }
-    }
-
-    GL_CALL(UseProgram(fPLSSetupProgram.fProgram));
-    this->fHWVertexArrayState.setVertexArrayID(this, 0);
-
-    GrGLAttribArrayState* attribs = this->fHWVertexArrayState.bindInternalVertexArray(this);
-    attribs->set(this, 0, fPLSSetupProgram.fArrayBuffer.get(), kVec2f_GrVertexAttribType,
-                 2 * sizeof(GrGLfloat), 0);
-    attribs->disableUnusedArrays(this, 0x1);
-
-    GL_CALL(Uniform4f(fPLSSetupProgram.fPosXformUniform, bounds.width(), bounds.height(),
-                      bounds.left(), bounds.top()));
-
-    GrXferProcessor::BlendInfo blendInfo;
-    blendInfo.reset();
-    this->flushBlend(blendInfo, GrSwizzle());
-    this->flushColorWrite(true);
-    this->flushDrawFace(GrDrawFace::kBoth);
-    if (!fHWStencilSettings.isDisabled()) {
-        GL_CALL(Disable(GR_GL_STENCIL_TEST));
-    }
-    GL_CALL(DrawArrays(GR_GL_TRIANGLE_STRIP, 0, 4));
-    GL_CALL(UseProgram(fHWProgramID));
-    if (!fHWStencilSettings.isDisabled()) {
-        GL_CALL(Enable(GR_GL_STENCIL_TEST));
-    }
-}
-
-void GrGLGpu::setupPixelLocalStorage(const GrPipeline& pipeline,
-                                     const GrPrimitiveProcessor& primProc) {
-    fPLSHasBeenUsed = true;
-    const SkRect& bounds =
-            static_cast<const GrPLSGeometryProcessor&>(primProc).getBounds();
-    // setup pixel local storage -- this means capturing and storing the current framebuffer color
-    // and initializing the winding counts to zero
-    GrRenderTarget* rt = pipeline.getRenderTarget();
-    SkScalar width = SkIntToScalar(rt->width());
-    SkScalar height = SkIntToScalar(rt->height());
-    // dst rect edges in NDC (-1 to 1)
-    // having some issues with rounding, just expand the bounds by 1 and trust the scissor to keep
-    // it contained properly
-    GrGLfloat dx0 = 2.0f * (bounds.left() - 1) / width - 1.0f;
-    GrGLfloat dx1 = 2.0f * (bounds.right() + 1) / width - 1.0f;
-    GrGLfloat dy0 = -2.0f * (bounds.top() - 1) / height + 1.0f;
-    GrGLfloat dy1 = -2.0f * (bounds.bottom() + 1) / height + 1.0f;
-    SkRect deviceBounds = SkRect::MakeXYWH(dx0, dy0, dx1 - dx0, dy1 - dy0);
-
-    GL_CALL(Enable(GR_GL_FETCH_PER_SAMPLE_ARM));
-    this->stampPLSSetupRect(deviceBounds);
-}
-
 void GrGLGpu::onResolveRenderTarget(GrRenderTarget* target) {
     GrGLRenderTarget* rt = static_cast<GrGLRenderTarget*>(target);
     if (rt->needsResolve()) {
diff --git a/src/gpu/gl/GrGLGpu.h b/src/gpu/gl/GrGLGpu.h
index 57068fb..564ed76 100644
--- a/src/gpu/gl/GrGLGpu.h
+++ b/src/gpu/gl/GrGLGpu.h
@@ -144,8 +144,6 @@
 
     void drawDebugWireRect(GrRenderTarget*, const SkIRect&, GrColor) override;
 
-    void finishOpList() override;
-
     GrFence SK_WARN_UNUSED_RESULT insertFence() override;
     bool waitFence(GrFence, uint64_t timeout) override;
     void deleteFence(GrFence) const override;
@@ -273,10 +271,6 @@
                                       const SkIPoint& dstPoint);
     bool generateMipmap(GrGLTexture* texture, bool gammaCorrect);
 
-    void stampPLSSetupRect(const SkRect& bounds);
-
-    void setupPixelLocalStorage(const GrPipeline&, const GrPrimitiveProcessor&);
-
     static bool BlendCoeffReferencesConstant(GrBlendCoeff coeff);
 
     class ProgramCache : public ::SkNoncopyable {
@@ -404,7 +398,6 @@
     bool createCopyProgram(GrTexture* srcTexture);
     bool createMipmapProgram(int progIdx);
     bool createWireRectProgram();
-    bool createPLSSetupProgram();
 
     // GL program-related state
     ProgramCache*               fProgramCache;
@@ -647,15 +640,6 @@
         return (wide ? 0x2 : 0x0) | (tall ? 0x1 : 0x0);
     }
 
-    struct {
-        GrGLuint          fProgram;
-        GrGLint           fPosXformUniform;
-        sk_sp<GrGLBuffer> fArrayBuffer;
-    }                                       fPLSSetupProgram;
-
-    bool                                    fHWPLSEnabled;
-    bool                                    fPLSHasBeenUsed;
-
     float                                   fHWMinSampleShading;
 
     typedef GrGpu INHERITED;
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index f09b668..d9e73f0 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -77,12 +77,9 @@
 
     this->setFragmentData(primProc, pipeline, &nextSamplerIdx);
 
-    if (primProc.getPixelLocalStorageState() !=
-        GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
-        const GrXferProcessor& xp = pipeline.getXferProcessor();
-        fXferProcessor->setData(fProgramDataManager, xp);
-        this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
-    }
+    const GrXferProcessor& xp = pipeline.getXferProcessor();
+    fXferProcessor->setData(fProgramDataManager, xp);
+    this->bindTextures(xp, pipeline.getAllowSRGBInputs(), &nextSamplerIdx);
 }
 
 void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc,
@@ -93,12 +90,6 @@
     while (const GrFragmentProcessor* fp  = iter.next()) {
         this->generateMipmaps(*fp, pipeline.getAllowSRGBInputs());
     }
-
-    if (primProc.getPixelLocalStorageState() !=
-        GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
-        const GrXferProcessor& xp = pipeline.getXferProcessor();
-        this->generateMipmaps(xp, pipeline.getAllowSRGBInputs());
-    }
 }
 
 void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc,
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
index f583420..a1f5173 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.cpp
@@ -96,13 +96,6 @@
 bool GrGLSLFragmentShaderBuilder::enableFeature(GLSLFeature feature) {
     const GrShaderCaps& shaderCaps = *fProgramBuilder->shaderCaps();
     switch (feature) {
-        case kPixelLocalStorage_GLSLFeature:
-            if (shaderCaps.pixelLocalStorageSize() <= 0) {
-                return false;
-            }
-            this->addFeature(1 << kPixelLocalStorage_GLSLFeature,
-                             "GL_EXT_shader_pixel_local_storage");
-            return true;
         case kMultisampleInterpolation_GLSLFeature:
             if (!shaderCaps.multisampleInterpolationSupport()) {
                 return false;
diff --git a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
index ab806ea..764f3bd 100644
--- a/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
+++ b/src/gpu/glsl/GrGLSLFragmentShaderBuilder.h
@@ -29,7 +29,6 @@
      * if code is added that uses one of these features without calling enableFeature()
      */
     enum GLSLFeature {
-        kPixelLocalStorage_GLSLFeature = kLastGLSLPrivateFeature + 1,
         kMultisampleInterpolation_GLSLFeature
     };
 
diff --git a/src/gpu/glsl/GrGLSLPLSPathRendering.h b/src/gpu/glsl/GrGLSLPLSPathRendering.h
deleted file mode 100644
index 60889e9..0000000
--- a/src/gpu/glsl/GrGLSLPLSPathRendering.h
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2016 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#define GR_GL_PLS_DSTCOLOR_NAME  "pls.dstColor"
-#define GR_GL_PLS_PATH_DATA_DECL "__pixel_localEXT PLSData {\n"\
-                                 "    layout(rgba8i) ivec4 windings;\n"\
-                                 "    layout(rgba8) vec4 dstColor;\n"\
-                                 "} pls;\n"
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
index 385026a..1fcf040 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp
@@ -62,12 +62,8 @@
     this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage);
 
     this->emitAndInstallFragProcs(inputColor, inputCoverage);
-    if (primProc.getPixelLocalStorageState() !=
-        GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) {
-        this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor,
-                                     *inputCoverage, primProc.getPixelLocalStorageState());
-        this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
-    }
+    this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, *inputCoverage);
+    this->emitFSOutputSwizzle(this->pipeline().getXferProcessor().hasSecondaryOutput());
 
     return this->checkSamplerCounts() && this->checkImageStorageCounts();
 }
@@ -217,8 +213,7 @@
 
 void GrGLSLProgramBuilder::emitAndInstallXferProc(const GrXferProcessor& xp,
                                                   const GrGLSLExpr4& colorIn,
-                                                  const GrGLSLExpr4& coverageIn,
-                                                  GrPixelLocalStorageState plsState) {
+                                                  const GrGLSLExpr4& coverageIn) {
     // Program builders have a bit of state we need to clear with each effect
     AutoStageAdvance adv(this);
 
@@ -243,7 +238,6 @@
     SkSTArray<2, ImageStorageHandle> imageStorageArray(xp.numImageStorages());
     this->emitSamplersAndImageStorages(xp, &texSamplers, &bufferSamplers, &imageStorageArray);
 
-    bool usePLSDstRead = (plsState == GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState);
     GrGLSLXferProcessor::EmitArgs args(&fFS,
                                        this->uniformHandler(),
                                        this->shaderCaps(),
@@ -253,8 +247,7 @@
                                        fFS.getSecondaryColorOutputName(),
                                        texSamplers.begin(),
                                        bufferSamplers.begin(),
-                                       imageStorageArray.begin(),
-                                       usePLSDstRead);
+                                       imageStorageArray.begin());
     fXferProcessor->emitCode(args);
 
     // We have to check that effects and the code they emit are consistent, ie if an effect
diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h
index 321d81c..7486646 100644
--- a/src/gpu/glsl/GrGLSLProgramBuilder.h
+++ b/src/gpu/glsl/GrGLSLProgramBuilder.h
@@ -154,8 +154,7 @@
                                 GrGLSLExpr4* output);
     void emitAndInstallXferProc(const GrXferProcessor&,
                                 const GrGLSLExpr4& colorIn,
-                                const GrGLSLExpr4& coverageIn,
-                                GrPixelLocalStorageState plsState);
+                                const GrGLSLExpr4& coverageIn);
     void emitSamplersAndImageStorages(const GrProcessor& processor,
                                       SkTArray<SamplerHandle>* outTexSamplerHandles,
                                       SkTArray<SamplerHandle>* outBufferSamplerHandles,
diff --git a/src/gpu/glsl/GrGLSLXferProcessor.h b/src/gpu/glsl/GrGLSLXferProcessor.h
index 90c1bce..b4bde37 100644
--- a/src/gpu/glsl/GrGLSLXferProcessor.h
+++ b/src/gpu/glsl/GrGLSLXferProcessor.h
@@ -35,20 +35,18 @@
                  const char* outputSecondary,
                  const SamplerHandle* texSamplers,
                  const SamplerHandle* bufferSamplers,
-                 const ImageStorageHandle* imageStorages,
-                 const bool usePLSDstRead)
-            : fXPFragBuilder(fragBuilder)
-            , fUniformHandler(uniformHandler)
-            , fShaderCaps(caps)
-            , fXP(xp)
-            , fInputColor(inputColor)
-            , fInputCoverage(inputCoverage)
-            , fOutputPrimary(outputPrimary)
-            , fOutputSecondary(outputSecondary)
-            , fTexSamplers(texSamplers)
-            , fBufferSamplers(bufferSamplers)
-            , fImageStorages(imageStorages)
-            , fUsePLSDstRead(usePLSDstRead) {}
+                 const ImageStorageHandle* imageStorages)
+                : fXPFragBuilder(fragBuilder)
+                , fUniformHandler(uniformHandler)
+                , fShaderCaps(caps)
+                , fXP(xp)
+                , fInputColor(inputColor)
+                , fInputCoverage(inputCoverage)
+                , fOutputPrimary(outputPrimary)
+                , fOutputSecondary(outputSecondary)
+                , fTexSamplers(texSamplers)
+                , fBufferSamplers(bufferSamplers)
+                , fImageStorages(imageStorages) {}
 
         GrGLSLXPFragmentBuilder* fXPFragBuilder;
         GrGLSLUniformHandler* fUniformHandler;
@@ -61,7 +59,6 @@
         const SamplerHandle* fTexSamplers;
         const SamplerHandle* fBufferSamplers;
         const ImageStorageHandle* fImageStorages;
-        bool fUsePLSDstRead;
     };
     /**
      * This is similar to emitCode() in the base class, except it takes a full shader builder.
diff --git a/src/gpu/ops/GrDrawOp.h b/src/gpu/ops/GrDrawOp.h
index 1512642..18c218f 100644
--- a/src/gpu/ops/GrDrawOp.h
+++ b/src/gpu/ops/GrDrawOp.h
@@ -70,8 +70,7 @@
                            const GrCaps& caps) const {
         FragmentProcessorAnalysisInputs input;
         this->getFragmentProcessorAnalysisInputs(&input);
-        analysis->reset(*input.colorInput(), *input.coverageInput(), processors,
-                        input.usesPLSDstRead(), appliedClip, caps);
+        analysis->reset(*input.colorInput(), *input.coverageInput(), processors, appliedClip, caps);
     }
 
 protected:
@@ -121,14 +120,9 @@
         GrPipelineInput* colorInput() { return &fColorInput; }
         GrPipelineInput* coverageInput() { return &fCoverageInput; }
 
-        void setUsesPLSDstRead() { fUsesPLSDstRead = true; }
-
-        bool usesPLSDstRead() const { return fUsesPLSDstRead; }
-
     private:
         GrPipelineInput fColorInput;
         GrPipelineInput fCoverageInput;
-        bool fUsesPLSDstRead = false;
     };
 
 private:
diff --git a/src/gpu/ops/GrPLSPathRenderer.cpp b/src/gpu/ops/GrPLSPathRenderer.cpp
deleted file mode 100644
index ac2f4fc..0000000
--- a/src/gpu/ops/GrPLSPathRenderer.cpp
+++ /dev/null
@@ -1,946 +0,0 @@
-/*
- * Copyright 2015 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#include "GrPLSPathRenderer.h"
-
-#include "GrCaps.h"
-#include "GrContext.h"
-#include "GrDefaultGeoProcFactory.h"
-#include "GrDrawOpTest.h"
-#include "GrOpFlushState.h"
-#include "GrPLSGeometryProcessor.h"
-#include "GrPathUtils.h"
-#include "GrPipelineBuilder.h"
-#include "GrProcessor.h"
-#include "GrStyle.h"
-#include "GrTessellator.h"
-#include "SkChunkAlloc.h"
-#include "SkGeometry.h"
-#include "SkPathPriv.h"
-#include "SkString.h"
-#include "SkTSort.h"
-#include "SkTraceEvent.h"
-#include "gl/builders/GrGLProgramBuilder.h"
-#include "glsl/GrGLSLGeometryProcessor.h"
-#include "glsl/GrGLSLPLSPathRendering.h"
-#include "ops/GrMeshDrawOp.h"
-
-GrPLSPathRenderer::GrPLSPathRenderer() {
-}
-
-struct PLSVertex {
-    SkPoint  fPos;
-    // for triangles, these are the three triangle vertices
-    // for quads, vert1 is the texture UV coords, and vert2 and vert3 are the line segment
-    // comprising the flat edge of the quad
-    SkPoint  fVert1;
-    SkPoint  fVert2;
-    SkPoint  fVert3;
-    int fWinding;
-};
-typedef SkTArray<PLSVertex, true> PLSVertices;
-
-typedef SkTArray<SkPoint, true> FinishVertices;
-
-static const float kCubicTolerance = 0.5f;
-static const float kConicTolerance = 0.5f;
-
-static const float kBloatSize = 1.0f;
-
-static const float kBloatLimit = 640000.0f;
-
-#define kQuadNumVertices 5
-static void add_quad(SkPoint pts[3], PLSVertices& vertices) {
-    SkPoint normal = SkPoint::Make(pts[0].fY - pts[2].fY,
-                                   pts[2].fX - pts[0].fX);
-    normal.setLength(kBloatSize);
-    SkScalar cross = (pts[1] - pts[0]).cross(pts[2] - pts[0]);
-    if (cross < 0) {
-        normal = -normal;
-    }
-    PLSVertex quad[kQuadNumVertices];
-    quad[0].fPos = pts[0] + normal;
-    quad[1].fPos = pts[0] - normal;
-    quad[2].fPos = pts[1] - normal;
-    quad[3].fPos = pts[2] - normal;
-    quad[4].fPos = pts[2] + normal;
-    for (int i = 0; i < kQuadNumVertices; i++) {
-        quad[i].fWinding = cross < 0 ? 1 : -1;
-        if (cross > 0.0) {
-            quad[i].fVert2 = pts[0];
-            quad[i].fVert3 = pts[2];
-        }
-        else {
-            quad[i].fVert2 = pts[2];
-            quad[i].fVert3 = pts[0];
-        }
-    }
-    GrPathUtils::QuadUVMatrix DevToUV(pts);
-    DevToUV.apply<kQuadNumVertices, sizeof(PLSVertex), sizeof(SkPoint)>(quad);
-    for (int i = 2; i < kQuadNumVertices; i++) {
-        vertices.push_back(quad[0]);
-        vertices.push_back(quad[i - 1]);
-        vertices.push_back(quad[i]);
-    }
-}
-
-/* Used by bloat_tri; outsets a single point. */
-static bool outset(SkPoint* p1, SkPoint line1, SkPoint line2) {
-    // rotate the two line vectors 90 degrees to form the normals, and compute
-    // the dot product of the normals
-    SkScalar dotProd = line1.fY * line2.fY + line1.fX * line2.fX;
-    SkScalar lengthSq = 1.0f / ((1.0f - dotProd) / 2.0f);
-    if (lengthSq > kBloatLimit) {
-        return false;
-    }
-    SkPoint bisector = line1 + line2;
-    bisector.setLength(SkScalarSqrt(lengthSq) * kBloatSize);
-    *p1 += bisector;
-    return true;
-}
-
-/* Bloats a triangle so as to create a border kBloatSize pixels wide all around it. */
-static bool bloat_tri(SkPoint pts[3]) {
-    SkPoint line1 = pts[0] - pts[1];
-    line1.normalize();
-    SkPoint line2 = pts[0] - pts[2];
-    line2.normalize();
-    SkPoint line3 = pts[1] - pts[2];
-    line3.normalize();
-
-    SkPoint result[3];
-    result[0] = pts[0];
-    if (!outset(&result[0], line1, line2)) {
-        return false;
-    }
-    result[1] = pts[1];
-    if (!outset(&result[1], -line1, line3)) {
-        return false;
-    }
-    result[2] = pts[2];
-    if (!outset(&result[2], -line3, -line2)) {
-        return false;
-    }
-    pts[0] = result[0];
-    pts[1] = result[1];
-    pts[2] = result[2];
-    return true;
-}
-
-static bool get_geometry(const SkPath& path, const SkMatrix& m, PLSVertices& triVertices,
-                         PLSVertices& quadVertices, GrResourceProvider* resourceProvider,
-                         SkRect bounds) {
-    SkScalar screenSpaceTol = GrPathUtils::kDefaultTolerance;
-    SkScalar tol = GrPathUtils::scaleToleranceToSrc(screenSpaceTol, m, bounds);
-    int contourCnt;
-    int maxPts = GrPathUtils::worstCasePointCount(path, &contourCnt, tol);
-    if (maxPts <= 0) {
-        return 0;
-    }
-    SkPath linesOnlyPath;
-    linesOnlyPath.setFillType(path.getFillType());
-    SkSTArray<15, SkPoint, true> quadPoints;
-    SkPath::Iter iter(path, true);
-    bool done = false;
-    while (!done) {
-        SkPoint pts[4];
-        SkPath::Verb verb = iter.next(pts);
-        switch (verb) {
-            case SkPath::kMove_Verb:
-                SkASSERT(quadPoints.count() % 3 == 0);
-                for (int i = 0; i < quadPoints.count(); i += 3) {
-                    add_quad(&quadPoints[i], quadVertices);
-                }
-                quadPoints.reset();
-                m.mapPoints(&pts[0], 1);
-                linesOnlyPath.moveTo(pts[0]);
-                break;
-            case SkPath::kLine_Verb:
-                m.mapPoints(&pts[1], 1);
-                linesOnlyPath.lineTo(pts[1]);
-                break;
-            case SkPath::kQuad_Verb:
-                m.mapPoints(pts, 3);
-                linesOnlyPath.lineTo(pts[2]);
-                quadPoints.push_back(pts[0]);
-                quadPoints.push_back(pts[1]);
-                quadPoints.push_back(pts[2]);
-                break;
-            case SkPath::kCubic_Verb: {
-                m.mapPoints(pts, 4);
-                SkSTArray<15, SkPoint, true> quads;
-                GrPathUtils::convertCubicToQuads(pts, kCubicTolerance, &quads);
-                int count = quads.count();
-                for (int q = 0; q < count; q += 3) {
-                    linesOnlyPath.lineTo(quads[q + 2]);
-                    quadPoints.push_back(quads[q]);
-                    quadPoints.push_back(quads[q + 1]);
-                    quadPoints.push_back(quads[q + 2]);
-                }
-                break;
-            }
-            case SkPath::kConic_Verb: {
-                m.mapPoints(pts, 3);
-                SkScalar weight = iter.conicWeight();
-                SkAutoConicToQuads converter;
-                const SkPoint* quads = converter.computeQuads(pts, weight, kConicTolerance);
-                int count = converter.countQuads();
-                for (int i = 0; i < count; ++i) {
-                    linesOnlyPath.lineTo(quads[2 * i + 2]);
-                    quadPoints.push_back(quads[2 * i]);
-                    quadPoints.push_back(quads[2 * i + 1]);
-                    quadPoints.push_back(quads[2 * i + 2]);
-                }
-                break;
-            }
-            case SkPath::kClose_Verb:
-                linesOnlyPath.close();
-                break;
-            case SkPath::kDone_Verb:
-                done = true;
-                break;
-            default: SkASSERT(false);
-        }
-    }
-    SkASSERT(quadPoints.count() % 3 == 0);
-    for (int i = 0; i < quadPoints.count(); i += 3) {
-        add_quad(&quadPoints[i], quadVertices);
-    }
-
-    static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
-    GrUniqueKey key;
-    GrUniqueKey::Builder builder(&key, kDomain, 2);
-    builder[0] = path.getGenerationID();
-    builder[1] = path.getFillType();
-    builder.finish();
-    GrTessellator::WindingVertex* windingVertices;
-    int triVertexCount = GrTessellator::PathToVertices(linesOnlyPath, 0, bounds, &windingVertices);
-    if (triVertexCount > 0) {
-        for (int i = 0; i < triVertexCount; i += 3) {
-            SkPoint p1 = windingVertices[i].fPos;
-            SkPoint p2 = windingVertices[i + 1].fPos;
-            SkPoint p3 = windingVertices[i + 2].fPos;
-            int winding = windingVertices[i].fWinding;
-            SkASSERT(windingVertices[i + 1].fWinding == winding);
-            SkASSERT(windingVertices[i + 2].fWinding == winding);
-            SkScalar cross = (p2 - p1).cross(p3 - p1);
-            SkPoint bloated[3] = { p1, p2, p3 };
-            if (cross < 0.0f) {
-                SkTSwap(p1, p3);
-            }
-            if (bloat_tri(bloated)) {
-                triVertices.push_back({ bloated[0], p1, p2, p3, winding });
-                triVertices.push_back({ bloated[1], p1, p2, p3, winding });
-                triVertices.push_back({ bloated[2], p1, p2, p3, winding });
-            }
-            else {
-                SkScalar minX = SkTMin(p1.fX, SkTMin(p2.fX, p3.fX)) - 1.0f;
-                SkScalar minY = SkTMin(p1.fY, SkTMin(p2.fY, p3.fY)) - 1.0f;
-                SkScalar maxX = SkTMax(p1.fX, SkTMax(p2.fX, p3.fX)) + 1.0f;
-                SkScalar maxY = SkTMax(p1.fY, SkTMax(p2.fY, p3.fY)) + 1.0f;
-                triVertices.push_back({ { minX, minY }, p1, p2, p3, winding });
-                triVertices.push_back({ { maxX, minY }, p1, p2, p3, winding });
-                triVertices.push_back({ { minX, maxY }, p1, p2, p3, winding });
-                triVertices.push_back({ { maxX, minY }, p1, p2, p3, winding });
-                triVertices.push_back({ { maxX, maxY }, p1, p2, p3, winding });
-                triVertices.push_back({ { minX, maxY }, p1, p2, p3, winding });
-            }
-        }
-        delete[] windingVertices;
-    }
-    return triVertexCount > 0 || quadVertices.count() > 0;
-}
-
-class PLSAATriangleEffect : public GrPLSGeometryProcessor {
-public:
-
-    static GrPLSGeometryProcessor* Create(const SkMatrix& localMatrix,
-                                          bool usesLocalCoords) {
-        return new PLSAATriangleEffect(localMatrix, usesLocalCoords);
-    }
-
-    virtual ~PLSAATriangleEffect() {}
-
-    const char* name() const override { return "PLSAATriangle"; }
-
-    const Attribute* inPosition() const { return fInPosition; }
-    const Attribute* inVertex1() const { return fInVertex1; }
-    const Attribute* inVertex2() const { return fInVertex2; }
-    const Attribute* inVertex3() const { return fInVertex3; }
-    const Attribute* inWindings() const { return fInWindings; }
-    const SkMatrix& localMatrix() const { return fLocalMatrix; }
-    bool usesLocalCoords() const { return fUsesLocalCoords; }
-
-    class GLSLProcessor : public GrGLSLGeometryProcessor {
-    public:
-        GLSLProcessor(const GrGeometryProcessor&) {}
-
-        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
-            const PLSAATriangleEffect& te = args.fGP.cast<PLSAATriangleEffect>();
-            GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
-            GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
-            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
-            varyingHandler->emitAttributes(te);
-
-            this->setupPosition(vsBuilder, gpArgs, te.inPosition()->fName);
-
-            GrGLSLVertToFrag v1(kVec2f_GrSLType);
-            varyingHandler->addVarying("Vertex1", &v1, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);",
-                                   v1.vsOut(),
-                                   te.inVertex1()->fName,
-                                   te.inVertex1()->fName);
-
-            GrGLSLVertToFrag v2(kVec2f_GrSLType);
-            varyingHandler->addVarying("Vertex2", &v2, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);",
-                                   v2.vsOut(),
-                                   te.inVertex2()->fName,
-                                   te.inVertex2()->fName);
-
-            GrGLSLVertToFrag v3(kVec2f_GrSLType);
-            varyingHandler->addVarying("Vertex3", &v3, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);",
-                                   v3.vsOut(),
-                                   te.inVertex3()->fName,
-                                   te.inVertex3()->fName);
-
-            GrGLSLVertToFrag delta1(kVec2f_GrSLType);
-            varyingHandler->addVarying("delta1", &delta1, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
-                                   delta1.vsOut(), v1.vsOut(), v2.vsOut(), v2.vsOut(), v1.vsOut());
-
-            GrGLSLVertToFrag delta2(kVec2f_GrSLType);
-            varyingHandler->addVarying("delta2", &delta2, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
-                                   delta2.vsOut(), v2.vsOut(), v3.vsOut(), v3.vsOut(), v2.vsOut());
-
-            GrGLSLVertToFrag delta3(kVec2f_GrSLType);
-            varyingHandler->addVarying("delta3", &delta3, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
-                                   delta3.vsOut(), v3.vsOut(), v1.vsOut(), v1.vsOut(), v3.vsOut());
-
-            GrGLSLVertToFrag windings(kInt_GrSLType);
-            varyingHandler->addFlatVarying("windings", &windings, kLow_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = %s;",
-                                   windings.vsOut(), te.inWindings()->fName);
-
-            // emit transforms
-            this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
-                                 te.inPosition()->fName, te.localMatrix(),
-                                 args.fFPCoordTransformHandler);
-
-            GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
-            SkAssertResult(fsBuilder->enableFeature(
-                           GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
-            fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL);
-            // Compute four subsamples, each shifted a quarter pixel along x and y from
-            // gl_FragCoord. The oriented box positioning of the subsamples is of course not
-            // optimal, but it greatly simplifies the math and this simplification is necessary for
-            // performance reasons.
-            fsBuilder->codeAppendf("highp vec2 firstSample = sk_FragCoord.xy - vec2(0.25);");
-            fsBuilder->codeAppendf("highp vec2 delta1 = %s;", delta1.fsIn());
-            fsBuilder->codeAppendf("highp vec2 delta2 = %s;", delta2.fsIn());
-            fsBuilder->codeAppendf("highp vec2 delta3 = %s;", delta3.fsIn());
-            // Check whether first sample is inside the triangle by computing three dot products. If
-            // all are < 0, we're inside. The first vector in each case is half of what it is
-            // "supposed" to be, because we re-use them later as adjustment factors for which half
-            // is the correct value, so we multiply the dots by two to compensate.
-            fsBuilder->codeAppendf("highp float d1 = dot(delta1, (firstSample - %s).yx) * 2.0;",
-                                   v1.fsIn());
-            fsBuilder->codeAppendf("highp float d2 = dot(delta2, (firstSample - %s).yx) * 2.0;",
-                                   v2.fsIn());
-            fsBuilder->codeAppendf("highp float d3 = dot(delta3, (firstSample - %s).yx) * 2.0;",
-                                   v3.fsIn());
-            fsBuilder->codeAppend("highp float dmax = max(d1, max(d2, d3));");
-            fsBuilder->codeAppendf("pls.windings[0] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
-            // for subsequent samples, we don't recalculate the entire dot product -- just adjust it
-            // to the value it would have if we did recompute it.
-            fsBuilder->codeAppend("d1 += delta1.x;");
-            fsBuilder->codeAppend("d2 += delta2.x;");
-            fsBuilder->codeAppend("d3 += delta3.x;");
-            fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));");
-            fsBuilder->codeAppendf("pls.windings[1] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
-            fsBuilder->codeAppend("d1 += delta1.y;");
-            fsBuilder->codeAppend("d2 += delta2.y;");
-            fsBuilder->codeAppend("d3 += delta3.y;");
-            fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));");
-            fsBuilder->codeAppendf("pls.windings[2] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
-            fsBuilder->codeAppend("d1 -= delta1.x;");
-            fsBuilder->codeAppend("d2 -= delta2.x;");
-            fsBuilder->codeAppend("d3 -= delta3.x;");
-            fsBuilder->codeAppend("dmax = max(d1, max(d2, d3));");
-            fsBuilder->codeAppendf("pls.windings[3] += (dmax <= 0.0) ? %s : 0;", windings.fsIn());
-        }
-
-        static inline void GenKey(const GrGeometryProcessor& gp,
-                                  const GrShaderCaps&,
-                                  GrProcessorKeyBuilder* b) {
-            const PLSAATriangleEffect& te = gp.cast<PLSAATriangleEffect>();
-            uint32_t key = 0;
-            key |= te.localMatrix().hasPerspective() ? 0x1 : 0x0;
-            b->add32(key);
-        }
-
-        void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
-                     FPCoordTransformIter&& transformIter) override {
-            this->setTransformDataHelper(gp.cast<PLSAATriangleEffect>().fLocalMatrix, pdman,
-                                         &transformIter);
-        }
-
-    private:
-        typedef GrGLSLGeometryProcessor INHERITED;
-    };
-
-    virtual void getGLSLProcessorKey(const GrShaderCaps& caps,
-                                   GrProcessorKeyBuilder* b) const override {
-        GLSLProcessor::GenKey(*this, caps, b);
-    }
-
-    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
-        return new GLSLProcessor(*this);
-    }
-
-private:
-    PLSAATriangleEffect(const SkMatrix& localMatrix, bool usesLocalCoords)
-        : fLocalMatrix(localMatrix)
-        , fUsesLocalCoords(usesLocalCoords) {
-        this->initClassID<PLSAATriangleEffect>();
-        fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
-                                             kHigh_GrSLPrecision);
-        fInVertex1 = &this->addVertexAttrib("inVertex1", kVec2f_GrVertexAttribType,
-                                            kHigh_GrSLPrecision);
-        fInVertex2 = &this->addVertexAttrib("inVertex2", kVec2f_GrVertexAttribType,
-                                            kHigh_GrSLPrecision);
-        fInVertex3 = &this->addVertexAttrib("inVertex3", kVec2f_GrVertexAttribType,
-                                            kHigh_GrSLPrecision);
-        fInWindings = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType,
-                                             kLow_GrSLPrecision);
-    }
-
-    const Attribute* fInPosition;
-    const Attribute* fInVertex1;
-    const Attribute* fInVertex2;
-    const Attribute* fInVertex3;
-    const Attribute* fInWindings;
-    SkMatrix         fLocalMatrix;
-    bool             fUsesLocalCoords;
-
-    GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
-
-    typedef GrGeometryProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-/*
- * Quadratic specified by 0=u^2-v canonical coords. u and v are the first
- * two components of the vertex attribute. Coverage is based on signed
- * distance with negative being inside, positive outside. The edge is specified in
- * window space (y-down). If either the third or fourth component of the interpolated
- * vertex coord is > 0 then the pixel is considered outside the edge. This is used to
- * attempt to trim to a portion of the infinite quad.
- * Requires shader derivative instruction support.
- */
-
-class PLSQuadEdgeEffect : public GrPLSGeometryProcessor {
-public:
-
-    static GrPLSGeometryProcessor* Create(const SkMatrix& localMatrix,
-                                          bool usesLocalCoords) {
-        return new PLSQuadEdgeEffect(localMatrix, usesLocalCoords);
-    }
-
-    virtual ~PLSQuadEdgeEffect() {}
-
-    const char* name() const override { return "PLSQuadEdge"; }
-
-    const Attribute* inPosition() const { return fInPosition; }
-    const Attribute* inUV() const { return fInUV; }
-    const Attribute* inEndpoint1() const { return fInEndpoint1; }
-    const Attribute* inEndpoint2() const { return fInEndpoint2; }
-    const Attribute* inWindings() const { return fInWindings; }
-    const SkMatrix& localMatrix() const { return fLocalMatrix; }
-    bool usesLocalCoords() const { return fUsesLocalCoords; }
-
-    class GLSLProcessor : public GrGLSLGeometryProcessor {
-    public:
-        GLSLProcessor(const GrGeometryProcessor&) {}
-
-        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
-            const PLSQuadEdgeEffect& qe = args.fGP.cast<PLSQuadEdgeEffect>();
-            GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
-            GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
-            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
-            // emit attributes
-            varyingHandler->emitAttributes(qe);
-
-            GrGLSLVertToFrag uv(kVec2f_GrSLType);
-            varyingHandler->addVarying("uv", &uv, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = %s;", uv.vsOut(), qe.inUV()->fName);
-
-            GrGLSLVertToFrag ep1(kVec2f_GrSLType);
-            varyingHandler->addVarying("endpoint1", &ep1, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", ep1.vsOut(),
-                                  qe.inEndpoint1()->fName, qe.inEndpoint1()->fName);
-
-            GrGLSLVertToFrag ep2(kVec2f_GrSLType);
-            varyingHandler->addVarying("endpoint2", &ep2, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x, %s.y);", ep2.vsOut(),
-                                  qe.inEndpoint2()->fName, qe.inEndpoint2()->fName);
-
-            GrGLSLVertToFrag delta(kVec2f_GrSLType);
-            varyingHandler->addVarying("delta", &delta, kHigh_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = vec2(%s.x - %s.x, %s.y - %s.y) * 0.5;",
-                                   delta.vsOut(), ep1.vsOut(), ep2.vsOut(), ep2.vsOut(),
-                                   ep1.vsOut());
-
-            GrGLSLVertToFrag windings(kInt_GrSLType);
-            varyingHandler->addFlatVarying("windings", &windings, kLow_GrSLPrecision);
-            vsBuilder->codeAppendf("%s = %s;",
-                                   windings.vsOut(), qe.inWindings()->fName);
-
-            // Setup position
-            this->setupPosition(vsBuilder, gpArgs, qe.inPosition()->fName);
-
-            // emit transforms
-            this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
-                                 qe.inPosition()->fName, qe.localMatrix(),
-                                 args.fFPCoordTransformHandler);
-
-            GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
-            SkAssertResult(fsBuilder->enableFeature(
-                           GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
-            static const int QUAD_ARGS = 2;
-            GrShaderVar inQuadArgs[QUAD_ARGS] = {
-                GrShaderVar("dot", kFloat_GrSLType, 0, kHigh_GrSLPrecision),
-                GrShaderVar("uv", kVec2f_GrSLType, 0, kHigh_GrSLPrecision)
-            };
-            SkString inQuadName;
-
-            const char* inQuadCode = "if (uv.x * uv.x <= uv.y) {"
-                                     "return dot >= 0.0;"
-                                     "} else {"
-                                     "return false;"
-                                     "}";
-            fsBuilder->emitFunction(kBool_GrSLType, "in_quad", QUAD_ARGS, inQuadArgs, inQuadCode,
-                                    &inQuadName);
-            fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL);
-            // keep the derivative instructions outside the conditional
-            fsBuilder->codeAppendf("highp vec2 uvdX = dFdx(%s);", uv.fsIn());
-            fsBuilder->codeAppendf("highp vec2 uvdY = dFdy(%s);", uv.fsIn());
-            fsBuilder->codeAppend("highp vec2 uvIncX = uvdX * 0.45 + uvdY * -0.1;");
-            fsBuilder->codeAppend("highp vec2 uvIncY = uvdX * 0.1 + uvdY * 0.55;");
-            fsBuilder->codeAppendf("highp vec2 uv = %s.xy - uvdX * 0.35 - uvdY * 0.25;",
-                                   uv.fsIn());
-            fsBuilder->codeAppendf("highp vec2 firstSample = sk_FragCoord.xy - vec2(0.25);");
-            fsBuilder->codeAppendf("highp float d = dot(%s, (firstSample - %s).yx) * 2.0;",
-                                   delta.fsIn(), ep1.fsIn());
-            fsBuilder->codeAppendf("pls.windings[0] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
-                                   windings.fsIn());
-            fsBuilder->codeAppend("uv += uvIncX;");
-            fsBuilder->codeAppendf("d += %s.x;", delta.fsIn());
-            fsBuilder->codeAppendf("pls.windings[1] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
-                                   windings.fsIn());
-            fsBuilder->codeAppend("uv += uvIncY;");
-            fsBuilder->codeAppendf("d += %s.y;", delta.fsIn());
-            fsBuilder->codeAppendf("pls.windings[2] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
-                                   windings.fsIn());
-            fsBuilder->codeAppend("uv -= uvIncX;");
-            fsBuilder->codeAppendf("d -= %s.x;", delta.fsIn());
-            fsBuilder->codeAppendf("pls.windings[3] += %s(d, uv) ? %s : 0;", inQuadName.c_str(),
-                                   windings.fsIn());
-        }
-
-        static inline void GenKey(const GrGeometryProcessor& gp,
-                                  const GrShaderCaps&,
-                                  GrProcessorKeyBuilder* b) {
-            const PLSQuadEdgeEffect& qee = gp.cast<PLSQuadEdgeEffect>();
-            uint32_t key = 0;
-            key |= qee.usesLocalCoords() && qee.localMatrix().hasPerspective() ? 0x1 : 0x0;
-            b->add32(key);
-        }
-
-        void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
-                             FPCoordTransformIter&& transformIter) override {
-            this->setTransformDataHelper(gp.cast<PLSQuadEdgeEffect>().fLocalMatrix, pdman,
-                                         &transformIter);
-        }
-
-    private:
-        typedef GrGLSLGeometryProcessor INHERITED;
-    };
-
-    virtual void getGLSLProcessorKey(const GrShaderCaps& caps,
-                                   GrProcessorKeyBuilder* b) const override {
-        GLSLProcessor::GenKey(*this, caps, b);
-    }
-
-    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
-        return new GLSLProcessor(*this);
-    }
-
-private:
-    PLSQuadEdgeEffect(const SkMatrix& localMatrix, bool usesLocalCoords)
-        : fLocalMatrix(localMatrix)
-        , fUsesLocalCoords(usesLocalCoords) {
-        this->initClassID<PLSQuadEdgeEffect>();
-        fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
-                                             kHigh_GrSLPrecision);
-        fInUV = &this->addVertexAttrib("inUV", kVec2f_GrVertexAttribType, kHigh_GrSLPrecision);
-        fInEndpoint1 = &this->addVertexAttrib("inEndpoint1", kVec2f_GrVertexAttribType,
-                                              kHigh_GrSLPrecision);
-        fInEndpoint2 = &this->addVertexAttrib("inEndpoint2", kVec2f_GrVertexAttribType,
-                                              kHigh_GrSLPrecision);
-        fInWindings  = &this->addVertexAttrib("inWindings", kInt_GrVertexAttribType,
-                                              kLow_GrSLPrecision);
-    }
-
-    const Attribute* fInPosition;
-    const Attribute* fInUV;
-    const Attribute* fInEndpoint1;
-    const Attribute* fInEndpoint2;
-    const Attribute* fInWindings;
-    SkMatrix         fLocalMatrix;
-    bool             fUsesLocalCoords;
-
-    GR_DECLARE_GEOMETRY_PROCESSOR_TEST;
-
-    typedef GrGeometryProcessor INHERITED;
-};
-
-class PLSFinishEffect : public GrGeometryProcessor {
-public:
-
-    static GrGeometryProcessor* Create(GrColor color, bool useEvenOdd, const SkMatrix& localMatrix,
-                                       bool usesLocalCoords) {
-        return new PLSFinishEffect(color, useEvenOdd, localMatrix, usesLocalCoords);
-    }
-
-    virtual ~PLSFinishEffect() {}
-
-    const char* name() const override { return "PLSFinish"; }
-
-    const Attribute* inPosition() const { return fInPosition; }
-    GrColor color() const { return fColor; }
-    const SkMatrix& localMatrix() const { return fLocalMatrix; }
-    bool usesLocalCoords() const { return fUsesLocalCoords; }
-
-    GrPixelLocalStorageState getPixelLocalStorageState() const override {
-        return GrPixelLocalStorageState::kFinish_GrPixelLocalStorageState;
-    }
-
-    const char* getDestColorOverride() const override {
-        return GR_GL_PLS_DSTCOLOR_NAME;
-    }
-
-    class GLSLProcessor : public GrGLSLGeometryProcessor {
-    public:
-        GLSLProcessor(const GrGeometryProcessor&) {}
-
-        void onEmitCode(EmitArgs& args, GrGPArgs* gpArgs) override {
-            const PLSFinishEffect& fe = args.fGP.cast<PLSFinishEffect>();
-            GrGLSLVertexBuilder* vsBuilder = args.fVertBuilder;
-            GrGLSLVaryingHandler* varyingHandler = args.fVaryingHandler;
-            GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
-
-            fUseEvenOdd = uniformHandler->addUniform(kFragment_GrShaderFlag,
-                                                    kFloat_GrSLType, kLow_GrSLPrecision,
-                                                    "useEvenOdd");
-            const char* useEvenOdd = uniformHandler->getUniformCStr(fUseEvenOdd);
-
-            varyingHandler->emitAttributes(fe);
-            this->setupPosition(vsBuilder, gpArgs, fe.inPosition()->fName);
-            this->emitTransforms(vsBuilder, varyingHandler, uniformHandler, gpArgs->fPositionVar,
-                                 fe.inPosition()->fName, fe.localMatrix(),
-                                 args.fFPCoordTransformHandler);
-
-            GrGLSLPPFragmentBuilder* fsBuilder = args.fFragBuilder;
-            SkAssertResult(fsBuilder->enableFeature(
-                           GrGLSLFragmentShaderBuilder::kPixelLocalStorage_GLSLFeature));
-            fsBuilder->declAppendf(GR_GL_PLS_PATH_DATA_DECL);
-            fsBuilder->codeAppend("float coverage;");
-            fsBuilder->codeAppendf("if (%s != 0.0) {", useEvenOdd);
-            fsBuilder->codeAppend("coverage = float(abs(pls.windings[0]) % 2) * 0.25;");
-            fsBuilder->codeAppend("coverage += float(abs(pls.windings[1]) % 2) * 0.25;");
-            fsBuilder->codeAppend("coverage += float(abs(pls.windings[2]) % 2) * 0.25;");
-            fsBuilder->codeAppend("coverage += float(abs(pls.windings[3]) % 2) * 0.25;");
-            fsBuilder->codeAppend("} else {");
-            fsBuilder->codeAppend("coverage = pls.windings[0] != 0 ? 0.25 : 0.0;");
-            fsBuilder->codeAppend("coverage += pls.windings[1] != 0 ? 0.25 : 0.0;");
-            fsBuilder->codeAppend("coverage += pls.windings[2] != 0 ? 0.25 : 0.0;");
-            fsBuilder->codeAppend("coverage += pls.windings[3] != 0 ? 0.25 : 0.0;");
-            fsBuilder->codeAppend("}");
-            this->setupUniformColor(fsBuilder, uniformHandler, args.fOutputColor,
-                                    &fColorUniform);
-            fsBuilder->codeAppendf("%s = vec4(coverage);", args.fOutputCoverage);
-            fsBuilder->codeAppendf("%s = vec4(1.0, 0.0, 1.0, 1.0);", args.fOutputColor);
-        }
-
-        static inline void GenKey(const GrGeometryProcessor& gp,
-                                  const GrShaderCaps&,
-                                  GrProcessorKeyBuilder* b) {
-            const PLSFinishEffect& fe = gp.cast<PLSFinishEffect>();
-            uint32_t key = 0;
-            key |= fe.usesLocalCoords() && fe.localMatrix().hasPerspective() ? 0x1 : 0x0;
-            b->add32(key);
-        }
-
-        void setData(const GrGLSLProgramDataManager& pdman, const GrPrimitiveProcessor& gp,
-                     FPCoordTransformIter&& transformIter) override {
-            const PLSFinishEffect& fe = gp.cast<PLSFinishEffect>();
-            pdman.set1f(fUseEvenOdd, fe.fUseEvenOdd);
-            if (fe.color() != fColor) {
-                GrGLfloat c[4];
-                GrColorToRGBAFloat(fe.color(), c);
-                pdman.set4fv(fColorUniform, 1, c);
-                fColor = fe.color();
-            }
-            this->setTransformDataHelper(fe.fLocalMatrix, pdman, &transformIter);
-        }
-
-    private:
-        GrColor fColor;
-        UniformHandle fColorUniform;
-        UniformHandle fUseEvenOdd;
-
-        typedef GrGLSLGeometryProcessor INHERITED;
-    };
-
-    virtual void getGLSLProcessorKey(const GrShaderCaps& caps,
-                                   GrProcessorKeyBuilder* b) const override {
-        GLSLProcessor::GenKey(*this, caps, b);
-    }
-
-    virtual GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override {
-        return new GLSLProcessor(*this);
-    }
-
-private:
-    PLSFinishEffect(GrColor color, bool useEvenOdd, const SkMatrix& localMatrix,
-                    bool usesLocalCoords)
-        : fColor(color)
-        , fUseEvenOdd(useEvenOdd)
-        , fLocalMatrix(localMatrix)
-        , fUsesLocalCoords(usesLocalCoords) {
-        this->initClassID<PLSFinishEffect>();
-        fInPosition = &this->addVertexAttrib("inPosition", kVec2f_GrVertexAttribType,
-                                             kHigh_GrSLPrecision);
-    }
-
-    const Attribute* fInPosition;
-    GrColor          fColor;
-    bool             fUseEvenOdd;
-    SkMatrix         fLocalMatrix;
-    bool             fUsesLocalCoords;
-
-    typedef GrGeometryProcessor INHERITED;
-};
-
-///////////////////////////////////////////////////////////////////////////////
-
-bool GrPLSPathRenderer::onCanDrawPath(const CanDrawPathArgs& args) const {
-    // We have support for even-odd rendering, but are having some troublesome
-    // seams. Disable in the presence of even-odd for now.
-    SkPath path;
-    args.fShape->asPath(&path);
-    return args.fShaderCaps->shaderDerivativeSupport() && GrAAType::kCoverage == args.fAAType &&
-            args.fShape->style().isSimpleFill() && !path.isInverseFillType() &&
-            path.getFillType() == SkPath::FillType::kWinding_FillType;
-}
-
-class PLSPathOp final : public GrMeshDrawOp {
-public:
-    DEFINE_OP_CLASS_ID
-    static std::unique_ptr<GrDrawOp> Make(GrColor color, const SkPath& path,
-                                          const SkMatrix& viewMatrix) {
-        return std::unique_ptr<GrDrawOp>(new PLSPathOp(color, path, viewMatrix));
-    }
-
-    const char* name() const override { return "PLSPathOp"; }
-
-    SkString dumpInfo() const override {
-        SkString string;
-        string.printf("Color 0x%08x, UsesLocalCoords: %d\n", fColor, fUsesLocalCoords);
-        string.append(DumpPipelineInfo(*this->pipeline()));
-        string.append(INHERITED::dumpInfo());
-        return string;
-    }
-
-private:
-    PLSPathOp(GrColor color, const SkPath& path, const SkMatrix& viewMatrix)
-            : INHERITED(ClassID()), fColor(color), fPath(path), fViewMatrix(viewMatrix) {
-        // compute bounds
-        this->setTransformedBounds(path.getBounds(), fViewMatrix, HasAABloat::kYes,
-                                   IsZeroArea::kNo);
-    }
-
-    void getFragmentProcessorAnalysisInputs(FragmentProcessorAnalysisInputs* input) const override {
-        input->colorInput()->setToConstant(fColor);
-        input->coverageInput()->setToUnknown();
-        input->setUsesPLSDstRead();
-    }
-
-    void applyPipelineOptimizations(const GrPipelineOptimizations& optimizations) override {
-        optimizations.getOverrideColorIfSet(&fColor);
-
-        fUsesLocalCoords = optimizations.readsLocalCoords();
-    }
-
-    void onPrepareDraws(Target* target) const override {
-
-        SkMatrix invert;
-        if (fUsesLocalCoords && !fViewMatrix.invert(&invert)) {
-            SkDebugf("Could not invert viewmatrix\n");
-            return;
-        }
-
-        // Setup GrGeometryProcessors
-        sk_sp<GrPLSGeometryProcessor> triangleProcessor(
-                PLSAATriangleEffect::Create(invert, fUsesLocalCoords));
-        sk_sp<GrPLSGeometryProcessor> quadProcessor(
-                PLSQuadEdgeEffect::Create(invert, fUsesLocalCoords));
-
-        GrResourceProvider* rp = target->resourceProvider();
-        SkRect bounds;
-        this->bounds().roundOut(&bounds);
-        triangleProcessor->setBounds(bounds);
-        quadProcessor->setBounds(bounds);
-
-        // We use the fact that SkPath::transform path does subdivision based on
-        // perspective. Otherwise, we apply the view matrix when copying to the
-        // segment representation.
-        const SkMatrix* viewMatrix = &fViewMatrix;
-
-        // We avoid initializing the path unless we have to
-        const SkPath* pathPtr = &fPath;
-        SkTLazy<SkPath> tmpPath;
-        if (viewMatrix->hasPerspective()) {
-            SkPath* tmpPathPtr = tmpPath.init(*pathPtr);
-            tmpPathPtr->setIsVolatile(true);
-            tmpPathPtr->transform(*viewMatrix);
-            viewMatrix = &SkMatrix::I();
-            pathPtr = tmpPathPtr;
-        }
-
-        GrMesh mesh;
-
-        PLSVertices triVertices;
-        PLSVertices quadVertices;
-        if (!get_geometry(*pathPtr, *viewMatrix, triVertices, quadVertices, rp, bounds)) {
-            return;
-        }
-
-        if (triVertices.count()) {
-            const GrBuffer* triVertexBuffer;
-            int firstTriVertex;
-            size_t triStride = triangleProcessor->getVertexStride();
-            PLSVertex* triVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace(
-                    triStride, triVertices.count(), &triVertexBuffer, &firstTriVertex));
-            if (!triVerts) {
-                SkDebugf("Could not allocate vertices\n");
-                return;
-            }
-            for (int i = 0; i < triVertices.count(); ++i) {
-                triVerts[i] = triVertices[i];
-            }
-            mesh.init(kTriangles_GrPrimitiveType, triVertexBuffer, firstTriVertex,
-                      triVertices.count());
-            target->draw(triangleProcessor.get(), mesh);
-        }
-
-        if (quadVertices.count()) {
-            const GrBuffer* quadVertexBuffer;
-            int firstQuadVertex;
-            size_t quadStride = quadProcessor->getVertexStride();
-            PLSVertex* quadVerts = reinterpret_cast<PLSVertex*>(target->makeVertexSpace(
-                    quadStride, quadVertices.count(), &quadVertexBuffer, &firstQuadVertex));
-            if (!quadVerts) {
-                SkDebugf("Could not allocate vertices\n");
-                return;
-            }
-            for (int i = 0; i < quadVertices.count(); ++i) {
-                quadVerts[i] = quadVertices[i];
-            }
-            mesh.init(kTriangles_GrPrimitiveType, quadVertexBuffer, firstQuadVertex,
-                      quadVertices.count());
-            target->draw(quadProcessor.get(), mesh);
-        }
-
-        sk_sp<GrGeometryProcessor> finishProcessor(
-                PLSFinishEffect::Create(fColor,
-                                        pathPtr->getFillType() ==
-                                                            SkPath::FillType::kEvenOdd_FillType,
-                                        invert,
-                                        fUsesLocalCoords));
-        const GrBuffer* rectVertexBuffer;
-        size_t finishStride = finishProcessor->getVertexStride();
-        int firstRectVertex;
-        static const int kRectVertexCount = 6;
-        SkPoint* rectVerts = reinterpret_cast<SkPoint*>(target->makeVertexSpace(
-                finishStride, kRectVertexCount, &rectVertexBuffer, &firstRectVertex));
-        if (!rectVerts) {
-            SkDebugf("Could not allocate vertices\n");
-            return;
-        }
-        rectVerts[0] = { bounds.fLeft, bounds.fTop };
-        rectVerts[1] = { bounds.fLeft, bounds.fBottom };
-        rectVerts[2] = { bounds.fRight, bounds.fBottom };
-        rectVerts[3] = { bounds.fLeft, bounds.fTop };
-        rectVerts[4] = { bounds.fRight, bounds.fTop };
-        rectVerts[5] = { bounds.fRight, bounds.fBottom };
-
-        mesh.init(kTriangles_GrPrimitiveType, rectVertexBuffer, firstRectVertex,
-                  kRectVertexCount);
-        target->draw(finishProcessor.get(), mesh);
-    }
-
-    bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override {
-        return false;
-    }
-
-    bool fUsesLocalCoords;
-
-    GrColor fColor;
-    SkPath fPath;
-    SkMatrix fViewMatrix;
-    typedef GrMeshDrawOp INHERITED;
-};
-
-SkDEBUGCODE(bool inPLSDraw = false;)
-bool GrPLSPathRenderer::onDrawPath(const DrawPathArgs& args) {
-    SkASSERT(!args.fShape->isEmpty());
-    SkASSERT(!inPLSDraw);
-    SkDEBUGCODE(inPLSDraw = true;)
-    SkPath path;
-    args.fShape->asPath(&path);
-
-    std::unique_ptr<GrDrawOp> op = PLSPathOp::Make(args.fPaint.getColor(), path, *args.fViewMatrix);
-    GrPipelineBuilder pipelineBuilder(std::move(args.fPaint), args.fAAType);
-    pipelineBuilder.setUserStencil(args.fUserStencilSettings);
-
-    args.fRenderTargetContext->addDrawOp(pipelineBuilder, *args.fClip, std::move(op));
-    SkDEBUGCODE(inPLSDraw = false;)
-    return true;
-
-}
-
-///////////////////////////////////////////////////////////////////////////////////////////////////
-
-#if GR_TEST_UTILS
-
-DRAW_OP_TEST_DEFINE(PLSPathOp) {
-    GrColor color = GrRandomColor(random);
-    SkMatrix vm = GrTest::TestMatrixInvertible(random);
-    SkPath path = GrTest::TestPathConvex(random);
-
-    return PLSPathOp::Make(color, path, vm);
-}
-
-#endif
diff --git a/src/gpu/ops/GrPLSPathRenderer.h b/src/gpu/ops/GrPLSPathRenderer.h
deleted file mode 100644
index 39f21ba..0000000
--- a/src/gpu/ops/GrPLSPathRenderer.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2012 Google Inc.
- *
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-#ifndef GrPLSPathRenderer_DEFINED
-#define GrPLSPathRenderer_DEFINED
-
-#include "GrPathRenderer.h"
-
-/*
- * Renders arbitrary antialiased paths using pixel local storage as a scratch buffer. The overall
- * technique is very similar to the approach presented in "Resolution independent rendering of
- * deformable vector objects using graphics hardware" by Kokojima et al.
-
- * We first render the straight-line portions of the path (essentially pretending as if all segments
- * were kLine_Verb) as a triangle fan, using a fragment shader which updates the winding counts
- * appropriately. We then render the curved portions of the path using a Loop-Blinn shader which
- * calculates which portion of the triangle is covered by the quad (conics and cubics are split down
- * to quads). Where we diverge from Kokojima is that, instead of rendering into the stencil buffer
- * and using built-in MSAA to handle straight-line antialiasing, we use the pixel local storage area
- * and calculate the MSAA ourselves in the fragment shader. Essentially, we manually evaluate the
- * coverage of each pixel four times, storing four winding counts into the pixel local storage area,
- * and compute the final coverage based on those winding counts.
- *
- * Our approach is complicated by the need to perform antialiasing on straight edges as well,
- * without relying on hardware MSAA. We instead bloat the triangles to ensure complete coverage,
- * pass the original (un-bloated) vertices in to the fragment shader, and then have the fragment
- * shader use these vertices to evaluate whether a given sample is located within the triangle or
- * not. This gives us MSAA4 edges on triangles which line up nicely with no seams. We similarly face
- * problems on the back (flat) edges of quads, where we have to ensure that the back edge is
- * antialiased in the same way. Similar to the triangle case, we pass in the two (unbloated)
- * vertices defining the back edge of the quad and the fragment shader uses these vertex coordinates
- * to discard samples falling on the other side of the quad's back edge.
- */
-class GrPLSPathRenderer : public GrPathRenderer {
-public:
-    GrPLSPathRenderer();
-
-    bool onCanDrawPath(const CanDrawPathArgs& args) const override;
-
-protected:
-    bool onDrawPath(const DrawPathArgs& args) override;
-};
-
-#endif