Move new WriteVertexData utility to a GrVertexWriter helper struct

Encapsulates the pointer storage and advancement, shortens usage.

Bug: skia:
Change-Id: Id06cd273ed638395d1fd53b3b66f87d4d33a4f3b
Reviewed-on: https://skia-review.googlesource.com/c/170727
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Mike Klein <mtklein@google.com>
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index b5209a3..19b859e 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -9,7 +9,7 @@
 
 #include "GrDefaultGeoProcFactory.h"
 #include "GrPathUtils.h"
-#include "ops/GrMeshDrawOp.h"
+#include "GrVertexWriter.h"
 
 #include "SkArenaAlloc.h"
 #include "SkGeometry.h"
@@ -200,15 +200,17 @@
 };
 
 inline void* emit_vertex(Vertex* v, const AAParams* aaParams, void* data) {
-    if (!aaParams) {
-        return GrMeshDrawOp::WriteVertexData(data, v->fPoint);
+    GrVertexWriter verts{data};
+    verts.write(v->fPoint);
+
+    if (aaParams) {
+        if (aaParams->fTweakAlpha) {
+            verts.write(SkAlphaMulQ(aaParams->fColor, SkAlpha255To256(v->fAlpha)));
+        } else {
+            verts.write(aaParams->fColor, GrNormalizeByteToFloat(v->fAlpha));
+        }
     }
-    if (aaParams->fTweakAlpha) {
-        GrColor color = SkAlphaMulQ(aaParams->fColor, SkAlpha255To256(v->fAlpha));
-        return GrMeshDrawOp::WriteVertexData(data, v->fPoint, color);
-    }
-    float coverage = GrNormalizeByteToFloat(v->fAlpha);
-    return GrMeshDrawOp::WriteVertexData(data, v->fPoint, aaParams->fColor, coverage);
+    return verts.fPtr;
 }
 
 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, const AAParams* aaParams, void* data) {
diff --git a/src/gpu/GrVertexWriter.h b/src/gpu/GrVertexWriter.h
new file mode 100644
index 0000000..8bfcef7
--- /dev/null
+++ b/src/gpu/GrVertexWriter.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef GrVertexWriter_DEFINED
+#define GrVertexWriter_DEFINED
+
+#include "SkTemplates.h"
+#include <type_traits>
+
+/**
+ * Helper for writing vertex data to a buffer. Usage:
+ *  GrVertexWriter vertices{target->makeVertexSpace(...)};
+ *  vertices.write(A0, B0, C0, ...);
+ *  vertices.write(A1, B1, C1, ...);
+ *
+ * Supports any number of arguments. Each argument must be POD (plain old data), or an array
+ * thereof.
+ */
+struct GrVertexWriter {
+    template <typename T, typename... Args>
+    void write(const T& val, const Args&... remainder) {
+        static_assert(std::is_pod<T>::value, "");
+        static_assert(alignof(T) == 4, "");
+        memcpy(fPtr, &val, sizeof(T));
+        fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
+        this->write(remainder...);
+    }
+
+    template <typename T, size_t N, typename... Args>
+    void write(const T(&val)[N], const Args&... remainder) {
+        static_assert(std::is_pod<T>::value, "");
+        static_assert(alignof(T) == 4, "");
+        memcpy(fPtr, val, N * sizeof(T));
+        fPtr = SkTAddOffset<void>(fPtr, N * sizeof(T));
+        this->write(remainder...);
+    }
+
+    void write() {}
+
+    void* fPtr;
+};
+
+#endif
diff --git a/src/gpu/ops/GrAAConvexPathRenderer.cpp b/src/gpu/ops/GrAAConvexPathRenderer.cpp
index 1f2b703..624c261 100644
--- a/src/gpu/ops/GrAAConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAAConvexPathRenderer.cpp
@@ -18,6 +18,7 @@
 #include "GrRenderTargetContext.h"
 #include "GrShape.h"
 #include "GrSimpleMeshDrawOpHelper.h"
+#include "GrVertexWriter.h"
 #include "SkGeometry.h"
 #include "SkPathPriv.h"
 #include "SkPointPriv.h"
@@ -690,19 +691,20 @@
 
 // extract the result vertices and indices from the GrAAConvexTessellator
 static void extract_lines_only_verts(const GrAAConvexTessellator& tess,
-                                     void* vertices,
+                                     void* vertData,
                                      GrColor color,
                                      uint16_t* idxs,
                                      bool tweakAlphaForCoverage) {
+    GrVertexWriter verts{vertData};
     for (int i = 0; i < tess.numPts(); ++i) {
-        vertices = GrMeshDrawOp::WriteVertexData(vertices, tess.point(i));
+        verts.write(tess.point(i));
         if (tweakAlphaForCoverage) {
             SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
             unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i));
             GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
-            vertices = GrMeshDrawOp::WriteVertexData(vertices, scaledColor);
+            verts.write(scaledColor);
         } else {
-            vertices = GrMeshDrawOp::WriteVertexData(vertices, color, tess.coverage(i));
+            verts.write(color, tess.coverage(i));
         }
     }
 
