diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.cpp b/Source/Core/VideoCommon/Src/TextureDecoder.cpp index 4ca645caaf..e934997dd7 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/TextureDecoder.cpp @@ -323,6 +323,19 @@ void decodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch) } } +static void copyDXTBlock(u8* dst, const u8* src) +{ + ((u16*)dst)[0] = Common::swap16(((u16*)src)[0]); + ((u16*)dst)[1] = Common::swap16(((u16*)src)[1]); + u32 pixels = ((u32*)src)[1]; + // A bit of trickiness here: the row are in the same order + // between the two formats, but the ordering within the rows + // is reversed. + pixels = ((pixels >> 4) & 0x0F0F0F0F) | ((pixels << 4) & 0xF0F0F0F0); + pixels = ((pixels >> 2) & 0x33333333) | ((pixels << 2) & 0xCCCCCCCC); + ((u32*)dst)[1] = pixels; +} + //switch endianness, unswizzle //TODO: to save memory, don't blindly convert everything to argb8888 @@ -439,24 +452,20 @@ PC_TexFormat TexDecoder_Decode_real(u8 *dst, const u8 *src, int width, int heigh return PC_TEX_FMT_BGRA32; case GX_TF_CMPR: // speed critical { - // TODO: Shuffle to PC S3TC (DXTC) format instead of converting - // 11111111 22222222 55555555 66666666 - // 33333333 44444444 77777777 88888888 - // The metroid games use this format almost exclusively. for (int y = 0; y < height; y += 8) for (int x = 0; x < width; x += 8) { - decodeDXTBlock((u32*)dst+y*width+x, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlock((u32*)dst+y*width+x+4, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlock((u32*)dst+(y+4)*width+x, (DXTBlock*)src, width); - src += sizeof(DXTBlock); - decodeDXTBlock((u32*)dst+(y+4)*width+x+4, (DXTBlock*)src, width); - src += sizeof(DXTBlock); + copyDXTBlock(dst+(y/2)*width+x*2, src); + src += 8; + copyDXTBlock(dst+(y/2)*width+x*2+8, src); + src += 8; + copyDXTBlock(dst+(y/2+2)*width+x*2, src); + src += 8; + copyDXTBlock(dst+(y/2+2)*width+x*2+8, src); + src += 8; } } - return PC_TEX_FMT_BGRA32; + return PC_TEX_FMT_DXT1; } // The "copy" texture formats, too? diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index 35204cbfc5..63b1d21001 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -366,46 +366,62 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width if (expandedWidth != width) glPixelStorei(GL_UNPACK_ROW_LENGTH, expandedWidth); - int gl_format; - int gl_iformat; - int gl_type; - switch (dfmt) + if (dfmt != PC_TEX_FMT_DXT1) { - default: - case PC_TEX_FMT_NONE: - PanicAlert("Invalid PC texture format %i", dfmt); - case PC_TEX_FMT_BGRA32: - gl_format = GL_BGRA; - gl_iformat = 4; - gl_type = GL_UNSIGNED_BYTE; - break; - case PC_TEX_FMT_I8: - gl_format = GL_LUMINANCE; - gl_iformat = GL_INTENSITY; - gl_type = GL_UNSIGNED_BYTE; - break; - case PC_TEX_FMT_IA8: - gl_format = GL_LUMINANCE_ALPHA; - gl_iformat = GL_LUMINANCE8_ALPHA8; - gl_type = GL_UNSIGNED_BYTE; - break; - case PC_TEX_FMT_RGB565: - gl_format = GL_RGB; - gl_iformat = GL_RGB; - gl_type = GL_UNSIGNED_SHORT_5_6_5; - break; - } + int gl_format; + int gl_iformat; + int gl_type; + switch (dfmt) + { + default: + case PC_TEX_FMT_NONE: + PanicAlert("Invalid PC texture format %i", dfmt); + case PC_TEX_FMT_BGRA32: + gl_format = GL_BGRA; + gl_iformat = 4; + gl_type = GL_UNSIGNED_BYTE; + break; + case PC_TEX_FMT_I8: + gl_format = GL_LUMINANCE; + gl_iformat = GL_INTENSITY; + gl_type = GL_UNSIGNED_BYTE; + break; + case PC_TEX_FMT_IA8: + gl_format = GL_LUMINANCE_ALPHA; + gl_iformat = GL_LUMINANCE8_ALPHA8; + gl_type = GL_UNSIGNED_BYTE; + break; + case PC_TEX_FMT_RGB565: + gl_format = GL_RGB; + gl_iformat = GL_RGB; + gl_type = GL_UNSIGNED_SHORT_5_6_5; + break; + } - if (!entry.isNonPow2 && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2)) - { - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); - glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); + if (!entry.isNonPow2 && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2)) + { + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); - glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); - entry.bHaveMipMaps = true; + glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_FALSE); + entry.bHaveMipMaps = true; + } + else + glTexImage2D(target, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); } else - glTexImage2D(target, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); + { + // Round dimensions up to the next multiple of 4; this is an OpenGL + // requirement. + // FIXME: Why does the GameCube have compressed textures that aren't + // multiples of 4, and what is the best way to handle them? + // An example is in SSB Melee's Adventure Mode on the Paratroopas' + // wings. + int nativeWidth = (width + 3) & ~3; + int nativeHeight = (height + 3) & ~3; + glCompressedTexImage2D(target, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + nativeWidth, nativeHeight, 0, nativeWidth*nativeHeight/2, temp); + } if (expandedWidth != width) // reset glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);