Introduction of set of functions to manage generation of texture fetch shader code.
authortwiz@google.com <twiz@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 2 Aug 2012 15:15:16 +0000 (15:15 +0000)
committertwiz@google.com <twiz@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 2 Aug 2012 15:15:16 +0000 (15:15 +0000)
A new set of routines have been added to GrGLShaderBuilder to emit texture fetches, taking into consideration the format of the texture to be accessed, and the channel swizzle.
Review URL: https://codereview.appspot.com/6446072

git-svn-id: http://skia.googlecode.com/svn/trunk@4919 2bbb7eff-a529-9590-31e7-b0007b416f81

22 files changed:
include/gpu/GrCustomStage.h
include/gpu/GrProgramStageFactory.h
src/effects/SkLightingImageFilter.cpp
src/effects/gradients/SkLinearGradient.cpp
src/effects/gradients/SkRadialGradient.cpp
src/effects/gradients/SkSweepGradient.cpp
src/effects/gradients/SkTwoPointConicalGradient.cpp
src/effects/gradients/SkTwoPointRadialGradient.cpp
src/gpu/GrCustomStage.cpp
src/gpu/effects/GrColorTableEffect.cpp
src/gpu/effects/GrColorTableEffect.h
src/gpu/effects/GrConvolutionEffect.cpp
src/gpu/effects/GrMorphologyEffect.cpp
src/gpu/effects/GrSingleTextureEffect.cpp
src/gpu/effects/GrTextureDomainEffect.cpp
src/gpu/gl/GrGLProgram.h
src/gpu/gl/GrGLProgramStage.cpp
src/gpu/gl/GrGLProgramStage.h
src/gpu/gl/GrGLShaderBuilder.cpp
src/gpu/gl/GrGLShaderBuilder.h
src/gpu/gl/GrGpuGL_program.cpp
src/gpu/gl/GrGpuGL_unittest.cpp

index 9060766..a13ecd4 100644 (file)
 
 class GrContext;
 class GrTexture;
+class SkString;
+
+/** A class representing the swizzle access pattern for a texture.
+ */
+class GrTextureAccess {
+public:
+    typedef char Swizzle[4];
+
+    GrTextureAccess(const GrTexture* texture, const SkString& swizzle);
+
+    const GrTexture* getTexture() const { return fTexture; }
+    const Swizzle& getSwizzle() const { return fSwizzle; }
+
+    bool referencesAlpha() const {
+        return fSwizzle[0] == 'a' || fSwizzle[1] == 'a' || fSwizzle[2] == 'a' || fSwizzle[3] == 'a';
+    }
+
+private:
+    const GrTexture* fTexture;
+    Swizzle fSwizzle;
+};
 
 /** Provides custom vertex shader, fragment shader, uniform data for a
     particular stage of the Ganesh shading pipeline. 
@@ -74,13 +95,17 @@ public:
      */
     virtual bool isEqual(const GrCustomStage&) const;
 
-     /** Human-meaningful string to identify this effect; may be embedded
-         in generated shader code. */
+    /** Human-meaningful string to identify this effect; may be embedded
+        in generated shader code. */
     const char* name() const { return this->getFactory().name(); }
 
     virtual unsigned int numTextures() const;
     virtual GrTexture* texture(unsigned int index) const;
 
+    /** Returns the access pattern for the texture at index.  Returns NULL if index is
+        unused. */
+    virtual const GrTextureAccess* textureAccess(unsigned int index) const;
+
     void* operator new(size_t size);
     void operator delete(void* target);
 
index f2b4f5f..90f6b32 100644 (file)
 
 class GrCustomStage;
 class GrGLProgramStage;
