Implement GrGpu::transferFromBufferToBuffer on GL
Bug: skia:13427
Bug: skia:12720
Change-Id: Ic2cdebd86a814bed3bf22848218bbf355724a0e0
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/550712
Commit-Queue: Brian Salomon <bsalomon@google.com>
Reviewed-by: Greg Daniel <egdaniel@google.com>
diff --git a/src/gpu/ganesh/gl/GrGLCaps.cpp b/src/gpu/ganesh/gl/GrGLCaps.cpp
index 026e4bd..e8ce6c5 100644
--- a/src/gpu/ganesh/gl/GrGLCaps.cpp
+++ b/src/gpu/ganesh/gl/GrGLCaps.cpp
@@ -544,6 +544,16 @@
fTransferFromSurfaceToBufferSupport = false;
}
+ if (GR_IS_GR_GL(standard) &&
+ (version >= GR_GL_VER(3, 1) || ctxInfo.hasExtension("GL_ARB_copy_buffer"))) {
+ fTransferFromBufferToBufferSupport = true;
+ } else if (GR_IS_GR_GL_ES(standard) &&
+ (version >= GR_GL_VER(3, 0) || ctxInfo.hasExtension("GL_NV_copy_buffer"))) {
+ fTransferFromBufferToBufferSupport = true;
+ } else if (GR_IS_GR_WEBGL(standard) && version >= GR_GL_VER(2,0)) {
+ fTransferFromBufferToBufferSupport = true;
+ }
+
// On many GPUs, map memory is very expensive, so we effectively disable it here by setting the
// threshold to the maximum unless the client gives us a hint that map memory is cheap.
if (fBufferMapThreshold < 0) {
@@ -3691,6 +3701,10 @@
fDisallowDynamicMSAA = true;
}
+ // Below we are aggressive about turning off all mapping/transfer functionality together. This
+ // could be finer grained if code paths and tests were adjusted to check more specific caps.
+ // For example it might be possible to support buffer to buffer transfers even if buffer mapping
+ // or buffer to surface transfers don't work.
#if defined(__has_feature)
#if defined(SK_BUILD_FOR_MAC) && __has_feature(thread_sanitizer)
// See skbug.com/7058
@@ -3698,6 +3712,7 @@
fMapBufferFlags = kNone_MapFlags;
fTransferFromBufferToTextureSupport = false;
fTransferFromSurfaceToBufferSupport = false;
+ fTransferFromBufferToBufferSupport = false;
fTransferBufferType = TransferBufferType::kNone;
#endif
#endif
@@ -3712,6 +3727,7 @@
fMapBufferFlags = kNone_MapFlags;
fTransferFromBufferToTextureSupport = false;
fTransferFromSurfaceToBufferSupport = false;
+ fTransferFromBufferToBufferSupport = false;
fTransferBufferType = TransferBufferType::kNone;
}
diff --git a/src/gpu/ganesh/gl/GrGLGpu.cpp b/src/gpu/ganesh/gl/GrGLGpu.cpp
index cbce1e8..24b9c78 100644
--- a/src/gpu/ganesh/gl/GrGLGpu.cpp
+++ b/src/gpu/ganesh/gl/GrGLGpu.cpp
@@ -895,6 +895,28 @@
mipLevelCount);
}
+bool GrGLGpu::onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,
+ size_t srcOffset,
+ sk_sp<GrGpuBuffer> dst,
+ size_t dstOffset,
+ size_t size) {
+ auto glSrc = static_cast<const GrGLBuffer*>(src.get());
+ auto glDst = static_cast<const GrGLBuffer*>(dst.get());
+
+ // If we refactored bindBuffer() to use something other than GrGpuBufferType to indicate the
+ // binding target then we could use the COPY_READ and COPY_WRITE targets here. But
+ // CopyBufferSubData is documented to work with all the targets so it's not clear it's worth it.
+ this->bindBuffer(GrGpuBufferType::kXferCpuToGpu, glSrc);
+ this->bindBuffer(GrGpuBufferType::kXferGpuToCpu, glDst);
+
+ GL_CALL(CopyBufferSubData(GR_GL_PIXEL_UNPACK_BUFFER,
+ GR_GL_PIXEL_PACK_BUFFER,
+ srcOffset,
+ dstOffset,
+ size));
+ return true;
+}
+
bool GrGLGpu::onTransferPixelsTo(GrTexture* texture,
SkIRect rect,
GrColorType textureColorType,
diff --git a/src/gpu/ganesh/gl/GrGLGpu.h b/src/gpu/ganesh/gl/GrGLGpu.h
index 3012fe5..18493b5 100644
--- a/src/gpu/ganesh/gl/GrGLGpu.h
+++ b/src/gpu/ganesh/gl/GrGLGpu.h
@@ -322,6 +322,12 @@
int mipLevelCount,
bool prepForTexSampling) override;
+ bool onTransferFromBufferToBuffer(sk_sp<GrGpuBuffer> src,
+ size_t srcOffset,
+ sk_sp<GrGpuBuffer> dst,
+ size_t dstOffset,
+ size_t size) override;
+
bool onTransferPixelsTo(GrTexture*,
SkIRect,
GrColorType textureColorType,