aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-01-04 18:34:30 +0000
committerGravatar bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-01-04 18:34:30 +0000
commit34cccde630fc618649b9737bee464203d042bfbb (patch)
treeeab2cbb6ebc20e68af3bcfe628fc37aa21e59d7a /src/gpu
parent6eb549e8ca3d88d7536859fd5aa3343fc3011f2f (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.h9
-rw-r--r--src/gpu/gl/GrGLProgram.cpp178
-rw-r--r--src/gpu/gl/GrGLProgram.h91
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp36
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h39
-rw-r--r--src/gpu/gl/GrGpuGL.cpp47
-rw-r--r--src/gpu/gl/GrGpuGL.h18
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp32
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(&timestamp);
+ const GrGLTexture::TexParams& oldTexParams = texture->getCachedTexParams(&timestamp);
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