aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Gal/OpenGL
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-11-01 01:22:24 -0300
committerGitHub <noreply@github.com>2018-11-01 01:22:24 -0300
commit44c1cf3fe5a3886f34251f93fbcfc3b9c8f0e164 (patch)
tree257771bfe3360c9be09717e8f9466bcc2999a555 /Ryujinx.Graphics/Gal/OpenGL
parent1e7ea76f148660ff403938f3f84376879901e3ff (diff)
Implment common and independent blend properly (fixes #458) (#485)
* Implment common and independent blend properly * Nits
Diffstat (limited to 'Ryujinx.Graphics/Gal/OpenGL')
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs154
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs203
2 files changed, 268 insertions, 89 deletions
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
index 6b3d4fd6..49165101 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
@@ -47,34 +47,37 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public static DepthFunction GetDepthFunc(GalComparisonOp Func)
{
- //Looks like the GPU can take it's own values (described in GalComparisonOp) and OpenGL values alike
- if ((int)Func >= (int)DepthFunction.Never &&
- (int)Func <= (int)DepthFunction.Always)
+ return (DepthFunction)GetFunc(Func);
+ }
+
+ public static StencilFunction GetStencilFunc(GalComparisonOp Func)
+ {
+ return (StencilFunction)GetFunc(Func);
+ }
+
+ private static All GetFunc(GalComparisonOp Func)
+ {
+ if ((int)Func >= (int)All.Never &&
+ (int)Func <= (int)All.Always)
{
- return (DepthFunction)Func;
+ return (All)Func;
}
switch (Func)
{
- case GalComparisonOp.Never: return DepthFunction.Never;
- case GalComparisonOp.Less: return DepthFunction.Less;
- case GalComparisonOp.Equal: return DepthFunction.Equal;
- case GalComparisonOp.Lequal: return DepthFunction.Lequal;
- case GalComparisonOp.Greater: return DepthFunction.Greater;
- case GalComparisonOp.NotEqual: return DepthFunction.Notequal;
- case GalComparisonOp.Gequal: return DepthFunction.Gequal;
- case GalComparisonOp.Always: return DepthFunction.Always;
+ case GalComparisonOp.Never: return All.Never;
+ case GalComparisonOp.Less: return All.Less;
+ case GalComparisonOp.Equal: return All.Equal;
+ case GalComparisonOp.Lequal: return All.Lequal;
+ case GalComparisonOp.Greater: return All.Greater;
+ case GalComparisonOp.NotEqual: return All.Notequal;
+ case GalComparisonOp.Gequal: return All.Gequal;
+ case GalComparisonOp.Always: return All.Always;
}
throw new ArgumentException(nameof(Func) + " \"" + Func + "\" is not valid!");
}
- public static StencilFunction GetStencilFunc(GalComparisonOp Func)
- {
- //OGL comparison values match, it's just an enum cast
- return (StencilFunction)GetDepthFunc(Func);
- }
-
public static DrawElementsType GetDrawElementsType(GalIndexFormat Format)
{
switch (Format)
@@ -282,11 +285,25 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
switch (BlendEquation)
{
- case GalBlendEquation.FuncAdd: return BlendEquationMode.FuncAdd;
- case GalBlendEquation.FuncSubtract: return BlendEquationMode.FuncSubtract;
- case GalBlendEquation.FuncReverseSubtract: return BlendEquationMode.FuncReverseSubtract;
- case GalBlendEquation.Min: return BlendEquationMode.Min;
- case GalBlendEquation.Max: return BlendEquationMode.Max;
+ case GalBlendEquation.FuncAdd:
+ case GalBlendEquation.FuncAddGl:
+ return BlendEquationMode.FuncAdd;
+
+ case GalBlendEquation.FuncSubtract:
+ case GalBlendEquation.FuncSubtractGl:
+ return BlendEquationMode.FuncSubtract;
+
+ case GalBlendEquation.FuncReverseSubtract:
+ case GalBlendEquation.FuncReverseSubtractGl:
+ return BlendEquationMode.FuncReverseSubtract;
+
+ case GalBlendEquation.Min:
+ case GalBlendEquation.MinGl:
+ return BlendEquationMode.Min;
+
+ case GalBlendEquation.Max:
+ case GalBlendEquation.MaxGl:
+ return BlendEquationMode.Max;
}
throw new ArgumentException(nameof(BlendEquation) + " \"" + BlendEquation + "\" is not valid!");
@@ -296,27 +313,80 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
switch (BlendFactor)
{
- case GalBlendFactor.Zero: return BlendingFactor.Zero;
- case GalBlendFactor.One: return BlendingFactor.One;
- case GalBlendFactor.SrcColor: return BlendingFactor.SrcColor;
- case GalBlendFactor.OneMinusSrcColor: return BlendingFactor.OneMinusSrcColor;
- case GalBlendFactor.DstColor: return BlendingFactor.DstColor;
- case GalBlendFactor.OneMinusDstColor: return BlendingFactor.OneMinusDstColor;
- case GalBlendFactor.SrcAlpha: return BlendingFactor.SrcAlpha;
- case GalBlendFactor.OneMinusSrcAlpha: return BlendingFactor.OneMinusSrcAlpha;
- case GalBlendFactor.DstAlpha: return BlendingFactor.DstAlpha;
- case GalBlendFactor.OneMinusDstAlpha: return BlendingFactor.OneMinusDstAlpha;
- case GalBlendFactor.OneMinusConstantColor: return BlendingFactor.OneMinusConstantColor;
- case GalBlendFactor.ConstantAlpha: return BlendingFactor.ConstantAlpha;
- case GalBlendFactor.OneMinusConstantAlpha: return BlendingFactor.OneMinusConstantAlpha;
- case GalBlendFactor.SrcAlphaSaturate: return BlendingFactor.SrcAlphaSaturate;
- case GalBlendFactor.Src1Color: return BlendingFactor.Src1Color;
- case GalBlendFactor.OneMinusSrc1Color: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Color;
- case GalBlendFactor.Src1Alpha: return BlendingFactor.Src1Alpha;
- case GalBlendFactor.OneMinusSrc1Alpha: return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Alpha;
+ case GalBlendFactor.Zero:
+ case GalBlendFactor.ZeroGl:
+ return BlendingFactor.Zero;
+
+ case GalBlendFactor.One:
+ case GalBlendFactor.OneGl:
+ return BlendingFactor.One;
+
+ case GalBlendFactor.SrcColor:
+ case GalBlendFactor.SrcColorGl:
+ return BlendingFactor.SrcColor;
+
+ case GalBlendFactor.OneMinusSrcColor:
+ case GalBlendFactor.OneMinusSrcColorGl:
+ return BlendingFactor.OneMinusSrcColor;
+
+ case GalBlendFactor.DstColor:
+ case GalBlendFactor.DstColorGl:
+ return BlendingFactor.DstColor;
+
+ case GalBlendFactor.OneMinusDstColor:
+ case GalBlendFactor.OneMinusDstColorGl:
+ return BlendingFactor.OneMinusDstColor;
+
+ case GalBlendFactor.SrcAlpha:
+ case GalBlendFactor.SrcAlphaGl:
+ return BlendingFactor.SrcAlpha;
+
+ case GalBlendFactor.OneMinusSrcAlpha:
+ case GalBlendFactor.OneMinusSrcAlphaGl:
+ return BlendingFactor.OneMinusSrcAlpha;
+
+ case GalBlendFactor.DstAlpha:
+ case GalBlendFactor.DstAlphaGl:
+ return BlendingFactor.DstAlpha;
+
+ case GalBlendFactor.OneMinusDstAlpha:
+ case GalBlendFactor.OneMinusDstAlphaGl:
+ return BlendingFactor.OneMinusDstAlpha;
+
+ case GalBlendFactor.OneMinusConstantColor:
+ case GalBlendFactor.OneMinusConstantColorGl:
+ return BlendingFactor.OneMinusConstantColor;
+
+ case GalBlendFactor.ConstantAlpha:
+ case GalBlendFactor.ConstantAlphaGl:
+ return BlendingFactor.ConstantAlpha;
+
+ case GalBlendFactor.OneMinusConstantAlpha:
+ case GalBlendFactor.OneMinusConstantAlphaGl:
+ return BlendingFactor.OneMinusConstantAlpha;
+
+ case GalBlendFactor.SrcAlphaSaturate:
+ case GalBlendFactor.SrcAlphaSaturateGl:
+ return BlendingFactor.SrcAlphaSaturate;
+
+ case GalBlendFactor.Src1Color:
+ case GalBlendFactor.Src1ColorGl:
+ return BlendingFactor.Src1Color;
+
+ case GalBlendFactor.OneMinusSrc1Color:
+ case GalBlendFactor.OneMinusSrc1ColorGl:
+ return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Color;
+
+ case GalBlendFactor.Src1Alpha:
+ case GalBlendFactor.Src1AlphaGl:
+ return BlendingFactor.Src1Alpha;
+
+ case GalBlendFactor.OneMinusSrc1Alpha:
+ case GalBlendFactor.OneMinusSrc1AlphaGl:
+ return (BlendingFactor)BlendingFactorSrc.OneMinusSrc1Alpha;
case GalBlendFactor.ConstantColor:
- case GalBlendFactor.ConstantColorG80:
+ case GalBlendFactor.ConstantColorGl:
return BlendingFactor.ConstantColor;
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
index 6e1cabba..e81cf8a3 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
@@ -121,15 +121,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
StencilFrontOpZPass = GalStencilOp.Keep,
StencilFrontMask = UInt32.MaxValue,
- BlendEnabled = false,
- BlendSeparateAlpha = false,
-
- BlendEquationRgb = 0,
- BlendFuncSrcRgb = GalBlendFactor.One,
- BlendFuncDstRgb = GalBlendFactor.Zero,
- BlendEquationAlpha = 0,
- BlendFuncSrcAlpha = GalBlendFactor.One,
- BlendFuncDstAlpha = GalBlendFactor.Zero,
+ BlendIndependent = false,
PrimitiveRestartEnabled = false,
PrimitiveRestartIndex = 0
@@ -137,7 +129,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
{
- Old.ColorMasks[Index] = ColorMaskRgba.Default;
+ Old.Blends[Index] = BlendState.Default;
+
+ Old.ColorMasks[Index] = ColorMaskState.Default;
}
}
@@ -268,49 +262,22 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
}
- if (New.BlendEnabled != Old.BlendEnabled)
+ if (New.BlendIndependent)
{
- Enable(EnableCap.Blend, New.BlendEnabled);
+ for (int Index = 0; Index < GalPipelineState.RenderTargetsCount; Index++)
+ {
+ SetBlendState(Index, New.Blends[Index], Old.Blends[Index]);
+ }
}
-
- if (New.BlendEnabled)
+ else
{
- if (New.BlendSeparateAlpha)
+ if (New.BlendIndependent != Old.BlendIndependent)
{
- if (New.BlendEquationRgb != Old.BlendEquationRgb ||
- New.BlendEquationAlpha != Old.BlendEquationAlpha)
- {
- GL.BlendEquationSeparate(
- OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb),
- OGLEnumConverter.GetBlendEquation(New.BlendEquationAlpha));
- }
-
- if (New.BlendFuncSrcRgb != Old.BlendFuncSrcRgb ||
- New.BlendFuncDstRgb != Old.BlendFuncDstRgb ||
- New.BlendFuncSrcAlpha != Old.BlendFuncSrcAlpha ||
- New.BlendFuncDstAlpha != Old.BlendFuncDstAlpha)
- {
- GL.BlendFuncSeparate(
- (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
- (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb),
- (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcAlpha),
- (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.BlendFuncDstAlpha));
- }
+ SetAllBlendState(New.Blends[0]);
}
else
{
- if (New.BlendEquationRgb != Old.BlendEquationRgb)
- {
- GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.BlendEquationRgb));
- }
-
- if (New.BlendFuncSrcRgb != Old.BlendFuncSrcRgb ||
- New.BlendFuncDstRgb != Old.BlendFuncDstRgb)
- {
- GL.BlendFunc(
- OGLEnumConverter.GetBlendFactor(New.BlendFuncSrcRgb),
- OGLEnumConverter.GetBlendFactor(New.BlendFuncDstRgb));
- }
+ SetBlendState(New.Blends[0], Old.Blends[0]);
}
}
@@ -357,6 +324,136 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Old = New;
}
+ private void SetAllBlendState(BlendState New)
+ {
+ Enable(EnableCap.Blend, New.Enabled);
+
+ if (New.Enabled)
+ {
+ if (New.SeparateAlpha)
+ {
+ GL.BlendEquationSeparate(
+ OGLEnumConverter.GetBlendEquation(New.EquationRgb),
+ OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
+
+ GL.BlendFuncSeparate(
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
+ }
+ else
+ {
+ GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.EquationRgb));
+
+ GL.BlendFunc(
+ OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
+ OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
+ }
+ }
+ }
+
+ private void SetBlendState(BlendState New, BlendState Old)
+ {
+ if (New.Enabled != Old.Enabled)
+ {
+ Enable(EnableCap.Blend, New.Enabled);
+ }
+
+ if (New.Enabled)
+ {
+ if (New.SeparateAlpha)
+ {
+ if (New.EquationRgb != Old.EquationRgb ||
+ New.EquationAlpha != Old.EquationAlpha)
+ {
+ GL.BlendEquationSeparate(
+ OGLEnumConverter.GetBlendEquation(New.EquationRgb),
+ OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
+ }
+
+ if (New.FuncSrcRgb != Old.FuncSrcRgb ||
+ New.FuncDstRgb != Old.FuncDstRgb ||
+ New.FuncSrcAlpha != Old.FuncSrcAlpha ||
+ New.FuncDstAlpha != Old.FuncDstAlpha)
+ {
+ GL.BlendFuncSeparate(
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
+ }
+ }
+ else
+ {
+ if (New.EquationRgb != Old.EquationRgb)
+ {
+ GL.BlendEquation(OGLEnumConverter.GetBlendEquation(New.EquationRgb));
+ }
+
+ if (New.FuncSrcRgb != Old.FuncSrcRgb ||
+ New.FuncDstRgb != Old.FuncDstRgb)
+ {
+ GL.BlendFunc(
+ OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
+ OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
+ }
+ }
+ }
+ }
+
+ private void SetBlendState(int Index, BlendState New, BlendState Old)
+ {
+ if (New.Enabled != Old.Enabled)
+ {
+ Enable(IndexedEnableCap.Blend, Index, New.Enabled);
+ }
+
+ if (New.Enabled)
+ {
+ if (New.SeparateAlpha)
+ {
+ if (New.EquationRgb != Old.EquationRgb ||
+ New.EquationAlpha != Old.EquationAlpha)
+ {
+ GL.BlendEquationSeparate(
+ Index,
+ OGLEnumConverter.GetBlendEquation(New.EquationRgb),
+ OGLEnumConverter.GetBlendEquation(New.EquationAlpha));
+ }
+
+ if (New.FuncSrcRgb != Old.FuncSrcRgb ||
+ New.FuncDstRgb != Old.FuncDstRgb ||
+ New.FuncSrcAlpha != Old.FuncSrcAlpha ||
+ New.FuncDstAlpha != Old.FuncDstAlpha)
+ {
+ GL.BlendFuncSeparate(
+ Index,
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb),
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcAlpha),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstAlpha));
+ }
+ }
+ else
+ {
+ if (New.EquationRgb != Old.EquationRgb)
+ {
+ GL.BlendEquation(Index, OGLEnumConverter.GetBlendEquation(New.EquationRgb));
+ }
+
+ if (New.FuncSrcRgb != Old.FuncSrcRgb ||
+ New.FuncDstRgb != Old.FuncDstRgb)
+ {
+ GL.BlendFunc(
+ Index,
+ (BlendingFactorSrc) OGLEnumConverter.GetBlendFactor(New.FuncSrcRgb),
+ (BlendingFactorDest)OGLEnumConverter.GetBlendFactor(New.FuncDstRgb));
+ }
+ }
+ }
+ }
+
private void BindConstBuffers(GalPipelineState New)
{
int FreeBinding = OGLShader.ReservedCbufCount;
@@ -640,6 +737,18 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
}
+ private void Enable(IndexedEnableCap Cap, int Index, bool Enabled)
+ {
+ if (Enabled)
+ {
+ GL.Enable(Cap, Index);
+ }
+ else
+ {
+ GL.Disable(Cap, Index);
+ }
+ }
+
public void ResetDepthMask()
{
Old.DepthWriteEnabled = true;
@@ -647,7 +756,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void ResetColorMask(int Index)
{
- Old.ColorMasks[Index] = ColorMaskRgba.Default;
+ Old.ColorMasks[Index] = ColorMaskState.Default;
}
}
} \ No newline at end of file