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
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 0558701..b57177b 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 @@
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 @@
}
}
+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 @@
* 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 @@
* 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 @@
} 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::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 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 @@
}
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 @@
}
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 @@
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 @@
} 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 @@
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 @@
builder.finished(fProgramID);
this->initSamplerUniforms();
- fUniforms.fRTHeight = builder.getRTHeightUniform();
+ fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
return true;
}
@@ -874,72 +868,48 @@
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) {
+void GrGLProgram::setData(GrGpuGL* gpu) {
+ const GrDrawState& drawState = gpu->getDrawState();
- 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) {
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