summaryrefslogtreecommitdiff
path: root/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp')
-rw-r--r--Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp163
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();