From 4639e7330eb9c7720a5fbfbcfc57f9173c2ed819 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Thu, 25 Mar 2021 20:36:31 -0300 Subject: [PATCH] metal: initial implementation of Texture:newImageData. --- src/modules/graphics/metal/Texture.mm | 48 +++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 3 deletions(-) diff --git a/src/modules/graphics/metal/Texture.mm b/src/modules/graphics/metal/Texture.mm index 3b9a1208b..946afc6f8 100644 --- a/src/modules/graphics/metal/Texture.mm +++ b/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 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 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 cmd = gfx->getCommandBuffer(); + + gfx->submitBlitEncoder(); + gfx->submitCommandBuffer(); + + [cmd waitUntilCompleted]; + + memcpy(imagedata->getData(), buffer.contents, imagedata->getSize()); +}} void Texture::setSamplerState(const SamplerState &s) { @autoreleasepool {