+class GrGLCaps;
 
 class GrProgramStageFactory : public GrNoncopyable {
 public:
-    typedef uint16_t StageKey;
+    typedef uint32_t StageKey;
     enum {
         kProgramStageKeyBits = 10,
+        kTexturingStageKeyBits = 6
     };
 
-    virtual StageKey glStageKey(const GrCustomStage& stage) const = 0;
+    virtual StageKey glStageKey(const GrCustomStage& stage,
+                                const GrGLCaps& caps ) const = 0;
     virtual GrGLProgramStage* createGLInstance(
         const GrCustomStage& stage) const = 0;
 
@@ -68,7 +71,7 @@ template <typename StageClass>
 class GrTProgramStageFactory : public GrProgramStageFactory {
 
 public:
-    typedef typename StageClass::GLProgramStage GLProgramStage; 
+    typedef typename StageClass::GLProgramStage GLProgramStage;
 
     /** Returns a human-readable name that is accessible via GrCustomStage or
         GrGLProgramStage and is consistent between the two of them.
@@ -80,20 +83,26 @@ public:
         id identifies the GrCustomShader subclass. The remainder is based
         on the aspects of the GrCustomStage object's configuration that affect
         GLSL code generation. */
-    virtual StageKey glStageKey(const GrCustomStage& stage) const SK_OVERRIDE {
+    virtual StageKey glStageKey(const GrCustomStage& stage,
+                                const GrGLCaps& caps) const SK_OVERRIDE {
         GrAssert(kIllegalStageClassID != fStageClassID);
-        StageKey stageID = GLProgramStage::GenKey(stage);
+        StageKey stageID = GLProgramStage::GenKey(stage, caps);
+        StageKey textureKey = GLProgramStage::GenTextureKey(stage, caps);
 #if GR_DEBUG
         static const StageKey kIllegalIDMask =
             (uint16_t) (~((1U << kProgramStageKeyBits) - 1));
         GrAssert(!(kIllegalIDMask & stageID));
+
+        static const StageKey kIllegalTextureKeyMask =
+            (uint16_t) (~((1U << kTexturingStageKeyBits) - 1));
+        GrAssert(!(kIllegalTextureKeyMask & textureKey));
 #endif
-        return fStageClassID | stageID;
+        return fStageClassID | (textureKey << kProgramStageKeyBits) | stageID;
     }
 
     /** Returns a new instance of the appropriate *GL* implementation class
-     for the given GrCustomStage; caller is responsible for deleting
-     the object. */
+        for the given GrCustomStage; caller is responsible for deleting
+        the object. */
     virtual GLProgramStage* createGLInstance(
                         const GrCustomStage& stage) const SK_OVERRIDE {
         return SkNEW_ARGS(GLProgramStage, (*this, stage));
@@ -113,7 +122,7 @@ public:
 
 protected:
     GrTProgramStageFactory() {
-        fStageClassID = GenID() << kProgramStageKeyBits;
+        fStageClassID = GenID() << (kProgramStageKeyBits + kTexturingStageKeyBits) ;
     }
 };
 
index 98c294c..b6532aa 100644 (file)
@@ -918,7 +918,7 @@ public:
 
     virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) = 0;
 
-    static inline StageKey GenKey(const GrCustomStage& s);
+    static inline StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
 
     virtual void setData(const GrGLUniformManager&,
                          const GrCustomStage&,
@@ -1086,8 +1086,8 @@ vec3 interiorNormal(float m[9], float surfaceScale) {\n\
     code->appendf(")%s;\n", builder->fModulate.c_str());
 }
 
-GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(
-  const GrCustomStage& s) {
+GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(const GrCustomStage& s,
+                                                      const GrGLCaps& caps) {
     return static_cast<const GrLightingEffect&>(s).light()->type();
 }
 
index cd44d3f..d88540e 100644 (file)
@@ -491,7 +491,7 @@ public:
                         const char* outputColor,
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
-    static StageKey GenKey(const GrCustomStage& s) { return 0; }
+    static StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps) { return 0; }
 
 private:
 
index 32083dc..f3978a5 100644 (file)
@@ -487,7 +487,7 @@ public:
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
 
-    static StageKey GenKey(const GrCustomStage& s) { return 0; }
+    static StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps) { return 0; }
 
 private:
 
index 1daaa7d..0dee9b5 100644 (file)
@@ -396,7 +396,7 @@ public:
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
 
-    static StageKey GenKey(const GrCustomStage& s) { return 0; }
+    static StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps) { return 0; }
 
 private:
 
index 9fe180a..8902573 100644 (file)
@@ -340,7 +340,7 @@ public:
                          const GrRenderTarget*,
                          int stageNum) SK_OVERRIDE;
 
-    static StageKey GenKey(const GrCustomStage& s);
+    static StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
 
 protected:
 
@@ -636,7 +636,7 @@ void GrGLConical2Gradient::setData(const GrGLUniformManager& uman,
     }
 }
 
