diff options
Diffstat (limited to 'Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp')
| -rw-r--r-- | Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp | 163 |
1 files changed, 159 insertions, 4 deletions
diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index 0552cefcf2..bea1631ea1 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -133,7 +133,7 @@ void TextureCache::Cleanup() } } -TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, int height, int tex_format, int tlutaddr, int tlutfmt) +/*TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, int height, int tex_format, int tlutaddr, int tlutfmt) { if (address == 0) return NULL; @@ -203,6 +203,162 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, } } + //PC_TexFormat pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, tex_format, tlutaddr, tlutfmt); + PC_TexFormat pcfmt = GetPC_TexFormat(tex_format, tlutfmt); + + D3DFORMAT d3d_fmt; + switch (pcfmt) { + case PC_TEX_FMT_BGRA32: + case PC_TEX_FMT_RGBA32: + d3d_fmt = D3DFMT_A8R8G8B8; + break; + case PC_TEX_FMT_RGB565: + d3d_fmt = D3DFMT_R5G6B5; + break; + case PC_TEX_FMT_IA4_AS_IA8: + d3d_fmt = D3DFMT_A8L8; + break; + case PC_TEX_FMT_I8: + case PC_TEX_FMT_I4_AS_I8: + d3d_fmt = D3DFMT_A8L8; + break; + case PC_TEX_FMT_IA8: + d3d_fmt = D3DFMT_A8L8; + break; + case PC_TEX_FMT_DXT1: + d3d_fmt = D3DFMT_DXT1; + break; + } + + //Make an entry in the table + TCacheEntry& entry = textures[texID]; + + entry.oldpixel = ((u32 *)ptr)[0]; + if (g_ActiveConfig.bSafeTextureCache) + entry.hash = hash_value; + else + { + entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); + ((u32 *)ptr)[0] = entry.hash; + } + + entry.addr = address; + entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format); + entry.isRenderTarget = false; + entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1))); + if (!skip_texture_create) { + entry.texture = D3D::CreateOnlyTexture2D(width, height, d3d_fmt); + } + D3DLOCKED_RECT Lock; + entry.texture->LockRect(0, &Lock, NULL, 0); + TexDecoder_DirectDecode((u8*)Lock.pBits,ptr,expandedWidth,height,Lock.Pitch,tex_format,tlutaddr,tlutfmt); + entry.texture->UnlockRect(0); + entry.frameCount = frameCount; + entry.w = width; + entry.h = height; + entry.fmt = tex_format; + + if (g_ActiveConfig.bDumpTextures) + { + // dump texture to file + char szTemp[MAX_PATH]; + char szDir[MAX_PATH]; + const char* uniqueId = globals->unique_id; + bool bCheckedDumpDir = false; + sprintf(szDir, "%s/%s", FULL_DUMP_TEXTURES_DIR, uniqueId); + if (!bCheckedDumpDir) + { + if (!File::Exists(szDir) || !File::IsDirectory(szDir)) + File::CreateDir(szDir); + + bCheckedDumpDir = true; + } + sprintf(szTemp, "%s/%s_%08x_%i.png", szDir, uniqueId, texHash, tex_format); + //sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format); <-- Old method + if (!File::Exists(szTemp)) + D3DXSaveTextureToFileA(szTemp,D3DXIFF_BMP,entry.texture,0); + } + + INCSTAT(stats.numTexturesCreated); + SETSTAT(stats.numTexturesAlive, (int)textures.size()); + + //Set the texture! + D3D::SetTexture(stage, entry.texture); + + DEBUGGER_PAUSE_LOG_AT(NEXT_NEW_TEXTURE,true,{printf("A new texture (%d x %d) is loaded", width, height);}); + return &entry; +}*/ + +TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, int height, int tex_format, int tlutaddr, int tlutfmt) +{ + if (address == 0) + return NULL; + + u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address); + int bsw = TexDecoder_GetBlockWidthInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16; + int bsh = TexDecoder_GetBlockHeightInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16; + int expandedWidth = (width + bsw) & (~bsw); + int expandedHeight = (height + bsh) & (~bsh); + + u32 hash_value; + u32 texID = address; + u32 texHash; + + if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bDumpTextures) + { + texHash = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, expandedHeight, tex_format, 0); + if (g_ActiveConfig.bSafeTextureCache) + hash_value = texHash; + if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2)) + { + // WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up) + // tlut size can be up to 32768B (GX_TF_C14X2) but Safer == Slower. + // This trick (to change the texID depending on the TLUT addr) is a trick to get around + // an issue with metroid prime's fonts, where it has multiple sets of fonts on top of + // each other stored in a single texture, and uses the palette to make different characters + // visible or invisible. Thus, unless we want to recreate the textures for every drawn character, + // we must make sure that texture with different tluts get different IDs. + u32 tlutHash = TexDecoder_GetTlutHash(&texMem[tlutaddr], (tex_format == GX_TF_C4) ? 32 : 128); + texHash ^= tlutHash; + if (g_ActiveConfig.bSafeTextureCache) + texID ^= tlutHash; + } + } + + bool skip_texture_create = false; + TexCache::iterator iter = textures.find(texID); + + if (iter != textures.end()) + { + TCacheEntry &entry = iter->second; + + if (!g_ActiveConfig.bSafeTextureCache) + hash_value = ((u32 *)ptr)[0]; + + if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash))) + { + entry.frameCount = frameCount; + D3D::SetTexture(stage, entry.texture); + return &entry; + } + else + { + // Let's reload the new texture data into the same texture, + // instead of destroying it and having to create a new one. + // Might speed up movie playback very, very slightly. + + if (width == entry.w && height==entry.h &&(tex_format | (tlutfmt << 16)) == entry.fmt) + { + skip_texture_create = true; + } + else + { + entry.Destroy(false); + textures.erase(iter); + } + } + } + PC_TexFormat pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, tex_format, tlutaddr, tlutfmt); D3DFORMAT d3d_fmt; @@ -255,7 +411,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, entry.frameCount = frameCount; entry.w = width; entry.h = height; - entry.fmt = tex_format; + entry.fmt = tex_format | (tlutfmt << 16); if (g_ActiveConfig.bDumpTextures) { @@ -286,8 +442,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, DEBUGGER_PAUSE_LOG_AT(NEXT_NEW_TEXTURE,true,{printf("A new texture (%d x %d) is loaded", width, height);}); return &entry; -} - +} void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bIsIntensityFmt, u32 copyfmt, int bScaleByHalf, const EFBRectangle &source_rect) { int efb_w = source_rect.GetWidth(); |
