| Index: src/gpu/gl/GrGLProgramDesc.cpp
 | 
| diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
 | 
| index 545ed2114c7d5ea01512cae139f7f0537bb9e15b..8d0ea3d6b370f7df36ce9a6a90cf4eb21a2df00b 100644
 | 
| --- a/src/gpu/gl/GrGLProgramDesc.cpp
 | 
| +++ b/src/gpu/gl/GrGLProgramDesc.cpp
 | 
| @@ -53,6 +53,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|                              GrBlendCoeff dstCoeff,
 | 
|                              const GrGpuGL* gpu,
 | 
|                              const GrDeviceCoordTexture* dstCopy,
 | 
| +                            const GrEffectStage** geometryProcessor,
 | 
|                              SkTArray<const GrEffectStage*, true>* colorStages,
 | 
|                              SkTArray<const GrEffectStage*, true>* coverageStages,
 | 
|                              GrGLProgramDesc* desc) {
 | 
| @@ -69,6 +70,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|  
 | 
|      int firstEffectiveColorStage = 0;
 | 
|      bool inputColorIsUsed = true;
 | 
| +
 | 
|      if (!skipColor) {
 | 
|          firstEffectiveColorStage = drawState.numColorStages();
 | 
|          while (firstEffectiveColorStage > 0 && inputColorIsUsed) {
 | 
| @@ -107,6 +109,9 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|      bool requiresVertexShader = !GrGpu::IsPathRenderingDrawType(drawType);
 | 
|  
 | 
|      int numStages = 0;
 | 
| +    if (drawState.hasGeometryProcessor()) {
 | 
| +        numStages++;
 | 
| +    }
 | 
|      if (!skipColor) {
 | 
|          numStages += drawState.numColorStages() - firstEffectiveColorStage;
 | 
|      }
 | 
| @@ -120,12 +125,42 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|  
 | 
|      int offsetAndSizeIndex = 0;
 | 
|      bool effectKeySuccess = true;
 | 
| +
 | 
| +    KeyHeader* header = desc->header();
 | 
| +    // make sure any padding in the header is zeroed.
 | 
| +    memset(desc->header(), 0, kHeaderSize);
 | 
| +
 | 
| +    // We can only have one effect which touches the vertex shader
 | 
| +    if (drawState.hasGeometryProcessor()) {
 | 
| +        uint16_t* offsetAndSize =
 | 
| +                reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
 | 
| +                                            offsetAndSizeIndex * 2 * sizeof(uint16_t));
 | 
| +
 | 
| +            GrEffectKeyBuilder b(&desc->fKey);
 | 
| +            uint16_t effectKeySize;
 | 
| +            uint32_t effectOffset = desc->fKey.count();
 | 
| +            effectKeySuccess |= GetEffectKeyAndUpdateStats(
 | 
| +                                    *drawState.getGeometryProcessor(), gpu->glCaps(),
 | 
| +                                    requiresLocalCoordAttrib, &b,
 | 
| +                                    &effectKeySize, &readsDst,
 | 
| +                                    &readFragPosition, &requiresVertexShader);
 | 
| +            effectKeySuccess |= (effectOffset <= SK_MaxU16);
 | 
| +
 | 
| +            offsetAndSize[0] = SkToU16(effectOffset);
 | 
| +            offsetAndSize[1] = effectKeySize;
 | 
| +            ++offsetAndSizeIndex;
 | 
| +            *geometryProcessor = drawState.getGeometryProcessor();
 | 
| +            SkASSERT(requiresVertexShader);
 | 
| +            header->fHasGeometryProcessor = true;
 | 
| +    }
 | 
| +
 | 
|      if (!skipColor) {
 | 
|          for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
 | 
|              uint16_t* offsetAndSize =
 | 
|                  reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
 | 
|                                              offsetAndSizeIndex * 2 * sizeof(uint16_t));
 | 
|  
 | 
| +            bool effectRequiresVertexShader = false;
 | 
|              GrEffectKeyBuilder b(&desc->fKey);
 | 
|              uint16_t effectKeySize;
 | 
|              uint32_t effectOffset = desc->fKey.count();
 | 
| @@ -133,12 +168,13 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|                                      drawState.getColorStage(s), gpu->glCaps(),
 | 
|                                      requiresLocalCoordAttrib, &b,
 | 
|                                      &effectKeySize, &readsDst,
 | 
| -                                    &readFragPosition, &requiresVertexShader);
 | 
| +                                    &readFragPosition, &effectRequiresVertexShader);
 | 
