| Index: src/gpu/gl/GrGLProgramEffects.cpp
 | 
| diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp
 | 
| index d5826abe3042e9e1eb9057996d763483161a3044..17c666a015b87369c631ec65f027dcc33b66baa0 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);
 | 
| +}
 | 
| 
 |