A simple change to move a bunch of stuff out of Gr*Geometry.h

BUG=skia:

Review URL: https://codereview.chromium.org/920863002
diff --git a/src/gpu/gl/GrGLGeometryProcessor.cpp b/src/gpu/gl/GrGLGeometryProcessor.cpp
new file mode 100644
index 0000000..a8d020a
--- /dev/null
+++ b/src/gpu/gl/GrGLGeometryProcessor.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLGeometryProcessor.h"
+
+#include "builders/GrGLProgramBuilder.h"
+
+void GrGLGeometryProcessor::emitCode(EmitArgs& args) {
+    GrGLVertexBuilder* vsBuilder = args.fPB->getVertexShaderBuilder();
+    GrGPArgs gpArgs;
+    this->onEmitCode(args, &gpArgs);
+    vsBuilder->transformToNormalizedDeviceSpace(gpArgs.fPositionVar);
+}
+
+void GrGLGeometryProcessor::emitTransforms(GrGLGPBuilder* pb,
+                                           const GrShaderVar& posVar,
+                                           const char* localCoords,
+                                           const SkMatrix& localMatrix,
+                                           const TransformsIn& tin,
+                                           TransformsOut* tout) {
+    GrGLVertexBuilder* vb = pb->getVertexShaderBuilder();
+    tout->push_back_n(tin.count());
+    fInstalledTransforms.push_back_n(tin.count());
+    for (int i = 0; i < tin.count(); i++) {
+        const ProcCoords& coordTransforms = tin[i];
+        fInstalledTransforms[i].push_back_n(coordTransforms.count());
+        for (int t = 0; t < coordTransforms.count(); t++) {
+            SkString strUniName("StageMatrix");
+            strUniName.appendf("_%i_%i", i, t);
+            GrSLType varyingType;
+
+            GrCoordSet coordType = coordTransforms[t]->sourceCoords();
+            uint32_t type = coordTransforms[t]->getMatrix().getType();
+            if (kLocal_GrCoordSet == coordType) {
+                type |= localMatrix.getType();
+            }
+            varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType :
+                                                                         kVec2f_GrSLType;
+            GrSLPrecision precision = coordTransforms[t]->precision();
+
+            const char* uniName;
+            fInstalledTransforms[i][t].fHandle =
+                    pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+                                   kMat33f_GrSLType, precision,
+                                   strUniName.c_str(),
+                                   &uniName).toShaderBuilderIndex();
+
+            SkString strVaryingName("MatrixCoord");
+            strVaryingName.appendf("_%i_%i", i, t);
+
+            GrGLVertToFrag v(varyingType);
+            pb->addVarying(strVaryingName.c_str(), &v, precision);
+
+            SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType);
+            SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
+                                   (SkString(v.fsIn()), varyingType));
+
+            // varying = matrix * coords (logically)
+            if (kDevice_GrCoordSet == coordType) {
+                if (kVec2f_GrSLType == varyingType) {
+                    if (kVec2f_GrSLType == posVar.getType()) {
+                        vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;",
+                                        v.vsOut(), uniName, posVar.c_str());
+                    } else {
+                        // The brackets here are just to scope the temp variable
+                        vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str());
+                        vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut());
+                    }
+                } else {
+                    if (kVec2f_GrSLType == posVar.getType()) {
+                        vb->codeAppendf("%s = %s * vec3(%s, 1);",
+                                        v.vsOut(), uniName, posVar.c_str());
+                    } else {
+                        vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str());
+                    }
+                }
+            } else {
+                if (kVec2f_GrSLType == varyingType) {
+                    vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords);
+                } else {
+                    vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords);
+                }
+            }
+        }
+    }
+}
+
+void
+GrGLGeometryProcessor::setTransformData(const GrPrimitiveProcessor& primProc,
+                                        const GrGLProgramDataManager& pdman,
+                                        int index,
+                                        const SkTArray<const GrCoordTransform*, true>& transforms) {
+    SkSTArray<2, Transform, true>& procTransforms = fInstalledTransforms[index];
+    int numTransforms = transforms.count();
+    for (int t = 0; t < numTransforms; ++t) {
+        SkASSERT(procTransforms[t].fHandle.isValid());
+        const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
+        if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) {
+            pdman.setSkMatrix(procTransforms[t].fHandle.convertToUniformHandle(), transform);
+            procTransforms[t].fCurrentValue = transform;
+        }
+    }
+}
+
+void GrGLGeometryProcessor::SetupPosition(GrGLVertexBuilder* vsBuilder,
+                                          GrGPArgs* gpArgs,
+                                          const char* posName,
+                                          const SkMatrix& mat,
+                                          const char* matName) {
+    if (mat.isIdentity()) {
+        gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
+
+        vsBuilder->codeAppendf("vec2 %s = %s;", gpArgs->fPositionVar.c_str(), posName);
+    } else if (!mat.hasPerspective()) {
+        gpArgs->fPositionVar.set(kVec2f_GrSLType, "pos2");
+
+        vsBuilder->codeAppendf("vec2 %s = vec2(%s * vec3(%s, 1));",
+                               gpArgs->fPositionVar.c_str(), matName, posName);
+    } else {
+        gpArgs->fPositionVar.set(kVec3f_GrSLType, "pos3");
+
+        vsBuilder->codeAppendf("vec3 %s = %s * vec3(%s, 1);",
+                               gpArgs->fPositionVar.c_str(), matName, posName);
+    }
+}
diff --git a/src/gpu/gl/GrGLGeometryProcessor.h b/src/gpu/gl/GrGLGeometryProcessor.h
index da6c347..e8b16af 100644
--- a/src/gpu/gl/GrGLGeometryProcessor.h
+++ b/src/gpu/gl/GrGLGeometryProcessor.h
@@ -8,126 +8,10 @@
 #ifndef GrGLGeometryProcessor_DEFINED
 #define GrGLGeometryProcessor_DEFINED
 