-GrCustomStage::StageKey GrGLConical2Gradient::GenKey(const GrCustomStage& s) {
+GrCustomStage::StageKey GrGLConical2Gradient::GenKey(const GrCustomStage& s, const GrGLCaps& caps) {
     return (static_cast<const GrConical2Gradient&>(s).isDegenerate());
 }
 
@@ -669,4 +669,4 @@ GrCustomStage* SkTwoPointConicalGradient::asNewCustomStage(
     return NULL;
 }
 
-#endif
\ No newline at end of file
+#endif
index 06e27fe..84ae91d 100644 (file)
@@ -373,7 +373,7 @@ public:
                          const GrRenderTarget*,
                          int stageNum) SK_OVERRIDE;
 
-    static StageKey GenKey(const GrCustomStage& s);
+    static StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
 
 protected:
 
@@ -608,7 +608,7 @@ void GrGLRadial2Gradient::setData(const GrGLUniformManager& uman,
     }
 }
 
-GrCustomStage::StageKey GrGLRadial2Gradient::GenKey(const GrCustomStage& s) {
+GrCustomStage::StageKey GrGLRadial2Gradient::GenKey(const GrCustomStage& s, const GrGLCaps& caps) {
     return (static_cast<const GrRadial2Gradient&>(s).isDegenerate());
 }
 
index 43de5ae..bea07cf 100644 (file)
@@ -8,6 +8,7 @@
 #include "GrContext.h"
 #include "GrCustomStage.h"
 #include "GrMemoryPool.h"
+#include "SkString.h"
 #include "SkTLS.h"
 
 SK_DEFINE_INST_COUNT(GrCustomStage)
@@ -31,6 +32,17 @@ private:
 int32_t GrProgramStageFactory::fCurrStageClassID =
                                     GrProgramStageFactory::kIllegalStageClassID;
 
+GrTextureAccess::GrTextureAccess(const GrTexture* texture, const SkString& swizzle)
+    : fTexture(texture) {
+    GrAssert(swizzle.size() <= 4);
+    for (unsigned int offset = 0; offset < swizzle.size(); ++offset) {
+        fSwizzle[offset] = swizzle[offset];
+    }
+    if (swizzle.size() < 4) {
+      fSwizzle[swizzle.size()] = 0;
+    }
+}
+
 GrCustomStage::GrCustomStage() {
 
 }
@@ -63,6 +75,10 @@ GrTexture* GrCustomStage::texture(unsigned int index) const {
     return NULL;
 }
 
+const GrTextureAccess* GrCustomStage::textureAccess(unsigned int index) const {
+    return NULL;
+}
+
 void * GrCustomStage::operator new(size_t size) {
     return GrCustomStage_Globals::GetTLS()->allocate(size);
 }
@@ -70,4 +86,3 @@ void * GrCustomStage::operator new(size_t size) {
 void GrCustomStage::operator delete(void* target) {
     GrCustomStage_Globals::GetTLS()->release(target);
 }
-
index 2075c22..f1ce664 100644 (file)
@@ -30,49 +30,72 @@ public:
                          const GrRenderTarget*,
                          int stageNum) SK_OVERRIDE {}
 
-    static inline StageKey GenKey(const GrCustomStage&);
+    static StageKey GenKey(const GrCustomStage&, const GrGLCaps&);
 
 private:
+
+    const GrCustomStage& fCustomStage;
+
     typedef GrGLProgramStage INHERITED;
 };
 
 GrGLColorTableEffect::GrGLColorTableEffect(
     const GrProgramStageFactory& factory, const GrCustomStage& stage)
