Revert "Fold analytic clip FPs into GrReducedClip"

This reverts commit 4355b26b359d5f2597a10012e7eb11fb3a1f025b.

Reason for revert: Most likely CL for layout test failures on Chrome roll: https://bugs.chromium.org/p/chromium/issues/detail?id=785931

Original change's description:
> Fold analytic clip FPs into GrReducedClip
> 
> Perf result on Pixel phone (sorted by impact):
> 
>   GEOMEAN                              7.44 -> 6.92 ms   [ 93%]
> 
>   keymobi_cnn_com.skp                  3.55 -> 3.59 ms   [101%]
>   keymobi_theverge_com.skp             4.08 -> 4.13 ms   [101%]
>   desk_skbug6850autoscroll.skp         1.21 -> 1.22 ms   [101%]
>   ...
>   top25desk_weather_com.skp            14.2 -> 11.5 ms   [ 81%]
>   keymobi_androidpolice_com_2012_.skp  3.84 -> 2.95 ms   [ 77%]
>   keymobi_shop_mobileweb_ebay_com.skp  2.94 -> 2.26 ms   [ 77%]
>   keymobi_boingboing_net.skp           3.08 -> 2.24 ms   [ 73%]
>   desk_jsfiddlebigcar.skp              1.90 -> 1.25 ms   [ 66%]
>   keymobi_m_youtube_com_watch_v_9.skp  13.5 -> 8.84 ms   [ 65%]
>   keymobi_sfgate_com_.skp              8.55 -> 5.55 ms   [ 65%]
>   keymobi_blogger.skp                  4.01 -> 2.60 ms   [ 65%]
> 
> Cleaner code, improved skps, slightly better geometric mean time.
> 
> Pixel C is mostly unaffected, presumably because it uses window
> rectangles.
> 
> Bug: skia:7190
> Change-Id: Ia93f68b2f971ea66b3ab19dc73557ea602932a92
> Reviewed-on: https://skia-review.googlesource.com/67424
> Commit-Queue: Chris Dalton <csmartdalton@google.com>
> Reviewed-by: Brian Salomon <bsalomon@google.com>

TBR=bsalomon@google.com,robertphillips@google.com,csmartdalton@google.com

Change-Id: I86ff05196eaaeca4fb63836c9b449bbea76fe80b
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: skia:7190
Reviewed-on: https://skia-review.googlesource.com/72480
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/include/gpu/GrCaps.h b/include/gpu/GrCaps.h
index b19281b..4da73c9 100644
--- a/include/gpu/GrCaps.h
+++ b/include/gpu/GrCaps.h
@@ -143,10 +143,6 @@
 
     int maxWindowRectangles() const { return fMaxWindowRectangles; }
 
-    // A tuned, platform-specific value for the maximum number of analytic fragment processors we
-    // should use to implement a clip, before falling back on a mask.
-    int maxClipAnalyticFPs() const { return fMaxClipAnalyticFPs; }
-
     virtual bool isConfigTexturable(GrPixelConfig) const = 0;
     virtual bool isConfigRenderable(GrPixelConfig config, bool withMSAA) const = 0;
     // Returns whether a texture of the given config can be copied to a texture of the same config.
@@ -245,7 +241,6 @@
     int fMaxStencilSampleCount;
     int fMaxRasterSamples;
     int fMaxWindowRectangles;
-    int fMaxClipAnalyticFPs;
 
 private:
     virtual void onApplyOptionsOverrides(const GrContextOptions&) {}
diff --git a/src/gpu/GrCaps.cpp b/src/gpu/GrCaps.cpp
index a4a78ad..2e25845 100644
--- a/src/gpu/GrCaps.cpp
+++ b/src/gpu/GrCaps.cpp
@@ -69,14 +69,6 @@
     fMaxRasterSamples = 0;
     fMaxWindowRectangles = 0;
 
-    // An default count of 4 was chosen because of the common pattern in Blink of:
-    //   isect RR
-    //   diff  RR
-    //   isect convex_poly
-    //   isect convex_poly
-    // when drawing rounded div borders.
-    fMaxClipAnalyticFPs = 4;
-
     fSuppressPrints = options.fSuppressPrints;
 #if GR_TEST_UTILS
     fWireframeMode = options.fWireframeMode;
