Fix EFB Scaled Copy in OpenGL plugin.

It no longer uses the TEXTURE_RECTANGLE extension for GameCube textures. Since GameCube always uses normalized texture coordinates, it's an unnecessary burden.

Please test hi-res textures.

Wow, it's been a while.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6144 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Nolan Check 2010-08-29 04:56:53 +00:00
parent 4e81cb4012
commit e1d1a1eba0
3 changed files with 44 additions and 92 deletions

View File

@ -109,42 +109,26 @@ void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode,TexMode1 &
{ {
mode = newmode; mode = newmode;
mode1 = newmode1; mode1 = newmode1;
if (isRectangle)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
if (bHaveMipMaps)
{ {
// very limited! if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, mode.min_filter += 4; // take equivalent forced linear
(newmode.mag_filter || g_ActiveConfig.bForceFiltering) ? GL_LINEAR : GL_NEAREST); int filt = newmode.min_filter;
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/32.0f));
if (newmode.wrap_s == 2 || newmode.wrap_t == 2)
DEBUG_LOG(VIDEO, "cannot support mirrorred repeat mode");
if (newmode.wrap_s == 1 || newmode.wrap_t == 1)
DEBUG_LOG(VIDEO, "cannot support repeat mode");
}
else
{
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
if (bHaveMipMaps)
{
if (g_ActiveConfig.bForceFiltering && newmode.min_filter < 4)
mode.min_filter += 4; // take equivalent forced linear
int filt = newmode.min_filter;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt & 7]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, newmode1.min_lod >> 4);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, newmode1.max_lod >> 4);
glTexEnvf(GL_TEXTURE_FILTER_CONTROL, GL_TEXTURE_LOD_BIAS, (newmode.lod_bias/32.0f));
}
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
} }
else
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
(g_ActiveConfig.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, c_WrapSettings[newmode.wrap_s]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]);
if (g_Config.iMaxAnisotropy >= 1) if (g_Config.iMaxAnisotropy >= 1)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy)); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_ActiveConfig.iMaxAnisotropy));
@ -355,8 +339,8 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
|| ((address == entry.addr) && (hash_value == entry.hash) && ((int) FullFormat == entry.fmt) && entry.MipLevels >= maxlevel)) || ((address == entry.addr) && (hash_value == entry.hash) && ((int) FullFormat == entry.fmt) && entry.MipLevels >= maxlevel))
{ {
entry.frameCount = frameCount; entry.frameCount = frameCount;
glEnable(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
entry.SetTextureParameters(tm0,tm1); entry.SetTextureParameters(tm0,tm1);
entry.isDynamic = false; entry.isDynamic = false;
@ -369,10 +353,9 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
// Might speed up movie playback very, very slightly. // Might speed up movie playback very, very slightly.
TextureisDynamic = (entry.isRenderTarget || entry.isDynamic) && !g_ActiveConfig.bCopyEFBToTexture; TextureisDynamic = (entry.isRenderTarget || entry.isDynamic) && !g_ActiveConfig.bCopyEFBToTexture;
if (((!(entry.isRenderTarget || entry.isDynamic) && width == entry.w && height == entry.h && (int)FullFormat == entry.fmt) || if (((!(entry.isRenderTarget || entry.isDynamic) && width == entry.w && height == entry.h && (int)FullFormat == entry.fmt) ||
((entry.isRenderTarget || entry.isDynamic) && entry.w == width && entry.h == height && entry.Scaledw == width && entry.Scaledh == height)) ((entry.isRenderTarget || entry.isDynamic) && entry.w == width && entry.h == height && entry.Scaledw == width && entry.Scaledh == height)))
&& !entry.isRectangle)
{ {
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
entry.SetTextureParameters(tm0,tm1); entry.SetTextureParameters(tm0,tm1);
skip_texture_create = true; skip_texture_create = true;
@ -405,15 +388,8 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
{ {
expandedWidth = width; expandedWidth = width;
expandedHeight = height; expandedHeight = height;
entry.scaleX = (float) width / oldWidth;
entry.scaleY = (float) height / oldHeight;
} }
} }
else
{
entry.scaleX = 1.0f;
entry.scaleY = 1.0f;
}
if (dfmt == PC_TEX_FMT_NONE) if (dfmt == PC_TEX_FMT_NONE)
dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt); dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
@ -431,11 +407,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
entry.addr = address; entry.addr = address;
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format); entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format);
// For static textures, we use NPOT. GLenum target = GL_TEXTURE_2D;
entry.isRectangle = false;
// old code: entry.isRectangle = ((width & (width - 1)) || (height & (height - 1)));
GLenum target = entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D;
if (!skip_texture_create) { if (!skip_texture_create) {
glGenTextures(1, (GLuint *)&entry.texture); glGenTextures(1, (GLuint *)&entry.texture);
glBindTexture(target, entry.texture); glBindTexture(target, entry.texture);
@ -749,9 +721,9 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
if (!bIsInit) if (!bIsInit)
{ {
glGenTextures(1, (GLuint *)&entry.texture); glGenTextures(1, (GLuint *)&entry.texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, gl_iformat, Scaledtex_w, Scaledtex_h, 0, gl_format, gl_type, NULL); glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, Scaledtex_w, Scaledtex_h, 0, gl_format, gl_type, NULL);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
entry.isRenderTarget = true; entry.isRenderTarget = true;
entry.isDynamic = false; entry.isDynamic = false;
@ -767,7 +739,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
} }
if (((entry.isRenderTarget || entry.isDynamic) && entry.Scaledw == Scaledtex_w && entry.Scaledh == Scaledtex_h)) if (((entry.isRenderTarget || entry.isDynamic) && entry.Scaledw == Scaledtex_w && entry.Scaledh == Scaledtex_h))
{ {
glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
// for some reason mario sunshine errors here... // for some reason mario sunshine errors here...
// Beyond Good and Evil does too, occasionally. // Beyond Good and Evil does too, occasionally.
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
@ -775,8 +747,8 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
// Delete existing texture. // Delete existing texture.
glDeleteTextures(1,(GLuint *)&entry.texture); glDeleteTextures(1,(GLuint *)&entry.texture);
glGenTextures(1, (GLuint *)&entry.texture); glGenTextures(1, (GLuint *)&entry.texture);
glBindTexture(entry.isDynamic ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
glTexImage2D(entry.isDynamic ? GL_TEXTURE_2D : GL_TEXTURE_RECTANGLE_ARB, 0, gl_iformat, Scaledtex_w, Scaledtex_h, 0, gl_format, gl_type, NULL); glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, Scaledtex_w, Scaledtex_h, 0, gl_format, gl_type, NULL);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
entry.isRenderTarget = !entry.isDynamic; entry.isRenderTarget = !entry.isDynamic;
} }
@ -784,14 +756,14 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
if (!bIsInit) if (!bIsInit)
{ {
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if (GL_REPORT_ERROR() != GL_NO_ERROR) { if (GL_REPORT_ERROR() != GL_NO_ERROR) {
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
} }
@ -801,9 +773,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
entry.h = h; entry.h = h;
entry.Scaledw = Scaledtex_w; entry.Scaledw = Scaledtex_w;
entry.Scaledh = Scaledtex_h; entry.Scaledh = Scaledtex_h;
entry.isRectangle = !entry.isDynamic;
entry.scaleX = (g_ActiveConfig.bCopyEFBScaled && !entry.isDynamic) ? xScale : 1.0f;
entry.scaleY = (g_ActiveConfig.bCopyEFBScaled && !entry.isDynamic) ? yScale : 1.0f;
entry.fmt = copyfmt; entry.fmt = copyfmt;
entry.hash = 0; entry.hash = 0;
@ -821,7 +790,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
g_framebufferManager.SetFramebuffer(s_TempFramebuffer); g_framebufferManager.SetFramebuffer(s_TempFramebuffer);
// Bind texture to temporary framebuffer // Bind texture to temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, entry.texture, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, entry.texture, 0);
GL_REPORT_FBO_ERROR(); GL_REPORT_FBO_ERROR();
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
@ -848,7 +817,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// Unbind texture from temporary framebuffer // Unbind texture from temporary framebuffer
glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, 0, 0); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, 0, 0);
} }
if(!g_ActiveConfig.bCopyEFBToTexture) if(!g_ActiveConfig.bCopyEFBToTexture)
@ -876,7 +845,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
if (g_ActiveConfig.bDumpEFBTarget) if (g_ActiveConfig.bDumpEFBTarget)
{ {
static int count = 0; static int count = 0;
SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX), count++).c_str(), GL_TEXTURE_RECTANGLE_ARB, entry.texture, entry.w, entry.h); SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX), count++).c_str(), GL_TEXTURE_2D, entry.texture, entry.w, entry.h);
} }
} }

