Revert 5428 and 5429.



git-svn-id: http://skia.googlecode.com/svn/trunk@5430 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/effects/GrColorTableEffect.cpp b/src/gpu/effects/GrColorTableEffect.cpp
index d662398..56c5109 100644
--- a/src/gpu/effects/GrColorTableEffect.cpp
+++ b/src/gpu/effects/GrColorTableEffect.cpp
@@ -65,20 +65,20 @@
     }
 
     code->appendf("\t\t%s.a = ", outputColor);
-    builder->appendTextureLookup(code, samplers[0], "vec2(coord.a, 0.125)");
-    code->append(";\n");
+    builder->emitCustomTextureLookup(samplers[0],
+                                     "vec2(coord.a, 0.125)");
 
     code->appendf("\t\t%s.r = ", outputColor);
-    builder->appendTextureLookup(code, samplers[0], "vec2(coord.r, 0.375)");
-    code->append(";\n");
+    builder->emitCustomTextureLookup(samplers[0],
+                                     "vec2(coord.r, 0.375)");
 
     code->appendf("\t\t%s.g = ", outputColor);
-    builder->appendTextureLookup(code, samplers[0], "vec2(coord.g, 0.625)");
-    code->append(";\n");
+    builder->emitCustomTextureLookup(samplers[0],
+                                     "vec2(coord.g, 0.625)");
 
     code->appendf("\t\t%s.b = ", outputColor);
-    builder->appendTextureLookup(code, samplers[0], "vec2(coord.b, 0.875)");
-    code->append(";\n");
+    builder->emitCustomTextureLookup(samplers[0],
+                                     "vec2(coord.b, 0.875)");
 
     code->appendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
 }
