First stage of reworking custom shader infrastructure to allow
radial mappings.

http://codereview.appspot.com/6239043/



git-svn-id: http://skia.googlecode.com/svn/trunk@4040 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 29d1573..8ccf585 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -21,23 +21,24 @@
                           const GrCustomStage* stage);
     virtual void setupVSUnis(VarArray* vsUnis, int stage) SK_OVERRIDE;
     virtual void setupFSUnis(VarArray* fsUnis, int stage) SK_OVERRIDE;
-    virtual void emitVS(GrStringBuilder* code,
+    virtual void emitVS(GrGLShaderBuilder* state,
                         const char* vertexCoords) SK_OVERRIDE;
-    virtual void emitFS(GrStringBuilder* code,
+    virtual void emitFS(GrGLShaderBuilder* state,
                         const char* outputColor,
                         const char* inputColor,
-                        const char* samplerName,
-                        const char* sampleCoords) SK_OVERRIDE;
+                        const char* samplerName) SK_OVERRIDE;
     virtual void initUniforms(const GrGLInterface*, int programID) SK_OVERRIDE;
 
-    virtual void setData(const GrGLInterface*, const GrCustomStage*,
-                         const GrGLTexture*) SK_OVERRIDE;
+    virtual void setData(const GrGLInterface*, 
+                         const GrGLTexture&,
+                         GrCustomStage*,
+                         int stageNum) SK_OVERRIDE;
 
     static inline StageKey GenKey(const GrCustomStage* s);
     
 protected:
 
-    int            fKernelWidth;
+    unsigned int   fKernelWidth;
     GrGLShaderVar* fKernelVar;
     GrGLShaderVar* fImageIncrementVar;
  
@@ -89,8 +90,9 @@
     fsUnis->push_back(*fImageIncrementVar).setEmitPrecision(false);
 }
 