-    : INHERITED(factory) {
+    : INHERITED(factory)
+    , fCustomStage(stage) {
  }
 
-void GrGLColorTableEffect::emitFS(GrGLShaderBuilder* state,
+void GrGLColorTableEffect::emitFS(GrGLShaderBuilder* builder,
                                   const char* outputColor,
                                   const char* inputColor,
                                   const char* samplerName) {
     static const float kColorScaleFactor = 255.0f / 256.0f;
     static const float kColorOffsetFactor = 1.0f / 512.0f;
-    SkString* code = &state->fFSCode; 
+    SkString* code = &builder->fFSCode;
     code->appendf("\t\tvec4 coord = vec4(%s.rgb / %s.a, %s.a);\n",
                   inputColor, inputColor, inputColor);
     code->appendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n",
                   kColorScaleFactor,
                   kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor);
-    code->appendf("\t\t%s.a = texture2D(%s, vec2(coord.a, 0.125)).a;\n",
-                  outputColor, samplerName);
-    code->appendf("\t\t%s.r = texture2D(%s, vec2(coord.r, 0.375)).a;\n",
-                  outputColor, samplerName);
-    code->appendf("\t\t%s.g = texture2D(%s, vec2(coord.g, 0.625)).a;\n",
-                  outputColor, samplerName);
-    code->appendf("\t\t%s.b = texture2D(%s, vec2(coord.b, 0.875)).a;\n",
-                  outputColor, samplerName);
+
+    const GrTextureAccess& access = *fCustomStage.textureAccess(0);
+    code->appendf("\t\t%s.a = ", outputColor);
+    builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+                                     access,
+                                     samplerName,
+                                     "vec2(coord.a, 0.125)");
+
+    code->appendf("\t\t%s.r = ", outputColor);
+    builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+                                     access,
+                                     samplerName,
+                                     "vec2(coord.r, 0.375)");
+
+    code->appendf("\t\t%s.g = ", outputColor);
+    builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+                                     access,
+                                     samplerName,
+                                     "vec2(coord.g, 0.625)");
+
+    code->appendf("\t\t%s.b = ", outputColor);
+    builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+                                     access,
+                                     samplerName,
+                                     "vec2(coord.b, 0.875)");
+
     code->appendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
 }
 
-GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey(
-    const GrCustomStage& s) {
+GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey(const GrCustomStage& s,
+                                                        const GrGLCaps& caps) {
     return 0;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
 
 GrColorTableEffect::GrColorTableEffect(GrTexture* texture)
-    : INHERITED(texture) {
+    : INHERITED(texture)
+    , fTextureAccess(texture, SkString("a")) {
 }
 
 GrColorTableEffect::~GrColorTableEffect() {
@@ -85,3 +108,10 @@ const GrProgramStageFactory&  GrColorTableEffect::getFactory() const {
 bool GrColorTableEffect::isEqual(const GrCustomStage& sBase) const {
     return INHERITED::isEqual(sBase);
 }
+
+const GrTextureAccess* GrColorTableEffect::textureAccess(unsigned int index) const {
+    if (0 == index)
+        return &fTextureAccess;
+
+    return NULL;
+}
index ee7a630..16d76ad 100644 (file)
@@ -29,10 +29,14 @@ public:
     virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
     virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
 
+    virtual const GrTextureAccess* textureAccess(unsigned int index) const SK_OVERRIDE;
+
     typedef GrGLColorTableEffect GLProgramStage;
 
 private:
 
+    GrTextureAccess fTextureAccess;
+
     typedef GrSingleTextureEffect INHERITED;
 };
 #endif
index 6af891b..5cce800 100644 (file)
@@ -33,7 +33,7 @@ public:
                          const GrRenderTarget*,
                          int stageNum) SK_OVERRIDE;
 
-    static inline StageKey GenKey(const GrCustomStage&);
+    static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&);
 
 private:
     int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
@@ -125,8 +125,8 @@ void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
     uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
 }
 
-GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey(
-                                                    const GrCustomStage& s) {
+GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey(const GrCustomStage& s,
+                                                         const GrGLCaps& caps) {
     return static_cast<const GrConvolutionEffect&>(s).radius();
 }
 
@@ -185,4 +185,3 @@ bool GrConvolutionEffect::isEqual(const GrCustomStage& sBase) const {
             this->direction() == s.direction() &&
             0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
 }
-
index f8b268d..be8485e 100644 (file)
@@ -26,7 +26,7 @@ public:
                         const char* inputColor,
                         const char* samplerName) SK_OVERRIDE;
 
-    static inline StageKey GenKey(const GrCustomStage& s);
+    static inline StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
 
     virtual void setData(const GrGLUniformManager&,
                          const GrCustomStage&,
@@ -98,8 +98,8 @@ void GrGLMorphologyEffect ::emitFS(GrGLShaderBuilder* builder,
     code->appendf("\t\t%s = value%s;\n", outputColor, builder->fModulate.c_str());
 }
 
-GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey(
-                                                    const GrCustomStage& s) {
+GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey(const GrCustomStage& s,
+                                                        const GrGLCaps& caps) {
     const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(s);
     StageKey key = static_cast<StageKey>(m.radius());
     key |= (m.type() << 8);
index 350d9e6..5f66e09 100644 (file)
@@ -26,7 +26,7 @@ public:
         builder->emitDefaultFetch(outputColor, samplerName);
     }
 
-    static inline StageKey GenKey(const GrCustomStage&) { return 0; }
+    static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&) { return 0; }
 
 private:
 
@@ -56,5 +56,3 @@ GrTexture* GrSingleTextureEffect::texture(unsigned int index) const {
 const GrProgramStageFactory& GrSingleTextureEffect::getFactory() const {
     return GrTProgramStageFactory<GrSingleTextureEffect>::getInstance();
 }
-
-
index 1bf0512..e76d0c9 100644 (file)
@@ -27,7 +27,7 @@ public:
                          const GrRenderTarget*,
                          int stageNum) SK_OVERRIDE;
 
-    static inline StageKey GenKey(const GrCustomStage&) { return 0; }
+    static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&) { return 0; }
 
 private:
     GrGLUniformManager::UniformHandle fNameUni;
@@ -107,5 +107,3 @@ bool GrTextureDomainEffect::isEqual(const GrCustomStage& sBase) const {
     const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase);
     return (INHERITED::isEqual(sBase) && this->fTextureDomain == s.fTextureDomain);
 }