-#include "GrGLProcessor.h"
+#include "GrGLPrimitiveProcessor.h"
 
-class GrBatchTracker;
-class GrFragmentProcessor;
-class GrGLGPBuilder;
-
-class GrGLPrimitiveProcessor {
-public:
-    GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); }
-    virtual ~GrGLPrimitiveProcessor() {}
-
-    typedef GrGLProgramDataManager::UniformHandle UniformHandle;
-    typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
-
-    typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
-    typedef SkSTArray<8, ProcCoords> TransformsIn;
-    typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut;
-
-    struct EmitArgs {
-        EmitArgs(GrGLGPBuilder* pb,
-                 const GrPrimitiveProcessor& gp,
-                 const GrBatchTracker& bt,
-                 const char* outputColor,
-                 const char* outputCoverage,
-                 const TextureSamplerArray& samplers,
-                 const TransformsIn& transformsIn,
-                 TransformsOut* transformsOut)
-            : fPB(pb)
-            , fGP(gp)
-            , fBT(bt)
-            , fOutputColor(outputColor)
-            , fOutputCoverage(outputCoverage)
-            , fSamplers(samplers)
-            , fTransformsIn(transformsIn)
-            , fTransformsOut(transformsOut) {}
-        GrGLGPBuilder* fPB;
-        const GrPrimitiveProcessor& fGP;
-        const GrBatchTracker& fBT;
-        const char* fOutputColor;
-        const char* fOutputCoverage;
-        const TextureSamplerArray& fSamplers;
-        const TransformsIn& fTransformsIn;
-        TransformsOut* fTransformsOut;
-    };
-
-    /**
-     * This is similar to emitCode() in the base class, except it takes a full shader builder.
-     * This allows the effect subclass to emit vertex code.
-     */
-    virtual void emitCode(EmitArgs&) = 0;
-
-
-    /** A GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that
-        produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and
-        uploads any uniform variables required  by the shaders created in emitCode(). The
-        GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
-        GrGLPrimitiveProcessor and to have an identical processor key as the one that created this
-        GrGLPrimitiveProcessor.  */
-    virtual void setData(const GrGLProgramDataManager&,
-                         const GrPrimitiveProcessor&,
-                         const GrBatchTracker&) = 0;
-
-    static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
-
-protected:
-    /** a helper which can setup vertex, constant, or uniform color depending on inputType.
-     *  This function will only do the minimum required to emit the correct shader code.  If
-     *  inputType == attribute, then colorAttr must not be NULL.  Likewise, if inputType == Uniform
-     *  then colorUniform must not be NULL.
-     */
-    void setupColorPassThrough(GrGLGPBuilder* pb,
-                               GrGPInput inputType,
-                               const char* inputName,
-                               const GrGeometryProcessor::Attribute* colorAttr,
-                               UniformHandle* colorUniform);
-
-    const char* uViewM() const { return fViewMatrixName; }
-
-    /** a helper function to setup the uniform handle for the uniform view matrix */
-    void addUniformViewMatrix(GrGLGPBuilder*);
-
-
-    /** a helper function to upload a uniform viewmatrix.
-     * TODO we can remove this function when we have deferred geometry in place
-     */
-    void setUniformViewMatrix(const GrGLProgramDataManager&,
-                              const SkMatrix& viewMatrix);
-
-    class ShaderVarHandle {
-    public:
-        bool isValid() const { return fHandle > -1; }
-        ShaderVarHandle() : fHandle(-1) {}
-        ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
-        int handle() const { SkASSERT(this->isValid()); return fHandle; }
-        UniformHandle convertToUniformHandle() {
-            SkASSERT(this->isValid());
-            return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
-        }
-
-    private:
-        int fHandle;
-    };
-
-    struct Transform {
-        Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
-        ShaderVarHandle fHandle;
-        SkMatrix       fCurrentValue;
-        GrSLType       fType;
-    };
-
-    SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms;
-
-private:
-    UniformHandle fViewMatrixUniform;
-    SkMatrix fViewMatrix;
-    const char* fViewMatrixName;
-};
-
-class GrGLPathRendering;
 class GrGLVertexBuilder;
