Introduction of set of functions to manage generation of texture fetch shader code.

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
This commit is contained in:
twiz@google.com 2012-08-02 15:15:16 +00:00
parent eb7ad4a8b9
commit a5e65ec434
22 changed files with 238 additions and 55 deletions

View File

@ -14,6 +14,27 @@
class GrContext; class GrContext;
class GrTexture; 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 /** Provides custom vertex shader, fragment shader, uniform data for a
particular stage of the Ganesh shading pipeline. particular stage of the Ganesh shading pipeline.
@ -74,13 +95,17 @@ public:
*/ */
virtual bool isEqual(const GrCustomStage&) const; virtual bool isEqual(const GrCustomStage&) const;
/** Human-meaningful string to identify this effect; may be embedded /** Human-meaningful string to identify this effect; may be embedded
in generated shader code. */ in generated shader code. */
const char* name() const { return this->getFactory().name(); } const char* name() const { return this->getFactory().name(); }
virtual unsigned int numTextures() const; virtual unsigned int numTextures() const;
virtual GrTexture* texture(unsigned int index) 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 new(size_t size);
void operator delete(void* target); void operator delete(void* target);

View File

@ -19,15 +19,18 @@
class GrCustomStage; class GrCustomStage;
class GrGLProgramStage; class GrGLProgramStage;
class GrGLCaps;
class GrProgramStageFactory : public GrNoncopyable { class GrProgramStageFactory : public GrNoncopyable {
public: public:
typedef uint16_t StageKey; typedef uint32_t StageKey;
enum { enum {
kProgramStageKeyBits = 10, 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( virtual GrGLProgramStage* createGLInstance(
const GrCustomStage& stage) const = 0; const GrCustomStage& stage) const = 0;
@ -68,7 +71,7 @@ template <typename StageClass>
class GrTProgramStageFactory : public GrProgramStageFactory { class GrTProgramStageFactory : public GrProgramStageFactory {
public: public:
typedef typename StageClass::GLProgramStage GLProgramStage; typedef typename StageClass::GLProgramStage GLProgramStage;
/** Returns a human-readable name that is accessible via GrCustomStage or /** Returns a human-readable name that is accessible via GrCustomStage or
GrGLProgramStage and is consistent between the two of them. GrGLProgramStage and is consistent between the two of them.
@ -80,20 +83,26 @@ public:
id identifies the GrCustomShader subclass. The remainder is based id identifies the GrCustomShader subclass. The remainder is based
on the aspects of the GrCustomStage object's configuration that affect on the aspects of the GrCustomStage object's configuration that affect
GLSL code generation. */ 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); GrAssert(kIllegalStageClassID != fStageClassID);
StageKey stageID = GLProgramStage::GenKey(stage); StageKey stageID = GLProgramStage::GenKey(stage, caps);
StageKey textureKey = GLProgramStage::GenTextureKey(stage, caps);
#if GR_DEBUG #if GR_DEBUG
static const StageKey kIllegalIDMask = static const StageKey kIllegalIDMask =
(uint16_t) (~((1U << kProgramStageKeyBits) - 1)); (uint16_t) (~((1U << kProgramStageKeyBits) - 1));
GrAssert(!(kIllegalIDMask & stageID)); GrAssert(!(kIllegalIDMask & stageID));
static const StageKey kIllegalTextureKeyMask =
(uint16_t) (~((1U << kTexturingStageKeyBits) - 1));
GrAssert(!(kIllegalTextureKeyMask & textureKey));
#endif #endif
return fStageClassID | stageID; return fStageClassID | (textureKey << kProgramStageKeyBits) | stageID;
} }
/** Returns a new instance of the appropriate *GL* implementation class /** Returns a new instance of the appropriate *GL* implementation class
for the given GrCustomStage; caller is responsible for deleting for the given GrCustomStage; caller is responsible for deleting
the object. */ the object. */
virtual GLProgramStage* createGLInstance( virtual GLProgramStage* createGLInstance(
const GrCustomStage& stage) const SK_OVERRIDE { const GrCustomStage& stage) const SK_OVERRIDE {
return SkNEW_ARGS(GLProgramStage, (*this, stage)); return SkNEW_ARGS(GLProgramStage, (*this, stage));
@ -113,7 +122,7 @@ public:
protected: protected:
GrTProgramStageFactory() { GrTProgramStageFactory() {
fStageClassID = GenID() << kProgramStageKeyBits; fStageClassID = GenID() << (kProgramStageKeyBits + kTexturingStageKeyBits) ;
} }
}; };

View File

@ -918,7 +918,7 @@ public:
virtual void emitLightFunc(const GrGLShaderBuilder*, SkString* funcs) = 0; 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&, virtual void setData(const GrGLUniformManager&,
const GrCustomStage&, const GrCustomStage&,
@ -1086,8 +1086,8 @@ vec3 interiorNormal(float m[9], float surfaceScale) {\n\
code->appendf(")%s;\n", builder->fModulate.c_str()); code->appendf(")%s;\n", builder->fModulate.c_str());
} }
GrGLProgramStage::StageKey GrGLLightingEffect::GenKey( GrGLProgramStage::StageKey GrGLLightingEffect::GenKey(const GrCustomStage& s,
const GrCustomStage& s) { const GrGLCaps& caps) {
return static_cast<const GrLightingEffect&>(s).light()->type(); return static_cast<const GrLightingEffect&>(s).light()->type();
} }

View File

@ -491,7 +491,7 @@ public:
const char* outputColor, const char* outputColor,
const char* inputColor, const char* inputColor,
const char* samplerName) SK_OVERRIDE; 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: private:

View File

@ -487,7 +487,7 @@ public:
const char* inputColor, const char* inputColor,
const char* samplerName) SK_OVERRIDE; 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: private:

View File

@ -396,7 +396,7 @@ public:
const char* inputColor, const char* inputColor,
const char* samplerName) SK_OVERRIDE; 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: private:

