Use GrVertexWriter in GrSmallPathRenderer

Make TriStrip a templated rect, with a helper for SkRect.
Added writeQuadValue overload for GrQuad.

Bug: skia:
Change-Id: I2934e5dbb086c5dbe0cc4846176bab8ccc324cf6
Reviewed-on: https://skia-review.googlesource.com/c/171534
Reviewed-by: Mike Klein <mtklein@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/GrVertexWriter.h b/src/gpu/GrVertexWriter.h
index 6026348..2c6fbfd 100644
--- a/src/gpu/GrVertexWriter.h
+++ b/src/gpu/GrVertexWriter.h
@@ -8,6 +8,7 @@
 #ifndef GrVertexWriter_DEFINED
 #define GrVertexWriter_DEFINED
 
+#include "GrQuad.h"
 #include "SkTemplates.h"
 #include <type_traits>
 
@@ -26,7 +27,10 @@
     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, "");
+        // This assert is barely related to what we're trying to check - that our vertex data
+        // matches our attribute layouts, where each attribute is aligned to four bytes. If this
+        // becomes a problem, just remove it.
+        static_assert(alignof(T) <= 4, "");
         memcpy(fPtr, &val, sizeof(T));
         fPtr = SkTAddOffset<void>(fPtr, sizeof(T));
         this->write(remainder...);
@@ -35,7 +39,7 @@
     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, "");
+        static_assert(alignof(T) <= 4, "");
         memcpy(fPtr, val, N * sizeof(T));
         fPtr = SkTAddOffset<void>(fPtr, N * sizeof(T));
         this->write(remainder...);
@@ -54,7 +58,12 @@
      * - For any arguments of type TriStrip, a unique SkPoint will be written at each vertex,
      *   in this order: left-top, left-bottom, right-top, right-bottom.
      */
-    struct TriStrip { const SkRect& fRect; };
+    template <typename T>
+    struct TriStrip { T l, t, r, b; };
+
+    static TriStrip<float> TriStripFromRect(const SkRect& r) {
+        return { r.fLeft, r.fTop, r.fRight, r.fBottom };
+    }
 
     template <typename... Args>
     void writeQuad(const Args&... remainder) {
@@ -79,15 +88,20 @@
         this->write(val);
     }
 
-    template <int corner>
-    void writeQuadValue(const TriStrip& r) {
+    template <int corner, typename T>
+    void writeQuadValue(const TriStrip<T>& r) {
         switch (corner) {
-            case 0: this->write(r.fRect.fLeft , r.fRect.fTop);    break;
-            case 1: this->write(r.fRect.fLeft , r.fRect.fBottom); break;
-            case 2: this->write(r.fRect.fRight, r.fRect.fTop);    break;
-            case 3: this->write(r.fRect.fRight, r.fRect.fBottom); break;
+            case 0: this->write(r.l, r.t); break;
+            case 1: this->write(r.l, r.b); break;
+            case 2: this->write(r.r, r.t); break;
+            case 3: this->write(r.r, r.b); break;
         }
     }
+
+    template <int corner>
+    void writeQuadValue(const GrQuad& q) {
+        this->write(q.point(corner));
+    }
 };
 
 #endif
diff --git a/src/gpu/ops/GrLatticeOp.cpp b/src/gpu/ops/GrLatticeOp.cpp
index 4cc766b..7551668 100644
--- a/src/gpu/ops/GrLatticeOp.cpp
+++ b/src/gpu/ops/GrLatticeOp.cpp
@@ -255,8 +255,8 @@
                 domain.store(&texDomain);
                 coords.store(&texCoords);
 
-                vertices.writeQuad(GrVertexWriter::TriStrip{ dstR },
-                                   GrVertexWriter::TriStrip{ texCoords },
+                vertices.writeQuad(GrVertexWriter::TriStripFromRect(dstR),
+                                   GrVertexWriter::TriStripFromRect(texCoords),
                                    texDomain,
                                    patchColor);
             }
diff --git a/src/gpu/ops/GrRegionOp.cpp b/src/gpu/ops/GrRegionOp.cpp
index d824609..7f1ad81 100644
--- a/src/gpu/ops/GrRegionOp.cpp
+++ b/src/gpu/ops/GrRegionOp.cpp
@@ -121,7 +121,7 @@
             SkRegion::Iterator iter(fRegions[i].fRegion);
             while (!iter.done()) {
                 SkRect rect = SkRect::Make(iter.rect());
-                vertices.writeQuad(GrVertexWriter::TriStrip{ rect }, color);
+                vertices.writeQuad(GrVertexWriter::TriStripFromRect(rect), color);
                 iter.next();
             }
         }
diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp
index 215178c..2582262 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -15,6 +15,7 @@
 #include "GrRenderTargetContext.h"
 #include "GrResourceProvider.h"
 #include "GrSimpleMeshDrawOpHelper.h"
+#include "GrVertexWriter.h"
 #include "SkAutoMalloc.h"
 #include "SkAutoPixmapStorage.h"
 #include "SkDistanceFieldGen.h"
@@ -367,8 +368,7 @@
         }
 
         // allocate vertices
-        size_t kVertexStride = flushInfo.fGeometryProcessor->vertexStride();
-
+        const size_t kVertexStride = flushInfo.fGeometryProcessor->vertexStride();
         const GrBuffer* vertexBuffer;
 
         // We need to make sure we don't overflow a 32 bit int when we request space in the
