simplify GrAtlasTextOp's onPrepare

Change-Id: Ib9fa2d9300a5bc7bfe7231cd858128a79a93bb48
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/302839
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 136b4e8..55ce686 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -12,6 +12,7 @@
 #include "src/core/SkMathPriv.h"
 #include "src/core/SkMatrixPriv.h"
 #include "src/core/SkMatrixProvider.h"
+#include "src/core/SkSpan.h"
 #include "src/core/SkStrikeCache.h"
 #include "src/gpu/GrCaps.h"
 #include "src/gpu/GrMemoryPool.h"
@@ -169,6 +170,7 @@
 
     FlushInfo flushInfo;
     flushInfo.fPrimProcProxies = primProcProxies;
+    flushInfo.fIndexBuffer = resourceProvider->refNonAAQuadIndexBuffer();
 
     bool vmPerspective = fGeoData[0].fDrawMatrix.hasPerspective();
     if (this->usesDistanceFields()) {
@@ -183,102 +185,75 @@
                 numActiveViews, filter, maskFormat, localMatrix, vmPerspective);
     }
 
-    int vertexStride = (int)flushInfo.fGeometryProcessor->vertexStride();
+    const int vertexStride = (int)flushInfo.fGeometryProcessor->vertexStride();
 
     // Ensure we don't request an insanely large contiguous vertex allocation.
     static const int kMaxVertexBytes = GrBufferAllocPool::kDefaultBufferSize;
     const int quadSize = vertexStride * kVerticesPerGlyph;
     const int maxQuadsPerBuffer = kMaxVertexBytes / quadSize;
 
-    // Where the quad buffer begins and ends relative to totalGlyphsRegened.
-    int quadBufferBegin = 0;
-    int quadBufferEnd = std::min(this->numGlyphs(), maxQuadsPerBuffer);
+    int allGlyphsCursor = 0;
+    const int allGlyphsEnd = this->numGlyphs();
+    int quadCursor;
+    int quadEnd;
+    char* vertices;
 