View File

@ -340,7 +340,7 @@ public:
const GrRenderTarget*, const GrRenderTarget*,
int stageNum) SK_OVERRIDE; int stageNum) SK_OVERRIDE;
static StageKey GenKey(const GrCustomStage& s); static StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
protected: 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()); return (static_cast<const GrConical2Gradient&>(s).isDegenerate());
} }
@ -669,4 +669,4 @@ GrCustomStage* SkTwoPointConicalGradient::asNewCustomStage(
return NULL; return NULL;
} }
#endif #endif

View File

@ -373,7 +373,7 @@ public:
const GrRenderTarget*, const GrRenderTarget*,
int stageNum) SK_OVERRIDE; int stageNum) SK_OVERRIDE;
static StageKey GenKey(const GrCustomStage& s); static StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
protected: 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()); return (static_cast<const GrRadial2Gradient&>(s).isDegenerate());
} }

View File

@ -8,6 +8,7 @@
#include "GrContext.h" #include "GrContext.h"
#include "GrCustomStage.h" #include "GrCustomStage.h"
#include "GrMemoryPool.h" #include "GrMemoryPool.h"
#include "SkString.h"
#include "SkTLS.h" #include "SkTLS.h"
SK_DEFINE_INST_COUNT(GrCustomStage) SK_DEFINE_INST_COUNT(GrCustomStage)
@ -31,6 +32,17 @@ private:
int32_t GrProgramStageFactory::fCurrStageClassID = int32_t GrProgramStageFactory::fCurrStageClassID =
GrProgramStageFactory::kIllegalStageClassID; 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() { GrCustomStage::GrCustomStage() {
} }
@ -63,6 +75,10 @@ GrTexture* GrCustomStage::texture(unsigned int index) const {
return NULL; return NULL;
} }
const GrTextureAccess* GrCustomStage::textureAccess(unsigned int index) const {
return NULL;
}
void * GrCustomStage::operator new(size_t size) { void * GrCustomStage::operator new(size_t size) {
return GrCustomStage_Globals::GetTLS()->allocate(size); return GrCustomStage_Globals::GetTLS()->allocate(size);
} }
@ -70,4 +86,3 @@ void * GrCustomStage::operator new(size_t size) {
void GrCustomStage::operator delete(void* target) { void GrCustomStage::operator delete(void* target) {
GrCustomStage_Globals::GetTLS()->release(target); GrCustomStage_Globals::GetTLS()->release(target);
} }

View File

@ -30,49 +30,72 @@ public:
const GrRenderTarget*, const GrRenderTarget*,
int stageNum) SK_OVERRIDE {} int stageNum) SK_OVERRIDE {}
static inline StageKey GenKey(const GrCustomStage&); static StageKey GenKey(const GrCustomStage&, const GrGLCaps&);
private: private:
const GrCustomStage& fCustomStage;
typedef GrGLProgramStage INHERITED; typedef GrGLProgramStage INHERITED;
}; };
GrGLColorTableEffect::GrGLColorTableEffect( GrGLColorTableEffect::GrGLColorTableEffect(
const GrProgramStageFactory& factory, const GrCustomStage& stage) 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* outputColor,
const char* inputColor, const char* inputColor,
const char* samplerName) { const char* samplerName) {
static const float kColorScaleFactor = 255.0f / 256.0f; static const float kColorScaleFactor = 255.0f / 256.0f;
static const float kColorOffsetFactor = 1.0f / 512.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", code->appendf("\t\tvec4 coord = vec4(%s.rgb / %s.a, %s.a);\n",
inputColor, inputColor, inputColor); inputColor, inputColor, inputColor);
code->appendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n", code->appendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n",
kColorScaleFactor, kColorScaleFactor,
kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor); kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor);
code->appendf("\t\t%s.a = texture2D(%s, vec2(coord.a, 0.125)).a;\n",
outputColor, samplerName); const GrTextureAccess& access = *fCustomStage.textureAccess(0);
code->appendf("\t\t%s.r = texture2D(%s, vec2(coord.r, 0.375)).a;\n", code->appendf("\t\t%s.a = ", outputColor);
outputColor, samplerName); builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
code->appendf("\t\t%s.g = texture2D(%s, vec2(coord.g, 0.625)).a;\n", access,
outputColor, samplerName); samplerName,
code->appendf("\t\t%s.b = texture2D(%s, vec2(coord.b, 0.875)).a;\n", "vec2(coord.a, 0.125)");
outputColor, samplerName);
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); code->appendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
} }
GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey( GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey(const GrCustomStage& s,
const GrCustomStage& s) { const GrGLCaps& caps) {
return 0; return 0;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
GrColorTableEffect::GrColorTableEffect(GrTexture* texture) GrColorTableEffect::GrColorTableEffect(GrTexture* texture)
: INHERITED(texture) { : INHERITED(texture)
, fTextureAccess(texture, SkString("a")) {
} }
GrColorTableEffect::~GrColorTableEffect() { GrColorTableEffect::~GrColorTableEffect() {
@ -85,3 +108,10 @@ const GrProgramStageFactory& GrColorTableEffect::getFactory() const {
bool GrColorTableEffect::isEqual(const GrCustomStage& sBase) const { bool GrColorTableEffect::isEqual(const GrCustomStage& sBase) const {
return INHERITED::isEqual(sBase); return INHERITED::isEqual(sBase);
} }
const GrTextureAccess* GrColorTableEffect::textureAccess(unsigned int index) const {
if (0 == index)
return &fTextureAccess;
return NULL;
}

View File

@ -29,10 +29,14 @@ public:
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE; virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE; virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
virtual const GrTextureAccess* textureAccess(unsigned int index) const SK_OVERRIDE;
typedef GrGLColorTableEffect GLProgramStage; typedef GrGLColorTableEffect GLProgramStage;
private: private:
GrTextureAccess fTextureAccess;
typedef GrSingleTextureEffect INHERITED; typedef GrSingleTextureEffect INHERITED;
}; };
#endif #endif

View File

@ -33,7 +33,7 @@ public:
const GrRenderTarget*, const GrRenderTarget*,
int stageNum) SK_OVERRIDE; int stageNum) SK_OVERRIDE;
static inline StageKey GenKey(const GrCustomStage&); static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&);
private: private:
int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); } 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()); uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
} }
GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey( GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey(const GrCustomStage& s,
const GrCustomStage& s) { const GrGLCaps& caps) {
return static_cast<const GrConvolutionEffect&>(s).radius(); return static_cast<const GrConvolutionEffect&>(s).radius();
} }
@ -185,4 +185,3 @@ bool GrConvolutionEffect::isEqual(const GrCustomStage& sBase) const {
this->direction() == s.direction() && this->direction() == s.direction() &&
0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float))); 0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
} }