@@ -169,7 +161,6 @@
     writer->appendS32("Max Stencil Sample Count", fMaxStencilSampleCount);
     writer->appendS32("Max Raster Samples", fMaxRasterSamples);
     writer->appendS32("Max Window Rectangles", fMaxWindowRectangles);
-    writer->appendS32("Max Clip Analytic Fragment Processors", fMaxClipAnalyticFPs);
 
     static const char* kInstancedSupportNames[] = {
         "None",
diff --git a/src/gpu/GrClipStackClip.cpp b/src/gpu/GrClipStackClip.cpp
index 52fab72..c0fe106 100644
--- a/src/gpu/GrClipStackClip.cpp
+++ b/src/gpu/GrClipStackClip.cpp
@@ -30,6 +30,7 @@
 typedef GrReducedClip::InitialState InitialState;
 typedef GrReducedClip::ElementList ElementList;
 
+static const int kMaxAnalyticElements = 4;
 const char GrClipStackClip::kMaskTestTag[] = "clip_mask";
 
 bool GrClipStackClip::quickContains(const SkRect& rect) const {
@@ -175,6 +176,80 @@
     return false;
 }
 
+static bool get_analytic_clip_processor(const ElementList& elements,
+                                        bool abortIfAA,
+                                        const SkRect& drawDevBounds,
+                                        std::unique_ptr<GrFragmentProcessor>* resultFP) {
+    SkASSERT(elements.count() <= kMaxAnalyticElements);
+    SkSTArray<kMaxAnalyticElements, std::unique_ptr<GrFragmentProcessor>> fps;
+    ElementList::Iter iter(elements);
+    while (iter.get()) {
+        SkClipOp op = iter.get()->getOp();
+        bool invert;
+        bool skip = false;
+        switch (op) {
+            case kReplace_SkClipOp:
+                SkASSERT(iter.get() == elements.head());
+                // Fallthrough, handled same as intersect.
+            case kIntersect_SkClipOp:
+                invert = false;
+                if (iter.get()->contains(drawDevBounds)) {
+                    skip = true;
+                }
+                break;
+            case kDifference_SkClipOp:
+                invert = true;
+                // We don't currently have a cheap test for whether a rect is fully outside an
+                // element's primitive, so don't attempt to set skip.
+                break;
+            default:
+                return false;
+        }
+        if (!skip) {
+            GrClipEdgeType edgeType;
+            if (iter.get()->isAA()) {
+                if (abortIfAA) {
+                    return false;
+                }
+                edgeType =
+                    invert ? GrClipEdgeType::kInverseFillAA : GrClipEdgeType::kFillAA;
+            } else {
+                edgeType =
+                    invert ? GrClipEdgeType::kInverseFillBW : GrClipEdgeType::kFillBW;
+            }
+
+            switch (iter.get()->getDeviceSpaceType()) {
+                case SkClipStack::Element::DeviceSpaceType::kPath:
+                    fps.emplace_back(
+                            GrConvexPolyEffect::Make(edgeType, iter.get()->getDeviceSpacePath()));
+                    break;
+                case SkClipStack::Element::DeviceSpaceType::kRRect: {
+                    fps.emplace_back(
+                            GrRRectEffect::Make(edgeType, iter.get()->getDeviceSpaceRRect()));
+                    break;
+                }
+                case SkClipStack::Element::DeviceSpaceType::kRect: {
+                    fps.emplace_back(
+                            GrConvexPolyEffect::Make(edgeType, iter.get()->getDeviceSpaceRect()));
+                    break;
+                }
+                default:
+                    break;
+            }
+            if (!fps.back()) {
+                return false;
+            }
+        }
+        iter.next();
+    }
+
+    *resultFP = nullptr;
+    if (fps.count()) {
+        *resultFP = GrFragmentProcessor::RunInSeries(fps.begin(), fps.count());
+    }
+    return true;
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // sort out what kind of clip mask needs to be created: alpha, stencil,
 // scissor, or entirely software
@@ -190,19 +265,8 @@
         return true;
     }
 
-    int maxAnalyticFPs = context->caps()->maxClipAnalyticFPs();
-    if (GrFSAAType::kNone != renderTargetContext->fsaaType()) {
-        // With mixed samples (non-msaa color buffer), any coverage info is lost from color once it
-        // hits the color buffer anyway, so we may as well use coverage AA if nothing else in the
-        // pipe is multisampled.
-        if (renderTargetContext->numColorSamples() > 0 || useHWAA || hasUserStencilSettings) {
-            maxAnalyticFPs = 0;
-        }
-        SkASSERT(!context->caps()->avoidStencilBuffers()); // We disable MSAA when avoiding stencil.
-    }
-
-    GrReducedClip reducedClip(*fStack, devBounds, renderTargetContext->priv().maxWindowRectangles(),
-                              maxAnalyticFPs);
+    const GrReducedClip reducedClip(*fStack, devBounds,
+                                    renderTargetContext->priv().maxWindowRectangles());
 
     if (reducedClip.hasScissor() && !GrClip::IsInsideClip(reducedClip.scissor(), devBounds)) {
         out->hardClip().addScissor(reducedClip.scissor(), bounds);
@@ -213,10 +277,6 @@
                                             GrWindowRectsState::Mode::kExclusive);
     }
 
