diff --git a/Ryujinx.Graphics.GAL/IPipeline.cs b/Ryujinx.Graphics.GAL/IPipeline.cs
index e365529bfa..3eb778e08e 100644
--- a/Ryujinx.Graphics.GAL/IPipeline.cs
+++ b/Ryujinx.Graphics.GAL/IPipeline.cs
@@ -42,6 +42,8 @@ namespace Ryujinx.Graphics.GAL
void SetImage(int index, ShaderStage stage, ITexture texture);
+ void SetLogicOpState(bool enable, LogicalOp op);
+
void SetOrigin(Origin origin);
void SetPointSize(float size);
diff --git a/Ryujinx.Graphics.GAL/LogicalOp.cs b/Ryujinx.Graphics.GAL/LogicalOp.cs
new file mode 100644
index 0000000000..848215d0cd
--- /dev/null
+++ b/Ryujinx.Graphics.GAL/LogicalOp.cs
@@ -0,0 +1,22 @@
+namespace Ryujinx.Graphics.GAL
+{
+ public enum LogicalOp
+ {
+ Clear = 0x1500,
+ And = 0x1501,
+ AndReverse = 0x1502,
+ Copy = 0x1503,
+ AndInverted = 0x1504,
+ Noop = 0x1505,
+ Xor = 0x1506,
+ Or = 0x1507,
+ Nor = 0x1508,
+ Equiv = 0x1509,
+ Invert = 0x150A,
+ OrReverse = 0x150B,
+ CopyInverted = 0x150C,
+ OrInverted = 0x150D,
+ Nand = 0x150E,
+ Set = 0x150F
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/Engine/Methods.cs b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
index 5677c8a054..06298cdf38 100644
--- a/Ryujinx.Graphics.Gpu/Engine/Methods.cs
+++ b/Ryujinx.Graphics.Gpu/Engine/Methods.cs
@@ -252,6 +252,11 @@ namespace Ryujinx.Graphics.Gpu.Engine
UpdateBlendState(state);
}
+ if (state.QueryModified(MethodOffset.LogicOpState))
+ {
+ UpdateLogicOpState(state);
+ }
+
CommitBindings();
}
@@ -875,6 +880,17 @@ namespace Ryujinx.Graphics.Gpu.Engine
}
}
+ ///
+ /// Updates host logical operation state, based on guest state.
+ ///
+ /// Current GPU state
+ public void UpdateLogicOpState(GpuState state)
+ {
+ LogicalOpState logicOpState = state.Get(MethodOffset.LogicOpState);
+
+ _context.Renderer.Pipeline.SetLogicOpState(logicOpState.Enable, logicOpState.LogicalOp);
+ }
+
///
/// Storage buffer address and size information.
///
diff --git a/Ryujinx.Graphics.Gpu/State/LogicalOpState.cs b/Ryujinx.Graphics.Gpu/State/LogicalOpState.cs
new file mode 100644
index 0000000000..d052a45c60
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/State/LogicalOpState.cs
@@ -0,0 +1,12 @@
+using Ryujinx.Graphics.GAL;
+
+namespace Ryujinx.Graphics.Gpu.State
+{
+ struct LogicalOpState
+ {
+#pragma warning disable CS0649
+ public Boolean32 Enable;
+ public LogicalOp LogicalOp;
+#pragma warning restore CS0649
+ }
+}
diff --git a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
index 2e0a197e2a..d7d5d90391 100644
--- a/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
+++ b/Ryujinx.Graphics.Gpu/State/MethodOffset.cs
@@ -92,6 +92,7 @@ namespace Ryujinx.Graphics.Gpu.State
FaceState = 0x646,
ViewportTransformEnable = 0x64b,
ViewVolumeClipControl = 0x64f,
+ LogicOpState = 0x671,
Clear = 0x674,
RtColorMask = 0x680,
ReportState = 0x6c0,
diff --git a/Ryujinx.Graphics.OpenGL/EnumConversion.cs b/Ryujinx.Graphics.OpenGL/EnumConversion.cs
index aebe54fa57..a4bd39ccaf 100644
--- a/Ryujinx.Graphics.OpenGL/EnumConversion.cs
+++ b/Ryujinx.Graphics.OpenGL/EnumConversion.cs
@@ -443,5 +443,48 @@ namespace Ryujinx.Graphics.OpenGL
return NvViewportSwizzle.ViewportSwizzlePositiveXNv;
}
+
+ public static All Convert(this LogicalOp op)
+ {
+ switch (op)
+ {
+ case LogicalOp.Clear:
+ return All.Clear;
+ case LogicalOp.And:
+ return All.And;
+ case LogicalOp.AndReverse:
+ return All.AndReverse;
+ case LogicalOp.Copy:
+ return All.Copy;
+ case LogicalOp.AndInverted:
+ return All.AndInverted;
+ case LogicalOp.Noop:
+ return All.Noop;
+ case LogicalOp.Xor:
+ return All.Xor;
+ case LogicalOp.Or:
+ return All.Or;
+ case LogicalOp.Nor:
+ return All.Nor;
+ case LogicalOp.Equiv:
+ return All.Equiv;
+ case LogicalOp.Invert:
+ return All.Invert;
+ case LogicalOp.OrReverse:
+ return All.OrReverse;
+ case LogicalOp.CopyInverted:
+ return All.CopyInverted;
+ case LogicalOp.OrInverted:
+ return All.OrInverted;
+ case LogicalOp.Nand:
+ return All.Nand;
+ case LogicalOp.Set:
+ return All.Set;
+ }
+
+ Logger.PrintDebug(LogClass.Gpu, $"Invalid {nameof(LogicalOp)} enum value: {op}.");
+
+ return All.Never;
+ }
}
}
diff --git a/Ryujinx.Graphics.OpenGL/Pipeline.cs b/Ryujinx.Graphics.OpenGL/Pipeline.cs
index 62e5394e10..9623c826f8 100644
--- a/Ryujinx.Graphics.OpenGL/Pipeline.cs
+++ b/Ryujinx.Graphics.OpenGL/Pipeline.cs
@@ -547,6 +547,20 @@ namespace Ryujinx.Graphics.OpenGL
GL.Enable(IndexedEnableCap.Blend, index);
}
+ public void SetLogicOpState(bool enable, LogicalOp op)
+ {
+ if (enable)
+ {
+ GL.Enable(EnableCap.ColorLogicOp);
+
+ GL.LogicOp((LogicOp)op.Convert());
+ }
+ else
+ {
+ GL.Disable(EnableCap.ColorLogicOp);
+ }
+ }
+
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
{
if ((enables & PolygonModeMask.Point) != 0)