Move convolution from code in GrGLProgram to new GrConvolutionEffect
class. This is the first test of the new Ganesh shader pipeline.

Also includes some cleanup of the gpu.gyp file: added src/gpu, allowing
us to remove ../ from many #include directives.

http://codereview.appspot.com/6199053/



git-svn-id: http://skia.googlecode.com/svn/trunk@3887 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/gl/GrGLCaps.cpp b/src/gpu/gl/GrGLCaps.cpp
index 6031c73..e3dcd57 100644
--- a/src/gpu/gl/GrGLCaps.cpp
+++ b/src/gpu/gl/GrGLCaps.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2012 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLCaps.h b/src/gpu/gl/GrGLCaps.h
index eb09576..d159d98 100644
--- a/src/gpu/gl/GrGLCaps.h
+++ b/src/gpu/gl/GrGLCaps.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2012 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLContextInfo.cpp b/src/gpu/gl/GrGLContextInfo.cpp
index 33e19ab..45368fe 100644
--- a/src/gpu/gl/GrGLContextInfo.cpp
+++ b/src/gpu/gl/GrGLContextInfo.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2012 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLCreateNativeInterface_none.cpp b/src/gpu/gl/GrGLCreateNativeInterface_none.cpp
index 914ed51..e0c72c5 100644
--- a/src/gpu/gl/GrGLCreateNativeInterface_none.cpp
+++ b/src/gpu/gl/GrGLCreateNativeInterface_none.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLCreateNullInterface.cpp b/src/gpu/gl/GrGLCreateNullInterface.cpp
index 0a27a06..d790e06 100644
--- a/src/gpu/gl/GrGLCreateNullInterface.cpp
+++ b/src/gpu/gl/GrGLCreateNullInterface.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -8,7 +7,7 @@
 
 
 #include "gl/GrGLInterface.h"
-#include "../GrTDArray.h"
+#include "GrTDArray.h"
 #include "GrGLDefines.h"
 
 GrGLvoid GR_GL_FUNCTION_TYPE nullGLActiveTexture(GrGLenum texture) {}
diff --git a/src/gpu/gl/GrGLDefaultInterface_native.cpp b/src/gpu/gl/GrGLDefaultInterface_native.cpp
index 13988c0..e695f15 100644
--- a/src/gpu/gl/GrGLDefaultInterface_native.cpp
+++ b/src/gpu/gl/GrGLDefaultInterface_native.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLDefaultInterface_none.cpp b/src/gpu/gl/GrGLDefaultInterface_none.cpp
index 183c477..84c7f7c 100644
--- a/src/gpu/gl/GrGLDefaultInterface_none.cpp
+++ b/src/gpu/gl/GrGLDefaultInterface_none.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLDefines.h b/src/gpu/gl/GrGLDefines.h
index 0e03b55..d63a166 100644
--- a/src/gpu/gl/GrGLDefines.h
+++ b/src/gpu/gl/GrGLDefines.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLIRect.h b/src/gpu/gl/GrGLIRect.h
index 05bba11..038520d 100644
--- a/src/gpu/gl/GrGLIRect.h
+++ b/src/gpu/gl/GrGLIRect.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLIndexBuffer.cpp b/src/gpu/gl/GrGLIndexBuffer.cpp
index b99bdd4..5468992 100644
--- a/src/gpu/gl/GrGLIndexBuffer.cpp
+++ b/src/gpu/gl/GrGLIndexBuffer.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLIndexBuffer.h b/src/gpu/gl/GrGLIndexBuffer.h
index 68c165f..3a08c0e 100644
--- a/src/gpu/gl/GrGLIndexBuffer.h
+++ b/src/gpu/gl/GrGLIndexBuffer.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -11,7 +10,7 @@
 #ifndef GrGLIndexBuffer_DEFINED
 #define GrGLIndexBuffer_DEFINED
 
-#include "../GrIndexBuffer.h"
+#include "GrIndexBuffer.h"
 #include "gl/GrGLInterface.h"
 
 class GrGpuGL;