-    if (std::unique_ptr<GrFragmentProcessor> clipFPs = reducedClip.detachAnalyticFPs()) {
-        out->addCoverageFP(std::move(clipFPs));
-    }
-
     if (reducedClip.maskElements().isEmpty()) {
         return InitialState::kAllIn == reducedClip.initialState();
     }
@@ -229,9 +289,41 @@
     SkASSERT(rtIBounds.contains(scissor)); // Mask shouldn't be larger than the RT.
 #endif
 
+    bool avoidStencilBuffers = context->caps()->avoidStencilBuffers();
+
+    // An element count of 4 was chosen because of the common pattern in Blink of:
+    //   isect RR
+    //   diff  RR
+    //   isect convex_poly
+    //   isect convex_poly
+    // when drawing rounded div borders. This could probably be tuned based on a
+    // configuration's relative costs of switching RTs to generate a mask vs
+    // longer shaders.
+    if (reducedClip.maskElements().count() <= kMaxAnalyticElements) {
+        // When there are multiple samples we want to do per-sample clipping, not compute a
+        // fractional pixel coverage.
+        bool disallowAnalyticAA =
+                GrFSAAType::kNone != renderTargetContext->fsaaType() && !avoidStencilBuffers;
+        if (disallowAnalyticAA && !renderTargetContext->numColorSamples()) {
+            // With a single color sample, any coverage info is lost from color once it hits the
+            // color buffer anyway, so we may as well use coverage AA if nothing else in the pipe
+            // is multisampled.
+            disallowAnalyticAA = useHWAA || hasUserStencilSettings;
+        }
+        std::unique_ptr<GrFragmentProcessor> clipFP;
+        if ((reducedClip.maskRequiresAA() || avoidStencilBuffers) &&
+            get_analytic_clip_processor(reducedClip.maskElements(), disallowAnalyticAA, devBounds,
+                                        &clipFP)) {
+            if (clipFP) {
+                out->addCoverageFP(std::move(clipFP));
+            }
+            return true;
+        }
+    }
+
     // If the stencil buffer is multisampled we can use it to do everything.
     if ((GrFSAAType::kNone == renderTargetContext->fsaaType() && reducedClip.maskRequiresAA()) ||
-        context->caps()->avoidStencilBuffers()) {
+        avoidStencilBuffers) {
         sk_sp<GrTextureProxy> result;
         if (UseSWOnlyPath(context, hasUserStencilSettings, renderTargetContext, reducedClip)) {
             // The clip geometry is complex enough that it will be more efficient to create it
@@ -251,8 +343,7 @@
         // If alpha or software clip mask creation fails, fall through to the stencil code paths,
         // unless stencils are disallowed.
         if (context->caps()->avoidStencilBuffers()) {
-            SkDebugf("WARNING: Clip mask requires stencil, but stencil unavailable. "
-                     "Clip will be ignored.\n");
+            SkDebugf("WARNING: Clip mask requires stencil, but stencil unavailable. Clip will be ignored.\n");
             return false;
         }
     }
@@ -262,14 +353,11 @@
     // This relies on the property that a reduced sub-rect of the last clip will contain all the
     // relevant window rectangles that were in the last clip. This subtle requirement will go away
     // after clipping is overhauled.
-    if (renderTargetContext->priv().mustRenderClip(reducedClip.maskGenID(), reducedClip.scissor(),
-                                                   reducedClip.numAnalyticFPs())) {
+    if (renderTargetContext->priv().mustRenderClip(reducedClip.maskGenID(),
+                                                   reducedClip.scissor())) {
         reducedClip.drawStencilClipMask(context, renderTargetContext);
-        renderTargetContext->priv().setLastClip(reducedClip.maskGenID(), reducedClip.scissor(),
-                                                reducedClip.numAnalyticFPs());
+        renderTargetContext->priv().setLastClip(reducedClip.maskGenID(), reducedClip.scissor());
     }
-    // GrAppliedClip doesn't need to figure numAnalyticFPs into its key (used by operator==) because
-    // it verifies the FPs are also equal.
     out->hardClip().addStencilClip(reducedClip.maskGenID());
     return true;
 }
@@ -277,16 +365,14 @@
 ////////////////////////////////////////////////////////////////////////////////
 // Create a 8-bit clip mask in alpha
 
-static void create_clip_mask_key(uint32_t clipGenID, const SkIRect& bounds, int numAnalyticFPs,
-                                 GrUniqueKey* key) {
+static void create_clip_mask_key(uint32_t clipGenID, const SkIRect& bounds, GrUniqueKey* key) {
     static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
-    GrUniqueKey::Builder builder(key, kDomain, 4, GrClipStackClip::kMaskTestTag);
+    GrUniqueKey::Builder builder(key, kDomain, 3, GrClipStackClip::kMaskTestTag);
     builder[0] = clipGenID;
     // SkToS16 because image filters outset layers to a size indicated by the filter, which can
     // sometimes result in negative coordinates from device space.
     builder[1] = SkToS16(bounds.fLeft) | (SkToS16(bounds.fRight) << 16);
     builder[2] = SkToS16(bounds.fTop) | (SkToS16(bounds.fBottom) << 16);
-    builder[3] = numAnalyticFPs;
 }
 
 static void add_invalidate_on_pop_message(const SkClipStack& stack, uint32_t clipGenID,
@@ -307,8 +393,7 @@
                                                            const GrReducedClip& reducedClip) const {
     GrResourceProvider* resourceProvider = context->resourceProvider();
     GrUniqueKey key;
-    create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(),
-                         reducedClip.numAnalyticFPs(), &key);
+    create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(), &key);
 
     sk_sp<GrTextureProxy> proxy(resourceProvider->findOrCreateProxyByUniqueKey(
                                                                 key, kBottomLeft_GrSurfaceOrigin));
@@ -420,8 +505,7 @@
         GrContext* context, const GrReducedClip& reducedClip,
         GrRenderTargetContext* renderTargetContext) const {
     GrUniqueKey key;
-    create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(),
-                         reducedClip.numAnalyticFPs(), &key);
+    create_clip_mask_key(reducedClip.maskGenID(), reducedClip.scissor(), &key);
 
     sk_sp<GrTextureProxy> proxy(context->resourceProvider()->findOrCreateProxyByUniqueKey(
                                                                   key, kTopLeft_GrSurfaceOrigin));
