Remove unneeded helpers in AA and non-AA rect GrBatch subclasses.

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2115673002

Review-Url: https://codereview.chromium.org/2115673002
diff --git a/src/gpu/batches/GrAAFillRectBatch.cpp b/src/gpu/batches/GrAAFillRectBatch.cpp
index cba91c6..f8d4f8d 100644
--- a/src/gpu/batches/GrAAFillRectBatch.cpp
+++ b/src/gpu/batches/GrAAFillRectBatch.cpp
@@ -200,13 +200,16 @@
 
     static AAFillRectNoLocalMatrixBatch* Create() { return new AAFillRectNoLocalMatrixBatch; }
 
-    const char* name() const override { return Name(); }
+    const char* name() const override { return "AAFillRectBatchNoLocalMatrix"; }
 
     SkString dumpInfo() const override {
         SkString str;
         str.appendf("# batched: %d\n", fGeoData.count());
         for (int i = 0; i < fGeoData.count(); ++i) {
-            str.append(DumpInfo(fGeoData[i], i));
+            const Geometry& geo = fGeoData[i];
+            str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
+                        i, geo.fColor,
+                        geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
         }
         str.append(INHERITED::dumpInfo());
         return str;
@@ -217,7 +220,7 @@
                                       GrBatchToXPOverrides* overrides) const override {
         // When this is called on a batch, there is only one geometry bundle
         color->setKnownFourComponents(fGeoData[0].fColor);
-        InitInvariantOutputCoverage(coverage);
+        coverage->setUnknownSingleComponent();
     }
 
     void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
@@ -228,92 +231,32 @@
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
     // After seeding, the client should call init() so the Batch can initialize itself
-    void init() {
-        const Geometry& geo = fGeoData[0];
-        SetBounds(geo, &fBounds);
-    }
-
-    void updateBoundsAfterAppend() {
-        const Geometry& geo = fGeoData.back();
-        UpdateBoundsAfterAppend(geo, &fBounds);
-    }
+    void init() { fBounds = fGeoData[0].fDevRect; }
 
 private:
-    static const int kVertsPerInstance = kVertsPerAAFillRect;
-    static const int kIndicesPerInstance = kIndicesPerAAFillRect;
-
-    static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
-        out->setUnknownSingleComponent();
-    }
-
-    static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
-        return get_index_buffer(rp);
-    }
-
-    static void SetBounds(const Geometry& geo, SkRect* outBounds) {
-        *outBounds = geo.fDevRect;
-    }
-
-    static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
-        outBounds->join(geo.fDevRect);
-    }
-
-    static const char* Name() { return "AAFillRectBatchNoLocalMatrix"; }
-
-    static SkString DumpInfo(const Geometry& geo, int index) {
-        SkString str;
-        str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
-                    index,
-                    geo.fColor,
-                    geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
-        return str;
-    }
-
-    static bool CanCombine(const Geometry& mine, const Geometry& theirs,
-                           const GrXPOverridesForBatch& overrides) {
-        // We apply the viewmatrix to the rect points on the cpu.  However, if the pipeline uses
-        // local coords then we won't be able to batch.  We could actually upload the viewmatrix
-        // using vertex attributes in these cases, but haven't investigated that
-        return !overrides.readsLocalCoords() || mine.fViewMatrix.cheapEqualTo(theirs.fViewMatrix);
-    }
-
-    static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
-                                             const GrXPOverridesForBatch& overrides) {
-        sk_sp<GrGeometryProcessor> gp =
-                create_fill_rect_gp(geo.fViewMatrix, overrides,
-                                    GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type);
-
-        SkASSERT(overrides.canTweakAlphaForCoverage() ?
-                 gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
-                 gp->getVertexStride() ==
-                         sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
-        return gp;
-    }
-
-    static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
-                          const GrXPOverridesForBatch& overrides) {
-        generate_aa_fill_rect_geometry(vertices, vertexStride,
-                                       geo.fColor, geo.fViewMatrix, geo.fRect, geo.fDevRect,
-                                       overrides, nullptr);
-    }
-
     AAFillRectNoLocalMatrixBatch() : INHERITED(ClassID()) {}
 
     void onPrepareDraws(Target* target) const override {
-        sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
+        sk_sp<GrGeometryProcessor> gp =
+                create_fill_rect_gp(fGeoData[0].fViewMatrix, fOverrides,
+                                    GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type);
         if (!gp) {
             SkDebugf("Couldn't create GrGeometryProcessor\n");
             return;
         }
+        SkASSERT(fOverrides.canTweakAlphaForCoverage() ?
+                     gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr) :
+                     gp->getVertexStride() ==
+                         sizeof(GrDefaultGeoProcFactory::PositionColorCoverageAttr));
 
         size_t vertexStride = gp->getVertexStride();
         int instanceCount = fGeoData.count();
 