View File

@ -29,10 +29,10 @@ class TextureMngr
public: public:
struct TCacheEntry struct TCacheEntry
{ {
TCacheEntry() : texture(0), addr(0), size_in_bytes(0), hash(0), TCacheEntry() : texture(0), addr(0), size_in_bytes(0), hash(0),
w(0), h(0), MipLevels(0),Scaledw(0), Scaledh(0), scaleX(1.0f), scaleY(1.0f), w(0), h(0), MipLevels(0),Scaledw(0), Scaledh(0),
isRenderTarget(false), isDynamic(false), isRectangle(true), isRenderTarget(false), isDynamic(false), bHaveMipMaps(false)
bHaveMipMaps(false) { mode.hex = 0xFCFCFCFC; } { mode.hex = 0xFCFCFCFC; }
GLuint texture; GLuint texture;
u32 addr; u32 addr;
@ -46,12 +46,10 @@ public:
int frameCount; int frameCount;
int w, h, fmt,MipLevels; int w, h, fmt,MipLevels;
int Scaledw, Scaledh; int Scaledw, Scaledh;
float scaleX, scaleY; // Hires texutres need this
bool isRenderTarget; // if render texture, then rendertex is filled with the direct copy of the render target bool isRenderTarget; // if render texture, then rendertex is filled with the direct copy of the render target
// later conversions would have to convert properly from rendertexfmt to texfmt // later conversions would have to convert properly from rendertexfmt to texfmt
bool isDynamic; // modified from cpu bool isDynamic; // modified from cpu
bool isRectangle; // if nonpow2, use GL_TEXTURE_2D, else GL_TEXTURE_RECTANGLE_NV
bool bHaveMipMaps; bool bHaveMipMaps;
void SetTextureParameters(TexMode0& newmode,TexMode1 &newmode1); void SetTextureParameters(TexMode0& newmode,TexMode1 &newmode1);

View File

@ -274,30 +274,15 @@ void Flush()
if (tentry) if (tentry)
{ {
// texture loaded fine, set dims for pixel shader // 0s are probably for no manual wrapping needed.
if (tentry->isRectangle) PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
{
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, tentry->mode.wrap_s, tentry->mode.wrap_t);
nonpow2tex |= 1 << i;
if (tentry->mode.wrap_s > 0) nonpow2tex |= 1 << (8 + i);
if (tentry->mode.wrap_t > 0) nonpow2tex |= 1 << (16 + i);
}
// if texture is power of two, set to ones (since don't need scaling)
// (the above seems to have changed - we set the width and height here too.
else
{
// 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
}
// texture is hires - pass the scaling size
if (tentry->scaleX != 1.0f || tentry->scaleY != 1.0f)
PixelShaderManager::SetCustomTexScale(i, tentry->scaleX, tentry->scaleY);
if (g_ActiveConfig.iLog & CONF_SAVETEXTURES) if (g_ActiveConfig.iLog & CONF_SAVETEXTURES)
{ {
// save the textures // save the textures
char strfile[255]; char strfile[255];
sprintf(strfile, "%stex%.3d_%d.tga", File::GetUserPath(D_DUMPFRAMES_IDX), g_Config.iSaveTargetId, i); sprintf(strfile, "%stex%.3d_%d.tga", File::GetUserPath(D_DUMPFRAMES_IDX), g_Config.iSaveTargetId, i);
SaveTexture(strfile, tentry->isRectangle?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h); SaveTexture(strfile, GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h);
} }
} }
else else