From 2301a3b49ee8d2f23eabd0ba508d5ad2cd9a96dd Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 15 Feb 2013 00:30:02 +0100 Subject: [PATCH] Flip texcoord vertically when texturing from FBO to compensate for OpenGL coordinate systems --- GPU/GLES/DisplayListInterpreter.cpp | 15 ++++++++++----- GPU/GLES/ShaderManager.cpp | 5 ++++- GPU/GLES/TextureCache.cpp | 29 +++++++++++++++++++++++------ GPU/GLES/TextureCache.h | 1 + GPU/GLES/TransformPipeline.cpp | 2 ++ GPU/GLES/VertexShaderGenerator.cpp | 6 ++++++ GPU/GPUState.h | 2 ++ 7 files changed, 48 insertions(+), 12 deletions(-) diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index d1a8f606db..039fc97910 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -542,22 +542,26 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { break; case GE_CMD_TEXTUREMAPENABLE: - gstate_c.textureChanged = true; + if (diff) + gstate_c.textureChanged = true; break; case GE_CMD_LIGHTINGENABLE: break; case GE_CMD_FOGCOLOR: - shaderManager_->DirtyUniform(DIRTY_FOGCOLOR); + if (diff) + shaderManager_->DirtyUniform(DIRTY_FOGCOLOR); break; case GE_CMD_FOG1: - shaderManager_->DirtyUniform(DIRTY_FOGCOEF); + if (diff) + shaderManager_->DirtyUniform(DIRTY_FOGCOEF); break; case GE_CMD_FOG2: - shaderManager_->DirtyUniform(DIRTY_FOGCOEF); + if (diff) + shaderManager_->DirtyUniform(DIRTY_FOGCOEF); break; case GE_CMD_FOGENABLE: @@ -618,6 +622,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXADDR6: case GE_CMD_TEXADDR7: gstate_c.textureChanged = true; + shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); break; case GE_CMD_TEXBUFWIDTH0: @@ -667,7 +672,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_TEXSIZE0: gstate_c.curTextureWidth = 1 << (gstate.texsize[0] & 0xf); - gstate_c.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf); + gstate_c.curTextureHeight = 1 << ((gstate.texsize[0] >> 8) & 0xf); shaderManager_->DirtyUniform(DIRTY_UVSCALEOFFSET); //fall thru - ignoring the mipmap sizes for now case GE_CMD_TEXSIZE1: diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index c3a91cebf4..6a985c8446 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -138,6 +138,7 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs) glUniform1i(u_tex, 0); // The rest, use the "dirty" mechanism. dirtyUniforms = DIRTY_ALL; + use(); } LinkedShader::~LinkedShader() { @@ -264,8 +265,10 @@ void LinkedShader::updateUniforms() { // Texturing if (u_uvscaleoffset != -1 && (dirtyUniforms & DIRTY_UVSCALEOFFSET)) { - float uvscaleoff[4] = { gstate_c.uScale, gstate_c.vScale, gstate_c.uOff, gstate_c.vOff}; + float uvscaleoff[4] = {gstate_c.uScale, gstate_c.vScale, gstate_c.uOff, gstate_c.vOff}; if (gstate.isModeThrough()) { + // We never get here because we don't use HW transform with through mode. + // Although - why don't we? uvscaleoff[0] /= gstate_c.curTextureWidth; uvscaleoff[1] /= gstate_c.curTextureHeight; uvscaleoff[2] /= gstate_c.curTextureWidth; diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index fdfb3f4257..4b964a274e 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -24,9 +24,20 @@ #include "TextureCache.h" #include "../Core/Config.h" -// If a texture hasn't been seen for 200 frames, get rid of it. +// If a texture hasn't been seen for this many frames, get rid of it. #define TEXTURE_KILL_AGE 200 -float maxAnisotropyLevel ; + +u32 RoundUpToPowerOf2(u32 v) +{ + v--; + v |= v >> 1; + v |= v >> 2; + v |= v >> 4; + v |= v >> 8; + v |= v >> 16; + v++; + return v; +} TextureCache::TextureCache() { lastBoundTexture = -1; @@ -681,22 +692,28 @@ void TextureCache::SetTexture() { TexCache::iterator iter = cache.find(cachekey); TexCacheEntry *entry = NULL; + gstate_c.flipTexture = false; + if (iter != cache.end()) { entry = &iter->second; // Check for FBO - slow! if (entry->fbo) { + int w = 1 << (gstate.texsize[0] & 0xf); + int h = 1 << ((gstate.texsize[0] >> 8) & 0xf); + fbo_bind_color_as_texture(entry->fbo, 0); UpdateSamplingParams(*entry, false); int fbow, fboh; fbo_get_dimensions(entry->fbo, &fbow, &fboh); - // Almost certain this isn't right. - gstate_c.curTextureWidth = fbow; - gstate_c.curTextureHeight = fboh; + // This isn't right. + gstate_c.curTextureWidth = w; //w; //RoundUpToPowerOf2(fbow); + gstate_c.curTextureHeight = h; // RoundUpToPowerOf2(fboh); + gstate_c.flipTexture = true; + entry->lastFrame = gpuStats.numFrames; return; } - //Validate the texture here (width, height etc) int dim = gstate.texsize[0] & 0xF0F; diff --git a/GPU/GLES/TextureCache.h b/GPU/GLES/TextureCache.h index 881e672902..bb1958c365 100644 --- a/GPU/GLES/TextureCache.h +++ b/GPU/GLES/TextureCache.h @@ -101,5 +101,6 @@ private: u16 *clutBuf16; int lastBoundTexture; + float maxAnisotropyLevel; }; diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index d63269572e..c20b60e130 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -642,6 +642,8 @@ void TransformDrawEngine::SoftwareTransformAndDraw( memcpy(&transformed[index].x, v, 3 * sizeof(float)); transformed[index].fog = fogCoef; memcpy(&transformed[index].u, uv, 2 * sizeof(float)); + if (gstate_c.flipTexture) + transformed[index].v = 1.0f - transformed[index].v * 2.0f; for (int i = 0; i < 4; i++) { transformed[index].color0[i] = c0[i] * 255.0f; } diff --git a/GPU/GLES/VertexShaderGenerator.cpp b/GPU/GLES/VertexShaderGenerator.cpp index f9da12ed74..b5a5edb19e 100644 --- a/GPU/GLES/VertexShaderGenerator.cpp +++ b/GPU/GLES/VertexShaderGenerator.cpp @@ -60,6 +60,9 @@ void ComputeVertexShaderID(VertexShaderID *id, int prim) id->d[0] |= ((int)enableFog) << 2; id->d[0] |= doTexture << 3; id->d[0] |= (hasColor & 1) << 4; + if (doTexture) + id->d[0] |= (gstate_c.flipTexture & 1) << 5; + if (CanUseHardwareTransform(prim)) { id->d[0] |= 1 << 8; id->d[0] |= (hasNormal & 1) << 9; @@ -139,6 +142,7 @@ void GenerateVertexShader(int prim, char *buffer) { bool hasColor = (gstate.vertType & GE_VTYPE_COL_MASK) != 0 || !hwXForm; bool hasNormal = (gstate.vertType & GE_VTYPE_NRM_MASK) != 0 && hwXForm; bool enableFog = gstate.isFogEnabled() && !gstate.isModeThrough() && !gstate.isModeClear(); + bool flipV = gstate_c.flipTexture; DoLightComputation doLight[4] = {LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF}; if (hwXForm) { @@ -396,6 +400,8 @@ void GenerateVertexShader(int prim, char *buffer) { // ILLEGAL break; } + if (flipV) + WRITE(p, " v_texcoord.y = 1.0f - v_texcoord.y;\n"); } // Compute fogdepth diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 516042e892..ca036b2506 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -238,6 +238,8 @@ struct GPUStateCache float uScale,vScale; float uOff,vOff; + bool flipTexture; + float zMin, zMax; float lightpos[4][3]; float lightdir[4][3];