-        SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
+        SkAutoTUnref<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
         InstancedHelper helper;
         void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
-                                     indexBuffer, kVertsPerInstance,
-                                     kIndicesPerInstance, instanceCount);
+                                     indexBuffer, kVertsPerAAFillRect,
+                                     kIndicesPerAAFillRect, instanceCount);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
@@ -321,14 +264,15 @@
 
         for (int i = 0; i < instanceCount; i++) {
             intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
-                             i * kVertsPerInstance * vertexStride;
-            Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
+                             i * kVertsPerAAFillRect * vertexStride;
+            generate_aa_fill_rect_geometry(verts, vertexStride,
+                                           fGeoData[i].fColor, fGeoData[i].fViewMatrix,
+                                           fGeoData[i].fRect, fGeoData[i].fDevRect, fOverrides,
+                                           nullptr);
         }
         helper.recordDraw(target, gp.get());
     }
 
-    const Geometry& seedGeometry() const { return fGeoData[0]; }
-
     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
         AAFillRectNoLocalMatrixBatch* that = t->cast<AAFillRectNoLocalMatrixBatch>();
         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
@@ -336,7 +280,11 @@
             return false;
         }
 
-        if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
+        // We apply the viewmatrix to the rect points on the cpu.  However, if the pipeline uses
+        // local coords then we won't be able to batch.  We could actually upload the viewmatrix
+        // using vertex attributes in these cases, but haven't investigated that
+        if (fOverrides.readsLocalCoords() &&
+            !fGeoData[0].fViewMatrix.cheapEqualTo(that->fGeoData[0].fViewMatrix)) {
             return false;
         }
 
@@ -371,13 +319,16 @@
 
     static AAFillRectLocalMatrixBatch* Create() { return new AAFillRectLocalMatrixBatch; }
 
-    const char* name() const override { return Name(); }
+    const char* name() const override { return "AAFillRectBatchLocalMatrix"; }
 
     SkString dumpInfo() const override {
         SkString str;
         str.appendf("# batched: %d\n", fGeoData.count());
         for (int i = 0; i < fGeoData.count(); ++i) {
-            str.append(DumpInfo(fGeoData[i], i));
+            const Geometry& geo = fGeoData[i];
+            str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
+                        i, geo.fColor,
+                        geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
         }
         str.append(INHERITED::dumpInfo());
         return str;
@@ -388,7 +339,7 @@
                                       GrBatchToXPOverrides* overrides) const override {
         // When this is called on a batch, there is only one geometry bundle
         color->setKnownFourComponents(fGeoData[0].fColor);
-        InitInvariantOutputCoverage(coverage);
+        coverage->setUnknownSingleComponent();
     }
 
     void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
@@ -399,90 +350,33 @@
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
     // After seeding, the client should call init() so the Batch can initialize itself
-    void init() {
-        const Geometry& geo = fGeoData[0];
-        SetBounds(geo, &fBounds);
-    }
-
-    void updateBoundsAfterAppend() {
-        const Geometry& geo = fGeoData.back();
-        UpdateBoundsAfterAppend(geo, &fBounds);
-    }
+    void init() { fBounds = fGeoData[0].fDevRect; }
 
 private:
-    static const int kVertsPerInstance = kVertsPerAAFillRect;
-    static const int kIndicesPerInstance = kIndicesPerAAFillRect;
-
-    static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
-        out->setUnknownSingleComponent();
-    }
-
-    static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
-        return get_index_buffer(rp);
-    }
-
-    static void SetBounds(const Geometry& geo, SkRect* outBounds) {
-        *outBounds = geo.fDevRect;
-    }
-
-    static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
-        outBounds->join(geo.fDevRect);
-    }
-
-    static const char* Name() { return "AAFillRectBatchLocalMatrix"; }
-
-    static SkString DumpInfo(const Geometry& geo, int index) {
-        SkString str;
-        str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
-                    index,
-                    geo.fColor,
-                    geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
-        return str;
-    }
-
-    static bool CanCombine(const Geometry& mine, const Geometry& theirs,
-                           const GrXPOverridesForBatch& overrides) {
-        return true;
-    }
-
-    static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
-                                               const GrXPOverridesForBatch& overrides) {
-        sk_sp<GrGeometryProcessor> gp =
-                create_fill_rect_gp(geo.fViewMatrix, overrides,
-                                    GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type);
-
-        SkASSERT(overrides.canTweakAlphaForCoverage() ?
-                 gp->getVertexStride() ==
-                         sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
-                 gp->getVertexStride() ==
-                         sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage));
-        return gp;
-    }
-
-    static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
-                          const GrXPOverridesForBatch& overrides) {
-        generate_aa_fill_rect_geometry(vertices, vertexStride,
-                                       geo.fColor, geo.fViewMatrix, geo.fRect, geo.fDevRect,
-                                       overrides, &geo.fLocalMatrix);
-    }
-
     AAFillRectLocalMatrixBatch() : INHERITED(ClassID()) {}
 
     void onPrepareDraws(Target* target) const override {
-        sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
+        sk_sp<GrGeometryProcessor> gp =
+                create_fill_rect_gp(fGeoData[0].fViewMatrix, fOverrides,
+                                    GrDefaultGeoProcFactory::LocalCoords::kHasExplicit_Type);
         if (!gp) {
             SkDebugf("Couldn't create GrGeometryProcessor\n");
             return;
         }
+        SkASSERT(fOverrides.canTweakAlphaForCoverage() ?
+                 gp->getVertexStride() ==
+                 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
+                 gp->getVertexStride() ==
+                 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordCoverage));
 
         size_t vertexStride = gp->getVertexStride();
         int instanceCount = fGeoData.count();
 
-        SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
+        SkAutoTUnref<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
         InstancedHelper helper;
         void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
-                                     indexBuffer, kVertsPerInstance,
-                                     kIndicesPerInstance, instanceCount);
+                                     indexBuffer, kVertsPerAAFillRect,
+                                     kIndicesPerAAFillRect, instanceCount);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
@@ -490,14 +384,15 @@
 
         for (int i = 0; i < instanceCount; i++) {
             intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
-                             i * kVertsPerInstance * vertexStride;
-            Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
+                             i * kVertsPerAAFillRect * vertexStride;
+            generate_aa_fill_rect_geometry(verts, vertexStride, fGeoData[i].fColor,
+                                           fGeoData[i].fViewMatrix, fGeoData[i].fRect,
+                                           fGeoData[i].fDevRect, fOverrides,
+                                           &fGeoData[i].fLocalMatrix);
         }
         helper.recordDraw(target, gp.get());
     }
 
-    const Geometry& seedGeometry() const { return fGeoData[0]; }
-
     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
         AAFillRectLocalMatrixBatch* that = t->cast<AAFillRectLocalMatrixBatch>();
         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
@@ -505,10 +400,6 @@
             return false;
         }
 
-        if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
-            return false;
-        }
-
         // In the event of two batches, one who can tweak, one who cannot, we just fall back to
         // not tweaking
         if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
