Add SkSurface::asyncReadPixels()

Initial version. Current limitations: No Metal support, no color space
conversions, for each src color type only one dst color type is legal (
which may or may not be the src color type), no alpha type conversions.

Bug: skia:8962

Change-Id: I6f046a32342b8f5ffb1799d67d7ba15c250ef9bf
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/212981
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/ops/GrTransferFromOp.cpp b/src/gpu/ops/GrTransferFromOp.cpp
new file mode 100644
index 0000000..e1ddfc5
--- /dev/null
+++ b/src/gpu/ops/GrTransferFromOp.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/gpu/ops/GrTransferFromOp.h"
+#include "include/private/GrRecordingContext.h"
+#include "src/gpu/GrCaps.h"
+#include "src/gpu/GrGpuCommandBuffer.h"
+#include "src/gpu/GrMemoryPool.h"
+#include "src/gpu/GrRecordingContextPriv.h"
+
+std::unique_ptr<GrOp> GrTransferFromOp::Make(GrRecordingContext* context,
+                                             const SkIRect& srcRect,
+                                             GrColorType dstColorType,
+                                             sk_sp<GrGpuBuffer> dstBuffer,
+                                             size_t dstOffset) {
+    SkASSERT(context->priv().caps()->transferFromOffsetAlignment(dstColorType));
+    SkASSERT(dstOffset % context->priv().caps()->transferFromOffsetAlignment(dstColorType) == 0);
+    GrOpMemoryPool* pool = context->priv().opMemoryPool();
+    return pool->allocate<GrTransferFromOp>(srcRect, dstColorType, std::move(dstBuffer), dstOffset);
+}
+
+void GrTransferFromOp::onExecute(GrOpFlushState* state, const SkRect& chainBounds) {
+    state->commandBuffer()->transferFrom(fSrcRect, fDstColorType, fDstBuffer.get(), fDstOffset);
+}