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.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);
}
}
}

View File

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

View File

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