implemented GrMtlGpuCommandBuffer for draws in Metal gpu backend

Bug: skia:
Change-Id: Ifc20a7734a02fe48ef79af201b4ebc882aedefb3
Reviewed-on: https://skia-review.googlesource.com/146382
Commit-Queue: Timothy Liang <timliang@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/mtl/GrMtlGpuCommandBuffer.h b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
index e5b259c..d3f964f 100644
--- a/src/gpu/mtl/GrMtlGpuCommandBuffer.h
+++ b/src/gpu/mtl/GrMtlGpuCommandBuffer.h
@@ -10,9 +10,12 @@
 
 #include "GrGpuCommandBuffer.h"
 #include "GrMtlGpu.h"
+#include "GrMesh.h"
 
 #import <metal/metal.h>
 
+typedef uint32_t GrColor;
+class GrMtlPipelineState;
 class GrMtlRenderTarget;
 
 class GrMtlGpuTextureCommandBuffer : public GrGpuTextureCommandBuffer {
@@ -37,19 +40,13 @@
     typedef GrGpuTextureCommandBuffer INHERITED;
 };
 
-class GrMtlGpuRTCommandBuffer : public GrGpuRTCommandBuffer {
+class GrMtlGpuRTCommandBuffer : public GrGpuRTCommandBuffer, private GrMesh::SendToGpuImpl {
 public:
     GrMtlGpuRTCommandBuffer(GrMtlGpu* gpu, GrRenderTarget* rt, GrSurfaceOrigin origin,
                             const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
-                            const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo)
-            : INHERITED(rt, origin)
-            , fGpu(gpu)
-            , fColorLoadAndStoreInfo(colorInfo)
-            , fStencilLoadAndStoreInfo(stencilInfo) {
-        // Silence unused var warning
-        (void)fColorLoadAndStoreInfo;
-        (void)fStencilLoadAndStoreInfo;
-    }
+                            const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo);
+
+    ~GrMtlGpuRTCommandBuffer() override;
 
     void begin() override {}
     void end() override {}
@@ -61,29 +58,79 @@
     void inlineUpload(GrOpFlushState* state, GrDeferredTextureUploadFn& upload) override {}
 
     void copy(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
-              const SkIPoint& dstPoint) override {
-        fGpu->copySurface(fRenderTarget, fOrigin, src, srcOrigin, srcRect, dstPoint);
-    }
+              const SkIPoint& dstPoint) override;
+
+    void submit();
 
 private:
+    void internalBegin();
+    void internalEnd();
+
     GrGpu* gpu() override { return fGpu; }
 
+    GrMtlPipelineState* prepareDrawState(
+            const GrPrimitiveProcessor& primProc,
+            const GrPipeline& pipeline,
+            const GrPipeline::FixedDynamicState* fixedDynamicState,
+            const GrMesh meshes[],
+            int meshCount);
+
     void onDraw(const GrPrimitiveProcessor& primProc,
                 const GrPipeline& pipeline,
                 const GrPipeline::FixedDynamicState* fixedDynamicState,
                 const GrPipeline::DynamicStateArrays* dynamicStateArrays,
                 const GrMesh mesh[],
                 int meshCount,
-                const SkRect& bounds) override {}
+                const SkRect& bounds) override;
 
     void onClear(const GrFixedClip& clip, GrColor color) override {}
 
     void onClearStencilClip(const GrFixedClip& clip, bool insideStencilMask) override {}
 
+    MTLRenderPassDescriptor* createRenderPassDesc() const;
+
+    void bindGeometry(const GrBuffer* vertexBuffer, const GrBuffer* instanceBuffer);
+
+    // GrMesh::SendToGpuImpl methods. These issue the actual Metal draw commands.
+    // Marked final as a hint to the compiler to not use virtual dispatch.
+    void sendMeshToGpu(GrPrimitiveType primType, const GrBuffer* vertexBuffer, int vertexCount,
+                       int baseVertex) final {
+        this->sendInstancedMeshToGpu(primType, vertexBuffer, vertexCount, baseVertex, nullptr, 1,
+                                     0);
+    }
+
+    void sendIndexedMeshToGpu(GrPrimitiveType primType, const GrBuffer* indexBuffer, int indexCount,
+                              int baseIndex, uint16_t /*minIndexValue*/, uint16_t /*maxIndexValue*/,
+                              const GrBuffer* vertexBuffer, int baseVertex,
+                              GrPrimitiveRestart restart) final {
+        SkASSERT(restart == GrPrimitiveRestart::kNo);
+        this->sendIndexedInstancedMeshToGpu(primType, indexBuffer, indexCount, baseIndex,
+                                            vertexBuffer, baseVertex, nullptr, 1, 0,
+                                            GrPrimitiveRestart::kNo);
+    }
+
+    void sendInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* vertexBuffer, int vertexCount,
+                                int baseVertex, const GrBuffer* instanceBuffer, int instanceCount,
+                                int baseInstance) final;
+
+    void sendIndexedInstancedMeshToGpu(GrPrimitiveType, const GrBuffer* indexBuffer, int indexCount,
+                                       int baseIndex, const GrBuffer* vertexBuffer, int baseVertex,
+                                       const GrBuffer* instanceBuffer, int instanceCount,
+                                       int baseInstance, GrPrimitiveRestart) final;
+
     GrMtlGpu*                                     fGpu;
     GrGpuRTCommandBuffer::LoadAndStoreInfo        fColorLoadAndStoreInfo;
     GrGpuRTCommandBuffer::StencilLoadAndStoreInfo fStencilLoadAndStoreInfo;
 
+    id<MTLRenderCommandEncoder> fActiveRenderCmdEncoder;
+    MTLRenderPassDescriptor* fRenderPassDesc;
+
+    struct CommandBufferInfo {
+        SkRect fBounds;
+    };
+
+    CommandBufferInfo fCommandBufferInfo;
+
     typedef GrGpuRTCommandBuffer INHERITED;
 };