Increase batching for AA fill rects.

This allows batching of rects provided without a local matrix when local coords are required and when the view matrix changes.

It also allows batching of rects with a local matrix with rects without a local matrix.
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2116823002

Review-Url: https://codereview.chromium.org/2116823002
diff --git a/src/gpu/batches/GrAAFillRectBatch.cpp b/src/gpu/batches/GrAAFillRectBatch.cpp
index ffbab96..fedde70 100644
--- a/src/gpu/batches/GrAAFillRectBatch.cpp
+++ b/src/gpu/batches/GrAAFillRectBatch.cpp
@@ -13,9 +13,9 @@
 #include "GrResourceKey.h"
 #include "GrResourceProvider.h"
 #include "GrTypes.h"
+#include "GrVertexBatch.h"
 #include "SkMatrix.h"
 #include "SkRect.h"
-#include "GrVertexBatch.h"
 
 GR_DECLARE_STATIC_UNIQUE_KEY(gAAFillRectIndexBufferKey);
 
@@ -45,35 +45,6 @@
         gAAFillRectIndexBufferKey);
 }
 
-static sk_sp<GrGeometryProcessor> create_fill_rect_gp(
-                                       const SkMatrix& viewMatrix,
-                                       const GrXPOverridesForBatch& overrides,
-                                       GrDefaultGeoProcFactory::LocalCoords::Type localCoordsType) {
-    using namespace GrDefaultGeoProcFactory;
-
-    Color color(Color::kAttribute_Type);
-    Coverage::Type coverageType;
-    // TODO remove coverage if coverage is ignored
-    /*if (coverageIgnored) {
-        coverageType = Coverage::kNone_Type;
-    } else*/ if (overrides.canTweakAlphaForCoverage()) {
-        coverageType = Coverage::kSolid_Type;
-    } else {
-        coverageType = Coverage::kAttribute_Type;
-    }
-    Coverage coverage(coverageType);
-
-    // We assume the caller has inverted the viewmatrix
-    if (LocalCoords::kHasExplicit_Type == localCoordsType) {
-        LocalCoords localCoords(localCoordsType);
-        return GrDefaultGeoProcFactory::Make(color, coverage, localCoords, SkMatrix::I());
-    } else {
-        LocalCoords localCoords(overrides.readsLocalCoords() ? localCoordsType :
-                                                               LocalCoords::kUnused_Type);
-        return MakeForDeviceSpace(color, coverage, localCoords, viewMatrix);
-    }
-}
-
 static void generate_aa_fill_rect_geometry(intptr_t verts,
                                            size_t vertexStride,
                                            GrColor color,
@@ -137,7 +108,7 @@
     if (localMatrix) {
         SkMatrix invViewMatrix;
         if (!viewMatrix.invert(&invViewMatrix)) {
-            SkASSERT(false);
+            SkDebugf("View matrix is non-invertible, local coords will be wrong.");
             invViewMatrix = SkMatrix::I();
         }
         SkMatrix localCoordMatrix;
@@ -186,28 +157,37 @@
         }
     }
 }
