Browse Source

metal: initial implementation of Texture:newImageData.

Alex Szpakowski 4 years ago
parent
commit
4639e7330e
1 changed files with 45 additions and 3 deletions
  1. 45 3
      src/modules/graphics/metal/Texture.mm

+ 45 - 3
src/modules/graphics/metal/Texture.mm

@@ -206,9 +206,51 @@ void Texture::generateMipmapsInternal()
 }}
 
 void Texture::readbackImageData(love::image::ImageData *imagedata, int slice, int mipmap, const Rect &rect)
-{
-	// TODO
-}
+{ @autoreleasepool {
+	auto gfx = Graphics::getInstance();
+
+	id<MTLBlitCommandEncoder> encoder = gfx->useBlitEncoder();
+
+	size_t rowSize = 0;
+	if (isCompressed())
+		rowSize = getPixelFormatCompressedBlockRowSize(format, rect.w);
+	else
+		rowSize = getPixelFormatUncompressedRowSize(format, rect.w);
+
+	// TODO: Verify this is correct for compressed formats at small sizes.
+	// TODO: make sure this is consistent with the imagedata byte size?
+	size_t sliceSize = getPixelFormatSliceSize(format, rect.w, rect.h);
+
+	int z = texType == TEXTURE_VOLUME ? slice : 0;
+
+	id<MTLBuffer> buffer = [gfx->device newBufferWithLength:sliceSize
+													options:MTLResourceStorageModeShared];
+
+	MTLBlitOption options = MTLBlitOptionNone;
+
+	if (isPixelFormatDepthStencil(format))
+		options = MTLBlitOptionDepthFromDepthStencil;
+
+	[encoder copyFromTexture:texture
+				 sourceSlice:texType == TEXTURE_VOLUME ? 0 : slice
+				 sourceLevel:mipmap
+				sourceOrigin:MTLOriginMake(rect.x, rect.y, z)
+				  sourceSize:MTLSizeMake(rect.w, rect.h, 1)
+					toBuffer:buffer
+		   destinationOffset:0
+	  destinationBytesPerRow:rowSize
+	destinationBytesPerImage:sliceSize
+					 options:options];
+
+	id<MTLCommandBuffer> cmd = gfx->getCommandBuffer();
+
+	gfx->submitBlitEncoder();
+	gfx->submitCommandBuffer();
+
+	[cmd waitUntilCompleted];
+
+	memcpy(imagedata->getData(), buffer.contents, imagedata->getSize());
+}}
 
 void Texture::setSamplerState(const SamplerState &s)
 { @autoreleasepool {