Implement GrDawnGpuTextureCommandBuffer.

Implement copy() of both this and GrDawnGpuRTCommandBuffer as
texture-buffer-texture copies (for now).
Cache GrDawnTextureCommandBuffer in GrDawnGpu, as is done for
the RT flavour.

Change-Id: I22b7af013486ec76f5c50ec69532e96901620bc5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/233998
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Stephen White <senorblanco@chromium.org>
diff --git a/src/gpu/dawn/GrDawnGpu.cpp b/src/gpu/dawn/GrDawnGpu.cpp
index 2d9178d..d90958d 100644
--- a/src/gpu/dawn/GrDawnGpu.cpp
+++ b/src/gpu/dawn/GrDawnGpu.cpp
@@ -64,15 +64,14 @@
             GrRenderTarget* rt, GrSurfaceOrigin origin, const SkRect& bounds,
             const GrGpuRTCommandBuffer::LoadAndStoreInfo& colorInfo,
             const GrGpuRTCommandBuffer::StencilLoadAndStoreInfo& stencilInfo) {
-    fCachedRTCommandBuffer.reset(
-        new GrDawnGpuRTCommandBuffer(this, rt, origin, colorInfo, stencilInfo));
-    return fCachedRTCommandBuffer.get();
+    fRTCommandBuffer.reset(new GrDawnGpuRTCommandBuffer(this, rt, origin, colorInfo, stencilInfo));
+    return fRTCommandBuffer.get();
 }
 
 GrGpuTextureCommandBuffer* GrDawnGpu::getCommandBuffer(GrTexture* texture,
                                                        GrSurfaceOrigin origin) {
-    SkASSERT(!"unimplemented");
-    return nullptr;
+    fTextureCommandBuffer.reset(new GrDawnGpuTextureCommandBuffer(this, texture, origin));
+    return fTextureCommandBuffer.get();
 }
 
 ///////////////////////////////////////////////////////////////////////////////
