diff --git a/Source/Core/Common/Src/LinearDiskCache.cpp b/Source/Core/Common/Src/LinearDiskCache.cpp index 1df7614b6d..5e634ce3a8 100644 --- a/Source/Core/Common/Src/LinearDiskCache.cpp +++ b/Source/Core/Common/Src/LinearDiskCache.cpp @@ -22,7 +22,7 @@ static const char ID[4] = {'D', 'C', 'A', 'C'}; // Update this to the current SVN revision every time you change shader generation code. // We don't automatically get this from SVN_REV because that would mean regenerating the // shader cache for every revision, graphics-related or not, which is simply annoying. -const int version = 6296; +const int version = 6306; LinearDiskCache::LinearDiskCache() : file_(NULL), num_entries_(0) { diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 288af0d386..616318db84 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -519,8 +519,8 @@ const char *GeneratePixelShaderCode(DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType WRITE(p, "void main(\n"); if(ApiType != API_D3D11) { - // TODO: Support DSTALPHA_DUAL_SOURCE_BLEND for non-D3D11 shaders - WRITE(p, " out float4 ocol0 : COLOR0,%s\n in float4 rawpos : %s,\n", + WRITE(p, " out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n", + dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "", DepthTextureEnable ? "\n out float depth : DEPTH," : "", ApiType == API_OPENGL ? "WPOS" : "POSITION"); } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h index c0fb1a55f3..754a094cdb 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h +++ b/Source/Plugins/Plugin_VideoOGL/Src/GLUtil.h @@ -136,4 +136,9 @@ extern CGcontext g_cgcontext; extern CGprofile g_cgvProf, g_cgfProf; #endif +// XXX: Dual-source blending in OpenGL does not work correctly yet. To make it +// work, we may need to use glBindFragDataLocation. To use that, we need to +// use GLSL shaders across the whole pipeline. Yikes! +const bool USE_DUAL_SOURCE_BLEND = false; + #endif // _GLINIT_H_ diff --git a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp index b9882f1087..44c84aaf8f 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/Render.cpp @@ -151,7 +151,7 @@ static const GLenum glSrcFactors[8] = GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; @@ -162,7 +162,7 @@ static const GLenum glDestFactors[8] = { GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, // NOTE: If dual-source blending is enabled, use SRC1_ALPHA GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA }; @@ -1034,17 +1034,47 @@ void Renderer::SetBlendMode(bool forceUpdate) u32 changes = forceUpdate ? 0xFFFFFFFF : newval ^ s_blendMode; + bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate + && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + bool useDualSource = USE_DUAL_SOURCE_BLEND && useDstAlpha && GLEW_ARB_blend_func_extended; + if (changes & 1) // blend enable change (newval & 1) ? glEnable(GL_BLEND) : glDisable(GL_BLEND); if (changes & 4) + { // subtract enable change - glBlendEquation(newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD); + GLenum equation = newval & 4 ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD; + GLenum equationAlpha = useDualSource ? GL_FUNC_ADD : equation; + glBlendEquationSeparate(equation, equationAlpha); + } if (changes & 0x1F8) + { + GLenum srcFactor = glSrcFactors[(newval >> 3) & 7]; + GLenum srcFactorAlpha = srcFactor; + GLenum dstFactor = glDestFactors[(newval >> 6) & 7]; + GLenum dstFactorAlpha = dstFactor; + if (useDualSource) + { + srcFactorAlpha = GL_ONE; + dstFactorAlpha = GL_ZERO; + + if (srcFactor == GL_SRC_ALPHA) + srcFactor = GL_SRC1_ALPHA; + else if (srcFactor == GL_ONE_MINUS_SRC_ALPHA) + srcFactor = GL_ONE_MINUS_SRC1_ALPHA; + + if (dstFactor == GL_SRC_ALPHA) + dstFactor = GL_SRC1_ALPHA; + else if (dstFactor == GL_ONE_MINUS_SRC_ALPHA) + dstFactor = GL_ONE_MINUS_SRC1_ALPHA; + } + // blend RGB change - glBlendFunc(glSrcFactors[(newval >> 3) & 7], glDestFactors[(newval >> 6) & 7]); + glBlendFuncSeparate(srcFactor, dstFactor, srcFactorAlpha, dstFactorAlpha); + } s_blendMode = newval; } diff --git a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp index ef308524d7..58e677d563 100644 --- a/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp @@ -184,8 +184,31 @@ void VertexManager::vFlush() VertexShaderManager::SetConstants(); PixelShaderManager::SetConstants(); + bool useDstAlpha = !g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate + && bpmem.zcontrol.pixel_format == PIXELFMT_RGBA6_Z24; + bool dualSourcePossible = USE_DUAL_SOURCE_BLEND && GLEW_ARB_blend_func_extended; + // finally bind - FRAGMENTSHADER* ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components); + FRAGMENTSHADER* ps; + if (dualSourcePossible) + { + if (useDstAlpha) + { + // If host supports GL_ARB_blend_func_extended, we can do dst alpha in + // the same pass as regular rendering. + Renderer::SetBlendMode(true); + ps = PixelShaderCache::SetShader(DSTALPHA_DUAL_SOURCE_BLEND, g_nativeVertexFmt->m_components); + } + else + { + Renderer::SetBlendMode(true); + ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components); + } + } + else + { + ps = PixelShaderCache::SetShader(DSTALPHA_NONE,g_nativeVertexFmt->m_components); + } VERTEXSHADER* vs = VertexShaderCache::SetShader(g_nativeVertexFmt->m_components); if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid); // Lego Star Wars crashes here. if (vs) VertexShaderCache::SetCurrentShader(vs->glprogid); @@ -193,10 +216,8 @@ void VertexManager::vFlush() Draw(); // run through vertex groups again to set alpha - if (!g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate) + if (useDstAlpha && !dualSourcePossible) { - // TODO: If host supports GL_ARB_blend_func_extended, use - // DSTALPHA_DUAL_SOURCE_BLEND and set blend modes accordingly. ps = PixelShaderCache::SetShader(DSTALPHA_ALPHA_PASS,g_nativeVertexFmt->m_components); if (ps) PixelShaderCache::SetCurrentShader(ps->glprogid);