diff --git a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
index 996fa33..52785eb 100644
--- a/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
+++ b/src/gpu/ops/GrAALinearizingConvexPathRenderer.cpp
@@ -17,6 +17,7 @@
 #include "GrRenderTargetContext.h"
 #include "GrShape.h"
 #include "GrStyle.h"
+#include "GrVertexWriter.h"
 #include "SkGeometry.h"
 #include "SkPathPriv.h"
 #include "SkString.h"
@@ -80,21 +81,22 @@
 
 // extract the result vertices and indices from the GrAAConvexTessellator
 static void extract_verts(const GrAAConvexTessellator& tess,
-                          void* vertices,
+                          void* vertData,
                           size_t vertexStride,
                           GrColor color,
                           uint16_t firstIndex,
                           uint16_t* idxs,
                           bool tweakAlphaForCoverage) {
+    GrVertexWriter verts{vertData};
     for (int i = 0; i < tess.numPts(); ++i) {
-        vertices = GrMeshDrawOp::WriteVertexData(vertices, tess.point(i));
+        verts.write(tess.point(i));
         if (tweakAlphaForCoverage) {
             SkASSERT(SkScalarRoundToInt(255.0f * tess.coverage(i)) <= 255);
             unsigned scale = SkScalarRoundToInt(255.0f * tess.coverage(i));
             GrColor scaledColor = (0xff == scale) ? color : SkAlphaMulQ(color, scale);
-            vertices = GrMeshDrawOp::WriteVertexData(vertices, scaledColor);
+            verts.write(scaledColor);
         } else {
-            vertices = GrMeshDrawOp::WriteVertexData(vertices, color, tess.coverage(i));
+            verts.write(color, tess.coverage(i));
         }
     }
 
diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h
index c300f33..fc25cb1 100644
--- a/src/gpu/ops/GrMeshDrawOp.h
+++ b/src/gpu/ops/GrMeshDrawOp.h
@@ -27,35 +27,6 @@
     /** Abstract interface that represents a destination for a GrMeshDrawOp. */
     class Target;
 
-    /**
-     * Helpers for writing vertex data to a buffer. Usage:
-     *  void* vertices = ...;
-     *  vertices = WriteVertexData(vertices, A0, B0, C0, ...);
-     *  vertices = WriteVertexData(vertices, A1, B1, C1, ...);
-     *
-     * Supports any number of arguments. Each argument must be trivially copyable (or an array
-     * thereof).
-     */
-    template <typename T, typename... Args>
-    static inline void* SK_WARN_UNUSED_RESULT WriteVertexData(void* verts, const T& val,
-                                                              const Args&... remainder) {
-        static_assert(std::is_pod<T>::value, "");
-        static_assert(alignof(T) == 4, "");
-        memcpy(verts, &val, sizeof(T));
-        return WriteVertexData((char*)verts + sizeof(T), remainder...);
-    }
-
-    template <typename T, size_t N, typename... Args>
-    static inline void* SK_WARN_UNUSED_RESULT WriteVertexData(void* verts, const T (&val)[N],
-                                                              const Args&... remainder) {
-        static_assert(std::is_pod<T>::value, "");
-        static_assert(alignof(T) == 4, "");
-        memcpy(verts, val, N * sizeof(T));
-        return WriteVertexData((char*)verts + (N * sizeof(T)), remainder...);
-    }
-
-    static inline void* SK_WARN_UNUSED_RESULT WriteVertexData(void* verts) { return verts; }
-
 protected:
     GrMeshDrawOp(uint32_t classID);
 
diff --git a/src/gpu/ops/GrOvalOpFactory.cpp b/src/gpu/ops/GrOvalOpFactory.cpp
index 546b95d..20f55a2 100644
--- a/src/gpu/ops/GrOvalOpFactory.cpp
+++ b/src/gpu/ops/GrOvalOpFactory.cpp
@@ -13,6 +13,7 @@
 #include "GrResourceProvider.h"
 #include "GrShaderCaps.h"
 #include "GrStyle.h"
+#include "GrVertexWriter.h"
 #include "SkRRectPriv.h"
 #include "SkStrokeRec.h"
 #include "glsl/GrGLSLFragmentShaderBuilder.h"
@@ -1163,9 +1164,9 @@
 
         const GrBuffer* vertexBuffer;
         int firstVertex;
-        void* vertices = target->makeVertexSpace(gp->vertexStride(), fVertCount, &vertexBuffer,
-                                                 &firstVertex);
-        if (!vertices) {
+        GrVertexWriter vertices{target->makeVertexSpace(gp->vertexStride(), fVertCount,
+                                                        &vertexBuffer, &firstVertex)};
+        if (!vertices.fPtr) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -1188,6 +1189,7 @@
 
             // The inner radius in the vertex data must be specified in normalized space.
             innerRadius = innerRadius / outerRadius;
+            SkPoint radii = { outerRadius, innerRadius };
 
             SkPoint center = SkPoint::Make(bounds.centerX(), bounds.centerY());
             SkScalar halfWidth = 0.5f * bounds.width();
@@ -1212,19 +1214,21 @@
                 // compute the vertex position from this.
                 SkScalar dist = SkTMin(kOctagonOuter[i].dot(geoClipPlane) + offsetClipDist, 0.0f);
                 SkVector offset = kOctagonOuter[i] - geoClipPlane * dist;
-                vertices = WriteVertexData(vertices, center + offset * halfWidth, color, offset,
-                                           outerRadius, innerRadius);
+                vertices.write(center + offset * halfWidth,
+                               color,
+                               offset,
+                               radii);
                 if (fClipPlane) {
-                    vertices = WriteVertexData(vertices, circle.fClipPlane);
+                    vertices.write(circle.fClipPlane);
                 }
                 if (fClipPlaneIsect) {
-                    vertices = WriteVertexData(vertices, circle.fIsectPlane);
+                    vertices.write(circle.fIsectPlane);
                 }
                 if (fClipPlaneUnion) {
-                    vertices = WriteVertexData(vertices, circle.fUnionPlane);
+                    vertices.write(circle.fUnionPlane);
                 }
                 if (fRoundCaps) {
-                    vertices = WriteVertexData(vertices, circle.fRoundCapCenters);
+                    vertices.write(circle.fRoundCapCenters);
                 }
             }
 
@@ -1232,36 +1236,34 @@
                 // compute the inner ring
 
                 for (int i = 0; i < 8; ++i) {
-                    vertices = WriteVertexData(vertices,
-                                               center + kOctagonInner[i] * circle.fInnerRadius,
-                                               color,
-                                               kOctagonInner[i] * innerRadius,
-                                               outerRadius, innerRadius);
+                    vertices.write(center + kOctagonInner[i] * circle.fInnerRadius,
+                                   color,
+                                   kOctagonInner[i] * innerRadius,
+                                   radii);
                     if (fClipPlane) {
-                        vertices = WriteVertexData(vertices, circle.fClipPlane);
+                        vertices.write(circle.fClipPlane);
                     }
                     if (fClipPlaneIsect) {
-                        vertices = WriteVertexData(vertices, circle.fIsectPlane);
+                        vertices.write(circle.fIsectPlane);
                     }
                     if (fClipPlaneUnion) {
-                        vertices = WriteVertexData(vertices, circle.fUnionPlane);
+                        vertices.write(circle.fUnionPlane);
                     }
                     if (fRoundCaps) {
-                        vertices = WriteVertexData(vertices, circle.fRoundCapCenters);
+                        vertices.write(circle.fRoundCapCenters);
                     }
                 }
             } else {
                 // filled
-                vertices = WriteVertexData(vertices, center, color, SkPoint::Make(0, 0),
-                                           outerRadius, innerRadius);
+                vertices.write(center, color, SkPoint::Make(0, 0), radii);
                 if (fClipPlane) {
-                    vertices = WriteVertexData(vertices, circle.fClipPlane);
+                    vertices.write(circle.fClipPlane);
                 }
                 if (fClipPlaneIsect) {
-                    vertices = WriteVertexData(vertices, circle.fIsectPlane);
+                    vertices.write(circle.fIsectPlane);
                 }
                 if (fClipPlaneUnion) {
-                    vertices = WriteVertexData(vertices, circle.fUnionPlane);
+                    vertices.write(circle.fUnionPlane);
                 }
                 SkASSERT(!fRoundCaps);
             }
