use a linked list for GrAtlasTextOp geometries

Instead of using a GrTBlockList<Geometry> to hold the geometries
in the op. Allocate them on the RecordTimeAllocator, and
link them together.

Change-Id: I32af5724e7abeca1ddb6d38b26afbff7919cbc76
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/341725
Reviewed-by: Robert Phillips <robertphillips@google.com>
Commit-Queue: Herb Derby <herb@google.com>
diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp
index 3f217e7..c3a89d0 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -37,7 +37,7 @@
                              bool needsTransform,
                              int glyphCount,
                              SkRect deviceRect,
-                             const Geometry& geo,
+                             Geometry* geo,
                              GrPaint&& paint)
         : INHERITED{ClassID()}
         , fProcessors(std::move(paint))
@@ -46,9 +46,10 @@
         , fMaskType(static_cast<uint32_t>(maskType))
         , fUsesLocalCoords(false)
         , fNeedsGlyphTransform(needsTransform)
-        , fHasPerspective(needsTransform && geo.fDrawMatrix.hasPerspective())
-        , fUseGammaCorrectDistanceTable(false) {
-    fGeometries.push_back(geo);
+        , fHasPerspective(needsTransform && geo->fDrawMatrix.hasPerspective())
+        , fUseGammaCorrectDistanceTable(false)
+        , fHead{geo}
+        , fTail{&fHead->fNext} {
     // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
     // we treat this as a set of non-AA rects rendered with a texture.
     this->setBounds(deviceRect, HasAABloat::kNo, IsHairline::kNo);
@@ -61,7 +62,7 @@
                              SkColor luminanceColor,
                              bool useGammaCorrectDistanceTable,
                              uint32_t DFGPFlags,
-                             const Geometry& geo,
+                             Geometry* geo,
                              GrPaint&& paint)
         : INHERITED{ClassID()}
         , fProcessors(std::move(paint))
@@ -70,15 +71,34 @@
         , fMaskType(static_cast<uint32_t>(maskType))
         , fUsesLocalCoords(false)
         , fNeedsGlyphTransform(needsTransform)
-        , fHasPerspective(needsTransform && geo.fDrawMatrix.hasPerspective())
+        , fHasPerspective(needsTransform && geo->fDrawMatrix.hasPerspective())
         , fUseGammaCorrectDistanceTable(useGammaCorrectDistanceTable)
-        , fLuminanceColor(luminanceColor) {
-    fGeometries.push_back(geo);
+        , fLuminanceColor(luminanceColor)
+        , fHead{geo}
+        , fTail{&fHead->fNext} {
     // We don't have tight bounds on the glyph paths in device space. For the purposes of bounds
     // we treat this as a set of non-AA rects rendered with a texture.
     this->setBounds(deviceRect, HasAABloat::kNo, IsHairline::kNo);
 }
 
+auto GrAtlasTextOp::Geometry::Make(GrRecordingContext* rc,
+                                   const GrAtlasSubRun& subRun,
+                                   const SkMatrix& drawMatrix,
+                                   SkPoint drawOrigin,
+                                   SkIRect clipRect,
+                                   GrTextBlob* blob,
+                                   const SkPMColor4f& color) -> Geometry* {
+    auto arena = rc->priv().recordTimeAllocator();
+    return arena->make<Geometry>(subRun,
+                                 drawMatrix,
+                                 drawOrigin,
+                                 SkIRect::MakeEmpty(),
+                                 SkRef(blob),
+                                 color);
+}
+
+
+
 void GrAtlasTextOp::Geometry::fillVertexData(void *dst, int offset, int count) const {
     SkMatrix positionMatrix = fDrawMatrix;
     positionMatrix.preTranslate(fDrawOrigin.x(), fDrawOrigin.y());
@@ -94,12 +114,12 @@
 SkString GrAtlasTextOp::onDumpInfo() const {
     SkString str;
     int i = 0;
-    for (const auto& g : fGeometries.items()) {
+    for(Geometry* geom = fHead; geom != nullptr; geom = geom->fNext) {
         str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f\n",
                     i++,
-                    g.fColor.toBytes_RGBA(),
-                    g.fDrawOrigin.x(),
-                    g.fDrawOrigin.y());
+                    geom->fColor.toBytes_RGBA(),
+                    geom->fDrawOrigin.x(),
+                    geom->fDrawOrigin.y());
     }
 
     str += fProcessors.dumpProcessors();
@@ -121,7 +141,7 @@
     } else {
         // finalize() is called before any merging is done, so at this point there's at most one
         // Geometry with a color. Later, for non-bitmap ops, we may have mixed colors.
-        color.setToConstant(fGeometries.front().fColor);
+        color.setToConstant(fHead->fColor);
     }
 
     switch (this->maskType()) {
@@ -142,7 +162,7 @@
 
     auto analysis = fProcessors.finalize(
             color, coverage, clip, &GrUserStencilSettings::kUnused, hasMixedSampledCoverage, caps,
-            clampType, &fGeometries.front().fColor);
+            clampType, &fHead->fColor);
     // TODO(michaelludwig): Once processor analysis can be done external to op creation/finalization
     // the atlas op metadata can be fully const. This is okay for now since finalize() happens
     // before the op is merged, so during combineIfPossible, metadata is effectively const.
@@ -158,7 +178,7 @@
     // the matrix is identity. When the shaders require local coords, combineIfPossible requires all
     // all geometries to have same draw matrix.
     SkMatrix localMatrix = SkMatrix::I();
-    if (fUsesLocalCoords && !fGeometries.front().fDrawMatrix.invert(&localMatrix)) {
+    if (fUsesLocalCoords && !fHead->fDrawMatrix.invert(&localMatrix)) {
         return;
     }
 
@@ -200,7 +220,7 @@
         // Bitmap text uses a single color, combineIfPossible ensures all geometries have the same
         // color, so we can use the first's without worry.
         flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
-                target->allocator(), *target->caps().shaderCaps(), fGeometries.front().fColor,
+                target->allocator(), *target->caps().shaderCaps(), fHead->fColor,
                 false, views, numActiveViews, filter, maskFormat, localMatrix, fHasPerspective);
     }
 
@@ -236,9 +256,9 @@
 
     resetVertexBuffer();
 
-    for (const Geometry& geo : fGeometries.items()) {
-        const GrAtlasSubRun& subRun = geo.fSubRun;
-        SkASSERT((int) subRun.vertexStride(geo.fDrawMatrix) == vertexStride);
+    for (const Geometry* geo = fHead; geo != nullptr; geo = geo->fNext) {
+        const GrAtlasSubRun& subRun = geo->fSubRun;
+        SkASSERT((int) subRun.vertexStride(geo->fDrawMatrix) == vertexStride);
 
         const int subRunEnd = subRun.glyphCount();
         for (int subRunCursor = 0; subRunCursor < subRunEnd;) {
@@ -251,7 +271,7 @@
                 return;
             }
 
-            geo.fillVertexData(vertices + quadCursor * quadSize, subRunCursor, glyphsRegenerated);
+            geo->fillVertexData(vertices + quadCursor * quadSize, subRunCursor, glyphsRegenerated);
 
             subRunCursor += glyphsRegenerated;
             quadCursor += glyphsRegenerated;
@@ -363,8 +383,8 @@
     if (fUsesLocalCoords) {
         // If the fragment processors use local coordinates, the GPs compute them using the inverse
         // of the view matrix stored in a uniform, so all geometries must have the same matrix.
-        const SkMatrix& thisFirstMatrix = fGeometries.front().fDrawMatrix;
-        const SkMatrix& thatFirstMatrix = that->fGeometries.front().fDrawMatrix;
+        const SkMatrix& thisFirstMatrix = fHead->fDrawMatrix;
+        const SkMatrix& thatFirstMatrix = that->fHead->fDrawMatrix;
         if (!SkMatrixPriv::CheapEqual(thisFirstMatrix, thatFirstMatrix)) {
             return CombineResult::kCannotCombine;
         }
@@ -377,7 +397,7 @@
         }
     } else {
         if (this->maskType() == MaskType::kColorBitmap &&
-            fGeometries.front().fColor != that->fGeometries.front().fColor) {
+            fHead->fColor != that->fHead->fColor) {
             // This ensures all merged bitmap color text ops have a constant color
             return CombineResult::kCannotCombine;
         }
@@ -386,7 +406,8 @@
     fNumGlyphs += that->fNumGlyphs;
 
     // After concat, that's geometry list is emptied so it will not unref the blobs when destructed
-    fGeometries.concat(std::move(that->fGeometries));
+    this->addGeometry(that->fHead);
+    that->fHead = nullptr;
     return CombineResult::kMerged;
 }