Move edge GrEffects to locally defined classes.

This removes the general GrEdgeEffect and the specialized oval GrEffects and declares them within the renderer files that use them. It also splits GrEdgeEffect into three different GrEffects.

Author: jvanverth@google.com

Reviewed By: robertphillips@google.com

Review URL: https://chromiumcodereview.appspot.com/13344002

git-svn-id: http://skia.googlecode.com/svn/trunk@8493 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrAAConvexPathRenderer.cpp b/src/gpu/GrAAConvexPathRenderer.cpp
index 53c237b..ca5addc 100644
--- a/src/gpu/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/GrAAConvexPathRenderer.cpp
@@ -11,12 +11,15 @@
 #include "GrContext.h"
 #include "GrDrawState.h"
 #include "GrDrawTargetCaps.h"
+#include "GrEffect.h"
 #include "GrPathUtils.h"
+#include "GrTBackendEffectFactory.h"
 #include "SkString.h"
 #include "SkStrokeRec.h"
 #include "SkTrace.h"
 
-#include "effects/GrEdgeEffect.h"
+#include "gl/GrGLEffect.h"
+#include "gl/GrGLSL.h"
 
 GrAAConvexPathRenderer::GrAAConvexPathRenderer() {
 }
@@ -431,6 +434,123 @@
 
 }
 
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+ * 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 QuadEdgeEffect : public GrEffect {
+public:
+
+    static GrEffectRef* Create() {
+        // we go through this so we only have one copy of each effect
+        static GrEffectRef* gQuadEdgeEffectRef = 
+            CreateEffectRef(AutoEffectUnref(SkNEW(QuadEdgeEffect)));
+        static SkAutoTUnref<GrEffectRef> gUnref(gQuadEdgeEffectRef);
+
+        gQuadEdgeEffectRef->ref();
+        return gQuadEdgeEffectRef;
+    }
+
+    virtual ~QuadEdgeEffect() {}
+
+    static const char* Name() { return "QuadEdge"; }
+
+    virtual void getConstantColorComponents(GrColor* color, 
+                                            uint32_t* validFlags) const SK_OVERRIDE {
+        *validFlags = 0;
+    }
+
+    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
+        return GrTBackendEffectFactory<QuadEdgeEffect>::getInstance();
+    }
+
+    class GLEffect : public GrGLEffect {
+    public:
+        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
+            : INHERITED (factory) {}
+
+        virtual void emitCode(GrGLShaderBuilder* builder,
+                              const GrDrawEffect& drawEffect,
+                              EffectKey key,
+                              const char* outputColor,
+                              const char* inputColor,
+                              const TextureSamplerArray& samplers) SK_OVERRIDE {
+            const char *vsName, *fsName;
+            const SkString* attrName =
+                builder->getEffectAttributeName(drawEffect.getVertexAttribIndices()[0]);
+            builder->fsCodeAppendf("\t\tfloat edgeAlpha;\n");
+
+            SkAssertResult(builder->enableFeature(
+                                              GrGLShaderBuilder::kStandardDerivatives_GLSLFeature));
+            builder->addVarying(kVec4f_GrSLType, "QuadEdge", &vsName, &fsName);
+
+            // keep the derivative instructions outside the conditional
+            builder->fsCodeAppendf("\t\tvec2 duvdx = dFdx(%s.xy);\n", fsName);
+            builder->fsCodeAppendf("\t\tvec2 duvdy = dFdy(%s.xy);\n", fsName);
+            builder->fsCodeAppendf("\t\tif (%s.z > 0.0 && %s.w > 0.0) {\n", fsName, fsName);
+            // today we know z and w are in device space. We could use derivatives
+            builder->fsCodeAppendf("\t\t\tedgeAlpha = min(min(%s.z, %s.w) + 0.5, 1.0);\n", fsName,
+                                    fsName);
+            builder->fsCodeAppendf ("\t\t} else {\n");
+            builder->fsCodeAppendf("\t\t\tvec2 gF = vec2(2.0*%s.x*duvdx.x - duvdx.y,\n"
+                                   "\t\t\t               2.0*%s.x*duvdy.x - duvdy.y);\n",
+                                   fsName, fsName);
+            builder->fsCodeAppendf("\t\t\tedgeAlpha = (%s.x*%s.x - %s.y);\n", fsName, fsName,
+                                    fsName);
+            builder->fsCodeAppendf("\t\t\tedgeAlpha = "
+                                   "clamp(0.5 - edgeAlpha / length(gF), 0.0, 1.0);\n\t\t}\n");
+
+            SkString modulate;
+            GrGLSLModulate4f(&modulate, inputColor, "edgeAlpha");
+            builder->fsCodeAppendf("\t%s = %s;\n", outputColor, modulate.c_str());
+
+            builder->vsCodeAppendf("\t%s = %s;\n", vsName, attrName->c_str());
+        }
+
+        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
+            return 0x0;
+        }
+
+        virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
+
+    private:
+        typedef GrGLEffect INHERITED;
+    };
+
+private:
+    QuadEdgeEffect() { 
+        this->addVertexAttrib(kVec4f_GrSLType); 
+    }
+
+    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
+        return true;
+    }
+
+    GR_DECLARE_EFFECT_TEST;
+
+    typedef GrEffect INHERITED;
+};
+
+GR_DEFINE_EFFECT_TEST(QuadEdgeEffect);
+
+GrEffectRef* QuadEdgeEffect::TestCreate(SkMWCRandom* random,
+                                        GrContext*,
+                                        const GrDrawTargetCaps& caps,
+                                        GrTexture*[]) {
+    // Doesn't work without derivative instructions.
+    return caps.shaderDerivativeSupport() ? QuadEdgeEffect::Create() : NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 bool GrAAConvexPathRenderer::canDrawPath(const SkPath& path,
                                          const SkStrokeRec& stroke,
                                          const GrDrawTarget* target,
@@ -497,7 +617,7 @@
         kEdgeEffectStage = GrPaint::kTotalStages,
     };
     static const int kEdgeAttrIndex = 1;
-    GrEffectRef* quadEffect = GrEdgeEffect::Create(GrEdgeEffect::kQuad_EdgeType);
+    GrEffectRef* quadEffect = QuadEdgeEffect::Create();
     drawState->setEffect(kEdgeEffectStage, quadEffect, kEdgeAttrIndex)->unref();
 
     GrDrawTarget::AutoReleaseGeometry arg(target, vCount, iCount);