diff --git a/include/gpu/GrCustomStage.h b/include/gpu/GrCustomStage.h index 32d40b47d..9765a42f2 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 55c0a02b8..e4e373294 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 fTexture; + uint32_t fSwizzleMask; + char fSwizzle[5]; }; #endif diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index d7b4f13e2..f0dac4d18 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 8c8632681..0e7c2fc27 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(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 7b3bc617e..3f79af828 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 155f68282..c3c803806 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 d662398d4..0edc00de9 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 f79e58657..fe762fdbe 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 b2fe0cc15..b2e920538 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 211319cf5..209019623 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 dfe5277fb..2703110df 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 0dd1cb10d..e51f66351 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 b1a37fe37..b7d0c656d 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 17c00834f..43bd1b4ab 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(""); - } - - 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]); +/** + * 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; +} - return swizzleOut; +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; + } + 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 e02d53d00..f143af39a 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 845d1f860..442bbb42a 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(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 e39b05374..a1807da44 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(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 54f900ce9..c1d829c0c 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()};