-
-
index 18d97d5..62c70e5 100644 (file)
@@ -164,7 +164,7 @@ public:
 
             /** Non-zero if user-supplied code will write the stage's
                 contribution to the fragment shader. */
-            uint16_t fCustomStageKey;
+            GrProgramStageFactory::StageKey fCustomStageKey;
 
             GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask ==
                              kInConfigBitMask);
index 12c3894..b1a37fe 100644 (file)
@@ -27,3 +27,14 @@ void GrGLProgramStage::setData(const GrGLUniformManager&,
                                int stageNum) {
 }
 
+GrGLProgramStage::StageKey GrGLProgramStage::GenTextureKey(const GrCustomStage& stage,
+                                                           const GrGLCaps& caps) {
+    StageKey key = 0;
+    for (unsigned int index = 0; index < stage.numTextures(); ++index) {
+        if (stage.textureAccess(index)) {
+            key = (key << index) |
+                GrGLShaderBuilder::KeyForTextureAccess(*stage.textureAccess(index), caps);
+        }
+    }
+    return key;
+}
index 12163f8..8e3a4b1 100644 (file)
@@ -78,6 +78,8 @@ public:
 
     const char* name() const { return fFactory.name(); }
 
+    static StageKey GenTextureKey(const GrCustomStage&, const GrGLCaps&);
+
 protected:
 
     const GrProgramStageFactory& fFactory;
index 2844953..0d2a1ec 100644 (file)
@@ -8,6 +8,7 @@
 #include "gl/GrGLShaderBuilder.h"
 #include "gl/GrGLProgram.h"
 #include "gl/GrGLUniformHandle.h"
+#include "GrTexture.h"
 
 // number of each input/output type in a single allocation block
 static const int kVarsPerBlock = 8;
@@ -21,6 +22,50 @@ static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
 typedef GrGLUniformManager::UniformHandle UniformHandle;
 ///////////////////////////////////////////////////////////////////////////////
 
+static SkString build_sampler_string(GrGLShaderBuilder::SamplerMode samplerMode) {
+    SkString sampler("texture2D");
+    switch (samplerMode) {
+      case GrGLShaderBuilder::kDefault_SamplerMode:
+          break;
+      case GrGLShaderBuilder::kProj_SamplerMode:
+          sampler.append("Proj");
+          break;
+      case GrGLShaderBuilder::kExplicitDivide_SamplerMode:
+          GrAssert(false);  // Not Implemented
+          break;
+    }
+
+    return sampler;
+}
+
+static bool texture_requires_alpha_to_red_swizzle(const GrGLCaps& caps,
+                                                  const GrTextureAccess& access) {
+    return GrPixelConfigIsAlphaOnly(access.getTexture()->config()) && caps.textureRedSupport() &&
+        access.referencesAlpha();
+}
+
+static SkString build_swizzle_string(const GrTextureAccess& textureAccess,
+                                     const GrGLCaps& caps) {
+    const GrTextureAccess::Swizzle& swizzle = textureAccess.getSwizzle();
+    if (0 == swizzle[0]) {
+        return SkString("");
+    }
+
+    SkString swizzleOut(".");
+    bool alphaIsRed = texture_requires_alpha_to_red_swizzle(caps, textureAccess);
+    for (int offset = 0; offset < 4 && swizzle[offset]; ++offset) {
+        if (alphaIsRed && 'a' == swizzle[offset]) {
+            swizzleOut.appendf("r");
+        } else {
+            swizzleOut.appendf("%c", swizzle[offset]);
+        }
+    }
+
+    return swizzleOut;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
 // Architectural assumption: always 2-d input coords.
 // Likely to become non-constant and non-static, perhaps even
 // varying by stage, if we use 1D textures for gradients!
@@ -120,6 +165,34 @@ void GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
     fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
 }
 
