From 6ee3f733351bc1b7f1c737eaccf57e31a3388849 Mon Sep 17 00:00:00 2001 From: Wunkolo Date: Sun, 18 Jun 2023 08:13:17 -0700 Subject: [PATCH] Bisect `TextureFmt` and `ColorFmt` Makes framebuffer-formats unrepresentable from texture formats while allowing them to alias each other. Add utility functions as well that just re-use the `TextureFmt` ones. --- include/PICA/regs.hpp | 54 ++++++++++++++++--------- include/renderer_gl/renderer_gl.hpp | 2 +- include/renderer_gl/textures.hpp | 6 +-- src/core/renderer_gl/renderer_gl.cpp | 2 +- src/core/renderer_gl/textures.cpp | 60 ++++++++++++++-------------- 5 files changed, 70 insertions(+), 54 deletions(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 9a011cc4..7b726974 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -130,7 +130,7 @@ namespace PICA { }; } - enum class ColorFmt : u32 { + enum class TextureFmt : u32 { RGBA8 = 0x0, RGB8 = 0x1, RGBA5551 = 0x2, @@ -147,6 +147,14 @@ namespace PICA { ETC1A4 = 0xD, }; + enum class ColorFmt : u32 { + RGBA8 = 0x0, + RGB8 = 0x1, + RGBA5551 = 0x2, + RGB565 = 0x3, + RGBA4 = 0x4, + }; + enum class DepthFmt : u32 { Depth16 = 0, Unknown1 = 1, // Technically selectable, but function is unknown @@ -155,39 +163,47 @@ namespace PICA { }; // Returns the string representation of a texture format - inline constexpr const char* textureFormatToString(ColorFmt fmt) { + inline constexpr const char* textureFormatToString(TextureFmt fmt) { switch (fmt) { - case ColorFmt::RGBA8: return "RGBA8"; - case ColorFmt::RGB8: return "RGB8"; - case ColorFmt::RGBA5551: return "RGBA5551"; - case ColorFmt::RGB565: return "RGB565"; - case ColorFmt::RGBA4: return "RGBA4"; - case ColorFmt::IA8: return "IA8"; - case ColorFmt::RG8: return "RG8"; - case ColorFmt::I8: return "I8"; - case ColorFmt::A8: return "A8"; - case ColorFmt::IA4: return "IA4"; - case ColorFmt::I4: return "I4"; - case ColorFmt::A4: return "A4"; - case ColorFmt::ETC1: return "ETC1"; - case ColorFmt::ETC1A4: return "ETC1A4"; + case TextureFmt::RGBA8: return "RGBA8"; + case TextureFmt::RGB8: return "RGB8"; + case TextureFmt::RGBA5551: return "RGBA5551"; + case TextureFmt::RGB565: return "RGB565"; + case TextureFmt::RGBA4: return "RGBA4"; + case TextureFmt::IA8: return "IA8"; + case TextureFmt::RG8: return "RG8"; + case TextureFmt::I8: return "I8"; + case TextureFmt::A8: return "A8"; + case TextureFmt::IA4: return "IA4"; + case TextureFmt::I4: return "I4"; + case TextureFmt::A4: return "A4"; + case TextureFmt::ETC1: return "ETC1"; + case TextureFmt::ETC1A4: return "ETC1A4"; default: return "Unknown"; } } + inline constexpr const char* textureFormatToString(ColorFmt fmt) { + return textureFormatToString(static_cast(fmt)); + } + inline constexpr bool hasStencil(DepthFmt format) { return format == PICA::DepthFmt::Depth24Stencil8; } // Size occupied by each pixel in bytes // All formats are 16BPP except for RGBA8 (32BPP) and BGR8 (24BPP) - inline constexpr usize sizePerPixel(ColorFmt format) { + inline constexpr usize sizePerPixel(TextureFmt format) { switch (format) { - case ColorFmt::RGB8: return 3; - case ColorFmt::RGBA8: return 4; + case TextureFmt::RGB8: return 3; + case TextureFmt::RGBA8: return 4; default: return 2; } } + inline constexpr usize sizePerPixel(ColorFmt format) { + return sizePerPixel(static_cast(format)); + } + inline constexpr usize sizePerPixel(DepthFmt format) { switch (format) { case DepthFmt::Depth16: return 2; diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 383fa484..a41cfe87 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -46,7 +46,7 @@ class Renderer { OpenGL::uvec2 fbSize; // The size of the framebuffer (ie both the colour and depth buffer)' - u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer + u32 colourBufferLoc; // Location in 3DS VRAM for the colour buffer PICA::ColorFmt colourBufferFormat; // Format of the colours stored in the colour buffer // Same for the depth/stencil buffer diff --git a/include/renderer_gl/textures.hpp b/include/renderer_gl/textures.hpp index 4e54de2d..5469a59f 100644 --- a/include/renderer_gl/textures.hpp +++ b/include/renderer_gl/textures.hpp @@ -12,7 +12,7 @@ using Interval = boost::icl::right_open_interval; struct Texture { u32 location; u32 config; // Magnification/minification filter, wrapping configs, etc - PICA::ColorFmt format; + PICA::TextureFmt format; OpenGL::uvec2 size; bool valid; @@ -23,7 +23,7 @@ struct Texture { Texture() : valid(false) {} - Texture(u32 loc, PICA::ColorFmt format, u32 x, u32 y, u32 config, bool valid = true) + Texture(u32 loc, PICA::TextureFmt format, u32 x, u32 y, u32 config, bool valid = true) : location(loc), format(format), size({x, y}), config(config), valid(valid) { u64 endLoc = (u64)loc + sizeInBytes(); @@ -44,7 +44,7 @@ struct Texture { void free(); u64 sizeInBytes(); - u32 decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data); + u32 decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data); // Get the morton interleave offset of a texel based on its U and V values static u32 mortonInterleave(u32 u, u32 v); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 06748708..e6297d86 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -322,7 +322,7 @@ void Renderer::drawVertices(PICA::PrimType primType, std::span ver const u32 addr = (regs[0x85] & 0x0FFFFFFF) << 3; const u32 format = regs[0x8E] & 0xF; - Texture targetTex(addr, static_cast(format), width, height, config); + Texture targetTex(addr, static_cast(format), width, height, config); OpenGL::Texture tex = getTexture(targetTex); tex.bind(); } diff --git a/src/core/renderer_gl/textures.cpp b/src/core/renderer_gl/textures.cpp index b82653d5..a806e1eb 100644 --- a/src/core/renderer_gl/textures.cpp +++ b/src/core/renderer_gl/textures.cpp @@ -43,34 +43,34 @@ u64 Texture::sizeInBytes() { u64 pixelCount = u64(size.x()) * u64(size.y()); switch (format) { - case PICA::ColorFmt::RGBA8: // 4 bytes per pixel + case PICA::TextureFmt::RGBA8: // 4 bytes per pixel return pixelCount * 4; - case PICA::ColorFmt::RGB8: // 3 bytes per pixel + case PICA::TextureFmt::RGB8: // 3 bytes per pixel return pixelCount * 3; - case PICA::ColorFmt::RGBA5551: // 2 bytes per pixel - case PICA::ColorFmt::RGB565: - case PICA::ColorFmt::RGBA4: - case PICA::ColorFmt::RG8: - case PICA::ColorFmt::IA8: + case PICA::TextureFmt::RGBA5551: // 2 bytes per pixel + case PICA::TextureFmt::RGB565: + case PICA::TextureFmt::RGBA4: + case PICA::TextureFmt::RG8: + case PICA::TextureFmt::IA8: return pixelCount * 2; - case PICA::ColorFmt::A8: // 1 byte per pixel - case PICA::ColorFmt::I8: - case PICA::ColorFmt::IA4: + case PICA::TextureFmt::A8: // 1 byte per pixel + case PICA::TextureFmt::I8: + case PICA::TextureFmt::IA4: return pixelCount; - case PICA::ColorFmt::I4: // 4 bits per pixel - case PICA::ColorFmt::A4: + case PICA::TextureFmt::I4: // 4 bits per pixel + case PICA::TextureFmt::A4: return pixelCount / 2; - case PICA::ColorFmt::ETC1: // Compressed formats - case PICA::ColorFmt::ETC1A4: { + case PICA::TextureFmt::ETC1: // Compressed formats + case PICA::TextureFmt::ETC1A4: { // Number of 4x4 tiles const u64 tileCount = pixelCount / 16; // Tiles are 8 bytes each on ETC1 and 16 bytes each on ETC1A4 - const u64 tileSize = format == PICA::ColorFmt::ETC1 ? 8 : 16; + const u64 tileSize = format == PICA::TextureFmt::ETC1 ? 8 : 16; return tileCount * tileSize; } @@ -111,9 +111,9 @@ u32 Texture::getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) { // Get the texel at position (u, v) // fmt: format of the texture // data: texture data of the texture -u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { +u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) { switch (fmt) { - case PICA::ColorFmt::RGBA4: { + case PICA::TextureFmt::RGBA4: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -126,7 +126,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGBA5551: { + case PICA::TextureFmt::RGBA5551: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -139,7 +139,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGB565: { + case PICA::TextureFmt::RGB565: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8); @@ -151,7 +151,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RG8: { + case PICA::TextureFmt::RG8: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); @@ -162,7 +162,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGB8: { + case PICA::TextureFmt::RGB8: { u32 offset = getSwizzledOffset(u, v, size.u(), 3); auto ptr = static_cast(data); @@ -173,7 +173,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::RGBA8: { + case PICA::TextureFmt::RGBA8: { u32 offset = getSwizzledOffset(u, v, size.u(), 4); auto ptr = static_cast(data); @@ -185,7 +185,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (b << 16) | (g << 8) | r; } - case PICA::ColorFmt::IA4: { + case PICA::TextureFmt::IA4: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); @@ -197,7 +197,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::A4: { + case PICA::TextureFmt::A4: { u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); auto ptr = static_cast(data); @@ -209,7 +209,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (0 << 16) | (0 << 8) | 0; } - case PICA::ColorFmt::A8: { + case PICA::TextureFmt::A8: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); const u8 alpha = ptr[offset]; @@ -218,7 +218,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (0 << 16) | (0 << 8) | 0; } - case PICA::ColorFmt::I4: { + case PICA::TextureFmt::I4: { u32 offset = getSwizzledOffset_4bpp(u, v, size.u()); auto ptr = static_cast(data); @@ -230,7 +230,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::I8: { + case PICA::TextureFmt::I8: { u32 offset = getSwizzledOffset(u, v, size.u(), 1); auto ptr = static_cast(data); const u8 intensity = ptr[offset]; @@ -239,7 +239,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::IA8: { + case PICA::TextureFmt::IA8: { u32 offset = getSwizzledOffset(u, v, size.u(), 2); auto ptr = static_cast(data); @@ -249,8 +249,8 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::ColorFmt fmt, const void* data) { return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity; } - case PICA::ColorFmt::ETC1: return getTexelETC(false, u, v, size.u(), data); - case PICA::ColorFmt::ETC1A4: return getTexelETC(true, u, v, size.u(), data); + case PICA::TextureFmt::ETC1: return getTexelETC(false, u, v, size.u(), data); + case PICA::TextureFmt::ETC1A4: return getTexelETC(true, u, v, size.u(), data); default: Helpers::panic("[Texture::DecodeTexel] Unimplemented format = %d", static_cast(fmt));