diff --git a/src/gpu/effects/GrConfigConversionEffect.cpp b/src/gpu/effects/GrConfigConversionEffect.cpp
index a5385ac..ffaab35 100644
--- a/src/gpu/effects/GrConfigConversionEffect.cpp
+++ b/src/gpu/effects/GrConfigConversionEffect.cpp
@@ -25,6 +25,7 @@
                         const TextureSamplerArray& samplers) SK_OVERRIDE {
         builder->fFSCode.appendf("\t\t%s = ", outputColor);
         builder->appendTextureLookup(&builder->fFSCode, samplers[0]);
+        builder->fFSCode.appendf("%s;\n", builder->fSwizzle.c_str());
         if (GrConfigConversionEffect::kNone_PMConversion == fPMConversion) {
             GrAssert(fSwapRedAndBlue);
             builder->fFSCode.appendf("\t%s = %s.bgra;\n", outputColor, outputColor);
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index dfe5277..934c4fc 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -964,30 +964,16 @@
 
     int numTextures = stage->numTextures();
     SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers;
-    // temporary until we force custom stages to provide their own texture access
-    SkSTArray<8, bool, true> deleteTextureAccess;
-
     textureSamplers.push_back_n(numTextures);
-    deleteTextureAccess.push_back_n(numTextures);
-
     for (int i = 0; i < numTextures; ++i) {
         // Right now we don't require a texture access for every texture. This will change soon.
         const GrTextureAccess* access = stage->textureAccess(i);
-        GrAssert(NULL != stage->texture(i));
-        if (NULL == access) {
-            SkString swizzle;
-            if (desc.fInConfigFlags & StageDesc::kSmearAlpha_InConfigFlag) {
-                swizzle.printf("aaaa");
-            } else {
-                swizzle.printf("rgba");
-            }
-            access = SkNEW_ARGS(GrTextureAccess, (stage->texture(i), swizzle));
-            deleteTextureAccess[i] = true;
-        } else {
+        if (NULL != access) {
             GrAssert(access->getTexture() == stage->texture(i));
-            deleteTextureAccess[i] = false;
+            textureSamplers[i].init(builder, access);
+        } else {
+            textureSamplers[i].init(builder, stage->texture(i));
         }
-        textureSamplers[i].init(builder, access);
         uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform);
     }
 
@@ -1005,15 +991,12 @@
     glStage->emitVS(builder, varyingVSName);
     builder->fVSCode.appendf("\t}\n");
 
+    builder->computeSwizzle(desc.fInConfigFlags);
+
     // Enclose custom code in a block to avoid namespace conflicts
     builder->fFSCode.appendf("\t{ // %s \n", glStage->name());
     glStage->emitFS(builder, fsOutColor, fsInColor, textureSamplers);
     builder->fFSCode.appendf("\t}\n");
 
-    for (int i = 0; i < numTextures; ++i) {
-        if (deleteTextureAccess[i]) {
-            SkDELETE(textureSamplers[i].textureAccess());
-        }
-    }
     return glStage;
 }
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 0dd1cb1..e32238b 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -105,11 +105,19 @@
                 kNone_InConfigFlag                      = 0x00,
 
                 /**
-                 Smear alpha across all four channels. It is prefereable to perform the smear
-                 outside the shader using GL_ARB_texture_swizzle if possible rather than setting
-                 this flag.
+                 Smear alpha across all four channels. This is incompatible with
+                 kSmearRed. It is prefereable to perform the smear outside the
+                 shader using GL_ARB_texture_swizzle if possible rather than
+                 setting this flag.
                 */
-                kSmearAlpha_InConfigFlag                = 0x01,
+                kSmearAlpha_InConfigFlag                = 0x02,
+
+                /**
+                 Smear the red channel across all four channels. This flag is
+                 incompatible with kSmearAlpha. It is preferable to use
+                 GL_ARB_texture_swizzle instead of this  flag.
+                */
+                kSmearRed_InConfigFlag                  = 0x04,
 
                 kDummyInConfigFlag,
                 kInConfigBitMask = (kDummyInConfigFlag-1) |
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 68f2eb3..b10f4e6 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -83,6 +83,19 @@
     , fTexCoordVaryingType(kVoid_GrSLType) {
 }
 
+void GrGLShaderBuilder::computeSwizzle(uint32_t configFlags) {
+    fSwizzle = "";
+    if (configFlags & GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag) {
+        GrAssert(!(configFlags &
+                   GrGLProgram::StageDesc::kSmearRed_InConfigFlag));
+        fSwizzle = ".aaaa";
+    } else if (configFlags & GrGLProgram::StageDesc::kSmearRed_InConfigFlag) {
+        GrAssert(!(configFlags &
+                   GrGLProgram::StageDesc::kSmearAlpha_InConfigFlag));
+        fSwizzle = ".rrrr";
+    }
+}
+
 void GrGLShaderBuilder::setupTextureAccess(const char* varyingFSName, GrSLType varyingType) {
     // FIXME: We don't know how the custom stage will manipulate the coords. So we give up on using
     // projective texturing and always give the stage 2D coords. This will be fixed when custom
@@ -113,17 +126,14 @@
                                             const GrGLShaderBuilder::TextureSampler& sampler,
                                             const char* coordName,
                                             GrSLType varyingType) const {
-    GrAssert(NULL != sampler.textureAccess());
-    SkString swizzle = build_swizzle_string(*sampler.textureAccess(), fContext.caps());
-
     if (NULL == coordName) {
         coordName = fDefaultTexCoordsName.c_str();
         varyingType = kVec2f_GrSLType;
     }
-    out->appendf("%s(%s, %s)%s;\n",
+    out->appendf("%s(%s, %s)",
                  sample_function_name(varyingType),
                  this->getUniformCStr(sampler.fSamplerUniform),
-                 coordName, swizzle.c_str());
+                 coordName);
 }
 
 void GrGLShaderBuilder::appendTextureLookupAndModulate(
@@ -135,9 +145,22 @@
     GrAssert(NULL != out);
     SkString lookup;
     this->appendTextureLookup(&lookup, sampler, coordName, varyingType);
+    lookup.append(fSwizzle.c_str());
     GrGLSLModulate4f(out, modulation, lookup.c_str());
 }
 
+void GrGLShaderBuilder::emitCustomTextureLookup(const GrGLShaderBuilder::TextureSampler& sampler,
+                                                const char* coordName,
+                                                GrSLType varyingType) {
+    GrAssert(NULL != sampler.textureAccess());
+    SkString swizzle = build_swizzle_string(*sampler.textureAccess(), fContext.caps());
+
+    fFSCode.appendf("%s( %s, %s)%s;\n",
+                    sample_function_name(varyingType),
+                    this->getUniformCStr(sampler.fSamplerUniform),
+                    coordName, swizzle.c_str());
+}
+
 GrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access,
                                                                const GrGLCaps& caps) {
     GrCustomStage::StageKey key = 0;
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index e02d53d..c5ac078 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -29,6 +29,7 @@
     public:
         TextureSampler()
             : fTextureAccess(NULL)
+            , fTexture(NULL)
             , fSamplerUniform(GrGLUniformManager::kInvalidUniformHandle) {}
 
         TextureSampler(const TextureSampler& other) { *this = other; }
@@ -37,6 +38,7 @@
             GrAssert(NULL == fTextureAccess);
             GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
 
+            fTexture = other.fTexture;
             fTextureAccess = other.fTextureAccess;
             fSamplerUniform = other.fSamplerUniform;
             return *this;
@@ -47,6 +49,7 @@
     private:
         void init(GrGLShaderBuilder* builder, const GrTextureAccess* access) {
             GrAssert(NULL == fTextureAccess);
+            GrAssert(NULL == fTexture);
             GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
 
             GrAssert(NULL != builder);
@@ -57,9 +60,27 @@
             GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
 
             fTextureAccess = access;
+            fTexture = access->getTexture();
+        }
+
+        // TODO: Remove once GrTextureAccess is required.
+        void init(GrGLShaderBuilder* builder, const GrTexture* texture) {
+            GrAssert(NULL == fTextureAccess);
+            GrAssert(NULL == fTexture);
+            GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform);
+
+            GrAssert(NULL != builder);
+            GrAssert(NULL != texture);
+            fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
+                                                  kSampler2D_GrSLType,
+                                                  "Sampler");
+            GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform);
+
+            fTexture = texture;
         }
 
         const GrTextureAccess*            fTextureAccess;
