GL: Delete code for GL_TEXTURE_RECTANGLE_ARB in case of non-pow2 textures - all modern GFX cards that can run Dolphin should support non-pow2 textures anyway. This removes some complexity and reduces the numbers of pixel shaders that need to be generated in some situations. Also fixes some texture mirroring problems. Let me know if this breaks things on ATI for some reason.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3833 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard 2009-07-18 11:26:58 +00:00
parent 3a14b31b81
commit 3ad0db6830
11 changed files with 79 additions and 211 deletions

View File

@ -28,7 +28,7 @@
// a unique identifier, basically containing all the bits. Yup, it's a lot .... // 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 // It would likely be a lot more efficient to build this incrementally as the attributes
// are set... // are set...
void GetPixelShaderId(PIXELSHADERUID &uid, u32 s_texturemask, u32 dstAlphaEnable) void GetPixelShaderId(PIXELSHADERUID &uid, u32 dstAlphaEnable)
{ {
u32 projtexcoords = 0; u32 projtexcoords = 0;
for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++) { for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; i++) {
@ -51,7 +51,7 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 s_texturemask, u32 dstAlphaEnable
for (int i = 0; i < 8; i += 2) 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); ((u8*)&uid.values[1])[i/2] = (bpmem.tevksel[i].hex & 0xf) | ((bpmem.tevksel[i + 1].hex & 0xf) << 4);
uid.values[2] = s_texturemask; uid.values[2] = 0;
uid.values[3] = (u32)bpmem.fog.c_proj_fsel.fsel | uid.values[3] = (u32)bpmem.fog.c_proj_fsel.fsel |
((u32)bpmem.fog.c_proj_fsel.proj << 3); ((u32)bpmem.fog.c_proj_fsel.proj << 3);
@ -130,8 +130,8 @@ void GetPixelShaderId(PIXELSHADERUID &uid, u32 s_texturemask, u32 dstAlphaEnable
// output is given by .outreg // output is given by .outreg
// tevtemp is set according to swapmodetables and // tevtemp is set according to swapmodetables and
static void WriteStage(char *&p, int n, u32 texture_mask); static void WriteStage(char *&p, int n);
static void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, u32 texture_mask); static void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap);
static void WriteAlphaCompare(char *&p, int num, int comp); static void WriteAlphaCompare(char *&p, int num, int comp);
static bool WriteAlphaTest(char *&p, bool HLSL); static bool WriteAlphaTest(char *&p, bool HLSL);
static void WriteFog(char *&p); static void WriteFog(char *&p);
@ -368,7 +368,7 @@ static void BuildSwapModeTable()
} }
} }
const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL) const char *GeneratePixelShader(bool dstAlphaEnable, bool HLSL)
{ {
text[sizeof(text) - 1] = 0x7C; // canary text[sizeof(text) - 1] = 0x7C; // canary
DVSTARTPROFILE(); DVSTARTPROFILE();
@ -391,30 +391,13 @@ const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL
} }
} }
// Declare samplers
if (texture_mask) {
WRITE(p, "uniform samplerRECT ");
bool bfirst = true;
for (int i = 0; i < 8; ++i) {
if (texture_mask & (1<<i)) {
WRITE(p, "%s samp%d : register(s%d)", bfirst?"":",", i, i);
bfirst = false;
}
}
WRITE(p, ";\n");
}
if (texture_mask != 0xff) {
WRITE(p, "uniform sampler2D "); WRITE(p, "uniform sampler2D ");
bool bfirst = true; bool bfirst = true;
for (int i = 0; i < 8; ++i) { for (int i = 0; i < 8; ++i) {
if (!(texture_mask & (1<<i))) {
WRITE(p, "%s samp%d : register(s%d)", bfirst ? "" : ",",i, i); WRITE(p, "%s samp%d : register(s%d)", bfirst ? "" : ",",i, i);
bfirst = false; bfirst = false;
} }
}
WRITE(p, ";\n"); WRITE(p, ";\n");
}
WRITE(p, "\n"); WRITE(p, "\n");
@ -476,7 +459,7 @@ const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL
char buffer[32]; char buffer[32];
sprintf(buffer, "float3 indtex%d", i); sprintf(buffer, "float3 indtex%d", i);
SampleTexture(p, buffer, "tempcoord", "abg", bpmem.tevindref.getTexMap(i), texture_mask); SampleTexture(p, buffer, "tempcoord", "abg", bpmem.tevindref.getTexMap(i));
} }
} }
@ -486,7 +469,7 @@ const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL
} }
for (int i = 0; i < numStages; i++) for (int i = 0; i < numStages; i++)
WriteStage(p, i, texture_mask); //build the equation for this stage WriteStage(p, i); //build the equation for this stage
if (numTexgen >= 7) { if (numTexgen >= 7) {
WRITE(p, "float4 clipPos = float4(uv0.w, uv1.w, uv2.w, uv3.w);\n"); WRITE(p, "float4 clipPos = float4(uv0.w, uv1.w, uv2.w, uv3.w);\n");
@ -529,7 +512,7 @@ const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL
return text; return text;
} }
static void WriteStage(char *&p, int n, u32 texture_mask) static void WriteStage(char *&p, int n)
{ {
char *rasswap = swapModeTable[bpmem.combiners[n].alphaC.rswap]; char *rasswap = swapModeTable[bpmem.combiners[n].alphaC.rswap];
char *texswap = swapModeTable[bpmem.combiners[n].alphaC.tswap]; char *texswap = swapModeTable[bpmem.combiners[n].alphaC.tswap];
@ -642,7 +625,7 @@ static void WriteStage(char *&p, int n, u32 texture_mask)
} }
} }
SampleTexture(p, "textemp", "tevcoord", texswap, texmap, texture_mask); SampleTexture(p, "textemp", "tevcoord", texswap, texmap);
} }
else else
WRITE(p, "textemp=float4(1,1,1,1);\n"); WRITE(p, "textemp=float4(1,1,1,1);\n");
@ -749,38 +732,10 @@ static void WriteStage(char *&p, int n, u32 texture_mask)
WRITE(p, "\n"); WRITE(p, "\n");
} }
void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap, u32 texture_mask) void SampleTexture(char *&p, const char *destination, const char *texcoords, const char *texswap, int texmap)
{ {
if (texture_mask & (1<<texmap)) {
// non pow 2
bool bwraps = (texture_mask & (0x100<<texmap)) ? true : false;
bool bwrapt = (texture_mask & (0x10000<<texmap)) ? true : false;
if (bwraps || bwrapt) {
if (bwraps) {
WRITE(p, "tempcoord.x = fmod(%s.x, "I_TEXDIMS"[%d].x);\n", texcoords, texmap);
}
else {
WRITE(p, "tempcoord.x = %s.x;\n", texcoords);
}
if (bwrapt) {
WRITE(p, "tempcoord.y = fmod(%s.y, "I_TEXDIMS"[%d].y);\n", texcoords, texmap);
}
else {
WRITE(p, "tempcoord.y = %s.y;\n", texcoords);
}
WRITE(p, "%s=texRECT(samp%d,tempcoord.xy).%s;\n", destination, texmap, texswap);
}
else {
WRITE(p, "%s=texRECT(samp%d,%s.xy).%s;\n", destination, texmap, texcoords, texswap);
}
}
else {
WRITE(p, "%s=tex2D(samp%d,%s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap); WRITE(p, "%s=tex2D(samp%d,%s.xy * "I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap);
} }
}
static void WriteAlphaCompare(char *&p, int num, int comp) static void WriteAlphaCompare(char *&p, int num, int comp)
{ {

View File

@ -92,7 +92,7 @@ public:
} }
}; };
const char *GeneratePixelShader(u32 texture_mask, bool dstAlphaEnable, bool HLSL = false); const char *GeneratePixelShader(bool dstAlphaEnable, bool HLSL = false);
void GetPixelShaderId(PIXELSHADERUID &, u32 s_texturemask, u32 dstAlphaEnable); void GetPixelShaderId(PIXELSHADERUID &, u32 dstAlphaEnable);
#endif #endif

