Wrap all GrCustomStage textures in GrTextureAccess, remove StageDesc::fInConfigFlags
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 11 Sep 2012 15:45:20 +0000 (15:45 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 11 Sep 2012 15:45:20 +0000 (15:45 +0000)
Review URL: https://codereview.appspot.com/6494114

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

18 files changed:
include/gpu/GrCustomStage.h
include/gpu/GrTextureAccess.h
src/effects/gradients/SkGradientShader.cpp
src/effects/gradients/SkGradientShaderPriv.h
src/gpu/GrCustomStage.cpp
src/gpu/GrTextureAccess.cpp
src/gpu/effects/GrColorTableEffect.cpp
src/gpu/effects/GrColorTableEffect.h
src/gpu/effects/GrSingleTextureEffect.cpp
src/gpu/effects/GrSingleTextureEffect.h
src/gpu/gl/GrGLProgram.cpp
src/gpu/gl/GrGLProgram.h
src/gpu/gl/GrGLProgramStage.cpp
src/gpu/gl/GrGLShaderBuilder.cpp
src/gpu/gl/GrGLShaderBuilder.h
src/gpu/gl/GrGpuGL.cpp
src/gpu/gl/GrGpuGL_program.cpp
tests/GLProgramsTest.cpp

index 32d40b47d716d02b8e7da802fe34f6bddeacc6e4..9765a42f2bbf91eaf47d856253715130edd7dd83 100644 (file)
@@ -81,12 +81,14 @@ public:
         in generated shader code. */
     const char* name() const { return this->getFactory().name(); }
 
-    virtual unsigned int numTextures() const;
-    virtual GrTexture* texture(unsigned int index) const;
+    virtual int numTextures() const;
 
-    /** Returns the access pattern for the texture at index.  Returns NULL if index is
-        unused. */
-    virtual const GrTextureAccess* textureAccess(unsigned int index) const;
+    /** Returns the access pattern for the texture at index. index must be valid according to
+        numTextures(). */
+    virtual const GrTextureAccess& textureAccess(int index) const;
+
+    /** Shortcut for textureAccess(index).texture(); */
+    GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); }
 
     void* operator new(size_t size);
     void operator delete(void* target);
index 55c0a02b874b004c9867fdea3cd68941f2110647..e4e373294afa8b3c70f79bbd85e14570150c2def 100644 (file)
@@ -8,29 +8,62 @@
 #ifndef GrTextureAccess_DEFINED
 #define GrTextureAccess_DEFINED
 
-#include "GrTypes.h"
+#include "GrNoncopyable.h"
+#include "SkRefCnt.h"
 
 class GrTexture;
-class SkString;
 
-/** A class representing the swizzle access pattern for a texture.
+/** A class representing the swizzle access pattern for a texture. Note that if the texture is
+ *  an alpha-only texture then the alpha channel is substituted for other components. Any mangling
+ *  to handle the r,g,b->a conversions for alpha textures is automatically included in the stage
+ *  key. However, if a GrCustomStage uses different swizzles based on its input then it must
+ *  consider that variation in its key-generation.
  */
