aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-09-11 15:45:20 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-09-11 15:45:20 +0000
commit6d003d1ddced3e71684b8b3785d1e5a16255688d (patch)
tree6c6b8b1e3900aa90b01d5f159bb9fb83e1c75585
parent4813458d89fb276680168848bd861b307cf83f51 (diff)
Wrap all GrCustomStage textures in GrTextureAccess, remove StageDesc::fInConfigFlags
Review URL: https://codereview.appspot.com/6494114 git-svn-id: http://skia.googlecode.com/svn/trunk@5485 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--include/gpu/GrCustomStage.h12
-rw-r--r--include/gpu/GrTextureAccess.h59
-rw-r--r--src/effects/gradients/SkGradientShader.cpp20
-rw-r--r--src/effects/gradients/SkGradientShaderPriv.h8
-rw-r--r--src/gpu/GrCustomStage.cpp14
-rw-r--r--src/gpu/GrTextureAccess.cpp68
-rw-r--r--src/gpu/effects/GrColorTableEffect.cpp11
-rw-r--r--src/gpu/effects/GrColorTableEffect.h8
-rw-r--r--src/gpu/effects/GrSingleTextureEffect.cpp10
-rw-r--r--src/gpu/effects/GrSingleTextureEffect.h6
-rw-r--r--src/gpu/gl/GrGLProgram.cpp28
-rw-r--r--src/gpu/gl/GrGLProgram.h23
-rw-r--r--src/gpu/gl/GrGLProgramStage.cpp10
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp87
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h4
-rw-r--r--src/gpu/gl/GrGpuGL.cpp26
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp9
-rw-r--r--tests/GLProgramsTest.cpp5
18 files changed, 214 insertions, 194 deletions
diff --git a/include/gpu/GrCustomStage.h b/include/gpu/GrCustomStage.h
index 32d40b47d7..9765a42f2b 100644
--- a/include/gpu/GrCustomStage.h
+++ b/include/gpu/GrCustomStage.h
@@ -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);
diff --git a/include/gpu/GrTextureAccess.h b/include/gpu/GrTextureAccess.h
index 55c0a02b87..e4e373294a 100644
--- a/include/gpu/GrTextureAccess.h
+++ b/include/gpu/GrTextureAccess.h
@@ -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
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp
index d7b4f13e2c..f0dac4d181 100644
--- a/src/effects/gradients/SkGradientShader.cpp
+++ b/src/effects/gradients/SkGradientShader.cpp
@@ -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,
diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h
index 8c8632681f..0e7c2fc279 100644
--- a/src/effects/gradients/SkGradientShaderPriv.h
+++ b/src/effects/gradients/SkGradientShaderPriv.h
@@ -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;
diff --git a/src/gpu/GrCustomStage.cpp b/src/gpu/GrCustomStage.cpp
index 7b3bc617e0..3f79af828b 100644
--- a/src/gpu/GrCustomStage.cpp
+++ b/src/gpu/GrCustomStage.cpp
@@ -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) {
diff --git a/src/gpu/GrTextureAccess.cpp b/src/gpu/GrTextureAccess.cpp
index 155f682827..c3c8038060 100644
--- a/src/gpu/GrTextureAccess.cpp
+++ b/src/gpu/GrTextureAccess.cpp
@@ -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);
+}
diff --git a/src/gpu/effects/GrColorTableEffect.cpp b/src/gpu/effects/GrColorTableEffect.cpp
index d662398d4a..0edc00de95 100644
--- a/src/gpu/effects/GrColorTableEffect.cpp
+++ b/src/gpu/effects/GrColorTableEffect.cpp
@@ -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;
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/effects/GrColorTableEffect.h b/src/gpu/effects/GrColorTableEffect.h
index f79e586579..fe762fdbec 100644
--- a/src/gpu/effects/GrColorTableEffect.h
+++ b/src/gpu/effects/GrColorTableEffect.h
@@ -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
diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp
index b2fe0cc15e..b2e920538c 100644
--- a/src/gpu/effects/GrSingleTextureEffect.cpp
+++ b/src/gpu/effects/GrSingleTextureEffect.cpp
@@ -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 {
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h
index 211319cf51..209019623c 100644
--- a/src/gpu/effects/GrSingleTextureEffect.h
+++ b/src/gpu/effects/GrSingleTextureEffect.h
@@ -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;
};
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index dfe5277fb9..2703110df6 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -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;
}
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 0dd1cb10d5..e51f66351c 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -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);
}
diff --git a/src/gpu/gl/GrGLProgramStage.cpp b/src/gpu/gl/GrGLProgramStage.cpp
index b1a37fe374..b7d0c656d7 100644
--- a/src/gpu/gl/GrGLProgramStage.cpp
+++ b/src/gpu/gl/GrGLProgramStage.cpp
@@ -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;
}
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 17c00834fd..43bd1b4ab5 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -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,
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index e02d53d00a..f143af39a7 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -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
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 845d1f860b..442bbb42a0 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -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);
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index e39b05374f..a1807da445 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -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;
}
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index 54f900ce9d..c1d829c0ce 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -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()};