diff --git a/include/renderer_mtl/pica_to_mtl.hpp b/include/renderer_mtl/pica_to_mtl.hpp index b8911f89..d4c6dc7c 100644 --- a/include/renderer_mtl/pica_to_mtl.hpp +++ b/include/renderer_mtl/pica_to_mtl.hpp @@ -10,7 +10,7 @@ namespace PICA { struct MTLPixelFormatInfo { MTL::PixelFormat pixelFormat; size_t bytesPerTexel; - void (*decoder)(OpenGL::uvec2, u32, u32, std::span, std::vector&); + void (*decoder)(OpenGL::uvec2, u32, u32, std::span, u8*); bool needsSwizzle = false; MTL::TextureSwizzleChannels swizzle{ diff --git a/include/renderer_mtl/texture_decoder.hpp b/include/renderer_mtl/texture_decoder.hpp index 6fd5cfb5..376231c0 100644 --- a/include/renderer_mtl/texture_decoder.hpp +++ b/include/renderer_mtl/texture_decoder.hpp @@ -4,21 +4,21 @@ // TODO: remove dependency on OpenGL #include "opengl.hpp" -void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); -void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData); +void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); +void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData); diff --git a/src/core/renderer_mtl/mtl_texture.cpp b/src/core/renderer_mtl/mtl_texture.cpp index 49f78a13..29d4024a 100644 --- a/src/core/renderer_mtl/mtl_texture.cpp +++ b/src/core/renderer_mtl/mtl_texture.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "colour.hpp" #include "renderer_mtl/objc_helper.hpp" @@ -109,16 +110,18 @@ namespace Metal { } void Texture::decodeTexture(std::span data) { - std::vector decoded; - decoded.reserve(u64(size.u()) * u64(size.v()) * formatInfo.bytesPerTexel); + std::unique_ptr decodedData(new u8[u64(size.u()) * u64(size.v()) * formatInfo.bytesPerTexel]); + // This pointer will be incremented by our texture decoders + u8* decodePtr = decodedData.get(); - // Decode texels line by line - for (u32 v = 0; v < size.v(); v++) { - for (u32 u = 0; u < size.u(); u++) { - formatInfo.decoder(size, u, v, data, decoded); - } - } + // Decode texels line by line + for (u32 v = 0; v < size.v(); v++) { + for (u32 u = 0; u < size.u(); u++) { + formatInfo.decoder(size, u, v, data, decodePtr); + decodePtr += formatInfo.bytesPerTexel; + } + } - texture->replaceRegion(MTL::Region(0, 0, size.u(), size.v()), 0, 0, decoded.data(), formatInfo.bytesPerTexel * size.u(), 0); + texture->replaceRegion(MTL::Region(0, 0, size.u(), size.v()), 0, 0, decodedData.get(), formatInfo.bytesPerTexel * size.u(), 0); } } // namespace Metal diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp index 6ec11aa3..e6fdf653 100644 --- a/src/core/renderer_mtl/renderer_mtl.cpp +++ b/src/core/renderer_mtl/renderer_mtl.cpp @@ -128,7 +128,7 @@ void RendererMTL::display() { } void RendererMTL::initGraphicsContext(SDL_Window* window) { - // On iOS, the SwiftUI side handles MetalLayer & the CommandQueue + // On iOS, the SwiftUI side handles the MetalLayer #ifdef PANDA3DS_IOS device = MTL::CreateSystemDefaultDevice(); #else @@ -138,7 +138,7 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) { device = MTL::CreateSystemDefaultDevice(); metalLayer->setDevice(device); #endif - checkForMTLPixelFormatSupport(device); + checkForMTLPixelFormatSupport(device); commandQueue = device->newCommandQueue(); diff --git a/src/core/renderer_mtl/texture_decoder.cpp b/src/core/renderer_mtl/texture_decoder.cpp index 081d4889..06db2d76 100644 --- a/src/core/renderer_mtl/texture_decoder.cpp +++ b/src/core/renderer_mtl/texture_decoder.cpp @@ -37,32 +37,32 @@ u32 getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) { return offset / 2; } -void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 4); const u8 alpha = inData[offset]; const u8 b = inData[offset + 1]; const u8 g = inData[offset + 2]; const u8 r = inData[offset + 3]; - outData.push_back(r); - outData.push_back(g); - outData.push_back(b); - outData.push_back(alpha); + *outData++ = r; + *outData++ = g; + *outData++ = b; + *outData++ = alpha; } -void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 3); const u8 b = inData[offset]; const u8 g = inData[offset + 1]; const u8 r = inData[offset + 2]; - outData.push_back(r); - outData.push_back(g); - outData.push_back(b); - outData.push_back(0xff); + *outData++ = r; + *outData++ = g; + *outData++ = b; + *outData++ = 0xff; } -void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); @@ -72,11 +72,11 @@ void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span(texel); u16 outTexel = (alpha << 15) | (r << 10) | (g << 5) | b; - outData.push_back(outTexel & 0xff); - outData.push_back((outTexel >> 8) & 0xff); + *outData++ = outTexel & 0xff; + *outData++ = (outTexel >> 8) & 0xff; } -void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); @@ -85,21 +85,21 @@ void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span(texel)); u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel)); - outData.push_back(r); - outData.push_back(g); - outData.push_back(b); - outData.push_back(alpha); + *outData++ = r; + *outData++ = g; + *outData++ = b; + *outData++ = alpha; } -void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); - outData.push_back(texel & 0xff); - outData.push_back((texel >> 8) & 0xff); + *outData++ = texel & 0xff; + *outData++ = (texel >> 8) & 0xff; } -void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); @@ -107,13 +107,13 @@ void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span(texel)); const u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel)); - outData.push_back(r); - outData.push_back(g); - outData.push_back(b); - outData.push_back(0xff); + *outData++ = r; + *outData++ = g; + *outData++ = b; + *outData++ = 0xff; } -void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { u32 offset = getSwizzledOffset(u, v, size.u(), 2); u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); @@ -122,11 +122,11 @@ void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span(texel); u8 r = getBits<12, 4, u8>(texel); - outData.push_back((b << 4) | alpha); - outData.push_back((r << 4) | g); + *outData++ = (b << 4) | alpha; + *outData++ = (r << 4) | g; } -void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { u32 offset = getSwizzledOffset(u, v, size.u(), 2); u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); @@ -135,90 +135,90 @@ void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span(texel)); u8 r = Colour::convert4To8Bit(getBits<12, 4, u8>(texel)); - outData.push_back(r); - outData.push_back(g); - outData.push_back(b); - outData.push_back(alpha); + *outData++ = r; + *outData++ = g; + *outData++ = b; + *outData++ = alpha; } -void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { u32 offset = getSwizzledOffset(u, v, size.u(), 2); // Same as I8 except each pixel gets its own alpha value too const u8 alpha = inData[offset]; const u8 intensity = inData[offset + 1]; - outData.push_back(intensity); - outData.push_back(alpha); + *outData++ = intensity; + *outData++ = alpha; } -void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { u32 offset = getSwizzledOffset(u, v, size.u(), 2); constexpr u8 b = 0; const u8 g = inData[offset]; const u8 r = inData[offset + 1]; - outData.push_back(r); - outData.push_back(g); + *outData++ = r; + *outData++ = g; } -void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { u32 offset = getSwizzledOffset(u, v, size.u(), 1); const u8 intensity = inData[offset]; - outData.push_back(intensity); + *outData++ = intensity; } -void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { u32 offset = getSwizzledOffset(u, v, size.u(), 1); const u8 alpha = inData[offset]; - outData.push_back(alpha); + *outData++ = alpha; } -void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 1); const u8 texel = inData[offset]; const u8 alpha = texel & 0xf; const u8 intensity = texel >> 4; - outData.push_back((intensity << 4) | intensity); - outData.push_back((alpha << 4) | intensity); + *outData++ = (intensity << 4) | intensity; + *outData++ = (alpha << 4) | intensity; } -void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset(u, v, size.u(), 1); const u8 texel = inData[offset]; const u8 alpha = Colour::convert4To8Bit(texel & 0xf); const u8 intensity = Colour::convert4To8Bit(texel >> 4); - outData.push_back(intensity); - outData.push_back(alpha); + *outData++ = intensity; + *outData++ = alpha; } -void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); // For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates u8 intensity = inData[offset] >> ((u % 2) ? 4 : 0); intensity = Colour::convert4To8Bit(getBits<0, 4>(intensity)); - outData.push_back(intensity); + *outData++ = intensity; } -void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { const u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); // For odd U coordinates, grab the top 4 bits, and the low 4 bits for even coordinates u8 alpha = inData[offset] >> ((u % 2) ? 4 : 0); alpha = Colour::convert4To8Bit(getBits<0, 4>(alpha)); - outData.push_back(alpha); + *outData++ = alpha; } static constexpr u32 signExtend3To32(u32 val) { return (u32)(s32(val) << 29 >> 29); } -void decodeETC(u32 u, u32 v, u64 colourData, u32 alpha, std::vector& outData) { +void decodeETC(u32 u, u32 v, u64 colourData, u32 alpha, u8* outData) { static constexpr u32 modifiers[8][2] = { {2, 8}, {5, 17}, {9, 29}, {13, 42}, {18, 60}, {24, 80}, {33, 106}, {47, 183}, }; @@ -280,14 +280,14 @@ void decodeETC(u32 u, u32 v, u64 colourData, u32 alpha, std::vector& outData g = std::clamp(g + modifier, 0, 255); b = std::clamp(b + modifier, 0, 255); - outData.push_back(r); - outData.push_back(g); - outData.push_back(b); - outData.push_back(alpha); + *outData++ = r; + *outData++ = g; + *outData++ = b; + *outData++ = alpha; } template -void getTexelETC(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void getTexelETC(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { // Pixel offset of the 8x8 tile based on u, v and the width of the texture u32 offs = ((u & ~7) * 8) + ((v & ~7) * size.u()); if (!hasAlpha) { @@ -325,10 +325,10 @@ void getTexelETC(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, s decodeETC(u, v, colourData, alpha, outData); } -void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { getTexelETC(size, u, v, inData, outData); } -void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, std::vector& outData) { +void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span inData, u8* outData) { getTexelETC(size, u, v, inData, outData); }