diff --git a/src/gpu/GrReducedClip.cpp b/src/gpu/GrReducedClip.cpp
index 992411a..d37c83f 100644
--- a/src/gpu/GrReducedClip.cpp
+++ b/src/gpu/GrReducedClip.cpp
@@ -21,8 +21,6 @@
 #include "GrStyle.h"
 #include "GrUserStencilSettings.h"
 #include "SkClipOpPriv.h"
-#include "effects/GrConvexPolyEffect.h"
-#include "effects/GrRRectEffect.h"
 
 /**
  * There are plenty of optimizations that could be added here. Maybe flips could be folded into
@@ -32,11 +30,8 @@
  * take a rect in case the caller knows a bound on what is to be drawn through this clip.
  */
 GrReducedClip::GrReducedClip(const SkClipStack& stack, const SkRect& queryBounds,
-                             int maxWindowRectangles, int maxAnalyticFPs)
-        : fMaxWindowRectangles(maxWindowRectangles)
-        , fMaxAnalyticFPs(maxAnalyticFPs) {
+                             int maxWindowRectangles) {
     SkASSERT(!queryBounds.isEmpty());
-    SkASSERT(fMaxWindowRectangles <= GrWindowRectangles::kMaxWindows);
     fHasScissor = false;
     fAAClipRectGenID = SK_InvalidGenID;
 
@@ -102,13 +97,12 @@
         }
         fHasScissor = true;
 