@@ -1482,9 +1484,9 @@
 
         const GrBuffer* vertexBuffer;
         int firstVertex;
-        void* vertices = target->makeVertexSpace(gp->vertexStride(), fVertCount, &vertexBuffer,
-                                                 &firstVertex);
-        if (!vertices) {
+        GrVertexWriter vertices{target->makeVertexSpace(gp->vertexStride(), fVertCount,
+                                                        &vertexBuffer, &firstVertex)};
+        if (!vertices.fPtr) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
@@ -1529,24 +1531,22 @@
             };
 
             for (int i = 0; i < 8; ++i) {
-                vertices = WriteVertexData(vertices,
-                                           center + kOctagonOuter[i] * halfWidth,
-                                           color,
-                                           reflectY(kOctagonOuter[i]),
-                                           circle.fOuterRadius,
-                                           normInnerRadius,
-                                           dashParams);
+                vertices.write(center + kOctagonOuter[i] * halfWidth,
+                               color,
+                               reflectY(kOctagonOuter[i]),
+                               circle.fOuterRadius,
+                               normInnerRadius,
+                               dashParams);
             }
 
             // Compute the vertices of the inner octagon.
             for (int i = 0; i < 8; ++i) {
-                vertices = WriteVertexData(vertices,
-                                           center + kOctagonInner[i] * circle.fInnerRadius,
-                                           color,
-                                           reflectY(kOctagonInner[i]) * normInnerRadius,
-                                           circle.fOuterRadius,
-                                           normInnerRadius,
-                                           dashParams);
+                vertices.write(center + kOctagonInner[i] * circle.fInnerRadius,
+                               color,
+                               reflectY(kOctagonInner[i]) * normInnerRadius,
+                               circle.fOuterRadius,
+                               normInnerRadius,
+                               dashParams);
             }
 
             const uint16_t* primIndices = circle_type_to_indices(true);