View File

@ -40,11 +40,6 @@ static u32 lastAlpha = 0;
static u32 lastTexDims[8]={0}; // width | height << 16 | wrap_s << 28 | wrap_t << 30 static u32 lastTexDims[8]={0}; // width | height << 16 | wrap_s << 28 | wrap_t << 30
static u32 lastZBias = 0; static u32 lastZBias = 0;
// lower byte describes if a texture is nonpow2 or pow2
// next byte describes whether the repeat wrap mode is enabled for the s channel
// next byte is for t channel
static u32 s_texturemask = 0;
void PixelShaderManager::Init() void PixelShaderManager::Init()
{ {
s_nColorsChanged[0] = s_nColorsChanged[1] = 0; s_nColorsChanged[0] = s_nColorsChanged[1] = 0;
@ -208,26 +203,15 @@ void PixelShaderManager::SetConstants()
void PixelShaderManager::SetPSTextureDims(int texid) void PixelShaderManager::SetPSTextureDims(int texid)
{ {
// non pow 2 textures - texdims.xy are the real texture dimensions used for wrapping // texdims.xy are reciprocals of the real texture dimensions
// pow 2 textures - texdims.xy are reciprocals of the real texture dimensions // texdims.zw are the scaled dimensions
// both - texdims.zw are the scaled dimensions
float fdims[4]; float fdims[4];
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]; TCoordInfo& tc = bpmem.texcoords[texid];
fdims[0] = 1.0f / (float)(lastTexDims[texid] & 0xffff); fdims[0] = 1.0f / (float)(lastTexDims[texid] & 0xffff);
fdims[1] = 1.0f / (float)((lastTexDims[texid] >> 16) & 0xfff); fdims[1] = 1.0f / (float)((lastTexDims[texid] >> 16) & 0xfff);
fdims[2] = (float)(tc.s.scale_minus_1 + 1) * lastCustomTexScale[texid][0]; fdims[2] = (float)(tc.s.scale_minus_1 + 1) * lastCustomTexScale[texid][0];
fdims[3] = (float)(tc.t.scale_minus_1 + 1) * lastCustomTexScale[texid][1]; 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]); PRIM_LOG("texdims%d: %f %f %f %f\n", texid, fdims[0], fdims[1], fdims[2], fdims[3]);
SetPSConstant4fv(C_TEXDIMS + texid, fdims); SetPSConstant4fv(C_TEXDIMS + texid, fdims);
@ -328,23 +312,6 @@ void PixelShaderManager::SetZTextureTypeChanged()
s_bZTextureTypeChanged = true; 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) void PixelShaderManager::SetTexCoordChanged(u8 texmapid)
{ {
s_nTexDimsChanged |= 1 << texmapid; s_nTexDimsChanged |= 1 << texmapid;
@ -368,8 +335,3 @@ void PixelShaderManager::SetColorMatrix(const float* pmatrix, const float* pfCon
SetPSConstant4fv(C_COLORMATRIX+3, pmatrix+12); SetPSConstant4fv(C_COLORMATRIX+3, pmatrix+12);
SetPSConstant4fv(C_COLORMATRIX+4, pfConstAdd); SetPSConstant4fv(C_COLORMATRIX+4, pfConstAdd);
} }
u32 PixelShaderManager::GetTextureMask()
{
return s_texturemask;
}

View File

@ -46,12 +46,10 @@ public:
static void SetTevKSelChanged(int id); static void SetTevKSelChanged(int id);
static void SetZTextureTypeChanged(); static void SetZTextureTypeChanged();
static void SetIndTexScaleChanged(u8 stagemask); static void SetIndTexScaleChanged(u8 stagemask);
static void SetTexturesUsed(u32 nonpow2tex);
static void SetTexCoordChanged(u8 texmapid); static void SetTexCoordChanged(u8 texmapid);
static void SetFogColorChanged(); static void SetFogColorChanged();
static void SetFogParamChanged(); static void SetFogParamChanged();
static void SetColorMatrix(const float* pmatrix, const float* pfConstAdd); static void SetColorMatrix(const float* pmatrix, const float* pfConstAdd);
static u32 GetTextureMask();
}; };

