aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar twiz@google.com <twiz@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-02 15:15:16 +0000
committerGravatar twiz@google.com <twiz@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-08-02 15:15:16 +0000
commita5e65ec434fed44dc616e4f64950b835b541181b (patch)
treeffe3592179c7c3ce78db8e5e485c641900042015 /src/gpu
parenteb7ad4a8b9c67743d6aa4e71b82e32f4cf1c8a9f (diff)
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
Diffstat (limited to 'src/gpu')
-rw-r--r--src/gpu/GrCustomStage.cpp17
-rw-r--r--src/gpu/effects/GrColorTableEffect.cpp60
-rw-r--r--src/gpu/effects/GrColorTableEffect.h4
-rw-r--r--src/gpu/effects/GrConvolutionEffect.cpp7
-rw-r--r--src/gpu/effects/GrMorphologyEffect.cpp6
-rw-r--r--src/gpu/effects/GrSingleTextureEffect.cpp4
-rw-r--r--src/gpu/effects/GrTextureDomainEffect.cpp4
-rw-r--r--src/gpu/gl/GrGLProgram.h2
-rw-r--r--src/gpu/gl/GrGLProgramStage.cpp11
-rw-r--r--src/gpu/gl/GrGLProgramStage.h2
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp73
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h17
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp6
-rw-r--r--src/gpu/gl/GrGpuGL_unittest.cpp2
14 files changed, 182 insertions, 33 deletions
diff --git a/src/gpu/GrCustomStage.cpp b/src/gpu/GrCustomStage.cpp
index 43de5ae271..bea07cfab4 100644
--- a/src/gpu/GrCustomStage.cpp
+++ b/src/gpu/GrCustomStage.cpp
@@ -8,6 +8,7 @@
#include "GrContext.h"
#include "GrCustomStage.h"
#include "GrMemoryPool.h"
+#include "SkString.h"
#include "SkTLS.h"
SK_DEFINE_INST_COUNT(GrCustomStage)
@@ -31,6 +32,17 @@ private:
int32_t GrProgramStageFactory::fCurrStageClassID =
GrProgramStageFactory::kIllegalStageClassID;
+GrTextureAccess::GrTextureAccess(const GrTexture* texture, const SkString& swizzle)
+ : fTexture(texture) {
+ GrAssert(swizzle.size() <= 4);
+ for (unsigned int offset = 0; offset < swizzle.size(); ++offset) {
+ fSwizzle[offset] = swizzle[offset];
+ }
+ if (swizzle.size() < 4) {
+ fSwizzle[swizzle.size()] = 0;
+ }
+}
+
GrCustomStage::GrCustomStage() {
}
@@ -63,6 +75,10 @@ GrTexture* GrCustomStage::texture(unsigned int index) const {
return NULL;
}
+const GrTextureAccess* GrCustomStage::textureAccess(unsigned int index) const {
+ return NULL;
+}
+
void * GrCustomStage::operator new(size_t size) {
return GrCustomStage_Globals::GetTLS()->allocate(size);
}
@@ -70,4 +86,3 @@ void * GrCustomStage::operator new(size_t size) {
void GrCustomStage::operator delete(void* target) {
GrCustomStage_Globals::GetTLS()->release(target);
}
-
diff --git a/src/gpu/effects/GrColorTableEffect.cpp b/src/gpu/effects/GrColorTableEffect.cpp
index 2075c22fbb..f1ce664826 100644
--- a/src/gpu/effects/GrColorTableEffect.cpp
+++ b/src/gpu/effects/GrColorTableEffect.cpp
@@ -30,49 +30,72 @@ public:
const GrRenderTarget*,
int stageNum) SK_OVERRIDE {}
- static inline StageKey GenKey(const GrCustomStage&);
+ static StageKey GenKey(const GrCustomStage&, const GrGLCaps&);
private:
+
+ const GrCustomStage& fCustomStage;
+
typedef GrGLProgramStage INHERITED;
};
GrGLColorTableEffect::GrGLColorTableEffect(
const GrProgramStageFactory& factory, const GrCustomStage& stage)
- : INHERITED(factory) {
+ : INHERITED(factory)
+ , fCustomStage(stage) {
}
-void GrGLColorTableEffect::emitFS(GrGLShaderBuilder* state,
+void GrGLColorTableEffect::emitFS(GrGLShaderBuilder* builder,
const char* outputColor,
const char* inputColor,
const char* samplerName) {
static const float kColorScaleFactor = 255.0f / 256.0f;
static const float kColorOffsetFactor = 1.0f / 512.0f;
- SkString* code = &state->fFSCode;
+ SkString* code = &builder->fFSCode;
code->appendf("\t\tvec4 coord = vec4(%s.rgb / %s.a, %s.a);\n",
inputColor, inputColor, inputColor);
code->appendf("\t\tcoord = coord * %f + vec4(%f, %f, %f, %f);\n",
kColorScaleFactor,
kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor, kColorOffsetFactor);
- code->appendf("\t\t%s.a = texture2D(%s, vec2(coord.a, 0.125)).a;\n",
- outputColor, samplerName);
- code->appendf("\t\t%s.r = texture2D(%s, vec2(coord.r, 0.375)).a;\n",
- outputColor, samplerName);
- code->appendf("\t\t%s.g = texture2D(%s, vec2(coord.g, 0.625)).a;\n",
- outputColor, samplerName);
- code->appendf("\t\t%s.b = texture2D(%s, vec2(coord.b, 0.875)).a;\n",
- outputColor, samplerName);
+
+ const GrTextureAccess& access = *fCustomStage.textureAccess(0);
+ code->appendf("\t\t%s.a = ", outputColor);
+ builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+ access,
+ samplerName,
+ "vec2(coord.a, 0.125)");
+
+ code->appendf("\t\t%s.r = ", outputColor);
+ builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+ access,
+ samplerName,
+ "vec2(coord.r, 0.375)");
+
+ code->appendf("\t\t%s.g = ", outputColor);
+ builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+ access,
+ samplerName,
+ "vec2(coord.g, 0.625)");
+
+ code->appendf("\t\t%s.b = ", outputColor);
+ builder->emitCustomTextureLookup(GrGLShaderBuilder::kDefault_SamplerMode,
+ access,
+ samplerName,
+ "vec2(coord.b, 0.875)");
+
code->appendf("\t\t%s.rgb *= %s.a;\n", outputColor, outputColor);
}
-GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey(
- const GrCustomStage& s) {
+GrGLProgramStage::StageKey GrGLColorTableEffect::GenKey(const GrCustomStage& s,
+ const GrGLCaps& caps) {
return 0;
}
///////////////////////////////////////////////////////////////////////////////
GrColorTableEffect::GrColorTableEffect(GrTexture* texture)
- : INHERITED(texture) {
+ : INHERITED(texture)
+ , fTextureAccess(texture, SkString("a")) {
}
GrColorTableEffect::~GrColorTableEffect() {
@@ -85,3 +108,10 @@ const GrProgramStageFactory& GrColorTableEffect::getFactory() const {
bool GrColorTableEffect::isEqual(const GrCustomStage& sBase) const {
return INHERITED::isEqual(sBase);
}
+
+const GrTextureAccess* GrColorTableEffect::textureAccess(unsigned int index) const {
+ if (0 == index)
+ return &fTextureAccess;
+
+ return NULL;
+}
diff --git a/src/gpu/effects/GrColorTableEffect.h b/src/gpu/effects/GrColorTableEffect.h
index ee7a630469..16d76ade7f 100644
--- a/src/gpu/effects/GrColorTableEffect.h
+++ b/src/gpu/effects/GrColorTableEffect.h
@@ -29,10 +29,14 @@ public:
virtual const GrProgramStageFactory& getFactory() const SK_OVERRIDE;
virtual bool isEqual(const GrCustomStage&) const SK_OVERRIDE;
+ virtual const GrTextureAccess* textureAccess(unsigned int index) const SK_OVERRIDE;
+
typedef GrGLColorTableEffect GLProgramStage;
private:
+ GrTextureAccess fTextureAccess;
+
typedef GrSingleTextureEffect INHERITED;
};
#endif
diff --git a/src/gpu/effects/GrConvolutionEffect.cpp b/src/gpu/effects/GrConvolutionEffect.cpp
index 6af891b098..5cce800b51 100644
--- a/src/gpu/effects/GrConvolutionEffect.cpp
+++ b/src/gpu/effects/GrConvolutionEffect.cpp
@@ -33,7 +33,7 @@ public:
const GrRenderTarget*,
int stageNum) SK_OVERRIDE;
- static inline StageKey GenKey(const GrCustomStage&);
+ static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&);
private:
int width() const { return Gr1DKernelEffect::WidthFromRadius(fRadius); }
@@ -125,8 +125,8 @@ void GrGLConvolutionEffect::setData(const GrGLUniformManager& uman,
uman.set1fv(fKernelUni, 0, this->width(), conv.kernel());
}
-GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey(
- const GrCustomStage& s) {
+GrGLProgramStage::StageKey GrGLConvolutionEffect::GenKey(const GrCustomStage& s,
+ const GrGLCaps& caps) {
return static_cast<const GrConvolutionEffect&>(s).radius();
}
@@ -185,4 +185,3 @@ bool GrConvolutionEffect::isEqual(const GrCustomStage& sBase) const {
this->direction() == s.direction() &&
0 == memcmp(fKernel, s.fKernel, this->width() * sizeof(float)));
}
-
diff --git a/src/gpu/effects/GrMorphologyEffect.cpp b/src/gpu/effects/GrMorphologyEffect.cpp
index f8b268dae6..be8485e554 100644
--- a/src/gpu/effects/GrMorphologyEffect.cpp
+++ b/src/gpu/effects/GrMorphologyEffect.cpp
@@ -26,7 +26,7 @@ public:
const char* inputColor,
const char* samplerName) SK_OVERRIDE;
- static inline StageKey GenKey(const GrCustomStage& s);
+ static inline StageKey GenKey(const GrCustomStage& s, const GrGLCaps& caps);
virtual void setData(const GrGLUniformManager&,
const GrCustomStage&,
@@ -98,8 +98,8 @@ void GrGLMorphologyEffect ::emitFS(GrGLShaderBuilder* builder,
code->appendf("\t\t%s = value%s;\n", outputColor, builder->fModulate.c_str());
}
-GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey(
- const GrCustomStage& s) {
+GrGLProgramStage::StageKey GrGLMorphologyEffect::GenKey(const GrCustomStage& s,
+ const GrGLCaps& caps) {
const GrMorphologyEffect& m = static_cast<const GrMorphologyEffect&>(s);
StageKey key = static_cast<StageKey>(m.radius());
key |= (m.type() << 8);
diff --git a/src/gpu/effects/GrSingleTextureEffect.cpp b/src/gpu/effects/GrSingleTextureEffect.cpp
index 350d9e6bc5..5f66e09805 100644
--- a/src/gpu/effects/GrSingleTextureEffect.cpp
+++ b/src/gpu/effects/GrSingleTextureEffect.cpp
@@ -26,7 +26,7 @@ public:
builder->emitDefaultFetch(outputColor, samplerName);
}
- static inline StageKey GenKey(const GrCustomStage&) { return 0; }
+ static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&) { return 0; }
private:
@@ -56,5 +56,3 @@ GrTexture* GrSingleTextureEffect::texture(unsigned int index) const {
const GrProgramStageFactory& GrSingleTextureEffect::getFactory() const {
return GrTProgramStageFactory<GrSingleTextureEffect>::getInstance();
}
-
-
diff --git a/src/gpu/effects/GrTextureDomainEffect.cpp b/src/gpu/effects/GrTextureDomainEffect.cpp
index 1bf0512da7..e76d0c916b 100644
--- a/src/gpu/effects/GrTextureDomainEffect.cpp
+++ b/src/gpu/effects/GrTextureDomainEffect.cpp
@@ -27,7 +27,7 @@ public:
const GrRenderTarget*,
int stageNum) SK_OVERRIDE;
- static inline StageKey GenKey(const GrCustomStage&) { return 0; }
+ static inline StageKey GenKey(const GrCustomStage&, const GrGLCaps&) { return 0; }
private:
GrGLUniformManager::UniformHandle fNameUni;
@@ -107,5 +107,3 @@ bool GrTextureDomainEffect::isEqual(const GrCustomStage& sBase) const {
const GrTextureDomainEffect& s = static_cast<const GrTextureDomainEffect&>(sBase);
return (INHERITED::isEqual(sBase) && this->fTextureDomain == s.fTextureDomain);
}
-
-
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index 18d97d5652..62c70e54bc 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -164,7 +164,7 @@ public:
/** Non-zero if user-supplied code will write the stage's
contribution to the fragment shader. */
- uint16_t fCustomStageKey;
+ GrProgramStageFactory::StageKey fCustomStageKey;
GR_STATIC_ASSERT((InConfigFlags)(uint8_t)kInConfigBitMask ==
kInConfigBitMask);
diff --git a/src/gpu/gl/GrGLProgramStage.cpp b/src/gpu/gl/GrGLProgramStage.cpp
index 12c3894131..b1a37fe374 100644
--- a/src/gpu/gl/GrGLProgramStage.cpp
+++ b/src/gpu/gl/GrGLProgramStage.cpp
@@ -27,3 +27,14 @@ void GrGLProgramStage::setData(const GrGLUniformManager&,
int stageNum) {
}
+GrGLProgramStage::StageKey GrGLProgramStage::GenTextureKey(const GrCustomStage& stage,
+ const GrGLCaps& caps) {
+ StageKey key = 0;
+ for (unsigned int index = 0; index < stage.numTextures(); ++index) {
+ if (stage.textureAccess(index)) {
+ key = (key << index) |
+ GrGLShaderBuilder::KeyForTextureAccess(*stage.textureAccess(index), caps);
+ }
+ }
+ return key;
+}
diff --git a/src/gpu/gl/GrGLProgramStage.h b/src/gpu/gl/GrGLProgramStage.h
index 12163f8917..8e3a4b1584 100644
--- a/src/gpu/gl/GrGLProgramStage.h
+++ b/src/gpu/gl/GrGLProgramStage.h
@@ -78,6 +78,8 @@ public:
const char* name() const { return fFactory.name(); }
+ static StageKey GenTextureKey(const GrCustomStage&, const GrGLCaps&);
+
protected:
const GrProgramStageFactory& fFactory;
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 28449537e7..0d2a1ecf44 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -8,6 +8,7 @@
#include "gl/GrGLShaderBuilder.h"
#include "gl/GrGLProgram.h"
#include "gl/GrGLUniformHandle.h"
+#include "GrTexture.h"
// number of each input/output type in a single allocation block
static const int kVarsPerBlock = 8;
@@ -21,6 +22,50 @@ static const GrGLShaderVar::Precision kDefaultFragmentPrecision = GrGLShaderVar:
typedef GrGLUniformManager::UniformHandle UniformHandle;
///////////////////////////////////////////////////////////////////////////////
+static SkString build_sampler_string(GrGLShaderBuilder::SamplerMode samplerMode) {
+ SkString sampler("texture2D");
+ switch (samplerMode) {
+ case GrGLShaderBuilder::kDefault_SamplerMode:
+ break;
+ case GrGLShaderBuilder::kProj_SamplerMode:
+ sampler.append("Proj");
+ break;
+ case GrGLShaderBuilder::kExplicitDivide_SamplerMode:
+ GrAssert(false); // Not Implemented
+ break;
+ }
+
+ return sampler;
+}
+
+static bool texture_requires_alpha_to_red_swizzle(const GrGLCaps& caps,
+ const GrTextureAccess& access) {
+ return GrPixelConfigIsAlphaOnly(access.getTexture()->config()) && caps.textureRedSupport() &&
+ access.referencesAlpha();
+}
+
+static SkString build_swizzle_string(const GrTextureAccess& textureAccess,
+ const GrGLCaps& caps) {
+ const GrTextureAccess::Swizzle& swizzle = textureAccess.getSwizzle();
+ if (0 == swizzle[0]) {
+ return SkString("");
+ }
+
+ SkString swizzleOut(".");
+ bool alphaIsRed = texture_requires_alpha_to_red_swizzle(caps, textureAccess);
+ for (int offset = 0; offset < 4 && swizzle[offset]; ++offset) {
+ if (alphaIsRed && 'a' == swizzle[offset]) {
+ swizzleOut.appendf("r");
+ } else {
+ swizzleOut.appendf("%c", swizzle[offset]);
+ }
+ }
+
+ return swizzleOut;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
// Architectural assumption: always 2-d input coords.
// Likely to become non-constant and non-static, perhaps even
// varying by stage, if we use 1D textures for gradients!
@@ -120,6 +165,34 @@ void GrGLShaderBuilder::emitDefaultFetch(const char* outColor,
fFSCode.appendf("%s%s;\n", fSwizzle.c_str(), fModulate.c_str());
}
+void GrGLShaderBuilder::emitCustomTextureLookup(SamplerMode samplerMode,
+ const GrTextureAccess& textureAccess,
+ const char* samplerName,
+ const char* coordName) {
+ GrAssert(samplerName && coordName);
+ SkString sampler = build_sampler_string(samplerMode);
+ SkString swizzle = build_swizzle_string(textureAccess, fContext.caps());
+
+ fFSCode.appendf("%s( %s, %s)%s;\n", sampler.c_str(), samplerName,
+ coordName, swizzle.c_str());
+}
+
+GrCustomStage::StageKey GrGLShaderBuilder::KeyForTextureAccess(const GrTextureAccess& access,
+ const GrGLCaps& caps) {
+ GrCustomStage::StageKey key = 0;
+ // Assume that swizzle support implies that we never have to modify a shader to adjust
+ // for texture format/swizzle settings.
+ if (caps.textureSwizzleSupport()) {
+ return key;
+ }
+
+ if (texture_requires_alpha_to_red_swizzle(caps, access)) {
+ key = 1;
+ }
+
+ return key;
+}
+
GrGLUniformManager::UniformHandle GrGLShaderBuilder::addUniformArray(uint32_t visibility,
GrSLType type,
const char* name,
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index f110628627..16a11e29a0 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -9,6 +9,7 @@
#define GrGLShaderBuilder_DEFINED
#include "GrAllocator.h"
+#include "GrCustomStage.h"
#include "gl/GrGLShaderVar.h"
#include "gl/GrGLSL.h"
#include "gl/GrGLUniformManager.h"
@@ -55,6 +56,22 @@ public:
void emitDefaultFetch(const char* outColor,
const char* samplerName);
+ /** Emits a texture lookup to the shader code with the form:
+ texture2D{Proj}(samplerName, coordName).swizzle
+ The routine selects the type of texturing based on samplerMode.
+ The generated swizzle state is built based on the format of the texture and the requested
+ swizzle access pattern. */
+ void emitCustomTextureLookup(SamplerMode samplerMode,
+ const GrTextureAccess& textureAccess,
+ const char* samplerName,
+ const char* coordName);
+
+ /** Generates a StageKey for the shader code based on the texture access parameters and the
+ capabilities of the GL context. This is useful for keying the shader programs that may
+ have multiple representations, based on the type/format of textures used. */
+ static GrCustomStage::StageKey KeyForTextureAccess(const GrTextureAccess& access,
+ const GrGLCaps& caps);
+
/** Add a uniform variable to the current program, that has visibilty in one or more shaders.
visibility is a bitfield of ShaderType values indicating from which shaders the uniform
should be accessible. At least one bit must be set. Geometry shader uniforms are not
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 6d6d9167af..c959f66b9a 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -596,12 +596,13 @@ namespace {
void setup_custom_stage(GrGLProgram::Desc::StageDesc* stage,
const GrSamplerState& sampler,
+ const GrGLCaps& caps,
const GrCustomStage** customStages,
GrGLProgram* program, int index) {
const GrCustomStage* customStage = sampler.getCustomStage();
if (customStage) {
const GrProgramStageFactory& factory = customStage->getFactory();
- stage->fCustomStageKey = factory.glStageKey(*customStage);
+ stage->fCustomStageKey = factory.glStageKey(*customStage, caps);
customStages[index] = customStage;
} else {
stage->fCustomStageKey = 0;
@@ -746,7 +747,8 @@ void GrGpuGL::buildProgram(bool isPoints,
}
}
- setup_custom_stage(&stage, sampler, customStages, fCurrentProgram.get(), s);
+ setup_custom_stage(&stage, sampler, this->glCaps(), customStages,
+ fCurrentProgram.get(), s);
} else {
stage.fOptFlags = 0;
diff --git a/src/gpu/gl/GrGpuGL_unittest.cpp b/src/gpu/gl/GrGpuGL_unittest.cpp
index 1a28b9811f..7fd61d9f88 100644
--- a/src/gpu/gl/GrGpuGL_unittest.cpp
+++ b/src/gpu/gl/GrGpuGL_unittest.cpp
@@ -413,7 +413,7 @@ bool GrGpuGL::programUnitTest() {
customStages[s].reset(create_random_effect(&stage, &random, getContext()));
if (NULL != customStages[s]) {
stage.fCustomStageKey =
- customStages[s]->getFactory().glStageKey(*customStages[s]);
+ customStages[s]->getFactory().glStageKey(*customStages[s], this->glCaps());
}
}
}