View File

@ -26,7 +26,7 @@ public:
const char* inputColor, const char* inputColor,
const char* samplerName) SK_OVERRIDE; 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&, virtual void setData(const GrGLUniformManager&,
const GrCustomStage&, const GrCustomStage&,
@ -98,8 +98,8 @@ void GrGLMorphologyEffect ::emitFS(GrGLShaderBuilder* builder,
code->appendf("\t\t%s = value%s;\n", outputColor, builder->fModulate.c_str()); code->appendf("\t\t%s = value%s;\n", outputColor, builder->fModulate.c_str());
} }
GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey( GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey(const GrCustomStage& s,
const GrCustomStage& s) { const GrGLCaps& caps) {
const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(s); const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(s);
StageKey key = static_cast<StageKey>(m.radius()); StageKey key = static_cast<StageKey>(m.radius());
key |= (m.type() << 8); key |= (m.type() << 8);

View File

@ -26,7 +26,7 @@ public:
builder->emitDefaultFetch(outputColor, samplerName); builder->emitDefaultFetch(outputColor, samplerName);
} }
static inline StageKey GenKey(const GrCustomStage&) { return 0; } static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&) { return 0; }
private: private:
@ -56,5 +56,3 @@ GrTexture* GrSingleTextureEffect::texture(unsigned int index) const {
const GrProgramStageFactory& GrSingleTextureEffect::getFactory() const { const GrProgramStageFactory& GrSingleTextureEffect::getFactory() const {
return GrTProgramStageFactory<GrSingleTextureEffect>::getInstance(); return GrTProgramStageFactory<GrSingleTextureEffect>::getInstance();
} }

View File

@ -27,7 +27,7 @@ public:
const GrRenderTarget*, const GrRenderTarget*,
int stageNum) SK_OVERRIDE; int stageNum) SK_OVERRIDE;
static inline StageKey GenKey(const GrCustomStage&) { return 0; } static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&) { return 0; }
private: private:
GrGLUniformManager::UniformHandle fNameUni; GrGLUniformManager::UniformHandle fNameUni;
@ -107,5 +107,3 @@ bool GrTextureDomainEffect::isEqual(const GrCustomStage& sBase) const {
const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase); const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase);
return (INHERITED::isEqual(sBase) && this->fTextureDomain == s.fTextureDomain); return (INHERITED::isEqual(sBase) && this->fTextureDomain == s.fTextureDomain);
} }