|              effectKeySuccess |= (effectOffset <= SK_MaxU16);
 | 
|  
 | 
|              offsetAndSize[0] = SkToU16(effectOffset);
 | 
|              offsetAndSize[1] = effectKeySize;
 | 
|              ++offsetAndSizeIndex;
 | 
| +            SkASSERT(!effectRequiresVertexShader);
 | 
|          }
 | 
|      }
 | 
|      if (!skipCoverage) {
 | 
| @@ -147,6 +183,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|                  reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
 | 
|                                              offsetAndSizeIndex * 2 * sizeof(uint16_t));
 | 
|  
 | 
| +            bool effectRequiresVertexShader = false;
 | 
|              GrEffectKeyBuilder b(&desc->fKey);
 | 
|              uint16_t effectKeySize;
 | 
|              uint32_t effectOffset = desc->fKey.count();
 | 
| @@ -154,12 +191,13 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|                                      drawState.getCoverageStage(s), gpu->glCaps(),
 | 
|                                      requiresLocalCoordAttrib, &b,
 | 
|                                      &effectKeySize, &readsDst,
 | 
| -                                    &readFragPosition, &requiresVertexShader);
 | 
| +                                    &readFragPosition, &effectRequiresVertexShader);
 | 
|              effectKeySuccess |= (effectOffset <= SK_MaxU16);
 | 
|  
 | 
|              offsetAndSize[0] = SkToU16(effectOffset);
 | 
|              offsetAndSize[1] = effectKeySize;
 | 
|              ++offsetAndSizeIndex;
 | 
| +            SkASSERT(!effectRequiresVertexShader);
 | 
|          }
 | 
|      }
 | 
|      if (!effectKeySuccess) {
 | 
| @@ -167,10 +205,6 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|          return false;
 | 
|      }
 | 
|  
 | 
| -    KeyHeader* header = desc->header();
 | 
| -    // make sure any padding in the header is zeroed.
 | 
| -    memset(desc->header(), 0, kHeaderSize);
 | 
| -
 | 
|      // Because header is a pointer into the dynamic array, we can't push any new data into the key
 | 
|      // below here.
 | 
|  
 | 
| @@ -259,9 +293,11 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|      header->fCoverageOutput = kModulate_CoverageOutput;
 | 
|  
 | 
|      // If we do have coverage determine whether it matters.
 | 
| -    bool separateCoverageFromColor = false;
 | 
| +    bool separateCoverageFromColor = drawState.hasGeometryProcessor();
 | 
|      if (!drawState.isCoverageDrawing() && !skipCoverage &&
 | 
| -        (drawState.numCoverageStages() > 0 || requiresCoverageAttrib)) {
 | 
| +        (drawState.numCoverageStages() > 0 ||
 | 
| +         drawState.hasGeometryProcessor() ||
 | 
| +         requiresCoverageAttrib)) {
 | 
|  
 | 
|          if (gpu->caps()->dualSourceBlendingSupport() &&
 | 
|              !(blendOpts & (GrDrawState::kEmitCoverage_BlendOptFlag |
 | 
| @@ -286,6 +322,7 @@ bool GrGLProgramDesc::Build(const GrDrawState& drawState,
 | 
|              separateCoverageFromColor = true;
 | 
|          }
 | 
|      }
 | 
| +
 | 
|      if (!skipColor) {
 | 
|          for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
 | 
|              colorStages->push_back(&drawState.getColorStage(s));
 | 
| 
 |