@@ -337,8 +336,12 @@
 }
 
 void GrDawnGpu::submit(GrGpuCommandBuffer* buffer) {
-    if (auto buf = static_cast<GrDawnGpuRTCommandBuffer*>(buffer->asRTCommandBuffer())) {
-        buf->submit();
+    if (buffer->asRTCommandBuffer()) {
+        SkASSERT(fRTCommandBuffer.get() == buffer);
+        fRTCommandBuffer->submit();
+    } else {
+        SkASSERT(fTextureCommandBuffer.get() == buffer);
+        fTextureCommandBuffer->submit();
     }
 }
 
diff --git a/src/gpu/dawn/GrDawnGpu.h b/src/gpu/dawn/GrDawnGpu.h
index 7362a54..9d87b69 100644
--- a/src/gpu/dawn/GrDawnGpu.h
+++ b/src/gpu/dawn/GrDawnGpu.h
@@ -13,6 +13,7 @@
 
 class GrPipeline;
 class GrDawnGpuRTCommandBuffer;
+class GrDawnGpuTextureCommandBuffer;
 
 namespace SkSL {
     class Compiler;
@@ -143,7 +144,8 @@
     dawn::Device                                    fDevice;
     dawn::Queue                                     fQueue;
     std::unique_ptr<SkSL::Compiler>                 fCompiler;
-    std::unique_ptr<GrDawnGpuRTCommandBuffer>       fCachedRTCommandBuffer;
+    std::unique_ptr<GrDawnGpuRTCommandBuffer>       fRTCommandBuffer;
+    std::unique_ptr<GrDawnGpuTextureCommandBuffer>  fTextureCommandBuffer;
 
     typedef GrGpu INHERITED;
 };
diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
index 1f1a664..f156af3 100644
--- a/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
+++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.cpp
@@ -18,22 +18,65 @@
 #include "src/gpu/dawn/GrDawnProgramBuilder.h"
 #include "src/gpu/dawn/GrDawnRenderTarget.h"
 #include "src/gpu/dawn/GrDawnStencilAttachment.h"
+#include "src/gpu/dawn/GrDawnTexture.h"
 #include "src/gpu/dawn/GrDawnUtil.h"
 #include "src/sksl/SkSLCompiler.h"
 
-void GrDawnGpuTextureCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
-                                         const SkIPoint& dstPoint) {
-    SkASSERT(!"unimplemented");
+GrDawnGpuTextureCommandBuffer::GrDawnGpuTextureCommandBuffer(GrDawnGpu* gpu,
+                                                             GrTexture* texture,
+                                                             GrSurfaceOrigin origin)
+    : INHERITED(texture, origin)
+    , fGpu(gpu) {
+    fEncoder = fGpu->device().CreateCommandEncoder();
 }
 
-void GrDawnGpuTextureCommandBuffer::insertEventMarker(const char* msg) {
-    SkASSERT(!"unimplemented");
+void GrDawnGpuTextureCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
+                                         const SkIPoint& dstPoint) {
+    if (!src->asTexture()) {
+        return;
+    }
+    uint32_t width = srcRect.width(), height = srcRect.height();
+    size_t rowBytes = srcRect.width() * GrBytesPerPixel(src->config());
+    rowBytes = GrDawnRoundRowBytes(rowBytes);
+    size_t sizeInBytes = height * rowBytes;
+
+    dawn::BufferDescriptor desc;
+    desc.usage = dawn::BufferUsageBit::CopySrc | dawn::BufferUsageBit::CopyDst;
+    desc.size = sizeInBytes;
+
+    dawn::Buffer buffer = fGpu->device().CreateBuffer(&desc);
+
+    dawn::TextureCopyView srcTextureView, dstTextureView;
+    srcTextureView.texture = static_cast<GrDawnTexture*>(src->asTexture())->texture();
+    srcTextureView.origin = {(uint32_t) srcRect.x(), (uint32_t) srcRect.y(), 0};
+    dstTextureView.texture = static_cast<GrDawnTexture*>(fTexture)->texture();
+    dstTextureView.origin = {(uint32_t) dstPoint.x(), (uint32_t) dstPoint.y(), 0};
+
+    dawn::BufferCopyView bufferView;
+    bufferView.buffer = buffer;
+    bufferView.offset = 0;
+    bufferView.rowPitch = rowBytes;
+    bufferView.imageHeight = height;
+
+    dawn::Extent3D copySize = {width, height, 1};
+    fEncoder.CopyTextureToBuffer(&srcTextureView, &bufferView, &copySize);
+    fEncoder.CopyBufferToTexture(&bufferView, &dstTextureView, &copySize);
+}
+
+void GrDawnGpuTextureCommandBuffer::transferFrom(const SkIRect& srcRect,
+                                                 GrColorType surfaceColorType,
+                                                 GrColorType bufferColorType,
+                                                 GrGpuBuffer* transferBuffer,
+                                                 size_t offset) {
+    fGpu->transferPixelsFrom(fTexture, srcRect.fLeft, srcRect.fTop, srcRect.width(),
+                             srcRect.height(), surfaceColorType, bufferColorType, transferBuffer,
+                             offset);
 }
 
 void GrDawnGpuTextureCommandBuffer::submit() {
-    for (int i = 0; i < fCopies.count(); ++i) {
-        CopyInfo& copyInfo = fCopies[i];
-        fGpu->copySurface(fTexture, copyInfo.fSrc, copyInfo.fSrcRect, copyInfo.fDstPoint);
+    dawn::CommandBuffer commandBuffer = fEncoder.Finish();
+    if (commandBuffer) {
+        fGpu->queue().Submit(1, &commandBuffer);
     }
 }
 
@@ -147,7 +190,51 @@
 
 void GrDawnGpuRTCommandBuffer::copy(GrSurface* src, const SkIRect& srcRect,
                                     const SkIPoint& dstPoint) {
-    SkASSERT(!"unimplemented");
+    auto s = static_cast<GrDawnTexture*>(src->asTexture());
+    auto d = static_cast<GrDawnTexture*>(fRenderTarget->asTexture());
+
+    if (!s || !d) {
+        return;
+    }
+
+    dawn::Texture srcTex = s->texture();
+    dawn::Texture dstTex = d->texture();
+
+    uint32_t x = srcRect.x();
+    uint32_t y = srcRect.y();
+    uint32_t width = srcRect.width();
+    uint32_t height = srcRect.height();
+    int rowPitch = GrDawnRoundRowBytes(width * GrBytesPerPixel(src->config()));
+    int sizeInBytes = rowPitch * height;
+
+    dawn::BufferDescriptor desc;
+    desc.usage = dawn::BufferUsageBit::CopySrc | dawn::BufferUsageBit::CopyDst;
+    desc.size = sizeInBytes;
+
+    dawn::Buffer buffer = fGpu->device().CreateBuffer(&desc);
+
+    uint32_t dstX = dstPoint.x();
+    uint32_t dstY = dstPoint.y();
+    fPassEncoder.EndPass();
+
+    dawn::TextureCopyView srcTextureCopyView;
+    srcTextureCopyView.texture = srcTex;
+    srcTextureCopyView.origin = {x, y, 0};
+
+    dawn::TextureCopyView dstTextureCopyView;
+    dstTextureCopyView.texture = dstTex;
+    dstTextureCopyView.origin = {dstX, dstY, 0};
+
+    dawn::BufferCopyView bufferCopyView;
+    bufferCopyView.buffer = buffer;
+    bufferCopyView.offset = 0;
+    bufferCopyView.rowPitch = rowPitch;
+    bufferCopyView.imageHeight = height;
+
+    dawn::Extent3D copySize = {width, height, 1};
+    fEncoder.CopyTextureToBuffer(&srcTextureCopyView, &bufferCopyView, &copySize);
+    fEncoder.CopyBufferToTexture(&bufferCopyView, &dstTextureCopyView, &copySize);
+    fPassEncoder = beginRenderPass(dawn::LoadOp::Load, dawn::LoadOp::Load);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
diff --git a/src/gpu/dawn/GrDawnGpuCommandBuffer.h b/src/gpu/dawn/GrDawnGpuCommandBuffer.h
index afe323b..162f850 100644
--- a/src/gpu/dawn/GrDawnGpuCommandBuffer.h
+++ b/src/gpu/dawn/GrDawnGpuCommandBuffer.h
@@ -20,33 +20,20 @@
 
 class GrDawnGpuTextureCommandBuffer : public GrGpuTextureCommandBuffer {
 public:
-    GrDawnGpuTextureCommandBuffer(GrDawnGpu* gpu, GrTexture* texture, GrSurfaceOrigin origin)
-        : INHERITED(texture, origin)
-        , fGpu(gpu) {
-    }
-
+    GrDawnGpuTextureCommandBuffer(GrDawnGpu* gpu, GrTexture* texture, GrSurfaceOrigin origin);
     ~GrDawnGpuTextureCommandBuffer() override;
 
     void copy(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
 
-    void insertEventMarker(const char*) override;
-
-private:
+    void transferFrom(const SkIRect& srcRect, GrColorType surfaceColorType,
+                      GrColorType bufferColorType, GrGpuBuffer* transferBuffer,
+                      size_t offset) override;
+    void insertEventMarker(const char*) override {}
     void submit();
 
-    struct CopyInfo {
-        CopyInfo(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
-                 const SkIPoint& dstPoint)
-            : fSrc(src), fSrcOrigin(srcOrigin), fSrcRect(srcRect), fDstPoint(dstPoint) {}
-
-        GrSurface*      fSrc;
-        GrSurfaceOrigin fSrcOrigin;
-        SkIRect         fSrcRect;
-        SkIPoint        fDstPoint;
-    };
-
-    GrDawnGpu*                   fGpu;
-    SkTArray<CopyInfo>          fCopies;
+private:
+    GrDawnGpu*                        fGpu;
+    dawn::CommandEncoder              fEncoder;
 
     typedef GrGpuTextureCommandBuffer INHERITED;
 };
@@ -131,17 +118,6 @@
         GrDeferredTextureUploadFn fUpload;
     };
 
-    struct CopyInfo {
-        CopyInfo(GrSurface* src, GrSurfaceOrigin srcOrigin, const SkIRect& srcRect,
-                 const SkIPoint& dstPoint)
-            : fSrc(src), fSrcOrigin(srcOrigin), fSrcRect(srcRect), fDstPoint(dstPoint) {}
-
-        GrSurface*      fSrc;
-        GrSurfaceOrigin fSrcOrigin;
-        SkIRect         fSrcRect;
-        SkIPoint        fDstPoint;
-    };
-
     GrDawnGpu*                  fGpu;
     dawn::CommandEncoder        fEncoder;
     dawn::RenderPassEncoder     fPassEncoder;