diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 53d4b95739..52603e3cc8 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -28,7 +28,7 @@ // a unique identifier, basically containing all the bits. Yup, it's a lot .... // It would likely be a lot more efficient to build this incrementally as the attributes // are set... -void GetPixelShaderId(PIXELSHADERUID &uid, u32 dstAlphaEnable) +void GetPixelShaderId(PIXELSHADERUID &uid, u32 s_texturemask, u32 dstAlphaEnable) { u32 projtexcoords = 0; for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++) { @@ -51,7 +51,7 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 dstAlphaEnable) for (int i = 0; i < 8; i += 2) ((u8*)&uid.values[1])[i/2] = (bpmem.tevksel[i].hex & 0xf) | ((bpmem.tevksel[i + 1].hex & 0xf) << 4); - uid.values[2] = 0; + uid.values[2] = s_texturemask; uid.values[3] = (u32)bpmem.fog.c_proj_fsel.fsel | ((u32)bpmem.fog.c_proj_fsel.proj << 3); @@ -130,8 +130,8 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 dstAlphaEnable) // output is given by .outreg // tevtemp is set according to swapmodetables and -static void WriteStage(char *&p, int n); -static void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap); +static void WriteStage(char *&p, int n, u32 texture_mask); +static void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, u32 texture_mask); static void WriteAlphaCompare(char *&p, int num, int comp); static bool WriteAlphaTest(char *&p, bool HLSL); static void WriteFog(char *&p); @@ -368,7 +368,7 @@ static void BuildSwapModeTable() } } -const char *GeneratePixelShader(bool dstAlphaEnable, bool HLSL) +const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL) { text[sizeof(text) - 1] = 0x7C; // canary DVSTARTPROFILE(); @@ -391,13 +391,30 @@ const char *GeneratePixelShader(bool dstAlphaEnable, bool HLSL) } } - WRITE(p, "uniform sampler2D "); - bool bfirst = true; - for (int i = 0; i < 8; ++i) { - WRITE(p, "%s samp%d : register(s%d)", bfirst ? "" : ",",i, i); - bfirst = false; + // Declare samplers + if (texture_mask) { + WRITE(p, "uniform samplerRECT "); + bool bfirst = true; + for (int i = 0; i < 8; ++i) { + if (texture_mask & (1<= 7) { WRITE(p, "float4 clipPos = float4(uv0.w, uv1.w, uv2.w, uv3.w);\n"); @@ -512,7 +529,7 @@ const char *GeneratePixelShader(bool dstAlphaEnable, bool HLSL) return text; } -static void WriteStage(char *&p, int n) +static void WriteStage(char *&p, int n, u32 texture_mask) { char *rasswap = swapModeTable[bpmem.combiners[n].alphaC.rswap]; char *texswap = swapModeTable[bpmem.combiners[n].alphaC.tswap]; @@ -612,7 +629,7 @@ static void WriteStage(char *&p, int n) } } - WRITE(p, "rastemp=%s.%s;\n", tevRasTable[bpmem.tevorders[n / 2].getColorChan(n & 1)], rasswap); + WRITE(p, "rastemp=%s.%s;\n", tevRasTable[bpmem.tevorders[n / 2].getColorChan(n & 1)],rasswap); if (bpmem.tevorders[n/2].getEnable(n&1)) { int texmap = bpmem.tevorders[n/2].getTexMap(n&1); @@ -625,7 +642,7 @@ static void WriteStage(char *&p, int n) } } - SampleTexture(p, "textemp", "tevcoord", texswap, texmap); + SampleTexture(p, "textemp", "tevcoord", texswap, texmap, texture_mask); } else WRITE(p, "textemp=float4(1,1,1,1);\n"); @@ -732,9 +749,37 @@ static void WriteStage(char *&p, int n) WRITE(p, "\n"); } -void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap) +void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, u32 texture_mask) { - WRITE(p, "%s=tex2D(samp%d,%s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); + if (texture_mask & (1<> 16) & 0xfff); - fdims[2] = (float)(tc.s.scale_minus_1 + 1) * lastCustomTexScale[texid][0]; - fdims[3] = (float)(tc.t.scale_minus_1 + 1) * lastCustomTexScale[texid][1]; + if (s_texturemask & (1 << texid)) + { + TCoordInfo& tc = bpmem.texcoords[texid]; + fdims[0] = (float)(lastTexDims[texid] & 0xffff); + fdims[1] = (float)((lastTexDims[texid] >> 16) & 0xfff); + fdims[2] = (float)(tc.s.scale_minus_1 + 1)*lastCustomTexScale[texid][0]; + fdims[3] = (float)(tc.t.scale_minus_1 + 1)*lastCustomTexScale[texid][1]; + } + else + { + TCoordInfo& tc = bpmem.texcoords[texid]; + fdims[0] = 1.0f / (float)(lastTexDims[texid] & 0xffff); + fdims[1] = 1.0f / (float)((lastTexDims[texid] >> 16) & 0xfff); + fdims[2] = (float)(tc.s.scale_minus_1 + 1) * lastCustomTexScale[texid][0]; + fdims[3] = (float)(tc.t.scale_minus_1 + 1) * lastCustomTexScale[texid][1]; + } PRIM_LOG("texdims%d: %f %f %f %f\n", texid, fdims[0], fdims[1], fdims[2], fdims[3]); SetPSConstant4fv(C_TEXDIMS + texid, fdims); @@ -312,6 +328,23 @@ void PixelShaderManager::SetZTextureTypeChanged() s_bZTextureTypeChanged = true; } +void PixelShaderManager::SetTexturesUsed(u32 nonpow2tex) +{ + if (s_texturemask != nonpow2tex) + { + for (int i = 0; i < 8; ++i) + { + if (nonpow2tex & (0x10101 << i)) + { + // this check was previously implicit, but should it be here? + if (s_nTexDimsChanged ) + s_nTexDimsChanged |= 1 << i; + } + } + s_texturemask = nonpow2tex; + } +} + void PixelShaderManager::SetTexCoordChanged(u8 texmapid) { s_nTexDimsChanged |= 1 << texmapid; @@ -335,3 +368,8 @@ void PixelShaderManager::SetColorMatrix(const float* pmatrix, const float* pfCon SetPSConstant4fv(C_COLORMATRIX+3, pmatrix+12); SetPSConstant4fv(C_COLORMATRIX+4, pfConstAdd); } + +u32 PixelShaderManager::GetTextureMask() +{ + return s_texturemask; +} diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.h b/Source/Core/VideoCommon/Src/PixelShaderManager.h index bb6933fb2e..858c19a881 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderManager.h +++ b/Source/Core/VideoCommon/Src/PixelShaderManager.h @@ -46,10 +46,12 @@ public: static void SetTevKSelChanged(int id); static void SetZTextureTypeChanged(); static void SetIndTexScaleChanged(u8 stagemask); + static void SetTexturesUsed(u32 nonpow2tex); static void SetTexCoordChanged(u8 texmapid); static void SetFogColorChanged(); static void SetFogParamChanged(); static void SetColorMatrix(const float* pmatrix, const float* pfConstAdd); + static u32 GetTextureMask(); }; diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index 7f5b34c0d2..3208475ddf 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -410,7 +410,7 @@ const char *GenerateVertexShader(u32 components) break; } - if (xfregs.bEnableDualTexTransform && texinfo.texgentype == XF_TEXGEN_REGULAR) { // only works for regular tex gen types? + if(xfregs.bEnableDualTexTransform && texinfo.texgentype == XF_TEXGEN_REGULAR) { // only works for regular tex gen types? if (xfregs.texcoords[i].postmtxinfo.normalize) WRITE(p, "o.tex%d.xyz = normalize(o.tex%d.xyz);\n", i, i); @@ -470,8 +470,7 @@ char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char if (coloralpha == 1 ) swizzle = "xyz"; else if (coloralpha == 2 ) swizzle = "w"; - if (!(chan.attnfunc & 1)) - { + if (!(chan.attnfunc & 1)) { // atten disabled switch (chan.diffusefunc) { case LIGHTDIF_NONE: @@ -486,9 +485,7 @@ char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char default: _assert_(0); } } - else - { - // spec and spot + else { // spec and spot WRITE(p, "ldir = "I_LIGHTS".lights[%d].pos.xyz - pos.xyz;\n", index); if (chan.attnfunc == 3) { // spot diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp index e154fe4878..8093ed401f 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp @@ -67,7 +67,7 @@ void PixelShaderCache::SetShader() DVSTARTPROFILE(); PIXELSHADERUID uid; - GetPixelShaderId(uid, false); + GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), false); PSCache::iterator iter; iter = PixelShaders.find(uid); @@ -85,7 +85,7 @@ void PixelShaderCache::SetShader() } bool HLSL = false; - const char *code = GeneratePixelShader(false, HLSL); + const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(), false, HLSL); LPDIRECT3DPIXELSHADER9 shader = HLSL ? D3D::CompilePixelShader(code, (int)strlen(code), false) : CompileCgShader(code); if (shader) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index b526efb485..f974ccf604 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -198,6 +198,7 @@ void Flush() } } + u32 nonpow2tex = 0; for (int i = 0; i < 8; i++) { if (usedtextures & (1 << i)) { @@ -210,14 +211,25 @@ void Flush() if (tentry) { // texture loaded fine, set dims for pixel shader + if (tentry->isNonPow2) { + 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. - PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); + else + { + PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); + } } else ERROR_LOG(VIDEO, "error loading texture"); } } + PixelShaderManager::SetTexturesUsed(nonpow2tex); + int numVertices = indexGen.GetNumVerts(); if (numVertices) diff --git a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp index 6ff2585750..1b8107696e 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp @@ -145,7 +145,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable) DVSTARTPROFILE(); PIXELSHADERUID uid; u32 dstAlpha = dstAlphaEnable ? 1 : 0; - GetPixelShaderId(uid, dstAlpha); + GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), dstAlpha); PSCache::iterator iter = pshaders.find(uid); @@ -160,7 +160,8 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable) } PSCacheEntry& newentry = pshaders[uid]; - const char *code = GeneratePixelShader(dstAlphaEnable, false); + const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(), + dstAlphaEnable); #if defined(_DEBUG) || defined(DEBUGFAST) if (g_Config.iLog & CONF_SAVESHADERS && code) { diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp index 022343992e..8cd4d0b29f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.cpp @@ -107,20 +107,37 @@ bool TextureMngr::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 rang void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode) { mode = newmode; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, - (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); + if (isRectangle) + { + // very limited! + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, + (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, + (g_Config.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); - if (bHaveMipMaps) { - int filt = newmode.min_filter; - if (g_Config.bForceFiltering && newmode.min_filter < 4) - newmode.min_filter += 4; // take equivalent forced linear - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]); + 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) { + int filt = newmode.min_filter; + if (g_Config.bForceFiltering && newmode.min_filter < 4) + newmode.min_filter += 4; // take equivalent forced linear + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, c_MinLinearFilter[filt]); + } + else + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + (g_Config.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_Config.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) glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_Config.iMaxAnisotropy)); @@ -284,8 +301,9 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash))) { entry.frameCount = frameCount; - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, entry.texture); + 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); if (entry.mode.hex != tm0.hex) entry.SetTextureParameters(tm0); //DebugLog("%cC addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_Config.bSafeTextureCache ? 'S' : 'U' @@ -299,7 +317,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width // Might speed up movie playback very, very slightly. if (width == entry.w && height == entry.h && tex_format == entry.fmt) { - glBindTexture(GL_TEXTURE_2D, entry.texture); + glBindTexture(entry.isRectangle ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture); if (entry.mode.hex != tm0.hex) entry.SetTextureParameters(tm0); skip_texture_create = true; @@ -352,13 +370,19 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width //DebugLog("%c addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_Config.bSafeTextureCache ? 'S' : 'U' // , address, tex_format, entry.hash, width, height); + entry.addr = address; entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format); entry.isRenderTarget = false; + // For static textures, we use NPOT. + 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) { glGenTextures(1, (GLuint *)&entry.texture); - glBindTexture(GL_TEXTURE_2D, entry.texture); + glBindTexture(target, entry.texture); } if (dfmt != PC_TEX_FMT_DXT1) @@ -411,7 +435,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width break; } - if ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2) + if (!entry.isRectangle && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2)) { glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); @@ -420,14 +444,14 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width entry.bHaveMipMaps = true; } else - glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); + glTexImage2D(target, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); if (expandedWidth != width) // reset glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { - glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, + glCompressedTexImage2D(target, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, expandedWidth, expandedHeight, 0, expandedWidth*expandedHeight/2, temp); } @@ -444,7 +468,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width char szDir[MAX_PATH]; bool bCheckedDumpDir = false; - sprintf(szDir, "%s/%s", FULL_DUMP_TEXTURES_DIR,((struct SConfig *)globals->config)->m_LocalCoreStartupParameter.GetUniqueID().c_str()); + sprintf(szDir,"%s/%s",FULL_DUMP_TEXTURES_DIR,((struct SConfig *)globals->config)->m_LocalCoreStartupParameter.GetUniqueID().c_str()); if(!bCheckedDumpDir) { @@ -454,10 +478,10 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width bCheckedDumpDir = true; } - sprintf(szTemp, "%s/%s_%08x_%i.tga", szDir, ((struct SConfig *)globals->config)->m_LocalCoreStartupParameter.GetUniqueID().c_str(), texHash, tex_format); + sprintf(szTemp, "%s/%s_%08x_%i.tga",szDir, ((struct SConfig *)globals->config)->m_LocalCoreStartupParameter.GetUniqueID().c_str(), texHash, tex_format); if (!File::Exists(szTemp)) { - SaveTexture(szTemp, GL_TEXTURE_2D, entry.texture, expandedWidth, expandedHeight); + SaveTexture(szTemp, target, entry.texture, expandedWidth, expandedHeight); } } @@ -484,7 +508,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool bool bIsInit = textures.find(address) != textures.end(); PRIM_LOG("copytarg: addr=0x%x, fromz=%d, intfmt=%d, copyfmt=%d", address, (int)bFromZBuffer, (int)bIsIntensityFmt,copyfmt); - + TCacheEntry& entry = textures[address]; entry.hash = 0; entry.hashoffset = 0; @@ -499,52 +523,48 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool if (!bIsInit) { glGenTextures(1, (GLuint *)&entry.texture); - glBindTexture(GL_TEXTURE_2D, entry.texture); - glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); GL_REPORT_ERRORD(); } else { _assert_(entry.texture); - bool bReInit = true; GL_REPORT_ERROR(); - if (entry.w == w && entry.h == h) + if (entry.w == w && entry.h == h && entry.isRectangle) { - glBindTexture(GL_TEXTURE_2D, entry.texture); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); // for some reason mario sunshine errors here... // Beyond Good and Evil does too, occasionally. - GLenum err = GL_REPORT_ERROR(); - if (err == GL_NO_ERROR) - bReInit = false; - } - - if (bReInit) - { - // necessary, for some reason opengl gives errors when texture isn't deleted + GL_REPORT_ERROR(); + } else { + // Delete existing texture. glDeleteTextures(1,(GLuint *)&entry.texture); glGenTextures(1, (GLuint *)&entry.texture); - glBindTexture(GL_TEXTURE_2D, entry.texture); - glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); GL_REPORT_ERRORD(); } } + if (!bIsInit || !entry.isRenderTarget) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); if (glGetError() != GL_NO_ERROR) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP); GL_REPORT_ERRORD(); } } entry.w = w; entry.h = h; + entry.isRectangle = true; entry.isRenderTarget = true; entry.fmt = copyfmt; @@ -602,7 +622,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool if (copyfmt < 2) { - // ???? fConstAdd[3] = 16.0f / 255.0f; colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f; } @@ -675,7 +694,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool Renderer::SetFramebuffer(s_TempFramebuffer); // Bind texture to temporary framebuffer - glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, entry.texture, 0); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, entry.texture, 0); GL_REPORT_FBO_ERROR(); GL_REPORT_ERRORD(); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.h b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.h index 6a1e29791b..0997f1c5fe 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/TextureMngr.h @@ -29,7 +29,7 @@ class TextureMngr public: struct TCacheEntry { - TCacheEntry() : texture(0), addr(0), size_in_bytes(0), hash(0), w(0), h(0), scaleX(1.0f), scaleY(1.0f), isRenderTarget(false), isUpsideDown(false), bHaveMipMaps(false) { mode.hex = 0xFCFCFCFC; } + TCacheEntry() : texture(0), addr(0), size_in_bytes(0), hash(0), w(0), h(0), scaleX(1.0f), scaleY(1.0f), isRenderTarget(false), isUpsideDown(false), isRectangle(true), bHaveMipMaps(false) { mode.hex = 0xFCFCFCFC; } GLuint texture; u32 addr; @@ -48,6 +48,7 @@ public: 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 bool isUpsideDown; + bool isRectangle; // if nonpow2, use GL_TEXTURE_2D, else GL_TEXTURE_RECTANGLE_NV bool bHaveMipMaps; void SetTextureParameters(TexMode0& newmode); diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index a988aced0a..b49c1f5ef0 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -207,6 +207,7 @@ void Flush() if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); + u32 nonpow2tex = 0; for (int i = 0; i < 8; i++) { if (usedtextures & (1 << i)) @@ -220,9 +221,21 @@ void Flush() if (tentry != NULL) { - // 0s are probably for no manual wrapping needed. - PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); - + // texture loaded fine, set dims for pixel shader + if (tentry->isRectangle) + { + 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); @@ -231,7 +244,7 @@ void Flush() // save the textures char strfile[255]; sprintf(strfile, "%sframes/tex%.3d_%d.tga", FULL_DUMP_DIR, g_Config.iSaveTargetId, i); - SaveTexture(strfile, GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h); + SaveTexture(strfile, tentry->isRectangle?GL_TEXTURE_RECTANGLE_ARB:GL_TEXTURE_2D, tentry->texture, tentry->w, tentry->h); } } else @@ -239,6 +252,8 @@ void Flush() } } + PixelShaderManager::SetTexturesUsed(nonpow2tex); + FRAGMENTSHADER* ps = PixelShaderCache::GetShader(false); VERTEXSHADER* vs = VertexShaderCache::GetShader(g_nativeVertexFmt->m_components);