Metal: Use std::unique_ptr for texture decode

This commit is contained in:
wheremyfoodat 2025-03-16 13:52:32 +02:00
parent fa123cea3f
commit e635b9ec8a
5 changed files with 95 additions and 92 deletions

View file

@ -10,7 +10,7 @@ namespace PICA {
struct MTLPixelFormatInfo { struct MTLPixelFormatInfo {
MTL::PixelFormat pixelFormat; MTL::PixelFormat pixelFormat;
size_t bytesPerTexel; size_t bytesPerTexel;
void (*decoder)(OpenGL::uvec2, u32, u32, std::span<const u8>, std::vector<u8>&); void (*decoder)(OpenGL::uvec2, u32, u32, std::span<const u8>, u8*);
bool needsSwizzle = false; bool needsSwizzle = false;
MTL::TextureSwizzleChannels swizzle{ MTL::TextureSwizzleChannels swizzle{

View file

@ -4,21 +4,21 @@
// TODO: remove dependency on OpenGL // TODO: remove dependency on OpenGL
#include "opengl.hpp" #include "opengl.hpp"
void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);
void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData); void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData);

View file

@ -3,6 +3,7 @@
#include <fmt/format.h> #include <fmt/format.h>
#include <array> #include <array>
#include <memory>
#include "colour.hpp" #include "colour.hpp"
#include "renderer_mtl/objc_helper.hpp" #include "renderer_mtl/objc_helper.hpp"
@ -109,16 +110,18 @@ namespace Metal {
} }
void Texture::decodeTexture(std::span<const u8> data) { void Texture::decodeTexture(std::span<const u8> data) {
std::vector<u8> decoded; std::unique_ptr<u8[]> decodedData(new u8[u64(size.u()) * u64(size.v()) * formatInfo.bytesPerTexel]);
decoded.reserve(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 // Decode texels line by line
for (u32 v = 0; v < size.v(); v++) { for (u32 v = 0; v < size.v(); v++) {
for (u32 u = 0; u < size.u(); u++) { for (u32 u = 0; u < size.u(); u++) {
formatInfo.decoder(size, u, v, data, decoded); 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 } // namespace Metal

View file

@ -128,7 +128,7 @@ void RendererMTL::display() {
} }
void RendererMTL::initGraphicsContext(SDL_Window* window) { 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 #ifdef PANDA3DS_IOS
device = MTL::CreateSystemDefaultDevice(); device = MTL::CreateSystemDefaultDevice();
#else #else
@ -138,7 +138,7 @@ void RendererMTL::initGraphicsContext(SDL_Window* window) {
device = MTL::CreateSystemDefaultDevice(); device = MTL::CreateSystemDefaultDevice();
metalLayer->setDevice(device); metalLayer->setDevice(device);
#endif #endif
checkForMTLPixelFormatSupport(device); checkForMTLPixelFormatSupport(device);
commandQueue = device->newCommandQueue(); commandQueue = device->newCommandQueue();

View file

@ -37,32 +37,32 @@ u32 getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) {
return offset / 2; return offset / 2;
} }
void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelABGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 4); const u32 offset = getSwizzledOffset(u, v, size.u(), 4);
const u8 alpha = inData[offset]; const u8 alpha = inData[offset];
const u8 b = inData[offset + 1]; const u8 b = inData[offset + 1];
const u8 g = inData[offset + 2]; const u8 g = inData[offset + 2];
const u8 r = inData[offset + 3]; const u8 r = inData[offset + 3];
outData.push_back(r); *outData++ = r;
outData.push_back(g); *outData++ = g;
outData.push_back(b); *outData++ = b;
outData.push_back(alpha); *outData++ = alpha;
} }
void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelBGR8ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 3); const u32 offset = getSwizzledOffset(u, v, size.u(), 3);
const u8 b = inData[offset]; const u8 b = inData[offset];
const u8 g = inData[offset + 1]; const u8 g = inData[offset + 1];
const u8 r = inData[offset + 2]; const u8 r = inData[offset + 2];
outData.push_back(r); *outData++ = r;
outData.push_back(g); *outData++ = g;
outData.push_back(b); *outData++ = b;
outData.push_back(0xff); *outData++ = 0xff;
} }
void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelA1BGR5ToBGR5A1(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); 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<const
u8 r = getBits<11, 5, u8>(texel); u8 r = getBits<11, 5, u8>(texel);
u16 outTexel = (alpha << 15) | (r << 10) | (g << 5) | b; u16 outTexel = (alpha << 15) | (r << 10) | (g << 5) | b;
outData.push_back(outTexel & 0xff); *outData++ = outTexel & 0xff;
outData.push_back((outTexel >> 8) & 0xff); *outData++ = (outTexel >> 8) & 0xff;
} }
void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelA1BGR5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); 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<const
u8 g = Colour::convert5To8Bit(getBits<6, 5, u8>(texel)); u8 g = Colour::convert5To8Bit(getBits<6, 5, u8>(texel));
u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel)); u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel));
outData.push_back(r); *outData++ = r;
outData.push_back(g); *outData++ = g;
outData.push_back(b); *outData++ = b;
outData.push_back(alpha); *outData++ = alpha;
} }
void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelB5G6R5ToB5G6R5(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8);
outData.push_back(texel & 0xff); *outData++ = texel & 0xff;
outData.push_back((texel >> 8) & 0xff); *outData++ = (texel >> 8) & 0xff;
} }
void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelB5G6R5ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 2); const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
const u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); 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<const
const u8 g = Colour::convert6To8Bit(getBits<5, 6, u8>(texel)); const u8 g = Colour::convert6To8Bit(getBits<5, 6, u8>(texel));
const u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel)); const u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel));
outData.push_back(r); *outData++ = r;
outData.push_back(g); *outData++ = g;
outData.push_back(b); *outData++ = b;
outData.push_back(0xff); *outData++ = 0xff;
} }
void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelABGR4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2); u32 offset = getSwizzledOffset(u, v, size.u(), 2);
u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); 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<const u
u8 g = getBits<8, 4, u8>(texel); u8 g = getBits<8, 4, u8>(texel);
u8 r = getBits<12, 4, u8>(texel); u8 r = getBits<12, 4, u8>(texel);
outData.push_back((b << 4) | alpha); *outData++ = (b << 4) | alpha;
outData.push_back((r << 4) | g); *outData++ = (r << 4) | g;
} }
void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelABGR4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2); u32 offset = getSwizzledOffset(u, v, size.u(), 2);
u16 texel = u16(inData[offset]) | (u16(inData[offset + 1]) << 8); 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<const u
u8 g = Colour::convert4To8Bit(getBits<8, 4, u8>(texel)); u8 g = Colour::convert4To8Bit(getBits<8, 4, u8>(texel));
u8 r = Colour::convert4To8Bit(getBits<12, 4, u8>(texel)); u8 r = Colour::convert4To8Bit(getBits<12, 4, u8>(texel));
outData.push_back(r); *outData++ = r;
outData.push_back(g); *outData++ = g;
outData.push_back(b); *outData++ = b;
outData.push_back(alpha); *outData++ = alpha;
} }
void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelAI8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2); u32 offset = getSwizzledOffset(u, v, size.u(), 2);
// Same as I8 except each pixel gets its own alpha value too // Same as I8 except each pixel gets its own alpha value too
const u8 alpha = inData[offset]; const u8 alpha = inData[offset];
const u8 intensity = inData[offset + 1]; const u8 intensity = inData[offset + 1];
outData.push_back(intensity); *outData++ = intensity;
outData.push_back(alpha); *outData++ = alpha;
} }
void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelGR8ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 2); u32 offset = getSwizzledOffset(u, v, size.u(), 2);
constexpr u8 b = 0; constexpr u8 b = 0;
const u8 g = inData[offset]; const u8 g = inData[offset];
const u8 r = inData[offset + 1]; const u8 r = inData[offset + 1];
outData.push_back(r); *outData++ = r;
outData.push_back(g); *outData++ = g;
} }
void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelI8ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 1); u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 intensity = inData[offset]; const u8 intensity = inData[offset];
outData.push_back(intensity); *outData++ = intensity;
} }
void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelA8ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset(u, v, size.u(), 1); u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 alpha = inData[offset]; const u8 alpha = inData[offset];
outData.push_back(alpha); *outData++ = alpha;
} }
void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelAI4ToABGR4(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 1); const u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 texel = inData[offset]; const u8 texel = inData[offset];
const u8 alpha = texel & 0xf; const u8 alpha = texel & 0xf;
const u8 intensity = texel >> 4; const u8 intensity = texel >> 4;
outData.push_back((intensity << 4) | intensity); *outData++ = (intensity << 4) | intensity;
outData.push_back((alpha << 4) | intensity); *outData++ = (alpha << 4) | intensity;
} }
void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelAI4ToRG8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset(u, v, size.u(), 1); const u32 offset = getSwizzledOffset(u, v, size.u(), 1);
const u8 texel = inData[offset]; const u8 texel = inData[offset];
const u8 alpha = Colour::convert4To8Bit(texel & 0xf); const u8 alpha = Colour::convert4To8Bit(texel & 0xf);
const u8 intensity = Colour::convert4To8Bit(texel >> 4); const u8 intensity = Colour::convert4To8Bit(texel >> 4);
outData.push_back(intensity); *outData++ = intensity;
outData.push_back(alpha); *outData++ = alpha;
} }
void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelI4ToR8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); 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 // 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); u8 intensity = inData[offset] >> ((u % 2) ? 4 : 0);
intensity = Colour::convert4To8Bit(getBits<0, 4>(intensity)); intensity = Colour::convert4To8Bit(getBits<0, 4>(intensity));
outData.push_back(intensity); *outData++ = intensity;
} }
void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelA4ToA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
const u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); 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 // 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); u8 alpha = inData[offset] >> ((u % 2) ? 4 : 0);
alpha = Colour::convert4To8Bit(getBits<0, 4>(alpha)); 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); } static constexpr u32 signExtend3To32(u32 val) { return (u32)(s32(val) << 29 >> 29); }
void decodeETC(u32 u, u32 v, u64 colourData, u32 alpha, std::vector<u8>& outData) { void decodeETC(u32 u, u32 v, u64 colourData, u32 alpha, u8* outData) {
static constexpr u32 modifiers[8][2] = { static constexpr u32 modifiers[8][2] = {
{2, 8}, {5, 17}, {9, 29}, {13, 42}, {18, 60}, {24, 80}, {33, 106}, {47, 183}, {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<u8>& outData
g = std::clamp(g + modifier, 0, 255); g = std::clamp(g + modifier, 0, 255);
b = std::clamp(b + modifier, 0, 255); b = std::clamp(b + modifier, 0, 255);
outData.push_back(r); *outData++ = r;
outData.push_back(g); *outData++ = g;
outData.push_back(b); *outData++ = b;
outData.push_back(alpha); *outData++ = alpha;
} }
template <bool hasAlpha> template <bool hasAlpha>
void getTexelETC(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void getTexelETC(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
// Pixel offset of the 8x8 tile based on u, v and the width of the texture // 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()); u32 offs = ((u & ~7) * 8) + ((v & ~7) * size.u());
if (!hasAlpha) { if (!hasAlpha) {
@ -325,10 +325,10 @@ void getTexelETC(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, s
decodeETC(u, v, colourData, alpha, outData); decodeETC(u, v, colourData, alpha, outData);
} }
void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelETC1ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
getTexelETC<false>(size, u, v, inData, outData); getTexelETC<false>(size, u, v, inData, outData);
} }
void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, std::vector<u8>& outData) { void decodeTexelETC1A4ToRGBA8(OpenGL::uvec2 size, u32 u, u32 v, std::span<const u8> inData, u8* outData) {
getTexelETC<true>(size, u, v, inData, outData); getTexelETC<true>(size, u, v, inData, outData);
} }