diff --git a/src/gpu/gl/GrGLInterface.cpp b/src/gpu/gl/GrGLInterface.cpp
index bbcf923..a86c143b 100644
--- a/src/gpu/gl/GrGLInterface.cpp
+++ b/src/gpu/gl/GrGLInterface.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 3e1f1d4..88b1456 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -6,13 +5,13 @@
  * found in the LICENSE file.
  */
 
-
 #include "GrGLProgram.h"
 
-#include "../GrAllocator.h"
+#include "GrAllocator.h"
 #include "GrCustomStage.h"
 #include "GrGLProgramStage.h"
 #include "GrGLShaderVar.h"
+#include "GrProgramStageFactory.h"
 #include "SkTrace.h"
 #include "SkXfermode.h"
 
@@ -647,7 +646,6 @@
 bool GrGLProgram::genProgram(const GrGLContextInfo& gl,
                              GrCustomStage** customStages,
                              GrGLProgram::CachedData* programData) const {
-
     ShaderCodeSegments segments;
     const uint32_t& layout = fProgramDesc.fVertexLayout;
 
@@ -757,18 +755,12 @@
     }
 
     ///////////////////////////////////////////////////////////////////////////
-    // Convert generic effect representation to GL-specific backend so they
-    // can be accesseed in genStageCode() and in subsequent uses of
-    // programData.
+    // We need to convert generic effect representations to GL-specific
+    // backends so they can be accesseed in genStageCode() and in subsequent,
+    // uses of programData, but it's safest to do so below when we're *sure*
+    // we need them.
     for (int s = 0; s < GrDrawState::kNumStages; ++s) {
-        GrCustomStage* customStage = customStages[s];
-        if (NULL != customStage) {
-            GrGLProgramStageFactory* factory = customStage->getGLFactory();
-            programData->fCustomStage[s] =
-                factory->createGLInstance(customStage);
-        } else {
-            programData->fCustomStage[s] = NULL;
-        }
+        programData->fCustomStage[s] = NULL;
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -798,6 +790,12 @@
                     inCoords = texCoordAttrs[tcIdx].c_str();
                 }
 
+                if (NULL != customStages[s]) {
+                    GrProgramStageFactory* factory =
+                        customStages[s]->getFactory();
+                    programData->fCustomStage[s] =
+                        factory->createGLInstance(customStages[s]);
+                }
                 this->genStageCode(gl,
                                    s,
                                    fProgramDesc.fStages[s],
@@ -918,6 +916,12 @@
                         inCoords = texCoordAttrs[tcIdx].c_str();
                     }
 
+                    if (NULL != customStages[s]) {
+                        GrProgramStageFactory* factory =
+                            customStages[s]->getFactory();
+                        programData->fCustomStage[s] =
+                            factory->createGLInstance(customStages[s]);
+                    }
                     this->genStageCode(gl, s,
                         fProgramDesc.fStages[s],
                         inCoverage.size() ? inCoverage.c_str() : NULL,
@@ -1618,76 +1622,6 @@
 
 }
 
