Index: src/gpu/gl/GrGLProgramEffects.cpp |
diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp |
index d5826abe3042e9e1eb9057996d763483161a3044..b24d157642ef8a2a9af51afc4b8a0e1b80a2e9b3 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,6 +68,74 @@ 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) { |
@@ -179,23 +246,14 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& unifor |
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()); |
+ SkASSERT(get_transform_matrix(drawEffect, t).isIdentity()); |
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]; |
+ 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); |
@@ -205,21 +263,10 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& unifor |
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; |
+ 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; |
} |
@@ -229,6 +276,62 @@ void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& unifor |
} |
} |
+void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu, |
+ const GrGLUniformManager& uniformManager, |
+ const GrEffectStage* effectStages[]) { |
+ int numEffects = fGLEffects.count(); |
+ SkASSERT(numEffects == fTransformKeys.count()); |
+ SkASSERT(numEffects == fSamplers.count()); |
+ int texCoordIdx = fFirstTexCoordIdx; |
+ SkASSERT(texCoordIdx >= 0); |
+ for (int e = 0; e < numEffects; ++e) { |
+ GrDrawEffect drawEffect(*effectStages[e], false); |
+ fGLEffects[e]->setData(uniformManager, drawEffect); |
+ this->setTexGenState(gpu, drawEffect, &texCoordIdx, e); |
+ this->bindTextures(gpu, *drawEffect.effect(), e); |
+ } |
+ SkASSERT(fNumTexCoordSets == texCoordIdx - fFirstTexCoordIdx); |
+} |
+ |
+void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu, |
+ const GrDrawEffect& drawEffect, |
+ int* texCoordIdx, |
+ int effectIdx) { |
+ EffectKey transformKey = fTransformKeys[effectIdx]; |
+ int numTransforms = (*drawEffect.effect())->numTransforms(); |
+ for (int t = 0; t < numTransforms; ++t) { |
+ switch (get_matrix_type(transformKey, t)) { |
+ case kIdentity_MatrixType: { |
+ SkASSERT(get_transform_matrix(drawEffect, t).isIdentity()); |
+ GrGLfloat identity[] = {1, 0, 0, |
+ 0, 1, 0}; |
+ gpu->enableTexGen((*texCoordIdx)++, 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((*texCoordIdx)++, GrGpuGL::kST_TexGenComponents, translate); |
+ break; |
+ } |
+ case kNoPersp_MatrixType: { |
+ const SkMatrix& transform = get_transform_matrix(drawEffect, t); |
+ gpu->enableTexGen((*texCoordIdx)++, GrGpuGL::kST_TexGenComponents, transform); |
+ break; |
+ } |
+ case kGeneral_MatrixType: { |
+ const SkMatrix& transform = get_transform_matrix(drawEffect, t); |
+ gpu->enableTexGen((*texCoordIdx)++, GrGpuGL::kSTR_TexGenComponents, transform); |
+ break; |
+ } |
+ default: |
+ GrCrash("Unexpected matrixs type."); |
+ } |
+ } |
+} |
+ |
void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) { |
const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx]; |
int numSamplers = samplers.count(); |
@@ -305,14 +408,13 @@ void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect, |
TransformedCoordsArray* outCoords) { |
typedef GrGLVertexProgramEffects::Transform Transform; |
SkTArray<Transform, true>& transforms = fProgramEffects->fTransforms.push_back(); |
- EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); |
+ EffectKey transformKey = 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(transformKey, t)) { |
case kIdentity_MatrixType: |
transforms[t].fType = kVoid_GrSLType; |
uniName = NULL; |
@@ -360,7 +462,7 @@ void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect, |
const char* fsVaryingName; |
fBuilder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); |
- const GrGLShaderVar& coords = (kPositionCoords_Flag & key) ? |
+ const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(transformKey, t) ? |
fBuilder->positionAttribute() : |
fBuilder->localCoordsAttribute(); |
// varying = matrix * coords (logically) |
@@ -388,7 +490,63 @@ void GrGLVertexProgramEffectsBuilder::emitTransforms(const GrEffectRef& effect, |
default: |
GrCrash("Unexpected uniform type."); |
} |
- SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (fsVaryingName, varyingType)); |
+ SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, |
+ (SkString(fsVaryingName), varyingType)); |
+ } |
+} |
+ |
+GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder( |
+ GrGLFragmentOnlyShaderBuilder* builder, |
+ int reserveCount) |
+ : fBuilder(builder) |
+ , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) { |
+} |
+ |
+void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, |
+ EffectKey key, |
+ const char* outColor, |
+ const char* inColor, |
+ int stageIndex) { |
+ SkASSERT(NULL != fProgramEffects.get()); |
+ |
+ 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(effect, key, &coords); |
+ INHERITED::emitSamplers(fBuilder, fProgramEffects.get(), effect, &samplers); |
+ |
+ GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); |
+ fProgramEffects->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->fsCodeAppend(openBrace.c_str()); |
+ |
+ SkASSERT(!glEffect->isVertexEffect()); |
+ glEffect->emitCode(fBuilder, drawEffect, key, outColor, inColor, coords, samplers); |
+ |
+ fBuilder->fsCodeAppend("\t}\n"); |
+} |
+ |
+void GrGLTexGenProgramEffectsBuilder::setupTexGen(const GrEffectRef& effect, |
+ EffectKey effectKey, |
+ TransformedCoordsArray* outCoords) { |
+ int numTransforms = effect->numTransforms(); |
+ SkDEBUGCODE(fProgramEffects->fNumTexCoordSets += numTransforms;) |
+ int texCoordIdx = fBuilder->addTexCoordSets(numTransforms); |
+ EffectKey transformKey = GrBackendEffectFactory::GetTransformKey(effectKey); |
+ fProgramEffects->fTransformKeys.push_back(transformKey); |
+ SkString name; |
+ for (int t = 0; t < numTransforms; ++t) { |
+ GrSLType type = kGeneral_MatrixType == get_matrix_type(transformKey, t) ? |
+ kVec3f_GrSLType : |
+ kVec2f_GrSLType; |
+ name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIdx++); |
+ SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type)); |
} |
} |