View File

@ -470,7 +470,8 @@ char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char
if (coloralpha == 1 ) swizzle = "xyz"; if (coloralpha == 1 ) swizzle = "xyz";
else if (coloralpha == 2 ) swizzle = "w"; else if (coloralpha == 2 ) swizzle = "w";
if (!(chan.attnfunc & 1)) { if (!(chan.attnfunc & 1))
{
// atten disabled // atten disabled
switch (chan.diffusefunc) { switch (chan.diffusefunc) {
case LIGHTDIF_NONE: case LIGHTDIF_NONE:
@ -485,7 +486,9 @@ char* GenerateLightShader(char* p, int index, const LitChannel& chan, const char
default: _assert_(0); default: _assert_(0);
} }
} }
else { // spec and spot else
{
// spec and spot
WRITE(p, "ldir = "I_LIGHTS".lights[%d].pos.xyz - pos.xyz;\n", index); WRITE(p, "ldir = "I_LIGHTS".lights[%d].pos.xyz - pos.xyz;\n", index);
if (chan.attnfunc == 3) { // spot if (chan.attnfunc == 3) { // spot

View File

@ -67,7 +67,7 @@ void PixelShaderCache::SetShader()
DVSTARTPROFILE(); DVSTARTPROFILE();
PIXELSHADERUID uid; PIXELSHADERUID uid;
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), false); GetPixelShaderId(uid, false);
PSCache::iterator iter; PSCache::iterator iter;
iter = PixelShaders.find(uid); iter = PixelShaders.find(uid);
@ -85,7 +85,7 @@ void PixelShaderCache::SetShader()
} }
bool HLSL = false; bool HLSL = false;
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(), false, HLSL); const char *code = GeneratePixelShader(false, HLSL);
LPDIRECT3DPIXELSHADER9 shader = HLSL ? D3D::CompilePixelShader(code, (int)strlen(code), false) : CompileCgShader(code); LPDIRECT3DPIXELSHADER9 shader = HLSL ? D3D::CompilePixelShader(code, (int)strlen(code), false) : CompileCgShader(code);
if (shader) if (shader)
{ {

View File

@ -198,7 +198,6 @@ void Flush()
} }
} }
u32 nonpow2tex = 0;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (usedtextures & (1 << i)) { if (usedtextures & (1 << i)) {
@ -211,25 +210,14 @@ void Flush()
if (tentry) { if (tentry) {
// texture loaded fine, set dims for pixel shader // 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) // 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. // (the above seems to have changed - we set the width and height here too.
else
{
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
} }
}
else else
ERROR_LOG(VIDEO, "error loading texture"); ERROR_LOG(VIDEO, "error loading texture");
} }
} }
PixelShaderManager::SetTexturesUsed(nonpow2tex);
int numVertices = indexGen.GetNumVerts(); int numVertices = indexGen.GetNumVerts();
if (numVertices) if (numVertices)