-
-class AAFillRectNoLocalMatrixBatch : public GrVertexBatch {
+class AAFillRectBatch : public GrVertexBatch {
 public:
     DEFINE_BATCH_CLASS_ID
-    AAFillRectNoLocalMatrixBatch(GrColor color,
-                                 const SkMatrix& viewMatrix,
-                                 const SkRect& rect,
-                                 const SkRect& devRect) : INHERITED(ClassID()) {
-        fRects.emplace_back(RectInfo{color, viewMatrix, rect, devRect});
+
+    AAFillRectBatch(GrColor color,
+                    const SkMatrix& viewMatrix,
+                    const SkRect& rect,
+                    const SkRect& devRect,
+                    const SkMatrix* localMatrix) : INHERITED(ClassID()) {
+        if (localMatrix) {
+            void* mem = fRectData.push_back_n(sizeof(RectWithLocalMatrixInfo));
+            new (mem) RectWithLocalMatrixInfo(color, viewMatrix, rect, devRect, *localMatrix);
+        } else {
+            void* mem = fRectData.push_back_n(sizeof(RectInfo));
+            new (mem) RectInfo(color, viewMatrix, rect, devRect);
+        }
         fBounds = devRect;
+        fRectCnt = 1;
     }
 
-    const char* name() const override { return "AAFillRectBatchNoLocalMatrix"; }
+    const char* name() const override { return "AAFillRectBatch"; }
 
     SkString dumpInfo() const override {
         SkString str;
-        str.appendf("# batched: %d\n", fRects.count());
-        for (int i = 0; i < fRects.count(); ++i) {
-            const RectInfo& info = fRects[i];
+        str.appendf("# batched: %d\n", fRectCnt);
+        const RectInfo* info = this->first();
+        for (int i = 0; i < fRectCnt; ++i) {
+            const SkRect& rect = info->rect();
             str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
-                        i, info.fColor,
-                        info.fRect.fLeft, info.fRect.fTop, info.fRect.fRight, info.fRect.fBottom);
+                        i, info->color(), rect.fLeft, rect.fTop, rect.fRight, rect.fBottom);
+            info = this->next(info);
         }
         str.append(INHERITED::dumpInfo());
         return str;
@@ -217,30 +197,39 @@
                                       GrInitInvariantOutput* coverage,
                                       GrBatchToXPOverrides* overrides) const override {
         // When this is called on a batch, there is only one rect
-        color->setKnownFourComponents(fRects[0].fColor);
+        color->setKnownFourComponents(this->first()->color());
         coverage->setUnknownSingleComponent();
     }
 
     void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
-        overrides.getOverrideColorIfSet(&fRects[0].fColor);
+        GrColor color;
+        if (overrides.getOverrideColorIfSet(&color)) {
+            this->first()->setColor(color);
+        }
         fOverrides = overrides;
     }
 
 private:
-    AAFillRectNoLocalMatrixBatch() : INHERITED(ClassID()) {}
-
     void onPrepareDraws(Target* target) const override {
-        sk_sp<GrGeometryProcessor> gp =
-                create_fill_rect_gp(fRects[0].fViewMatrix, fOverrides,
-                                    GrDefaultGeoProcFactory::LocalCoords::kUsePosition_Type);
+        bool needLocalCoords = fOverrides.readsLocalCoords();
+        using namespace GrDefaultGeoProcFactory;
+
+        Color color(Color::kAttribute_Type);
+        Coverage::Type coverageType;
+        if (fOverrides.canTweakAlphaForCoverage()) {
+            coverageType = Coverage::kSolid_Type;
+        } else {
+            coverageType = Coverage::kAttribute_Type;
+        }
+        Coverage coverage(coverageType);
+        LocalCoords lc = needLocalCoords ? LocalCoords::kHasExplicit_Type
+                                         : LocalCoords::kUnused_Type;
+        sk_sp<GrGeometryProcessor> gp = GrDefaultGeoProcFactory::Make(color, coverage, lc,
+                                                                      SkMatrix::I());
         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();
 
@@ -248,171 +237,104 @@
         InstancedHelper helper;
         void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
                                      indexBuffer, kVertsPerAAFillRect,
-                                     kIndicesPerAAFillRect, fRects.count());
+                                     kIndicesPerAAFillRect, fRectCnt);
         if (!vertices || !indexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
 
-        for (int i = 0; i < fRects.count(); i++) {
+        const RectInfo* info = this->first();
+        const SkMatrix* localMatrix = nullptr;
+        for (int i = 0; i < fRectCnt; i++) {
             intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
                              i * kVertsPerAAFillRect * vertexStride;
-            generate_aa_fill_rect_geometry(verts, vertexStride,
-                                           fRects[i].fColor, fRects[i].fViewMatrix,
-                                           fRects[i].fRect, fRects[i].fDevRect, fOverrides,
-                                           nullptr);
+            if (needLocalCoords) {
+                if (info->hasLocalMatrix()) {
+                    localMatrix = &static_cast<const RectWithLocalMatrixInfo*>(info)->localMatrix();
+                } else {
+                    localMatrix = &SkMatrix::I();
+                }
+            }
+            generate_aa_fill_rect_geometry(verts, vertexStride, info->color(),
+                                           info->viewMatrix(), info->rect(),
+                                           info->devRect(), fOverrides, localMatrix);
+            info = this->next(info);
         }
         helper.recordDraw(target, gp.get());
     }
 
     bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
-        AAFillRectNoLocalMatrixBatch* that = t->cast<AAFillRectNoLocalMatrixBatch>();
+        AAFillRectBatch* that = t->cast<AAFillRectBatch>();
         if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
                                     that->bounds(), caps)) {
             return false;
         }
 