+void GrGLShaderBuilder::emitCustomTextureLookup(SamplerMode samplerMode,
+                                                const GrTextureAccess& textureAccess,
+                                                const char* samplerName,
+                                                const char* coordName) {
+    GrAssert(samplerName && coordName);
+    SkString sampler = build_sampler_string(samplerMode);
+    SkString swizzle = build_swizzle_string(textureAccess, fContext.caps());
+
+    fFSCode.appendf("%s( %s, %s)%s;\n", sampler.c_str(), samplerName,
+                    coordName, swizzle.c_str());
+}
+
+GrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access,
+                                                               const GrGLCaps& caps) {
+    GrCustomStage::StageKey key = 0;
+    // Assume that swizzle support implies that we never have to modify a shader to adjust
+    // for texture format/swizzle settings.
+    if (caps.textureSwizzleSupport()) {
+        return key;
+    }
+
+    if (texture_requires_alpha_to_red_swizzle(caps, access)) {
+        key = 1;
+    }
+
+    return key;
+}
+
 GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
                                                                      GrSLType type,
                                                                      const char* name,
index f110628..16a11e2 100644 (file)
@@ -9,6 +9,7 @@
 #define GrGLShaderBuilder_DEFINED
 
 #include "GrAllocator.h"
+#include "GrCustomStage.h"
 #include "gl/GrGLShaderVar.h"
 #include "gl/GrGLSL.h"
 #include "gl/GrGLUniformManager.h"
@@ -55,6 +56,22 @@ public:
     void emitDefaultFetch(const char* outColor,
                           const char* samplerName);
 
+    /** 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. */
+    void emitCustomTextureLookup(SamplerMode samplerMode,
+                                 const GrTextureAccess& textureAccess,
+                                 const char* samplerName,
+                                 const char* coordName);
+
+    /** Generates a StageKey for the shader code based on the texture access parameters and the
+        capabilities of the GL context.  This is useful for keying the shader programs that may
+        have multiple representations, based on the type/format of textures used. */
+    static GrCustomStage::StageKey KeyForTextureAccess(const GrTextureAccess& access,
+                                                       const GrGLCaps& caps);
+
     /** Add a uniform variable to the current program, that has visibilty in one or more shaders.
         visibility is a bitfield of ShaderType values indicating from which shaders the uniform
         should be accessible. At least one bit must be set. Geometry shader uniforms are not
index 6d6d916..c959f66 100644 (file)
@@ -596,12 +596,13 @@ namespace {
 
 void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage,
                         const GrSamplerState& sampler,
+                        const GrGLCaps& caps,
                         const GrCustomStage** customStages,
                         GrGLProgram* program, int index) {
     const GrCustomStage* customStage = sampler.getCustomStage();
     if (customStage) {
         const GrProgramStageFactory& factory = customStage->getFactory();
-        stage->fCustomStageKey = factory.glStageKey(*customStage);
+        stage->fCustomStageKey = factory.glStageKey(*customStage, caps);
         customStages[index] = customStage;
     } else {
         stage->fCustomStageKey = 0;
@@ -746,7 +747,8 @@ void GrGpuGL::buildProgram(bool isPoints,
                 }
             }
 
-            setup_custom_stage(&stage, sampler, customStages, fCurrentProgram.get(), s);
+            setup_custom_stage(&stage, sampler, this->glCaps(), customStages,
+                               fCurrentProgram.get(), s);
 
         } else {
             stage.fOptFlags         = 0;
index 1a28b98..7fd61d9 100644 (file)
@@ -413,7 +413,7 @@ bool GrGpuGL::programUnitTest() {
                 customStages[s].reset(create_random_effect(&stage, &random, getContext()));
                 if (NULL != customStages[s]) {
                     stage.fCustomStageKey =
-                        customStages[s]->getFactory().glStageKey(*customStages[s]);
+                        customStages[s]->getFactory().glStageKey(*customStages[s], this->glCaps());
                 }
             }
         }