+
 /**
  * If a GL effect needs a GrGLFullShaderBuilder* object to emit vertex code, then it must inherit
  * from this class. Since paths don't have vertices, this class is only meant to be used internally
@@ -189,40 +73,4 @@
     typedef GrGLPrimitiveProcessor INHERITED;
 };
 
-class GrGLGpu;
-
-class GrGLPathProcessor : public GrGLPrimitiveProcessor {
-public:
-    GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&);
-
-    static void GenKey(const GrPathProcessor&,
-                       const GrBatchTracker& bt,
-                       const GrGLCaps&,
-                       GrProcessorKeyBuilder* b);
-
-    void emitCode(EmitArgs&) SK_OVERRIDE;
-
-    virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0;
-
-    virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {}
-
-    void setData(const GrGLProgramDataManager&,
-                 const GrPrimitiveProcessor&,
-                 const GrBatchTracker&) SK_OVERRIDE;
-
-    virtual void setTransformData(const GrPrimitiveProcessor&,
-                                  int index,
-                                  const SkTArray<const GrCoordTransform*, true>& transforms,
-                                  GrGLPathRendering*,
-                                  GrGLuint programID) = 0;
-
-    virtual void didSetData(GrGLPathRendering*) {}
-
-private:
-    UniformHandle fColorUniform;
-    GrColor fColor;
-
-    typedef GrGLPrimitiveProcessor INHERITED;
-};
-
 #endif
diff --git a/src/gpu/gl/GrGLPathProcessor.cpp b/src/gpu/gl/GrGLPathProcessor.cpp
new file mode 100644
index 0000000..3f3e5d9
--- /dev/null
+++ b/src/gpu/gl/GrGLPathProcessor.cpp
@@ -0,0 +1,183 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLPathProcessor.h"
+
+#include "GrPathProcessor.h"
+#include "GrGLGpu.h"
+#include "GrGLPathRendering.h"
+
+GrGLPathProcessor::GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&)
+    : fColor(GrColor_ILLEGAL) {}
+
+void GrGLPathProcessor::emitCode(EmitArgs& args) {
+    GrGLGPBuilder* pb = args.fPB;
+    GrGLGPFragmentBuilder* fs = args.fPB->getFragmentShaderBuilder();
+    const PathBatchTracker& local = args.fBT.cast<PathBatchTracker>();
+
+    // emit transforms
+    this->emitTransforms(args.fPB, args.fTransformsIn, args.fTransformsOut);
+
+    // Setup uniform color
+    if (kUniform_GrGPInput == local.fInputColorType) {
+        const char* stagedLocalVarName;
+        fColorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                                       kVec4f_GrSLType,
+                                       kDefault_GrSLPrecision,
+                                       "Color",
+                                       &stagedLocalVarName);
+        fs->codeAppendf("%s = %s;", args.fOutputColor, stagedLocalVarName);
+    }
+
+    // setup constant solid coverage
+    if (kAllOnes_GrGPInput == local.fInputCoverageType) {
+        fs->codeAppendf("%s = vec4(1);", args.fOutputCoverage);
+    }
+}
+
+void GrGLPathProcessor::GenKey(const GrPathProcessor&,
+                               const GrBatchTracker& bt,
+                               const GrGLCaps&,
+                               GrProcessorKeyBuilder* b) {
+    const PathBatchTracker& local = bt.cast<PathBatchTracker>();
+    b->add32(local.fInputColorType | local.fInputCoverageType << 16);
+}
+
+void GrGLPathProcessor::setData(const GrGLProgramDataManager& pdman,
+                                const GrPrimitiveProcessor& primProc,
+                                const GrBatchTracker& bt) {
+    const PathBatchTracker& local = bt.cast<PathBatchTracker>();
+    if (kUniform_GrGPInput == local.fInputColorType && local.fColor != fColor) {
+        GrGLfloat c[4];
+        GrColorToRGBAFloat(local.fColor, c);
+        pdman.set4fv(fColorUniform, 1, c);
+        fColor = local.fColor;
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void GrGLLegacyPathProcessor::emitTransforms(GrGLGPBuilder*, const TransformsIn& tin,
+                                             TransformsOut* tout) {
+    tout->push_back_n(tin.count());
+    fInstalledTransforms.push_back_n(tin.count());
+    for (int i = 0; i < tin.count(); i++) {
+        const ProcCoords& coordTransforms = tin[i];
+        int texCoordIndex = this->addTexCoordSets(coordTransforms.count());
+
+        // Use the first uniform location as the texcoord index.
+        fInstalledTransforms[i].push_back_n(1);
+        fInstalledTransforms[i][0].fHandle = ShaderVarHandle(texCoordIndex);
+
+        SkString name;
+        for (int t = 0; t < coordTransforms.count(); ++t) {
+            GrSLType type = coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
+                                                                               kVec2f_GrSLType;
+
+            name.printf("%s(gl_TexCoord[%i])", GrGLSLTypeString(type), texCoordIndex++);
+            SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords, (name, type));
+        }
+    }
+}
+
+void GrGLLegacyPathProcessor::setTransformData(
+        const GrPrimitiveProcessor& primProc,
+        int index,
+        const SkTArray<const GrCoordTransform*, true>& transforms,
+        GrGLPathRendering* glpr,
+        GrGLuint) {
+    // We've hidden the texcoord index in the first entry of the transforms array for each
+    // effect
+    int texCoordIndex = fInstalledTransforms[index][0].fHandle.handle();
+    for (int t = 0; t < transforms.count(); ++t) {
+        const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(), *transforms[t]);
+        GrGLPathRendering::PathTexGenComponents components =
+                GrGLPathRendering::kST_PathTexGenComponents;
+        if (transform.hasPerspective()) {
+            components = GrGLPathRendering::kSTR_PathTexGenComponents;
+        }
+        glpr->enablePathTexGen(texCoordIndex++, components, transform);
+    }
+}
+
+void GrGLLegacyPathProcessor::didSetData(GrGLPathRendering* glpr) {
+    glpr->flushPathTexGenSettings(fTexCoordSetCnt);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+void GrGLNormalPathProcessor::emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,
+                                             TransformsOut* tout) {
+    tout->push_back_n(tin.count());
+    fInstalledTransforms.push_back_n(tin.count());
+    for (int i = 0; i < tin.count(); i++) {
+        const ProcCoords& coordTransforms = tin[i];
+        fInstalledTransforms[i].push_back_n(coordTransforms.count());
+        for (int t = 0; t < coordTransforms.count(); t++) {
+            GrSLType varyingType =
+                    coordTransforms[t]->getMatrix().hasPerspective() ? kVec3f_GrSLType :
+                                                                       kVec2f_GrSLType;
+
+
+            SkString strVaryingName("MatrixCoord");
+            strVaryingName.appendf("_%i_%i", i, t);
+            GrGLVertToFrag v(varyingType);
+            pb->addVarying(strVaryingName.c_str(), &v);
+            SeparableVaryingInfo& varyingInfo = fSeparableVaryingInfos.push_back();
+            varyingInfo.fVariable = pb->getFragmentShaderBuilder()->fInputs.back();
+            varyingInfo.fLocation = fSeparableVaryingInfos.count() - 1;
+            varyingInfo.fType = varyingType;
+            fInstalledTransforms[i][t].fHandle = ShaderVarHandle(varyingInfo.fLocation);
+            fInstalledTransforms[i][t].fType = varyingType;
+
+            SkNEW_APPEND_TO_TARRAY(&(*tout)[i], GrGLProcessor::TransformedCoords,
+                                   (SkString(v.fsIn()), varyingType));
+        }
+    }
+}
+
+void GrGLNormalPathProcessor::resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {
+    int count = fSeparableVaryingInfos.count();
+    for (int i = 0; i < count; ++i) {
+        GrGLint location;
+        GR_GL_CALL_RET(gpu->glInterface(),
+                       location,
+                       GetProgramResourceLocation(programId,
+                                                  GR_GL_FRAGMENT_INPUT,
+                                                  fSeparableVaryingInfos[i].fVariable.c_str()));
+        fSeparableVaryingInfos[i].fLocation = location;
+    }
+}
+
+void GrGLNormalPathProcessor::setTransformData(
+        const GrPrimitiveProcessor& primProc,
+        int index,
+        const SkTArray<const GrCoordTransform*, true>& coordTransforms,
+        GrGLPathRendering* glpr,
+        GrGLuint programID) {
+    SkSTArray<2, Transform, true>& transforms = fInstalledTransforms[index];
+    int numTransforms = transforms.count();
+    for (int t = 0; t < numTransforms; ++t) {
+        SkASSERT(transforms[t].fHandle.isValid());
+        const SkMatrix& transform = GetTransformMatrix(primProc.localMatrix(),
+                                                       *coordTransforms[t]);
+        if (transforms[t].fCurrentValue.cheapEqualTo(transform)) {
+            continue;
+        }
+        transforms[t].fCurrentValue = transform;
+        const SeparableVaryingInfo& fragmentInput =
+                fSeparableVaryingInfos[transforms[t].fHandle.handle()];
+        SkASSERT(transforms[t].fType == kVec2f_GrSLType ||
+                 transforms[t].fType == kVec3f_GrSLType);
+        unsigned components = transforms[t].fType == kVec2f_GrSLType ? 2 : 3;
+        glpr->setProgramPathFragmentInputTransform(programID,
+                                                   fragmentInput.fLocation,
+                                                   GR_GL_OBJECT_LINEAR,
+                                                   components,
+                                                   transform);
+    }
+}
diff --git a/src/gpu/gl/GrGLPathProcessor.h b/src/gpu/gl/GrGLPathProcessor.h
new file mode 100644
index 0000000..368f1f9
--- /dev/null
+++ b/src/gpu/gl/GrGLPathProcessor.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLPathProcessor_DEFINED
+#define GrGLPathProcessor_DEFINED
+
+#include "GrGLPrimitiveProcessor.h"
+
+class GrPathProcessor;
+class GrGLPathRendering;
+class GrGLGpu;
+
+class GrGLPathProcessor : public GrGLPrimitiveProcessor {
+public:
+    GrGLPathProcessor(const GrPathProcessor&, const GrBatchTracker&);
+
+    static void GenKey(const GrPathProcessor&,
+                       const GrBatchTracker& bt,
+                       const GrGLCaps&,
+                       GrProcessorKeyBuilder* b);
+
+    void emitCode(EmitArgs&) SK_OVERRIDE;
+
+    virtual void emitTransforms(GrGLGPBuilder*, const TransformsIn&, TransformsOut*) = 0;
+
+    virtual void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId) {}
+
+    void setData(const GrGLProgramDataManager&,
+                 const GrPrimitiveProcessor&,
+                 const GrBatchTracker&) SK_OVERRIDE;
+
+    virtual void setTransformData(const GrPrimitiveProcessor&,
+                                  int index,
+                                  const SkTArray<const GrCoordTransform*, true>& transforms,
+                                  GrGLPathRendering*,
+                                  GrGLuint programID) = 0;
+
+    virtual void didSetData(GrGLPathRendering*) {}
+
+private:
+    UniformHandle fColorUniform;
+    GrColor fColor;
+
+    typedef GrGLPrimitiveProcessor INHERITED;
+};
+
+class GrGLLegacyPathProcessor : public GrGLPathProcessor {
+public:
+    GrGLLegacyPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt,
+                            int maxTexCoords)
+        : INHERITED(pathProc, bt)
+        , fTexCoordSetCnt(0) {
+        SkDEBUGCODE(fMaxTexCoords = maxTexCoords;)
+    }
+
+    int addTexCoordSets(int count) {
+        int firstFreeCoordSet = fTexCoordSetCnt;
+        fTexCoordSetCnt += count;
+        SkASSERT(fMaxTexCoords >= fTexCoordSetCnt);
+        return firstFreeCoordSet;
+    }
+
+    void emitTransforms(GrGLGPBuilder*, const TransformsIn& tin, TransformsOut* tout) SK_OVERRIDE;
+
+    void setTransformData(const GrPrimitiveProcessor& primProc,
+                          int index,
+                          const SkTArray<const GrCoordTransform*, true>& transforms,
+                          GrGLPathRendering* glpr,
+                          GrGLuint) SK_OVERRIDE;
+
+    void didSetData(GrGLPathRendering* glpr) SK_OVERRIDE;
+
+private:
+    SkDEBUGCODE(int fMaxTexCoords;)
+    int fTexCoordSetCnt;
+
+    typedef GrGLPathProcessor INHERITED;
+};
+
+class GrGLNormalPathProcessor : public GrGLPathProcessor {
+public:
+    GrGLNormalPathProcessor(const GrPathProcessor& pathProc, const GrBatchTracker& bt)
+        : INHERITED(pathProc, bt) {}
+
+    void emitTransforms(GrGLGPBuilder* pb, const TransformsIn& tin,TransformsOut* tout) SK_OVERRIDE;
+
+    void resolveSeparableVaryings(GrGLGpu* gpu, GrGLuint programId);
+
+    void setTransformData(const GrPrimitiveProcessor& primProc,
+                          int index,
+                          const SkTArray<const GrCoordTransform*, true>& coordTransforms,
+                          GrGLPathRendering* glpr,
+                          GrGLuint programID) SK_OVERRIDE;
+
+private:
+    struct SeparableVaryingInfo {
+        GrSLType      fType;
+        GrGLShaderVar fVariable;
+        GrGLint       fLocation;
+    };
+
+    typedef SkSTArray<8, SeparableVaryingInfo, true> SeparableVaryingInfoArray;
+
+    SeparableVaryingInfoArray fSeparableVaryingInfos;
+
+    typedef GrGLPathProcessor INHERITED;
+};
+
+#endif
diff --git a/src/gpu/gl/GrGLPrimitiveProcessor.cpp b/src/gpu/gl/GrGLPrimitiveProcessor.cpp
new file mode 100644
index 0000000..335dc4f
--- /dev/null
+++ b/src/gpu/gl/GrGLPrimitiveProcessor.cpp
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "GrGLPrimitiveProcessor.h"
+
+#include "builders/GrGLProgramBuilder.h"
+
+SkMatrix GrGLPrimitiveProcessor::GetTransformMatrix(const SkMatrix& localMatrix,
+                                                    const GrCoordTransform& coordTransform) {
+    SkMatrix combined;
+    // We only apply the localmatrix to localcoords
+    if (kLocal_GrCoordSet == coordTransform.sourceCoords()) {
+        combined.setConcat(coordTransform.getMatrix(), localMatrix);
+    } 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;
+}
+
+void
+GrGLPrimitiveProcessor::setupColorPassThrough(GrGLGPBuilder* pb,
+                                              GrGPInput inputType,
+                                              const char* outputName,
+                                              const GrGeometryProcessor::Attribute* colorAttr,
+                                              UniformHandle* colorUniform) {
+    GrGLGPFragmentBuilder* fs = pb->getFragmentShaderBuilder();
+    if (kUniform_GrGPInput == inputType) {
+        SkASSERT(colorUniform);
+        const char* stagedLocalVarName;
+        *colorUniform = pb->addUniform(GrGLProgramBuilder::kFragment_Visibility,
+                                       kVec4f_GrSLType,
+                                       kDefault_GrSLPrecision,
+                                       "Color",
+                                       &stagedLocalVarName);
+        fs->codeAppendf("%s = %s;", outputName, stagedLocalVarName);
+    } else if (kAttribute_GrGPInput == inputType) {
+        SkASSERT(colorAttr);
+        pb->addPassThroughAttribute(colorAttr, outputName);
+    } else if (kAllOnes_GrGPInput == inputType) {
+        fs->codeAppendf("%s = vec4(1);", outputName);
+    }
+}
+
+void GrGLPrimitiveProcessor::addUniformViewMatrix(GrGLGPBuilder* pb) {
+    fViewMatrixUniform = pb->addUniform(GrGLProgramBuilder::kVertex_Visibility,
+                                        kMat33f_GrSLType, kDefault_GrSLPrecision,
+                                        "uViewM",
+                                        &fViewMatrixName);
+}
+
+void GrGLPrimitiveProcessor::setUniformViewMatrix(const GrGLProgramDataManager& pdman,
+                                                  const SkMatrix& viewMatrix) {
+    if (!fViewMatrix.cheapEqualTo(viewMatrix)) {
+        SkASSERT(fViewMatrixUniform.isValid());
+        fViewMatrix = viewMatrix;
+
+        GrGLfloat viewMatrix[3 * 3];
+        GrGLGetMatrix<3>(viewMatrix, fViewMatrix);
+        pdman.setMatrix3f(fViewMatrixUniform, viewMatrix);
+    }
+}
diff --git a/src/gpu/gl/GrGLPrimitiveProcessor.h b/src/gpu/gl/GrGLPrimitiveProcessor.h
new file mode 100644
index 0000000..30b1c17
--- /dev/null
+++ b/src/gpu/gl/GrGLPrimitiveProcessor.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrGLPrimitiveProcessor_DEFINED
+#define GrGLPrimitiveProcessor_DEFINED
+
+#include "GrPrimitiveProcessor.h"
+#include "GrGLProcessor.h"
+
+class GrBatchTracker;
+class GrPrimitiveProcessor;
+class GrGLGPBuilder;
+
+class GrGLPrimitiveProcessor {
+public:
+    GrGLPrimitiveProcessor() : fViewMatrixName(NULL) { fViewMatrix = SkMatrix::InvalidMatrix(); }
+    virtual ~GrGLPrimitiveProcessor() {}
+
+    typedef GrGLProgramDataManager::UniformHandle UniformHandle;
+    typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray;
+
+    typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords;
+    typedef SkSTArray<8, ProcCoords> TransformsIn;
+    typedef SkSTArray<8, GrGLProcessor::TransformedCoordsArray> TransformsOut;
+
+    struct EmitArgs {
+        EmitArgs(GrGLGPBuilder* pb,
+                 const GrPrimitiveProcessor& gp,
+                 const GrBatchTracker& bt,
+                 const char* outputColor,
+                 const char* outputCoverage,
+                 const TextureSamplerArray& samplers,
+                 const TransformsIn& transformsIn,
+                 TransformsOut* transformsOut)
+            : fPB(pb)
+            , fGP(gp)
+            , fBT(bt)
+            , fOutputColor(outputColor)
+            , fOutputCoverage(outputCoverage)
+            , fSamplers(samplers)
+            , fTransformsIn(transformsIn)
+            , fTransformsOut(transformsOut) {}
+        GrGLGPBuilder* fPB;
+        const GrPrimitiveProcessor& fGP;
+        const GrBatchTracker& fBT;
+        const char* fOutputColor;
+        const char* fOutputCoverage;
+        const TextureSamplerArray& fSamplers;
+        const TransformsIn& fTransformsIn;
+        TransformsOut* fTransformsOut;
+    };
+
+    /**
+     * This is similar to emitCode() in the base class, except it takes a full shader builder.
+     * This allows the effect subclass to emit vertex code.
+     */
+    virtual void emitCode(EmitArgs&) = 0;
+
+
+    /** A GrGLPrimitiveProcessor instance can be reused with any GrGLPrimitiveProcessor that
+        produces the same stage key; this function reads data from a GrGLPrimitiveProcessor and
+        uploads any uniform variables required  by the shaders created in emitCode(). The
+        GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this
+        GrGLPrimitiveProcessor and to have an identical processor key as the one that created this
+        GrGLPrimitiveProcessor.  */
+    virtual void setData(const GrGLProgramDataManager&,
+                         const GrPrimitiveProcessor&,
+                         const GrBatchTracker&) = 0;
+
+    static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&);
+
+protected:
+    /** a helper which can setup vertex, constant, or uniform color depending on inputType.
+     *  This function will only do the minimum required to emit the correct shader code.  If
+     *  inputType == attribute, then colorAttr must not be NULL.  Likewise, if inputType == Uniform
+     *  then colorUniform must not be NULL.
+     */
+    void setupColorPassThrough(GrGLGPBuilder* pb,
+                               GrGPInput inputType,
+                               const char* inputName,
+                               const GrPrimitiveProcessor::Attribute* colorAttr,
+                               UniformHandle* colorUniform);
+
+    const char* uViewM() const { return fViewMatrixName; }
+
+    /** a helper function to setup the uniform handle for the uniform view matrix */
+    void addUniformViewMatrix(GrGLGPBuilder*);
+
+
+    /** a helper function to upload a uniform viewmatrix.
+     * TODO we can remove this function when we have deferred geometry in place
+     */
+    void setUniformViewMatrix(const GrGLProgramDataManager&,
+                              const SkMatrix& viewMatrix);
+
+    class ShaderVarHandle {
+    public:
+        bool isValid() const { return fHandle > -1; }
+        ShaderVarHandle() : fHandle(-1) {}
+        ShaderVarHandle(int value) : fHandle(value) { SkASSERT(this->isValid()); }
+        int handle() const { SkASSERT(this->isValid()); return fHandle; }
+        UniformHandle convertToUniformHandle() {
+            SkASSERT(this->isValid());
+            return GrGLProgramDataManager::UniformHandle::CreateFromUniformIndex(fHandle);
+        }
+
+    private:
+        int fHandle;
+    };
+
+    struct Transform {
+        Transform() : fType(kVoid_GrSLType) { fCurrentValue = SkMatrix::InvalidMatrix(); }
+        ShaderVarHandle fHandle;
+        SkMatrix       fCurrentValue;
+        GrSLType       fType;
+    };
+
+    SkSTArray<8, SkSTArray<2, Transform, true> > fInstalledTransforms;
+
+private:
+    UniformHandle fViewMatrixUniform;
+    SkMatrix fViewMatrix;
+    const char* fViewMatrixName;
+};
+
+#endif
diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp
index eebcf6b..2f6b784 100644
--- a/src/gpu/gl/GrGLProgram.cpp
+++ b/src/gpu/gl/GrGLProgram.cpp
@@ -11,12 +11,12 @@
 #include "GrProcessor.h"
 #include "GrCoordTransform.h"
 #include "GrGLGeometryProcessor.h"
