Respect max index buffer sizes in GrFillRectOp::MakeSet

This is required before we can lower the max AA quad count (again).

Bug: b/143572065 skia:9601
Change-Id: Iea5884ffff9bd62f62527fcb597dac97d33ecd76
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/254438
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/ops/GrFillRectOp.cpp b/src/gpu/ops/GrFillRectOp.cpp
index ec6fa0b..2ee183a 100644
--- a/src/gpu/ops/GrFillRectOp.cpp
+++ b/src/gpu/ops/GrFillRectOp.cpp
@@ -178,13 +178,11 @@
     DEFINE_OP_CLASS_ID
 
 private:
-    // For GrFillRectOp::MakeSet's use of addQuad
-    friend std::unique_ptr<GrDrawOp> GrFillRectOp::MakeSet(
-            GrRecordingContext*,
-            GrPaint&&,
-            GrAAType, const SkMatrix& viewMatrix,
-            const GrRenderTargetContext::QuadSetEntry quads[], int quadCount,
-            const GrUserStencilSettings*);
+    friend class ::GrFillRectOp; // for access to addQuad
+
+#if GR_TEST_UTILS
+    int numQuads() const final { return fQuads.count(); }
+#endif
 
     void onPrepareDraws(Target* target) override {
         TRACE_EVENT0("skia.gpu", TRACE_FUNC);
@@ -297,19 +295,29 @@
     // But since it's avoiding the op list management, it must update the op's bounds. This is only
     // used with quad sets, which uses the same view matrix for each quad so this assumes that the
     // device quad type of the new quad is the same as the op's.
-    void addQuad(const GrQuad& deviceQuad, const GrQuad& localQuad,
+    bool addQuad(const GrQuad& deviceQuad, const GrQuad& localQuad,
                  const SkPMColor4f& color, GrQuadAAFlags edgeAA, GrAAType aaType) {
         // The new quad's aa type should be the same as the first quad's or none, except when the
         // first quad's aa type was already downgraded to none, in which case the stored type must
         // be lifted to back to the requested type.
-        if (aaType != fHelper.aaType()) {
-            if (aaType != GrAAType::kNone) {
-                // Original quad was downgraded to non-aa, lift back up to this quad's required type
-                SkASSERT(fHelper.aaType() == GrAAType::kNone);
-                fHelper.setAAType(aaType);
+        if (aaType != fHelper.aaType() && aaType != GrAAType::kNone) {
+            auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(aaType,
+                                                                            fQuads.count()+1);
+            if (fQuads.count()+1 > GrQuadPerEdgeAA::QuadLimit(indexBufferOption)) {
+                // Promoting to the new aaType would've caused an overflow of the indexBuffer
+                // limit
+                return false;
             }
-            // else the new quad could have been downgraded but the other quads can't be, so don't
-            // reset the op's accumulated aa type.
+
+            // Original quad was downgraded to non-aa, lift back up to this quad's required type
+            SkASSERT(fHelper.aaType() == GrAAType::kNone);
+            fHelper.setAAType(aaType);
+        } else {
+            auto indexBufferOption = GrQuadPerEdgeAA::CalcIndexBufferOption(fHelper.aaType(),
+                                                                            fQuads.count()+1);
+            if (fQuads.count()+1 > GrQuadPerEdgeAA::QuadLimit(indexBufferOption)) {
+                return false; // This op can't grow any more
+            }
         }
 
         // Update the bounds and add the quad to this op's storage
@@ -318,6 +326,7 @@
         this->setBounds(newBounds, HasAABloat(fHelper.aaType() == GrAAType::kCoverage),
                         IsHairline::kNo);
         fQuads.append(deviceQuad, { color, edgeAA }, fHelper.isTrivial() ? nullptr : &localQuad);
+        return true;
     }
 
     struct ColorAndAA {
@@ -335,45 +344,46 @@
 
 } // anonymous namespace
 
-namespace GrFillRectOp {
-
-std::unique_ptr<GrDrawOp> Make(GrRecordingContext* context,
-                               GrPaint&& paint,
-                               GrAAType aaType,
-                               GrQuadAAFlags aaFlags,
-                               const GrQuad& deviceQuad,
-                               const GrQuad& localQuad,
-                               const GrUserStencilSettings* stencil) {
+std::unique_ptr<GrDrawOp> GrFillRectOp::Make(GrRecordingContext* context,
+                                             GrPaint&& paint,
+                                             GrAAType aaType,
+                                             GrQuadAAFlags aaFlags,
+                                             const GrQuad& deviceQuad,
+                                             const GrQuad& localQuad,
+                                             const GrUserStencilSettings* stencil) {
     return FillRectOp::Make(context, std::move(paint), aaType, aaFlags, stencil,
                             deviceQuad, localQuad);
 }
 
-std::unique_ptr<GrDrawOp> MakeNonAARect(GrRecordingContext* context,
-                                        GrPaint&& paint,
-                                        const SkMatrix& view,
-                                        const SkRect& rect,
-                                        const GrUserStencilSettings* stencil) {
+std::unique_ptr<GrDrawOp> GrFillRectOp::MakeNonAARect(GrRecordingContext* context,
+                                                      GrPaint&& paint,
+                                                      const SkMatrix& view,
+                                                      const SkRect& rect,
+                                                      const GrUserStencilSettings* stencil) {
     return FillRectOp::Make(context, std::move(paint), GrAAType::kNone, GrQuadAAFlags::kNone,
                             stencil, GrQuad::MakeFromRect(rect, view), GrQuad(rect));
 }
 
-std::unique_ptr<GrDrawOp> MakeSet(GrRecordingContext* context,
-                                  GrPaint&& paint,
-                                  GrAAType aaType,
-                                  const SkMatrix& viewMatrix,
-                                  const GrRenderTargetContext::QuadSetEntry quads[],
-                                  int cnt,
-                                  const GrUserStencilSettings* stencilSettings) {
+std::unique_ptr<GrDrawOp> GrFillRectOp::MakeOp(GrRecordingContext* context,
+                                               GrPaint&& paint,
+                                               GrAAType aaType,
+                                               const SkMatrix& viewMatrix,
+                                               const GrRenderTargetContext::QuadSetEntry quads[],
+                                               int cnt,
+                                               const GrUserStencilSettings* stencilSettings,
+                                               int* numConsumed) {
     // First make a draw op for the first quad in the set
     SkASSERT(cnt > 0);
 
     paint.setColor4f(quads[0].fColor);
-    std::unique_ptr<GrDrawOp> op = FillRectOp::Make(context, std::move(paint), aaType,
+    std::unique_ptr<GrDrawOp> op = FillRectOp::Make(
+            context, std::move(paint), aaType,
             quads[0].fAAFlags, stencilSettings,
             GrQuad::MakeFromRect(quads[0].fRect, viewMatrix),
             GrQuad::MakeFromRect(quads[0].fRect, quads[0].fLocalMatrix));
-    auto* fillRects = op->cast<FillRectOp>();
+    FillRectOp* fillRects = op->cast<FillRectOp>();
 
+    *numConsumed = 1;
     // Accumulate remaining quads similar to onCombineIfPossible() without creating an op
     for (int i = 1; i < cnt; ++i) {
         GrQuad deviceQuad = GrQuad::MakeFromRect(quads[i].fRect, viewMatrix);
@@ -383,18 +393,52 @@
         GrQuadUtils::ResolveAAType(aaType, quads[i].fAAFlags, deviceQuad,
                                    &resolvedAA, &resolvedEdgeFlags);
 
-        fillRects->addQuad(deviceQuad,
-                           GrQuad::MakeFromRect(quads[i].fRect, quads[i].fLocalMatrix),
-                           quads[i].fColor, resolvedEdgeFlags,resolvedAA);
+        if (!fillRects->addQuad(deviceQuad,
+                                GrQuad::MakeFromRect(quads[i].fRect, quads[i].fLocalMatrix),
+                                quads[i].fColor, resolvedEdgeFlags, resolvedAA)) {
+            break;
+        }
+
+        (*numConsumed)++;
     }
 
     return op;
 }
 
-} // namespace GrFillRectOp
+void GrFillRectOp::AddFillRectOps(GrRenderTargetContext* rtc,
+                                  const GrClip& clip,
+                                  GrRecordingContext* context,
+                                  GrPaint&& paint,
+                                  GrAAType aaType,
+                                  const SkMatrix& viewMatrix,
+                                  const GrRenderTargetContext::QuadSetEntry quads[],
+                                  int cnt,
+                                  const GrUserStencilSettings* stencilSettings) {
+
+    int offset = 0;
+    int numLeft = cnt;
+    while (numLeft) {
+        int numConsumed = 0;
+
+        std::unique_ptr<GrDrawOp> op = MakeOp(context, GrPaint::Clone(paint), aaType, viewMatrix,
+                                              &quads[offset], numLeft, stencilSettings,
+                                              &numConsumed);
+
+        offset += numConsumed;
+        numLeft -= numConsumed;
+
+        rtc->addDrawOp(clip, std::move(op));
+    }
+
+    SkASSERT(offset == cnt);
+}
 
 #if GR_TEST_UTILS
 
+uint32_t GrFillRectOp::ClassID() {
+    return FillRectOp::ClassID();
+}
+
 #include "src/gpu/GrDrawOpTest.h"
 #include "src/gpu/SkGr.h"
 
@@ -417,35 +461,11 @@
 
     if (random->nextBool()) {
         if (random->nextBool()) {
-            if (random->nextBool()) {
-                // Local matrix with a set op
-                uint32_t extraQuadCt = random->nextRangeU(1, 4);
-                SkTArray<GrRenderTargetContext::QuadSetEntry> quads(extraQuadCt + 1);
-                quads.push_back(
-                        {rect, SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU())),
-                         GrTest::TestMatrixInvertible(random), aaFlags});
-                for (uint32_t i = 0; i < extraQuadCt; ++i) {
-                    GrQuadAAFlags aaFlags = GrQuadAAFlags::kNone;
-                    aaFlags |= random->nextBool() ? GrQuadAAFlags::kLeft : GrQuadAAFlags::kNone;
-                    aaFlags |= random->nextBool() ? GrQuadAAFlags::kTop : GrQuadAAFlags::kNone;
-                    aaFlags |= random->nextBool() ? GrQuadAAFlags::kRight : GrQuadAAFlags::kNone;
-                    aaFlags |= random->nextBool() ? GrQuadAAFlags::kBottom : GrQuadAAFlags::kNone;
-
-                    quads.push_back(
-                        {GrTest::TestRect(random),
-                         SkPMColor4f::FromBytes_RGBA(SkColorToPremulGrColor(random->nextU())),
-                         GrTest::TestMatrixInvertible(random), aaFlags});
-                }
-
-                return GrFillRectOp::MakeSet(context, std::move(paint), aaType, viewMatrix,
-                                             quads.begin(), quads.count(), stencil);
-            } else {
-                // Single local matrix
-                SkMatrix localMatrix = GrTest::TestMatrixInvertible(random);
-                return GrFillRectOp::Make(context, std::move(paint), aaType, aaFlags,
-                                          GrQuad::MakeFromRect(rect, viewMatrix),
-                                          GrQuad::MakeFromRect(rect, localMatrix), stencil);
-            }
+            // Single local matrix
+            SkMatrix localMatrix = GrTest::TestMatrixInvertible(random);
+            return GrFillRectOp::Make(context, std::move(paint), aaType, aaFlags,
+                                      GrQuad::MakeFromRect(rect, viewMatrix),
+                                      GrQuad::MakeFromRect(rect, localMatrix), stencil);
         } else {
             // Pass local rect directly
             SkRect localRect = GrTest::TestRect(random);