+        const GrTexture*                  fTexture; // TODO: remove once tex access cannot be NULL
         GrGLUniformManager::UniformHandle fSamplerUniform;
 
         friend class GrGLShaderBuilder; // to access fSamplerUniform
@@ -76,29 +97,30 @@
 
     GrGLShaderBuilder(const GrGLContextInfo&, GrGLUniformManager&);
 
+    void computeSwizzle(uint32_t configFlags);
+
     /** Determines whether we should use texture2D() or texture2Dproj(), and if an explicit divide
         is required for the sample coordinates, creates the new variable and emits the code to
         initialize it. This should only be called by GrGLProgram.*/
     void setupTextureAccess(const char* varyingFSName, GrSLType varyingType);
 
-    /** Appends a texture sample with projection if necessary; if coordName is not
+    /** appends a texture sample with projection if necessary; if coordName is not
         specified, uses fSampleCoords. coordType must either be Vec2f or Vec3f. The latter is
-        interpreted as projective texture coords. The vec length and swizzle order of the result
-        depends on the GrTextureAccess associated with the TextureSampler. */
+        interpreted as projective texture coords. */
     void appendTextureLookup(SkString* out,
                              const TextureSampler&,
                              const char* coordName = NULL,
                              GrSLType coordType = kVec2f_GrSLType) const;
 
-    /** Does the work of appendTextureLookup and modulates the result by modulation. The result is
-        always a vec4. modulation and the swizzle specified by TextureSampler must both be vec4 or
-        float. If modulation is "" or NULL it this function acts as though appendTextureLookup were
-        called. */
+    /** appends a texture lookup, with swizzle as necessary. If coordName is NULL then it as if
+        defaultTexCoordsName() was passed. coordType must be either kVec2f or kVec3f. If modulateVar
+        is not NULL or "" then the texture lookup will be modulated by it. modulation must refer to
+        be expression that evaluates to a float or vec4. */
     void appendTextureLookupAndModulate(SkString* out,
                                         const char* modulation,
                                         const TextureSampler&,
                                         const char* coordName = NULL,
-                                        GrSLType coordType = kVec2f_GrSLType) const;
+                                        GrSLType varyingType = kVec2f_GrSLType) const;
 
     /** Gets the name of the default texture coords which are always kVec2f */
     const char* defaultTexCoordsName() const { return fDefaultTexCoordsName.c_str(); }
@@ -109,6 +131,16 @@
         return fTexCoordVaryingType == kVec3f_GrSLType;
     }
 
+    /** Emits a texture lookup to the shader code with the form:
+          texture2D{Proj}(samplerName, coordName).swizzle
+        The routine selects the type of texturing based on samplerMode.
+        The generated swizzle state is built based on the format of the texture and the requested
+        swizzle access pattern.  coordType must either be Vec2f or Vec3f. The latter is interpreted
+        as projective texture coords.*/
+    void emitCustomTextureLookup(const TextureSampler&,
+                                 const char* coordName,
+                                 GrSLType coordType = kVec2f_GrSLType);
+
     /** Emits a helper function outside of main(). Currently ShaderType must be
         kFragment_ShaderType. */
     void emitFunction(ShaderType shader,
@@ -202,6 +234,13 @@
     SkString    fFSCode;
     bool        fUsesGS;
 
+    /// Per-stage settings - only valid while we're inside GrGLProgram::genStageCode().
+    //@{
+
+    SkString         fSwizzle;
+
+    //@}
+
 private:
     enum {
         kNonStageIdx = -1,
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index e39b053..7e62f93 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -722,7 +722,13 @@
                     if (GrPixelConfigIsAlphaOnly(texture->config())) {
                         // If we don't have texture swizzle support then the shader must smear the
                         // single channel after reading the texture.
-                        stage.fInConfigFlags |= StageDesc::kSmearAlpha_InConfigFlag;
+                        if (this->glCaps().textureRedSupport()) {
+                            // We can use R8 textures so use kSmearRed.
+                            stage.fInConfigFlags |= StageDesc::kSmearRed_InConfigFlag;
+                        } else {
+                            // We can use A8 textures so use kSmearAlpha.
+                            stage.fInConfigFlags |= StageDesc::kSmearAlpha_InConfigFlag;
+                        }
                     }
                 }
             }
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 54f900c..c99d66a 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -78,6 +78,7 @@
     static const int IN_CONFIG_FLAGS[] = {
         StageDesc::kNone_InConfigFlag,
         StageDesc::kSmearAlpha_InConfigFlag,
+        StageDesc::kSmearRed_InConfigFlag,
     };
 
     static const int NUM_TESTS = 512;