-        // 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() &&
-            !fRects[0].fViewMatrix.cheapEqualTo(that->fRects[0].fViewMatrix)) {
-            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()) {
             fOverrides = that->fOverrides;
         }
 
-        fRects.push_back_n(that->fRects.count(), that->fRects.begin());
+        fRectData.push_back_n(that->fRectData.count(), that->fRectData.begin());
+        fRectCnt += that->fRectCnt;
         this->joinBounds(that->bounds());
         return true;
     }
 
     struct RectInfo {
+    public:
+        RectInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
+                 const SkRect& devRect)
+            : RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kNo) {}
+        bool hasLocalMatrix() const { return HasLocalMatrix::kYes == fHasLocalMatrix; }
+        GrColor color() const { return fColor; }
+        const SkMatrix& viewMatrix() const { return fViewMatrix; }
+        const SkRect& rect() const { return fRect; }
+        const SkRect& devRect() const { return fDevRect; }
+
+        void setColor(GrColor color) { fColor = color; }
+    protected:
+        enum class HasLocalMatrix : uint32_t { kNo, kYes };
+
+        RectInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
+                 const SkRect& devRect, HasLocalMatrix hasLM)
+                : fHasLocalMatrix(hasLM)
+                , fColor(color)
+                , fViewMatrix(viewMatrix)
+                , fRect(rect)
+                , fDevRect(devRect) {}
+
+        HasLocalMatrix fHasLocalMatrix;
         GrColor fColor;
         SkMatrix fViewMatrix;
         SkRect fRect;
         SkRect fDevRect;
     };
 
