Don't use analytic clip FPs when drawing to stencil

It doesn't make sense to multiply by coverage when drawing to stencil.
This could theoretically work with FPs that discard and/or modify
the sample mask, but for the time being an analytic FP means one that
calculates a coverage value.

Bug: skia:7190
Change-Id: I44140a5823f8683ec08244bdf9d369f51fa05dd9
Reviewed-on: https://skia-review.googlesource.com/68362
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/GrClip.h b/src/gpu/GrClip.h
index bd7d8a1..7358e67 100644
--- a/src/gpu/GrClip.h
+++ b/src/gpu/GrClip.h
@@ -8,13 +8,12 @@
 #ifndef GrClip_DEFINED
 #define GrClip_DEFINED
 
-#include "GrTypes.h"
+#include "GrAppliedClip.h"
+#include "GrRenderTargetContext.h"
 #include "SkRRect.h"
 #include "SkRect.h"
 
-class GrAppliedClip;
 class GrContext;
-class GrRenderTargetContext;
 
 /**
  * GrClip is an abstract base class for applying a clip. It constructs a clip mask if necessary, and
@@ -37,8 +36,7 @@
      * skipped as it is fully clipped out.
      */
     virtual bool apply(GrContext*, GrRenderTargetContext*, bool useHWAA,
-                       bool hasUserStencilSettings, GrAppliedClip* result,
-                       SkRect* bounds) const = 0;
+                       bool hasUserStencilSettings, GrAppliedClip*, SkRect* bounds) const = 0;
 
     virtual ~GrClip() {}
 
@@ -133,10 +131,32 @@
     }
 };
 
+
+/**
+ * GrHardClip never uses coverage FPs. It can only enforce the clip using the already-existing
+ * stencil buffer contents and/or fixed-function state like scissor. Always aliased if MSAA is off.
+ */
+class GrHardClip : public GrClip {
+public:
+    /**
+     * Sets the appropriate hardware state modifications on GrAppliedHardClip that will implement
+     * the clip. On input 'bounds' is a conservative bounds of the draw that is to be clipped. After
+     * return 'bounds' has been intersected with a conservative bounds of the clip. A return value
+     * of false indicates that the draw can be skipped as it is fully clipped out.
+     */
+    virtual bool apply(int rtWidth, int rtHeight, GrAppliedHardClip* out, SkRect* bounds) const = 0;
+
+private:
+    bool apply(GrContext*, GrRenderTargetContext* rtc, bool useHWAA, bool hasUserStencilSettings,
+               GrAppliedClip* out, SkRect* bounds) const final {
+        return this->apply(rtc->width(), rtc->height(), &out->hardClip(), bounds);
+    }
+};
+
 /**
  * Specialized implementation for no clip.
  */
-class GrNoClip final : public GrClip {
+class GrNoClip final : public GrHardClip {
 private:
     bool quickContains(const SkRect&) const final { return true; }
     bool quickContains(const SkRRect&) const final { return true; }
@@ -147,10 +167,7 @@
             *isIntersectionOfRects = true;
         }
     }
-    bool apply(GrContext*, GrRenderTargetContext*, bool, bool, GrAppliedClip*,
-               SkRect*) const final {
-        return true;
-    }
+    bool apply(int rtWidth, int rtHeight, GrAppliedHardClip*, SkRect*) const final { return true; }
     bool isRRect(const SkRect&, SkRRect*, GrAA*) const override { return false; }
 };