1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/gpu/gl/GrGLProgramEffects.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,586 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "GrGLProgramEffects.h" 1.12 +#include "GrDrawEffect.h" 1.13 +#include "gl/GrGLEffect.h" 1.14 +#include "gl/GrGLShaderBuilder.h" 1.15 +#include "gl/GrGLVertexEffect.h" 1.16 +#include "gl/GrGpuGL.h" 1.17 + 1.18 +typedef GrGLProgramEffects::EffectKey EffectKey; 1.19 +typedef GrGLProgramEffects::TransformedCoords TransformedCoords; 1.20 +typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray; 1.21 +typedef GrGLProgramEffects::TextureSampler TextureSampler; 1.22 +typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray; 1.23 + 1.24 +/** 1.25 + * We specialize the vertex code for each of these matrix types. 1.26 + */ 1.27 +enum MatrixType { 1.28 + kIdentity_MatrixType = 0, 1.29 + kTrans_MatrixType = 1, 1.30 + kNoPersp_MatrixType = 2, 1.31 + kGeneral_MatrixType = 3, 1.32 +}; 1.33 + 1.34 +/** 1.35 + * The key for an individual coord transform is made up of a matrix type and a bit that 1.36 + * indicates the source of the input coords. 1.37 + */ 1.38 +enum { 1.39 + kMatrixTypeKeyBits = 2, 1.40 + kMatrixTypeKeyMask = (1 << kMatrixTypeKeyBits) - 1, 1.41 + kPositionCoords_Flag = (1 << kMatrixTypeKeyBits), 1.42 + kTransformKeyBits = kMatrixTypeKeyBits + 1, 1.43 +}; 1.44 + 1.45 +namespace { 1.46 + 1.47 +/** 1.48 + * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are 1.49 + * present in the texture's config. swizzleComponentMask indicates the channels present in the 1.50 + * shader swizzle. 1.51 + */ 1.52 +inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps, 1.53 + uint32_t configComponentMask, 1.54 + uint32_t swizzleComponentMask) { 1.55 + if (caps.textureSwizzleSupport()) { 1.56 + // Any remapping is handled using texture swizzling not shader modifications. 1.57 + return false; 1.58 + } 1.59 + // check if the texture is alpha-only 1.60 + if (kA_GrColorComponentFlag == configComponentMask) { 1.61 + if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) { 1.62 + // we must map the swizzle 'a's to 'r'. 1.63 + return true; 1.64 + } 1.65 + if (kRGB_GrColorComponentFlags & swizzleComponentMask) { 1.66 + // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that 1.67 + // alpha-only textures smear alpha across all four channels when read. 1.68 + return true; 1.69 + } 1.70 + } 1.71 + return false; 1.72 +} 1.73 + 1.74 +/** 1.75 + * Retrieves the matrix type from transformKey for the transform at transformIdx. 1.76 + */ 1.77 +MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) { 1.78 + return static_cast<MatrixType>( 1.79 + (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask); 1.80 +} 1.81 + 1.82 +/** 1.83 + * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be 1.84 + * the same coordinate set as the original GrCoordTransform if the position and local coords are 1.85 + * identical for this program. 1.86 + */ 1.87 +GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) { 1.88 + return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ? 1.89 + kPosition_GrCoordSet : 1.90 + kLocal_GrCoordSet; 1.91 +} 1.92 + 1.93 +/** 1.94 + * Retrieves the final translation that a transform needs to apply to its source coords (and 1.95 + * verifies that a translation is all it needs). 1.96 + */ 1.97 +void get_transform_translation(const GrDrawEffect& drawEffect, 1.98 + int transformIdx, 1.99 + GrGLfloat* tx, 1.100 + GrGLfloat* ty) { 1.101 + const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx); 1.102 + SkASSERT(!coordTransform.reverseY()); 1.103 + const SkMatrix& matrix = coordTransform.getMatrix(); 1.104 + if (kLocal_GrCoordSet == coordTransform.sourceCoords() && 1.105 + !drawEffect.programHasExplicitLocalCoords()) { 1.106 + const SkMatrix& coordChangeMatrix = drawEffect.getCoordChangeMatrix(); 1.107 + SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType())); 1.108 + *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX]); 1.109 + *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY]); 1.110 + } else { 1.111 + SkASSERT(SkMatrix::kTranslate_Mask == matrix.getType()); 1.112 + *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX]); 1.113 + *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY]); 1.114 + } 1.115 +} 1.116 + 1.117 +/** 1.118 + * Retrieves the final matrix that a transform needs to apply to its source coords. 1.119 + */ 1.120 +SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) { 1.121 + const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx); 1.122 + SkMatrix combined; 1.123 + if (kLocal_GrCoordSet == coordTransform.sourceCoords() && 1.124 + !drawEffect.programHasExplicitLocalCoords()) { 1.125 + combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix()); 1.126 + } else { 1.127 + combined = coordTransform.getMatrix(); 1.128 + } 1.129 + if (coordTransform.reverseY()) { 1.130 + // combined.postScale(1,-1); 1.131 + // combined.postTranslate(0,1); 1.132 + combined.set(SkMatrix::kMSkewY, 1.133 + combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]); 1.134 + combined.set(SkMatrix::kMScaleY, 1.135 + combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]); 1.136 + combined.set(SkMatrix::kMTransY, 1.137 + combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]); 1.138 + } 1.139 + return combined; 1.140 +} 1.141 + 1.142 +} 1.143 + 1.144 +//////////////////////////////////////////////////////////////////////////////// 1.145 + 1.146 +EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) { 1.147 + EffectKey key = 0; 1.148 + int numAttributes = drawEffect.getVertexAttribIndexCount(); 1.149 + SkASSERT(numAttributes <= 2); 1.150 + const int* attributeIndices = drawEffect.getVertexAttribIndices(); 1.151 + for (int a = 0; a < numAttributes; ++a) { 1.152 + EffectKey value = attributeIndices[a] << 3 * a; 1.153 + SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap 1.154 + key |= value; 1.155 + } 1.156 + return key; 1.157 +} 1.158 + 1.159 +EffectKey GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) { 1.160 + EffectKey totalKey = 0; 1.161 + int numTransforms = (*drawEffect.effect())->numTransforms(); 1.162 + for (int t = 0; t < numTransforms; ++t) { 1.163 + EffectKey key = 0; 1.164 + const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(t); 1.165 + SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType(); 1.166 + SkMatrix::TypeMask type1; 1.167 + if (kLocal_GrCoordSet == coordTransform.sourceCoords()) { 1.168 + type1 = drawEffect.getCoordChangeMatrix().getType(); 1.169 + } else { 1.170 + if (drawEffect.programHasExplicitLocalCoords()) { 1.171 + // We only make the key indicate that device coords are referenced when the local coords 1.172 + // are not actually determined by positions. Otherwise the local coords var and position 1.173 + // var are identical. 1.174 + key |= kPositionCoords_Flag; 1.175 + } 1.176 + type1 = SkMatrix::kIdentity_Mask; 1.177 + } 1.178 + 1.179 + int combinedTypes = type0 | type1; 1.180 + 1.181 + bool reverseY = coordTransform.reverseY(); 1.182 + 1.183 + if (SkMatrix::kPerspective_Mask & combinedTypes) { 1.184 + key |= kGeneral_MatrixType; 1.185 + } else if (((SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask) & combinedTypes) || reverseY) { 1.186 + key |= kNoPersp_MatrixType; 1.187 + } else if (SkMatrix::kTranslate_Mask & combinedTypes) { 1.188 + key |= kTrans_MatrixType; 1.189 + } else { 1.190 + key |= kIdentity_MatrixType; 1.191 + } 1.192 + key <<= kTransformKeyBits * t; 1.193 + SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap 1.194 + totalKey |= key; 1.195 + } 1.196 + return totalKey; 1.197 +} 1.198 + 1.199 +EffectKey GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) { 1.200 + EffectKey key = 0; 1.201 + int numTextures = (*drawEffect.effect())->numTextures(); 1.202 + for (int t = 0; t < numTextures; ++t) { 1.203 + const GrTextureAccess& access = (*drawEffect.effect())->textureAccess(t); 1.204 + uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config()); 1.205 + if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) { 1.206 + key |= 1 << t; 1.207 + } 1.208 + } 1.209 + return key; 1.210 +} 1.211 + 1.212 +GrGLProgramEffects::~GrGLProgramEffects() { 1.213 + int numEffects = fGLEffects.count(); 1.214 + for (int e = 0; e < numEffects; ++e) { 1.215 + SkDELETE(fGLEffects[e]); 1.216 + } 1.217 +} 1.218 + 1.219 +void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder, 1.220 + const GrEffectRef& effect, 1.221 + TextureSamplerArray* outSamplers) { 1.222 + SkTArray<Sampler, true>& samplers = fSamplers.push_back(); 1.223 + int numTextures = effect->numTextures(); 1.224 + samplers.push_back_n(numTextures); 1.225 + SkString name; 1.226 + for (int t = 0; t < numTextures; ++t) { 1.227 + name.printf("Sampler%d", t); 1.228 + samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1.229 + kSampler2D_GrSLType, 1.230 + name.c_str()); 1.231 + SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler, 1.232 + (samplers[t].fUniform, effect->textureAccess(t))); 1.233 + } 1.234 +} 1.235 + 1.236 +void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) { 1.237 + int numEffects = fGLEffects.count(); 1.238 + SkASSERT(numEffects == fSamplers.count()); 1.239 + for (int e = 0; e < numEffects; ++e) { 1.240 + SkTArray<Sampler, true>& samplers = fSamplers[e]; 1.241 + int numSamplers = samplers.count(); 1.242 + for (int s = 0; s < numSamplers; ++s) { 1.243 + SkASSERT(samplers[s].fUniform.isValid()); 1.244 + uniformManager.setSampler(samplers[s].fUniform, *texUnitIdx); 1.245 + samplers[s].fTextureUnit = (*texUnitIdx)++; 1.246 + } 1.247 + } 1.248 +} 1.249 + 1.250 +void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) { 1.251 + const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx]; 1.252 + int numSamplers = samplers.count(); 1.253 + SkASSERT(numSamplers == effect->numTextures()); 1.254 + for (int s = 0; s < numSamplers; ++s) { 1.255 + SkASSERT(samplers[s].fTextureUnit >= 0); 1.256 + const GrTextureAccess& textureAccess = effect->textureAccess(s); 1.257 + gpu->bindTexture(samplers[s].fTextureUnit, 1.258 + textureAccess.getParams(), 1.259 + static_cast<GrGLTexture*>(textureAccess.getTexture())); 1.260 + } 1.261 +} 1.262 + 1.263 +//////////////////////////////////////////////////////////////////////////////// 1.264 + 1.265 +void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder, 1.266 + const GrEffectStage& stage, 1.267 + EffectKey key, 1.268 + const char* outColor, 1.269 + const char* inColor, 1.270 + int stageIndex) { 1.271 + GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords); 1.272 + const GrEffectRef& effect = *stage.getEffect(); 1.273 + SkSTArray<2, TransformedCoords> coords(effect->numTransforms()); 1.274 + SkSTArray<4, TextureSampler> samplers(effect->numTextures()); 1.275 + 1.276 + this->emitAttributes(builder, stage); 1.277 + this->emitTransforms(builder, effect, key, &coords); 1.278 + this->emitSamplers(builder, effect, &samplers); 1.279 + 1.280 + GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); 1.281 + fGLEffects.push_back(glEffect); 1.282 + 1.283 + // Enclose custom code in a block to avoid namespace conflicts 1.284 + SkString openBrace; 1.285 + openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name()); 1.286 + builder->vsCodeAppend(openBrace.c_str()); 1.287 + builder->fsCodeAppend(openBrace.c_str()); 1.288 + 1.289 + if (glEffect->isVertexEffect()) { 1.290 + GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect); 1.291 + vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); 1.292 + } else { 1.293 + glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); 1.294 + } 1.295 + 1.296 + builder->vsCodeAppend("\t}\n"); 1.297 + builder->fsCodeAppend("\t}\n"); 1.298 +} 1.299 + 1.300 +void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder, 1.301 + const GrEffectStage& stage) { 1.302 + int numAttributes = stage.getVertexAttribIndexCount(); 1.303 + const int* attributeIndices = stage.getVertexAttribIndices(); 1.304 + for (int a = 0; a < numAttributes; ++a) { 1.305 + // TODO: Make addAttribute mangle the name. 1.306 + SkString attributeName("aAttr"); 1.307 + attributeName.appendS32(attributeIndices[a]); 1.308 + builder->addEffectAttribute(attributeIndices[a], 1.309 + (*stage.getEffect())->vertexAttribType(a), 1.310 + attributeName); 1.311 + } 1.312 +} 1.313 + 1.314 +void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder, 1.315 + const GrEffectRef& effect, 1.316 + EffectKey effectKey, 1.317 + TransformedCoordsArray* outCoords) { 1.318 + SkTArray<Transform, true>& transforms = fTransforms.push_back(); 1.319 + EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); 1.320 + int numTransforms = effect->numTransforms(); 1.321 + transforms.push_back_n(numTransforms); 1.322 + for (int t = 0; t < numTransforms; t++) { 1.323 + GrSLType varyingType = kVoid_GrSLType; 1.324 + const char* uniName; 1.325 + switch (get_matrix_type(totalKey, t)) { 1.326 + case kIdentity_MatrixType: 1.327 + transforms[t].fType = kVoid_GrSLType; 1.328 + uniName = NULL; 1.329 + varyingType = kVec2f_GrSLType; 1.330 + break; 1.331 + case kTrans_MatrixType: 1.332 + transforms[t].fType = kVec2f_GrSLType; 1.333 + uniName = "StageTranslate"; 1.334 + varyingType = kVec2f_GrSLType; 1.335 + break; 1.336 + case kNoPersp_MatrixType: 1.337 + transforms[t].fType = kMat33f_GrSLType; 1.338 + uniName = "StageMatrix"; 1.339 + varyingType = kVec2f_GrSLType; 1.340 + break; 1.341 + case kGeneral_MatrixType: 1.342 + transforms[t].fType = kMat33f_GrSLType; 1.343 + uniName = "StageMatrix"; 1.344 + varyingType = kVec3f_GrSLType; 1.345 + break; 1.346 + default: 1.347 + GrCrash("Unexpected key."); 1.348 + } 1.349 + SkString suffixedUniName; 1.350 + if (kVoid_GrSLType != transforms[t].fType) { 1.351 + if (0 != t) { 1.352 + suffixedUniName.append(uniName); 1.353 + suffixedUniName.appendf("_%i", t); 1.354 + uniName = suffixedUniName.c_str(); 1.355 + } 1.356 + transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility, 1.357 + transforms[t].fType, 1.358 + uniName, 1.359 + &uniName); 1.360 + } 1.361 + 1.362 + const char* varyingName = "MatrixCoord"; 1.363 + SkString suffixedVaryingName; 1.364 + if (0 != t) { 1.365 + suffixedVaryingName.append(varyingName); 1.366 + suffixedVaryingName.appendf("_%i", t); 1.367 + varyingName = suffixedVaryingName.c_str(); 1.368 + } 1.369 + const char* vsVaryingName; 1.370 + const char* fsVaryingName; 1.371 + builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName); 1.372 + 1.373 + const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ? 1.374 + builder->positionAttribute() : 1.375 + builder->localCoordsAttribute(); 1.376 + // varying = matrix * coords (logically) 1.377 + switch (transforms[t].fType) { 1.378 + case kVoid_GrSLType: 1.379 + SkASSERT(kVec2f_GrSLType == varyingType); 1.380 + builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str()); 1.381 + break; 1.382 + case kVec2f_GrSLType: 1.383 + SkASSERT(kVec2f_GrSLType == varyingType); 1.384 + builder->vsCodeAppendf("\t%s = %s + %s;\n", 1.385 + vsVaryingName, uniName, coords.c_str()); 1.386 + break; 1.387 + case kMat33f_GrSLType: { 1.388 + SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); 1.389 + if (kVec2f_GrSLType == varyingType) { 1.390 + builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n", 1.391 + vsVaryingName, uniName, coords.c_str()); 1.392 + } else { 1.393 + builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n", 1.394 + vsVaryingName, uniName, coords.c_str()); 1.395 + } 1.396 + break; 1.397 + } 1.398 + default: 1.399 + GrCrash("Unexpected uniform type."); 1.400 + } 1.401 + SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, 1.402 + (SkString(fsVaryingName), varyingType)); 1.403 + } 1.404 +} 1.405 + 1.406 +void GrGLVertexProgramEffects::setData(GrGpuGL* gpu, 1.407 + const GrGLUniformManager& uniformManager, 1.408 + const GrEffectStage* effectStages[]) { 1.409 + int numEffects = fGLEffects.count(); 1.410 + SkASSERT(numEffects == fTransforms.count()); 1.411 + SkASSERT(numEffects == fSamplers.count()); 1.412 + for (int e = 0; e < numEffects; ++e) { 1.413 + GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords); 1.414 + fGLEffects[e]->setData(uniformManager, drawEffect); 1.415 + this->setTransformData(uniformManager, drawEffect, e); 1.416 + this->bindTextures(gpu, *drawEffect.effect(), e); 1.417 + } 1.418 +} 1.419 + 1.420 +void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager, 1.421 + const GrDrawEffect& drawEffect, 1.422 + int effectIdx) { 1.423 + SkTArray<Transform, true>& transforms = fTransforms[effectIdx]; 1.424 + int numTransforms = transforms.count(); 1.425 + SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms()); 1.426 + for (int t = 0; t < numTransforms; ++t) { 1.427 + SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType)); 1.428 + switch (transforms[t].fType) { 1.429 + case kVoid_GrSLType: 1.430 + SkASSERT(get_transform_matrix(drawEffect, t).isIdentity()); 1.431 + return; 1.432 + case kVec2f_GrSLType: { 1.433 + GrGLfloat tx, ty; 1.434 + get_transform_translation(drawEffect, t, &tx, &ty); 1.435 + if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx || 1.436 + transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) { 1.437 + uniformManager.set2f(transforms[t].fHandle, tx, ty); 1.438 + transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx); 1.439 + transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty); 1.440 + } 1.441 + break; 1.442 + } 1.443 + case kMat33f_GrSLType: { 1.444 + const SkMatrix& matrix = get_transform_matrix(drawEffect, t); 1.445 + if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) { 1.446 + uniformManager.setSkMatrix(transforms[t].fHandle, matrix); 1.447 + transforms[t].fCurrentValue = matrix; 1.448 + } 1.449 + break; 1.450 + } 1.451 + default: 1.452 + GrCrash("Unexpected uniform type."); 1.453 + } 1.454 + } 1.455 +} 1.456 + 1.457 +GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder, 1.458 + int reserveCount) 1.459 + : fBuilder(builder) 1.460 + , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects, 1.461 + (reserveCount, fBuilder->hasExplicitLocalCoords()))) { 1.462 +} 1.463 + 1.464 +void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, 1.465 + GrGLProgramEffects::EffectKey key, 1.466 + const char* outColor, 1.467 + const char* inColor, 1.468 + int stageIndex) { 1.469 + SkASSERT(NULL != fProgramEffects.get()); 1.470 + fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex); 1.471 +} 1.472 + 1.473 +//////////////////////////////////////////////////////////////////////////////// 1.474 + 1.475 +void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder, 1.476 + const GrEffectStage& stage, 1.477 + EffectKey key, 1.478 + const char* outColor, 1.479 + const char* inColor, 1.480 + int stageIndex) { 1.481 + GrDrawEffect drawEffect(stage, false); 1.482 + const GrEffectRef& effect = *stage.getEffect(); 1.483 + SkSTArray<2, TransformedCoords> coords(effect->numTransforms()); 1.484 + SkSTArray<4, TextureSampler> samplers(effect->numTextures()); 1.485 + 1.486 + SkASSERT(0 == stage.getVertexAttribIndexCount()); 1.487 + this->setupTexGen(builder, effect, key, &coords); 1.488 + this->emitSamplers(builder, effect, &samplers); 1.489 + 1.490 + GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect); 1.491 + fGLEffects.push_back(glEffect); 1.492 + 1.493 + // Enclose custom code in a block to avoid namespace conflicts 1.494 + SkString openBrace; 1.495 + openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name()); 1.496 + builder->fsCodeAppend(openBrace.c_str()); 1.497 + 1.498 + SkASSERT(!glEffect->isVertexEffect()); 1.499 + glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers); 1.500 + 1.501 + builder->fsCodeAppend("\t}\n"); 1.502 +} 1.503 + 1.504 +void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder, 1.505 + const GrEffectRef& effect, 1.506 + EffectKey effectKey, 1.507 + TransformedCoordsArray* outCoords) { 1.508 + int numTransforms = effect->numTransforms(); 1.509 + EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey); 1.510 + int texCoordIndex = builder->addTexCoordSets(numTransforms); 1.511 + SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex)); 1.512 + SkString name; 1.513 + for (int t = 0; t < numTransforms; ++t) { 1.514 + GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ? 1.515 + kVec3f_GrSLType : 1.516 + kVec2f_GrSLType; 1.517 + name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++); 1.518 + SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type)); 1.519 + } 1.520 +} 1.521 + 1.522 +void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu, 1.523 + const GrGLUniformManager& uniformManager, 1.524 + const GrEffectStage* effectStages[]) { 1.525 + int numEffects = fGLEffects.count(); 1.526 + SkASSERT(numEffects == fTransforms.count()); 1.527 + SkASSERT(numEffects == fSamplers.count()); 1.528 + for (int e = 0; e < numEffects; ++e) { 1.529 + GrDrawEffect drawEffect(*effectStages[e], false); 1.530 + fGLEffects[e]->setData(uniformManager, drawEffect); 1.531 + this->setTexGenState(gpu, drawEffect, e); 1.532 + this->bindTextures(gpu, *drawEffect.effect(), e); 1.533 + } 1.534 +} 1.535 + 1.536 +void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu, 1.537 + const GrDrawEffect& drawEffect, 1.538 + int effectIdx) { 1.539 + EffectKey totalKey = fTransforms[effectIdx].fTransformKey; 1.540 + int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex; 1.541 + int numTransforms = (*drawEffect.effect())->numTransforms(); 1.542 + for (int t = 0; t < numTransforms; ++t) { 1.543 + switch (get_matrix_type(totalKey, t)) { 1.544 + case kIdentity_MatrixType: { 1.545 + SkASSERT(get_transform_matrix(drawEffect, t).isIdentity()); 1.546 + GrGLfloat identity[] = {1, 0, 0, 1.547 + 0, 1, 0}; 1.548 + gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity); 1.549 + break; 1.550 + } 1.551 + case kTrans_MatrixType: { 1.552 + GrGLfloat tx, ty; 1.553 + get_transform_translation(drawEffect, t, &tx, &ty); 1.554 + GrGLfloat translate[] = {1, 0, tx, 1.555 + 0, 1, ty}; 1.556 + gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate); 1.557 + break; 1.558 + } 1.559 + case kNoPersp_MatrixType: { 1.560 + const SkMatrix& transform = get_transform_matrix(drawEffect, t); 1.561 + gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform); 1.562 + break; 1.563 + } 1.564 + case kGeneral_MatrixType: { 1.565 + const SkMatrix& transform = get_transform_matrix(drawEffect, t); 1.566 + gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform); 1.567 + break; 1.568 + } 1.569 + default: 1.570 + GrCrash("Unexpected matrixs type."); 1.571 + } 1.572 + } 1.573 +} 1.574 + 1.575 +GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder( 1.576 + GrGLFragmentOnlyShaderBuilder* builder, 1.577 + int reserveCount) 1.578 + : fBuilder(builder) 1.579 + , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) { 1.580 +} 1.581 + 1.582 +void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage, 1.583 + GrGLProgramEffects::EffectKey key, 1.584 + const char* outColor, 1.585 + const char* inColor, 1.586 + int stageIndex) { 1.587 + SkASSERT(NULL != fProgramEffects.get()); 1.588 + fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex); 1.589 +}