fix GDI+ on Linux (again)

This commit is contained in:
CasualPokePlayer 2024-08-28 20:25:41 -07:00
parent ef028dfea4
commit 53436e81f5
3 changed files with 34 additions and 22 deletions

View File

@ -1,9 +1,6 @@
using System.Drawing;
using System.Drawing.Drawing2D; using System.Drawing.Drawing2D;
using System.Windows.Forms; using System.Windows.Forms;
using SDGraphics = System.Drawing.Graphics;
namespace BizHawk.Bizware.Graphics.Controls namespace BizHawk.Bizware.Graphics.Controls
{ {
internal sealed class GDIPlusControl : GraphicsControl internal sealed class GDIPlusControl : GraphicsControl
@ -13,22 +10,27 @@ namespace BizHawk.Bizware.Graphics.Controls
/// </summary> /// </summary>
private readonly GDIPlusControlRenderTarget _renderTarget; private readonly GDIPlusControlRenderTarget _renderTarget;
public GDIPlusControl(Func<Func<(SDGraphics Graphics, Rectangle Rectangle)>, GDIPlusControlRenderTarget> createControlRenderTarget) public GDIPlusControl(Func<Func<GDIPlusControlRenderContext>, GDIPlusControlRenderTarget> createControlRenderTarget)
{ {
_renderTarget = createControlRenderTarget(GetControlRenderContext); _renderTarget = createControlRenderTarget(GetControlRenderContext);
SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.UserPaint, true);
SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.Opaque, true);
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.UserMouse, true); SetStyle(ControlStyles.UserMouse, true);
DoubleBuffered = true; DoubleBuffered = false;
} }
private (SDGraphics Graphics, Rectangle Rectangle) GetControlRenderContext() private GDIPlusControlRenderContext GetControlRenderContext()
{ {
var graphics = CreateGraphics(); var graphics = CreateGraphics();
graphics.CompositingMode = CompositingMode.SourceCopy; graphics.CompositingMode = CompositingMode.SourceCopy;
graphics.CompositingQuality = CompositingQuality.HighSpeed; 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) public override void AllowTearing(bool state)
@ -52,7 +54,7 @@ namespace BizHawk.Bizware.Graphics.Controls
protected override void OnHandleCreated(EventArgs e) protected override void OnHandleCreated(EventArgs e)
{ {
base.OnHandleCreated(e); base.OnHandleCreated(e);
_renderTarget.CreateGraphics(); _renderTarget.CreateBufferedGraphics();
} }
protected override void OnHandleDestroyed(EventArgs e) protected override void OnHandleDestroyed(EventArgs e)
@ -64,10 +66,20 @@ namespace BizHawk.Bizware.Graphics.Controls
protected override void OnResize(EventArgs e) protected override void OnResize(EventArgs e)
{ {
base.OnResize(e); base.OnResize(e);
_renderTarget.CreateGraphics(); _renderTarget.CreateBufferedGraphics();
} }
public override void SwapBuffers() 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);
}
} }
} }

View File

@ -4,35 +4,35 @@ using SDGraphics = System.Drawing.Graphics;
namespace BizHawk.Bizware.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 public sealed class GDIPlusControlRenderTarget : IDisposable
{ {
private readonly Func<(SDGraphics, Rectangle)> _getControlRenderContext; private readonly Func<GDIPlusControlRenderContext> _getControlRenderContext;
private BufferedGraphicsContext _bufferedGraphicsContext = new(); private BufferedGraphicsContext _bufferedGraphicsContext = new();
public SDGraphics ControlGraphics;
public BufferedGraphics BufferedGraphics; public BufferedGraphics BufferedGraphics;
internal GDIPlusControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext) internal GDIPlusControlRenderTarget(Func<GDIPlusControlRenderContext> getControlRenderContext)
=> _getControlRenderContext = getControlRenderContext; => _getControlRenderContext = getControlRenderContext;
public void Dispose() public void Dispose()
{ {
ControlGraphics?.Dispose();
ControlGraphics = null;
BufferedGraphics?.Dispose(); BufferedGraphics?.Dispose();
BufferedGraphics = null; BufferedGraphics = null;
_bufferedGraphicsContext?.Dispose(); _bufferedGraphicsContext?.Dispose();
_bufferedGraphicsContext = null; _bufferedGraphicsContext = null;
} }
public void CreateGraphics() public void CreateBufferedGraphics()
{ {
ControlGraphics?.Dispose();
BufferedGraphics?.Dispose(); BufferedGraphics?.Dispose();
(ControlGraphics, var r) = _getControlRenderContext(); using var controlRenderContext = _getControlRenderContext();
r.Width = Math.Max(1, r.Width); BufferedGraphics = _bufferedGraphicsContext.Allocate(controlRenderContext.Graphics, controlRenderContext.Rectangle);
r.Height = Math.Max(1, r.Height);
BufferedGraphics = _bufferedGraphicsContext.Allocate(ControlGraphics, r);
} }
} }
} }

View File

@ -90,7 +90,7 @@ namespace BizHawk.Bizware.Graphics
public void BindDefaultRenderTarget() public void BindDefaultRenderTarget()
=> CurRenderTarget = null; => CurRenderTarget = null;
public GDIPlusControlRenderTarget CreateControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext) public GDIPlusControlRenderTarget CreateControlRenderTarget(Func<GDIPlusControlRenderContext> getControlRenderContext)
{ {
if (_controlRenderTarget != null) if (_controlRenderTarget != null)
{ {