Cleanup GrDefaultGeoProcFactory localCoords

TBR=bsalomon@google.com
BUG=skia:

Review URL: https://codereview.chromium.org/1257193002
diff --git a/src/gpu/GrDefaultGeoProcFactory.cpp b/src/gpu/GrDefaultGeoProcFactory.cpp
index 1273a29..79abda5 100644
--- a/src/gpu/GrDefaultGeoProcFactory.cpp
+++ b/src/gpu/GrDefaultGeoProcFactory.cpp
@@ -278,24 +278,43 @@
 
 const GrGeometryProcessor* GrDefaultGeoProcFactory::Create(const Color& color,
                                                            const Coverage& coverage,
-                                                           LocalCoords::Type localCoords,
-                                                           const SkMatrix& viewMatrix,
-                                                           const SkMatrix& localMatrix) {
+                                                           const LocalCoords& localCoords,
+                                                           const SkMatrix& viewMatrix) {
     uint32_t flags = 0;
     flags |= color.fType == Color::kAttribute_Type ? kColor_GPType : 0;
     flags |= coverage.fType == Coverage::kAttribute_Type ? kCoverage_GPType : 0;
-    flags |= localCoords == LocalCoords::kHasExplicit_Type ? kLocalCoord_GPType : 0;
+    flags |= localCoords.fType == LocalCoords::kHasExplicit_Type ? kLocalCoord_GPType : 0;
 
     uint8_t inCoverage = coverage.fCoverage;
     bool coverageWillBeIgnored = coverage.fType == Coverage::kNone_Type;
-    bool localCoordsWillBeRead = localCoords != LocalCoords::kNone_Type;
+    bool localCoordsWillBeRead = localCoords.fType != LocalCoords::kUnused_Type;
 
     GrColor inColor = color.fColor;
     return DefaultGeoProc::Create(flags,
                                   inColor,
                                   viewMatrix,
-                                  localMatrix,
+                                  localCoords.fMatrix ? *localCoords.fMatrix : SkMatrix::I(),
                                   localCoordsWillBeRead,
                                   coverageWillBeIgnored,
                                   inCoverage);
 }
+
+const GrGeometryProcessor* GrDefaultGeoProcFactory::CreateForDeviceSpace(
+                                                                     const Color& color,
+                                                                     const Coverage& coverage,
+                                                                     const LocalCoords& localCoords,
+                                                                     const SkMatrix& viewMatrix) {
+    SkASSERT(LocalCoords::kUsePosition_Type == localCoords.fType);
+    SkMatrix invert = SkMatrix::I();
+    if (!viewMatrix.isIdentity() && !viewMatrix.invert(&invert)) {
+        SkDebugf("Could not invert\n");
+        return NULL;
+    }
+
+    if (localCoords.hasLocalMatrix()) {
+        invert.preConcat(*localCoords.fMatrix);
+    }
+
+    LocalCoords inverted(LocalCoords::kUsePosition_Type, &invert);
+    return Create(color, coverage, inverted);
+}
diff --git a/src/gpu/GrDefaultGeoProcFactory.h b/src/gpu/GrDefaultGeoProcFactory.h
index 86c59c4..2436854 100644
--- a/src/gpu/GrDefaultGeoProcFactory.h
+++ b/src/gpu/GrDefaultGeoProcFactory.h
@@ -111,26 +111,36 @@
 
     struct LocalCoords {
         enum Type {
-            kNone_Type,
+            kUnused_Type,
             kUsePosition_Type,
             kHasExplicit_Type,
         };
+        LocalCoords(Type type) : fType(type), fMatrix(NULL) {}
+        LocalCoords(Type type, const SkMatrix* matrix) : fType(type), fMatrix(matrix) {
+            SkASSERT(kUnused_Type != type);
+        }
+        bool hasLocalMatrix() const { return NULL != fMatrix; }
+
+        Type fType;
+        const SkMatrix* fMatrix;
     };
 
     static const GrGeometryProcessor* Create(const Color&,
                                              const Coverage&,
-                                             LocalCoords::Type,
-                                             const SkMatrix& viewMatrix = SkMatrix::I(),
-                                             const SkMatrix& localMatrix = SkMatrix::I());
+                                             const LocalCoords&,
+                                             const SkMatrix& viewMatrix = SkMatrix::I());
 
     /*
-     * The following functions are used to create default GPs. If you just need to create
-     * attributes separately from creating the default GP, use the SetAttribs function followed
-     * by the Create function. Otherwise use CreateAndSetAttribs to do both at once.
-     *
-     * You must unref the return from Create.
+     * Use this factory to create a GrGeometryProcessor that expects a device space vertex position
+     * attribute. The view matrix must still be provided to compute correctly transformed
+     * coordinates for GrFragmentProcessors. It may fail if the view matrix is not invertible.
      */