-        // Now that we have determined the bounds to use and filtered out the trivial cases, call
-        // the helper that actually walks the stack.
-        this->walkStack(stack, tighterQuery);
+        // Now that we have determined the bounds to use and filtered out the trivial cases, call the
+        // helper that actually walks the stack.
+        this->walkStack(stack, tighterQuery, maxWindowRectangles);
     }
 
-    if (SK_InvalidGenID != fAAClipRectGenID && // Is there an AA clip rect?
-        ClipResult::kNotClipped == this->addAnalyticFP(fAAClipRect, Invert::kNo, true)) {
+    if (SK_InvalidGenID != fAAClipRectGenID) { // Is there an AA clip rect?
         if (fMaskElements.isEmpty()) {
             // Use a replace since it is faster than intersect.
             fMaskElements.addToHead(fAAClipRect, SkMatrix::I(), kReplace_SkClipOp, true /*doAA*/);
@@ -118,10 +112,12 @@
         }
         fMaskRequiresAA = true;
         fMaskGenID = fAAClipRectGenID;
+        fAAClipRectGenID = SK_InvalidGenID;
     }
 }
 
-void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBounds) {
+void GrReducedClip::walkStack(const SkClipStack& stack, const SkRect& queryBounds,
+                              int maxWindowRectangles) {
     // walk backwards until we get to:
     //  a) the beginning
     //  b) an operation that is known to make the bounds all inside/outside
@@ -184,7 +180,7 @@
                     } else if (GrClip::IsOutsideClip(element->getBounds(), queryBounds)) {
                         skippable = true;
                     } else if (!embiggens) {
-                        ClipResult result = this->clipOutsideElement(element);
+                        ClipResult result = this->clipOutsideElement(element, maxWindowRectangles);
                         if (ClipResult::kMadeEmpty == result) {
                             return;
                         }
@@ -484,43 +480,34 @@
             return ClipResult::kClipped;
 
         case Element::DeviceSpaceType::kRRect:
-            return this->addAnalyticFP(element->getDeviceSpaceRRect(), Invert::kNo,
-                                       element->isAA());
-
         case Element::DeviceSpaceType::kPath:
-            return this->addAnalyticFP(element->getDeviceSpacePath(), Invert::kNo, element->isAA());
+            return ClipResult::kNotClipped;
     }
 
     SK_ABORT("Unexpected DeviceSpaceType");
     return ClipResult::kNotClipped;
 }
 
