ok big changes here:

in videocommon little fix for the alpha test values, return to the original values as they are more accurate.
in D3D:
huge change in state management, now all the state management is centralized and redundant state changes are eliminated.
Fixed the overlapped viewport error in non ati cards:
the error was caused by this: when a viewport is defined larger than the current rendertarget, an error is thrown and the last valid viewport is used, this is the reference behavior, in ati cards if a larger viewport is defined, no eror is returned, the rendering is valid and is rendered using the projection defined by the viewport but limited to the rendertarget are, exactly like opengl or the GC hardware.
to solve this in reference drivers defined a large rendertarget (2x the size of the original) and proceed to render in a centered quad insithe the larger rendertarget, in this way larger viewports always falls inside a valid rendertarget size, the drawback of this is the waste of resources. it can be dynamized, depending or games or changed at runtime when a oversized viewport is detected, but i live that to future commits.
please test this and let me know the results.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4841 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado
2010-01-15 15:52:08 +00:00
parent c7e055d1f5
commit 8de76f8fe8
14 changed files with 624 additions and 341 deletions

View File

@ -136,162 +136,159 @@ void TextureCache::Cleanup()
}
}
/*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 == 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);
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);
if(pcfmt != PC_TEX_FMT_I8 && pcfmt != PC_TEX_FMT_I4_AS_I8)
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);
// 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.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,D3DLOCK_DISCARD);
// TexDecoder_DirectDecode((u8*)Lock.pBits,ptr,expandedWidth,height,Lock.Pitch,tex_format,tlutaddr,tlutfmt);
// entry.texture->UnlockRect(0);
// 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.frameCount = frameCount;
// entry.w = width;
// entry.h = height;
// entry.fmt = tex_format | (tlutfmt << 16);
//
// 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)
{
@ -427,7 +424,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
entry.addr = address;
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format);
entry.isRenderTarget = false;
entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1)));
entry.isNonPow2 = false;//((width & (width - 1)) || (height & (height - 1)));
if (!skip_texture_create) {
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
} else {
@ -496,7 +493,8 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
else
{
// Remove it and recreate it as a render target
iter->second.texture->Release();
if(iter->second.texture)
iter->second.texture->Release();
iter->second.texture = 0;
textures.erase(iter);
}
@ -512,7 +510,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, boo
entry.Scaledw = Scaledtex_w;
entry.Scaledh = Scaledtex_h;
entry.fmt = copyfmt;
entry.isNonPow2 = true;
D3D::dev->CreateTexture(Scaledtex_w, Scaledtex_h, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &entry.texture, 0);
textures[address] = entry;
tex = entry.texture;
@ -663,19 +661,18 @@ have_texture:
if(bScaleByHalf)
{
D3D::dev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::dev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
else
{
D3D::dev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
D3D::dev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
D3D::ChangeSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
D3D::ChangeSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
}
D3DFORMAT bformat = FBManager::GetEFBDepthRTSurfaceFormat();
D3D::drawShadedTexQuad(read_texture,&sourcerect, Renderer::GetTargetWidth() , Renderer::GetTargetHeight(),&destrect,((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer)? PixelShaderCache::GetDepthMatrixProgram(): PixelShaderCache::GetColorMatrixProgram(),VertexShaderCache::GetSimpleVertexShader());
D3D::drawShadedTexQuad(read_texture,&sourcerect, Renderer::GetFullTargetWidth() , Renderer::GetFullTargetHeight(),&destrect,((bformat != FOURCC_RAWZ && bformat != D3DFMT_D24X8) && bFromZBuffer)? PixelShaderCache::GetDepthMatrixProgram(): PixelShaderCache::GetColorMatrixProgram(),VertexShaderCache::GetSimpleVertexShader());
D3D::RefreshSamplerState(0, D3DSAMP_MINFILTER);
D3D::RefreshSamplerState(0, D3DSAMP_MAGFILTER);