hopefully fixed zww issue with new efb to ram.

implemented new efb to ram in opengl
modified TextureConversionShader preparing the implementation of new efb to ram in dx11
please test for regressions

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5874 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado
2010-07-12 19:30:25 +00:00
parent dcc51e0ef8
commit 9cb41e7c70
11 changed files with 445 additions and 287 deletions

View File

@ -52,6 +52,7 @@
#include "FramebufferManager.h"
#include "FileUtil.h"
#include "HiresTextures.h"
#include "TextureConverter.h"
u8 *TextureMngr::temp = NULL;
TextureMngr::TexCache TextureMngr::textures;
@ -95,13 +96,13 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int he
return SaveTGA(filename, width, height, &data[0]);
}
bool TextureMngr::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 range_size)
int TextureMngr::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 range_size)
{
if (addr + size_in_bytes < range_address)
return false;
return -1;
if (addr >= range_address + range_size)
return false;
return true;
return 1;
return 0;
}
void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode,TexMode1 &newmode1)
@ -197,14 +198,8 @@ void TextureMngr::ProgressiveCleanup()
{
if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second.frameCount)
{
if (!iter->second.isRenderTarget) {
iter->second.Destroy(false);
textures.erase(iter++);
}
else {
iter->second.Destroy(false);
textures.erase(iter++);
}
iter->second.Destroy(false);
iter = textures.erase(iter);
}
else
++iter;
@ -216,17 +211,34 @@ void TextureMngr::InvalidateRange(u32 start_address, u32 size)
TexCache::iterator iter = textures.begin();
while (iter != textures.end())
{
if (iter->second.IntersectsMemoryRange(start_address, size))
int rangePosition = iter->second.IntersectsMemoryRange(start_address, size);
if (rangePosition == 0)
{
iter->second.Destroy(false);
textures.erase(iter++);
}
else {
++iter;
else
{
++iter;
}
}
}
void TextureMngr::MakeRangeDynamic(u32 start_address, u32 size)
{
TexCache::iterator iter = textures.begin();
while (iter != textures.end())
{
int rangePosition = iter->second.IntersectsMemoryRange(start_address, size);
if ( rangePosition == 0)
{
iter->second.hash = 0;
}
++iter;
}
}
TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width, int height, u32 tex_format, int tlutaddr, int tlutfmt)
{
// notes (about "UNsafe texture cache"):
@ -273,6 +285,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
u32 texID = address;
u64 texHash = 0;
u32 FullFormat = tex_format;
bool TextureIsDinamic = false;
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
FullFormat = (tex_format | (tlutfmt << 16));
if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures)
@ -306,19 +319,47 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
TCacheEntry &entry = iter->second;
if (!g_ActiveConfig.bSafeTextureCache)
hash_value = ((u32 *)ptr)[0];
{
if(entry.isRenderTarget || entry.isDinamic)
{
if(!g_ActiveConfig.bCopyEFBToTexture && g_ActiveConfig.bVerifyTextureModificationsByCPU)
{
hash_value = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
{
hash_value ^= TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
}
}
else
{
hash_value = 0;
}
}
else
{
hash_value = ((u32 *)ptr)[0];
}
}
else
{
if(entry.isRenderTarget || entry.isDinamic)
{
if(g_ActiveConfig.bCopyEFBToTexture || !g_ActiveConfig.bVerifyTextureModificationsByCPU)
{
hash_value = 0;
}
}
}
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash) && ((int) FullFormat == entry.fmt && entry.MipLevels >= maxlevel)))
if (((entry.isRenderTarget || entry.isDinamic) && hash_value == entry.hash && address == entry.addr)
|| ((address == entry.addr) && (hash_value == entry.hash) && ((int) FullFormat == entry.fmt) && entry.MipLevels >= maxlevel))
{
entry.frameCount = frameCount;
glEnable(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D);
// entry.isRectangle ? TextureMngr::EnableTex2D(texstage) : TextureMngr::EnableTexRECT(texstage);
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture);
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD();
//if (entry.mode.hex != tm0.hex || entry.mode1.hex != tm1.hex)//gl needs this refreshed for every texture to work right
entry.SetTextureParameters(tm0,tm1);
//DebugLog("%cC addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_ActiveConfig.bSafeTextureCache ? 'S' : 'U'
// , address, tex_format, entry.hash, width, height);
entry.SetTextureParameters(tm0,tm1);
entry.isDinamic = false;
return &entry;
}
else
@ -326,12 +367,14 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
// 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 && (int) FullFormat == entry.fmt)
{
TextureIsDinamic = (entry.isRenderTarget || entry.isDinamic) && !g_ActiveConfig.bCopyEFBToTexture;
if (!entry.isRenderTarget &&
((!entry.isDinamic && width == entry.w && height==entry.h && FullFormat == entry.fmt)
|| (entry.isDinamic && entry.w == width && entry.h == height)))
{
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD();
//if (entry.mode.hex != tm0.hex || entry.mode1.hex != tm1.hex) //gl needs this refreshed for every texture to work right
entry.SetTextureParameters(tm0,tm1);
entry.SetTextureParameters(tm0,tm1);
skip_texture_create = true;
}
else
@ -344,6 +387,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
//Make an entry in the table
TCacheEntry& entry = textures[texID];
entry.isDinamic = TextureIsDinamic;
PC_TexFormat dfmt = PC_TEX_FMT_NONE;
if (g_ActiveConfig.bHiresTextures)
@ -370,12 +414,12 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
entry.oldpixel = ((u32 *)ptr)[0];
if (g_ActiveConfig.bSafeTextureCache)
if (g_ActiveConfig.bSafeTextureCache || entry.isDinamic)
entry.hash = hash_value;
else
else
{
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
((u32 *)ptr)[0] = entry.hash;
((u32 *)ptr)[0] = entry.hash;
}
entry.addr = address;
@ -575,9 +619,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
// IA4,RA4 - IA4
// Z8M,G8,I8,A8,Z8,R8,B8,Z8L - I8
// Z16,GB8,RG8,Z16L,IA8,RA8 - IA8
GLenum gl_format = GL_RGBA;
GLenum gl_iformat = 4;
GLenum gl_type = GL_UNSIGNED_BYTE;
float colmat[16];
float fConstAdd[4] = {0};
memset(colmat, 0, sizeof(colmat));
@ -688,6 +729,9 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
int w = (abs(source_rect.GetWidth()) >> bScaleByHalf);
int h = (abs(source_rect.GetHeight()) >> bScaleByHalf);
GLenum gl_format = GL_RGBA;
GLenum gl_iformat = 4;
GLenum gl_type = GL_UNSIGNED_BYTE;
GL_REPORT_ERRORD();
@ -699,12 +743,14 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
GL_REPORT_ERRORD();
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_iformat, w, h, 0, gl_format, gl_type, NULL);
GL_REPORT_ERRORD();
entry.isRenderTarget = true;
entry.isDinamic = false;
}
else
{
_assert_(entry.texture);
GL_REPORT_ERRORD();
if (entry.w == w && entry.h == h && entry.isRectangle && entry.fmt == (int) copyfmt)
if (entry.w == w && entry.h == h && entry.isRectangle)
{
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture);
// for some reason mario sunshine errors here...
@ -717,6 +763,8 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_iformat, w, h, 0, gl_format, gl_type, NULL);
GL_REPORT_ERRORD();
entry.isRenderTarget = true;
entry.isDinamic = false;
}
}
@ -737,7 +785,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
entry.w = w;
entry.h = h;
entry.isRectangle = true;
entry.isRenderTarget = true;
entry.fmt = copyfmt;
// Make sure to resolve anything we need to read from.
@ -747,41 +794,57 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
// We have to run a pixel shader, for color conversion.
Renderer::ResetAPIState(); // reset any game specific settings
if(!entry.isDinamic || g_ActiveConfig.bCopyEFBToTexture)
{
if (s_TempFramebuffer == 0)
glGenFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer);
if (s_TempFramebuffer == 0)
glGenFramebuffersEXT(1, (GLuint *)&s_TempFramebuffer);
g_framebufferManager.SetFramebuffer(s_TempFramebuffer);
// Bind texture to temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, entry.texture, 0);
GL_REPORT_FBO_ERROR();
GL_REPORT_ERRORD();
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
glViewport(0, 0, w, h);
g_framebufferManager.SetFramebuffer(s_TempFramebuffer);
// Bind texture to temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, entry.texture, 0);
GL_REPORT_FBO_ERROR();
GL_REPORT_ERRORD();
glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, read_texture);
glViewport(0, 0, w, h);
PixelShaderCache::SetCurrentShader(bFromZBuffer ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
GL_REPORT_ERRORD();
PixelShaderCache::SetCurrentShader(bFromZBuffer ? PixelShaderCache::GetDepthMatrixProgram() : PixelShaderCache::GetColorMatrixProgram());
PixelShaderManager::SetColorMatrix(colmat, fConstAdd); // set transformation
GL_REPORT_ERRORD();
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
TargetRectangle targetSource = Renderer::ConvertEFBRectangle(source_rect);
glBegin(GL_QUADS);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1);
glEnd();
glBegin(GL_QUADS);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.bottom); glVertex2f(-1, 1);
glTexCoord2f((GLfloat)targetSource.left, (GLfloat)targetSource.top ); glVertex2f(-1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.top ); glVertex2f( 1, -1);
glTexCoord2f((GLfloat)targetSource.right, (GLfloat)targetSource.bottom); glVertex2f( 1, 1);
glEnd();
GL_REPORT_ERRORD();
GL_REPORT_ERRORD();
// Unbind texture from temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
// Unbind texture from temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0);
}
if(!g_ActiveConfig.bCopyEFBToTexture)
{
textures[address].hash = TextureConverter::EncodeToRamFromTexture(
address,
read_texture,
Renderer::GetTargetScaleX(),
Renderer::GetTargetScaleY(),
bFromZBuffer,
bIsIntensityFmt,
copyfmt,
bScaleByHalf,
source_rect);
}
// Return to the EFB.
g_framebufferManager.SetFramebuffer(0);
Renderer::RestoreAPIState();