@@ -1758,8 +1758,8 @@
         // Setup geometry processor
         sk_sp<GrGeometryProcessor> gp(new EllipseGeometryProcessor(fStroked, localMatrix));
         QuadHelper helper(target, gp->vertexStride(), fEllipses.count());
-        void* verts = helper.vertices();
-        if (!verts) {
+        GrVertexWriter verts{helper.vertices()};
+        if (!verts.fPtr) {
             return;
         }
 
@@ -1788,29 +1788,25 @@
             }
 
             // The inner radius in the vertex data must be specified in normalized space.
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fLeft, bounds.fTop),
-                                    color,
-                                    SkPoint::Make(-xMaxOffset, -yMaxOffset),
-                                    invRadii);
+            verts.write(SkPoint::Make(bounds.fLeft, bounds.fTop),
+                        color,
+                        SkPoint::Make(-xMaxOffset, -yMaxOffset),
+                        invRadii);
 
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fLeft, bounds.fBottom),
-                                    color,
-                                    SkPoint::Make(-xMaxOffset, yMaxOffset),
-                                    invRadii);
+            verts.write(SkPoint::Make(bounds.fLeft, bounds.fBottom),
+                        color,
+                        SkPoint::Make(-xMaxOffset, yMaxOffset),
+                        invRadii);
 
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fRight, bounds.fTop),
-                                    color,
-                                    SkPoint::Make(xMaxOffset, -yMaxOffset),
-                                    invRadii);
+            verts.write(SkPoint::Make(bounds.fRight, bounds.fTop),
+                        color,
+                        SkPoint::Make(xMaxOffset, -yMaxOffset),
+                        invRadii);
 
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fRight, bounds.fBottom),
-                                    color,
-                                    SkPoint::Make(xMaxOffset, yMaxOffset),
-                                    invRadii);
+            verts.write(SkPoint::Make(bounds.fRight, bounds.fBottom),
+                        color,
+                        SkPoint::Make(xMaxOffset, yMaxOffset),
+                        invRadii);
         }
         auto pipe = fHelper.makePipeline(target);
         helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);