diff --git a/src/gpu/batches/GrNonAAFillRectBatch.cpp b/src/gpu/batches/GrNonAAFillRectBatch.cpp
index b986574..faccdf6 100644
--- a/src/gpu/batches/GrNonAAFillRectBatch.cpp
+++ b/src/gpu/batches/GrNonAAFillRectBatch.cpp
@@ -100,13 +100,16 @@
 
     static NonAAFillRectBatch* Create() { return new NonAAFillRectBatch; }
 
-    const char* name() const override { return Name(); }
+    const char* name() const override { return "NonAAFillRectBatch"; }
 
     SkString dumpInfo() const override {
         SkString str;
         str.appendf("# batched: %d\n", fGeoData.count());
         for (int i = 0; i < fGeoData.count(); ++i) {
-            str.append(DumpInfo(fGeoData[i], i));
+            const Geometry& geo = fGeoData[i];
+            str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
+                        i, geo.fColor,
+                        geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
         }
         str.append(INHERITED::dumpInfo());
         return str;
@@ -117,7 +120,7 @@
                                       GrBatchToXPOverrides* overrides) const override {
         // When this is called on a batch, there is only one geometry bundle
         color->setKnownFourComponents(fGeoData[0].fColor);
-        InitInvariantOutputCoverage(coverage);
+        coverage->setKnownSingleComponent(0xff);
     }
 
     void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
@@ -128,79 +131,25 @@
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
     // After seeding, the client should call init() so the Batch can initialize itself
-    void init() {
-        const Geometry& geo = fGeoData[0];
-        SetBounds(geo, &fBounds);
-    }
-
-    void updateBoundsAfterAppend() {
-        const Geometry& geo = fGeoData.back();
-        UpdateBoundsAfterAppend(geo, &fBounds);
-    }
+    void init() { fGeoData[0].fViewMatrix.mapRect(&fBounds, fGeoData[0].fRect); }
 
 private:
-    static const char* Name() { return "NonAAFillRectBatch"; }
-
-    static SkString DumpInfo(const Geometry& geo, int index) {
-        SkString str;
-        str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
-                    index,
-                    geo.fColor,
-                    geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
-        return str;
-    }
-
-    static bool CanCombine(const Geometry& mine, const Geometry& theirs,
-                           const GrXPOverridesForBatch& overrides) {
-        return true;
-    }
-
-    static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
-                                             const GrXPOverridesForBatch& overrides) {
-        sk_sp<GrGeometryProcessor> gp = make_gp(geo.fViewMatrix, overrides.readsCoverage(), true,
-                                                nullptr);
-
-        SkASSERT(gp->getVertexStride() ==
-                sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
-        return gp;
-    }
-
-    static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
-                          const GrXPOverridesForBatch& overrides) {
-        tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, &geo.fLocalQuad);
-    }
-
-    static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
-        out->setKnownSingleComponent(0xff);
-    }
-
-    static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
-        return rp->refQuadIndexBuffer();
-    }
-
-    static void SetBounds(const Geometry& geo, SkRect* outBounds) {
-        geo.fViewMatrix.mapRect(outBounds, geo.fRect);
-    }
-
-    static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
-        SkRect bounds = geo.fRect;
-        geo.fViewMatrix.mapRect(&bounds);
-        outBounds->join(bounds);
-    }
-
     NonAAFillRectBatch() : INHERITED(ClassID()) {}
 
     void onPrepareDraws(Target* target) const override {
-        sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
+        sk_sp<GrGeometryProcessor> gp = make_gp(fGeoData[0].fViewMatrix, fOverrides.readsCoverage(),
+                                                true, nullptr);
         if (!gp) {
             SkDebugf("Couldn't create GrGeometryProcessor\n");
             return;
         }
+        SkASSERT(gp->getVertexStride() ==
+                 sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr));
 
         size_t vertexStride = gp->getVertexStride();
         int instanceCount = fGeoData.count();
 
-        SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
+        SkAutoTUnref<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
         InstancedHelper helper;
         void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
                                      indexBuffer, kVertsPerInstance,