-    GrXPOverridesForBatch fOverrides;
-    SkSTArray<1, RectInfo, true> fRects;
-
-    typedef GrVertexBatch INHERITED;
-};
-
-class AAFillRectLocalMatrixBatch : public GrVertexBatch {
-public:
-    DEFINE_BATCH_CLASS_ID
-
-    AAFillRectLocalMatrixBatch(GrColor color,
-                               const SkMatrix& viewMatrix,
-                               const SkMatrix& localMatrix,
-                               const SkRect& rect,
-                               const SkRect& devRect) : INHERITED(ClassID()) {
-        fRects.emplace_back(RectInfo{color, viewMatrix, localMatrix, rect, devRect});
-        fBounds = devRect;
-    }
-
-    const char* name() const override { return "AAFillRectBatchLocalMatrix"; }
-
-    SkString dumpInfo() const override {
-        SkString str;
-        str.appendf("# batched: %d\n", fRects.count());
-        for (int i = 0; i < fRects.count(); ++i) {
-            const RectInfo& info = fRects[i];
-            str.appendf("%d: Color: 0x%08x, Rect [L: %.2f, T: %.2f, R: %.2f, B: %.2f]\n",
-                        i, info.fColor,
-                        info.fRect.fLeft, info.fRect.fTop, info.fRect.fRight, info.fRect.fBottom);
-        }
-        str.append(INHERITED::dumpInfo());
-        return str;
-    }
-
-    void computePipelineOptimizations(GrInitInvariantOutput* color,
-                                      GrInitInvariantOutput* coverage,
-                                      GrBatchToXPOverrides* overrides) const override {
-        // When this is called on a batch, there is only one rect
-        color->setKnownFourComponents(fRects[0].fColor);
-        coverage->setUnknownSingleComponent();
-    }
-
-    void initBatchTracker(const GrXPOverridesForBatch& overrides) override {
-        overrides.getOverrideColorIfSet(&fRects[0].fColor);
-        fOverrides = overrides;
-    }
-
-private:
-    AAFillRectLocalMatrixBatch() : INHERITED(ClassID()) {}
-
-    void onPrepareDraws(Target* target) const override {
-        sk_sp<GrGeometryProcessor> gp =
-                create_fill_rect_gp(fRects[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();
-
-        SkAutoTUnref<const GrBuffer> indexBuffer(get_index_buffer(target->resourceProvider()));
-        InstancedHelper helper;
-        void* vertices = helper.init(target, kTriangles_GrPrimitiveType, vertexStride,
-                                     indexBuffer, kVertsPerAAFillRect,
-                                     kIndicesPerAAFillRect, fRects.count());
-        if (!vertices || !indexBuffer) {
-            SkDebugf("Could not allocate vertices\n");
-            return;
-        }
-
-        for (int i = 0; i < fRects.count(); i++) {
-            intptr_t verts = reinterpret_cast<intptr_t>(vertices) +
-                             i * kVertsPerAAFillRect * vertexStride;
-            generate_aa_fill_rect_geometry(verts, vertexStride, fRects[i].fColor,
-                                           fRects[i].fViewMatrix, fRects[i].fRect,
-                                           fRects[i].fDevRect, fOverrides,
-                                           &fRects[i].fLocalMatrix);
-        }
-        helper.recordDraw(target, gp.get());
-    }
-
-    bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
-        AAFillRectLocalMatrixBatch* that = t->cast<AAFillRectLocalMatrixBatch>();
-        if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pipeline(),
-                                    that->bounds(), caps)) {
-            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()) {
-            fOverrides = that->fOverrides;
-        }
-
-        fRects.push_back_n(that->fRects.count(), that->fRects.begin());
-        this->joinBounds(that->bounds());
-        return true;
-    }
-
-    struct RectInfo {
-        GrColor fColor;
-        SkMatrix fViewMatrix;
+    struct RectWithLocalMatrixInfo : public RectInfo {
+    public:
+        RectWithLocalMatrixInfo(GrColor color, const SkMatrix& viewMatrix, const SkRect& rect,
+                                const SkRect& devRect, const SkMatrix& localMatrix)
+            : RectInfo(color, viewMatrix, rect, devRect, HasLocalMatrix::kYes)
+            , fLocalMatrix(localMatrix) {}
+        const SkMatrix& localMatrix() const { return fLocalMatrix; }
+    private:
         SkMatrix fLocalMatrix;
-        SkRect fRect;
-        SkRect fDevRect;
     };
 
+    RectInfo* first() { return reinterpret_cast<RectInfo*>(fRectData.begin()); }
+    const RectInfo* first() const { return reinterpret_cast<const RectInfo*>(fRectData.begin()); }
+    const RectInfo* next(const RectInfo* prev) const {
+        intptr_t next = reinterpret_cast<intptr_t>(prev) +
+                (prev->hasLocalMatrix() ? sizeof(RectWithLocalMatrixInfo)
+                                        : sizeof(RectInfo));
+        return reinterpret_cast<const RectInfo*>(next);
+    }
+
     GrXPOverridesForBatch fOverrides;
-    SkSTArray<1, RectInfo, true> fRects;
+    SkSTArray<4 * sizeof(RectWithLocalMatrixInfo), uint8_t, true> fRectData;
+    int fRectCnt;
 
     typedef GrVertexBatch INHERITED;
 };
@@ -423,7 +345,7 @@
                     const SkMatrix& viewMatrix,
                     const SkRect& rect,
                     const SkRect& devRect) {
-    return new AAFillRectNoLocalMatrixBatch(color, viewMatrix, rect, devRect);
+    return new AAFillRectBatch(color, viewMatrix, rect, devRect, nullptr);
 }
 
 GrDrawBatch* Create(GrColor color,
@@ -431,7 +353,7 @@
                     const SkMatrix& localMatrix,
                     const SkRect& rect,
                     const SkRect& devRect) {
-    return new AAFillRectLocalMatrixBatch(color, viewMatrix, localMatrix, rect, devRect);
+    return new AAFillRectBatch(color, viewMatrix, rect, devRect, &localMatrix);
 }
 
 GrDrawBatch* Create(GrColor color,