mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 23:25:40 +12:00
texture: Use spans
This commit is contained in:
parent
50bf9bf7da
commit
a019d98af9
5 changed files with 44 additions and 61 deletions
|
@ -129,17 +129,17 @@ class GPU {
|
||||||
|
|
||||||
// Get a pointer of type T* to the data starting from physical address paddr
|
// Get a pointer of type T* to the data starting from physical address paddr
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T* getPointerPhys(u32 paddr) {
|
T* getPointerPhys(u32 paddr, u32 size = 0) {
|
||||||
if (paddr >= PhysicalAddrs::FCRAM && paddr <= PhysicalAddrs::FCRAMEnd) {
|
if (paddr >= PhysicalAddrs::FCRAM && paddr + size <= PhysicalAddrs::FCRAMEnd) {
|
||||||
u8* fcram = mem.getFCRAM();
|
u8* fcram = mem.getFCRAM();
|
||||||
u32 index = paddr - PhysicalAddrs::FCRAM;
|
u32 index = paddr - PhysicalAddrs::FCRAM;
|
||||||
|
|
||||||
return (T*)&fcram[index];
|
return (T*)&fcram[index];
|
||||||
} else if (paddr >= PhysicalAddrs::VRAM && paddr <= PhysicalAddrs::VRAMEnd) {
|
} else if (paddr >= PhysicalAddrs::VRAM && paddr + size <= PhysicalAddrs::VRAMEnd) {
|
||||||
u32 index = paddr - PhysicalAddrs::VRAM;
|
u32 index = paddr - PhysicalAddrs::VRAM;
|
||||||
return (T*)&vram[index];
|
return (T*)&vram[index];
|
||||||
} else [[unlikely]] {
|
} else [[unlikely]] {
|
||||||
Helpers::panic("[GPU] Tried to access unknown physical address: %08X", paddr);
|
Helpers::panic("[GPU] Tried to access unknown physical address: %08X", paddr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -40,11 +40,11 @@ struct Texture {
|
||||||
|
|
||||||
void allocate();
|
void allocate();
|
||||||
void setNewConfig(u32 newConfig);
|
void setNewConfig(u32 newConfig);
|
||||||
void decodeTexture(const void* data);
|
void decodeTexture(std::span<const u8> data);
|
||||||
void free();
|
void free();
|
||||||
u64 sizeInBytes();
|
u64 sizeInBytes();
|
||||||
|
|
||||||
u32 decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data);
|
u32 decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data);
|
||||||
|
|
||||||
// Get the morton interleave offset of a texel based on its U and V values
|
// Get the morton interleave offset of a texel based on its U and V values
|
||||||
static u32 mortonInterleave(u32 u, u32 v);
|
static u32 mortonInterleave(u32 u, u32 v);
|
||||||
|
@ -59,6 +59,6 @@ struct Texture {
|
||||||
|
|
||||||
// Returns the texel at coordinates (u, v) of an ETC1(A4) texture
|
// Returns the texel at coordinates (u, v) of an ETC1(A4) texture
|
||||||
// TODO: Make hasAlpha a template parameter
|
// TODO: Make hasAlpha a template parameter
|
||||||
u32 getTexelETC(bool hasAlpha, u32 u, u32 v, u32 width, const void* data);
|
u32 getTexelETC(bool hasAlpha, u32 u, u32 v, u32 width, std::span<const u8> data);
|
||||||
u32 decodeETC(u32 alpha, u32 u, u32 v, u64 colourData);
|
u32 decodeETC(u32 alpha, u32 u, u32 v, u64 colourData);
|
||||||
};
|
};
|
||||||
|
|
|
@ -9,7 +9,7 @@ static constexpr u32 signExtend3To32(u32 val) {
|
||||||
return (u32)(s32(val) << 29 >> 29);
|
return (u32)(s32(val) << 29 >> 29);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 Texture::getTexelETC(bool hasAlpha, u32 u, u32 v, u32 width, const void* data) {
|
u32 Texture::getTexelETC(bool hasAlpha, u32 u, u32 v, u32 width, std::span<const u8> data) {
|
||||||
// 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) * width);
|
u32 offs = ((u & ~7) * 8) + ((v & ~7) * width);
|
||||||
if (!hasAlpha)
|
if (!hasAlpha)
|
||||||
|
@ -30,8 +30,7 @@ u32 Texture::getTexelETC(bool hasAlpha, u32 u, u32 v, u32 width, const void* dat
|
||||||
offs += subTileSize * subTileIndex;
|
offs += subTileSize * subTileIndex;
|
||||||
|
|
||||||
u32 alpha;
|
u32 alpha;
|
||||||
const u8* tmp = static_cast<const u8*>(data) + offs; // Pointer to colour and alpha data as u8*
|
const u64* ptr = reinterpret_cast<const u64*>(data.data() + offs); // Cast to u64*
|
||||||
const u64* ptr = reinterpret_cast<const u64*>(tmp); // Cast to u64*
|
|
||||||
|
|
||||||
if (hasAlpha) {
|
if (hasAlpha) {
|
||||||
// First 64 bits of the 4x4 subtile are alpha data
|
// First 64 bits of the 4x4 subtile are alpha data
|
||||||
|
@ -118,4 +117,4 @@ u32 Texture::decodeETC(u32 alpha, u32 u, u32 v, u64 colourData) {
|
||||||
b = std::clamp(b + modifier, 0, 255);
|
b = std::clamp(b + modifier, 0, 255);
|
||||||
|
|
||||||
return (alpha << 24) | (u32(b) << 16) | (u32(g) << 8) | u32(r);
|
return (alpha << 24) | (u32(b) << 16) | (u32(g) << 8) | u32(r);
|
||||||
}
|
}
|
||||||
|
|
|
@ -448,7 +448,7 @@ OpenGL::Texture RendererGL::getTexture(Texture& tex) {
|
||||||
if (buffer.has_value()) {
|
if (buffer.has_value()) {
|
||||||
return buffer.value().get().texture;
|
return buffer.value().get().texture;
|
||||||
} else {
|
} else {
|
||||||
const void* textureData = gpu.getPointerPhys<void*>(tex.location); // Get pointer to the texture data in 3DS memory
|
const auto textureData = std::span{gpu.getPointerPhys<u8>(tex.location), tex.sizeInBytes()}; // Get pointer to the texture data in 3DS memory
|
||||||
Texture& newTex = textureCache.add(tex);
|
Texture& newTex = textureCache.add(tex);
|
||||||
newTex.decodeTexture(textureData);
|
newTex.decodeTexture(textureData);
|
||||||
|
|
||||||
|
@ -515,4 +515,4 @@ void RendererGL::screenshot(const std::string& name) {
|
||||||
}
|
}
|
||||||
|
|
||||||
stbi_write_png(name.c_str(), width, height, 4, flippedPixels.data(), 0);
|
stbi_write_png(name.c_str(), width, height, 4, flippedPixels.data(), 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,12 +112,11 @@ u32 Texture::getSwizzledOffset_4bpp(u32 u, u32 v, u32 width) {
|
||||||
// Get the texel at position (u, v)
|
// Get the texel at position (u, v)
|
||||||
// fmt: format of the texture
|
// fmt: format of the texture
|
||||||
// data: texture data of the texture
|
// data: texture data of the texture
|
||||||
u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, std::span<const u8> data) {
|
||||||
switch (fmt) {
|
switch (fmt) {
|
||||||
case PICA::TextureFmt::RGBA4: {
|
case PICA::TextureFmt::RGBA4: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
u16 texel = u16(data[offset]) | (u16(data[offset + 1]) << 8);
|
||||||
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
|
|
||||||
|
|
||||||
u8 alpha = Colour::convert4To8Bit(getBits<0, 4, u8>(texel));
|
u8 alpha = Colour::convert4To8Bit(getBits<0, 4, u8>(texel));
|
||||||
u8 b = Colour::convert4To8Bit(getBits<4, 4, u8>(texel));
|
u8 b = Colour::convert4To8Bit(getBits<4, 4, u8>(texel));
|
||||||
|
@ -128,9 +127,8 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case PICA::TextureFmt::RGBA5551: {
|
case PICA::TextureFmt::RGBA5551: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
const u16 texel = u16(data[offset]) | (u16(data[offset + 1]) << 8);
|
||||||
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
|
|
||||||
|
|
||||||
u8 alpha = getBit<0>(texel) ? 0xff : 0;
|
u8 alpha = getBit<0>(texel) ? 0xff : 0;
|
||||||
u8 b = Colour::convert5To8Bit(getBits<1, 5, u8>(texel));
|
u8 b = Colour::convert5To8Bit(getBits<1, 5, u8>(texel));
|
||||||
|
@ -141,56 +139,47 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case PICA::TextureFmt::RGB565: {
|
case PICA::TextureFmt::RGB565: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
const u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
const u16 texel = u16(data[offset]) | (u16(data[offset + 1]) << 8);
|
||||||
u16 texel = u16(ptr[offset]) | (u16(ptr[offset + 1]) << 8);
|
|
||||||
|
|
||||||
u8 b = Colour::convert5To8Bit(getBits<0, 5, u8>(texel));
|
const u8 b = Colour::convert5To8Bit(getBits<0, 5, u8>(texel));
|
||||||
u8 g = Colour::convert6To8Bit(getBits<5, 6, u8>(texel));
|
const u8 g = Colour::convert6To8Bit(getBits<5, 6, u8>(texel));
|
||||||
u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel));
|
const u8 r = Colour::convert5To8Bit(getBits<11, 5, u8>(texel));
|
||||||
|
|
||||||
return (0xff << 24) | (b << 16) | (g << 8) | r;
|
return (0xff << 24) | (b << 16) | (g << 8) | r;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PICA::TextureFmt::RG8: {
|
case PICA::TextureFmt::RG8: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
|
||||||
|
|
||||||
constexpr u8 b = 0;
|
constexpr u8 b = 0;
|
||||||
u8 g = ptr[offset];
|
const u8 g = data[offset];
|
||||||
u8 r = ptr[offset + 1];
|
const u8 r = data[offset + 1];
|
||||||
|
|
||||||
return (0xff << 24) | (b << 16) | (g << 8) | r;
|
return (0xff << 24) | (b << 16) | (g << 8) | r;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PICA::TextureFmt::RGB8: {
|
case PICA::TextureFmt::RGB8: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 3);
|
const u32 offset = getSwizzledOffset(u, v, size.u(), 3);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
const u8 b = data[offset];
|
||||||
|
const u8 g = data[offset + 1];
|
||||||
u8 b = ptr[offset];
|
const u8 r = data[offset + 2];
|
||||||
u8 g = ptr[offset + 1];
|
|
||||||
u8 r = ptr[offset + 2];
|
|
||||||
|
|
||||||
return (0xff << 24) | (b << 16) | (g << 8) | r;
|
return (0xff << 24) | (b << 16) | (g << 8) | r;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PICA::TextureFmt::RGBA8: {
|
case PICA::TextureFmt::RGBA8: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 4);
|
const u32 offset = getSwizzledOffset(u, v, size.u(), 4);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
const u8 alpha = data[offset];
|
||||||
|
const u8 b = data[offset + 1];
|
||||||
u8 alpha = ptr[offset];
|
const u8 g = data[offset + 2];
|
||||||
u8 b = ptr[offset + 1];
|
const u8 r = data[offset + 3];
|
||||||
u8 g = ptr[offset + 2];
|
|
||||||
u8 r = ptr[offset + 3];
|
|
||||||
|
|
||||||
return (alpha << 24) | (b << 16) | (g << 8) | r;
|
return (alpha << 24) | (b << 16) | (g << 8) | r;
|
||||||
}
|
}
|
||||||
|
|
||||||
case PICA::TextureFmt::IA4: {
|
case PICA::TextureFmt::IA4: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
|
const u32 offset = getSwizzledOffset(u, v, size.u(), 1);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
const u8 texel = data[offset];
|
||||||
|
|
||||||
const u8 texel = ptr[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);
|
||||||
|
|
||||||
|
@ -199,11 +188,10 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case PICA::TextureFmt::A4: {
|
case PICA::TextureFmt::A4: {
|
||||||
u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
|
const u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
|
||||||
auto ptr = static_cast<const u8*>(data);
|
|
||||||
|
|
||||||
// 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 = ptr[offset] >> ((u % 2) ? 4 : 0);
|
u8 alpha = data[offset] >> ((u % 2) ? 4 : 0);
|
||||||
alpha = Colour::convert4To8Bit(getBits<0, 4>(alpha));
|
alpha = Colour::convert4To8Bit(getBits<0, 4>(alpha));
|
||||||
|
|
||||||
// A8 sets RGB to 0
|
// A8 sets RGB to 0
|
||||||
|
@ -212,8 +200,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
|
|
||||||
case PICA::TextureFmt::A8: {
|
case PICA::TextureFmt::A8: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
|
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
const u8 alpha = data[offset];
|
||||||
const u8 alpha = ptr[offset];
|
|
||||||
|
|
||||||
// A8 sets RGB to 0
|
// A8 sets RGB to 0
|
||||||
return (alpha << 24) | (0 << 16) | (0 << 8) | 0;
|
return (alpha << 24) | (0 << 16) | (0 << 8) | 0;
|
||||||
|
@ -221,10 +208,9 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
|
|
||||||
case PICA::TextureFmt::I4: {
|
case PICA::TextureFmt::I4: {
|
||||||
u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
|
u32 offset = getSwizzledOffset_4bpp(u, v, size.u());
|
||||||
auto ptr = static_cast<const u8*>(data);
|
|
||||||
|
|
||||||
// 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 = ptr[offset] >> ((u % 2) ? 4 : 0);
|
u8 intensity = data[offset] >> ((u % 2) ? 4 : 0);
|
||||||
intensity = Colour::convert4To8Bit(getBits<0, 4>(intensity));
|
intensity = Colour::convert4To8Bit(getBits<0, 4>(intensity));
|
||||||
|
|
||||||
// Intensity formats just copy the intensity value to every colour channel
|
// Intensity formats just copy the intensity value to every colour channel
|
||||||
|
@ -233,8 +219,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
|
|
||||||
case PICA::TextureFmt::I8: {
|
case PICA::TextureFmt::I8: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
|
u32 offset = getSwizzledOffset(u, v, size.u(), 1);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
const u8 intensity = data[offset];
|
||||||
const u8 intensity = ptr[offset];
|
|
||||||
|
|
||||||
// Intensity formats just copy the intensity value to every colour channel
|
// Intensity formats just copy the intensity value to every colour channel
|
||||||
return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity;
|
return (0xff << 24) | (intensity << 16) | (intensity << 8) | intensity;
|
||||||
|
@ -242,11 +227,10 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
|
|
||||||
case PICA::TextureFmt::IA8: {
|
case PICA::TextureFmt::IA8: {
|
||||||
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
u32 offset = getSwizzledOffset(u, v, size.u(), 2);
|
||||||
auto ptr = static_cast<const u8*>(data);
|
|
||||||
|
|
||||||
// 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 = ptr[offset];
|
const u8 alpha = data[offset];
|
||||||
const u8 intensity = ptr[offset + 1];
|
const u8 intensity = data[offset + 1];
|
||||||
return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity;
|
return (alpha << 24) | (intensity << 16) | (intensity << 8) | intensity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,7 +242,7 @@ u32 Texture::decodeTexel(u32 u, u32 v, PICA::TextureFmt fmt, const void* data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Texture::decodeTexture(const void* data) {
|
void Texture::decodeTexture(std::span<const u8> data) {
|
||||||
std::vector<u32> decoded;
|
std::vector<u32> decoded;
|
||||||
decoded.reserve(u64(size.u()) * u64(size.v()));
|
decoded.reserve(u64(size.u()) * u64(size.v()));
|
||||||
|
|
||||||
|
@ -272,4 +256,4 @@ void Texture::decodeTexture(const void* data) {
|
||||||
|
|
||||||
texture.bind();
|
texture.bind();
|
||||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.u(), size.v(), GL_RGBA, GL_UNSIGNED_BYTE, decoded.data());
|
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, size.u(), size.v(), GL_RGBA, GL_UNSIGNED_BYTE, decoded.data());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue