Some refactoring of GrCustomStage and friends

Review URL: http://codereview.appspot.com/6209071/



git-svn-id: http://skia.googlecode.com/svn/trunk@4003 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index d63b023..563d1a4 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -17,7 +17,7 @@
 
 public:
 
-    GrGLConvolutionEffect(GrConvolutionEffect* data);
+    GrGLConvolutionEffect(const GrCustomStage* stage);
     virtual const char* name() const SK_OVERRIDE;
     virtual void setupVSUnis(VarArray* vsUnis, int stage) SK_OVERRIDE;
     virtual void setupFSUnis(VarArray* fsUnis, int stage) SK_OVERRIDE;
@@ -30,13 +30,14 @@
                         const char* sampleCoords) SK_OVERRIDE;
     virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
 
-    virtual void setData(const GrGLInterface*, GrCustomStage*,
+    virtual void setData(const GrGLInterface*, const GrCustomStage*,
                          const GrGLTexture*) SK_OVERRIDE;
 
+    static inline StageKey GenKey(const GrCustomStage* s);
+    
 protected:
 
-    GrConvolutionEffect* fData;
- 
+    int            fKernelWidth;
     GrGLShaderVar* fKernelVar;
     GrGLShaderVar* fImageIncrementVar;
  
@@ -48,18 +49,16 @@
     typedef GrGLProgramStage INHERITED;
 };
 
-GrGLConvolutionEffect::GrGLConvolutionEffect(GrConvolutionEffect* data)
-    : fData(data)
-    , fKernelVar(NULL)
+GrGLConvolutionEffect::GrGLConvolutionEffect(const GrCustomStage* data)
+    : fKernelVar(NULL)
     , fImageIncrementVar(NULL)
     , fKernelLocation(0)
-    , fImageIncrementLocation(0)
-{
-
+    , fImageIncrementLocation(0) {
+    fKernelWidth = static_cast<const GrConvolutionEffect*>(data)->width();
 }
 
 const char* GrGLConvolutionEffect::name() const {
-    return fData->name();
+    return GrConvolutionEffect::Name();
 }
 
 void GrGLConvolutionEffect::setupVSUnis(VarArray* vsUnis,
@@ -81,7 +80,7 @@
     fKernelVar->setType(kFloat_GrSLType);
     fKernelVar->setTypeModifier(
         GrGLShaderVar::kUniform_TypeModifier);
-    fKernelVar->setArrayCount(fData->fKernelWidth);
+    fKernelVar->setArrayCount(fKernelWidth);
     (*fKernelVar->accessName()) = "uKernel";
     fKernelVar->accessName()->appendS32(stage);
 
@@ -93,7 +92,7 @@
 
 void GrGLConvolutionEffect::emitVS(GrStringBuilder* code,
                         const char* vertexCoords) {
-    float scale = (fData->fKernelWidth - 1) * 0.5f;
+    float scale = (fKernelWidth - 1) * 0.5f;
     code->appendf("\t\t%s -= vec2(%g, %g) * %s;\n",
                   vertexCoords, scale, scale,
                   fImageIncrementVar->getName().c_str());
@@ -121,7 +120,7 @@
     code->appendf("\t\tvec4 sum = vec4(0, 0, 0, 0);\n");
     code->appendf("\t\tvec2 coord = %s;\n", sampleCoords);
     code->appendf("\t\tfor (int i = 0; i < %d; i++) {\n",
-                  fData->fKernelWidth);
+                  fKernelWidth);
 
     code->appendf("\t\t\tsum += ");
     this->emitTextureLookup(code, samplerName, "coord");
@@ -143,14 +142,17 @@
 }
 
 void GrGLConvolutionEffect::setData(const GrGLInterface* gl,
-                                    GrCustomStage* data,
+                                    const GrCustomStage* data,
                                     const GrGLTexture* texture) {
-    fData = static_cast<GrConvolutionEffect*>(data);
+    const GrConvolutionEffect* conv =
+        static_cast<const GrConvolutionEffect*>(data);
+    // the code we generated was for a specific kernel width
+    GrAssert(conv->width() == fKernelWidth);
     GR_GL_CALL(gl, Uniform1fv(fKernelLocation,
-                              fData->fKernelWidth,
-                              fData->fKernel));
+                              fKernelWidth,
+                              conv->kernel()));
     float imageIncrement[2] = { 0 };