@@ -376,20 +376,18 @@
         if (instanceCount > SK_MaxS32 / kVerticesPerQuad) {
             return;
         }
-        void* vertices = target->makeVertexSpace(kVertexStride,
-                                                 kVerticesPerQuad * instanceCount,
-                                                 &vertexBuffer,
-                                                 &flushInfo.fVertexOffset);
+        GrVertexWriter vertices{target->makeVertexSpace(kVertexStride,
+                                                        kVerticesPerQuad * instanceCount,
+                                                        &vertexBuffer,
+                                                        &flushInfo.fVertexOffset)};
         flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer));
         flushInfo.fIndexBuffer = target->resourceProvider()->refQuadIndexBuffer();
-        if (!vertices || !flushInfo.fIndexBuffer) {
+        if (!vertices.fPtr || !flushInfo.fIndexBuffer) {
             SkDebugf("Could not allocate vertices\n");
             return;
         }
 
         flushInfo.fInstancesToFlush = 0;
-        // Pointer to the next set of vertices to write.
-        intptr_t offset = reinterpret_cast<intptr_t>(vertices);
         for (int i = 0; i < instanceCount; i++) {
             const Entry& args = fShapes[i];
 
@@ -492,9 +490,8 @@
             fAtlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
 
             // TODO4F: Preserve float colors
-            this->writePathVertices(fAtlas, offset, args.fColor.toBytes_RGBA(), kVertexStride,
-                                    args.fViewMatrix, shapeData);
-            offset += kVerticesPerQuad * kVertexStride;
+            this->writePathVertices(fAtlas, vertices, args.fColor.toBytes_RGBA(), args.fViewMatrix,
+                                    shapeData);
             flushInfo.fInstancesToFlush++;
         }
 
@@ -747,69 +744,34 @@
     }
 
     void writePathVertices(GrDrawOpAtlas* atlas,
-                           intptr_t offset,
+                           GrVertexWriter& vertices,
                            GrColor color,
-                           size_t vertexStride,
                            const SkMatrix& ctm,
                            const ShapeData* shapeData) const {
-        SkPoint* positions = reinterpret_cast<SkPoint*>(offset);
-
-        SkRect bounds = shapeData->fBounds;
-        SkRect translatedBounds(bounds);
+        SkRect translatedBounds(shapeData->fBounds);
         if (!fUsesDistanceField) {
             translatedBounds.offset(SkScalarFloorToScalar(ctm.get(SkMatrix::kMTransX)),
                                     SkScalarFloorToScalar(ctm.get(SkMatrix::kMTransY)));
         }
 
-        // vertex positions
-        // TODO make the vertex attributes a struct
+        // set up texture coordinates
+        GrVertexWriter::TriStrip<uint16_t> texCoords{
+            (uint16_t)shapeData->fTextureCoords.fLeft,
+            (uint16_t)shapeData->fTextureCoords.fTop,
+            (uint16_t)shapeData->fTextureCoords.fRight,
+            (uint16_t)shapeData->fTextureCoords.fBottom
+        };
+
         if (fUsesDistanceField && !ctm.hasPerspective()) {
             GrQuad quad(translatedBounds, ctm);
-            intptr_t positionOffset = offset;
-            SkPoint* position = (SkPoint*)positionOffset;
-            *position = quad.point(0);
-            positionOffset += vertexStride;
-            position = (SkPoint*)positionOffset;
-            *position = quad.point(1);
-            positionOffset += vertexStride;
-            position = (SkPoint*)positionOffset;
-            *position = quad.point(2);
-            positionOffset += vertexStride;
-            position = (SkPoint*)positionOffset;
-            *position = quad.point(3);
+            vertices.writeQuad(quad,
+                               color,
+                               texCoords);
         } else {
-            SkPointPriv::SetRectTriStrip(positions, translatedBounds, vertexStride);
+            vertices.writeQuad(GrVertexWriter::TriStripFromRect(translatedBounds),
+                               color,
+                               texCoords);
         }
-
-        // colors
-        for (int i = 0; i < kVerticesPerQuad; i++) {
-            GrColor* colorPtr = (GrColor*)(offset + sizeof(SkPoint) + i * vertexStride);
-            *colorPtr = color;
-        }
-
-        // set up texture coordinates
-        uint16_t l = shapeData->fTextureCoords.fLeft;
-        uint16_t t = shapeData->fTextureCoords.fTop;
-        uint16_t r = shapeData->fTextureCoords.fRight;
-        uint16_t b = shapeData->fTextureCoords.fBottom;
-
-        // set vertex texture coords
-        intptr_t textureCoordOffset = offset + sizeof(SkPoint) + sizeof(GrColor);
-        uint16_t* textureCoords = (uint16_t*) textureCoordOffset;
-        textureCoords[0] = l;
-        textureCoords[1] = t;
-        textureCoordOffset += vertexStride;
-        textureCoords = (uint16_t*)textureCoordOffset;
-        textureCoords[0] = l;
-        textureCoords[1] = b;
-        textureCoordOffset += vertexStride;
-        textureCoords = (uint16_t*)textureCoordOffset;
-        textureCoords[0] = r;
-        textureCoords[1] = t;
-        textureCoordOffset += vertexStride;
-        textureCoords = (uint16_t*)textureCoordOffset;
-        textureCoords[0] = r;
-        textureCoords[1] = b;
     }
 
     void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const {