-#include "GrGLProcessor.h"
-#include "GrGLXferProcessor.h"
 #include "GrGLGpu.h"
+#include "GrGLPathProcessor.h"
 #include "GrGLPathRendering.h"
 #include "GrGLShaderVar.h"
 #include "GrGLSL.h"
+#include "GrGLXferProcessor.h"
 #include "GrPipeline.h"
 #include "GrXferProcessor.h"
 #include "SkXfermode.h"
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index bb278be..5a62303 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -6,11 +6,14 @@
  */
 
 #include "GrGLProgramBuilder.h"
+
+#include "gl/GrGLGeometryProcessor.h"
+#include "gl/GrGLGpu.h"
+#include "gl/GrGLPathProcessor.h"
 #include "gl/GrGLProgram.h"
 #include "gl/GrGLSLPrettyPrint.h"
 #include "gl/GrGLUniformHandle.h"
-#include "../GrGLXferProcessor.h"
-#include "../GrGLGpu.h"
+#include "gl/GrGLXferProcessor.h"
 #include "GrCoordTransform.h"
 #include "GrGLProgramBuilder.h"
 #include "GrTexture.h"
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.h b/src/gpu/gl/builders/GrGLProgramBuilder.h
index a9288cc..37908f9 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.h
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.h
@@ -13,7 +13,7 @@
 #include "GrGLVertexShaderBuilder.h"
 #include "../GrGLProgramDataManager.h"
 #include "../GrGLUniformHandle.h"
-#include "../GrGLGeometryProcessor.h"
+#include "../GrGLPrimitiveProcessor.h"
 #include "../GrGLXferProcessor.h"
 #include "../../GrPendingFragmentStage.h"
 #include "../../GrPipeline.h"