Add a writer class for indirect draw commands

This enforces write-only access to the mapped buffers, will enable
chaining of indirect strokes, and gives us the ability to reorder the
fields for Metal.

Bug: chromium:1172543
Bug: skia:11291
Bug: skia:10419
Change-Id: I4449ff85dd0019f6d6d6781ede52bcf26dee8b02
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/367416
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Chris Dalton <csmartdalton@google.com>
diff --git a/src/gpu/mock/GrMockOpTarget.h b/src/gpu/mock/GrMockOpTarget.h
index a8cc8c5..9564cf3 100644
--- a/src/gpu/mock/GrMockOpTarget.h
+++ b/src/gpu/mock/GrMockOpTarget.h
@@ -56,32 +56,35 @@
         return fStaticVertexData;
     }
 
-    GrDrawIndirectCommand* makeDrawIndirectSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
-                                                 size_t* offsetInBytes) override {
-        int staticBufferCount = (int)SK_ARRAY_COUNT(fStaticDrawIndirectData);
-        if (drawCount > staticBufferCount) {
-            SK_ABORT("FATAL: wanted %i static drawIndirect elements; only have %i.\n",
-                     drawCount, staticBufferCount);
+    GrDrawIndirectWriter makeDrawIndirectSpace(int drawCount, sk_sp<const GrBuffer>* buffer,
+                                               size_t* offsetInBytes) override {
+        if (sizeof(GrDrawIndirectCommand) * drawCount > sizeof(fStaticIndirectData)) {
+            SK_ABORT("FATAL: wanted %zu bytes of static indirect data; only have %zu.\n",
+                     sizeof(GrDrawIndirectCommand) * drawCount, sizeof(fStaticIndirectData));
         }
         *offsetInBytes = 0;
-        return fStaticDrawIndirectData;
+        return fStaticIndirectData;
     }
 
     void putBackIndirectDraws(int count) override { /* no-op */ }
 
-    GrDrawIndexedIndirectCommand* makeDrawIndexedIndirectSpace(
-            int drawCount, sk_sp<const GrBuffer>* buffer, size_t* offsetInBytes) override {
-        int staticBufferCount = (int)SK_ARRAY_COUNT(fStaticDrawIndexedIndirectData);
-        if (drawCount > staticBufferCount) {
-            SK_ABORT("FATAL: wanted %i static drawIndexedIndirect elements; only have %i.\n",
-                     drawCount, staticBufferCount);
+    GrDrawIndexedIndirectWriter makeDrawIndexedIndirectSpace(int drawCount,
+                                                             sk_sp<const GrBuffer>* buffer,
+                                                             size_t* offsetInBytes) override {
+        if (sizeof(GrDrawIndexedIndirectCommand) * drawCount > sizeof(fStaticIndirectData)) {
+            SK_ABORT("FATAL: wanted %zu bytes of static indirect data; only have %zu.\n",
+                     sizeof(GrDrawIndexedIndirectCommand) * drawCount, sizeof(fStaticIndirectData));
         }
         *offsetInBytes = 0;
-        return fStaticDrawIndexedIndirectData;
+        return fStaticIndirectData;
     }
 
     void putBackIndexedIndirectDraws(int count) override { /* no-op */ }
 
+    // Call these methods to see what got written after the previous call to make*Space.
+    const void* peekStaticVertexData() const { return fStaticVertexData; }
+    const void* peekStaticIndirectData() const { return fStaticIndirectData; }
+
 #define UNIMPL(...) __VA_ARGS__ override { SK_ABORT("unimplemented."); }
     UNIMPL(void recordDraw(const GrGeometryProcessor*, const GrSimpleMesh[], int,
                            const GrSurfaceProxy* const[], GrPrimitiveType))
@@ -100,8 +103,7 @@
 private:
     sk_sp<GrDirectContext> fMockContext;
     char fStaticVertexData[6 * 1024 * 1024];
-    GrDrawIndirectCommand fStaticDrawIndirectData[32];
-    GrDrawIndexedIndirectCommand fStaticDrawIndexedIndirectData[32];
+    char fStaticIndirectData[sizeof(GrDrawIndexedIndirectCommand) * 32];
     SkSTArenaAllocWithReset<1024 * 1024> fAllocator;
     GrXferProcessor::DstProxyView fDstProxyView;
 };