-void genConvolutionVS(int stageNum,
-                      const StageDesc& desc,
-                      ShaderCodeSegments* segments,
-                      GrGLProgram::StageUniLocations* locations,
-                      GrGLShaderVar** kernel,
-                      const char** imageIncrementName,
-                      const char* varyingVSName) {
-    //GrGLShaderVar* kernel = &segments->fFSUnis.push_back();
-    *kernel = &segments->fFSUnis.push_back();
-    (*kernel)->setType(kFloat_GrSLType);
-    (*kernel)->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
-    (*kernel)->setArrayCount(desc.fKernelWidth);
-    GrGLShaderVar* imgInc = &segments->fFSUnis.push_back();
-    imgInc->setType(kVec2f_GrSLType);
-    imgInc->setTypeModifier(GrGLShaderVar::kUniform_TypeModifier);
-
-    convolve_param_names(stageNum,
-                         (*kernel)->accessName(),
-                         imgInc->accessName());
-    *imageIncrementName = imgInc->getName().c_str();
-
-    // need image increment in both VS and FS
-    segments->fVSUnis.push_back(*imgInc).setEmitPrecision(true);
-
-    locations->fKernelUni = kUseUniform;
-    locations->fImageIncrementUni = kUseUniform;
-    float scale = (desc.fKernelWidth - 1) * 0.5f;
-    segments->fVSCode.appendf("\t%s -= vec2(%g, %g) * %s;\n",
-                                  varyingVSName, scale, scale,
-                                  *imageIncrementName);
-}
-
-void genConvolutionFS(int stageNum,
-                      const StageDesc& desc,
-                      ShaderCodeSegments* segments,
-                      const char* samplerName,
-                      GrGLShaderVar* kernel,
-                      const char* swizzle,
-                      const char* imageIncrementName,
-                      const char* fsOutColor,
-                      GrStringBuilder& sampleCoords,
-                      GrStringBuilder& texFunc,
-                      GrStringBuilder& modulate) {
-    GrStringBuilder sumVar("sum");
-    sumVar.appendS32(stageNum);
-    GrStringBuilder coordVar("coord");
-    coordVar.appendS32(stageNum);
-
-    GrStringBuilder kernelIndex;
-    kernel->appendArrayAccess("i", &kernelIndex);
-
-    segments->fFSCode.appendf("\tvec4 %s = vec4(0, 0, 0, 0);\n",
-                              sumVar.c_str());
-    segments->fFSCode.appendf("\tvec2 %s = %s;\n", 
-                              coordVar.c_str(),
-                              sampleCoords.c_str());
-    segments->fFSCode.appendf("\tfor (int i = 0; i < %d; i++) {\n",
-                              desc.fKernelWidth);
-    segments->fFSCode.appendf("\t\t%s += %s(%s, %s)%s * %s;\n",
-                              sumVar.c_str(), texFunc.c_str(),
-                              samplerName, coordVar.c_str(), swizzle,
-                              kernelIndex.c_str());
-    segments->fFSCode.appendf("\t\t%s += %s;\n",
-                              coordVar.c_str(),
-                              imageIncrementName);
-    segments->fFSCode.append("\t}\n");
-    segments->fFSCode.appendf("\t%s = %s%s;\n", fsOutColor,
-                              sumVar.c_str(), modulate.c_str());
-}
- 
 void genMorphologyVS(int stageNum,
                      const StageDesc& desc,
                      ShaderCodeSegments* segments,
@@ -1775,7 +1709,7 @@
     /// Vertex Shader Stuff
 
     if (NULL != customStage) {
-        customStage->setupVSUnis(segments->fVSUnis, stageNum);
+        customStage->setupVSUnis(&segments->fVSUnis, stageNum);
     }
 
     // decide whether we need a matrix to transform texture coords
@@ -1852,10 +1786,7 @@
 
     GrGLShaderVar* kernel = NULL;
     const char* imageIncrementName = NULL;
-    if (StageDesc::kConvolution_FetchMode == desc.fFetchMode) {
-        genConvolutionVS(stageNum, desc, segments, locations,
-                         &kernel, &imageIncrementName, varyingVSName);
-    } else if (StageDesc::kDilate_FetchMode == desc.fFetchMode ||
+    if (StageDesc::kDilate_FetchMode == desc.fFetchMode ||
                StageDesc::kErode_FetchMode == desc.fFetchMode) {
         genMorphologyVS(stageNum, desc, segments, locations,
                         &imageIncrementName, varyingVSName);
@@ -1864,15 +1795,16 @@
     if (NULL != customStage) {
         GrStringBuilder vertexShader;
         customStage->emitVS(&vertexShader, varyingVSName);
-        segments->fVSCode.appendf("{\n");
+        segments->fVSCode.appendf("\t{ // stage %d %s\n",
+                                  stageNum, customStage->name());
         segments->fVSCode.append(vertexShader);
-        segments->fVSCode.appendf("}\n");
+        segments->fVSCode.appendf("\t}\n");
     }
 
     /// Fragment Shader Stuff
 
     if (NULL != customStage) {
-        customStage->setupFSUnis(segments->fFSUnis, stageNum);
+        customStage->setupFSUnis(&segments->fFSUnis, stageNum);
     }
 
     GrStringBuilder fsCoordName;
@@ -1985,9 +1917,6 @@
         break;
     case StageDesc::kConvolution_FetchMode:
         GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
-        genConvolutionFS(stageNum, desc, segments,
-            samplerName, kernel, swizzle, imageIncrementName, fsOutColor,
-            sampleCoords, texFunc, modulate);
         break;
     case StageDesc::kDilate_FetchMode:
     case StageDesc::kErode_FetchMode:
@@ -2040,15 +1969,16 @@
 
         GrStringBuilder fragmentShader;
         fsCoordName = customStage->emitTextureSetup(
-                          &fragmentShader, varyingFSName,
+                          &fragmentShader, sampleCoords.c_str(),
                           stageNum, coordDims, varyingDims);
         customStage->emitFS(&fragmentShader, fsOutColor, fsInColor,
                             samplerName, fsCoordName.c_str());
       
         // Enclose custom code in a block to avoid namespace conflicts
-        segments->fFSCode.appendf("{\n");
+        segments->fFSCode.appendf("\t{ // stage %d %s \n",
+                                  stageNum, customStage->name());
         segments->fFSCode.append(fragmentShader);
-        segments->fFSCode.appendf("}\n");
+        segments->fFSCode.appendf("\t}\n");
     }
 }
 
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 73bfa94..9e2ee7e 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -10,11 +9,11 @@
 #ifndef GrGLProgram_DEFINED
 #define GrGLProgram_DEFINED
 
-#include "../GrDrawState.h"
+#include "GrDrawState.h"
 #include "GrGLContextInfo.h"
 #include "GrGLSL.h"
-#include "../GrStringBuilder.h"
-#include "../GrGpu.h"
+#include "GrStringBuilder.h"
+#include "GrGpu.h"
 
 #include "SkXfermode.h"
 
@@ -108,6 +107,7 @@
                 kCustomTextureDomain_OptFlagBit = 1 << 2,
                 kIsEnabled_OptFlagBit           = 1 << 7
             };