View File

@ -145,7 +145,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
DVSTARTPROFILE(); DVSTARTPROFILE();
PIXELSHADERUID uid; PIXELSHADERUID uid;
u32 dstAlpha = dstAlphaEnable ? 1 : 0; u32 dstAlpha = dstAlphaEnable ? 1 : 0;
GetPixelShaderId(uid, PixelShaderManager::GetTextureMask(), dstAlpha); GetPixelShaderId(uid, dstAlpha);
PSCache::iterator iter = pshaders.find(uid); PSCache::iterator iter = pshaders.find(uid);
@ -160,8 +160,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
} }
PSCacheEntry& newentry = pshaders[uid]; PSCacheEntry& newentry = pshaders[uid];
const char *code = GeneratePixelShader(PixelShaderManager::GetTextureMask(), const char *code = GeneratePixelShader(dstAlphaEnable, false);
dstAlphaEnable);
#if defined(_DEBUG) || defined(DEBUGFAST) #if defined(_DEBUG) || defined(DEBUGFAST)
if (g_Config.iLog & CONF_SAVESHADERS && code) { if (g_Config.iLog & CONF_SAVESHADERS && code) {

View File

@ -107,22 +107,6 @@ bool TextureMngr::TCacheEntry::IntersectsMemoryRange(u32 range_address, u32 rang
void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode) void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode)
{ {
mode = newmode; mode = newmode;
if (isNonPow2)
{
// 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 (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, glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,
(newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST); (newmode.mag_filter || g_Config.bForceFiltering) ? GL_LINEAR : GL_NEAREST);
@ -137,7 +121,6 @@ void TextureMngr::TCacheEntry::SetTextureParameters(TexMode0 &newmode)
(g_Config.bForceFiltering || newmode.min_filter >= 4) ? GL_LINEAR : GL_NEAREST); (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_S, c_WrapSettings[newmode.wrap_s]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, c_WrapSettings[newmode.wrap_t]); 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_Config.iMaxAnisotropy)); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (float)(1 << g_Config.iMaxAnisotropy));
@ -301,9 +284,8 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash))) if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash)))
{ {
entry.frameCount = frameCount; entry.frameCount = frameCount;
glEnable(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
// entry.isNonPow2 ? TextureMngr::EnableTex2D(texstage) : TextureMngr::EnableTexRECT(texstage); glBindTexture(GL_TEXTURE_2D, entry.texture);
glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture);
if (entry.mode.hex != tm0.hex) if (entry.mode.hex != tm0.hex)
entry.SetTextureParameters(tm0); entry.SetTextureParameters(tm0);
//DebugLog("%cC addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_Config.bSafeTextureCache ? 'S' : 'U' //DebugLog("%cC addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_Config.bSafeTextureCache ? 'S' : 'U'
@ -317,7 +299,7 @@ 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.
if (width == entry.w && height == entry.h && tex_format == entry.fmt) if (width == entry.w && height == entry.h && tex_format == entry.fmt)
{ {
glBindTexture(entry.isNonPow2 ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
if (entry.mode.hex != tm0.hex) if (entry.mode.hex != tm0.hex)
entry.SetTextureParameters(tm0); entry.SetTextureParameters(tm0);
skip_texture_create = true; skip_texture_create = true;
@ -370,16 +352,13 @@ 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' //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); // , address, tex_format, entry.hash, width, height);
entry.addr = address; entry.addr = address;
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format); entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format);
entry.isRenderTarget = false; entry.isRenderTarget = false;
entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1)));
GLenum target = entry.isNonPow2 ? 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(GL_TEXTURE_2D, entry.texture);
} }
if (dfmt != PC_TEX_FMT_DXT1) if (dfmt != PC_TEX_FMT_DXT1)
@ -432,7 +411,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
break; break;
} }
if (!entry.isNonPow2 && ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2)) if ((tm0.min_filter & 3) == 1 || (tm0.min_filter & 3) == 2)
{ {
glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp);
@ -441,14 +420,14 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
entry.bHaveMipMaps = true; entry.bHaveMipMaps = true;
} }
else else
glTexImage2D(target, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp); glTexImage2D(GL_TEXTURE_2D, 0, gl_iformat, width, height, 0, gl_format, gl_type, temp);
if (expandedWidth != width) // reset if (expandedWidth != width) // reset
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
} }
else else
{ {
glCompressedTexImage2D(target, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
expandedWidth, expandedHeight, 0, expandedWidth*expandedHeight/2, temp); expandedWidth, expandedHeight, 0, expandedWidth*expandedHeight/2, temp);
} }
@ -478,7 +457,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
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)) if (!File::Exists(szTemp))
{ {
SaveTexture(szTemp, target, entry.texture, expandedWidth, expandedHeight); SaveTexture(szTemp, GL_TEXTURE_2D, entry.texture, expandedWidth, expandedHeight);
} }
} }
@ -507,7 +486,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
PRIM_LOG("copytarg: addr=0x%x, fromz=%d, intfmt=%d, copyfmt=%d", address, (int)bFromZBuffer, (int)bIsIntensityFmt,copyfmt); PRIM_LOG("copytarg: addr=0x%x, fromz=%d, intfmt=%d, copyfmt=%d", address, (int)bFromZBuffer, (int)bIsIntensityFmt,copyfmt);
TCacheEntry& entry = textures[address]; TCacheEntry& entry = textures[address];
entry.isNonPow2 = true;
entry.hash = 0; entry.hash = 0;
entry.hashoffset = 0; entry.hashoffset = 0;
entry.frameCount = frameCount; entry.frameCount = frameCount;
@ -521,8 +499,8 @@ 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);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
else else
@ -532,7 +510,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
GL_REPORT_ERROR(); GL_REPORT_ERROR();
if (entry.w == w && entry.h == h) if (entry.w == w && entry.h == h)
{ {
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 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.
GLenum err = GL_REPORT_ERROR(); GLenum err = GL_REPORT_ERROR();
@ -545,22 +523,22 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
// necessary, for some reason opengl gives errors when texture isn't deleted // necessary, for some reason opengl gives errors when texture isn't deleted
glDeleteTextures(1,(GLuint *)&entry.texture); glDeleteTextures(1,(GLuint *)&entry.texture);
glGenTextures(1, (GLuint *)&entry.texture); glGenTextures(1, (GLuint *)&entry.texture);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, entry.texture); glBindTexture(GL_TEXTURE_2D, entry.texture);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, 4, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
} }
} }
if (!bIsInit || !entry.isRenderTarget) if (!bIsInit || !entry.isRenderTarget)
{ {
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 (glGetError() != GL_NO_ERROR) { if (glGetError() != 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();
} }
} }
@ -624,6 +602,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
if (copyfmt < 2) if (copyfmt < 2)
{ {
// ????
fConstAdd[3] = 16.0f / 255.0f; fConstAdd[3] = 16.0f / 255.0f;
colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f; colmat[12] = 0.257f; colmat[13] = 0.504f; colmat[14] = 0.098f;
} }
@ -696,7 +675,7 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
Renderer::SetFramebuffer(s_TempFramebuffer); Renderer::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();

