diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.cpp b/Source/Core/VideoCommon/Src/TextureDecoder.cpp index 295577ced7..f094139d27 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/TextureDecoder.cpp @@ -57,6 +57,29 @@ int TexDecoder_GetTexelSizeInNibbles(int format) } } +int TexDecoder_GetTextureSizeInBytes(int width, int height, int format) +{ + return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 4; +} + +u32 TexDecoder_GetSafeTextureHash(const u8 *src, int width, int height, int texformat) +{ + int sz = TexDecoder_GetTextureSizeInBytes(width, height, texformat); + u32 hash = 0x1337c0de; + if (sz < 2048) { + for (int i = 0; i < sz / 4; i += 13) { + hash = _rotl(hash, 17) ^ ((u32 *)src)[i]; + } + return hash; + } else { + int step = sz / 13 / 4; + for (int i = 0; i < sz / 4; i += step) { + hash = _rotl(hash, 17) ^ ((u32 *)src)[i]; + } + } + return hash; +} + int TexDecoder_GetBlockWidthInTexels(int format) { switch (format) { diff --git a/Source/Core/VideoCommon/Src/TextureDecoder.h b/Source/Core/VideoCommon/Src/TextureDecoder.h index 86e07f3da4..bac0cec7a1 100644 --- a/Source/Core/VideoCommon/Src/TextureDecoder.h +++ b/Source/Core/VideoCommon/Src/TextureDecoder.h @@ -65,6 +65,7 @@ enum TextureFormat }; int TexDecoder_GetTexelSizeInNibbles(int format); +int TexDecoder_GetTextureSizeInBytes(int width, int height, int format); int TexDecoder_GetBlockWidthInTexels(int format); int TexDecoder_GetPaletteSize(int fmt); @@ -76,6 +77,8 @@ enum PC_TexFormat PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt); +u32 TexDecoder_GetSafeTextureHash(const u8 *src, int width, int height, int texformat); + void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center); #endif diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index da6b1c2bd3..bb46262cd4 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -217,10 +217,15 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width } } + int bs = TexDecoder_GetBlockWidthInTexels(format) - 1; + int expandedWidth = (width + bs) & (~bs); + if (iter != textures.end()) { TCacheEntry &entry = iter->second; - if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) { //stupid, improve + if (entry.isRenderTarget || + (TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format) == entry.hash && + palhash == entry.paletteHash)) { entry.frameCount = frameCount; //glEnable(entry.isNonPow2?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D); glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, entry.texture); @@ -251,18 +256,15 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width } } - int bs = TexDecoder_GetBlockWidthInTexels(format) - 1; - int expandedWidth = (width + bs) & (~bs); PC_TexFormat dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, format, tlutaddr, tlutfmt); //Make an entry in the table TCacheEntry& entry = textures[address]; - entry.hashoffset = 0; entry.paletteHash = palhash; entry.oldpixel = ((u32 *)ptr)[entry.hashoffset]; if (g_Config.bSafeTextureCache) { - entry.hash = entry.oldpixel; + entry.hash = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format); } else { entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); ((u32 *)ptr)[entry.hashoffset] = entry.hash;