-GrReducedClip::ClipResult GrReducedClip::clipOutsideElement(const Element* element) {
+GrReducedClip::ClipResult GrReducedClip::clipOutsideElement(const Element* element,
+                                                            int maxWindowRectangles) {
+    if (fWindowRects.count() >= maxWindowRectangles) {
+        return ClipResult::kNotClipped;
+    }
+
     switch (element->getDeviceSpaceType()) {
         case Element::DeviceSpaceType::kEmpty:
             return ClipResult::kMadeEmpty;
 
         case Element::DeviceSpaceType::kRect:
-            if (fWindowRects.count() < fMaxWindowRectangles) {
-                // Clip out the inside of every rect. We won't be able to entirely skip the AA ones,
-                // but it saves processing time.
-                this->addWindowRectangle(element->getDeviceSpaceRect(), element->isAA());
-                if (!element->isAA()) {
-                    return ClipResult::kClipped;
-                }
-            }
-            return this->addAnalyticFP(element->getDeviceSpaceRect(), Invert::kYes,
-                                       element->isAA());
+            // Clip out the inside of every rect. We won't be able to entirely skip the AA ones, but
+            // it saves processing time.
+            this->addWindowRectangle(element->getDeviceSpaceRect(), element->isAA());
+            return !element->isAA() ? ClipResult::kClipped : ClipResult::kNotClipped;
 
         case Element::DeviceSpaceType::kRRect: {
-            const SkRRect& clipRRect = element->getDeviceSpaceRRect();
-            ClipResult clipResult = this->addAnalyticFP(clipRRect, Invert::kYes, element->isAA());
-            if (fWindowRects.count() >= fMaxWindowRectangles) {
-                return clipResult;
-            }
-
             // Clip out the interiors of round rects with two window rectangles in the shape of a
-            // "plus". This doesn't let us skip the clip element, but still saves processing time.
+            // plus. It doesn't allow us to skip the clip element, but still saves processing time.
+            const SkRRect& clipRRect = element->getDeviceSpaceRRect();
             SkVector insetTL = clipRRect.radii(SkRRect::kUpperLeft_Corner);
             SkVector insetBR = clipRRect.radii(SkRRect::kLowerRight_Corner);
             if (SkRRect::kComplex_Type == clipRRect.getType()) {
@@ -534,25 +521,24 @@
             const SkRect& bounds = clipRRect.getBounds();
             if (insetTL.x() + insetBR.x() >= bounds.width() ||
                 insetTL.y() + insetBR.y() >= bounds.height()) {
-                return clipResult; // The interior "plus" is empty.
+                return ClipResult::kNotClipped; // The interior "plus" is empty.
             }
 
             SkRect horzRect = SkRect::MakeLTRB(bounds.left(), bounds.top() + insetTL.y(),
                                                bounds.right(), bounds.bottom() - insetBR.y());
             this->addWindowRectangle(horzRect, element->isAA());
-
-            if (fWindowRects.count() < fMaxWindowRectangles) {
-                SkRect vertRect = SkRect::MakeLTRB(bounds.left() + insetTL.x(), bounds.top(),
-                                                   bounds.right() - insetBR.x(), bounds.bottom());
-                this->addWindowRectangle(vertRect, element->isAA());
+            if (fWindowRects.count() >= maxWindowRectangles) {
+                return ClipResult::kNotClipped;
             }
 
-            return clipResult;
+            SkRect vertRect = SkRect::MakeLTRB(bounds.left() + insetTL.x(), bounds.top(),
+                                               bounds.right() - insetBR.x(), bounds.bottom());
+            this->addWindowRectangle(vertRect, element->isAA());
+            return ClipResult::kNotClipped;
         }
 
         case Element::DeviceSpaceType::kPath:
-            return this->addAnalyticFP(element->getDeviceSpacePath(), Invert::kYes,
-                                       element->isAA());
+            return ClipResult::kNotClipped;
     }
 
     SK_ABORT("Unexpected DeviceSpaceType");
@@ -571,43 +557,6 @@
     }
 }
 
-template<typename T>
-inline GrReducedClip::ClipResult GrReducedClip::addAnalyticFP(const T& deviceSpaceShape,
-                                                              Invert invert, bool aa) {
-    if (fAnalyticFPs.count() >= fMaxAnalyticFPs) {
-        return ClipResult::kNotClipped;
-    }
-
-    GrClipEdgeType edgeType;
-    if (Invert::kNo == invert) {
-        edgeType = aa ? GrClipEdgeType::kFillAA : GrClipEdgeType::kFillBW;
-    } else {
-        edgeType = aa ? GrClipEdgeType::kInverseFillAA : GrClipEdgeType::kInverseFillBW;
-    }
-
-    if (auto fp = make_analytic_clip_fp(edgeType, deviceSpaceShape)) {
-        fAnalyticFPs.push_back(std::move(fp));
-        return ClipResult::kClipped;
-    }
-
-    return ClipResult::kNotClipped;
-}
-
-std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType,
-                                                           const SkRect& deviceSpaceRect) {
-    return GrConvexPolyEffect::Make(edgeType, deviceSpaceRect);
-}
-
-std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType,
-                                                           const SkRRect& deviceSpaceRRect) {
-    return GrRRectEffect::Make(edgeType, deviceSpaceRRect);
-}
-
-std::unique_ptr<GrFragmentProcessor> make_analytic_clip_fp(GrClipEdgeType edgeType,
-                                                           const SkPath& deviceSpacePath) {
-    return GrConvexPolyEffect::Make(edgeType, deviceSpacePath);
-}
-
 void GrReducedClip::makeEmpty() {
     fHasScissor = false;
     fAAClipRectGenID = SK_InvalidGenID;
diff --git a/src/gpu/GrReducedClip.h b/src/gpu/GrReducedClip.h
index 3ad2ab9..0746439 100644
--- a/src/gpu/GrReducedClip.h
+++ b/src/gpu/GrReducedClip.h
@@ -8,7 +8,6 @@
 #ifndef GrReducedClip_DEFINED
 #define GrReducedClip_DEFINED
 
-#include "GrFragmentProcessor.h"
 #include "GrWindowRectangles.h"
 #include "SkClipStack.h"
 #include "SkTLList.h"
@@ -25,8 +24,7 @@
     using Element = SkClipStack::Element;
     using ElementList = SkTLList<SkClipStack::Element, 16>;
 
-    GrReducedClip(const SkClipStack&, const SkRect& queryBounds,
-                  int maxWindowRectangles = 0, int maxAnalyticFPs = 0);
+    GrReducedClip(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles = 0);
 
     /**
      * If hasScissor() is true, the clip mask is not valid outside this rect and the caller must
@@ -50,13 +48,6 @@
      */
     const GrWindowRectangles& windowRectangles() const { return fWindowRects; }
 
-    int numAnalyticFPs() const { return fAnalyticFPs.count(); }
-
-    std::unique_ptr<GrFragmentProcessor> detachAnalyticFPs() {
-        SkDEBUGCODE(for (const auto& fp : fAnalyticFPs) { SkASSERT(fp); })
-        return GrFragmentProcessor::RunInSeries(fAnalyticFPs.begin(), fAnalyticFPs.count());
-    }
-
     /**
      * An ordered list of clip elements that could not be skipped or implemented by other means. If
      * nonempty, the caller must create an alpha and/or stencil mask for these elements and apply it
@@ -90,7 +81,7 @@
     bool drawStencilClipMask(GrContext*, GrRenderTargetContext*) const;
 
 private:
-    void walkStack(const SkClipStack&, const SkRect& queryBounds);
+    void walkStack(const SkClipStack&, const SkRect& queryBounds, int maxWindowRectangles);
 
     enum class ClipResult {
         kNotClipped,
@@ -100,35 +91,24 @@
 
     // Clips the the given element's interior out of the final clip.
     // NOTE: do not call for elements followed by ops that can grow the clip.
-    ClipResult clipInsideElement(const Element*);
+    ClipResult clipInsideElement(const Element* element);
 
     // Clips the the given element's exterior out of the final clip.
     // NOTE: do not call for elements followed by ops that can grow the clip.
-    ClipResult clipOutsideElement(const Element*);
+    ClipResult clipOutsideElement(const Element* element, int maxWindowRectangles);
 
     void addWindowRectangle(const SkRect& elementInteriorRect, bool elementIsAA);
-
-    enum class Invert : bool {
-        kNo,
-        kYes
-    };
-
-    template<typename T> ClipResult addAnalyticFP(const T& deviceSpaceShape, Invert, bool aa);
-
     void makeEmpty();
 
-    const int fMaxWindowRectangles;
-    const int fMaxAnalyticFPs;
-    SkIRect fScissor;
-    bool fHasScissor;
-    SkRect fAAClipRect;
-    uint32_t fAAClipRectGenID; // GenID the mask will have if includes the AA clip rect.
-    GrWindowRectangles fWindowRects;
-    SkSTArray<4, std::unique_ptr<GrFragmentProcessor>> fAnalyticFPs;
-    ElementList fMaskElements;
-    uint32_t fMaskGenID;
-    bool fMaskRequiresAA;
-    InitialState fInitialState;
+    SkIRect              fScissor;
+    bool                 fHasScissor;
+    SkRect               fAAClipRect;
+    uint32_t             fAAClipRectGenID; // GenID the mask will have if includes the AA clip rect.
+    GrWindowRectangles   fWindowRects;
+    ElementList          fMaskElements;
+    uint32_t             fMaskGenID;
+    bool                 fMaskRequiresAA;
+    InitialState         fInitialState;
 };
 
 #endif
diff --git a/src/gpu/GrRenderTargetContextPriv.h b/src/gpu/GrRenderTargetContextPriv.h
index 0d73793..874e9c9 100644
--- a/src/gpu/GrRenderTargetContextPriv.h
+++ b/src/gpu/GrRenderTargetContextPriv.h
@@ -29,22 +29,18 @@
 
     // called to note the last clip drawn to the stencil buffer.
     // TODO: remove after clipping overhaul.
-    void setLastClip(uint32_t clipStackGenID, const SkIRect& devClipBounds,
-                     int numClipAnalyticFPs) {
+    void setLastClip(uint32_t clipStackGenID, const SkIRect& devClipBounds) {
         GrRenderTargetOpList* opList = fRenderTargetContext->getRTOpList();
         opList->fLastClipStackGenID = clipStackGenID;
         opList->fLastDevClipBounds = devClipBounds;
-        opList->fLastClipNumAnalyticFPs = numClipAnalyticFPs;
     }
 
     // called to determine if we have to render the clip into SB.
     // TODO: remove after clipping overhaul.
-    bool mustRenderClip(uint32_t clipStackGenID, const SkIRect& devClipBounds,
-                        int numClipAnalyticFPs) const {
+    bool mustRenderClip(uint32_t clipStackGenID, const SkIRect& devClipBounds) const {
         GrRenderTargetOpList* opList = fRenderTargetContext->getRTOpList();
         return opList->fLastClipStackGenID != clipStackGenID ||
-               !opList->fLastDevClipBounds.contains(devClipBounds) ||
-               opList->fLastClipNumAnalyticFPs != numClipAnalyticFPs;
+               !opList->fLastDevClipBounds.contains(devClipBounds);
     }
 
     void clear(const GrFixedClip&, const GrColor, bool canIgnoreClip);
diff --git a/src/gpu/GrRenderTargetOpList.h b/src/gpu/GrRenderTargetOpList.h
index e9797db..24125ac 100644
--- a/src/gpu/GrRenderTargetOpList.h
+++ b/src/gpu/GrRenderTargetOpList.h
@@ -156,7 +156,6 @@
 
     uint32_t                       fLastClipStackGenID;
     SkIRect                        fLastDevClipBounds;
-    int                            fLastClipNumAnalyticFPs;
 
     // For ops/opList we have mean: 5 stdDev: 28
     SkSTArray<5, RecordedOp, true> fRecordedOps;
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 172c220..0c185e4 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -527,13 +527,6 @@
         GR_GL_GetIntegerv(gli, GR_GL_MAX_WINDOW_RECTANGLES, &fMaxWindowRectangles);
     }
 
-    if (kPowerVRRogue_GrGLRenderer == ctxInfo.renderer()) {
-        // Temporarily disabling clip analytic fragments processors on Nexus player while we work
-        // around a driver bug related to gl_FragCoord.
-        // https://bugs.chromium.org/p/skia/issues/detail?id=7286
-        fMaxClipAnalyticFPs = 0;
-    }
-
 #ifndef SK_BUILD_FOR_IOS
     if (kPowerVR54x_GrGLRenderer == ctxInfo.renderer() ||
         kPowerVRRogue_GrGLRenderer == ctxInfo.renderer() ||