+            // Convolution is obsolete; left in for testing only
             enum FetchMode {
                 kSingle_FetchMode,
                 k2x2_FetchMode,
@@ -320,6 +320,9 @@
 
         void copyAndTakeOwnership(CachedData& other) {
             memcpy(this, &other, sizeof(*this));
+            for (int i = 0; i < GrDrawState::kNumStages; ++i) {
+                other.fCustomStage[i] = NULL;
+            }
         }
 
     public:
diff --git a/src/gpu/gl/GrGLProgramStage.cpp b/src/gpu/gl/GrGLProgramStage.cpp
index 302eb07..6620438 100644
--- a/src/gpu/gl/GrGLProgramStage.cpp
+++ b/src/gpu/gl/GrGLProgramStage.cpp
@@ -13,19 +13,11 @@
 
 ///////////////////////////////////////////////////////////////////////////////
 
-GrGLProgramStageFactory::~GrGLProgramStageFactory(void) {
+void GrGLProgramStage::setupVSUnis(VarArray* vsUnis, int stage) {
 
 }
 
-uint16_t GrGLProgramStageFactory::stageKey(const GrCustomStage*) {
-    return 0;
-}
-
-void GrGLProgramStage::setupVSUnis(VarArray& vsUnis, int stage) {
-
-}
-
-void GrGLProgramStage::setupFSUnis(VarArray& fsUnis, int stage) {
+void GrGLProgramStage::setupFSUnis(VarArray* fsUnis, int stage) {
 
 }
 
@@ -33,7 +25,8 @@
 
 }
 
-void GrGLProgramStage::setData(const GrGLInterface*, GrCustomStage*) {
+void GrGLProgramStage::setData(const GrGLInterface*, GrCustomStage*,
+                               const GrGLTexture*) {
 
 }
 
diff --git a/src/gpu/gl/GrGLProgramStage.h b/src/gpu/gl/GrGLProgramStage.h
index 210b4c3..340c99f 100644
--- a/src/gpu/gl/GrGLProgramStage.h
+++ b/src/gpu/gl/GrGLProgramStage.h
@@ -8,13 +8,14 @@
 #ifndef GrGLCustomStage_DEFINED
 #define GrGLCustomStage_DEFINED
 
-#include "../GrAllocator.h"
+#include "GrAllocator.h"
 #include "GrGLShaderVar.h"
 #include "GrGLSL.h"
-#include "../GrStringBuilder.h"
+#include "GrStringBuilder.h"
 
 class GrCustomStage;
 struct GrGLInterface;
+class GrGLTexture;
 
 /** @file
     This file contains specializations for OpenGL of the shader stages
@@ -39,17 +40,19 @@
     
     virtual ~GrGLProgramStage();
 
+    virtual const char* name() const = 0;
+
     /** Creates any uniform variables the vertex shader requires
         and appends them to vsUnis;
         must guarantee they are unique (typically done by
         appending the stage number). */
-    virtual void setupVSUnis(VarArray& vsUnis, int stage);
+    virtual void setupVSUnis(VarArray* vsUnis, int stage);
 
     /** Creates any uniform variables the fragment shader requires
         and appends them to fsUnis;
         must guarantee they are unique (typically done by
         appending the stage number). */
-    virtual void setupFSUnis(VarArray& fsUnis, int stage);
+    virtual void setupFSUnis(VarArray* fsUnis, int stage);
 
     /** Given an empty GrStringBuilder and the names of variables;
         must write shader code into that GrStringBuilder.
@@ -86,7 +89,8 @@
         are to be read.
         TODO: since we don't have a factory, we can't assert to enforce
         this. Shouldn't we? */
-    virtual void setData(const GrGLInterface*, GrCustomStage*);
+    virtual void setData(const GrGLInterface*, GrCustomStage*,
+                         const GrGLTexture*);
 
     // TODO: needs a better name
     enum SamplerMode {
@@ -95,7 +99,7 @@
         kExplicitDivide_SamplerMode  // must do an explicit divide
     };
 
-    void setSamplerMode(SamplerMode shaderMode) { fSamplerMode = shaderMode; }
+    void setSamplerMode(SamplerMode samplerMode) { fSamplerMode = samplerMode; }
 
     /** Returns the *effective* coord name after any perspective divide
         or other transform. */
@@ -118,33 +122,4 @@
 
 };
 
-
-/// Every GrGLProgramStage subclass needs a GrGLProgramStageFactory subclass
-/// to manage its creation.
-
-class GrGLProgramStageFactory {
-
-public:
-
-    virtual ~GrGLProgramStageFactory();
-
-    /** Returns a short unique identifier for this subclass x its
-        parameters. If the key differs, different shader code must
-        be generated; if the key matches, shader code can be reused.
-        0 == no custom stage. */
-    virtual uint16_t stageKey(const GrCustomStage*);
-
-    /** Returns a new instance of the appropriate implementation class
-        for the given GrCustomStage; caller is responsible for deleting
-        the object. */
-    virtual GrGLProgramStage* createGLInstance(GrCustomStage*) = 0;
-
-protected:
-
-    /** Disable default constructor - instances should be singletons
-        with static factory functions: our test examples are all stateless,
-        but we suspect that future implementations may want to cache data? */
-    GrGLProgramStageFactory() { }
-};
-
 #endif
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index c98914a..cce3def 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -6,7 +5,6 @@
  * found in the LICENSE file.
  */
 
-
 #include "GrGLRenderTarget.h"
 
 #include "GrGpuGL.h"
diff --git a/src/gpu/gl/GrGLRenderTarget.h b/src/gpu/gl/GrGLRenderTarget.h
index eb817df..d5f04d4 100644
--- a/src/gpu/gl/GrGLRenderTarget.h
+++ b/src/gpu/gl/GrGLRenderTarget.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLShaderVar.h b/src/gpu/gl/GrGLShaderVar.h
index 149214e..1f9b990 100644
--- a/src/gpu/gl/GrGLShaderVar.h
+++ b/src/gpu/gl/GrGLShaderVar.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -11,7 +10,7 @@
 
 #include "GrGLContextInfo.h"
 #include "GrGLSL.h"
-#include "../GrStringBuilder.h"
+#include "GrStringBuilder.h"
 
 #define USE_UNIFORM_FLOAT_ARRAYS true
 
diff --git a/src/gpu/gl/GrGLStencilBuffer.cpp b/src/gpu/gl/GrGLStencilBuffer.cpp
index bc0bb36..69c0959 100644
--- a/src/gpu/gl/GrGLStencilBuffer.cpp
+++ b/src/gpu/gl/GrGLStencilBuffer.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLStencilBuffer.h b/src/gpu/gl/GrGLStencilBuffer.h
index 908921a..87bdb4a 100644
--- a/src/gpu/gl/GrGLStencilBuffer.h
+++ b/src/gpu/gl/GrGLStencilBuffer.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -11,7 +10,7 @@
 #define GrGLStencilBuffer_DEFINED
 
 #include "gl/GrGLInterface.h"
-#include "../GrStencilBuffer.h"
+#include "GrStencilBuffer.h"
 
 class GrGLStencilBuffer : public GrStencilBuffer {
 public:
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index 0a38da3..3d30610 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLTexture.h b/src/gpu/gl/GrGLTexture.h
index d13fc44..77e1c32 100644
--- a/src/gpu/gl/GrGLTexture.h
+++ b/src/gpu/gl/GrGLTexture.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -10,7 +9,7 @@
 #ifndef GrGLTexture_DEFINED
 #define GrGLTexture_DEFINED
 
-#include "../GrGpu.h"
+#include "GrGpu.h"
 #include "GrGLRenderTarget.h"
 
 /**
diff --git a/src/gpu/gl/GrGLUtil.cpp b/src/gpu/gl/GrGLUtil.cpp
index c11c8c0..9d854ba 100644
--- a/src/gpu/gl/GrGLUtil.cpp
+++ b/src/gpu/gl/GrGLUtil.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLVertexBuffer.cpp b/src/gpu/gl/GrGLVertexBuffer.cpp
index 5c94c36..d932f11 100644
--- a/src/gpu/gl/GrGLVertexBuffer.cpp
+++ b/src/gpu/gl/GrGLVertexBuffer.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGLVertexBuffer.h b/src/gpu/gl/GrGLVertexBuffer.h
index 5d2ba30..7df759e 100644
--- a/src/gpu/gl/GrGLVertexBuffer.h
+++ b/src/gpu/gl/GrGLVertexBuffer.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -11,7 +10,7 @@
 #ifndef GrGLVertexBuffer_DEFINED
 #define GrGLVertexBuffer_DEFINED
 
-#include "../GrVertexBuffer.h"
+#include "GrVertexBuffer.h"
 #include "gl/GrGLInterface.h"
 
 class GrGpuGL;
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 9aa9b31..69e494a 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index 77b300a..0f16feb 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -11,8 +10,8 @@
 #ifndef GrGpuGL_DEFINED
 #define GrGpuGL_DEFINED
 
-#include "../GrDrawState.h"
-#include "../GrGpu.h"
+#include "GrDrawState.h"
+#include "GrGpu.h"
 #include "GrGLContextInfo.h"
 #include "GrGLIndexBuffer.h"
 #include "GrGLIRect.h"
diff --git a/src/gpu/gl/GrGpuGLShaders.cpp b/src/gpu/gl/GrGpuGLShaders.cpp
index f381564..9b6600b 100644
--- a/src/gpu/gl/GrGpuGLShaders.cpp
+++ b/src/gpu/gl/GrGpuGLShaders.cpp
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *
@@ -7,16 +6,18 @@
  */
 
 
-#include "../GrBinHashKey.h"
+#include "GrBinHashKey.h"
+#include "effects/GrConvolutionEffect.h"
 #include "GrCustomStage.h"
 #include "GrGLProgram.h"
 #include "GrGLProgramStage.h"
 #include "GrGLSL.h"
 #include "GrGpuGLShaders.h"
-#include "../GrGpuVertex.h"
+#include "GrGpuVertex.h"
 #include "GrNoncopyable.h"
-#include "../GrStringBuilder.h"
-#include "../GrRandom.h"
+#include "GrProgramStageFactory.h"
+#include "GrRandom.h"
+#include "GrStringBuilder.h"
 
 #define SKIP_CACHE_CHECK    true
 #define GR_UINT32_MAX   static_cast<uint32_t>(-1)
@@ -263,6 +264,10 @@
                 pdesc.fVertexLayout |= kTextFormat_VertexLayoutBit;
             }
             StageDesc& stage = pdesc.fStages[s];
+
+            stage.fCustomStageKey = 0;
+            customStages[s] = NULL;
+
             stage.fOptFlags = STAGE_OPTS[random_int(&random, GR_ARRAY_COUNT(STAGE_OPTS))];
             stage.fInConfigFlags = IN_CONFIG_FLAGS[random_int(&random, GR_ARRAY_COUNT(IN_CONFIG_FLAGS))];
             stage.fCoordMapping =  random_int(&random, StageDesc::kCoordMappingCnt);
@@ -294,8 +299,19 @@
                     break;
             }
 
-            stage.fCustomStageKey = 0;
-            customStages[s] = NULL;
+            // TODO: is there a more elegant way to express this?
+            if (stage.fFetchMode == StageDesc::kConvolution_FetchMode) {
+                int direction = random_int(&random, 2);
+                float kernel[stage.fKernelWidth];
+                for (int i = 0; i < stage.fKernelWidth; i++) {
+                    kernel[i] = random.nextF();
+                }
+                customStages[s] = new GrConvolutionEffect(
+                    (GrSamplerState::FilterDirection)direction,
+                    stage.fKernelWidth, kernel);
+                stage.fCustomStageKey =
+                    customStages[s]->getFactory()->stageKey(customStages[s]);
+            }
         }
         CachedData cachedData;
         if (!program.genProgram(this->glContextInfo(), customStages,
@@ -829,8 +845,11 @@
             if (NULL != fProgramData->fCustomStage[s]) {
                 const GrSamplerState& sampler =
                     this->getDrawState().getSampler(s);
+                const GrGLTexture* texture =
+                    static_cast<const GrGLTexture*>(
+                        this->getDrawState().getTexture(s));
                 fProgramData->fCustomStage[s]->setData(
-                    this->glInterface(), sampler.getCustomStage());
+                    this->glInterface(), sampler.getCustomStage(), texture);
             }
         }
     }