View File

@ -164,7 +164,7 @@ public:
/** Non-zero if user-supplied code will write the stage's /** Non-zero if user-supplied code will write the stage's
contribution to the fragment shader. */ contribution to the fragment shader. */
uint16_t fCustomStageKey; GrProgramStageFactory::StageKey fCustomStageKey;
GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask == GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask ==
kInConfigBitMask); kInConfigBitMask);

View File

@ -27,3 +27,14 @@ void GrGLProgramStage::setData(const GrGLUniformManager&,
int stageNum) { 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;
}

View File

@ -78,6 +78,8 @@ public:
const char* name() const { return fFactory.name(); } const char* name() const { return fFactory.name(); }
static StageKey GenTextureKey(const GrCustomStage&, const GrGLCaps&);
protected: protected:
const GrProgramStageFactory& fFactory; const GrProgramStageFactory& fFactory;

View File

@ -8,6 +8,7 @@
#include "gl/GrGLShaderBuilder.h" #include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLProgram.h" #include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h" #include "gl/GrGLUniformHandle.h"
#include "GrTexture.h"
// number of each input/output type in a single allocation block // number of each input/output type in a single allocation block
static const int kVarsPerBlock = 8; static const int kVarsPerBlock = 8;
@ -21,6 +22,50 @@ static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
typedef GrGLUniformManager::UniformHandle UniformHandle; 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. // Architectural assumption: always 2-d input coords.
// Likely to become non-constant and non-static, perhaps even // Likely to become non-constant and non-static, perhaps even
// varying by stage, if we use 1D textures for gradients! // 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()); 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, GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
GrSLType type, GrSLType type,
const char* name, const char* name,

View File

@ -9,6 +9,7 @@
#define GrGLShaderBuilder_DEFINED #define GrGLShaderBuilder_DEFINED
#include "GrAllocator.h" #include "GrAllocator.h"
#include "GrCustomStage.h"
#include "gl/GrGLShaderVar.h" #include "gl/GrGLShaderVar.h"
#include "gl/GrGLSL.h" #include "gl/GrGLSL.h"
#include "gl/GrGLUniformManager.h" #include "gl/GrGLUniformManager.h"
@ -55,6 +56,22 @@ public:
void emitDefaultFetch(const char* outColor, void emitDefaultFetch(const char* outColor,
const char* samplerName); 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. /** 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 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 should be accessible. At least one bit must be set. Geometry shader uniforms are not

View File

@ -596,12 +596,13 @@ namespace {
void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage, void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage,
const GrSamplerState& sampler, const GrSamplerState& sampler,
const GrGLCaps& caps,
const GrCustomStage** customStages, const GrCustomStage** customStages,
GrGLProgram* program, int index) { GrGLProgram* program, int index) {
const GrCustomStage* customStage = sampler.getCustomStage(); const GrCustomStage* customStage = sampler.getCustomStage();
if (customStage) { if (customStage) {
const GrProgramStageFactory& factory = customStage->getFactory(); const GrProgramStageFactory& factory = customStage->getFactory();
stage->fCustomStageKey = factory.glStageKey(*customStage); stage->fCustomStageKey = factory.glStageKey(*customStage, caps);
customStages[index] = customStage; customStages[index] = customStage;
} else { } else {
stage->fCustomStageKey = 0; 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 { } else {
stage.fOptFlags = 0; stage.fOptFlags = 0;

View File

@ -413,7 +413,7 @@ bool GrGpuGL::programUnitTest() {
customStages[s].reset(create_random_effect(&stage, &random, getContext())); customStages[s].reset(create_random_effect(&stage, &random, getContext()));
if (NULL != customStages[s]) { if (NULL != customStages[s]) {
stage.fCustomStageKey = stage.fCustomStageKey =
customStages[s]->getFactory().glStageKey(*customStages[s]); customStages[s]->getFactory().glStageKey(*customStages[s], this->glCaps());
} }
} }
} }