aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/gpu/gl/GrGLProgram.cpp106
-rw-r--r--src/gpu/gl/GrGLProgram.h9
-rw-r--r--src/gpu/gl/GrGLProgramDesc.h1
-rw-r--r--src/gpu/gl/GrGLProgramEffects.cpp452
-rw-r--r--src/gpu/gl/GrGLProgramEffects.h174
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.cpp33
-rw-r--r--src/gpu/gl/GrGLShaderBuilder.h22
-rw-r--r--src/gpu/gl/GrGpuGL.cpp125
-rw-r--r--src/gpu/gl/GrGpuGL.h24
-rw-r--r--src/gpu/gl/GrGpuGL_program.cpp81
-rw-r--r--tests/GLProgramsTest.cpp9
11 files changed, 767 insertions, 269 deletions
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index 4fe7a2b7c9..1ca61e3748 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -39,7 +39,9 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[])
: fGpu(gpu)
-, fUniformManager(gpu) {
+, fUniformManager(gpu)
+, fHasVertexShader(false)
+, fNumTexCoordSets(0) {
fDesc = desc;
fProgramID = 0;
@@ -48,7 +50,21 @@ GrGLProgram::GrGLProgram(GrGpuGL* gpu,
fColor = GrColor_ILLEGAL;
fColorFilterColor = GrColor_ILLEGAL;
- this->genProgram(colorStages, coverageStages);
+ if (fDesc.getHeader().fHasVertexCode ||
+ !fGpu->glCaps().fixedFunctionSupport() ||
+ !fGpu->glCaps().pathStencilingSupport()) {
+
+ GrGLFullShaderBuilder fullBuilder(fGpu, fUniformManager, fDesc);
+ if (this->genProgram(&fullBuilder, colorStages, coverageStages)) {
+ fUniformHandles.fViewMatrixUni = fullBuilder.getViewMatrixUniform();
+ fHasVertexShader = true;
+ }
+ } else {
+ GrGLFragmentOnlyShaderBuilder fragmentOnlyBuilder(fGpu, fUniformManager, fDesc);
+ if (this->genProgram(&fragmentOnlyBuilder, colorStages, coverageStages)) {
+ fNumTexCoordSets = fragmentOnlyBuilder.getNumTexCoordSets();
+ }
+ }
}
GrGLProgram::~GrGLProgram() {
@@ -205,18 +221,16 @@ void expand_known_value4f(SkString* string, GrSLConstantVec vec) {
}
-bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
+bool GrGLProgram::genProgram(GrGLShaderBuilder* builder,
+ const GrEffectStage* colorStages[],
const GrEffectStage* coverageStages[]) {
SkASSERT(0 == fProgramID);
const GrGLProgramDesc::KeyHeader& header = fDesc.getHeader();
- GrGLFullShaderBuilder builder(fGpu, fUniformManager, fDesc);
- fUniformHandles.fViewMatrixUni = builder.getViewMatrixUniform();
-
// incoming color to current stage being processed.
- SkString inColor = builder.getInputColor();
- GrSLConstantVec knownColorValue = builder.getKnownColorValue();
+ SkString inColor = builder->getInputColor();
+ GrSLConstantVec knownColorValue = builder->getKnownColorValue();
// Get the coeffs for the Mode-based color filter, determine if color is needed.
SkXfermode::Coeff colorCoeff;
@@ -229,20 +243,20 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
need_blend_inputs(filterColorCoeff, colorCoeff, &needFilterColor, &needColor);
fColorEffects.reset(
- builder.createAndEmitEffects(colorStages,
- fDesc.effectKeys(),
- needColor ? fDesc.numColorEffects() : 0,
- &inColor,
- &knownColorValue));
+ builder->createAndEmitEffects(colorStages,
+ fDesc.effectKeys(),
+ needColor ? fDesc.numColorEffects() : 0,
+ &inColor,
+ &knownColorValue));
// Insert the color filter. This will soon be replaced by a color effect.
if (SkXfermode::kDst_Mode != header.fColorFilterXfermode) {
const char* colorFilterColorUniName = NULL;
- fUniformHandles.fColorFilterUni = builder.addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kVec4f_GrSLType, "FilterColor",
- &colorFilterColorUniName);
+ fUniformHandles.fColorFilterUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kVec4f_GrSLType, "FilterColor",
+ &colorFilterColorUniName);
- builder.fsCodeAppend("\tvec4 filteredColor;\n");
+ builder->fsCodeAppend("\tvec4 filteredColor;\n");
const char* color;
// add_color_filter requires a real input string.
if (knownColorValue == kOnes_GrSLConstantVec) {
@@ -252,36 +266,36 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
} else {
color = inColor.c_str();
}
- add_color_filter(&builder, "filteredColor", filterColorCoeff,
+ add_color_filter(builder, "filteredColor", filterColorCoeff,
colorCoeff, colorFilterColorUniName, color);
inColor = "filteredColor";
}
///////////////////////////////////////////////////////////////////////////
// compute the partial coverage
- SkString inCoverage = builder.getInputCoverage();
- GrSLConstantVec knownCoverageValue = builder.getKnownCoverageValue();
+ SkString inCoverage = builder->getInputCoverage();
+ GrSLConstantVec knownCoverageValue = builder->getKnownCoverageValue();
fCoverageEffects.reset(
- builder.createAndEmitEffects(coverageStages,
- fDesc.getEffectKeys() + fDesc.numColorEffects(),
- fDesc.numCoverageEffects(),
- &inCoverage,
- &knownCoverageValue));
+ builder->createAndEmitEffects(coverageStages,
+ fDesc.getEffectKeys() + fDesc.numColorEffects(),
+ fDesc.numCoverageEffects(),
+ &inCoverage,
+ &knownCoverageValue));
// discard if coverage is zero
if (header.fDiscardIfZeroCoverage && kOnes_GrSLConstantVec != knownCoverageValue) {
if (kZeros_GrSLConstantVec == knownCoverageValue) {
// This is unfortunate.
- builder.fsCodeAppend("\tdiscard;\n");
+ builder->fsCodeAppend("\tdiscard;\n");
} else {
- builder.fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
- inCoverage.c_str());
+ builder->fsCodeAppendf("\tif (all(lessThanEqual(%s, vec4(0.0)))) {\n\t\tdiscard;\n\t}\n",
+ inCoverage.c_str());
}
}
if (GrGLProgramDesc::CoverageOutputUsesSecondaryOutput(header.fCoverageOutput)) {
- const char* secondaryOutputName = builder.enableSecondaryOutput();
+ const char* secondaryOutputName = builder->enableSecondaryOutput();
// default coeff to ones for kCoverage_DualSrcOutput
SkString coeff;
@@ -317,7 +331,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
knownCoeffValue,
knownCoverageValue,
false);
- builder.fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
+ builder->fsCodeAppendf("\t%s = %s;\n", secondaryOutputName, modulate.c_str());
}
///////////////////////////////////////////////////////////////////////////
@@ -343,7 +357,7 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
SkString dstContribution;
GrSLConstantVec knownDstContributionValue = GrGLSLModulatef<4>(&dstContribution,
dstCoeff.c_str(),
- builder.dstColor(),
+ builder->dstColor(),
knownDstCoeffValue,
kNone_GrSLConstantVec,
true);
@@ -358,18 +372,18 @@ bool GrGLProgram::genProgram(const GrEffectStage* colorStages[],
} else {
expand_known_value4f(&fragColor, knownFragColorValue);
}
- builder.fsCodeAppendf("\t%s = %s;\n", builder.getColorOutputName(), fragColor.c_str());
+ builder->fsCodeAppendf("\t%s = %s;\n", builder->getColorOutputName(), fragColor.c_str());
- if (!builder.finish(&fProgramID)) {
+ if (!builder->finish(&fProgramID)) {
return false;
}
- fUniformHandles.fRTHeightUni = builder.getRTHeightUniform();
- fUniformHandles.fDstCopyTopLeftUni = builder.getDstCopyTopLeftUniform();
- fUniformHandles.fDstCopyScaleUni = builder.getDstCopyScaleUniform();
- fUniformHandles.fColorUni = builder.getColorUniform();
- fUniformHandles.fCoverageUni = builder.getCoverageUniform();
- fUniformHandles.fDstCopySamplerUni = builder.getDstCopySamplerUniform();
+ fUniformHandles.fRTHeightUni = builder->getRTHeightUniform();
+ fUniformHandles.fDstCopyTopLeftUni = builder->getDstCopyTopLeftUniform();
+ fUniformHandles.fDstCopyScaleUni = builder->getDstCopyScaleUniform();
+ fUniformHandles.fColorUni = builder->getColorUniform();
+ fUniformHandles.fCoverageUni = builder->getCoverageUniform();
+ fUniformHandles.fDstCopySamplerUni = builder->getDstCopySamplerUniform();
// This must be called after we set fDstCopySamplerUni above.
this->initSamplerUniforms();
@@ -445,6 +459,10 @@ void GrGLProgram::setData(GrDrawState::BlendOptFlags blendOpts,
fColorEffects->setData(fGpu, fUniformManager, colorStages);
fCoverageEffects->setData(fGpu, fUniformManager, coverageStages);
+
+ if (!fHasVertexShader) {
+ fGpu->disableUnusedTexGen(fNumTexCoordSets);
+ }
}
void GrGLProgram::setColor(const GrDrawState& drawState,
@@ -537,9 +555,13 @@ void GrGLProgram::setMatrixAndRenderTargetHeight(const GrDrawState& drawState) {
fUniformManager.set1f(fUniformHandles.fRTHeightUni, SkIntToScalar(size.fHeight));
}
- if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
- !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix()) ||
- fMatrixState.fRenderTargetSize != size) {
+ if (!fHasVertexShader) {
+ SkASSERT(!fUniformHandles.fViewMatrixUni.isValid());
+ fGpu->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
+ } else if (fMatrixState.fRenderTargetOrigin != rt->origin() ||
+ fMatrixState.fRenderTargetSize != size ||
+ !fMatrixState.fViewMatrix.cheapEqualTo(drawState.getViewMatrix())) {
+ SkASSERT(fUniformHandles.fViewMatrixUni.isValid());
fMatrixState.fViewMatrix = drawState.getViewMatrix();
fMatrixState.fRenderTargetSize = size;
diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h
index c8bcbf479e..23ed45602a 100644
--- a/src/gpu/gl/GrGLProgram.h
+++ b/src/gpu/gl/GrGLProgram.h
@@ -62,6 +62,8 @@ public:
*/
GrGLuint programID() const { return fProgramID; }
+ bool hasVertexShader() const { return fHasVertexShader; }
+
/**
* Some GL state that is relevant to programs is not stored per-program. In particular color
* and coverage attributes can be global state. This struct is read and updated by
@@ -160,7 +162,9 @@ private:
* This is the heavy initialization routine for building a GLProgram. colorStages and
* coverageStages correspond to the output of GrGLProgramDesc::Build().
*/
- bool genProgram(const GrEffectStage* colorStages[], const GrEffectStage* coverageStages[]);
+ bool genProgram(GrGLShaderBuilder* builder,
+ const GrEffectStage* colorStages[],
+ const GrEffectStage* coverageStages[]);
// Sets the texture units for samplers
void initSamplerUniforms();
@@ -195,6 +199,9 @@ private:
GrGLUniformManager fUniformManager;
UniformHandles fUniformHandles;
+ bool fHasVertexShader;
+ int fNumTexCoordSets;
+
typedef SkRefCnt INHERITED;
};
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index 0c7c8cf629..46eed09739 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -233,6 +233,7 @@ private:
friend class GrGLProgram;
friend class GrGLShaderBuilder;
friend class GrGLFullShaderBuilder;
+ friend class GrGLFragmentOnlyShaderBuilder;
};
#endif
diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp
index d5826abe30..17c666a015 100644
--- a/src/gpu/gl/GrGLProgramEffects.cpp
+++ b/src/gpu/gl/GrGLProgramEffects.cpp
@@ -37,7 +37,6 @@ enum {
kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1,
kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
kTransformKeyBits = kMatrixTypeKeyBits + 1,
- kTransformKeyMask = (1 << kTransformKeyBits) - 1,
};
namespace {
@@ -69,8 +68,78 @@ inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
return false;
}
+/**
+ * Retrieves the matrix type from transformKey for the transform at transformIdx.
+ */
+MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) {
+ return static_cast<MatrixType>(
+ (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
+}
+
+/**
+ * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
+ * the same coordinate set as the original GrCoordTransform if the position and local coords are
+ * identical for this program.
+ */
+GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) {
+ return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
+ kPosition_GrCoordSet :
+ kLocal_GrCoordSet;
+}
+
+/**
+ * Retrieves the final translation that a transform needs to apply to its source coords (and
+ * verifies that a translation is all it needs).
+ */
+void get_transform_translation(const GrDrawEffect& drawEffect,
+ int transformIdx,
+ GrGLfloat* tx,
+ GrGLfloat* ty) {
+ const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
+ SkASSERT(!coordTransform.reverseY());
+ const SkMatrix& matrix = coordTransform.getMatrix();
+ if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
+ !drawEffect.programHasExplicitLocalCoords()) {
+ const SkMatrix& coordChangeMatrix = drawEffect.getCoordChangeMatrix();
+ SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
+ *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX]);
+ *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY]);
+ } else {
+ SkASSERT(SkMatrix::kTranslate_Mask == matrix.getType());
+ *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
+ *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
+ }
}
+/**
+ * Retrieves the final matrix that a transform needs to apply to its source coords.
+ */
+SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
+ const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
+ SkMatrix combined;
+ if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
+ !drawEffect.programHasExplicitLocalCoords()) {
+ combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
+ } else {
+ combined = coordTransform.getMatrix();
+ }
+ if (coordTransform.reverseY()) {
+ // combined.postScale(1,-1);
+ // combined.postTranslate(0,1);
+ combined.set(SkMatrix::kMSkewY,
+ combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
+ combined.set(SkMatrix::kMScaleY,
+ combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
+ combined.set(SkMatrix::kMTransY,
+ combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
+ }
+ return combined;
+}
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
EffectKey key = 0;
int numAttributes = drawEffect.getVertexAttribIndexCount();
@@ -144,6 +213,23 @@ GrGLProgramEffects::~GrGLProgramEffects() {
}
}
+void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder,
+ const GrEffectRef& effect,
+ TextureSamplerArray* outSamplers) {
+ SkTArray<Sampler, true>& samplers = fSamplers.push_back();
+ int numTextures = effect->numTextures();
+ samplers.push_back_n(numTextures);
+ SkString name;
+ for (int t = 0; t < numTextures; ++t) {
+ name.printf("Sampler%d", t);
+ samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
+ kSampler2D_GrSLType,
+ name.c_str());
+ SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
+ (samplers[t].fUniform, effect->textureAccess(t)));
+ }
+}
+
void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) {
int numEffects = fGLEffects.count();
SkASSERT(numEffects == fSamplers.count());
@@ -158,77 +244,6 @@ void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager,
}
}
-void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
- const GrGLUniformManager& uniformManager,
- const GrEffectStage* effectStages[]) {
- int numEffects = fGLEffects.count();
- SkASSERT(numEffects == fTransforms.count());
- SkASSERT(numEffects == fSamplers.count());
- for (int e = 0; e < numEffects; ++e) {
- GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
- fGLEffects[e]->setData(uniformManager, drawEffect);
- this->setTransformData(uniformManager, drawEffect, e);
- this->bindTextures(gpu, *drawEffect.effect(), e);
- }
-}
-
-void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
- const GrDrawEffect& drawEffect,
- int effectIdx) {
- SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
- int numTransforms = transforms.count();
- SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms());
- for (int t = 0; t < numTransforms; ++t) {
- const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(t);
- const SkMatrix& matrix = coordTransform.getMatrix();
- const SkMatrix& coordChangeMatrix = kLocal_GrCoordSet == coordTransform.sourceCoords() ?
- drawEffect.getCoordChangeMatrix() :
- SkMatrix::I();
- SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType));
- switch (transforms[t].fType) {
- case kVoid_GrSLType:
- SkASSERT(matrix.isIdentity());
- SkASSERT(coordChangeMatrix.isIdentity());
- SkASSERT(!coordTransform.reverseY());
- return;
- case kVec2f_GrSLType: {
- SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
- SkASSERT(!coordTransform.reverseY());
- SkScalar tx = matrix[SkMatrix::kMTransX] + (coordChangeMatrix)[SkMatrix::kMTransX];
- SkScalar ty = matrix[SkMatrix::kMTransY] + (coordChangeMatrix)[SkMatrix::kMTransY];
- if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx ||
- transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) {
- uniformManager.set2f(transforms[t].fHandle, tx, ty);
- transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx);
- transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty);
- }
- break;
- }
- case kMat33f_GrSLType: {
- SkMatrix combined;
- combined.setConcat(matrix, coordChangeMatrix);
- if (coordTransform.reverseY()) {
- // combined.postScale(1,-1);
- // combined.postTranslate(0,1);
- combined.set(SkMatrix::kMSkewY,
- combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
- combined.set(SkMatrix::kMScaleY,
- combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
- combined.set(SkMatrix::kMTransY,
- combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
- }
- if (!transforms[t].fCurrentValue.cheapEqualTo(combined)) {
- uniformManager.setSkMatrix(transforms[t].fHandle, combined);
- transforms[t].fCurrentValue = combined;
- }
- break;
- }
- default:
- GrCrash("Unexpected uniform type.");
- }
- }
-}
-
void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) {
const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
int numSamplers = samplers.count();
@@ -244,75 +259,67 @@ void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, i
////////////////////////////////////////////////////////////////////////////////
-GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
- int reserveCount)
- : fBuilder(builder)
- , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
- (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
-}
-
-void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
- EffectKey key,
- const char* outColor,
- const char* inColor,
- int stageIndex) {
- SkASSERT(NULL != fProgramEffects.get());
-
- GrDrawEffect drawEffect(stage, fProgramEffects->fHasExplicitLocalCoords);
+void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
+ const GrEffectStage& stage,
+ EffectKey key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
const GrEffectRef& effect = *stage.getEffect();
SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
SkSTArray<4, TextureSampler> samplers(effect->numTextures());
- this->emitAttributes(stage);
- this->emitTransforms(effect, key, &coords);
- INHERITED::emitSamplers(fBuilder, fProgramEffects.get(), effect, &samplers);
+ this->emitAttributes(builder, stage);
+ this->emitTransforms(builder, effect, key, &coords);
+ this->emitSamplers(builder, effect, &samplers);
GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
- fProgramEffects->fGLEffects.push_back(glEffect);
+ fGLEffects.push_back(glEffect);
// Enclose custom code in a block to avoid namespace conflicts
SkString openBrace;
openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
- fBuilder->vsCodeAppend(openBrace.c_str());
- fBuilder->fsCodeAppend(openBrace.c_str());
+ builder->vsCodeAppend(openBrace.c_str());
+ builder->fsCodeAppend(openBrace.c_str());
if (glEffect->isVertexEffect()) {
GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
- vertexEffect->emitCode(fBuilder, drawEffect, key, outColor, inColor, coords, samplers);
+ vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
} else {
- glEffect->emitCode(fBuilder, drawEffect, key, outColor, inColor, coords, samplers);
+ glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
}
- fBuilder->vsCodeAppend("\t}\n");
- fBuilder->fsCodeAppend("\t}\n");
+ builder->vsCodeAppend("\t}\n");
+ builder->fsCodeAppend("\t}\n");
}
-void GrGLVertexProgramEffectsBuilder::emitAttributes(const GrEffectStage& stage) {
+void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
+ const GrEffectStage& stage) {
int numAttributes = stage.getVertexAttribIndexCount();
const int* attributeIndices = stage.getVertexAttribIndices();
for (int a = 0; a < numAttributes; ++a) {
// TODO: Make addAttribute mangle the name.
SkString attributeName("aAttr");
attributeName.appendS32(attributeIndices[a]);
- fBuilder->addEffectAttribute(attributeIndices[a],
- (*stage.getEffect())->vertexAttribType(a),
- attributeName);
+ builder->addEffectAttribute(attributeIndices[a],
+ (*stage.getEffect())->vertexAttribType(a),
+ attributeName);
}
}
-void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect,
- EffectKey effectKey,
- TransformedCoordsArray* outCoords) {
- typedef GrGLVertexProgramEffects::Transform Transform;
- SkTArray<Transform, true>& transforms = fProgramEffects->fTransforms.push_back();
+void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
+ const GrEffectRef& effect,
+ EffectKey effectKey,
+ TransformedCoordsArray* outCoords) {
+ SkTArray<Transform, true>& transforms = fTransforms.push_back();
EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
int numTransforms = effect->numTransforms();
transforms.push_back_n(numTransforms);
for (int t = 0; t < numTransforms; t++) {
- EffectKey key = (totalKey >> (kTransformKeyBits * t)) & kTransformKeyMask;
GrSLType varyingType = kVoid_GrSLType;
const char* uniName;
- switch (key & kMatrixTypeKeyMask) {
+ switch (get_matrix_type(totalKey, t)) {
case kIdentity_MatrixType:
transforms[t].fType = kVoid_GrSLType;
uniName = NULL;
@@ -343,10 +350,10 @@ void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect,
suffixedUniName.appendf("_%i", t);
uniName = suffixedUniName.c_str();
}
- transforms[t].fHandle = fBuilder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
- transforms[t].fType,
- uniName,
- &uniName);
+ transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
+ transforms[t].fType,
+ uniName,
+ &uniName);
}
const char* varyingName = "MatrixCoord";
@@ -358,55 +365,222 @@ void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect,
}
const char* vsVaryingName;
const char* fsVaryingName;
- fBuilder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
+ builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
- const GrGLShaderVar& coords = (kPositionCoords_Flag & key) ?
- fBuilder->positionAttribute() :
- fBuilder->localCoordsAttribute();
+ const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
+ builder->positionAttribute() :
+ builder->localCoordsAttribute();
// varying = matrix * coords (logically)
switch (transforms[t].fType) {
case kVoid_GrSLType:
SkASSERT(kVec2f_GrSLType == varyingType);
- fBuilder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str());
+ builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str());
break;
case kVec2f_GrSLType:
SkASSERT(kVec2f_GrSLType == varyingType);
- fBuilder->vsCodeAppendf("\t%s = %s + %s;\n",
- vsVaryingName, uniName, coords.c_str());
+ builder->vsCodeAppendf("\t%s = %s + %s;\n",
+ vsVaryingName, uniName, coords.c_str());
break;
case kMat33f_GrSLType: {
SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
if (kVec2f_GrSLType == varyingType) {
- fBuilder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
- vsVaryingName, uniName, coords.c_str());
+ builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
+ vsVaryingName, uniName, coords.c_str());
} else {
- fBuilder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
- vsVaryingName, uniName, coords.c_str());
+ builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
+ vsVaryingName, uniName, coords.c_str());
}
break;
}
default:
GrCrash("Unexpected uniform type.");
}
- SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (fsVaryingName, varyingType));
+ SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
+ (SkString(fsVaryingName), varyingType));
}
}
-void GrGLProgramEffectsBuilder::emitSamplers(GrGLShaderBuilder* builder,
- GrGLProgramEffects* programEffects,
- const GrEffectRef& effect,
- TextureSamplerArray* outSamplers) {
- typedef GrGLProgramEffects::Sampler Sampler;
- SkTArray<Sampler, true>& samplers = programEffects->fSamplers.push_back();
- int numTextures = effect->numTextures();
- samplers.push_back_n(numTextures);
+void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
+ const GrGLUniformManager& uniformManager,
+ const GrEffectStage* effectStages[]) {
+ int numEffects = fGLEffects.count();
+ SkASSERT(numEffects == fTransforms.count());
+ SkASSERT(numEffects == fSamplers.count());
+ for (int e = 0; e < numEffects; ++e) {
+ GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
+ fGLEffects[e]->setData(uniformManager, drawEffect);
+ this->setTransformData(uniformManager, drawEffect, e);
+ this->bindTextures(gpu, *drawEffect.effect(), e);
+ }
+}
+
+void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
+ const GrDrawEffect& drawEffect,
+ int effectIdx) {
+ SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
+ int numTransforms = transforms.count();
+ SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms());
+ for (int t = 0; t < numTransforms; ++t) {
+ SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType));
+ switch (transforms[t].fType) {
+ case kVoid_GrSLType:
+ SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
+ return;
+ case kVec2f_GrSLType: {
+ GrGLfloat tx, ty;
+ get_transform_translation(drawEffect, t, &tx, &ty);
+ if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx ||
+ transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) {
+ uniformManager.set2f(transforms[t].fHandle, tx, ty);
+ transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx);
+ transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty);
+ }
+ break;
+ }
+ case kMat33f_GrSLType: {
+ const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
+ if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
+ uniformManager.setSkMatrix(transforms[t].fHandle, matrix);
+ transforms[t].fCurrentValue = matrix;
+ }
+ break;
+ }
+ default:
+ GrCrash("Unexpected uniform type.");
+ }
+ }
+}
+
+GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
+ int reserveCount)
+ : fBuilder(builder)
+ , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
+ (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
+}
+
+void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
+ GrGLProgramEffects::EffectKey key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ SkASSERT(NULL != fProgramEffects.get());
+ fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
+ const GrEffectStage& stage,
+ EffectKey key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ GrDrawEffect drawEffect(stage, false);
+ const GrEffectRef& effect = *stage.getEffect();
+ SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
+ SkSTArray<4, TextureSampler> samplers(effect->numTextures());
+
+ SkASSERT(0 == stage.getVertexAttribIndexCount());
+ this->setupTexGen(builder, effect, key, &coords);
+ this->emitSamplers(builder, effect, &samplers);
+
+ GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
+ fGLEffects.push_back(glEffect);
+
+ // Enclose custom code in a block to avoid namespace conflicts
+ SkString openBrace;
+ openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
+ builder->fsCodeAppend(openBrace.c_str());
+
+ SkASSERT(!glEffect->isVertexEffect());
+ glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
+
+ builder->fsCodeAppend("\t}\n");
+}
+
+void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder,
+ const GrEffectRef& effect,
+ EffectKey effectKey,
+ TransformedCoordsArray* outCoords) {
+ int numTransforms = effect->numTransforms();
+ EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
+ int texCoordIndex = builder->addTexCoordSets(numTransforms);
+ SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
SkString name;
- for (int t = 0; t < numTextures; ++t) {
- name.printf("Sampler%d", t);
- samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
- kSampler2D_GrSLType,
- name.c_str());
- SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
- (samplers[t].fUniform, effect->textureAccess(t)));
+ for (int t = 0; t < numTransforms; ++t) {
+ GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
+ kVec3f_GrSLType :
+ kVec2f_GrSLType;
+ name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
+ SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
+ }
+}
+
+void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu,
+ const GrGLUniformManager& uniformManager,
+ const GrEffectStage* effectStages[]) {
+ int numEffects = fGLEffects.count();
+ SkASSERT(numEffects == fTransforms.count());
+ SkASSERT(numEffects == fSamplers.count());
+ for (int e = 0; e < numEffects; ++e) {
+ GrDrawEffect drawEffect(*effectStages[e], false);
+ fGLEffects[e]->setData(uniformManager, drawEffect);
+ this->setTexGenState(gpu, drawEffect, e);
+ this->bindTextures(gpu, *drawEffect.effect(), e);
}
}
+
+void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
+ const GrDrawEffect& drawEffect,
+ int effectIdx) {
+ EffectKey totalKey = fTransforms[effectIdx].fTransformKey;
+ int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
+ int numTransforms = (*drawEffect.effect())->numTransforms();
+ for (int t = 0; t < numTransforms; ++t) {
+ switch (get_matrix_type(totalKey, t)) {
+ case kIdentity_MatrixType: {
+ SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
+ GrGLfloat identity[] = {1, 0, 0,
+ 0, 1, 0};
+ gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity);
+ break;
+ }
+ case kTrans_MatrixType: {
+ GrGLfloat tx, ty;
+ get_transform_translation(drawEffect, t, &tx, &ty);
+ GrGLfloat translate[] = {1, 0, tx,
+ 0, 1, ty};
+ gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate);
+ break;
+ }
+ case kNoPersp_MatrixType: {
+ const SkMatrix& transform = get_transform_matrix(drawEffect, t);
+ gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform);
+ break;
+ }
+ case kGeneral_MatrixType: {
+ const SkMatrix& transform = get_transform_matrix(drawEffect, t);
+ gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform);
+ break;
+ }
+ default:
+ GrCrash("Unexpected matrixs type.");
+ }
+ }
+}
+
+GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder(
+ GrGLFragmentOnlyShaderBuilder* builder,
+ int reserveCount)
+ : fBuilder(builder)
+ , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) {
+}
+
+void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
+ GrGLProgramEffects::EffectKey key,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) {
+ SkASSERT(NULL != fProgramEffects.get());
+ fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
+}
diff --git a/src/gpu/gl/GrGLProgramEffects.h b/src/gpu/gl/GrGLProgramEffects.h
index f6f975ae4e..4572a4250d 100644
--- a/src/gpu/gl/GrGLProgramEffects.h
+++ b/src/gpu/gl/GrGLProgramEffects.h
@@ -14,10 +14,10 @@
#include "GrGLUniformManager.h"
class GrEffectStage;
-class GrGLProgramEffectsBuilder;
class GrGLVertexProgramEffectsBuilder;
class GrGLShaderBuilder;
class GrGLFullShaderBuilder;
+class GrGLFragmentOnlyShaderBuilder;
/**
* This class encapsulates an array of GrGLEffects and their supporting data (coord transforms
@@ -56,7 +56,7 @@ public:
*/
class TransformedCoords {
public:
- TransformedCoords(const char* name, GrSLType type)
+ TransformedCoords(const SkString& name, GrSLType type)
: fName(name), fType(type) {
}
@@ -97,14 +97,19 @@ public:
typedef SkTArray<TextureSampler> TextureSamplerArray;
protected:
- friend class GrGLProgramEffectsBuilder;
-
GrGLProgramEffects(int reserveCount)
: fGLEffects(reserveCount)
, fSamplers(reserveCount) {
}
/**
+ * Helper for emitEffect() in a subclasses. Emits uniforms for an effect's texture accesses and
+ * appends the necessary data to the TextureSamplerArray* object so effects can add texture
+ * lookups to their code. This method is only meant to be called during the construction phase.
+ */
+ void emitSamplers(GrGLShaderBuilder*, const GrEffectRef&, TextureSamplerArray*);
+
+ /**
* Helper for setData(). Binds all the textures for an effect.
*/
void bindTextures(GrGpuGL*, const GrEffectRef&, int effectIdx);
@@ -120,6 +125,23 @@ protected:
};
/**
+ * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
+ */
+class GrGLProgramEffectsBuilder {
+public:
+ /**
+ * Emits the effect's shader code, and stores the necessary uniforms internally.
+ */
+ virtual void emitEffect(const GrEffectStage&,
+ GrGLProgramEffects::EffectKey,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex) = 0;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+/**
* This is a GrGLProgramEffects implementation that does coord transforms with the vertex shader.
*/
class GrGLVertexProgramEffects : public GrGLProgramEffects {
@@ -138,6 +160,34 @@ private:
}
/**
+ * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
+ * during the construction phase.
+ */
+ void emitEffect(GrGLFullShaderBuilder*,
+ const GrEffectStage&,
+ GrGLProgramEffects::EffectKey,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex);
+
+ /**
+ * Helper for emitEffect(). Emits any attributes an effect may have.
+ */
+ void emitAttributes(GrGLFullShaderBuilder*, const GrEffectStage&);
+
+ /**
+ * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
+ * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
+ * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
+ * of the varyings in the VS and FS as well their types are appended to the
+ * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
+ */
+ void emitTransforms(GrGLFullShaderBuilder*,
+ const GrEffectRef&,
+ EffectKey,
+ TransformedCoordsArray*);
+
+ /**
* Helper for setData(). Sets all the transform matrices for an effect.
*/
void setTransformData(const GrGLUniformManager&, const GrDrawEffect&, int effectIdx);
@@ -155,39 +205,99 @@ private:
typedef GrGLProgramEffects INHERITED;
};
-////////////////////////////////////////////////////////////////////////////////
-
/**
- * This is an abstract base class for constructing different types of GrGLProgramEffects objects.
+ * This class is used to construct a GrGLVertexProgramEffects* object.
*/
-class GrGLProgramEffectsBuilder {
+class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
public:
- /**
- * Emits the effect's shader code, and stores the necessary uniforms internally.
- */
+ GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
+
virtual void emitEffect(const GrEffectStage&,
GrGLProgramEffects::EffectKey,
const char* outColor,
const char* inColor,
- int stageIndex) = 0;
+ int stageIndex) SK_OVERRIDE;
-protected:
/**
- * Helper for emitEffect(). Emits uniforms for an effect's texture accesses and appends the
- * necessary data to the TextureSamplerArray* object so effects can add texture lookups.
+ * Finalizes the building process and returns the effect array. After this call, the builder
+ * becomes invalid.
*/
- static void emitSamplers(GrGLShaderBuilder*,
- GrGLProgramEffects*,
- const GrEffectRef&,
- GrGLProgramEffects::TextureSamplerArray*);
+ GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
+
+private:
+ GrGLFullShaderBuilder* fBuilder;
+ SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
+
+ typedef GrGLProgramEffectsBuilder INHERITED;
};
+////////////////////////////////////////////////////////////////////////////////
+
/**
- * This class is used to construct a GrGLVertexProgramEffects object.
+ * This is a GrGLProgramEffects implementation that does coord transforms with the the built-in GL
+ * TexGen functionality.
*/
-class GrGLVertexProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
+class GrGLTexGenProgramEffects : public GrGLProgramEffects {
public:
- GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder*, int reserveCount);
+ virtual void setData(GrGpuGL*,
+ const GrGLUniformManager&,
+ const GrEffectStage* effectStages[]) SK_OVERRIDE;
+
+private:
+ friend class GrGLTexGenProgramEffectsBuilder;
+
+ GrGLTexGenProgramEffects(int reserveCount)
+ : INHERITED(reserveCount)
+ , fTransforms(reserveCount) {
+ }
+
+ /**
+ * Helper for GrGLProgramEffectsBuilder::emitEfffect(). This method is meant to only be called
+ * during the construction phase.
+ */
+ void emitEffect(GrGLFragmentOnlyShaderBuilder*,
+ const GrEffectStage&,
+ GrGLProgramEffects::EffectKey,
+ const char* outColor,
+ const char* inColor,
+ int stageIndex);
+
+ /**
+ * Helper for emitEffect(). Allocates texture units from the builder for each transform in an
+ * effect. The transforms all use adjacent texture units. They either use two or three of the
+ * coordinates at a given texture unit, depending on if they need perspective interpolation.
+ * The expressions to access the transformed coords (i.e. 'vec2(gl_TexCoord[0])') as well as the
+ * types are appended to the TransformedCoordsArray* object, which is in turn passed to the
+ * effect's emitCode() function.
+ */
+ void setupTexGen(GrGLFragmentOnlyShaderBuilder*,
+ const GrEffectRef&,
+ EffectKey,
+ TransformedCoordsArray*);
+
+ /**
+ * Helper for setData(). Sets the TexGen state for each transform in an effect.
+ */
+ void setTexGenState(GrGpuGL*, const GrDrawEffect&, int effectIdx);
+
+ struct Transforms {
+ Transforms(EffectKey transformKey, int texCoordIndex)
+ : fTransformKey(transformKey), fTexCoordIndex(texCoordIndex) {}
+ EffectKey fTransformKey;
+ int fTexCoordIndex;
+ };
+
+ SkTArray<Transforms> fTransforms;
+
+ typedef GrGLProgramEffects INHERITED;
+};
+
+/**
+ * This class is used to construct a GrGLTexGenProgramEffects* object.
+ */
+class GrGLTexGenProgramEffectsBuilder : public GrGLProgramEffectsBuilder {
+public:
+ GrGLTexGenProgramEffectsBuilder(GrGLFragmentOnlyShaderBuilder*, int reserveCount);
virtual void emitEffect(const GrEffectStage&,
GrGLProgramEffects::EffectKey,
@@ -202,24 +312,8 @@ public:
GrGLProgramEffects* finish() { return fProgramEffects.detach(); }
private:
- /**
- * Helper for emitEffect(). Emits any attributes an effect might have.
- */
- void emitAttributes(const GrEffectStage&);
-
- /**
- * Helper for emitEffect(). Emits code to implement an effect's coord transforms in the VS.
- * Varyings are added as an outputs of the VS and inputs to the FS. The varyings may be either a
- * vec2f or vec3f depending upon whether perspective interpolation is required or not. The names
- * of the varyings in the VS and FS as well their types are appended to the
- * TransformedCoordsArray* object, which is in turn passed to the effect's emitCode() function.
- */
- void emitTransforms(const GrEffectRef&,
- GrGLProgramEffects::EffectKey,
- GrGLProgramEffects::TransformedCoordsArray*);
-
- GrGLFullShaderBuilder* fBuilder;
- SkAutoTDelete<GrGLVertexProgramEffects> fProgramEffects;
+ GrGLFragmentOnlyShaderBuilder* fBuilder;
+ SkAutoTDelete<GrGLTexGenProgramEffects> fProgramEffects;
typedef GrGLProgramEffectsBuilder INHERITED;
};
diff --git a/src/gpu/gl/GrGLShaderBuilder.cpp b/src/gpu/gl/GrGLShaderBuilder.cpp
index 089ece7c07..00fefe1305 100644
--- a/src/gpu/gl/GrGLShaderBuilder.cpp
+++ b/src/gpu/gl/GrGLShaderBuilder.cpp
@@ -441,7 +441,6 @@ const char* GrGLShaderBuilder::fragmentPosition() {
}
}
-
void GrGLShaderBuilder::fsEmitFunction(GrSLType returnType,
const char* name,
int argCnt,
@@ -920,3 +919,35 @@ void GrGLFullShaderBuilder::bindProgramLocations(GrGLuint programId) const {
GL_CALL(BindAttribLocation(programId, attrib->fIndex, attrib->fName.c_str()));
}
}
+
+////////////////////////////////////////////////////////////////////////////////
+
+GrGLFragmentOnlyShaderBuilder::GrGLFragmentOnlyShaderBuilder(GrGpuGL* gpu,
+ GrGLUniformManager& uniformManager,
+ const GrGLProgramDesc& desc)
+ : INHERITED(gpu, uniformManager, desc)
+ , fNumTexCoordSets(0) {
+
+ SkASSERT(!desc.getHeader().fHasVertexCode);
+ SkASSERT(gpu->glCaps().fixedFunctionSupport());
+ SkASSERT(gpu->glCaps().pathStencilingSupport());
+ SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fColorInput);
+ SkASSERT(GrGLProgramDesc::kAttribute_ColorInput != desc.getHeader().fCoverageInput);
+}
+
+GrGLProgramEffects* GrGLFragmentOnlyShaderBuilder::createAndEmitEffects(
+ const GrEffectStage* effectStages[],
+ const EffectKey effectKeys[],
+ int effectCnt,
+ SkString* inOutFSColor,
+ GrSLConstantVec* fsInOutColorKnownValue) {
+
+ GrGLTexGenProgramEffectsBuilder texGenEffectsBuilder(this, effectCnt);
+ this->INHERITED::createAndEmitEffects(&texGenEffectsBuilder,
+ effectStages,
+ effectKeys,
+ effectCnt,
+ inOutFSColor,
+ fsInOutColorKnownValue);
+ return texGenEffectsBuilder.finish();
+}
diff --git a/src/gpu/gl/GrGLShaderBuilder.h b/src/gpu/gl/GrGLShaderBuilder.h
index 4c43fc36c3..208c61060b 100644
--- a/src/gpu/gl/GrGLShaderBuilder.h
+++ b/src/gpu/gl/GrGLShaderBuilder.h
@@ -450,4 +450,26 @@ private:
typedef GrGLShaderBuilder INHERITED;
};
+////////////////////////////////////////////////////////////////////////////////
+
+class GrGLFragmentOnlyShaderBuilder : public GrGLShaderBuilder {
+public:
+ GrGLFragmentOnlyShaderBuilder(GrGpuGL*, GrGLUniformManager&, const GrGLProgramDesc&);
+
+ int getNumTexCoordSets() const { return fNumTexCoordSets; }
+ int addTexCoordSets(int count) { return (fNumTexCoordSets += count) - count; }
+
+ virtual GrGLProgramEffects* createAndEmitEffects(
+ const GrEffectStage* effectStages[],
+ const EffectKey effectKeys[],
+ int effectCnt,
+ SkString* inOutFSColor,
+ GrSLConstantVec* fsInOutColorKnownValue) SK_OVERRIDE;
+
+private:
+ int fNumTexCoordSets;
+
+ typedef GrGLShaderBuilder INHERITED;
+};
+
#endif
diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
index 50d2a1f517..18165d9ca3 100644
--- a/src/gpu/gl/GrGpuGL.cpp
+++ b/src/gpu/gl/GrGpuGL.cpp
@@ -124,6 +124,7 @@ GrGpuGL::GrGpuGL(const GrGLContext& ctx, GrContext* context)
fCaps.reset(SkRef(ctx.info().caps()));
fHWBoundTextures.reset(ctx.info().caps()->maxFragmentTextureUnits());
+ fHWTexGenSettings.reset(ctx.info().caps()->maxFixedFunctionTextureCoords());
fillInConfigRenderableTable();
@@ -377,7 +378,13 @@ void GrGpuGL::onResetContext(uint32_t resetBits) {
GL_CALL(Disable(GR_GL_TEXTURE_GEN_T));
GL_CALL(Disable(GR_GL_TEXTURE_GEN_Q));
GL_CALL(Disable(GR_GL_TEXTURE_GEN_R));
+ if (this->caps()->pathStencilingSupport()) {
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ }
+ fHWTexGenSettings[i].fMode = GR_GL_NONE;
+ fHWTexGenSettings[i].fNumComponents = 0;
}
+ fHWActiveTexGenSets = 0;
}
// we assume these values
@@ -2114,6 +2121,124 @@ void GrGpuGL::bindTexture(int unitIdx, const GrTextureParams& params, GrGLTextur
texture->setCachedTexParams(newTexParams, this->getResetTimestamp());
}
+void GrGpuGL::setProjectionMatrix(const SkMatrix& matrix,
+ const SkISize& renderTargetSize,
+ GrSurfaceOrigin renderTargetOrigin) {
+
+ SkASSERT(this->glCaps().fixedFunctionSupport());
+
+ if (renderTargetOrigin == fHWProjectionMatrixState.fRenderTargetOrigin &&
+ renderTargetSize == fHWProjectionMatrixState.fRenderTargetSize &&
+ matrix.cheapEqualTo(fHWProjectionMatrixState.fViewMatrix)) {
+ return;
+ }
+
+ fHWProjectionMatrixState.fViewMatrix = matrix;
+ fHWProjectionMatrixState.fRenderTargetSize = renderTargetSize;
+ fHWProjectionMatrixState.fRenderTargetOrigin = renderTargetOrigin;
+
+ GrGLfloat glMatrix[4 * 4];
+ fHWProjectionMatrixState.getGLMatrix<4>(glMatrix);
+ GL_CALL(MatrixMode(GR_GL_PROJECTION));
+ GL_CALL(LoadMatrixf(glMatrix));
+}
+
+void GrGpuGL::enableTexGen(int unitIdx,
+ TexGenComponents components,
+ const GrGLfloat* coefficients) {
+
+ SkASSERT(this->glCaps().fixedFunctionSupport());
+ SkASSERT(this->caps()->pathStencilingSupport());
+ SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
+
+ if (GR_GL_OBJECT_LINEAR == fHWTexGenSettings[unitIdx].fMode &&
+ components == fHWTexGenSettings[unitIdx].fNumComponents &&
+ !memcmp(coefficients, fHWTexGenSettings[unitIdx].fCoefficients,
+ 3 * components * sizeof(GrGLfloat))) {
+ return;
+ }
+
+ this->setTextureUnit(unitIdx);
+
+ if (GR_GL_OBJECT_LINEAR != fHWTexGenSettings[unitIdx].fMode) {
+ for (int i = 0; i < 4; i++) {
+ GL_CALL(TexGeni(GR_GL_S + i, GR_GL_TEXTURE_GEN_MODE, GR_GL_OBJECT_LINEAR));
+ }
+ fHWTexGenSettings[unitIdx].fMode = GR_GL_OBJECT_LINEAR;
+ }
+
+ for (int i = fHWTexGenSettings[unitIdx].fNumComponents; i < components; i++) {
+ GL_CALL(Enable(GR_GL_TEXTURE_GEN_S + i));
+ }
+ for (int i = components; i < fHWTexGenSettings[unitIdx].fNumComponents; i++) {
+ GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + i));
+ }
+ fHWTexGenSettings[unitIdx].fNumComponents = components;
+
+ for (int i = 0; i < components; i++) {
+ GrGLfloat plane[] = {coefficients[0 + 3 * i],
+ coefficients[1 + 3 * i],
+ 0,
+ coefficients[2 + 3 * i]};
+ GL_CALL(TexGenfv(GR_GL_S + i, GR_GL_OBJECT_PLANE, plane));
+ }
+
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + unitIdx,
+ GR_GL_OBJECT_LINEAR,
+ components,
+ coefficients));
+
+ memcpy(fHWTexGenSettings[unitIdx].fCoefficients, coefficients,
+ 3 * components * sizeof(GrGLfloat));
+
+ fHWActiveTexGenSets = SkTMax(fHWActiveTexGenSets, unitIdx);
+}
+
+void GrGpuGL::enableTexGen(int unitIdx, TexGenComponents components, const SkMatrix& matrix) {
+
+ GrGLfloat coefficients[3 * 3];
+ SkASSERT(this->glCaps().fixedFunctionSupport());
+ SkASSERT(components >= kS_TexGenComponents && components <= kSTR_TexGenComponents);
+
+ coefficients[0] = SkScalarToFloat(matrix[SkMatrix::kMScaleX]);
+ coefficients[1] = SkScalarToFloat(matrix[SkMatrix::kMSkewX]);
+ coefficients[2] = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
+
+ if (components >= kST_TexGenComponents) {
+ coefficients[3] = SkScalarToFloat(matrix[SkMatrix::kMSkewY]);
+ coefficients[4] = SkScalarToFloat(matrix[SkMatrix::kMScaleY]);
+ coefficients[5] = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
+ }
+
+ if (components >= kSTR_TexGenComponents) {
+ coefficients[6] = SkScalarToFloat(matrix[SkMatrix::kMPersp0]);
+ coefficients[7] = SkScalarToFloat(matrix[SkMatrix::kMPersp1]);
+ coefficients[8] = SkScalarToFloat(matrix[SkMatrix::kMPersp2]);
+ }
+
+ enableTexGen(unitIdx, components, coefficients);
+}
+
+void GrGpuGL::disableUnusedTexGen(int numUsedTexCoordSets) {
+
+ SkASSERT(this->glCaps().fixedFunctionSupport());
+
+ for (int i = numUsedTexCoordSets; i < fHWActiveTexGenSets; i++) {
+ if (0 == fHWTexGenSettings[i].fNumComponents) {
+ continue;
+ }
+
+ this->setTextureUnit(i);
+ for (int j = 0; j < fHWTexGenSettings[i].fNumComponents; j++) {
+ GL_CALL(Disable(GR_GL_TEXTURE_GEN_S + j));
+ }
+ GL_CALL(PathTexGen(GR_GL_TEXTURE0 + i, GR_GL_NONE, 0, NULL));
+ fHWTexGenSettings[i].fNumComponents = 0;
+ }
+
+ fHWActiveTexGenSets = SkTMin(fHWActiveTexGenSets, numUsedTexCoordSets);
+}
+
void GrGpuGL::flushMiscFixedFunctionState() {
const GrDrawState& drawState = this->getDrawState();
diff --git a/src/gpu/gl/GrGpuGL.h b/src/gpu/gl/GrGpuGL.h
index b0195bbaed..a59654a0f8 100644
--- a/src/gpu/gl/GrGpuGL.h
+++ b/src/gpu/gl/GrGpuGL.h
@@ -37,8 +37,19 @@ public:
GrGLVersion glVersion() const { return fGLContext.info().version(); }
GrGLSLGeneration glslGeneration() const { return fGLContext.info().glslGeneration(); }
- // Used by GrGLProgram to bind necessary textures for GrGLEffects.
+ // Used by GrGLProgram and GrGLTexGenProgramEffects to configure OpenGL state.
void bindTexture(int unitIdx, const GrTextureParams& params, GrGLTexture* texture);
+ void setProjectionMatrix(const SkMatrix& matrix,
+ const SkISize& renderTargetSize,
+ GrSurfaceOrigin renderTargetOrigin);
+ enum TexGenComponents {
+ kS_TexGenComponents = 1,
+ kST_TexGenComponents = 2,
+ kSTR_TexGenComponents = 3
+ };
+ void enableTexGen(int unitIdx, TexGenComponents, const GrGLfloat* coefficients);
+ void enableTexGen(int unitIdx, TexGenComponents, const SkMatrix& matrix);
+ void disableUnusedTexGen(int numUsedTexCoordSets);
bool programUnitTest(int maxStages);
@@ -213,9 +224,6 @@ private:
#endif
};
- // sets the matrix for path stenciling (uses the GL fixed pipe matrices)
- void flushPathStencilMatrix();
-
// flushes dithering, color-mask, and face culling stat
void flushMiscFixedFunctionState();
@@ -432,6 +440,14 @@ private:
TriState fHWDitherEnabled;
GrRenderTarget* fHWBoundRenderTarget;
SkTArray<GrTexture*, true> fHWBoundTextures;
+
+ struct TexGenData {
+ GrGLenum fMode;
+ GrGLint fNumComponents;
+ GrGLfloat fCoefficients[3 * 3];
+ };
+ int fHWActiveTexGenSets;
+ SkTArray<TexGenData, true> fHWTexGenSettings;
///@}
// we record what stencil format worked last time to hopefully exit early
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index 8a3444e508..92eed8d9bb 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -210,28 +210,6 @@ void GrGpuGL::abandonResources(){
#define GL_CALL(X) GR_GL_CALL(this->glInterface(), X)
-void GrGpuGL::flushPathStencilMatrix() {
- const SkMatrix& viewMatrix = this->getDrawState().getViewMatrix();
- const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
- SkISize size;
- size.set(rt->width(), rt->height());
- const SkMatrix& vm = this->getDrawState().getViewMatrix();
-
- if (fHWProjectionMatrixState.fRenderTargetOrigin != rt->origin() ||
- !fHWProjectionMatrixState.fViewMatrix.cheapEqualTo(viewMatrix) ||
- fHWProjectionMatrixState.fRenderTargetSize!= size) {
-
- fHWProjectionMatrixState.fViewMatrix = vm;
- fHWProjectionMatrixState.fRenderTargetSize = size;
- fHWProjectionMatrixState.fRenderTargetOrigin = rt->origin();
-
- GrGLfloat projectionMatrix[4 * 4];
- fHWProjectionMatrixState.getGLMatrix<4>(projectionMatrix);
- GL_CALL(MatrixMode(GR_GL_PROJECTION));
- GL_CALL(LoadMatrixf(projectionMatrix));
- }
-}
-
bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstCopy) {
const GrDrawState& drawState = this->getDrawState();
@@ -239,7 +217,10 @@ bool GrGpuGL::flushGraphicsState(DrawType type, const GrDeviceCoordTexture* dstC
SkASSERT(NULL != drawState.getRenderTarget());
if (kStencilPath_DrawType == type) {
- this->flushPathStencilMatrix();
+ const GrRenderTarget* rt = this->getDrawState().getRenderTarget();
+ SkISize size;
+ size.set(rt->width(), rt->height());
+ this->setProjectionMatrix(drawState.getViewMatrix(), size, rt->origin());
} else {
this->flushMiscFixedFunctionState();
@@ -360,24 +341,40 @@ void GrGpuGL::setupGeometry(const DrawInfo& info, size_t* indexOffsetInBytes) {
GrGLAttribArrayState* attribState =
fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
- uint32_t usedAttribArraysMask = 0;
- const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
- int vertexAttribCount = this->getDrawState().getVertexAttribCount();
- for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
- ++vertexAttribIndex, ++vertexAttrib) {
-
- usedAttribArraysMask |= (1 << vertexAttribIndex);
- GrVertexAttribType attribType = vertexAttrib->fType;
- attribState->set(this,
- vertexAttribIndex,
- vbuf,
- GrGLAttribTypeToLayout(attribType).fCount,
- GrGLAttribTypeToLayout(attribType).fType,
- GrGLAttribTypeToLayout(attribType).fNormalized,
- stride,
- reinterpret_cast<GrGLvoid*>(
- vertexOffsetInBytes + vertexAttrib->fOffset));
- }
+ if (!fCurrentProgram->hasVertexShader()) {
+ int posIdx = this->getDrawState().positionAttributeIndex();
+ const GrVertexAttrib* vertexArray = this->getDrawState().getVertexAttribs() + posIdx;
+ GrVertexAttribType vertexArrayType = vertexArray->fType;
+ SkASSERT(!GrGLAttribTypeToLayout(vertexArrayType).fNormalized);
+ SkASSERT(GrGLAttribTypeToLayout(vertexArrayType).fCount == 2);
+ attribState->setFixedFunctionVertexArray(this,
+ vbuf,
+ 2,
+ GrGLAttribTypeToLayout(vertexArrayType).fType,
+ stride,
+ reinterpret_cast<GrGLvoid*>(
+ vertexOffsetInBytes + vertexArray->fOffset));
+ attribState->disableUnusedArrays(this, 0, true);
+ } else {
+ uint32_t usedAttribArraysMask = 0;
+ const GrVertexAttrib* vertexAttrib = this->getDrawState().getVertexAttribs();
+ int vertexAttribCount = this->getDrawState().getVertexAttribCount();
+ for (int vertexAttribIndex = 0; vertexAttribIndex < vertexAttribCount;
+ ++vertexAttribIndex, ++vertexAttrib) {
+
+ usedAttribArraysMask |= (1 << vertexAttribIndex);
+ GrVertexAttribType attribType = vertexAttrib->fType;
+ attribState->set(this,
+ vertexAttribIndex,
+ vbuf,
+ GrGLAttribTypeToLayout(attribType).fCount,
+ GrGLAttribTypeToLayout(attribType).fType,
+ GrGLAttribTypeToLayout(attribType).fNormalized,
+ stride,
+ reinterpret_cast<GrGLvoid*>(
+ vertexOffsetInBytes + vertexAttrib->fOffset));
+ }
- attribState->disableUnusedArrays(this, usedAttribArraysMask, false);
+ attribState->disableUnusedArrays(this, usedAttribArraysMask, false);
+ }
}
diff --git a/tests/GLProgramsTest.cpp b/tests/GLProgramsTest.cpp
index fe17f88945..13d0d2ee5b 100644
--- a/tests/GLProgramsTest.cpp
+++ b/tests/GLProgramsTest.cpp
@@ -78,6 +78,7 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
bool dstRead = false;
bool fragPos = false;
+ bool vertexCode = false;
int numStages = numColorStages + numCoverageStages;
for (int s = 0; s < numStages; ++s) {
const GrBackendEffectFactory& factory = (*stages[s]->getEffect())->getFactory();
@@ -89,6 +90,9 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
if ((*stages[s]->getEffect())->willReadFragmentPosition()) {
fragPos = true;
}
+ if ((*stages[s]->getEffect())->hasVertexCode()) {
+ vertexCode = true;
+ }
}
if (dstRead) {
@@ -103,6 +107,11 @@ void GrGLProgramDesc::setRandom(SkRandom* random,
header->fFragPosKey = 0;
}
+ header->fHasVertexCode = vertexCode ||
+ useLocalCoords ||
+ kAttribute_ColorInput == header->fColorInput ||
+ kAttribute_ColorInput == header->fCoverageInput;
+
CoverageOutput coverageOutput;
bool illegalCoverageOutput;
do {