-void GrGLConvolutionEffect::emitVS(GrStringBuilder* code,
+void GrGLConvolutionEffect::emitVS(GrGLShaderBuilder* state,
                         const char* vertexCoords) {
+    GrStringBuilder* code = &state->fVSCode;
     float scale = (fKernelWidth - 1) * 0.5f;
     code->appendf("\t\t%s -= vec2(%g, %g) * %s;\n",
                   vertexCoords, scale, scale,
@@ -98,11 +100,11 @@
 
 }
 
-void GrGLConvolutionEffect::emitFS(GrStringBuilder* code,
+void GrGLConvolutionEffect::emitFS(GrGLShaderBuilder* state,
                         const char* outputColor,
                         const char* inputColor,
-                        const char* samplerName,
-                        const char* sampleCoords) {
+                        const char* samplerName) {
+    GrStringBuilder* code = &state->fFSCode;
     const char* texFunc = "texture2D";
     bool complexCoord = false;
 
@@ -117,7 +119,7 @@
     fKernelVar->appendArrayAccess("i", &kernelIndex);
 
     code->appendf("\t\tvec4 sum = vec4(0, 0, 0, 0);\n");
-    code->appendf("\t\tvec2 coord = %s;\n", sampleCoords);
+    code->appendf("\t\tvec2 coord = %s;\n", state->fSampleCoords.c_str());
     code->appendf("\t\tfor (int i = 0; i < %d; i++) {\n",
                   fKernelWidth);
 
@@ -141,8 +143,9 @@
 }
 
 void GrGLConvolutionEffect::setData(const GrGLInterface* gl,
-                                    const GrCustomStage* data,
-                                    const GrGLTexture* texture) {
+                                    const GrGLTexture& texture,
+                                    GrCustomStage* data,
+                                    int stageNum) {
     const GrConvolutionEffect* conv =
         static_cast<const GrConvolutionEffect*>(data);
     // the code we generated was for a specific kernel width
@@ -153,10 +156,10 @@
     float imageIncrement[2] = { 0 };
     switch (conv->direction()) {
         case GrSamplerState::kX_FilterDirection:
-            imageIncrement[0] = 1.0f / texture->width();
+            imageIncrement[0] = 1.0f / texture.width();
             break;
         case GrSamplerState::kY_FilterDirection:
-            imageIncrement[1] = 1.0f / texture->width();
+            imageIncrement[1] = 1.0f / texture.width();
             break;
         default:
             GrCrash("Unknown filter direction.");
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 755a2f8..8fc3ac2 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -1588,11 +1588,9 @@
     }
 
     if (NULL != customStage) {
-        GrStringBuilder vertexShader;
-        customStage->emitVS(&vertexShader, varyingVSName);
         segments->fVSCode.appendf("\t{ // stage %d %s\n",
                                   stageNum, customStage->name());
-        segments->fVSCode.append(vertexShader);
+        customStage->emitVS(segments, varyingVSName);
         segments->fVSCode.appendf("\t}\n");
     }
 
@@ -1631,30 +1629,32 @@
     }
 
     segments->fComplexCoord = false;
-    switch (desc.fCoordMapping) {
-    case StageDesc::kIdentity_CoordMapping:
-        // Do nothing
-        break;
-    case StageDesc::kSweepGradient_CoordMapping:
-        segments->fSampleCoords.printf("vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)", segments->fSampleCoords.c_str(), segments->fSampleCoords.c_str());
-        segments->fComplexCoord = true;
-        break;
-    case StageDesc::kRadialGradient_CoordMapping:
-        segments->fSampleCoords.printf("vec2(length(%s.xy), 0.5)", segments->fSampleCoords.c_str());
-        segments->fComplexCoord = true;
-        break;
-    case StageDesc::kRadial2Gradient_CoordMapping:
-        genRadial2GradientCoordMapping(
-                           stageNum, segments,
-                           radial2VaryingFSName, radial2Params);
-        break;
-    case StageDesc::kRadial2GradientDegenerate_CoordMapping:
-        genRadial2GradientDegenerateCoordMapping(
-                           stageNum, segments,
-                           radial2VaryingFSName, radial2Params);
-        break;
-
-    };
+    // NOTE: GrGLProgramStages will soon responsible for mapping
+    //if (NULL == customStage) {
+        switch (desc.fCoordMapping) {
+        case StageDesc::kIdentity_CoordMapping:
+            // Do nothing
+            break;
+        case StageDesc::kSweepGradient_CoordMapping:
+            segments->fSampleCoords.printf("vec2(atan(- %s.y, - %s.x) * 0.1591549430918 + 0.5, 0.5)", segments->fSampleCoords.c_str(), segments->fSampleCoords.c_str());
+            segments->fComplexCoord = true;
+            break;
+        case StageDesc::kRadialGradient_CoordMapping:
+            segments->fSampleCoords.printf("vec2(length(%s.xy), 0.5)", segments->fSampleCoords.c_str());
+            segments->fComplexCoord = true;
+            break;
+        case StageDesc::kRadial2Gradient_CoordMapping:
+            genRadial2GradientCoordMapping(
+                               stageNum, segments,
+                               radial2VaryingFSName, radial2Params);
+            break;
+        case StageDesc::kRadial2GradientDegenerate_CoordMapping:
+            genRadial2GradientDegenerateCoordMapping(
+                               stageNum, segments,
+                               radial2VaryingFSName, radial2Params);
+            break;
+        }
+    //}
 
     static const uint32_t kMulByAlphaMask =
         (StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag |
@@ -1697,52 +1697,55 @@
         locations->fTexDomUni = kUseUniform;
     }
 
-    switch (desc.fFetchMode) {
-    case StageDesc::k2x2_FetchMode:
-        GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
-        gen2x2FS(stageNum, segments, locations,
-            samplerName, texelSizeName, swizzle, fsOutColor,
-            texFunc, modulate);
-        break;
-    case StageDesc::kConvolution_FetchMode:
-        GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
-        break;
-    case StageDesc::kDilate_FetchMode:
-    case StageDesc::kErode_FetchMode:
-        GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
-        genMorphologyFS(stageNum, desc, segments,
-            samplerName, swizzle, imageIncrementName, fsOutColor,
-            texFunc, modulate);
-        break;
-    default:
-        if (desc.fInConfigFlags & kMulByAlphaMask) {
-            // only one of the mul by alpha flags should be set
-            GrAssert(GrIsPow2(kMulByAlphaMask & desc.fInConfigFlags));
-            GrAssert(!(desc.fInConfigFlags & 
-                       StageDesc::kSmearAlpha_InConfigFlag));
-            GrAssert(!(desc.fInConfigFlags & 
-                       StageDesc::kSmearRed_InConfigFlag));
-            segments->fFSCode.appendf("\t%s = %s(%s, %s)%s;\n",
-                                      fsOutColor, texFunc.c_str(), 
-                                      samplerName,
-                                      segments->fSampleCoords.c_str(),
-                                      swizzle);
-            if (desc.fInConfigFlags &
-                StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag) {
-                segments->fFSCode.appendf("\t%s = vec4(ceil(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
-                                          fsOutColor, fsOutColor, fsOutColor,
-                                          fsOutColor, modulate.c_str());
+    // NOTE: GrGLProgramStages are now responsible for fetching
+    if (NULL == customStage) {
+        switch (desc.fFetchMode) {
+        case StageDesc::k2x2_FetchMode:
+            GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
+            gen2x2FS(stageNum, segments, locations,
+                samplerName, texelSizeName, swizzle, fsOutColor,
+                texFunc, modulate);
+            break;
+        case StageDesc::kConvolution_FetchMode:
+            GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
+            break;
+        case StageDesc::kDilate_FetchMode:
+        case StageDesc::kErode_FetchMode:
+            GrAssert(!(desc.fInConfigFlags & kMulByAlphaMask));
+            genMorphologyFS(stageNum, desc, segments,
+                samplerName, swizzle, imageIncrementName, fsOutColor,
+                texFunc, modulate);
+            break;
+        default:
+            if (desc.fInConfigFlags & kMulByAlphaMask) {
+                // only one of the mul by alpha flags should be set
+                GrAssert(GrIsPow2(kMulByAlphaMask & desc.fInConfigFlags));
+                GrAssert(!(desc.fInConfigFlags & 
+                           StageDesc::kSmearAlpha_InConfigFlag));
+                GrAssert(!(desc.fInConfigFlags & 
+                           StageDesc::kSmearRed_InConfigFlag));
+                segments->fFSCode.appendf("\t%s = %s(%s, %s)%s;\n",
+                                          fsOutColor, texFunc.c_str(), 
+                                          samplerName,
+                                          segments->fSampleCoords.c_str(),
+                                          swizzle);
+                if (desc.fInConfigFlags &
+                    StageDesc::kMulRGBByAlpha_RoundUp_InConfigFlag) {
+                    segments->fFSCode.appendf("\t%s = vec4(ceil(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
+                                              fsOutColor, fsOutColor, fsOutColor,
+                                              fsOutColor, modulate.c_str());
+                } else {
+                    segments->fFSCode.appendf("\t%s = vec4(floor(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
+                                              fsOutColor, fsOutColor, fsOutColor,
+                                              fsOutColor, modulate.c_str());
+                }
             } else {
-                segments->fFSCode.appendf("\t%s = vec4(floor(%s.rgb*%s.a*255.0)/255.0,%s.a)%s;\n",
-                                          fsOutColor, fsOutColor, fsOutColor,
-                                          fsOutColor, modulate.c_str());
+                segments->fFSCode.appendf("\t%s = %s(%s, %s)%s%s;\n",
+                                          fsOutColor, texFunc.c_str(), 
+                                          samplerName, 
+                                          segments->fSampleCoords.c_str(),
+                                          swizzle, modulate.c_str());
             }
-        } else {
-            segments->fFSCode.appendf("\t%s = %s(%s, %s)%s%s;\n",
-                                      fsOutColor, texFunc.c_str(), 
-                                      samplerName, 
-                                      segments->fSampleCoords.c_str(),
-                                      swizzle, modulate.c_str());
         }
     }
 
@@ -1762,8 +1765,7 @@
         segments->fFSCode.appendf("\t{ // stage %d %s \n",
                                   stageNum, customStage->name());
         customStage->emitTextureSetup(segments);
-        customStage->emitFS(&segments->fFSCode, fsOutColor, fsInColor,
-                            samplerName, segments->fSampleCoords.c_str());
+        customStage->emitFS(segments, fsOutColor, fsInColor, samplerName);
         segments->fFSCode.appendf("\t}\n");
     }
 }
diff --git a/src/gpu/gl/GrGLProgramStage.cpp b/src/gpu/gl/GrGLProgramStage.cpp
index 1221631..b5e2228 100644
--- a/src/gpu/gl/GrGLProgramStage.cpp
+++ b/src/gpu/gl/GrGLProgramStage.cpp
@@ -25,12 +25,19 @@
 
 }
 
+void GrGLProgramStage::setupVaryings(GrGLShaderBuilder* state, int stage) {
+
+}
+
 void GrGLProgramStage::initUniforms(const GrGLInterface*, int progID) {
 
 }
 
-void GrGLProgramStage::setData(const GrGLInterface*, const GrCustomStage*,
-                               const GrGLTexture*) {
+void GrGLProgramStage::setData(const GrGLInterface*, 
+                               const GrGLTexture&, 
+                               GrCustomStage*,
+                               int stageNum) {
+
 
 }
 
@@ -74,3 +81,15 @@
 
 }
 
+void GrGLProgramStage::emitDefaultFetch(GrGLShaderBuilder* state,
+                                        const char* fsOutColor,
+                                        const char* samplerName,
+                                        const char* swizzle,
+                                        const char* modulate) {
+    state->fFSCode.appendf("\t%s = ", fsOutColor);
+    this->emitTextureLookup(&state->fFSCode, samplerName,
+                            state->fSampleCoords.c_str());
+    state->fFSCode.appendf("%s%s;\n", swizzle, modulate);
+}
+
+
diff --git a/src/gpu/gl/GrGLProgramStage.h b/src/gpu/gl/GrGLProgramStage.h
index f072596..60ab60d 100644
--- a/src/gpu/gl/GrGLProgramStage.h
+++ b/src/gpu/gl/GrGLProgramStage.h
@@ -10,6 +10,7 @@
 
 #include "GrAllocator.h"
 #include "GrCustomStage.h"
+#include "GrGLProgram.h"
 #include "GrGLShaderBuilder.h"
 #include "GrGLShaderVar.h"
 #include "GrGLSL.h"
@@ -38,8 +39,6 @@
         kUseUniform = 2000
     };
 
-    typedef GrTAllocator<GrGLShaderVar> VarArray;
-
     GrGLProgramStage(const GrProgramStageFactory&);
 
     virtual ~GrGLProgramStage();
@@ -56,16 +55,22 @@
         appending the stage number). */
     virtual void setupFSUnis(VarArray* fsUnis, int stage);
 
-    /** Given an empty GrStringBuilder and the names of variables;
-        must write shader code into that GrStringBuilder.
+    /** Creates any varying variables shared between the shaders;
+        must guarantee they are unique (typically done by
+        appending the stage number). */
+    virtual void setupVaryings(GrGLShaderBuilder* state, int stage);
+
+    /** Appends vertex code to the appropriate GrStringBuilder
+        on the state.
+        The code will be inside an otherwise-empty block.
         Vertex shader input is a vec2 of coordinates, which may
         be altered.
         The code will be inside an otherwise-empty block. */
-    virtual void emitVS(GrStringBuilder* code,
+    virtual void emitVS(GrGLShaderBuilder* state,
                         const char* vertexCoords) = 0;
 
-    /** Given an empty GrStringBuilder and the names of variables;
-        must write shader code into that GrStringBuilder.
+    /** Appends fragment code to the appropriate GrStringBuilder
+        on the state.
         The code will be inside an otherwise-empty block.
         Fragment shader inputs are a vec2 of coordinates, one texture,
         and a color; output is a color. */
@@ -73,26 +78,23 @@
        a function here for them to call into that'll apply any texture
        domain - but do we force them to be honest about texture domain
        parameters? */
-    virtual void emitFS(GrStringBuilder* code,
+    virtual void emitFS(GrGLShaderBuilder* state,
                         const char* outputColor,
                         const char* inputColor,
-                        const char* samplerName,
-                        const char* sampleCoords) = 0;
+                        const char* samplerName) = 0;
 
     /** Binds uniforms; we must have already bound the program and
         determined its GL program ID. */
-    virtual void initUniforms(const GrGLInterface*, int programID);
+    virtual void initUniforms(const GrGLInterface* gl, int programID);
 
     /** A GrGLCustomStage instance can be reused with any GrCustomStage
         that produces the same stage key; this function reads data from
         a stage and uploads any uniform variables required by the shaders
-        created in emit*().
-        flush() to change the GrCustomStage from which the uniforms
-        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*, const GrCustomStage*,
-                         const GrGLTexture*);
+        created in emit*(). */
+    virtual void setData(const GrGLInterface* gl,
+                         const GrGLTexture& texture,
+                         GrCustomStage* stage,
+                         int stageNum);
 
     // TODO: needs a better name
     enum SamplerMode {
@@ -121,6 +123,14 @@
                            const char* samplerName,
                            const char* coordName);
 
+    /** Standard texture fetch, complete with swizzle & modulate if
+        appropriate. */
+    void emitDefaultFetch(GrGLShaderBuilder* state,
+                          const char* fsOutColor,
+                          const char* samplerName,
+                          const char* swizzle,
+                          const char* modulate);
+
     SamplerMode fSamplerMode;
 
     const GrProgramStageFactory& fFactory;
diff --git a/src/gpu/gl/GrGpuGLShaders.cpp b/src/gpu/gl/GrGpuGLShaders.cpp
index 0589cfe..802574c 100644
--- a/src/gpu/gl/GrGpuGLShaders.cpp
+++ b/src/gpu/gl/GrGpuGLShaders.cpp
@@ -764,7 +764,8 @@
                     static_cast<const GrGLTexture*>(
                         this->getDrawState().getTexture(s));
                 fProgramData->fCustomStage[s]->setData(
-                    this->glInterface(), sampler.getCustomStage(), texture);
+                    this->glInterface(), *texture,
+                    sampler.getCustomStage(), s);
             }
         }
     }