diff options
Diffstat (limited to 'src/gpu/gl')
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramStage.cpp | 11 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgramStage.h | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.cpp | 73 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.h | 17 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 6 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_unittest.cpp | 2 |
7 files changed, 109 insertions, 4 deletions
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()); } } } |