| Index: src/gpu/gl/GrGpuGL.cpp
 | 
| diff --git a/src/gpu/gl/GrGpuGL.cpp b/src/gpu/gl/GrGpuGL.cpp
 | 
| index a22988b01bbb8a117ea1262099dc8a934c076b25..0efb7ebdd002cbad9fffb4435a4c3c129be1bc62 100644
 | 
| --- a/src/gpu/gl/GrGpuGL.cpp
 | 
| +++ b/src/gpu/gl/GrGpuGL.cpp
 | 
| @@ -1344,6 +1344,112 @@ void GrGpuGL::flushScissor(const GrClipMaskManager::ScissorState& scissorState,
 | 
|      this->disableScissor();
 | 
|  }
 | 
|  
 | 
| +bool GrGpuGL::flushGraphicsState(const GrOptDrawState& optState) {
 | 
| +    // GrGpu::setupClipAndFlushState should have already checked this and bailed if not true.
 | 
| +    SkASSERT(optState.getRenderTarget());
 | 
| +
 | 
| +    if (kStencilPath_DrawType == optState.drawType()) {
 | 
| +        const GrRenderTarget* rt = optState.getRenderTarget();
 | 
| +        SkISize size;
 | 
| +        size.set(rt->width(), rt->height());
 | 
| +        this->glPathRendering()->setProjectionMatrix(optState.getViewMatrix(), size, rt->origin());
 | 
| +    } else {
 | 
| +        this->flushMiscFixedFunctionState(optState);
 | 
| +
 | 
| +        fCurrentProgram.reset(fProgramCache->getProgram(optState));
 | 
| +        if (NULL == fCurrentProgram.get()) {
 | 
| +            SkDEBUGFAIL("Failed to create program!");
 | 
| +            return false;
 | 
| +        }
 | 
| +
 | 
| +        fCurrentProgram.get()->ref();
 | 
| +
 | 
| +        GrGLuint programID = fCurrentProgram->programID();
 | 
| +        if (fHWProgramID != programID) {
 | 
| +            GL_CALL(UseProgram(programID));
 | 
| +            fHWProgramID = programID;
 | 
| +        }
 | 
| +
 | 
| +        this->flushBlend(optState);
 | 
| +
 | 
| +        fCurrentProgram->setData(optState);
 | 
| +    }
 | 
| +
 | 
| +    GrGLRenderTarget* glRT = static_cast<GrGLRenderTarget*>(optState.getRenderTarget());
 | 
| +    this->flushStencil(optState.getStencil(), optState.drawType());
 | 
| +    this->flushScissor(optState.getScissorState(), glRT->getViewport(), glRT->origin());
 | 
| +    this->flushAAState(optState);
 | 
| +
 | 
| +    // This must come after textures are flushed because a texture may need
 | 
| +    // to be msaa-resolved (which will modify bound FBO state).
 | 
| +    this->flushRenderTarget(glRT, NULL);
 | 
| +
 | 
| +    return true;
 | 
| +}
 | 
| +
 | 
| +void GrGpuGL::setupGeometry(const GrOptDrawState& optState,
 | 
| +                            const GrDrawTarget::DrawInfo& info,
 | 
| +                            size_t* indexOffsetInBytes) {
 | 
| +    GrGLVertexBuffer* vbuf;
 | 
| +    vbuf = (GrGLVertexBuffer*) info.vertexBuffer();
 | 
| +
 | 
| +    SkASSERT(vbuf);
 | 
| +    SkASSERT(!vbuf->isMapped());
 | 
| +
 | 
| +    GrGLIndexBuffer* ibuf = NULL;
 | 
| +    if (info.isIndexed()) {
 | 
| +        SkASSERT(indexOffsetInBytes);
 | 
| +
 | 
| +        *indexOffsetInBytes = 0;
 | 
| +        ibuf = (GrGLIndexBuffer*)info.indexBuffer();
 | 
| +
 | 
| +        SkASSERT(ibuf);
 | 
| +        SkASSERT(!ibuf->isMapped());
 | 
| +        *indexOffsetInBytes += ibuf->baseOffset();
 | 
| +    }
 | 
| +    GrGLAttribArrayState* attribState =
 | 
| +        fHWGeometryState.bindArrayAndBuffersToDraw(this, vbuf, ibuf);
 | 
| +
 | 
| +    if (fCurrentProgram->hasVertexShader()) {
 | 
| +        const GrGeometryProcessor* gp = optState.getGeometryProcessor();
 | 
| +
 | 
| +        GrGLsizei stride = static_cast<GrGLsizei>(gp->getVertexStride());
 | 
| +
 | 
| +        size_t vertexOffsetInBytes = stride * info.startVertex();
 | 
| +
 | 
| +        vertexOffsetInBytes += vbuf->baseOffset();
 | 
| +
 | 
| +        const SkTArray<GrGeometryProcessor::GrAttribute, true>& attribs = gp->getAttribs();
 | 
| +        int vaCount = attribs.count();
 | 
| +        uint32_t usedAttribArraysMask = 0;
 | 
| +        size_t offset = 0;
 | 
| +
 | 
| +        for (int attribIndex = 0; attribIndex < vaCount; attribIndex++) {
 | 
| +            usedAttribArraysMask |= (1 << attribIndex);
 | 
| +            GrVertexAttribType attribType = attribs[attribIndex].fType;
 | 
| +            attribState->set(this,
 | 
| +                             attribIndex,
 | 
| +                             vbuf,
 | 
| +                             GrGLAttribTypeToLayout(attribType).fCount,
 | 
| +                             GrGLAttribTypeToLayout(attribType).fType,
 | 
| +                             GrGLAttribTypeToLayout(attribType).fNormalized,
 | 
| +                             stride,
 | 
| +                             reinterpret_cast<GrGLvoid*>(vertexOffsetInBytes + offset));
 | 
| +            offset += attribs[attribIndex].fOffset;
 | 
| +        }
 | 
| +        attribState->disableUnusedArrays(this, usedAttribArraysMask);
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +void GrGpuGL::buildProgramDesc(const GrOptDrawState& optState,
 | 
| +                               const GrProgramDesc::DescInfo& descInfo,
 | 
| +                               GrGpu::DrawType drawType,
 | 
| +                               GrProgramDesc* desc) {
 | 
| +    if (!GrGLProgramDescBuilder::Build(optState, descInfo, drawType, this, desc)) {
 | 
| +        SkDEBUGFAIL("Failed to generate GL program descriptor");
 | 
| +    }
 | 
| +}
 | 
| +
 | 
|  void GrGpuGL::disableScissor() {
 | 
|      if (kNo_TriState != fHWScissorSettings.fEnabled) {
 | 
|          GL_CALL(Disable(GR_GL_SCISSOR_TEST));
 | 
| 
 |