diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index c9ad0004ca..3b6fdf1a58 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -283,10 +283,6 @@ bool ShouldUseShaderBlending() { if (!gstate.isAlphaBlendEnabled()) { return false; } - // We can't blit on GLES2, so we don't support it. We also want texelFetch (OpenGL 3.0+ / GLES3+.) - if (!gl_extensions.VersionGEThan(3, 0, 0) && !gl_extensions.GLES3) { - return false; - } if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) { return false; } @@ -516,6 +512,9 @@ void GenerateFragmentShader(char *buffer) { WRITE(p, "uniform sampler2D tex;\n"); if (!gstate.isModeClear() && ShouldUseShaderBlending()) { if (!gl_extensions.NV_shader_framebuffer_fetch) { + if (!gl_extensions.VersionGEThan(3, 0, 0) && !gl_extensions.GLES3) { + WRITE(p, "uniform vec2 u_fbotexSize;\n"); + } WRITE(p, "uniform sampler2D fbotex;\n"); } if (gstate.getBlendFuncA() == GE_SRCBLEND_FIXA) { @@ -766,6 +765,8 @@ void GenerateFragmentShader(char *buffer) { // TODO: EXT_shader_framebuffer_fetch on iOS 6, possibly others. if (gl_extensions.NV_shader_framebuffer_fetch) { WRITE(p, " lowp vec4 destColor = gl_LastFragData[0];\n"); + } else if (!gl_extensions.VersionGEThan(3, 0, 0) && !gl_extensions.GLES3) { + WRITE(p, " lowp vec4 destColor = %s(fbotex, gl_FragCoord.xy * u_fbotexSize.xy);\n", texture); } else { WRITE(p, " lowp vec4 destColor = texelFetch(fbotex, ivec2(gl_FragCoord.x, gl_FragCoord.y), 0);\n"); } diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index 13e8088ef4..72b8ecfae5 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -1053,6 +1053,8 @@ void FramebufferManager::DoSetRenderFrameBuffer() { gstate_c.curRTWidth = vfb->width; gstate_c.curRTHeight = vfb->height; } + gstate_c.curRTRenderWidth = vfb->renderWidth; + gstate_c.curRTRenderHeight = vfb->renderHeight; } void FramebufferManager::SetLineWidth() { diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index fdb9eda987..ad52d0325c 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -162,8 +162,8 @@ static const CommandTableEntry commandTable[] = { {GE_CMD_STENCILTESTENABLE, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_ALPHABLENDENABLE, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_BLENDMODE, FLAG_FLUSHBEFOREONCHANGE}, - {GE_CMD_BLENDFIXEDA, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &GLES_GPU::Execute_BlendFixA}, - {GE_CMD_BLENDFIXEDB, FLAG_FLUSHBEFOREONCHANGE | FLAG_EXECUTEONCHANGE, &GLES_GPU::Execute_BlendFixB}, + {GE_CMD_BLENDFIXEDA, FLAG_FLUSHBEFOREONCHANGE}, + {GE_CMD_BLENDFIXEDB, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_MASKRGB, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_MASKALPHA, FLAG_FLUSHBEFOREONCHANGE}, {GE_CMD_ZTEST, FLAG_FLUSHBEFOREONCHANGE}, @@ -1096,14 +1096,6 @@ void GLES_GPU::Execute_ColorRef(u32 op, u32 diff) { shaderManager_->DirtyUniform(DIRTY_ALPHACOLORREF); } -void GLES_GPU::Execute_BlendFixA(u32 op, u32 diff) { - shaderManager_->DirtyUniform(DIRTY_BLENDFIX); -} - -void GLES_GPU::Execute_BlendFixB(u32 op, u32 diff) { - shaderManager_->DirtyUniform(DIRTY_BLENDFIX); -} - void GLES_GPU::Execute_WorldMtxNum(u32 op, u32 diff) { // This is almost always followed by GE_CMD_WORLDMATRIXDATA. const u32_le *src = (const u32_le *)Memory::GetPointer(currentList->pc + 4); @@ -1634,11 +1626,7 @@ void GLES_GPU::ExecuteOpInternal(u32 op, u32 diff) { break; case GE_CMD_BLENDFIXEDA: - Execute_BlendFixA(op, diff); - break; - case GE_CMD_BLENDFIXEDB: - Execute_BlendFixB(op, diff); break; case GE_CMD_ALPHATESTENABLE: diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index 3d3f7e07d9..d5b09b2b11 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -128,8 +128,6 @@ public: void Execute_AlphaTest(u32 op, u32 diff); void Execute_StencilTest(u32 op, u32 diff); void Execute_ColorRef(u32 op, u32 diff); - void Execute_BlendFixA(u32 op, u32 diff); - void Execute_BlendFixB(u32 op, u32 diff); void Execute_WorldMtxNum(u32 op, u32 diff); void Execute_WorldMtxData(u32 op, u32 diff); void Execute_ViewMtxNum(u32 op, u32 diff); diff --git a/GPU/GLES/ShaderManager.cpp b/GPU/GLES/ShaderManager.cpp index 236c34220b..8412c62605 100644 --- a/GPU/GLES/ShaderManager.cpp +++ b/GPU/GLES/ShaderManager.cpp @@ -151,6 +151,7 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans u_fbotex = glGetUniformLocation(program, "fbotex"); u_blendFixA = glGetUniformLocation(program, "u_blendFixA"); u_blendFixB = glGetUniformLocation(program, "u_blendFixB"); + u_fbotexSize = glGetUniformLocation(program, "u_fbotexSize"); // Transform u_view = glGetUniformLocation(program, "u_view"); @@ -225,7 +226,7 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTrans if (u_view != -1) availableUniforms |= DIRTY_VIEWMATRIX; if (u_texmtx != -1) availableUniforms |= DIRTY_TEXMATRIX; if (u_stencilReplaceValue != -1) availableUniforms |= DIRTY_STENCILREPLACEVALUE; - if (u_blendFixA != -1 || u_blendFixB != -1) availableUniforms |= DIRTY_BLENDFIX; + if (u_blendFixA != -1 || u_blendFixB != -1 || u_fbotexSize != -1) availableUniforms |= DIRTY_SHADERBLEND; // Looping up to numBones lets us avoid checking u_bone[i] for (int i = 0; i < numBones; i++) { @@ -551,9 +552,17 @@ void LinkedShader::UpdateUniforms(u32 vertType) { } #endif - if (dirty & DIRTY_BLENDFIX) { + if (dirty & DIRTY_SHADERBLEND) { SetColorUniform3(u_blendFixA, gstate.getFixA()); SetColorUniform3(u_blendFixB, gstate.getFixB()); + + const float fbotexSize[2] = { + 1.0f / (float)gstate_c.curRTRenderWidth, + 1.0f / (float)gstate_c.curRTRenderHeight, + }; + if (u_fbotexSize != -1) { + glUniform2fv(u_fbotexSize, 1, fbotexSize); + } } // Lighting diff --git a/GPU/GLES/ShaderManager.h b/GPU/GLES/ShaderManager.h index 0810e2b1dd..87f696a61b 100644 --- a/GPU/GLES/ShaderManager.h +++ b/GPU/GLES/ShaderManager.h @@ -77,6 +77,7 @@ public: int u_fbotex; int u_blendFixA; int u_blendFixB; + int u_fbotexSize; // Fragment processing inputs int u_alphacolorref; @@ -130,7 +131,7 @@ enum DIRTY_AMBIENT = (1 << 15), DIRTY_MATAMBIENTALPHA = (1 << 16), - DIRTY_BLENDFIX = (1 << 17), // (either one.) + DIRTY_SHADERBLEND = (1 << 17), // Used only for in-shader blending. DIRTY_UVSCALEOFFSET = (1 << 18), // this will be dirtied ALL THE TIME... maybe we'll need to do "last value with this shader compares" DIRTY_TEXCLAMP = (1 << 19), diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index 695e06e4eb..72b631933b 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -195,8 +195,13 @@ void TransformDrawEngine::ApplyDrawState(int prim) { glActiveTexture(GL_TEXTURE1); framebufferManager_->BindFramebufferColor(NULL); + // If we are rendering at a higher resolution, linear is probably best for the dest color. + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glActiveTexture(GL_TEXTURE0); fboTexBound_ = true; + + shaderManager_->DirtyUniform(DIRTY_SHADERBLEND); } // None of the below logic is interesting, we're gonna do it entirely in the shader. wantBlend = false; @@ -204,6 +209,7 @@ void TransformDrawEngine::ApplyDrawState(int prim) { glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); + fboTexBound_ = false; } glstate.blend.set(wantBlend); diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index d9ef7b3de1..3dabcceabc 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -969,8 +969,8 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe glActiveTexture(GL_TEXTURE0); framebufferManager_->BindFramebufferColor(framebuffer, true); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); entry->status |= TexCacheEntry::STATUS_TEXPARAM_DIRTY; glDisable(GL_BLEND); diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 3562db36d1..cd3c8e7026 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -335,4 +335,6 @@ void GPUStateCache::DoState(PointerWrap &p) { p.Do(curRTWidth); p.Do(curRTHeight); + + // curRTBufferWidth and curRTBufferHeight don't need to be saved. } diff --git a/GPU/GPUState.h b/GPU/GPUState.h index 5448ec8beb..e14f6a62f2 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -475,6 +475,9 @@ struct GPUStateCache u32 curRTWidth; u32 curRTHeight; + u32 curRTRenderWidth; + u32 curRTRenderHeight; + u32 getRelativeAddress(u32 data) const; void DoState(PointerWrap &p); };