Home | History | Annotate | Download | only in gl
      1 /*
      2  * Copyright 2013 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrGLProgramEffects.h"
      9 #include "GrDrawEffect.h"
     10 #include "gl/GrGLEffect.h"
     11 #include "gl/GrGLShaderBuilder.h"
     12 #include "gl/GrGLVertexEffect.h"
     13 #include "gl/GrGpuGL.h"
     14 
     15 typedef GrGLProgramEffects::EffectKey EffectKey;
     16 typedef GrGLProgramEffects::TransformedCoords TransformedCoords;
     17 typedef GrGLProgramEffects::TransformedCoordsArray TransformedCoordsArray;
     18 typedef GrGLProgramEffects::TextureSampler TextureSampler;
     19 typedef GrGLProgramEffects::TextureSamplerArray TextureSamplerArray;
     20 
     21 /**
     22  * We specialize the vertex code for each of these matrix types.
     23  */
     24 enum MatrixType {
     25     kIdentity_MatrixType = 0,
     26     kTrans_MatrixType    = 1,
     27     kNoPersp_MatrixType  = 2,
     28     kGeneral_MatrixType  = 3,
     29 };
     30 
     31 /**
     32  * The key for an individual coord transform is made up of a matrix type and a bit that
     33  * indicates the source of the input coords.
     34  */
     35 enum {
     36     kMatrixTypeKeyBits   = 2,
     37     kMatrixTypeKeyMask   = (1 << kMatrixTypeKeyBits) - 1,
     38     kPositionCoords_Flag = (1 << kMatrixTypeKeyBits),
     39     kTransformKeyBits    = kMatrixTypeKeyBits + 1,
     40 };
     41 
     42 namespace {
     43 
     44 /**
     45  * Do we need to either map r,g,b->a or a->r. configComponentMask indicates which channels are
     46  * present in the texture's config. swizzleComponentMask indicates the channels present in the
     47  * shader swizzle.
     48  */
     49 inline bool swizzle_requires_alpha_remapping(const GrGLCaps& caps,
     50                                              uint32_t configComponentMask,
     51                                              uint32_t swizzleComponentMask) {
     52     if (caps.textureSwizzleSupport()) {
     53         // Any remapping is handled using texture swizzling not shader modifications.
     54         return false;
     55     }
     56     // check if the texture is alpha-only
     57     if (kA_GrColorComponentFlag == configComponentMask) {
     58         if (caps.textureRedSupport() && (kA_GrColorComponentFlag & swizzleComponentMask)) {
     59             // we must map the swizzle 'a's to 'r'.
     60             return true;
     61         }
     62         if (kRGB_GrColorComponentFlags & swizzleComponentMask) {
     63             // The 'r', 'g', and/or 'b's must be mapped to 'a' according to our semantics that
     64             // alpha-only textures smear alpha across all four channels when read.
     65             return true;
     66         }
     67     }
     68     return false;
     69 }
     70 
     71 /**
     72  * Retrieves the matrix type from transformKey for the transform at transformIdx.
     73  */
     74 MatrixType get_matrix_type(EffectKey transformKey, int transformIdx) {
     75     return static_cast<MatrixType>(
     76                (transformKey >> (kTransformKeyBits * transformIdx)) & kMatrixTypeKeyMask);
     77 }
     78 
     79 /**
     80  * Retrieves the source coords from transformKey for the transform at transformIdx. It may not be
     81  * the same coordinate set as the original GrCoordTransform if the position and local coords are
     82  * identical for this program.
     83  */
     84 GrCoordSet get_source_coords(EffectKey transformKey, int transformIdx) {
     85     return (transformKey >> (kTransformKeyBits * transformIdx)) & kPositionCoords_Flag ?
     86                kPosition_GrCoordSet :
     87                kLocal_GrCoordSet;
     88 }
     89 
     90 /**
     91  * Retrieves the final translation that a transform needs to apply to its source coords (and
     92  * verifies that a translation is all it needs).
     93  */
     94 void get_transform_translation(const GrDrawEffect& drawEffect,
     95                                int transformIdx,
     96                                GrGLfloat* tx,
     97                                GrGLfloat* ty) {
     98     const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
     99     SkASSERT(!coordTransform.reverseY());
    100     const SkMatrix& matrix = coordTransform.getMatrix();
    101     if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
    102         !drawEffect.programHasExplicitLocalCoords()) {
    103         const SkMatrix& coordChangeMatrix = drawEffect.getCoordChangeMatrix();
    104         SkASSERT(SkMatrix::kTranslate_Mask == (matrix.getType() | coordChangeMatrix.getType()));
    105         *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX] + coordChangeMatrix[SkMatrix::kMTransX]);
    106         *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY] + coordChangeMatrix[SkMatrix::kMTransY]);
    107     } else {
    108         SkASSERT(SkMatrix::kTranslate_Mask == matrix.getType());
    109         *tx = SkScalarToFloat(matrix[SkMatrix::kMTransX]);
    110         *ty = SkScalarToFloat(matrix[SkMatrix::kMTransY]);
    111     }
    112 }
    113 
    114 /**
    115  * Retrieves the final matrix that a transform needs to apply to its source coords.
    116  */
    117 SkMatrix get_transform_matrix(const GrDrawEffect& drawEffect, int transformIdx) {
    118     const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(transformIdx);
    119     SkMatrix combined;
    120     if (kLocal_GrCoordSet == coordTransform.sourceCoords() &&
    121         !drawEffect.programHasExplicitLocalCoords()) {
    122         combined.setConcat(coordTransform.getMatrix(), drawEffect.getCoordChangeMatrix());
    123     } else {
    124         combined = coordTransform.getMatrix();
    125     }
    126     if (coordTransform.reverseY()) {
    127         // combined.postScale(1,-1);
    128         // combined.postTranslate(0,1);
    129         combined.set(SkMatrix::kMSkewY,
    130             combined[SkMatrix::kMPersp0] - combined[SkMatrix::kMSkewY]);
    131         combined.set(SkMatrix::kMScaleY,
    132             combined[SkMatrix::kMPersp1] - combined[SkMatrix::kMScaleY]);
    133         combined.set(SkMatrix::kMTransY,
    134             combined[SkMatrix::kMPersp2] - combined[SkMatrix::kMTransY]);
    135     }
    136     return combined;
    137 }
    138 
    139 }
    140 
    141 ////////////////////////////////////////////////////////////////////////////////
    142 
    143 EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
    144     EffectKey key = 0;
    145     int numAttributes = drawEffect.getVertexAttribIndexCount();
    146     SkASSERT(numAttributes <= 2);
    147     const int* attributeIndices = drawEffect.getVertexAttribIndices();
    148     for (int a = 0; a < numAttributes; ++a) {
    149         EffectKey value = attributeIndices[a] << 3 * a;
    150         SkASSERT(0 == (value & key)); // keys for each attribute ought not to overlap
    151         key |= value;
    152     }
    153     return key;
    154 }
    155 
    156 EffectKey GrGLProgramEffects::GenTransformKey(const GrDrawEffect& drawEffect) {
    157     EffectKey totalKey = 0;
    158     int numTransforms = (*drawEffect.effect())->numTransforms();
    159     for (int t = 0; t < numTransforms; ++t) {
    160         EffectKey key = 0;
    161         const GrCoordTransform& coordTransform = (*drawEffect.effect())->coordTransform(t);
    162         SkMatrix::TypeMask type0 = coordTransform.getMatrix().getType();
    163         SkMatrix::TypeMask type1;
    164         if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
    165             type1 = drawEffect.getCoordChangeMatrix().getType();
    166         } else {
    167             if (drawEffect.programHasExplicitLocalCoords()) {
    168                 // We only make the key indicate that device coords are referenced when the local coords
    169                 // are not actually determined by positions. Otherwise the local coords var and position
    170                 // var are identical.
    171                 key |= kPositionCoords_Flag;
    172             }
    173             type1 = SkMatrix::kIdentity_Mask;
    174         }
    175 
    176         int combinedTypes = type0 | type1;
    177 
    178         bool reverseY = coordTransform.reverseY();
    179 
    180         if (SkMatrix::kPerspective_Mask & combinedTypes) {
    181             key |= kGeneral_MatrixType;
    182         } else if (((SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask) & combinedTypes) || reverseY) {
    183             key |= kNoPersp_MatrixType;
    184         } else if (SkMatrix::kTranslate_Mask & combinedTypes) {
    185             key |= kTrans_MatrixType;
    186         } else {
    187             key |= kIdentity_MatrixType;
    188         }
    189         key <<= kTransformKeyBits * t;
    190         SkASSERT(0 == (totalKey & key)); // keys for each transform ought not to overlap
    191         totalKey |= key;
    192     }
    193     return totalKey;
    194 }
    195 
    196 EffectKey GrGLProgramEffects::GenTextureKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps) {
    197     EffectKey key = 0;
    198     int numTextures = (*drawEffect.effect())->numTextures();
    199     for (int t = 0; t < numTextures; ++t) {
    200         const GrTextureAccess& access = (*drawEffect.effect())->textureAccess(t);
    201         uint32_t configComponentMask = GrPixelConfigComponentMask(access.getTexture()->config());
    202         if (swizzle_requires_alpha_remapping(caps, configComponentMask, access.swizzleMask())) {
    203             key |= 1 << t;
    204         }
    205     }
    206     return key;
    207 }
    208 
    209 GrGLProgramEffects::~GrGLProgramEffects() {
    210     int numEffects = fGLEffects.count();
    211     for (int e = 0; e < numEffects; ++e) {
    212         SkDELETE(fGLEffects[e]);
    213     }
    214 }
    215 
    216 void GrGLProgramEffects::emitSamplers(GrGLShaderBuilder* builder,
    217                                       const GrEffectRef& effect,
    218                                       TextureSamplerArray* outSamplers) {
    219     SkTArray<Sampler, true>& samplers = fSamplers.push_back();
    220     int numTextures = effect->numTextures();
    221     samplers.push_back_n(numTextures);
    222     SkString name;
    223     for (int t = 0; t < numTextures; ++t) {
    224         name.printf("Sampler%d", t);
    225         samplers[t].fUniform = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
    226                                                    kSampler2D_GrSLType,
    227                                                    name.c_str());
    228         SkNEW_APPEND_TO_TARRAY(outSamplers, TextureSampler,
    229                                (samplers[t].fUniform, effect->textureAccess(t)));
    230     }
    231 }
    232 
    233 void GrGLProgramEffects::initSamplers(const GrGLUniformManager& uniformManager, int* texUnitIdx) {
    234     int numEffects = fGLEffects.count();
    235     SkASSERT(numEffects == fSamplers.count());
    236     for (int e = 0; e < numEffects; ++e) {
    237         SkTArray<Sampler, true>& samplers = fSamplers[e];
    238         int numSamplers = samplers.count();
    239         for (int s = 0; s < numSamplers; ++s) {
    240             SkASSERT(samplers[s].fUniform.isValid());
    241             uniformManager.setSampler(samplers[s].fUniform, *texUnitIdx);
    242             samplers[s].fTextureUnit = (*texUnitIdx)++;
    243         }
    244     }
    245 }
    246 
    247 void GrGLProgramEffects::bindTextures(GrGpuGL* gpu, const GrEffectRef& effect, int effectIdx) {
    248     const SkTArray<Sampler, true>& samplers = fSamplers[effectIdx];
    249     int numSamplers = samplers.count();
    250     SkASSERT(numSamplers == effect->numTextures());
    251     for (int s = 0; s < numSamplers; ++s) {
    252         SkASSERT(samplers[s].fTextureUnit >= 0);
    253         const GrTextureAccess& textureAccess = effect->textureAccess(s);
    254         gpu->bindTexture(samplers[s].fTextureUnit,
    255                          textureAccess.getParams(),
    256                          static_cast<GrGLTexture*>(textureAccess.getTexture()));
    257     }
    258 }
    259 
    260 ////////////////////////////////////////////////////////////////////////////////
    261 
    262 void GrGLVertexProgramEffects::emitEffect(GrGLFullShaderBuilder* builder,
    263                                           const GrEffectStage& stage,
    264                                           EffectKey key,
    265                                           const char* outColor,
    266                                           const char* inColor,
    267                                           int stageIndex) {
    268     GrDrawEffect drawEffect(stage, fHasExplicitLocalCoords);
    269     const GrEffectRef& effect = *stage.getEffect();
    270     SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
    271     SkSTArray<4, TextureSampler> samplers(effect->numTextures());
    272 
    273     this->emitAttributes(builder, stage);
    274     this->emitTransforms(builder, effect, key, &coords);
    275     this->emitSamplers(builder, effect, &samplers);
    276 
    277     GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
    278     fGLEffects.push_back(glEffect);
    279 
    280     // Enclose custom code in a block to avoid namespace conflicts
    281     SkString openBrace;
    282     openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
    283     builder->vsCodeAppend(openBrace.c_str());
    284     builder->fsCodeAppend(openBrace.c_str());
    285 
    286     if (glEffect->isVertexEffect()) {
    287         GrGLVertexEffect* vertexEffect = static_cast<GrGLVertexEffect*>(glEffect);
    288         vertexEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
    289     } else {
    290         glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
    291     }
    292 
    293     builder->vsCodeAppend("\t}\n");
    294     builder->fsCodeAppend("\t}\n");
    295 }
    296 
    297 void GrGLVertexProgramEffects::emitAttributes(GrGLFullShaderBuilder* builder,
    298                                               const GrEffectStage& stage) {
    299     int numAttributes = stage.getVertexAttribIndexCount();
    300     const int* attributeIndices = stage.getVertexAttribIndices();
    301     for (int a = 0; a < numAttributes; ++a) {
    302         // TODO: Make addAttribute mangle the name.
    303         SkString attributeName("aAttr");
    304         attributeName.appendS32(attributeIndices[a]);
    305         builder->addEffectAttribute(attributeIndices[a],
    306                                     (*stage.getEffect())->vertexAttribType(a),
    307                                     attributeName);
    308     }
    309 }
    310 
    311 void GrGLVertexProgramEffects::emitTransforms(GrGLFullShaderBuilder* builder,
    312                                               const GrEffectRef& effect,
    313                                               EffectKey effectKey,
    314                                               TransformedCoordsArray* outCoords) {
    315     SkTArray<Transform, true>& transforms = fTransforms.push_back();
    316     EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
    317     int numTransforms = effect->numTransforms();
    318     transforms.push_back_n(numTransforms);
    319     for (int t = 0; t < numTransforms; t++) {
    320         GrSLType varyingType = kVoid_GrSLType;
    321         const char* uniName;
    322         switch (get_matrix_type(totalKey, t)) {
    323             case kIdentity_MatrixType:
    324                 transforms[t].fType = kVoid_GrSLType;
    325                 uniName = NULL;
    326                 varyingType = kVec2f_GrSLType;
    327                 break;
    328             case kTrans_MatrixType:
    329                 transforms[t].fType = kVec2f_GrSLType;
    330                 uniName = "StageTranslate";
    331                 varyingType = kVec2f_GrSLType;
    332                 break;
    333             case kNoPersp_MatrixType:
    334                 transforms[t].fType = kMat33f_GrSLType;
    335                 uniName = "StageMatrix";
    336                 varyingType = kVec2f_GrSLType;
    337                 break;
    338             case kGeneral_MatrixType:
    339                 transforms[t].fType = kMat33f_GrSLType;
    340                 uniName = "StageMatrix";
    341                 varyingType = kVec3f_GrSLType;
    342                 break;
    343             default:
    344                 GrCrash("Unexpected key.");
    345         }
    346         SkString suffixedUniName;
    347         if (kVoid_GrSLType != transforms[t].fType) {
    348             if (0 != t) {
    349                 suffixedUniName.append(uniName);
    350                 suffixedUniName.appendf("_%i", t);
    351                 uniName = suffixedUniName.c_str();
    352             }
    353             transforms[t].fHandle = builder->addUniform(GrGLShaderBuilder::kVertex_Visibility,
    354                                                         transforms[t].fType,
    355                                                         uniName,
    356                                                         &uniName);
    357         }
    358 
    359         const char* varyingName = "MatrixCoord";
    360         SkString suffixedVaryingName;
    361         if (0 != t) {
    362             suffixedVaryingName.append(varyingName);
    363             suffixedVaryingName.appendf("_%i", t);
    364             varyingName = suffixedVaryingName.c_str();
    365         }
    366         const char* vsVaryingName;
    367         const char* fsVaryingName;
    368         builder->addVarying(varyingType, varyingName, &vsVaryingName, &fsVaryingName);
    369 
    370         const GrGLShaderVar& coords = kPosition_GrCoordSet == get_source_coords(totalKey, t) ?
    371                                           builder->positionAttribute() :
    372                                           builder->localCoordsAttribute();
    373         // varying = matrix * coords (logically)
    374         switch (transforms[t].fType) {
    375             case kVoid_GrSLType:
    376                 SkASSERT(kVec2f_GrSLType == varyingType);
    377                 builder->vsCodeAppendf("\t%s = %s;\n", vsVaryingName, coords.c_str());
    378                 break;
    379             case kVec2f_GrSLType:
    380                 SkASSERT(kVec2f_GrSLType == varyingType);
    381                 builder->vsCodeAppendf("\t%s = %s + %s;\n",
    382                                        vsVaryingName, uniName, coords.c_str());
    383                 break;
    384             case kMat33f_GrSLType: {
    385                 SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
    386                 if (kVec2f_GrSLType == varyingType) {
    387                     builder->vsCodeAppendf("\t%s = (%s * vec3(%s, 1)).xy;\n",
    388                                            vsVaryingName, uniName, coords.c_str());
    389                 } else {
    390                     builder->vsCodeAppendf("\t%s = %s * vec3(%s, 1);\n",
    391                                            vsVaryingName, uniName, coords.c_str());
    392                 }
    393                 break;
    394             }
    395             default:
    396                 GrCrash("Unexpected uniform type.");
    397         }
    398         SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords,
    399                                (SkString(fsVaryingName), varyingType));
    400     }
    401 }
    402 
    403 void GrGLVertexProgramEffects::setData(GrGpuGL* gpu,
    404                                        const GrGLUniformManager& uniformManager,
    405                                        const GrEffectStage* effectStages[]) {
    406     int numEffects = fGLEffects.count();
    407     SkASSERT(numEffects == fTransforms.count());
    408     SkASSERT(numEffects == fSamplers.count());
    409     for (int e = 0; e < numEffects; ++e) {
    410         GrDrawEffect drawEffect(*effectStages[e], fHasExplicitLocalCoords);
    411         fGLEffects[e]->setData(uniformManager, drawEffect);
    412         this->setTransformData(uniformManager, drawEffect, e);
    413         this->bindTextures(gpu, *drawEffect.effect(), e);
    414     }
    415 }
    416 
    417 void GrGLVertexProgramEffects::setTransformData(const GrGLUniformManager& uniformManager,
    418                                                 const GrDrawEffect& drawEffect,
    419                                                 int effectIdx) {
    420     SkTArray<Transform, true>& transforms = fTransforms[effectIdx];
    421     int numTransforms = transforms.count();
    422     SkASSERT(numTransforms == (*drawEffect.effect())->numTransforms());
    423     for (int t = 0; t < numTransforms; ++t) {
    424         SkASSERT(transforms[t].fHandle.isValid() != (kVoid_GrSLType == transforms[t].fType));
    425         switch (transforms[t].fType) {
    426             case kVoid_GrSLType:
    427                 SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
    428                 return;
    429             case kVec2f_GrSLType: {
    430                 GrGLfloat tx, ty;
    431                 get_transform_translation(drawEffect, t, &tx, &ty);
    432                 if (transforms[t].fCurrentValue.get(SkMatrix::kMTransX) != tx ||
    433                     transforms[t].fCurrentValue.get(SkMatrix::kMTransY) != ty) {
    434                     uniformManager.set2f(transforms[t].fHandle, tx, ty);
    435                     transforms[t].fCurrentValue.set(SkMatrix::kMTransX, tx);
    436                     transforms[t].fCurrentValue.set(SkMatrix::kMTransY, ty);
    437                 }
    438                 break;
    439             }
    440             case kMat33f_GrSLType: {
    441                 const SkMatrix& matrix = get_transform_matrix(drawEffect, t);
    442                 if (!transforms[t].fCurrentValue.cheapEqualTo(matrix)) {
    443                     uniformManager.setSkMatrix(transforms[t].fHandle, matrix);
    444                     transforms[t].fCurrentValue = matrix;
    445                 }
    446                 break;
    447             }
    448             default:
    449                 GrCrash("Unexpected uniform type.");
    450         }
    451     }
    452 }
    453 
    454 GrGLVertexProgramEffectsBuilder::GrGLVertexProgramEffectsBuilder(GrGLFullShaderBuilder* builder,
    455                                                                  int reserveCount)
    456     : fBuilder(builder)
    457     , fProgramEffects(SkNEW_ARGS(GrGLVertexProgramEffects,
    458                                  (reserveCount, fBuilder->hasExplicitLocalCoords()))) {
    459 }
    460 
    461 void GrGLVertexProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
    462                                                  GrGLProgramEffects::EffectKey key,
    463                                                  const char* outColor,
    464                                                  const char* inColor,
    465                                                  int stageIndex) {
    466     SkASSERT(NULL != fProgramEffects.get());
    467     fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
    468 }
    469 
    470 ////////////////////////////////////////////////////////////////////////////////
    471 
    472 void GrGLTexGenProgramEffects::emitEffect(GrGLFragmentOnlyShaderBuilder* builder,
    473                                           const GrEffectStage& stage,
    474                                           EffectKey key,
    475                                           const char* outColor,
    476                                           const char* inColor,
    477                                           int stageIndex) {
    478     GrDrawEffect drawEffect(stage, false);
    479     const GrEffectRef& effect = *stage.getEffect();
    480     SkSTArray<2, TransformedCoords> coords(effect->numTransforms());
    481     SkSTArray<4, TextureSampler> samplers(effect->numTextures());
    482 
    483     SkASSERT(0 == stage.getVertexAttribIndexCount());
    484     this->setupTexGen(builder, effect, key, &coords);
    485     this->emitSamplers(builder, effect, &samplers);
    486 
    487     GrGLEffect* glEffect = effect->getFactory().createGLInstance(drawEffect);
    488     fGLEffects.push_back(glEffect);
    489 
    490     // Enclose custom code in a block to avoid namespace conflicts
    491     SkString openBrace;
    492     openBrace.printf("\t{ // Stage %d: %s\n", stageIndex, glEffect->name());
    493     builder->fsCodeAppend(openBrace.c_str());
    494 
    495     SkASSERT(!glEffect->isVertexEffect());
    496     glEffect->emitCode(builder, drawEffect, key, outColor, inColor, coords, samplers);
    497 
    498     builder->fsCodeAppend("\t}\n");
    499 }
    500 
    501 void GrGLTexGenProgramEffects::setupTexGen(GrGLFragmentOnlyShaderBuilder* builder,
    502                                            const GrEffectRef& effect,
    503                                            EffectKey effectKey,
    504                                            TransformedCoordsArray* outCoords) {
    505     int numTransforms = effect->numTransforms();
    506     EffectKey totalKey = GrBackendEffectFactory::GetTransformKey(effectKey);
    507     int texCoordIndex = builder->addTexCoordSets(numTransforms);
    508     SkNEW_APPEND_TO_TARRAY(&fTransforms, Transforms, (totalKey, texCoordIndex));
    509     SkString name;
    510     for (int t = 0; t < numTransforms; ++t) {
    511         GrSLType type = kGeneral_MatrixType == get_matrix_type(totalKey, t) ?
    512                             kVec3f_GrSLType :
    513                             kVec2f_GrSLType;
    514         name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
    515         SkNEW_APPEND_TO_TARRAY(outCoords, TransformedCoords, (name, type));
    516     }
    517 }
    518 
    519 void GrGLTexGenProgramEffects::setData(GrGpuGL* gpu,
    520                                        const GrGLUniformManager& uniformManager,
    521                                        const GrEffectStage* effectStages[]) {
    522     int numEffects = fGLEffects.count();
    523     SkASSERT(numEffects == fTransforms.count());
    524     SkASSERT(numEffects == fSamplers.count());
    525     for (int e = 0; e < numEffects; ++e) {
    526         GrDrawEffect drawEffect(*effectStages[e], false);
    527         fGLEffects[e]->setData(uniformManager, drawEffect);
    528         this->setTexGenState(gpu, drawEffect, e);
    529         this->bindTextures(gpu, *drawEffect.effect(), e);
    530     }
    531 }
    532 
    533 void GrGLTexGenProgramEffects::setTexGenState(GrGpuGL* gpu,
    534                                               const GrDrawEffect& drawEffect,
    535                                               int effectIdx) {
    536     EffectKey totalKey = fTransforms[effectIdx].fTransformKey;
    537     int texCoordIndex = fTransforms[effectIdx].fTexCoordIndex;
    538     int numTransforms = (*drawEffect.effect())->numTransforms();
    539     for (int t = 0; t < numTransforms; ++t) {
    540         switch (get_matrix_type(totalKey, t)) {
    541             case kIdentity_MatrixType: {
    542                 SkASSERT(get_transform_matrix(drawEffect, t).isIdentity());
    543                 GrGLfloat identity[] = {1, 0, 0,
    544                                         0, 1, 0};
    545                 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, identity);
    546                 break;
    547             }
    548             case kTrans_MatrixType: {
    549                 GrGLfloat tx, ty;
    550                 get_transform_translation(drawEffect, t, &tx, &ty);
    551                 GrGLfloat translate[] = {1, 0, tx,
    552                                          0, 1, ty};
    553                 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, translate);
    554                 break;
    555             }
    556             case kNoPersp_MatrixType: {
    557                 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
    558                 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kST_TexGenComponents, transform);
    559                 break;
    560             }
    561             case kGeneral_MatrixType: {
    562                 const SkMatrix& transform = get_transform_matrix(drawEffect, t);
    563                 gpu->enableTexGen(texCoordIndex++, GrGpuGL::kSTR_TexGenComponents, transform);
    564                 break;
    565             }
    566             default:
    567                 GrCrash("Unexpected matrixs type.");
    568         }
    569     }
    570 }
    571 
    572 GrGLTexGenProgramEffectsBuilder::GrGLTexGenProgramEffectsBuilder(
    573         GrGLFragmentOnlyShaderBuilder* builder,
    574         int reserveCount)
    575     : fBuilder(builder)
    576     , fProgramEffects(SkNEW_ARGS(GrGLTexGenProgramEffects, (reserveCount))) {
    577 }
    578 
    579 void GrGLTexGenProgramEffectsBuilder::emitEffect(const GrEffectStage& stage,
    580                                                  GrGLProgramEffects::EffectKey key,
    581                                                  const char* outColor,
    582                                                  const char* inColor,
    583                                                  int stageIndex) {
    584     SkASSERT(NULL != fProgramEffects.get());
    585     fProgramEffects->emitEffect(fBuilder, stage, key, outColor, inColor, stageIndex);
    586 }
    587