Index: src/gpu/vk/GrVkGpu.cpp |
diff --git a/src/gpu/vk/GrVkGpu.cpp b/src/gpu/vk/GrVkGpu.cpp |
index 9a8a6e4e8c5954f76b4dfa324260785fa7b0b70d..ed165c52a14f04d593e5a81bef939fd0554606d2 100644 |
--- a/src/gpu/vk/GrVkGpu.cpp |
+++ b/src/gpu/vk/GrVkGpu.cpp |
@@ -1702,27 +1702,41 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, |
VK_PIPELINE_STAGE_TRANSFER_BIT, |
false); |
- GrVkTransferBuffer* transferBuffer = |
- static_cast<GrVkTransferBuffer*>(this->createBuffer(rowBytes * height, |
- kXferGpuToCpu_GrBufferType, |
- kStream_GrAccessPattern)); |
- |
+ size_t bpp = GrBytesPerPixel(config); |
+ size_t tightRowBytes = bpp * width; |
bool flipY = kBottomLeft_GrSurfaceOrigin == surface->origin(); |
- VkOffset3D offset = { |
- left, |
- flipY ? surface->height() - top - height : top, |
- 0 |
- }; |
- // Copy the image to a buffer so we can map it to cpu memory |
VkBufferImageCopy region; |
memset(®ion, 0, sizeof(VkBufferImageCopy)); |
+ |
+ bool copyFromOrigin = this->vkCaps().mustDoCopiesFromOrigin(); |
+ if (copyFromOrigin) { |
+ region.imageOffset = { 0, 0, 0 }; |
+ region.imageExtent = { (uint32_t)(left + width), |
+ (uint32_t)(flipY ? surface->height() - top : top + height), |
+ 1 |
+ }; |
+ } else { |
+ VkOffset3D offset = { |
+ left, |
+ flipY ? surface->height() - top - height : top, |
+ 0 |
+ }; |
+ region.imageOffset = offset; |
+ region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; |
+ } |
+ |
+ size_t transBufferRowBytes = bpp * region.imageExtent.width; |
+ GrVkTransferBuffer* transferBuffer = |
+ static_cast<GrVkTransferBuffer*>(this->createBuffer(transBufferRowBytes * height, |
+ kXferGpuToCpu_GrBufferType, |
+ kStream_GrAccessPattern)); |
+ |
+ // Copy the image to a buffer so we can map it to cpu memory |
region.bufferOffset = transferBuffer->offset(); |
region.bufferRowLength = 0; // Forces RowLength to be width. We handle the rowBytes below. |
region.bufferImageHeight = 0; // Forces height to be tightly packed. Only useful for 3d images. |
region.imageSubresource = { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 }; |
- region.imageOffset = offset; |
- region.imageExtent = { (uint32_t)width, (uint32_t)height, 1 }; |
fCurrentCmdBuffer->copyImageToBuffer(this, |
image, |
@@ -1745,26 +1759,30 @@ bool GrVkGpu::onReadPixels(GrSurface* surface, |
void* mappedMemory = transferBuffer->map(); |
- size_t tightRowBytes = GrBytesPerPixel(config) * width; |
+ if (copyFromOrigin) { |
+ uint32_t skipRows = region.imageExtent.height - height; |
+ mappedMemory = (char*)mappedMemory + transBufferRowBytes * skipRows + bpp * left; |
+ } |
+ |
if (flipY) { |
const char* srcRow = reinterpret_cast<const char*>(mappedMemory); |
char* dstRow = reinterpret_cast<char*>(buffer)+(height - 1) * rowBytes; |
for (int y = 0; y < height; y++) { |
memcpy(dstRow, srcRow, tightRowBytes); |
- srcRow += tightRowBytes; |
+ srcRow += transBufferRowBytes; |
dstRow -= rowBytes; |
} |
} else { |
- if (tightRowBytes == rowBytes) { |
+ if (transBufferRowBytes == rowBytes) { |
memcpy(buffer, mappedMemory, rowBytes*height); |
} else { |
- SkRectMemcpy(buffer, rowBytes, mappedMemory, tightRowBytes, tightRowBytes, height); |
+ SkRectMemcpy(buffer, rowBytes, mappedMemory, transBufferRowBytes, tightRowBytes, |
+ height); |
} |
} |
transferBuffer->unmap(); |
transferBuffer->unref(); |
- |
return true; |
} |