-    flushInfo.fIndexBuffer = resourceProvider->refNonAAQuadIndexBuffer();
-    void* vertices = target->makeVertexSpace(
-            vertexStride,
-            kVerticesPerGlyph * (quadBufferEnd - quadBufferBegin),
-            &flushInfo.fVertexBuffer,
-            &flushInfo.fVertexOffset);
-    if (!vertices || !flushInfo.fVertexBuffer) {
-        SkDebugf("Could not allocate vertices\n");
-        return;
-    }
+    auto resetVertexBuffer = [&] {
+        quadCursor = 0;
+        quadEnd = std::min(maxQuadsPerBuffer, allGlyphsEnd - allGlyphsCursor);
 
-    // totalGlyphsRegened is all the glyphs for the op [0, this->numGlyphs()). The subRun glyph and
-    // quad buffer indices are calculated from this.
-    int totalGlyphsRegened = 0;
-    for (int i = 0; i < fGeoCount; i++) {
-        const Geometry& args = fGeoData[i];
-        auto subRun = args.fSubRunPtr;
+        vertices = (char*)target->makeVertexSpace(
+                vertexStride,
+                kVerticesPerGlyph * quadEnd,
+                &flushInfo.fVertexBuffer,
+                &flushInfo.fVertexOffset);
+
+        if (!vertices || !flushInfo.fVertexBuffer) {
+            SkDebugf("Could not allocate vertices\n");
+            return false;
+        }
+        return true;
+    };
+
+    resetVertexBuffer();
+
+    for (const Geometry& geo : SkMakeSpan(fGeoData.get(), fGeoCount)) {
+        GrAtlasSubRun* subRun = geo.fSubRunPtr;
         SkASSERT((int)subRun->vertexStride() == vertexStride);
-
         subRun->prepareGrGlyphs(target->strikeCache());
 
-        // TODO4F: Preserve float colors
-
-        // Where the subRun begins and ends relative to totalGlyphsRegened.
-        int subRunBegin = totalGlyphsRegened;
-        int subRunEnd = subRunBegin + subRun->glyphCount();
-
-        // Draw all the glyphs in the subRun.
-        while (totalGlyphsRegened < subRunEnd) {
-            // drawBegin and drawEnd are indices for the subRun on the
-            // interval [0, subRun->fGlyphs.size()).
-            int drawBegin = totalGlyphsRegened - subRunBegin;
-            // drawEnd is either the end of the subRun or the end of the current quad buffer.
-            int drawEnd = std::min(subRunEnd, quadBufferEnd) - subRunBegin;
-            auto[ok, glyphsRegenerated] = subRun->regenerateAtlas(drawBegin, drawEnd, target);
-
+        const int subRunEnd = subRun->glyphCount();
+        for (int subRunCursor = 0; subRunCursor < subRunEnd;) {
+            // Regenerate the atlas for the remainder of the glyphs in the run, or the remainder
+            // of the glyphs to fill the vertex buffer.
+            int regenEnd = subRunCursor + std::min(subRunEnd - subRunCursor, quadEnd - quadCursor);
+            auto[ok, glyphsRegenerated] = subRun->regenerateAtlas(subRunCursor, regenEnd, target);
             // There was a problem allocating the glyph in the atlas. Bail.
             if (!ok) {
                 return;
             }
 
-            // Update all the vertices for glyphsRegenerate glyphs.
-            if (glyphsRegenerated > 0) {
-                int quadBufferIndex = totalGlyphsRegened - quadBufferBegin;
-                auto regeneratedQuadBuffer =
-                        SkTAddOffset<char>(vertices, subRun->quadOffset(quadBufferIndex));
-                int subRunIndex = totalGlyphsRegened - subRunBegin;
-                args.fillVertexData(regeneratedQuadBuffer, subRunIndex, glyphsRegenerated);
-            }
+            geo.fillVertexData(vertices + quadCursor * quadSize, subRunCursor, glyphsRegenerated);
 
-            totalGlyphsRegened += glyphsRegenerated;
+            subRunCursor += glyphsRegenerated;
+            quadCursor += glyphsRegenerated;
+            allGlyphsCursor += glyphsRegenerated;
             flushInfo.fGlyphsToFlush += glyphsRegenerated;
 
-            // regenerate() has stopped part way through a SubRun. This means that either the atlas
-            // or the quad buffer is full or both. There is a case were the flow through
-            // the loop is strange. If we run out of quad buffer space at the same time the
-            // SubRun ends, then this is not triggered which is the right result for the last
-            // SubRun. But, if this is not the last SubRun, then advance to the next SubRun which
-            // will process no glyphs, and return to this point where the quad buffer will be
-            // expanded.
-            if (totalGlyphsRegened != subRunEnd) {
-                // Flush if not all glyphs drawn because either the quad buffer is full or the
-                // atlas is out of space.
+            if (quadCursor == quadEnd || subRunCursor < subRunEnd) {
+                // Flush if not all the glyphs are drawn because either the quad buffer is full or
+                // the atlas is out of space.
                 this->createDrawForGeneratedGlyphs(target, &flushInfo);
-                if (totalGlyphsRegened == quadBufferEnd) {
-                    // Quad buffer is full. Get more buffer.
-                    quadBufferBegin = totalGlyphsRegened;
-                    int quadBufferSize =
-                            std::min(maxQuadsPerBuffer, this->numGlyphs() - totalGlyphsRegened);
-                    quadBufferEnd = quadBufferBegin + quadBufferSize;
-
-                    vertices = target->makeVertexSpace(
-                            vertexStride,
-                            kVerticesPerGlyph * quadBufferSize,
-                            &flushInfo.fVertexBuffer,
-                            &flushInfo.fVertexOffset);
-                    if (!vertices || !flushInfo.fVertexBuffer) {
-                        SkDebugf("Could not allocate vertices\n");
+                if (quadCursor == quadEnd && allGlyphsCursor < allGlyphsEnd) {
+                    // If the vertex buffer is full and there are still glyphs to draw then
+                    // get a new buffer.
+                    if(!resetVertexBuffer()) {
                         return;
                     }
                 }
             }
         }
-    }  // for all geometries
-    this->createDrawForGeneratedGlyphs(target, &flushInfo);
+    }
 }
 
 void GrAtlasTextOp::onExecute(GrOpFlushState* flushState, const SkRect& chainBounds) {