View File

@ -29,7 +29,7 @@ class TextureMngr
public: public:
struct TCacheEntry 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), isNonPow2(true), 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), bHaveMipMaps(false) { mode.hex = 0xFCFCFCFC; }
GLuint texture; GLuint texture;
u32 addr; u32 addr;
@ -48,7 +48,6 @@ public:
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 isUpsideDown; bool isUpsideDown;
bool isNonPow2; // if nonpow2, use GL_TEXTURE_2D, else GL_TEXTURE_RECTANGLE_NV
bool bHaveMipMaps; bool bHaveMipMaps;
void SetTextureParameters(TexMode0& newmode); void SetTextureParameters(TexMode0& newmode);

View File

@ -207,7 +207,6 @@ void Flush()
if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages)
usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt);
u32 nonpow2tex = 0;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
if (usedtextures & (1 << i)) if (usedtextures & (1 << i))
@ -220,22 +219,10 @@ void Flush()
tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format); tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format);
if (tentry != NULL) if (tentry != NULL)
{
// 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.
else
{ {
// 0s are probably for no manual wrapping needed. // 0s are probably for no manual wrapping needed.
PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0);
}
// texture is hires - pass the scaling size // texture is hires - pass the scaling size
if (tentry->scaleX != 1.0f || tentry->scaleY != 1.0f) if (tentry->scaleX != 1.0f || tentry->scaleY != 1.0f)
PixelShaderManager::SetCustomTexScale(i, tentry->scaleX, tentry->scaleY); PixelShaderManager::SetCustomTexScale(i, tentry->scaleX, tentry->scaleY);
@ -244,7 +231,7 @@ void Flush()
// save the textures // save the textures
char strfile[255]; char strfile[255];
sprintf(strfile, "%sframes/tex%.3d_%d.tga", FULL_DUMP_DIR, g_Config.iSaveTargetId, i); sprintf(strfile, "%sframes/tex%.3d_%d.tga", FULL_DUMP_DIR, g_Config.iSaveTargetId, i);
SaveTexture(strfile, tentry->isNonPow2?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
@ -252,8 +239,6 @@ void Flush()
} }
} }
PixelShaderManager::SetTexturesUsed(nonpow2tex);
FRAGMENTSHADER* ps = PixelShaderCache::GetShader(false); FRAGMENTSHADER* ps = PixelShaderCache::GetShader(false);
VERTEXSHADER* vs = VertexShaderCache::GetShader(g_nativeVertexFmt->m_components); VERTEXSHADER* vs = VertexShaderCache::GetShader(g_nativeVertexFmt->m_components);