@@ -213,13 +162,12 @@
         for (int i = 0; i < instanceCount; i++) {
             intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
                              i * kVertsPerInstance * vertexStride;
-            Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
+            tesselate(verts, vertexStride, fGeoData[i].fColor, fGeoData[i].fViewMatrix,
+                      fGeoData[i].fRect, &fGeoData[i].fLocalQuad);
         }
         helper.recordDraw(target, gp.get());
     }
 
-    const Geometry& seedGeometry() const { return fGeoData[0]; }
-
     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
         NonAAFillRectBatch* that = t->cast<NonAAFillRectBatch>();
         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
@@ -227,10 +175,6 @@
             return false;
         }
 
-        if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
-            return false;
-        }
-
         // In the event of two batches, one who can tweak, one who cannot, we just fall back to
         // not tweaking
         if (fOverrides.canTweakAlphaForCoverage() && !that->fOverrides.canTweakAlphaForCoverage()) {
@@ -265,13 +209,16 @@
 
     static NonAAFillRectPerspectiveBatch* Create() { return new NonAAFillRectPerspectiveBatch; }
 
-    const char* name() const override { return Name(); }
+    const char* name() const override { return "NonAAFillRectPerspectiveBatch"; }
 
     SkString dumpInfo() const override {
         SkString str;
         str.appendf("# batched: %d\n", fGeoData.count());
         for (int i = 0; i < fGeoData.count(); ++i) {
-            str.append(DumpInfo(fGeoData[i], i));
+            const Geometry& geo = fGeoData[0];
+            str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
+                        i, geo.fColor,
+                        geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
         }
         str.append(INHERITED::dumpInfo());
         return str;
@@ -282,7 +229,7 @@
                                       GrBatchToXPOverrides* overrides) const override {
         // When this is called on a batch, there is only one geometry bundle
         color->setKnownFourComponents(fGeoData[0].fColor);
-        InitInvariantOutputCoverage(coverage);
+        coverage->setKnownSingleComponent(0xff);
     }
 
     void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
@@ -293,90 +240,30 @@
     SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
 
     // After seeding, the client should call init() so the Batch can initialize itself
-    void init() {
-        const Geometry& geo = fGeoData[0];
-        SetBounds(geo, &fBounds);
-    }
-
-    void updateBoundsAfterAppend() {
-        const Geometry& geo = fGeoData.back();
-        UpdateBoundsAfterAppend(geo, &fBounds);
-    }
+    void init() { fGeoData[0].fViewMatrix.mapRect(&fBounds, fGeoData[0].fRect); }
 
 private:
-    static const char* Name() { return "NonAAFillRectPerspectiveBatch"; }
-
-    static SkString DumpInfo(const Geometry& geo, int index) {
-        SkString str;
-        str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
-                    index,
-                    geo.fColor,
-                    geo.fRect.fLeft, geo.fRect.fTop, geo.fRect.fRight, geo.fRect.fBottom);
-        return str;
-    }
-
-    static bool CanCombine(const Geometry& mine, const Geometry& theirs,
-                           const GrXPOverridesForBatch& overrides) {
-        // We could batch across perspective vm changes if we really wanted to
-        return mine.fViewMatrix.cheapEqualTo(theirs.fViewMatrix) &&
-               mine.fHasLocalRect == theirs.fHasLocalRect &&
-               (!mine.fHasLocalMatrix || mine.fLocalMatrix.cheapEqualTo(theirs.fLocalMatrix));
-    }
-
-    static sk_sp<GrGeometryProcessor> MakeGP(const Geometry& geo,
-                                             const GrXPOverridesForBatch& overrides) {
-        sk_sp<GrGeometryProcessor> gp = make_gp(geo.fViewMatrix, overrides.readsCoverage(),
-                                                geo.fHasLocalRect,
-                                                geo.fHasLocalMatrix ? &geo.fLocalMatrix
-                                                                    : nullptr);
-
-        SkASSERT(geo.fHasLocalRect ?
-             gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr) :
-             gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
-        return gp;
-    }
-
-    static void Tesselate(intptr_t vertices, size_t vertexStride, const Geometry& geo,
-                          const GrXPOverridesForBatch& overrides) {
-        if (geo.fHasLocalRect) {
-            GrQuad quad(geo.fLocalRect);
-            tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, &quad);
-        } else {
-            tesselate(vertices, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, nullptr);
-        }
-    }
-
-    static void InitInvariantOutputCoverage(GrInitInvariantOutput* out) {
-        out->setKnownSingleComponent(0xff);
-    }
-
-    static const GrBuffer* GetIndexBuffer(GrResourceProvider* rp) {
-        return rp->refQuadIndexBuffer();
-    }
-
-    static void SetBounds(const Geometry& geo, SkRect* outBounds) {
-        geo.fViewMatrix.mapRect(outBounds, geo.fRect);
-    }
-
-    static void UpdateBoundsAfterAppend(const Geometry& geo, SkRect* outBounds) {
-        SkRect bounds = geo.fRect;
-        geo.fViewMatrix.mapRect(&bounds);
-        outBounds->join(bounds);
-    }
-
     NonAAFillRectPerspectiveBatch() : INHERITED(ClassID()) {}
 
     void onPrepareDraws(Target* target) const override {
-        sk_sp<GrGeometryProcessor> gp(MakeGP(this->seedGeometry(), fOverrides));
+        sk_sp<GrGeometryProcessor> gp = make_gp(fGeoData[0].fViewMatrix, fOverrides.readsCoverage(),
+                                                fGeoData[0].fHasLocalRect,
+                                                fGeoData[0].fHasLocalMatrix
+                                                    ? &fGeoData[0].fLocalMatrix
+                                                    : nullptr);
         if (!gp) {
             SkDebugf("Couldn't create GrGeometryProcessor\n");
             return;
         }
+        SkASSERT(fGeoData[0].fHasLocalRect
+                     ? gp->getVertexStride() ==
+                         sizeof(GrDefaultGeoProcFactory::PositionColorLocalCoordAttr)
+                     : gp->getVertexStride() == sizeof(GrDefaultGeoProcFactory::PositionColorAttr));
 
         size_t vertexStride = gp->getVertexStride();
         int instanceCount = fGeoData.count();
 
-        SkAutoTUnref<const GrBuffer> indexBuffer(GetIndexBuffer(target->resourceProvider()));
+        SkAutoTUnref<const GrBuffer> indexBuffer(target->resourceProvider()->refQuadIndexBuffer());
         InstancedHelper helper;
         void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
                                      indexBuffer, kVertsPerInstance,
@@ -387,9 +274,15 @@
         }
 
         for (int i = 0; i < instanceCount; i++) {
+            const Geometry& geo = fGeoData[i];
             intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
                              i * kVertsPerInstance * vertexStride;
-            Tesselate(verts, vertexStride, fGeoData[i], fOverrides);
+            if (geo.fHasLocalRect) {
+                GrQuad quad(geo.fLocalRect);
+                tesselate(verts, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, &quad);
+            } else {
+                tesselate(verts, vertexStride, geo.fColor, geo.fViewMatrix, geo.fRect, nullptr);
+            }
         }
         helper.recordDraw(target, gp.get());
     }
@@ -403,7 +296,15 @@
             return false;
         }
 
-        if (!CanCombine(this->seedGeometry(), that->seedGeometry(), fOverrides)) {
+        // We could batch across perspective vm changes if we really wanted to
+        if (!fGeoData[0].fViewMatrix.cheapEqualTo(that->fGeoData[0].fViewMatrix)) {
+            return false;
+        }
+        if (fGeoData[0].fHasLocalRect != that->fGeoData[0].fHasLocalRect) {
+            return false;
+        }
+        if (fGeoData[0].fHasLocalMatrix &&
+            !fGeoData[0].fLocalMatrix.cheapEqualTo(that->fGeoData[0].fLocalMatrix)) {
             return false;
         }