-    // TODO clean this up
+    static const GrGeometryProcessor* CreateForDeviceSpace(const Color&,
+                                                           const Coverage&,
+                                                           const LocalCoords&,
+                                                           const SkMatrix& viewMatrix);
+
+    // TODO deprecate this
     static const GrGeometryProcessor* Create(uint32_t gpTypeFlags,
                                              GrColor,
                                              bool localCoordsWillBeRead,
diff --git a/src/gpu/GrRectBatch.cpp b/src/gpu/GrRectBatch.cpp
index b6c5d74..5ef5591 100644
--- a/src/gpu/GrRectBatch.cpp
+++ b/src/gpu/GrRectBatch.cpp
@@ -13,39 +13,6 @@
 #include "GrDefaultGeoProcFactory.h"
 #include "GrPrimitiveProcessor.h"
 
-/** We always use per-vertex colors so that rects can be batched across color changes. Sometimes we
-    have explicit local coords and sometimes not. We *could* always provide explicit local coords
-    and just duplicate the positions when the caller hasn't provided a local coord rect, but we
-    haven't seen a use case which frequently switches between local rect and no local rect draws.
-
-    The color param is used to determine whether the opaque hint can be set on the draw state.
-    The caller must populate the vertex colors itself.
-
-    The vertex attrib order is always pos, color, [local coords].
- */
-static const GrGeometryProcessor* create_rect_gp(bool hasExplicitLocalCoords,
-                                                 const SkMatrix* localMatrix,
-                                                 bool coverageIgnored) {
-    typedef GrDefaultGeoProcFactory::Color Color;
-    typedef GrDefaultGeoProcFactory::Coverage Coverage;
-    typedef GrDefaultGeoProcFactory::LocalCoords LocalCoords;
-    Color color(Color::kAttribute_Type);
-    Coverage coverage(coverageIgnored ? Coverage::kNone_Type : Coverage::kSolid_Type);
-    LocalCoords::Type localCoords;
-    if (hasExplicitLocalCoords) {
-        localCoords = LocalCoords::kHasExplicit_Type;
-    } else {
-        localCoords = LocalCoords::kUsePosition_Type;
-    }
-
-    if (localMatrix) {
-        return GrDefaultGeoProcFactory::Create(color, coverage, localCoords, SkMatrix::I(),
-                                               *localMatrix);
-    } else {
-        return GrDefaultGeoProcFactory::Create(color, coverage, localCoords);
-    }
-}
-
 class RectBatch : public GrBatch {
 public:
     struct Geometry {
@@ -88,32 +55,17 @@
     }
 
     void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
-        // Go to device coords to allow batching across matrix changes
-        SkMatrix invert = SkMatrix::I();
-
-        // if we have a local rect, then we apply the localMatrix directly to the localRect to
-        // generate vertex local coords
-        bool hasExplicitLocalCoords = this->hasLocalRect();
-        if (!hasExplicitLocalCoords) {
-            if (!this->viewMatrix().isIdentity() && !this->viewMatrix().invert(&invert)) {
-                SkDebugf("Could not invert\n");
-                return;
-            }
-
-            if (this->hasLocalMatrix()) {
-                invert.preConcat(this->localMatrix());
-            }
+        SkAutoTUnref<const GrGeometryProcessor> gp(this->createRectGP());
+        if (!gp) {
+            SkDebugf("Could not create GrGeometryProcessor\n");
+            return;
         }
 
-        SkAutoTUnref<const GrGeometryProcessor> gp(create_rect_gp(hasExplicitLocalCoords,
-                                                                  &invert,
-                                                                  this->coverageIgnored()));
-
         batchTarget->initDraw(gp, pipeline);
 
         int instanceCount = fGeoData.count();
         size_t vertexStride = gp->getVertexStride();
-        SkASSERT(hasExplicitLocalCoords ?
+        SkASSERT(this->hasLocalRect() ?
                  vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
                  vertexStride == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
         QuadHelper helper;
@@ -211,6 +163,38 @@
         return true;
     }
 
+    /** We always use per-vertex colors so that rects can be batched across color changes. Sometimes
+        we  have explicit local coords and sometimes not. We *could* always provide explicit local
+        coords and just duplicate the positions when the caller hasn't provided a local coord rect,
+        but we haven't seen a use case which frequently switches between local rect and no local
+        rect draws.
+
+        The color param is used to determine whether the opaque hint can be set on the draw state.
+        The caller must populate the vertex colors itself.
+
+        The vertex attrib order is always pos, color, [local coords].
+     */
+    const GrGeometryProcessor* createRectGP() {
+        typedef GrDefaultGeoProcFactory::Color Color;
+        typedef GrDefaultGeoProcFactory::Coverage Coverage;
+        typedef GrDefaultGeoProcFactory::LocalCoords LocalCoords;
+        Color color(Color::kAttribute_Type);
+        Coverage coverage(this->coverageIgnored() ? Coverage::kNone_Type : Coverage::kSolid_Type);
+
+        // if we have a local rect, then we apply the localMatrix directly to the localRect to
+        // generate vertex local coords
+        if (this->hasLocalRect()) {
+            LocalCoords localCoords(LocalCoords::kHasExplicit_Type);
+            return GrDefaultGeoProcFactory::Create(color, coverage, localCoords);
+        } else {
+            LocalCoords localCoords(LocalCoords::kUsePosition_Type,
+                                    this->hasLocalMatrix() ? &this->localMatrix() : NULL);
+            return GrDefaultGeoProcFactory::CreateForDeviceSpace(color, coverage, localCoords,
+                                                                 this->viewMatrix());
+        }
+    }
+
+
     struct BatchTracker {
         GrColor fColor;
         bool fUsesLocalCoords;