From 53436e81f5a3d4d9a0c63f3dbe81bd70c33c291f Mon Sep 17 00:00:00 2001
From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com>
Date: Wed, 28 Aug 2024 20:25:41 -0700
Subject: [PATCH] fix GDI+ on Linux (again)

---
 .../Controls/GDIPlusControl.cs                | 32 +++++++++++++------
 .../GDIPlus/GDIPlusControlRenderTarget.cs     | 22 ++++++-------
 .../GDIPlus/IGL_GDIPlus.cs                    |  2 +-
 3 files changed, 34 insertions(+), 22 deletions(-)

diff --git a/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs b/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs
index 1bbb4810a2..0fa9fa78df 100644
--- a/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs
+++ b/src/BizHawk.Bizware.Graphics.Controls/Controls/GDIPlusControl.cs
@@ -1,9 +1,6 @@
-using System.Drawing;
 using System.Drawing.Drawing2D;
 using System.Windows.Forms;
 
-using SDGraphics = System.Drawing.Graphics;
-
 namespace BizHawk.Bizware.Graphics.Controls
 {
 	internal sealed class GDIPlusControl : GraphicsControl
@@ -13,22 +10,27 @@ namespace BizHawk.Bizware.Graphics.Controls
 		/// </summary>
 		private readonly GDIPlusControlRenderTarget _renderTarget;
 
-		public GDIPlusControl(Func<Func<(SDGraphics Graphics, Rectangle Rectangle)>, GDIPlusControlRenderTarget> createControlRenderTarget)
+		public GDIPlusControl(Func<Func<GDIPlusControlRenderContext>, GDIPlusControlRenderTarget> createControlRenderTarget)
 		{
 			_renderTarget = createControlRenderTarget(GetControlRenderContext);
 
 			SetStyle(ControlStyles.UserPaint, true);
 			SetStyle(ControlStyles.Opaque, true);
+			SetStyle(ControlStyles.AllPaintingInWmPaint, true);
 			SetStyle(ControlStyles.UserMouse, true);
-			DoubleBuffered = true;
+			DoubleBuffered = false;
 		}
 
-		private (SDGraphics Graphics, Rectangle Rectangle) GetControlRenderContext()
+		private GDIPlusControlRenderContext GetControlRenderContext()
 		{
 			var graphics = CreateGraphics();
 			graphics.CompositingMode = CompositingMode.SourceCopy;
 			graphics.CompositingQuality = CompositingQuality.HighSpeed;
-			return (graphics, ClientRectangle);
+			return new(graphics, ClientRectangle with
+			{
+				Width = Math.Max(ClientRectangle.Width, 1),
+				Height = Math.Max(ClientRectangle.Height, 1)
+			});
 		}
 
 		public override void AllowTearing(bool state)
@@ -52,7 +54,7 @@ namespace BizHawk.Bizware.Graphics.Controls
 		protected override void OnHandleCreated(EventArgs e)
 		{
 			base.OnHandleCreated(e);
-			_renderTarget.CreateGraphics();
+			_renderTarget.CreateBufferedGraphics();
 		}
 
 		protected override void OnHandleDestroyed(EventArgs e)
@@ -64,10 +66,20 @@ namespace BizHawk.Bizware.Graphics.Controls
 		protected override void OnResize(EventArgs e)
 		{
 			base.OnResize(e);
-			_renderTarget.CreateGraphics();
+			_renderTarget.CreateBufferedGraphics();
 		}
 
 		public override void SwapBuffers()
-			=> _renderTarget.BufferedGraphics?.Render(_renderTarget.ControlGraphics);
+		{
+			if (_renderTarget.BufferedGraphics is null)
+			{
+				return;
+			}
+
+			using var graphics = CreateGraphics();
+			graphics.CompositingMode = CompositingMode.SourceCopy;
+			graphics.CompositingQuality = CompositingQuality.HighSpeed;
+			_renderTarget.BufferedGraphics.Render(graphics);
+		}
 	}
 }
diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusControlRenderTarget.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusControlRenderTarget.cs
index 8d80232ece..2297343424 100644
--- a/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusControlRenderTarget.cs
+++ b/src/BizHawk.Bizware.Graphics/GDIPlus/GDIPlusControlRenderTarget.cs
@@ -4,35 +4,35 @@ using SDGraphics = System.Drawing.Graphics;
 
 namespace BizHawk.Bizware.Graphics
 {
+	public readonly record struct GDIPlusControlRenderContext(SDGraphics Graphics, Rectangle Rectangle) : IDisposable
+	{
+		public void Dispose()
+			=> Graphics.Dispose();
+	}
+
 	public sealed class GDIPlusControlRenderTarget : IDisposable
 	{
-		private readonly Func<(SDGraphics, Rectangle)> _getControlRenderContext;
+		private readonly Func<GDIPlusControlRenderContext> _getControlRenderContext;
 		private BufferedGraphicsContext _bufferedGraphicsContext = new();
 
-		public SDGraphics ControlGraphics;
 		public BufferedGraphics BufferedGraphics;
 
-		internal GDIPlusControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext)
+		internal GDIPlusControlRenderTarget(Func<GDIPlusControlRenderContext> getControlRenderContext)
 			=> _getControlRenderContext = getControlRenderContext;
 
 		public void Dispose()
 		{
-			ControlGraphics?.Dispose();
-			ControlGraphics = null;
 			BufferedGraphics?.Dispose();
 			BufferedGraphics = null;
 			_bufferedGraphicsContext?.Dispose();
 			_bufferedGraphicsContext = null;
 		}
 
-		public void CreateGraphics()
+		public void CreateBufferedGraphics()
 		{
-			ControlGraphics?.Dispose();
 			BufferedGraphics?.Dispose();
-			(ControlGraphics, var r) = _getControlRenderContext();
-			r.Width = Math.Max(1, r.Width);
-			r.Height = Math.Max(1, r.Height);
-			BufferedGraphics = _bufferedGraphicsContext.Allocate(ControlGraphics, r);
+			using var controlRenderContext = _getControlRenderContext();
+			BufferedGraphics = _bufferedGraphicsContext.Allocate(controlRenderContext.Graphics, controlRenderContext.Rectangle);
 		}
 	}
 }
diff --git a/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs b/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs
index 1a6dcb9bc4..17534c1fc4 100644
--- a/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs
+++ b/src/BizHawk.Bizware.Graphics/GDIPlus/IGL_GDIPlus.cs
@@ -90,7 +90,7 @@ namespace BizHawk.Bizware.Graphics
 		public void BindDefaultRenderTarget()
 			=> CurRenderTarget = null;
 
-		public GDIPlusControlRenderTarget CreateControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext)
+		public GDIPlusControlRenderTarget CreateControlRenderTarget(Func<GDIPlusControlRenderContext> getControlRenderContext)
 		{
 			if (_controlRenderTarget != null)
 			{