diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-04 18:34:30 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2013-01-04 18:34:30 +0000 |
commit | 34cccde630fc618649b9737bee464203d042bfbb (patch) | |
tree | eab2cbb6ebc20e68af3bcfe628fc37aa21e59d7a /src/gpu | |
parent | 6eb549e8ca3d88d7536859fd5aa3343fc3011f2f (diff) |
Allow GrEffects with multiple textures.
It will work as long as the total number of textures sis less than GrDrawState::kNumStages. That will be fixed in a follow up CL.
Review URL: https://codereview.appspot.com/7040052
git-svn-id: http://skia.googlecode.com/svn/trunk@7023 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/effects/GrSingleTextureEffect.h | 9 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 178 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 91 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.cpp | 36 | ||||
-rw-r--r-- | src/gpu/gl/GrGLShaderBuilder.h | 39 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.cpp | 47 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL.h | 18 | ||||
-rw-r--r-- | src/gpu/gl/GrGpuGL_program.cpp | 32 |
8 files changed, 208 insertions, 242 deletions
diff --git a/src/gpu/effects/GrSingleTextureEffect.h b/src/gpu/effects/GrSingleTextureEffect.h index 709d3dcd2b..a2f8bfff35 100644 --- a/src/gpu/effects/GrSingleTextureEffect.h +++ b/src/gpu/effects/GrSingleTextureEffect.h @@ -10,9 +10,9 @@ #include "GrEffect.h" #include "SkMatrix.h" -#include "GrTexture.h" class GrGLSingleTextureEffect; +class GrTexture; /** * An effect that draws a single texture with a texture matrix; commonly used as a base class. The @@ -48,13 +48,6 @@ public: return INHERITED::isEqual(effect) && fMatrix.cheapEqualTo(ste.getMatrix()); } - static inline SkMatrix MakeDivByTextureWHMatrix(const GrTexture* texture) { - GrAssert(NULL != texture); - SkMatrix mat; - mat.setIDiv(texture->width(), texture->height()); - return mat; - } - private: GR_DECLARE_EFFECT_TEST; diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 0558701322..b57177b8b7 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -10,6 +10,7 @@ #include "GrAllocator.h" #include "GrEffect.h" #include "GrGLEffect.h" +#include "GrGpuGL.h" #include "GrGLShaderVar.h" #include "GrBackendEffectFactory.h" #include "SkTrace.h" @@ -32,16 +33,6 @@ inline void tex_attr_name(int coordIdx, SkString* s) { s->appendS32(coordIdx); } -inline const char* float_vector_type_str(int count) { - return GrGLShaderVar::TypeString(GrSLFloatVectorType(count)); -} - -inline const char* vector_all_coords(int count) { - static const char* ALL[] = {"ERROR", "", ".xy", ".xyz", ".xyzw"}; - GrAssert(count >= 1 && count < (int)GR_ARRAY_COUNT(ALL)); - return ALL[count]; -} - inline const char* declared_color_output_name() { return "fsColorOut"; } inline const char* dual_source_output_name() { return "dualSourceOut"; } @@ -126,12 +117,14 @@ void GrGLProgram::overrideBlend(GrBlendCoeff* srcCoeff, } } +namespace { + // given two blend coeffecients determine whether the src // and/or dst computation can be omitted. -static inline void needBlendInputs(SkXfermode::Coeff srcCoeff, - SkXfermode::Coeff dstCoeff, - bool* needSrcValue, - bool* needDstValue) { +inline void need_blend_inputs(SkXfermode::Coeff srcCoeff, + SkXfermode::Coeff dstCoeff, + bool* needSrcValue, + bool* needDstValue) { if (SkXfermode::kZero_Coeff == srcCoeff) { switch (dstCoeff) { // these all read the src @@ -170,9 +163,9 @@ static inline void needBlendInputs(SkXfermode::Coeff srcCoeff, * Create a blend_coeff * value string to be used in shader code. Sets empty * string if result is trivially zero. */ -static void blendTermString(SkString* str, SkXfermode::Coeff coeff, - const char* src, const char* dst, - const char* value) { +inline void blend_term_string(SkString* str, SkXfermode::Coeff coeff, + const char* src, const char* dst, + const char* value) { switch (coeff) { case SkXfermode::kZero_Coeff: /** 0 */ *str = ""; @@ -213,19 +206,20 @@ static void blendTermString(SkString* str, SkXfermode::Coeff coeff, * Adds a line to the fragment shader code which modifies the color by * the specified color filter. */ -static void addColorFilter(SkString* fsCode, const char * outputVar, - SkXfermode::Coeff uniformCoeff, - SkXfermode::Coeff colorCoeff, - const char* filterColor, - const char* inColor) { +void add_color_filter(SkString* fsCode, const char * outputVar, + SkXfermode::Coeff uniformCoeff, + SkXfermode::Coeff colorCoeff, + const char* filterColor, + const char* inColor) { SkString colorStr, constStr; - blendTermString(&colorStr, colorCoeff, filterColor, inColor, inColor); - blendTermString(&constStr, uniformCoeff, filterColor, inColor, filterColor); + blend_term_string(&colorStr, colorCoeff, filterColor, inColor, inColor); + blend_term_string(&constStr, uniformCoeff, filterColor, inColor, filterColor); fsCode->appendf("\t%s = ", outputVar); GrGLSLAdd4f(fsCode, colorStr.c_str(), constStr.c_str()); fsCode->append(";\n"); } +} bool GrGLProgram::genEdgeCoverage(SkString* coverageVar, GrGLShaderBuilder* builder) const { @@ -308,8 +302,8 @@ void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) { } break; case GrGLProgram::Desc::kUniform_ColorInput: { const char* name; - fUniforms.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, "Color", &name); + fUniformHandles.fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, + kVec4f_GrSLType, "Color", &name); *inColor = name; break; } @@ -326,8 +320,8 @@ void GrGLProgram::genInputColor(GrGLShaderBuilder* builder, SkString* inColor) { void GrGLProgram::genUniformCoverage(GrGLShaderBuilder* builder, SkString* inOutCoverage) { const char* covUniName; - fUniforms.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, "Coverage", &covUniName); + fUniformHandles.fCoverageUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, + kVec4f_GrSLType, "Coverage", &covUniName); if (inOutCoverage->size()) { builder->fFSCode.appendf("\tvec4 uniCoverage = %s * %s;\n", covUniName, inOutCoverage->c_str()); @@ -542,8 +536,8 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { bool needColorFilterUniform; bool needComputedColor; - needBlendInputs(uniformCoeff, colorCoeff, - &needColorFilterUniform, &needComputedColor); + need_blend_inputs(uniformCoeff, colorCoeff, + &needColorFilterUniform, &needComputedColor); // the dual source output has no canonical var name, have to // declare an output, which is incompatible with gl_FragColor/gl_FragData. @@ -560,8 +554,8 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { } const char* viewMName; - fUniforms.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, - kMat33f_GrSLType, "ViewM", &viewMName); + fUniformHandles.fViewMatrixUni = builder.addUniform(GrGLShaderBuilder::kVertex_ShaderType, + kMat33f_GrSLType, "ViewM", &viewMName); builder.fVSCode.appendf("\tvec3 pos3 = %s * vec3(%s, 1);\n" @@ -617,13 +611,12 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { } builder.setCurrentStage(s); - fEffects[s] = GenStageCode(*stages[s], - fDesc.fEffectKeys[s], - &fUniforms.fStages[s], - inColor.size() ? inColor.c_str() : NULL, - outColor.c_str(), - inCoords, - &builder); + fEffects[s] = builder.createAndEmitGLEffect(*stages[s], + fDesc.fEffectKeys[s], + inColor.size() ? inColor.c_str() : NULL, + outColor.c_str(), + inCoords, + &fUniformHandles.fSamplerUnis[s]); builder.setNonStage(); inColor = outColor; } @@ -639,15 +632,16 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { if (uniformCoeffIsZero) { uniformCoeff = SkXfermode::kZero_Coeff; bool bogus; - needBlendInputs(SkXfermode::kZero_Coeff, colorCoeff, - &needColorFilterUniform, &bogus); + need_blend_inputs(SkXfermode::kZero_Coeff, colorCoeff, + &needColorFilterUniform, &bogus); } } const char* colorFilterColorUniName = NULL; if (needColorFilterUniform) { - fUniforms.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_ShaderType, - kVec4f_GrSLType, "FilterColor", - &colorFilterColorUniName); + fUniformHandles.fColorFilterUni = builder.addUniform( + GrGLShaderBuilder::kFragment_ShaderType, + kVec4f_GrSLType, "FilterColor", + &colorFilterColorUniName); } bool wroteFragColorZero = false; if (SkXfermode::kZero_Coeff == uniformCoeff && @@ -659,7 +653,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { } else if (SkXfermode::kDst_Mode != fDesc.fColorFilterXfermode) { builder.fFSCode.append("\tvec4 filteredColor;\n"); const char* color = adjustInColor(inColor); - addColorFilter(&builder.fFSCode, "filteredColor", uniformCoeff, + add_color_filter(&builder.fFSCode, "filteredColor", uniformCoeff, colorCoeff, colorFilterColorUniName, color); inColor = "filteredColor"; } @@ -722,13 +716,13 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { inCoverage.append("4"); } builder.setCurrentStage(s); - fEffects[s] = GenStageCode(*stages[s], - fDesc.fEffectKeys[s], - &fUniforms.fStages[s], - inCoverage.size() ? inCoverage.c_str() : NULL, - outCoverage.c_str(), - inCoords, - &builder); + fEffects[s] = builder.createAndEmitGLEffect( + *stages[s], + fDesc.fEffectKeys[s], + inCoverage.size() ? inCoverage.c_str() : NULL, + outCoverage.c_str(), + inCoords, + &fUniformHandles.fSamplerUnis[s]); builder.setNonStage(); inCoverage = outCoverage; } @@ -803,7 +797,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* stages[]) { builder.finished(fProgramID); this->initSamplerUniforms(); - fUniforms.fRTHeight = builder.getRTHeightUniform(); + fUniformHandles.fRTHeightUni = builder.getRTHeightUniform(); return true; } @@ -874,72 +868,48 @@ bool GrGLProgram::bindOutputsAttribsAndLinkProgram(const GrGLShaderBuilder& buil void GrGLProgram::initSamplerUniforms() { GL_CALL(UseProgram(fProgramID)); + // We simply bind the uniforms to successive texture units beginning at 0. setData() assumes this + // behavior. + GrGLint texUnitIdx = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { - int count = fUniforms.fStages[s].fSamplerUniforms.count(); - // FIXME: We're still always reserving one texture per stage. After GrTextureParams are - // expressed by the effect rather than the GrEffectStage we can move texture binding - // into GrGLProgram and it should be easier to fix this. - GrAssert(count <= 1); - for (int t = 0; t < count; ++t) { - UniformHandle uh = fUniforms.fStages[s].fSamplerUniforms[t]; - if (GrGLUniformManager::kInvalidUniformHandle != uh) { - fUniformManager.setSampler(uh, s); + int numSamplers = fUniformHandles.fSamplerUnis[s].count(); + for (int u = 0; u < numSamplers; ++u) { + UniformHandle handle = fUniformHandles.fSamplerUnis[s][u]; + if (GrGLUniformManager::kInvalidUniformHandle != handle) { + fUniformManager.setSampler(handle, texUnitIdx); + ++texUnitIdx; } } } } /////////////////////////////////////////////////////////////////////////////// -// Stage code generation - -// TODO: Move this function to GrGLShaderBuilder -GrGLEffect* GrGLProgram::GenStageCode(const GrEffectStage& stage, - GrGLEffect::EffectKey key, - StageUniforms* uniforms, - const char* fsInColor, // NULL means no incoming color - const char* fsOutColor, - const char* vsInCoord, - GrGLShaderBuilder* builder) { - - const GrEffect* effect = stage.getEffect(); - GrGLEffect* glEffect = effect->getFactory().createGLInstance(*effect); - - // setup texture samplers for GL effect - int numTextures = effect->numTextures(); - SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; - textureSamplers.push_back_n(numTextures); - for (int i = 0; i < numTextures; ++i) { - textureSamplers[i].init(builder, &effect->textureAccess(i)); - uniforms->fSamplerUniforms.push_back(textureSamplers[i].fSamplerUniform); - } - - // Enclose custom code in a block to avoid namespace conflicts - builder->fVSCode.appendf("\t{ // %s\n", glEffect->name()); - builder->fFSCode.appendf("\t{ // %s \n", glEffect->name()); - glEffect->emitCode(builder, - stage, - key, - vsInCoord, - fsOutColor, - fsInColor, - textureSamplers); - builder->fVSCode.appendf("\t}\n"); - builder->fFSCode.appendf("\t}\n"); - - return glEffect; -} -void GrGLProgram::setData(const GrDrawState& drawState) { +void GrGLProgram::setData(GrGpuGL* gpu) { + const GrDrawState& drawState = gpu->getDrawState(); + int rtHeight = drawState.getRenderTarget()->height(); - if (GrGLUniformManager::kInvalidUniformHandle != fUniforms.fRTHeight && fRTHeight != rtHeight) { - fUniformManager.set1f(fUniforms.fRTHeight, SkIntToScalar(rtHeight)); + if (GrGLUniformManager::kInvalidUniformHandle != fUniformHandles.fRTHeightUni && + fRTHeight != rtHeight) { + fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(rtHeight)); fRTHeight = rtHeight; } + GrGLint texUnitIdx = 0; for (int s = 0; s < GrDrawState::kNumStages; ++s) { if (NULL != fEffects[s]) { const GrEffectStage& stage = drawState.getStage(s); GrAssert(NULL != stage.getEffect()); fEffects[s]->setData(fUniformManager, stage); + int numSamplers = fUniformHandles.fSamplerUnis[s].count(); + for (int u = 0; u < numSamplers; ++u) { + UniformHandle handle = fUniformHandles.fSamplerUnis[s][u]; + if (GrGLUniformManager::kInvalidUniformHandle != handle) { + const GrTextureAccess& access = stage.getEffect()->textureAccess(u); + GrGLTexture* texture = static_cast<GrGLTexture*>(access.getTexture()); + gpu->bindTexture(texUnitIdx, access.getParams(), texture); + ++texUnitIdx; + } + } } } -} +}
\ No newline at end of file diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index 3902a8c028..e334391b67 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -48,7 +48,9 @@ public: virtual ~GrGLProgram(); - /** Call to abandon GL objects owned by this program */ + /** + * Call to abandon GL objects owned by this program. + */ void abandon(); /** @@ -68,10 +70,11 @@ public: static int TexCoordAttributeIdx(int tcIdx) { return 4 + tcIdx; } /** - * This function uploads uniforms and calls each GrEffect's setData. It is called before a draw - * occurs using the program after the program has already been bound. + * This function uploads uniforms and calls each GrGLEffect's setData. It is called before a + * draw occurs using the program after the program has already been bound. It also uses the + * GrGpuGL object to bind the textures required by the GrGLEffects. */ - void setData(const GrDrawState& drawState); + void setData(GrGpuGL*); // Parameters that affect code generation // This structs should be kept compact; it is input to an expensive hash key generator. @@ -114,30 +117,24 @@ public: bool fDiscardIfOutsideEdge; // stripped of bits that don't affect program generation - GrVertexLayout fVertexLayout; + GrVertexLayout fVertexLayout; /** Non-zero if this stage has an effect */ - GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages]; + GrGLEffect::EffectKey fEffectKeys[GrDrawState::kNumStages]; // To enable experimental geometry shader code (not for use in // production) #if GR_GL_EXPERIMENTAL_GS - bool fExperimentalGS; + bool fExperimentalGS; #endif - - uint8_t fColorInput; // casts to enum ColorInput - uint8_t fCoverageInput; // casts to enum CoverageInput - uint8_t fDualSrcOutput; // casts to enum DualSrcOutput - int8_t fFirstCoverageStage; - SkBool8 fEmitsPointSize; - - uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode + uint8_t fColorInput; // casts to enum ColorInput + uint8_t fCoverageInput; // casts to enum ColorInput + uint8_t fDualSrcOutput; // casts to enum DualSrcOutput + int8_t fFirstCoverageStage; + SkBool8 fEmitsPointSize; + uint8_t fColorFilterXfermode; // casts to enum SkXfermode::Mode }; - GR_STATIC_ASSERT(!(sizeof(Desc) % 4)); - private: - struct StageUniforms; - GrGLProgram(const GrGLContextInfo& gl, const Desc& desc, const GrEffectStage* stages[]); @@ -151,14 +148,6 @@ private: void genInputColor(GrGLShaderBuilder* builder, SkString* inColor); - static GrGLEffect* GenStageCode(const GrEffectStage& stage, - GrGLEffect::EffectKey key, - StageUniforms* stageUniforms, // TODO: Eliminate this - const char* fsInColor, // NULL means no incoming color - const char* fsOutColor, - const char* vsInCoord, - GrGLShaderBuilder* builder); - void genGeometryShader(GrGLShaderBuilder* segments) const; typedef GrGLUniformManager::UniformHandle UniformHandle; @@ -183,41 +172,39 @@ private: const char* adjustInColor(const SkString& inColor) const; - struct StageUniforms { - SkTArray<UniformHandle, true> fSamplerUniforms; - }; - - struct Uniforms { - UniformHandle fViewMatrixUni; - UniformHandle fColorUni; - UniformHandle fCoverageUni; - UniformHandle fColorFilterUni; + typedef SkSTArray<4, UniformHandle, true> SamplerUniSArray; + + struct UniformHandles { + UniformHandle fViewMatrixUni; + UniformHandle fColorUni; + UniformHandle fCoverageUni; + UniformHandle fColorFilterUni; // We use the render target height to provide a y-down frag coord when specifying // origin_upper_left is not supported. - UniformHandle fRTHeight; - StageUniforms fStages[GrDrawState::kNumStages]; - Uniforms() { + UniformHandle fRTHeightUni; + // An array of sampler uniform handles for each effect. + SamplerUniSArray fSamplerUnis[GrDrawState::kNumStages]; + + UniformHandles() { fViewMatrixUni = GrGLUniformManager::kInvalidUniformHandle; fColorUni = GrGLUniformManager::kInvalidUniformHandle; fCoverageUni = GrGLUniformManager::kInvalidUniformHandle; fColorFilterUni = GrGLUniformManager::kInvalidUniformHandle; - fRTHeight = GrGLUniformManager::kInvalidUniformHandle; + fRTHeightUni = GrGLUniformManager::kInvalidUniformHandle; } }; - // IDs - GrGLuint fVShaderID; - GrGLuint fGShaderID; - GrGLuint fFShaderID; - GrGLuint fProgramID; - + // GL IDs + GrGLuint fVShaderID; + GrGLuint fGShaderID; + GrGLuint fFShaderID; + GrGLuint fProgramID; // The matrix sent to GL is determined by both the client's matrix and // the size of the viewport. - SkMatrix fViewMatrix; - SkISize fViewportSize; + SkMatrix fViewMatrix; + SkISize fViewportSize; - // these reflect the current values of uniforms - // (GL uniform values travel with program) + // these reflect the current values of uniforms (GL uniform values travel with program) GrColor fColor; GrColor fCoverage; GrColor fColorFilterColor; @@ -225,11 +212,11 @@ private: GrGLEffect* fEffects[GrDrawState::kNumStages]; - Desc fDesc; + Desc fDesc; const GrGLContextInfo& fContextInfo; GrGLUniformManager fUniformManager; - Uniforms fUniforms; + UniformHandles fUniformHandles; friend class GrGpuGL; // TODO: remove this by adding getters and moving functionality. diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp index 8239740128..c00cf91686 100644 --- a/src/gpu/gl/GrGLShaderBuilder.cpp +++ b/src/gpu/gl/GrGLShaderBuilder.cpp @@ -412,3 +412,39 @@ void GrGLShaderBuilder::getShader(ShaderType type, SkString* shaderStr) const { void GrGLShaderBuilder::finished(GrGLuint programID) { fUniformManager.getUniformLocations(programID, fUniforms); } + +GrGLEffect* GrGLShaderBuilder::createAndEmitGLEffect( + const GrEffectStage& stage, + GrGLEffect::EffectKey key, + const char* fsInColor, + const char* fsOutColor, + const char* vsInCoord, + SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles) { + GrAssert(NULL != stage.getEffect()); + + const GrEffect& effect = *stage.getEffect(); + int numTextures = effect.numTextures(); + SkSTArray<8, GrGLShaderBuilder::TextureSampler> textureSamplers; + textureSamplers.push_back_n(numTextures); + for (int i = 0; i < numTextures; ++i) { + textureSamplers[i].init(this, &effect.textureAccess(i), i); + samplerHandles->push_back(textureSamplers[i].fSamplerUniform); + } + + GrGLEffect* glEffect = effect.getFactory().createGLInstance(effect); + + // Enclose custom code in a block to avoid namespace conflicts + this->fVSCode.appendf("\t{ // %s\n", glEffect->name()); + this->fFSCode.appendf("\t{ // %s \n", glEffect->name()); + glEffect->emitCode(this, + stage, + key, + vsInCoord, + fsOutColor, + fsInColor, + textureSamplers); + this->fVSCode.appendf("\t}\n"); + this->fFSCode.appendf("\t}\n"); + + return glEffect; +} diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h index 852079a09e..8934280cd0 100644 --- a/src/gpu/gl/GrGLShaderBuilder.h +++ b/src/gpu/gl/GrGLShaderBuilder.h @@ -11,7 +11,6 @@ #include "GrAllocator.h" #include "GrBackendEffectFactory.h" #include "GrEffect.h" -#include "gl/GrGLShaderVar.h" #include "gl/GrGLSL.h" #include "gl/GrGLUniformManager.h" @@ -24,7 +23,7 @@ class GrGLContextInfo; class GrGLShaderBuilder { public: /** - * Used by GrGLEffects to add texture reads to their shader code. + * Passed to GrGLEffects to add texture reads to their shader code. */ class TextureSampler { public: @@ -46,15 +45,19 @@ public: const GrTextureAccess* textureAccess() const { return fTextureAccess; } private: - void init(GrGLShaderBuilder* builder, const GrTextureAccess* access) { + // The idx param is used to ensure multiple samplers within a single effect have unique + // uniform names. + void init(GrGLShaderBuilder* builder, const GrTextureAccess* access, int idx) { GrAssert(NULL == fTextureAccess); GrAssert(GrGLUniformManager::kInvalidUniformHandle == fSamplerUniform); GrAssert(NULL != builder); GrAssert(NULL != access); + SkString name; + name.printf("Sampler%d_", idx); fSamplerUniform = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType, kSampler2D_GrSLType, - "Sampler"); + name.c_str()); GrAssert(GrGLUniformManager::kInvalidUniformHandle != fSamplerUniform); fTextureAccess = access; @@ -160,25 +163,31 @@ public: */ const GrGLShaderVar& positionAttribute() const { return *fPositionVar; } - /** Called after building is complete to get the final shader string. */ - void getShader(ShaderType, SkString*) const; - /** - * TODO: Make this do all the compiling, linking, etc. Hide from the GrEffects + * Interfaces used by GrGLProgram. + * TODO: Hide these from the GrEffects using friend or splitting this into two related classes. + * Also, GrGLProgram's shader string construction should be moved to this class. */ - void finished(GrGLuint programID); - /** - * Sets the current stage (used to make variable names unique). - * TODO: Hide from the GrEffects - */ + /** Called after building is complete to get the final shader string. */ + void getShader(ShaderType, SkString*) const; + void setCurrentStage(int stageIdx) { fCurrentStageIdx = stageIdx; } void setNonStage() { fCurrentStageIdx = kNonStageIdx; } - + // TODO: move remainder of shader code generation to this class and call this privately + // Handles of sampler uniforms generated for the effect are appended to samplerHandles. + GrGLEffect* createAndEmitGLEffect( + const GrEffectStage& stage, + GrBackendEffectFactory::EffectKey key, + const char* fsInColor, // NULL means no incoming color + const char* fsOutColor, + const char* vsInCoord, + SkTArray<GrGLUniformManager::UniformHandle, true>* samplerHandles); GrGLUniformManager::UniformHandle getRTHeightUniform() const { return fRTHeightUniform; } + // TODO: Make this do all the compiling, linking, etc. + void finished(GrGLuint programID); private: - typedef GrTAllocator<GrGLShaderVar> VarArray; void appendDecls(const VarArray&, SkString*) const; diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp index f01fd3f082..6e39637c02 100644 --- a/src/gpu/gl/GrGpuGL.cpp +++ b/src/gpu/gl/GrGpuGL.cpp @@ -2024,43 +2024,25 @@ inline GrGLenum tile_to_gl_wrap(SkShader::TileMode tm) { } -void GrGpuGL::flushBoundTextureAndParams(int stageIdx) { - GrDrawState* drawState = this->drawState(); - // FIXME: Assuming at most one texture per effect - const GrEffect* effect = drawState->stage(stageIdx)->getEffect(); - if (effect->numTextures() > 0) { - GrGLTexture* nextTexture = static_cast<GrGLTexture*>(effect->texture(0)); - if (NULL != nextTexture) { - const GrTextureParams& texParams = effect->textureAccess(0).getParams(); - this->flushBoundTextureAndParams(stageIdx, texParams, nextTexture); - } - } -} - -void GrGpuGL::flushBoundTextureAndParams(int stageIdx, - const GrTextureParams& params, - GrGLTexture* nextTexture) { +void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture) { + GrAssert(NULL != texture); - // true for now, but maybe not with GrEffect. - GrAssert(NULL != nextTexture); // If we created a rt/tex and rendered to it without using a texture and now we're texturing // from the rt it will still be the last bound texture, but it needs resolving. So keep this // out of the "last != next" check. - GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(nextTexture->asRenderTarget()); + GrGLRenderTarget* texRT = static_cast<GrGLRenderTarget*>(texture->asRenderTarget()); if (NULL != texRT) { this->onResolveRenderTarget(texRT); } - if (fHWBoundTextures[stageIdx] != nextTexture) { - this->setTextureUnit(stageIdx); - GL_CALL(BindTexture(GR_GL_TEXTURE_2D, nextTexture->textureID())); - //GrPrintf("---- bindtexture %d\n", nextTexture->textureID()); - fHWBoundTextures[stageIdx] = nextTexture; + if (fHWBoundTextures[unitIdx] != texture) { + this->setTextureUnit(unitIdx); + GL_CALL(BindTexture(GR_GL_TEXTURE_2D, texture->textureID())); + fHWBoundTextures[unitIdx] = texture; } ResetTimestamp timestamp; - const GrGLTexture::TexParams& oldTexParams = - nextTexture->getCachedTexParams(×tamp); + const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(×tamp); bool setAll = timestamp < this->getResetTimestamp(); GrGLTexture::TexParams newTexParams; @@ -2069,10 +2051,10 @@ void GrGpuGL::flushBoundTextureAndParams(int stageIdx, newTexParams.fWrapS = tile_to_gl_wrap(params.getTileModeX()); newTexParams.fWrapT = tile_to_gl_wrap(params.getTileModeY()); memcpy(newTexParams.fSwizzleRGBA, - GrGLShaderBuilder::GetTexParamSwizzle(nextTexture->config(), this->glCaps()), + GrGLShaderBuilder::GetTexParamSwizzle(texture->config(), this->glCaps()), sizeof(newTexParams.fSwizzleRGBA)); if (setAll || newTexParams.fFilter != oldTexParams.fFilter) { - this->setTextureUnit(stageIdx); + this->setTextureUnit(unitIdx); GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_MAG_FILTER, newTexParams.fFilter)); @@ -2081,13 +2063,13 @@ void GrGpuGL::flushBoundTextureAndParams(int stageIdx, newTexParams.fFilter)); } if (setAll || newTexParams.fWrapS != oldTexParams.fWrapS) { - this->setTextureUnit(stageIdx); + this->setTextureUnit(unitIdx); GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_S, newTexParams.fWrapS)); } if (setAll || newTexParams.fWrapT != oldTexParams.fWrapT) { - this->setTextureUnit(stageIdx); + this->setTextureUnit(unitIdx); GL_CALL(TexParameteri(GR_GL_TEXTURE_2D, GR_GL_TEXTURE_WRAP_T, newTexParams.fWrapT)); @@ -2096,12 +2078,11 @@ void GrGpuGL::flushBoundTextureAndParams(int stageIdx, (setAll || memcmp(newTexParams.fSwizzleRGBA, oldTexParams.fSwizzleRGBA, sizeof(newTexParams.fSwizzleRGBA)))) { - this->setTextureUnit(stageIdx); + this->setTextureUnit(unitIdx); set_tex_swizzle(newTexParams.fSwizzleRGBA, this->glInterface()); } - nextTexture->setCachedTexParams(newTexParams, - this->getResetTimestamp()); + texture->setCachedTexParams(newTexParams, this->getResetTimestamp()); } void GrGpuGL::flushMiscFixedFunctionState() { diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h index 33834cf709..97b95d05b5 100644 --- a/src/gpu/gl/GrGpuGL.h +++ b/src/gpu/gl/GrGpuGL.h @@ -36,6 +36,11 @@ public: return fGLContextInfo.glslGeneration(); } + // Used by GrGLProgram to bind necessary textures for GrGLEffects. + void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture); + + bool programUnitTest(); + // GrGpu overrides virtual GrPixelConfig preferredReadPixelsConfig(GrPixelConfig config) const SK_OVERRIDE; @@ -51,9 +56,6 @@ public: virtual void abandonResources() SK_OVERRIDE; - bool programUnitTest(); - - protected: // GrGpu overrides virtual void onResetContext() SK_OVERRIDE; @@ -196,16 +198,6 @@ private: const GrGLContextInfo& fGL; }; - // binds the texture and sets its texture params - // This may also perform a downsample on the src texture which may or may - // not modify the scissor test and rect. So in flushGraphicsState a - // call to flushScissor must occur after all textures have been flushed via - // this function. - void flushBoundTextureAndParams(int stage); - void flushBoundTextureAndParams(int stage, - const GrTextureParams& params, - GrGLTexture* nextTexture); - // sets the color specified by GrDrawState::setColor() void flushColor(GrColor color); diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp index 5850fc4d69..3d9f0fe726 100644 --- a/src/gpu/gl/GrGpuGL_program.cpp +++ b/src/gpu/gl/GrGpuGL_program.cpp @@ -151,7 +151,9 @@ void GrGpuGL::flushViewMatrix(DrawType type) { SkScalarToFloat(m[SkMatrix::kMTransY]), SkScalarToFloat(m[SkMatrix::kMPersp2]) }; - fCurrentProgram->fUniformManager.setMatrix3f(fCurrentProgram->fUniforms.fViewMatrixUni, mt); + fCurrentProgram->fUniformManager.setMatrix3f( + fCurrentProgram->fUniformHandles.fViewMatrixUni, + mt); fCurrentProgram->fViewMatrix = vm; fCurrentProgram->fViewportSize = viewportSize; } @@ -183,9 +185,10 @@ void GrGpuGL::flushColor(GrColor color) { // OpenGL ES doesn't support unsigned byte varieties of glUniform GrGLfloat c[4]; GrColorToRGBAFloat(color, c); - GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniforms.fColorUni); - fCurrentProgram->fUniformManager.set4fv(fCurrentProgram->fUniforms.fColorUni, - 0, 1, c); + GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniformHandles.fColorUni); + fCurrentProgram->fUniformManager.set4fv( + fCurrentProgram->fUniformHandles.fColorUni, + 0, 1, c); fCurrentProgram->fColor = color; } break; @@ -196,7 +199,7 @@ void GrGpuGL::flushColor(GrColor color) { GrCrash("Unknown color type."); } } - UniformHandle filterColorUni = fCurrentProgram->fUniforms.fColorFilterUni; + UniformHandle filterColorUni = fCurrentProgram->fUniformHandles.fColorFilterUni; if (kInvalidUniformHandle != filterColorUni && fCurrentProgram->fColorFilterColor != drawState.getColorFilterColor()) { GrGLfloat c[4]; @@ -234,9 +237,11 @@ void GrGpuGL::flushCoverage(GrColor coverage) { // glUniform GrGLfloat c[4]; GrColorToRGBAFloat(coverage, c); - GrAssert(kInvalidUniformHandle != fCurrentProgram->fUniforms.fCoverageUni); - fCurrentProgram->fUniformManager.set4fv(fCurrentProgram->fUniforms.fCoverageUni, - 0, 1, c); + GrAssert(kInvalidUniformHandle != + fCurrentProgram->fUniformHandles.fCoverageUni); + fCurrentProgram->fUniformManager.set4fv( + fCurrentProgram->fUniformHandles.fCoverageUni, + 0, 1, c); fCurrentProgram->fCoverage = coverage; } break; @@ -302,13 +307,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { this->flushColor(color); this->flushCoverage(coverage); - fCurrentProgram->setData(drawState); - - for (int s = 0; s < GrDrawState::kNumStages; ++s) { - if (this->isStageEnabled(s)) { - this->flushBoundTextureAndParams(s); - } - } + fCurrentProgram->setData(this); } this->flushStencil(type); this->flushViewMatrix(type); @@ -318,8 +317,7 @@ bool GrGpuGL::flushGraphicsState(DrawType type) { GrIRect* devRect = NULL; GrIRect devClipBounds; if (drawState.isClipState()) { - fClip->getConservativeBounds(drawState.getRenderTarget(), - &devClipBounds); + fClip->getConservativeBounds(drawState.getRenderTarget(), &devClipBounds); devRect = &devClipBounds; } // This must come after textures are flushed because a texture may need |