@@ -1002,7 +1021,7 @@
                         GrGLProgram* program, int index) {
     GrCustomStage* customStage = sampler.getCustomStage();
     if (customStage) {
-        GrGLProgramStageFactory* factory = customStage->getGLFactory();
+        GrProgramStageFactory* factory = customStage->getFactory();
         stage->fCustomStageKey = factory->stageKey(customStage);
         customStages[index] = customStage;
     } else {
@@ -1215,8 +1234,7 @@
                 }
             }
 
-            if (sampler.getFilter() == GrSamplerState::kConvolution_Filter ||
-                sampler.getFilter() == GrSamplerState::kDilate_Filter ||
+            if (sampler.getFilter() == GrSamplerState::kDilate_Filter ||
                 sampler.getFilter() == GrSamplerState::kErode_Filter) {
                 stage.fKernelWidth = sampler.getKernelWidth();
             } else {
diff --git a/src/gpu/gl/GrGpuGLShaders.h b/src/gpu/gl/GrGpuGLShaders.h
index 2ce95eb..55fd952 100644
--- a/src/gpu/gl/GrGpuGLShaders.h
+++ b/src/gpu/gl/GrGpuGLShaders.h
@@ -1,4 +1,3 @@
-
 /*
  * Copyright 2011 Google Inc.
  *