-class GrTextureAccess {
+class GrTextureAccess : GrNoncopyable {
 public:
-    typedef char Swizzle[4];
+    /**
+     * A default GrTextureAccess must have reset() called on it in a GrCustomStage subclass's
+     * constructor if it will be accessible via GrCustomStage::textureAccess().
+     */
+    GrTextureAccess();
 
-    GrTextureAccess(const GrTexture* texture, const SkString& swizzle);
+    /**
+     * swizzle must be a string between one and four (inclusive) characters containing only 'r',
+     * 'g', 'b',  and/or 'a'.
+     */
+    GrTextureAccess(GrTexture*, const char* swizzle);
 
-    const GrTexture* getTexture() const { return fTexture; }
-    const Swizzle& getSwizzle() const { return fSwizzle; }
+    /**
+     * Uses the default swizzle, "rgba".
+     */
+    GrTextureAccess(GrTexture*);
 
-    bool referencesAlpha() const {
-        return fSwizzle[0] == 'a' || fSwizzle[1] == 'a' || fSwizzle[2] == 'a' || fSwizzle[3] == 'a';
-    }
+    void reset(GrTexture*, const char* swizzle);
+    void reset(GrTexture*);
+
+    GrTexture* getTexture() const { return fTexture.get(); }
+
+    /**
+     * Returns a string representing the swizzle. The string is is null-terminated.
+     */
+    const char* getSwizzle() const { return fSwizzle; }
+
+    enum {
+        kR_SwizzleFlag = 0x1,
+        kG_SwizzleFlag = 0x2,
+        kB_SwizzleFlag = 0x4,
+        kA_SwizzleFlag = 0x8,
+
+        kRGB_SwizzleMask = (kR_SwizzleFlag |  kG_SwizzleFlag | kB_SwizzleFlag),
+    };
+
+    /** Returns a mask indicating which components are referenced in the swizzle. */
+    uint32_t swizzleMask() const { return fSwizzleMask; }
 
 private:
-    const GrTexture* fTexture;
-    Swizzle fSwizzle;
+    SkAutoTUnref<GrTexture> fTexture;
+    uint32_t                fSwizzleMask;
+    char                    fSwizzle[5];
 };
 
 #endif
index d7b4f13e2c718b71b54dec63301a464dff84eab7..f0dac4d18108ea77ec591cdc8740f67fd94c990e 100644 (file)
@@ -719,8 +719,7 @@ void GrGLGradientStage::emitColorLookup(GrGLShaderBuilder* builder,
 GrGradientEffect::GrGradientEffect(GrContext* ctx,
                                    const SkGradientShaderBase& shader,
                                    GrSamplerState* sampler)
-    : fTexture (NULL)
-    , fUseTexture (true) {
+    : fUseTexture (true) {
     // TODO: check for simple cases where we don't need a texture:
     //GradientInfo info;
     //shader.asAGradient(&info);
@@ -742,35 +741,32 @@ GrGradientEffect::GrGradientEffect(GrContext* ctx,
     if (-1 != fRow) {
         fYCoord = fAtlas->getYOffset(fRow) + GR_ScalarHalf *
                   fAtlas->getVerticalScaleFactor();
-        fTexture = fAtlas->getTexture();
+        fTextureAccess.reset(fAtlas->getTexture());
     } else {
-        fTexture = GrLockCachedBitmapTexture(ctx, bitmap, sampler->textureParams());
-        SkSafeRef(fTexture);
+        GrTexture* texture = GrLockCachedBitmapTexture(ctx, bitmap, sampler->textureParams());
+        fTextureAccess.reset(texture);
         fYCoord = GR_ScalarHalf;
 
         // Unlock immediately, this is not great, but we don't have a way of
         // knowing when else to unlock it currently, so it may get purged from
         // the cache, but it'll still be ref'd until it's no longer being used.
-        GrUnlockCachedBitmapTexture(fTexture);
+        GrUnlockCachedBitmapTexture(texture);
     }
 }
 
 GrGradientEffect::~GrGradientEffect() {
     if (this->useAtlas()) {
         fAtlas->unlockRow(fRow);
-    } else {
-        SkSafeUnref(fTexture);
     }
 }
 
-unsigned int GrGradientEffect::numTextures() const {
+int GrGradientEffect::numTextures() const {
     return fUseTexture ? 1 : 0;
 }
 
-GrTexture* GrGradientEffect::texture(unsigned int index)
-                             const {
+const GrTextureAccess& GrGradientEffect::textureAccess(int index) const {
     GrAssert(fUseTexture && 0 == index);
-    return fTexture;
+    return fTextureAccess;
 }
 
 int GrGradientEffect::RandomGradientParams(SkRandom* random,
index 8c8632681f383abe3993a6b9ca2b21fc7a378b18..0e7c2fc2794adc3f610b8472fb5a71cd49f3df07 100644 (file)
@@ -231,14 +231,14 @@ public:
 
     virtual ~GrGradientEffect();
 
-    unsigned int numTextures() const;
-    GrTexture* texture(unsigned int index) const;
+    virtual int numTextures() const SK_OVERRIDE;
+    virtual const GrTextureAccess& textureAccess(int index) const SK_OVERRIDE;
 
     bool useTexture() const { return fUseTexture; }
     bool useAtlas() const { return SkToBool(-1 != fRow); }
     GrScalar getYCoord() const { GrAssert(fUseTexture); return fYCoord; };
 
-    bool isEqual(const GrCustomStage& stage) const {
+    virtual bool isEqual(const GrCustomStage& stage) const SK_OVERRIDE {
         const GrGradientEffect& s = static_cast<const GrGradientEffect&>(stage);
         return INHERITED::isEqual(stage) && this->useAtlas() == s.useAtlas() &&
                fYCoord == s.getYCoord();
@@ -260,7 +260,7 @@ protected:
                                     SkShader::TileMode* tm);
 
 private:
-    GrTexture* fTexture;
+    GrTextureAccess fTextureAccess;
     bool fUseTexture;
     GrScalar fYCoord;
     GrTextureStripAtlas* fAtlas;
index 7b3bc617e03e26e289753ceeab75eaf9e59300a9..3f79af828bc7e8da9d10dfbb1f8967506491896a 100644 (file)
@@ -54,7 +54,7 @@ bool GrCustomStage::isEqual(const GrCustomStage& s) const {
     if (this->numTextures() != s.numTextures()) {
         return false;
     }
-    for (unsigned int i = 0; i < this->numTextures(); ++i) {
+    for (int i = 0; i < this->numTextures(); ++i) {
         if (this->texture(i) != s.texture(i)) {
             return false;
         }
@@ -62,16 +62,14 @@ bool GrCustomStage::isEqual(const GrCustomStage& s) const {
     return true;
 }
 
-unsigned int GrCustomStage::numTextures() const {
+int GrCustomStage::numTextures() const {
     return 0;
 }
 
-GrTexture* GrCustomStage::texture(unsigned int index) const {
-    return NULL;
-}
-
-const GrTextureAccess* GrCustomStage::textureAccess(unsigned int index) const {
-    return NULL;
+const GrTextureAccess& GrCustomStage::textureAccess(int index) const {
+    GrCrash("We shouldn't be calling this function on the base class.");
+    static GrTextureAccess kDummy;
+    return kDummy;
 }
 
 void * GrCustomStage::operator new(size_t size) {
index 155f6828278ec6e631724cad1069f7cb56511352..c3c80380603e43bd45759685ec02b70912752b09 100644 (file)
@@ -6,16 +6,62 @@
  */
 
 #include "GrTextureAccess.h"
-#include "SkString.h"
-
-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;
-    }
+
+#include "GrTexture.h"
+
+GrTextureAccess::GrTextureAccess() {
+#if GR_DEBUG
+    memcpy(fSwizzle, "void", 5);
+    fSwizzleMask = 0xbeeffeed;
+#endif
+}
+
+GrTextureAccess::GrTextureAccess(GrTexture* texture, const char* swizzle) {
+    this->reset(texture, swizzle);
+}
+
+GrTextureAccess::GrTextureAccess(GrTexture* texture) {
+    this->reset(texture);
 }
 
+void GrTextureAccess::reset(GrTexture* texture, const char* swizzle) {
+    GrAssert(NULL != texture);
+    GrAssert(strlen(swizzle) >= 1 && strlen(swizzle) <= 4);
+
+    texture->ref();
+    fTexture.reset(texture);
+
+    fSwizzleMask = 0;
+    fSwizzle[4] = '\0';
+    int i = 0;
+    do {
+        fSwizzle[i] = swizzle[i];
+        switch (swizzle[i]) {
+            case 'r':
+                fSwizzleMask |= kR_SwizzleFlag;
+                break;
+            case 'g':
+                fSwizzleMask |= kG_SwizzleFlag;
+                break;
+            case 'b':
+                fSwizzleMask |= kB_SwizzleFlag;
+                break;
+            case 'a':
+                fSwizzleMask |= kA_SwizzleFlag;
+                break;
+            case '\0':
+                break;
+            default:
+                GrCrash("Unexpected swizzle string character.");
+                break;
+        }
+    } while ('\0' != swizzle[i] && ++i < 4);
+}
+
+void GrTextureAccess::reset(GrTexture* texture) {
+    GrAssert(NULL != texture);
+    texture->ref();
+    fTexture.reset(texture);
+    memcpy(fSwizzle, "rgba", 5);
+    fSwizzleMask = (kRGB_SwizzleMask | kA_SwizzleFlag);
+}
index d662398d4a446d8e947c9e591fab13fd9aaa040f..0edc00de95a0a62115f0be2d6f938643e8151a9a 100644 (file)
@@ -91,8 +91,7 @@ GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey(const GrCustomStage& s,
 ///////////////////////////////////////////////////////////////////////////////
 
 GrColorTableEffect::GrColorTableEffect(GrTexture* texture)
-    : INHERITED(texture)
-    , fTextureAccess(texture, SkString("a")) {
+    : fTextureAccess(texture, "a") {
 }
 
 GrColorTableEffect::~GrColorTableEffect() {
@@ -106,11 +105,9 @@ 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;
+const GrTextureAccess& GrColorTableEffect::textureAccess(int index) const {
+    GrAssert(0 == index);
+    return fTextureAccess;
 }
 
 ///////////////////////////////////////////////////////////////////////////////
index f79e586579c415f65c81f7346247b043ed442022..fe762fdbec31c23cb22d8400854011067d6abe48 100644 (file)
@@ -18,8 +18,7 @@ class GrGLColorTableEffect;
  * counterpart to the SkTable_ColorFilter effect. A 256 * 4 (single-channel)
  * LUT is used to transform the input colors of the image.
  */
-class GrColorTableEffect : public GrSingleTextureEffect {
-
+class GrColorTableEffect : public GrCustomStage {
 public:
 
     GrColorTableEffect(GrTexture* texture);
@@ -29,7 +28,8 @@ 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;
+    virtual int numTextures() const SK_OVERRIDE { return 1; }
+    virtual const GrTextureAccess& textureAccess(int index) const SK_OVERRIDE;
 
     typedef GrGLColorTableEffect GLProgramStage;
 
@@ -38,6 +38,6 @@ private:
 
     GrTextureAccess fTextureAccess;
 
-    typedef GrSingleTextureEffect INHERITED;
+    typedef GrCustomStage INHERITED;
 };
 #endif
index b2fe0cc15e74a77713e9b8e660551957ae312591..b2e920538c9676cff476cd8ce1b860f42833c578 100644 (file)
@@ -38,21 +38,19 @@ private:
 ///////////////////////////////////////////////////////////////////////////////
 
 GrSingleTextureEffect::GrSingleTextureEffect(GrTexture* texture)
-    : fTexture (texture) {
-    SkSafeRef(fTexture);
+    : fTextureAccess(texture) {
 }
 
 GrSingleTextureEffect::~GrSingleTextureEffect() {
-    SkSafeUnref(fTexture);
 }
 
-unsigned int GrSingleTextureEffect::numTextures() const {
+int GrSingleTextureEffect::numTextures() const {
     return 1;
 }
 
-GrTexture* GrSingleTextureEffect::texture(unsigned int index) const {
+const GrTextureAccess& GrSingleTextureEffect::textureAccess(int index) const {
     GrAssert(0 == index);
-    return fTexture;
+    return fTextureAccess;
 }
 
 const GrProgramStageFactory& GrSingleTextureEffect::getFactory() const {
index 211319cf51c815f633101b3fa26bc0ef89ce5979..209019623c6e8740b638e596c7e1d2dfef3aaa05 100644 (file)
@@ -21,8 +21,8 @@ public:
     GrSingleTextureEffect(GrTexture* texture);
     virtual ~GrSingleTextureEffect();
 
-    virtual unsigned int numTextures() const SK_OVERRIDE;
-    virtual GrTexture* texture(unsigned int index) const SK_OVERRIDE;
+    virtual int numTextures() const SK_OVERRIDE;
+    virtual const GrTextureAccess& textureAccess(int index) const SK_OVERRIDE;
 
     static const char* Name() { return "Single Texture"; }
 
@@ -33,7 +33,7 @@ public:
 private:
     GR_DECLARE_CUSTOM_STAGE_TEST;
 
-    GrTexture* fTexture;
+    GrTextureAccess fTextureAccess;
 
     typedef GrCustomStage INHERITED;
 };
index dfe5277fb9082f78451bd2950f9237e899998696..2703110df67f42640b38161fbcc136b6873c9687 100644 (file)
@@ -931,8 +931,6 @@ GrGLProgramStage* GrGLProgram::GenStageCode(const GrCustomStage* stage,
 
     GrGLProgramStage* glStage = stage->getFactory().createGLInstance(*stage);
 
-    GrAssert((desc.fInConfigFlags & StageDesc::kInConfigBitMask) == desc.fInConfigFlags);
-
     /// Vertex Shader Stuff
 
     // decide whether we need a matrix to transform texture coords and whether the varying needs a
@@ -964,30 +962,11 @@ GrGLProgramStage* GrGLProgram::GenStageCode(const GrCustomStage* stage,
 
     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 {
-            GrAssert(access->getTexture() == stage->texture(i));
-            deleteTextureAccess[i] = false;
-        }
-        textureSamplers[i].init(builder, access);
+        textureSamplers[i].init(builder, &stage->textureAccess(i));
         uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform);
     }
 
@@ -1010,10 +989,5 @@ GrGLProgramStage* GrGLProgram::GenStageCode(const GrCustomStage* stage,
     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;
 }
index 0dd1cb10d5efb17f345ba84b29637b0821f15715..e51f66351c3fbf87c5a89e142ba5a17390fa5f1f 100644 (file)
@@ -97,35 +97,12 @@ public:
                 kIsEnabled_OptFlagBit           = 1 << 7
             };
 
-            /**
-              Flags set based on a src texture's pixel config. The operations
-              described are performed after reading a texel.
-             */
-            enum InConfigFlags {
-                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.
-                */
-                kSmearAlpha_InConfigFlag                = 0x01,
-
-                kDummyInConfigFlag,
-                kInConfigBitMask = (kDummyInConfigFlag-1) |
-                                   (kDummyInConfigFlag-2)
-            };
-
             uint8_t fOptFlags;
-            uint8_t fInConfigFlags; // bitfield of InConfigFlags values
 
             /** Non-zero if user-supplied code will write the stage's
                 contribution to the fragment shader. */
             GrProgramStageFactory::StageKey fCustomStageKey;
 
-            GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask ==
-                             kInConfigBitMask);
-
             inline bool isEnabled() const {
                 return SkToBool(fOptFlags & kIsEnabled_OptFlagBit);
             }
index b1a37fe374b35de7f9390f33441cca281ebfcd94..b7d0c656d73eaab01e5b01354d2ec7dc1dd0af2b 100644 (file)
@@ -30,11 +30,11 @@ void GrGLProgramStage::setData(const GrGLUniformManager&,
 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);
-        }
+    for (int index = 0; index < stage.numTextures(); ++index) {
+        const GrTextureAccess& access = stage.textureAccess(index);
+        StageKey value = GrGLShaderBuilder::KeyForTextureAccess(access, caps) << index;
+        GrAssert(0 == (value & key)); // keys for each access ought not to overlap
+        key |= value;
     }
     return key;
 }
index 17c00834fd95ad70b10f9610f33ec4e158d92e1f..43bd1b4ab5f9a981a55666cc4dbb2af0bc6c1631 100644 (file)
@@ -33,30 +33,40 @@ inline const char* sample_function_name(GrSLType type) {
     }
 }
 
-inline bool texture_requires_alpha_to_red_swizzle(const GrGLCaps& caps,
-                                                  const GrTextureAccess& access) {
-    return GrPixelConfigIsAlphaOnly(access.getTexture()->config()) && caps.textureRedSupport() &&
-        access.referencesAlpha();
-}
-
-SkString build_swizzle_string(const GrTextureAccess& textureAccess,
-                              const GrGLCaps& caps) {
-    const GrTextureAccess::Swizzle& swizzle = textureAccess.getSwizzle();
-    if (0 == swizzle[0]) {
-        return SkString("");
+/**
+ * Do we need to either map r,g,b->a or a->r.
+ */
+inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
+                                             const GrTextureAccess& access) {
+    if (GrPixelConfigIsAlphaOnly(access.getTexture()->config())) {
+        if (caps.textureRedSupport() && (GrTextureAccess::kA_SwizzleFlag & access.swizzleMask())) {
+            return true;
+        }
+        if (GrTextureAccess::kRGB_SwizzleMask & access.swizzleMask()) {
+            return true;
+        }
     }
+    return false;
+}
 
-    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]);
+void append_swizzle(SkString* outAppend,
+                    const GrTextureAccess& access,
+                    const GrGLCaps& caps) {
+    const char* swizzle = access.getSwizzle();
+    char mangledSwizzle[5];
+
+    // The swizzling occurs using texture params instead of shader-mangling if ARB_texture_swizzle
+    // is available.
+    if (!caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(access.getTexture()->config())) {
+        char alphaChar = caps.textureRedSupport() ? 'r' : 'a';
+        int i;
+        for (i = 0; '\0' != swizzle[i]; ++i) {
+            mangledSwizzle[i] = alphaChar;
         }
+        mangledSwizzle[i] ='\0';
+        swizzle = mangledSwizzle;
     }
-
-    return swizzleOut;
+    outAppend->appendf(".%s", swizzle);
 }
 
 }
@@ -114,16 +124,16 @@ void GrGLShaderBuilder::appendTextureLookup(SkString* out,
                                             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",
+    out->appendf("%s(%s, %s)",
                  sample_function_name(varyingType),
                  this->getUniformCStr(sampler.fSamplerUniform),
-                 coordName, swizzle.c_str());
+                 coordName);
+    append_swizzle(out, *sampler.textureAccess(), fContext.caps());
 }
 
 void GrGLShaderBuilder::appendTextureLookupAndModulate(
@@ -144,17 +154,36 @@ GrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAc
 
     // 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)) {
+    if (!caps.textureSwizzleSupport() && swizzle_requires_alpha_remapping(caps, access)) {
         key = 1;
     }
-
+    #if GR_DEBUG
+        // Assert that key is set iff the swizzle will be modified.
+        SkString origString(access.getSwizzle());
+        origString.prepend(".");
+        SkString modifiedString;
+        append_swizzle(&modifiedString, access, caps);
+        GrAssert(SkToBool(key) == (modifiedString != origString));
+    #endif
     return key;
 }
 
+const GrGLenum* GrGLShaderBuilder::GetTexParamSwizzle(GrPixelConfig config, const GrGLCaps& caps) {
+    if (caps.textureSwizzleSupport() && GrPixelConfigIsAlphaOnly(config)) {
+        if (caps.textureRedSupport()) {
+            static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED, GR_GL_RED, GR_GL_RED };
+            return gRedSmear;
+        } else {
+            static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
+                                                    GR_GL_ALPHA, GR_GL_ALPHA };
+            return gAlphaSmear;
+        }
+    } else {
+        static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN, GR_GL_BLUE, GR_GL_ALPHA };
+        return gStraight;
+    }
+}
+
 GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
                                                                      GrSLType type,
                                                                      const char* name,
index e02d53d00a2c9badb92308d714e31ced064459fe..f143af39a7689c23615106f2c783bdc75505671b 100644 (file)
@@ -125,6 +125,10 @@ public:
     static GrCustomStage::StageKey KeyForTextureAccess(const GrTextureAccess& access,
                                                        const GrGLCaps& caps);
 
+    /** If texture swizzling is available using tex parameters then it is preferred over mangling
+        the generated shader code. This potentially allows greater reuse of cached shaders. */
+    static const GrGLenum* GetTexParamSwizzle(GrPixelConfig config, 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 845d1f860b400ac1cc9bab82b7f12122a21c40b7..442bbb42a039a58b59b3864fdc6f93c97d133382 100644 (file)
@@ -9,6 +9,7 @@
 #include "GrGpuGL.h"
 #include "GrGLStencilBuffer.h"
 #include "GrGLPath.h"
+#include "GrGLShaderBuilder.h"
 #include "GrTemplates.h"
 #include "GrTypes.h"
 #include "SkTemplates.h"
@@ -2001,28 +2002,7 @@ void GrGpuGL::flushBlend(bool isLines,
 }
 namespace {
 
-// get_swizzle is only called from this .cpp so it is OK to inline it here
-inline const GrGLenum* get_swizzle(GrPixelConfig config,
-                                   const GrSamplerState& sampler,
-                                   const GrGLCaps& glCaps) {
-    if (GrPixelConfigIsAlphaOnly(config)) {
-        if (glCaps.textureRedSupport()) {
-            static const GrGLenum gRedSmear[] = { GR_GL_RED, GR_GL_RED,
-                                                  GR_GL_RED, GR_GL_RED };
-            return gRedSmear;
-        } else {
-            static const GrGLenum gAlphaSmear[] = { GR_GL_ALPHA, GR_GL_ALPHA,
-                                                    GR_GL_ALPHA, GR_GL_ALPHA };
-            return gAlphaSmear;
-        }
-    } else {
-        static const GrGLenum gStraight[] = { GR_GL_RED, GR_GL_GREEN,
-                                              GR_GL_BLUE,  GR_GL_ALPHA };
-        return gStraight;
-    }
-}
-
-void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) {
+inline void set_tex_swizzle(GrGLenum swizzle[4], const GrGLInterface* gl) {
     GR_GL_CALL(gl, TexParameteriv(GR_GL_TEXTURE_2D,
                                   GR_GL_TEXTURE_SWIZZLE_RGBA,
                                   reinterpret_cast<const GrGLint*>(swizzle)));
@@ -2089,7 +2069,7 @@ void GrGpuGL::flushBoundTextureAndParams(int stage,
     newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX());
     newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY());
     memcpy(newTexParams.fSwizzleRGBA,
-           get_swizzle(nextTexture->config(), drawState->getSampler(stage), this->glCaps()),
+           GrGLShaderBuilder::GetTexParamSwizzle(nextTexture->config(), this->glCaps()),
            sizeof(newTexParams.fSwizzleRGBA));
     if (setAll || newTexParams.fFilter != oldTexParams.fFilter) {
         this->setTextureUnit(stage);
index e39b05374f6693c452ff8d190dcf0aabe54a434c..a1807da445fb6199874085394d60dfe0d71c3eb2 100644 (file)
@@ -708,7 +708,6 @@ void GrGpuGL::buildProgram(bool isPoints,
             // FIXME: Still assuming one texture per custom stage
             const GrCustomStage* customStage = drawState.getSampler(s).getCustomStage();
             const GrGLTexture* texture = static_cast<const GrGLTexture*>(customStage->texture(0));
-            stage.fInConfigFlags = 0;
             if (NULL != texture) {
                 // We call this helper function rather then simply checking the client-specified
                 // texture matrix. This is because we may have to concat a y-inversion to account
@@ -718,13 +717,6 @@ void GrGpuGL::buildProgram(bool isPoints,
                 } else if (!sampler.getMatrix().hasPerspective()) {
                     stage.fOptFlags |= StageDesc::kNoPerspective_OptFlagBit;
                 }
-                if (!this->glCaps().textureSwizzleSupport()) {
-                    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;
-                    }
-                }
             }
 
             setup_custom_stage(&stage, sampler, this->glCaps(), customStages,
@@ -732,7 +724,6 @@ void GrGpuGL::buildProgram(bool isPoints,
 
         } else {
             stage.fOptFlags         = 0;
-            stage.fInConfigFlags    = 0;
             stage.fCustomStageKey   = 0;
             customStages[s] = NULL;
         }
index 54f900ce9d694155cb815128d25a83eb6d1cb021..c1d829c0ce1a6cf1ccad827069079d9be80c13e9 100644 (file)
@@ -75,10 +75,6 @@ bool GrGpuGL::programUnitTest() {
         0,
         StageDesc::kNoPerspective_OptFlagBit,
     };
-    static const int IN_CONFIG_FLAGS[] = {
-        StageDesc::kNone_InConfigFlag,
-        StageDesc::kSmearAlpha_InConfigFlag,
-    };
 
     static const int NUM_TESTS = 512;
 
@@ -152,7 +148,6 @@ bool GrGpuGL::programUnitTest() {
             stage.fCustomStageKey = 0;
 
             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))];
 
             if (stage.isEnabled()) {
                 GrTexture* dummyTextures[] = {dummyTexture1.get(), dummyTexture2.get()};