Add code path that avoids large indexBuffer draws

The bulkrect_1000_random_uniqueimages_batch on a Nexus 6P/Adreno 430

w/o this CL
curr/maxrss	loops	min	median	mean	max	stddev	samples   	config
 304/304 MB	1	151ms	159ms	158ms	163ms	3%	▆█▇▄▆▆▁▂█▅	gles

w/ this CL
curr/maxrss	loops	min	median	mean	max	stddev	samples   	config
 286/286 MB	1	18.1ms	18.1ms	18.1ms	18.1ms	0%	▂▄▅▃▅▅▃▄▁█	gles

Change-Id: I0f6d690b953444ec7a3176cb27c8a253caa55f5d
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/255986
Commit-Queue: Robert Phillips <robertphillips@google.com>
Reviewed-by: Michael Ludwig <michaelludwig@google.com>
diff --git a/src/gpu/ops/GrQuadPerEdgeAA.cpp b/src/gpu/ops/GrQuadPerEdgeAA.cpp
index 70a8607..ca0c7c0 100644
--- a/src/gpu/ops/GrQuadPerEdgeAA.cpp
+++ b/src/gpu/ops/GrQuadPerEdgeAA.cpp
@@ -381,7 +381,7 @@
     SkUNREACHABLE;
 }
 
-void ConfigureMesh(GrMesh* mesh, const VertexSpec& spec,
+void ConfigureMesh(const GrCaps& caps, GrMesh* mesh, const VertexSpec& spec,
                    int runningQuadCount, int quadsInDraw, int maxVerts,
                    sk_sp<const GrBuffer> vertexBuffer,
                    sk_sp<const GrBuffer> indexBuffer, int absVertBufferOffset) {
@@ -403,28 +403,42 @@
              spec.indexBufferOption() == IndexBufferOption::kIndexedRects);
     SkASSERT(indexBuffer);
 
-    int baseIndex, numIndicesToDraw;
-    int minVertex, maxVertex;
+    int maxNumQuads, numIndicesPerQuad, numVertsPerQuad;
 
     if (spec.indexBufferOption() == IndexBufferOption::kPictureFramed) {
-        SkASSERT(runningQuadCount + quadsInDraw <= GrResourceProvider::MaxNumAAQuads());
         // AA uses 8 vertices and 30 indices per quad, basically nested rectangles
-        baseIndex = runningQuadCount * GrResourceProvider::NumIndicesPerAAQuad();
-        numIndicesToDraw = quadsInDraw * GrResourceProvider::NumIndicesPerAAQuad();
-        minVertex = runningQuadCount * GrResourceProvider::NumVertsPerAAQuad();
-        maxVertex = (runningQuadCount + quadsInDraw) * GrResourceProvider::NumVertsPerAAQuad();
+        maxNumQuads = GrResourceProvider::MaxNumAAQuads();
+        numIndicesPerQuad = GrResourceProvider::NumIndicesPerAAQuad();
+        numVertsPerQuad = GrResourceProvider::NumVertsPerAAQuad();
     } else {
-        SkASSERT(runningQuadCount + quadsInDraw <= GrResourceProvider::MaxNumNonAAQuads());
         // Non-AA uses 4 vertices and 6 indices per quad
-        baseIndex = runningQuadCount * GrResourceProvider::NumIndicesPerNonAAQuad();
-        numIndicesToDraw = quadsInDraw * GrResourceProvider::NumIndicesPerNonAAQuad();
-        minVertex = runningQuadCount * GrResourceProvider::NumVertsPerNonAAQuad();
-        maxVertex = (runningQuadCount + quadsInDraw) * GrResourceProvider::NumVertsPerNonAAQuad();
+        maxNumQuads = GrResourceProvider::MaxNumNonAAQuads();
+        numIndicesPerQuad = GrResourceProvider::NumIndicesPerNonAAQuad();
+        numVertsPerQuad = GrResourceProvider::NumVertsPerNonAAQuad();
     }
 
-    mesh->setIndexed(std::move(indexBuffer), numIndicesToDraw, baseIndex, minVertex, maxVertex,
-                     GrPrimitiveRestart::kNo);
-    mesh->setVertexData(std::move(vertexBuffer), absVertBufferOffset);
+    SkASSERT(runningQuadCount + quadsInDraw <= maxNumQuads);
+
+    if (caps.avoidLargeIndexBufferDraws()) {
+        // When we need to avoid large index buffer draws we modify the base vertex of the draw
+        // which, in GL, requires rebinding all vertex attrib arrays, so a base index is generally
+        // preferred.
+        int offset = absVertBufferOffset + runningQuadCount * numVertsPerQuad;
+
+        mesh->setIndexedPatterned(std::move(indexBuffer), numIndicesPerQuad,
+                                  numVertsPerQuad, quadsInDraw, maxNumQuads);
+        mesh->setVertexData(std::move(vertexBuffer), offset);
+    } else {
+        int baseIndex = runningQuadCount * numIndicesPerQuad;
+        int numIndicesToDraw = quadsInDraw * numIndicesPerQuad;
+
+        int minVertex = runningQuadCount * numVertsPerQuad;
+        int maxVertex = (runningQuadCount + quadsInDraw) * numVertsPerQuad;
+
+        mesh->setIndexed(std::move(indexBuffer), numIndicesToDraw,
+                         baseIndex, minVertex, maxVertex, GrPrimitiveRestart::kNo);
+        mesh->setVertexData(std::move(vertexBuffer), absVertBufferOffset);
+    }
 }
 
 ////////////////// VertexSpec Implementation