-    switch (fData->fDirection) {
+    switch (conv->direction()) {
         case GrSamplerState::kX_FilterDirection:
             imageIncrement[0] = 1.0f / texture->width();
             break;
@@ -163,58 +165,9 @@
     GR_GL_CALL(gl, Uniform2fv(fImageIncrementLocation, 1, imageIncrement));
 }
 
-/////////////////////////////////////////////////////////////////////
-// TODO: stageKey() and sEffectId are the only non-boilerplate in
-// this class; we ought to be able to templatize?
-
-class GrConvolutionEffectFactory : public GrProgramStageFactory {
-
-public:
-
-    virtual ~GrConvolutionEffectFactory();
-
-    virtual uint16_t stageKey(const GrCustomStage* s) SK_OVERRIDE;
-    virtual GrGLProgramStage* createGLInstance(GrCustomStage* s) SK_OVERRIDE;
-
-    static GrConvolutionEffectFactory* getInstance();
-
-protected:
-
-    GrConvolutionEffectFactory();
-
-    // TODO: find a more reliable installation than hand-coding
-    // id values like '1'. 
-    static const int sEffectId = 1;
-
-private:
-
-    typedef GrProgramStageFactory INHERITED;
-};
-
-GrConvolutionEffectFactory::~GrConvolutionEffectFactory() {
-
-}
-
-uint16_t GrConvolutionEffectFactory::stageKey(const GrCustomStage* s) {
-    const GrConvolutionEffect* c =
-        static_cast<const GrConvolutionEffect*>(s);
-    GrAssert(c->width() < 256);
-    return (sEffectId << 8) | (c->width() & 0xff);
-}
-
-GrGLProgramStage* GrConvolutionEffectFactory::createGLInstance(
-    GrCustomStage* s) {
-    return new GrGLConvolutionEffect(static_cast<GrConvolutionEffect*>(s));
-}
-
-GrConvolutionEffectFactory* GrConvolutionEffectFactory::getInstance() {
-    static GrConvolutionEffectFactory* instance =
-        new GrConvolutionEffectFactory;
-    return instance;
-}
-
-GrConvolutionEffectFactory::GrConvolutionEffectFactory() {
-
+GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey(
+                                                    const GrCustomStage* s) {
+    return static_cast<const GrConvolutionEffect*>(s)->width();
 }
 
 /////////////////////////////////////////////////////////////////////
@@ -236,11 +189,12 @@
 }
 
 const char* GrConvolutionEffect::name() const {
-    return "Convolution";
+    return Name();
 }
 
-GrProgramStageFactory* GrConvolutionEffect::getFactory() const {
-    return GrConvolutionEffectFactory::getInstance();
+
+const GrProgramStageFactory& GrConvolutionEffect::getFactory() const {
+    return GrTProgramStageFactory<GrConvolutionEffect>::getInstance();
 }
 
 bool GrConvolutionEffect::isEqual(const GrCustomStage * sBase) const {
diff --git a/src/gpu/effects/GrConvolutionEffect.h b/src/gpu/effects/GrConvolutionEffect.h
index e3c3aa9..4fdddd9 100644
--- a/src/gpu/effects/GrConvolutionEffect.h
+++ b/src/gpu/effects/GrConvolutionEffect.h
@@ -11,6 +11,8 @@
 #include "GrCustomStage.h"
 #include "GrSamplerState.h" // for MAX_KENEL_WIDTH, FilterDirection
 
+class GrGLConvolutionEffect;
+
 class GrConvolutionEffect : public GrCustomStage {
 
 public:
@@ -19,11 +21,17 @@
                         unsigned int kernelWidth, const float* kernel);
     virtual ~GrConvolutionEffect();
 
-    virtual const char* name() const SK_OVERRIDE;
-    virtual GrProgramStageFactory* getFactory() const SK_OVERRIDE;
-    virtual bool isEqual(const GrCustomStage *) const SK_OVERRIDE;
-
     unsigned int width() const { return fKernelWidth; }
+    const float* kernel() const { return fKernel; }
+    GrSamplerState::FilterDirection direction() const { return fDirection; }
+    
+    static const char* Name() { return "Convolution"; }
+
+    typedef GrGLConvolutionEffect GLProgramStage;
+    
+    virtual const char* name() const SK_OVERRIDE;
+    virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
+    virtual bool isEqual(const GrCustomStage *) const SK_OVERRIDE;
 
 protected:
 
@@ -31,7 +39,6 @@
     unsigned int fKernelWidth;
     float fKernel[MAX_KERNEL_WIDTH];
 
-    friend class GrGLConvolutionEffect;
 
 private: