OpenGL plugin: Support for dual-source blending, CURRENTLY DISABLED. It doesn't work yet. To fix it, we may need to convert all our shaders to GLSL so that we can use glBindFragDataLocation.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6306 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Nolan Check 2010-10-23 19:55:19 +00:00
parent 91186d2b8a
commit 2ec3db44ed
5 changed files with 67 additions and 11 deletions

View File

@ -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) {

View File

@ -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");
}

View File

@ -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_

View File

@ -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;
}

View File

@ -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);