@@ -1993,8 +1989,8 @@
                 new DIEllipseGeometryProcessor(this->viewMatrix(), this->style()));
 
         QuadHelper helper(target, gp->vertexStride(), fEllipses.count());
-        void* verts = helper.vertices();
-        if (!verts) {
+        GrVertexWriter verts{helper.vertices()};
+        if (!verts.fPtr) {
             return;
         }
 
@@ -2020,33 +2016,29 @@
                 innerRatioY = yRadius / ellipse.fInnerYRadius;
             }
 
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fLeft, bounds.fTop),
-                                    color,
-                                    SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy),
-                                    SkPoint::Make(-innerRatioX - offsetDx,
-                                                  -innerRatioY - offsetDy));
+            verts.write(SkPoint::Make(bounds.fLeft, bounds.fTop),
+                        color,
+                        SkPoint::Make(-1.0f - offsetDx, -1.0f - offsetDy),
+                        SkPoint::Make(-innerRatioX - offsetDx,
+                                      -innerRatioY - offsetDy));
 
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fLeft, bounds.fBottom),
-                                    color,
-                                    SkPoint::Make(-1.0f - offsetDx, 1.0f + offsetDy),
-                                    SkPoint::Make(-innerRatioX - offsetDx,
-                                                   innerRatioY + offsetDy));
+            verts.write(SkPoint::Make(bounds.fLeft, bounds.fBottom),
+                        color,
+                        SkPoint::Make(-1.0f - offsetDx, 1.0f + offsetDy),
+                        SkPoint::Make(-innerRatioX - offsetDx,
+                                       innerRatioY + offsetDy));
 
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fRight, bounds.fTop),
-                                    color,
-                                    SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy),
-                                    SkPoint::Make( innerRatioX + offsetDx,
-                                                  -innerRatioY - offsetDy));
+            verts.write(SkPoint::Make(bounds.fRight, bounds.fTop),
+                        color,
+                        SkPoint::Make(1.0f + offsetDx, -1.0f - offsetDy),
+                        SkPoint::Make( innerRatioX + offsetDx,
+                                      -innerRatioY - offsetDy));
 
-            verts = WriteVertexData(verts,
-                                    SkPoint::Make(bounds.fRight, bounds.fBottom),
-                                    color,
-                                    SkPoint::Make(1.0f + offsetDx, 1.0f + offsetDy),
-                                    SkPoint::Make(innerRatioX + offsetDx,
-                                                  innerRatioY + offsetDy));
+            verts.write(SkPoint::Make(bounds.fRight, bounds.fBottom),
+                        color,
+                        SkPoint::Make(1.0f + offsetDx, 1.0f + offsetDy),
+                        SkPoint::Make(innerRatioX + offsetDx,
+                                      innerRatioY + offsetDy));
         }
         auto pipe = fHelper.makePipeline(target);
         helper.recordDraw(target, std::move(gp), pipe.fPipeline, pipe.fFixedDynamicState);