Change RenderTarget to IRenderTarget, implement classes accordingly
Changes GDI+ handling quite a bit, hopefully didn't break anything
This commit is contained in:
parent
25f62c6620
commit
8aac335d9b
|
@ -9,15 +9,19 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
{
|
||||
internal sealed class GDIPlusControl : GraphicsControl
|
||||
{
|
||||
public GDIPlusControl(Func<Func<(SDGraphics Graphics, Rectangle Rectangle)>, GDIPlusRenderTarget> createControlRenderTarget)
|
||||
/// <summary>
|
||||
/// The render target for rendering to this control
|
||||
/// </summary>
|
||||
private readonly GDIPlusControlRenderTarget _renderTarget;
|
||||
|
||||
public GDIPlusControl(Func<Func<(SDGraphics Graphics, Rectangle Rectangle)>, GDIPlusControlRenderTarget> createControlRenderTarget)
|
||||
{
|
||||
RenderTarget = createControlRenderTarget(GetControlRenderContext);
|
||||
_renderTarget = createControlRenderTarget(GetControlRenderContext);
|
||||
|
||||
SetStyle(ControlStyles.UserPaint, true);
|
||||
SetStyle(ControlStyles.Opaque, true);
|
||||
SetStyle(ControlStyles.UserMouse, true);
|
||||
DoubleBuffered = true;
|
||||
BackColor = Color.Black;
|
||||
}
|
||||
|
||||
private (SDGraphics Graphics, Rectangle Rectangle) GetControlRenderContext()
|
||||
|
@ -28,11 +32,6 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
return (graphics, ClientRectangle);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The render target for rendering to this control
|
||||
/// </summary>
|
||||
private GDIPlusRenderTarget RenderTarget { get; }
|
||||
|
||||
public override void AllowTearing(bool state)
|
||||
{
|
||||
// not controllable
|
||||
|
@ -54,22 +53,22 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
protected override void OnHandleCreated(EventArgs e)
|
||||
{
|
||||
base.OnHandleCreated(e);
|
||||
RenderTarget.CreateGraphics();
|
||||
_renderTarget.CreateGraphics();
|
||||
}
|
||||
|
||||
protected override void OnHandleDestroyed(EventArgs e)
|
||||
{
|
||||
base.OnHandleDestroyed(e);
|
||||
RenderTarget.Dispose();
|
||||
_renderTarget.Dispose();
|
||||
}
|
||||
|
||||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
RenderTarget.CreateGraphics();
|
||||
_renderTarget.CreateGraphics();
|
||||
}
|
||||
|
||||
public override void SwapBuffers()
|
||||
=> RenderTarget.BufferedGraphics?.Render(RenderTarget.CurGraphics);
|
||||
=> _renderTarget.BufferedGraphics?.Render(_renderTarget.ControlGraphics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using Vortice.Direct3D11;
|
||||
using Vortice.DXGI;
|
||||
|
||||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
internal sealed class D3D11RenderTarget : D3D11Texture2D, IRenderTarget
|
||||
{
|
||||
public ID3D11RenderTargetView RTV;
|
||||
|
||||
public D3D11RenderTarget(D3D11Resources resources, int width, int height)
|
||||
: base(resources, BindFlags.ShaderResource | BindFlags.RenderTarget, ResourceUsage.Default, CpuAccessFlags.None, width, height)
|
||||
{
|
||||
}
|
||||
|
||||
public override void CreateTexture()
|
||||
{
|
||||
base.CreateTexture();
|
||||
var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm);
|
||||
RTV = Device.CreateRenderTargetView(Texture, rtvd);
|
||||
}
|
||||
|
||||
public override void DestroyTexture()
|
||||
{
|
||||
RTV?.Dispose();
|
||||
RTV = null;
|
||||
base.DestroyTexture();
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
Context.OMSetRenderTargets(RTV);
|
||||
_resources.CurRenderTarget = this;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> $"D3D11 RenderTarget: {Width}x{Height}";
|
||||
}
|
||||
}
|
|
@ -26,8 +26,9 @@ namespace BizHawk.Bizware.Graphics
|
|||
|
||||
public FeatureLevel DeviceFeatureLevel;
|
||||
|
||||
public readonly HashSet<RenderTarget> RenderTargets = new();
|
||||
public readonly HashSet<D3D11Texture2D> ShaderTextures = new();
|
||||
public D3D11RenderTarget CurRenderTarget;
|
||||
|
||||
public readonly HashSet<D3D11Texture2D> Textures = new();
|
||||
public readonly HashSet<Shader> VertexShaders = new();
|
||||
public readonly HashSet<Shader> PixelShaders = new();
|
||||
public readonly HashSet<Pipeline> Pipelines = new();
|
||||
|
@ -94,6 +95,11 @@ namespace BizHawk.Bizware.Graphics
|
|||
RasterizerState = Device.CreateRasterizerState(rd);
|
||||
|
||||
Context.IASetPrimitiveTopology(PrimitiveTopology.TriangleStrip);
|
||||
|
||||
foreach (var tex2d in Textures)
|
||||
{
|
||||
tex2d.CreateTexture();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -102,8 +108,15 @@ namespace BizHawk.Bizware.Graphics
|
|||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public void DestroyResources()
|
||||
{
|
||||
foreach (var tex2d in Textures)
|
||||
{
|
||||
tex2d.DestroyTexture();
|
||||
}
|
||||
|
||||
CurRenderTarget = null;
|
||||
|
||||
LinearSamplerState?.Dispose();
|
||||
LinearSamplerState = null;
|
||||
PointSamplerState?.Dispose();
|
||||
|
@ -128,5 +141,11 @@ namespace BizHawk.Bizware.Graphics
|
|||
Factory1?.Dispose();
|
||||
Factory1 = null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DestroyResources();
|
||||
Textures.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,18 +10,18 @@ namespace BizHawk.Bizware.Graphics
|
|||
{
|
||||
internal class D3D11Texture2D : ITexture2D
|
||||
{
|
||||
private readonly D3D11Resources _resources;
|
||||
protected readonly D3D11Resources _resources;
|
||||
private readonly BindFlags _bindFlags;
|
||||
private readonly ResourceUsage _usage;
|
||||
private readonly CpuAccessFlags _cpuAccessFlags;
|
||||
|
||||
private ID3D11Device Device => _resources.Device;
|
||||
private ID3D11DeviceContext Context => _resources.Context;
|
||||
private HashSet<D3D11Texture2D> ShaderTextures => _resources.ShaderTextures;
|
||||
protected ID3D11Device Device => _resources.Device;
|
||||
protected ID3D11DeviceContext Context => _resources.Context;
|
||||
private HashSet<D3D11Texture2D> Textures => _resources.Textures;
|
||||
|
||||
private ID3D11Texture2D StagingTexture;
|
||||
|
||||
public ID3D11Texture2D Texture;
|
||||
protected ID3D11Texture2D Texture;
|
||||
public ID3D11ShaderResourceView SRV;
|
||||
public bool LinearFiltering;
|
||||
|
||||
|
@ -37,17 +37,18 @@ namespace BizHawk.Bizware.Graphics
|
|||
_cpuAccessFlags = cpuAccessFlags;
|
||||
Width = width;
|
||||
Height = height;
|
||||
// ReSharper disable once VirtualMemberCallInConstructor
|
||||
CreateTexture();
|
||||
ShaderTextures.Add(this);
|
||||
Textures.Add(this);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DestroyTexture();
|
||||
ShaderTextures.Remove(this);
|
||||
Textures.Remove(this);
|
||||
}
|
||||
|
||||
public void CreateTexture()
|
||||
public virtual void CreateTexture()
|
||||
{
|
||||
Texture = Device.CreateTexture2D(
|
||||
Format.B8G8R8A8_UNorm,
|
||||
|
@ -62,7 +63,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
SRV = Device.CreateShaderResourceView(Texture, srvd);
|
||||
}
|
||||
|
||||
public void DestroyTexture()
|
||||
public virtual void DestroyTexture()
|
||||
{
|
||||
SRV?.Dispose();
|
||||
SRV = null;
|
||||
|
|
|
@ -38,10 +38,10 @@ namespace BizHawk.Bizware.Graphics
|
|||
private ID3D11RasterizerState RasterizerState => _resources.RasterizerState;
|
||||
|
||||
private FeatureLevel DeviceFeatureLevel => _resources.DeviceFeatureLevel;
|
||||
private D3D11RenderTarget CurRenderTarget => _resources.CurRenderTarget;
|
||||
|
||||
// rendering state
|
||||
private Pipeline _curPipeline;
|
||||
private RenderTarget _curRenderTarget;
|
||||
private D3D11SwapChain.SwapChainResources _controlSwapChain;
|
||||
|
||||
public IGL_D3D11()
|
||||
|
@ -151,32 +151,9 @@ namespace BizHawk.Bizware.Graphics
|
|||
sw.PS = null;
|
||||
}
|
||||
|
||||
foreach (var rw in _resources.RenderTargets.Select(rt => (RenderTargetWrapper)rt.Opaque))
|
||||
{
|
||||
rw.RTV.Dispose();
|
||||
rw.RTV = null;
|
||||
}
|
||||
|
||||
foreach (var tex2d in _resources.ShaderTextures)
|
||||
{
|
||||
tex2d.DestroyTexture();
|
||||
}
|
||||
|
||||
_resources.Dispose();
|
||||
_resources.DestroyResources();
|
||||
_resources.CreateResources();
|
||||
|
||||
foreach (var tex2d in _resources.ShaderTextures)
|
||||
{
|
||||
tex2d.CreateTexture();
|
||||
}
|
||||
|
||||
foreach (var rt in _resources.RenderTargets)
|
||||
{
|
||||
var rw = (RenderTargetWrapper)rt.Opaque;
|
||||
var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm);
|
||||
rw.RTV = Device.CreateRenderTargetView(((D3D11Texture2D)rt.Texture2D).Texture, rtvd);
|
||||
}
|
||||
|
||||
foreach (var sw in _resources.VertexShaders.Select(vertexShader => (ShaderWrapper)vertexShader.Opaque))
|
||||
{
|
||||
sw.VS = Device.CreateVertexShader(sw.Bytecode.Span);
|
||||
|
@ -264,17 +241,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
}
|
||||
|
||||
public void ClearColor(Color color)
|
||||
{
|
||||
if (_curRenderTarget == null)
|
||||
{
|
||||
Context.ClearRenderTargetView(_controlSwapChain.RTV, new(color.R, color.B, color.G, color.A));
|
||||
}
|
||||
else
|
||||
{
|
||||
var rw = (RenderTargetWrapper)_curRenderTarget.Opaque;
|
||||
Context.ClearRenderTargetView(rw.RTV, new(color.R, color.B, color.G, color.A));
|
||||
}
|
||||
}
|
||||
=> Context.ClearRenderTargetView(CurRenderTarget?.RTV ?? _controlSwapChain.RTV, new(color.R, color.B, color.G, color.A));
|
||||
|
||||
private class ShaderWrapper // Disposable fields cleaned up by Internal_FreeShader
|
||||
{
|
||||
|
@ -607,11 +574,6 @@ namespace BizHawk.Bizware.Graphics
|
|||
public ShaderWrapper VertexShader, FragmentShader;
|
||||
}
|
||||
|
||||
private class RenderTargetWrapper
|
||||
{
|
||||
public ID3D11RenderTargetView RTV;
|
||||
}
|
||||
|
||||
private class VertexLayoutWrapper
|
||||
{
|
||||
public ID3D11InputLayout VertexInputLayout;
|
||||
|
@ -875,36 +837,13 @@ namespace BizHawk.Bizware.Graphics
|
|||
Context.RSSetScissorRect(x, y, width, height);
|
||||
}
|
||||
|
||||
public void FreeRenderTarget(RenderTarget rt)
|
||||
public IRenderTarget CreateRenderTarget(int width, int height)
|
||||
=> new D3D11RenderTarget(_resources, width, height);
|
||||
|
||||
public void BindDefaultRenderTarget()
|
||||
{
|
||||
var rw = (RenderTargetWrapper)rt.Opaque;
|
||||
rw.RTV.Dispose();
|
||||
_resources.RenderTargets.Remove(rt);
|
||||
rt.Texture2D.Dispose();
|
||||
}
|
||||
|
||||
public RenderTarget CreateRenderTarget(int width, int height)
|
||||
{
|
||||
var tex = new D3D11Texture2D(_resources, BindFlags.ShaderResource | BindFlags.RenderTarget, ResourceUsage.Default, CpuAccessFlags.None, width, height);
|
||||
var rtvd = new RenderTargetViewDescription(RenderTargetViewDimension.Texture2D, Format.B8G8R8A8_UNorm);
|
||||
var rw = new RenderTargetWrapper { RTV = Device.CreateRenderTargetView(tex.Texture, rtvd) };
|
||||
var rt = new RenderTarget(this, rw, tex);
|
||||
_resources.RenderTargets.Add(rt);
|
||||
return rt;
|
||||
}
|
||||
|
||||
public void BindRenderTarget(RenderTarget rt)
|
||||
{
|
||||
_curRenderTarget = rt;
|
||||
|
||||
if (rt == null)
|
||||
{
|
||||
Context.OMSetRenderTargets(_controlSwapChain.RTV);
|
||||
return;
|
||||
}
|
||||
|
||||
var rw = (RenderTargetWrapper)rt.Opaque;
|
||||
Context.OMSetRenderTargets(rw.RTV);
|
||||
_resources.CurRenderTarget = null;
|
||||
Context.OMSetRenderTargets(_controlSwapChain.RTV);
|
||||
}
|
||||
|
||||
public void Draw(IntPtr data, int count)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
using SDGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
public sealed class GDIPlusControlRenderTarget : IDisposable
|
||||
{
|
||||
private readonly Func<(SDGraphics, Rectangle)> _getControlRenderContext;
|
||||
private BufferedGraphicsContext _bufferedGraphicsContext = new();
|
||||
|
||||
public SDGraphics ControlGraphics;
|
||||
public BufferedGraphics BufferedGraphics;
|
||||
|
||||
internal GDIPlusControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext)
|
||||
=> _getControlRenderContext = getControlRenderContext;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ControlGraphics?.Dispose();
|
||||
ControlGraphics = null;
|
||||
BufferedGraphics?.Dispose();
|
||||
BufferedGraphics = null;
|
||||
_bufferedGraphicsContext?.Dispose();
|
||||
_bufferedGraphicsContext = null;
|
||||
}
|
||||
|
||||
public void CreateGraphics()
|
||||
{
|
||||
ControlGraphics?.Dispose();
|
||||
BufferedGraphics?.Dispose();
|
||||
(ControlGraphics, var r) = _getControlRenderContext();
|
||||
BufferedGraphics = _bufferedGraphicsContext.Allocate(ControlGraphics, r);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +1,30 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
|
||||
using SDGraphics = System.Drawing.Graphics;
|
||||
|
||||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
public class GDIPlusRenderTarget : IDisposable
|
||||
internal sealed class GDIPlusRenderTarget : GDIPlusTexture2D, IRenderTarget
|
||||
{
|
||||
internal GDIPlusRenderTarget(Func<BufferedGraphicsContext> getBufferedGraphicsContext,
|
||||
Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext = null)
|
||||
private readonly IGL_GDIPlus _gdiPlus;
|
||||
public SDGraphics TextureGraphics;
|
||||
|
||||
internal GDIPlusRenderTarget(IGL_GDIPlus gdiPlus, int width, int height)
|
||||
: base(width, height)
|
||||
{
|
||||
_getBufferedGraphicsContext = getBufferedGraphicsContext;
|
||||
_getControlRenderContext = getControlRenderContext;
|
||||
_gdiPlus = gdiPlus;
|
||||
TextureGraphics = SDGraphics.FromImage(SDBitmap);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public override void Dispose()
|
||||
{
|
||||
if (_getControlRenderContext != null)
|
||||
{
|
||||
CurGraphics?.Dispose();
|
||||
CurGraphics = null;
|
||||
}
|
||||
|
||||
BufferedGraphics?.Dispose();
|
||||
BufferedGraphics = null;
|
||||
TextureGraphics?.Dispose();
|
||||
TextureGraphics = null;
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
private readonly Func<BufferedGraphicsContext> _getBufferedGraphicsContext;
|
||||
public void Bind()
|
||||
=> _gdiPlus.CurRenderTarget = this;
|
||||
|
||||
/// <summary>
|
||||
/// get Graphics and Rectangle from a control, if any
|
||||
/// </summary>
|
||||
private readonly Func<(SDGraphics, Rectangle)> _getControlRenderContext;
|
||||
|
||||
/// <summary>
|
||||
/// the offscreen render target, if that's what this is representing
|
||||
/// </summary>
|
||||
public RenderTarget Target;
|
||||
|
||||
public SDGraphics CurGraphics;
|
||||
public BufferedGraphics BufferedGraphics;
|
||||
|
||||
public void CreateGraphics()
|
||||
{
|
||||
Rectangle r;
|
||||
if (_getControlRenderContext != null)
|
||||
{
|
||||
(CurGraphics, r) = _getControlRenderContext();
|
||||
}
|
||||
else
|
||||
{
|
||||
var gtex = (GDIPlusTexture2D)Target.Texture2D;
|
||||
CurGraphics?.Dispose();
|
||||
CurGraphics = SDGraphics.FromImage(gtex.SDBitmap);
|
||||
r = gtex.GetRectangle();
|
||||
}
|
||||
|
||||
BufferedGraphics?.Dispose();
|
||||
BufferedGraphics = _getBufferedGraphicsContext().Allocate(CurGraphics, r);
|
||||
}
|
||||
public override string ToString()
|
||||
=> $"GDI+ RenderTarget: {Width}x{Height}";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ using System.Drawing.Imaging;
|
|||
|
||||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
public class GDIPlusTexture2D : ITexture2D
|
||||
internal class GDIPlusTexture2D : ITexture2D
|
||||
{
|
||||
public Bitmap SDBitmap;
|
||||
public bool LinearFiltering;
|
||||
|
@ -19,7 +19,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
SDBitmap = new(width, height, PixelFormat.Format32bppArgb);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public virtual void Dispose()
|
||||
{
|
||||
SDBitmap?.Dispose();
|
||||
SDBitmap = null;
|
||||
|
|
|
@ -5,15 +5,22 @@ using System.Numerics;
|
|||
|
||||
using SDGraphics = System.Drawing.Graphics;
|
||||
|
||||
//TODO - maybe a layer to cache Graphics parameters (notably, filtering) ?
|
||||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
public class IGL_GDIPlus : IGL
|
||||
{
|
||||
private GDIPlusControlRenderTarget _controlRenderTarget;
|
||||
|
||||
internal GDIPlusRenderTarget CurRenderTarget;
|
||||
|
||||
public EDispMethod DispMethodEnum => EDispMethod.GdiPlus;
|
||||
|
||||
public void Dispose()
|
||||
=> BufferedGraphicsContext.Dispose();
|
||||
{
|
||||
}
|
||||
|
||||
internal SDGraphics GetCurrentGraphics()
|
||||
=> CurRenderTarget?.TextureGraphics ?? _controlRenderTarget.BufferedGraphics.Graphics;
|
||||
|
||||
public void ClearColor(Color color)
|
||||
=> GetCurrentGraphics().Clear(color);
|
||||
|
@ -118,62 +125,21 @@ namespace BizHawk.Bizware.Graphics
|
|||
{
|
||||
}
|
||||
|
||||
public void FreeRenderTarget(RenderTarget rt)
|
||||
{
|
||||
var grt = (GDIPlusRenderTarget)rt.Opaque;
|
||||
grt.Dispose();
|
||||
}
|
||||
public IRenderTarget CreateRenderTarget(int width, int height)
|
||||
=> new GDIPlusRenderTarget(this, width, height);
|
||||
|
||||
public RenderTarget CreateRenderTarget(int width, int height)
|
||||
{
|
||||
var tex2d = new GDIPlusTexture2D(width, height);
|
||||
var grt = new GDIPlusRenderTarget(() => BufferedGraphicsContext);
|
||||
var rt = new RenderTarget(this, grt, tex2d);
|
||||
grt.Target = rt;
|
||||
return rt;
|
||||
}
|
||||
public void BindDefaultRenderTarget()
|
||||
=> CurRenderTarget = null;
|
||||
|
||||
public void BindRenderTarget(RenderTarget rt)
|
||||
{
|
||||
if (_currOffscreenGraphics != null)
|
||||
{
|
||||
_currOffscreenGraphics.Dispose();
|
||||
_currOffscreenGraphics = null;
|
||||
}
|
||||
|
||||
if (rt == null)
|
||||
{
|
||||
// null means to use the default RT for the current control
|
||||
CurrentRenderTarget = _controlRenderTarget;
|
||||
}
|
||||
else
|
||||
{
|
||||
var gtex = (GDIPlusTexture2D)rt.Texture2D;
|
||||
CurrentRenderTarget = (GDIPlusRenderTarget)rt.Opaque;
|
||||
_currOffscreenGraphics = SDGraphics.FromImage(gtex.SDBitmap);
|
||||
}
|
||||
}
|
||||
|
||||
private GDIPlusRenderTarget _controlRenderTarget;
|
||||
|
||||
public GDIPlusRenderTarget CreateControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext)
|
||||
public GDIPlusControlRenderTarget CreateControlRenderTarget(Func<(SDGraphics Graphics, Rectangle Rectangle)> getControlRenderContext)
|
||||
{
|
||||
if (_controlRenderTarget != null)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(IGL_GDIPlus)} can only have one control render target");
|
||||
}
|
||||
|
||||
_controlRenderTarget = new(() => BufferedGraphicsContext, getControlRenderContext);
|
||||
_controlRenderTarget = new(getControlRenderContext);
|
||||
return _controlRenderTarget;
|
||||
}
|
||||
|
||||
private SDGraphics _currOffscreenGraphics;
|
||||
|
||||
public SDGraphics GetCurrentGraphics()
|
||||
=> _currOffscreenGraphics ?? CurrentRenderTarget.BufferedGraphics.Graphics;
|
||||
|
||||
public GDIPlusRenderTarget CurrentRenderTarget;
|
||||
|
||||
public readonly BufferedGraphicsContext BufferedGraphicsContext = new();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,17 +19,17 @@ namespace BizHawk.Bizware.Graphics
|
|||
EDispMethod DispMethodEnum { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Clears the color buffer with the specified color
|
||||
/// Clears the currently bound render target with the specified color
|
||||
/// </summary>
|
||||
void ClearColor(Color color);
|
||||
|
||||
/// <summary>
|
||||
/// compile a fragment shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
|
||||
/// Compile a fragment shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
|
||||
/// </summary>
|
||||
Shader CreateFragmentShader(string source, string entry, bool required);
|
||||
|
||||
/// <summary>
|
||||
/// compile a vertex shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
|
||||
/// Compile a vertex shader. This is the simplified method. A more complex method may be added later which will accept multiple sources and preprocessor definitions independently
|
||||
/// </summary>
|
||||
Shader CreateVertexShader(string source, string entry, bool required);
|
||||
|
||||
|
@ -59,40 +59,40 @@ namespace BizHawk.Bizware.Graphics
|
|||
void SetPipelineUniformMatrix(PipelineUniform uniform, ref Matrix4x4 mat, bool transpose);
|
||||
|
||||
/// <summary>
|
||||
/// sets a uniform value
|
||||
/// Sets a uniform value
|
||||
/// </summary>
|
||||
void SetPipelineUniform(PipelineUniform uniform, Vector4 value);
|
||||
|
||||
/// <summary>
|
||||
/// sets a uniform value
|
||||
/// Sets a uniform value
|
||||
/// </summary>
|
||||
void SetPipelineUniform(PipelineUniform uniform, Vector2 value);
|
||||
|
||||
/// <summary>
|
||||
/// sets a uniform value
|
||||
/// Sets a uniform value
|
||||
/// </summary>
|
||||
void SetPipelineUniform(PipelineUniform uniform, float value);
|
||||
|
||||
/// <summary>
|
||||
/// sets uniform values
|
||||
/// Sets uniform values
|
||||
/// </summary>
|
||||
void SetPipelineUniform(PipelineUniform uniform, Vector4[] values);
|
||||
|
||||
/// <summary>
|
||||
/// sets a uniform value
|
||||
/// Sets a uniform value
|
||||
/// </summary>
|
||||
void SetPipelineUniform(PipelineUniform uniform, bool value);
|
||||
|
||||
/// <summary>
|
||||
/// Draws based on the currently set pipeline
|
||||
/// data contains vertexes based on the pipeline's VertexLayout
|
||||
/// count is the vertex count
|
||||
/// Data contains vertexes based on the pipeline's VertexLayout
|
||||
/// Count is the vertex count
|
||||
/// Vertexes must form triangle strips
|
||||
/// </summary>
|
||||
void Draw(IntPtr data, int count);
|
||||
|
||||
/// <summary>
|
||||
/// creates a vertex layout resource
|
||||
/// Creates a vertex layout resource
|
||||
/// </summary>
|
||||
VertexLayout CreateVertexLayout();
|
||||
|
||||
|
@ -119,35 +119,32 @@ namespace BizHawk.Bizware.Graphics
|
|||
ITexture2D WrapGLTexture2D(int glTexId, int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// sets the viewport (and scissor) according to the provided specifications
|
||||
/// Sets the viewport (and scissor) according to the provided specifications
|
||||
/// </summary>
|
||||
void SetViewport(int x, int y, int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// generates a proper 2d othographic projection for the given destination size, suitable for use in a GUI
|
||||
/// Generates a proper 2D othographic projection for the given destination size, suitable for use in a GUI
|
||||
/// </summary>
|
||||
Matrix4x4 CreateGuiProjectionMatrix(int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// generates a proper view transform for a standard 2d ortho projection, including half-pixel jitter if necessary and
|
||||
/// re-establishing of a normal 2d graphics top-left origin. suitable for use in a GUI
|
||||
/// Generates a proper view transform for a standard 2D othographic projection, including half-pixel jitter if necessary
|
||||
/// and re-establishing of a normal 2D graphics top-left origin. Suitable for use in a GUI
|
||||
/// </summary>
|
||||
Matrix4x4 CreateGuiViewMatrix(int width, int height, bool autoflip = true);
|
||||
|
||||
/// <summary>
|
||||
/// Creates a render target. Only includes a color buffer. Pixel format control TBD
|
||||
/// Creates a render target. Only includes a color buffer, and will always be in byte order BGRA (i.e. little endian ARGB)
|
||||
/// This may unbind a previously bound render target
|
||||
/// </summary>
|
||||
RenderTarget CreateRenderTarget(int width, int height);
|
||||
IRenderTarget CreateRenderTarget(int width, int height);
|
||||
|
||||
/// <summary>
|
||||
/// Binds a RenderTarget for current rendering
|
||||
/// Binds the IGL's default render target (i.e. to the IGL's control)
|
||||
/// This implicitly unbinds any previously bound IRenderTarget
|
||||
/// </summary>
|
||||
void BindRenderTarget(RenderTarget rt);
|
||||
|
||||
/// <summary>
|
||||
/// Frees the provided render target. Same as disposing the resource.
|
||||
/// </summary>
|
||||
void FreeRenderTarget(RenderTarget rt);
|
||||
void BindDefaultRenderTarget();
|
||||
|
||||
/// <summary>
|
||||
/// Frees the provided pipeline. Same as disposing the resource.
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
/// <summary>
|
||||
/// A render target, essentially just a 2D texture which can be written as if it was a window
|
||||
/// As this is effectively a texture, it inherits ITexture2D
|
||||
/// However, note that semantically the CPU shouldn't be writing to a render target, so LoadFrom might not work!
|
||||
/// </summary>
|
||||
public interface IRenderTarget : ITexture2D
|
||||
{
|
||||
/// <summary>
|
||||
/// Binds this render target
|
||||
/// </summary>
|
||||
void Bind();
|
||||
}
|
||||
}
|
|
@ -34,7 +34,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
|
||||
// rendering state
|
||||
private Pipeline _currPipeline;
|
||||
private RenderTarget _currRenderTarget;
|
||||
internal bool DefaultRenderTargetBound;
|
||||
|
||||
// this IGL either requires at least OpenGL 3.0
|
||||
public static bool Available => OpenGLVersion.SupportsVersion(3, 0);
|
||||
|
@ -451,50 +451,14 @@ namespace BizHawk.Bizware.Graphics
|
|||
public ITexture2D WrapGLTexture2D(int glTexId, int width, int height)
|
||||
=> new OpenGLTexture2D(GL, (uint)glTexId, width, height);
|
||||
|
||||
public void FreeRenderTarget(RenderTarget rt)
|
||||
{
|
||||
rt.Texture2D.Dispose();
|
||||
GL.DeleteFramebuffer((uint)rt.Opaque);
|
||||
}
|
||||
|
||||
/// <exception cref="InvalidOperationException">framebuffer creation unsuccessful</exception>
|
||||
public RenderTarget CreateRenderTarget(int width, int height)
|
||||
public IRenderTarget CreateRenderTarget(int width, int height)
|
||||
=> new OpenGLRenderTarget(this, GL, width, height);
|
||||
|
||||
public void BindDefaultRenderTarget()
|
||||
{
|
||||
// create a texture for it
|
||||
var tex2d = new OpenGLTexture2D(GL, width, height);
|
||||
|
||||
// create the FBO
|
||||
var fbId = GL.GenFramebuffer();
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbId);
|
||||
|
||||
// bind the tex to the FBO
|
||||
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, tex2d.TexID, 0);
|
||||
|
||||
// do something, I guess say which color buffers are used by the framebuffer
|
||||
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
||||
|
||||
if ((FramebufferStatus)GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferStatus.Complete)
|
||||
{
|
||||
throw new InvalidOperationException($"Error creating framebuffer (at {nameof(GL.CheckFramebufferStatus)})");
|
||||
}
|
||||
|
||||
// since we're done configuring unbind this framebuffer, to return to the default
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
||||
|
||||
return new(this, fbId, tex2d);
|
||||
}
|
||||
|
||||
public void BindRenderTarget(RenderTarget rt)
|
||||
{
|
||||
_currRenderTarget = rt;
|
||||
if (rt == null)
|
||||
{
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, (uint)rt.Opaque);
|
||||
}
|
||||
DefaultRenderTargetBound = true;
|
||||
}
|
||||
|
||||
public Matrix4x4 CreateGuiProjectionMatrix(int width, int height)
|
||||
|
@ -511,7 +475,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
ret.M22 = -1.0f;
|
||||
ret.M41 = width * -0.5f;
|
||||
ret.M42 = height * 0.5f;
|
||||
if (autoflip && _currRenderTarget is not null) // flip as long as we're not a final render target
|
||||
if (autoflip && !DefaultRenderTargetBound) // flip as long as we're not a final render target
|
||||
{
|
||||
ret.M22 = 1.0f;
|
||||
ret.M42 *= -1;
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
using System;
|
||||
|
||||
using Silk.NET.OpenGL.Legacy;
|
||||
|
||||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
internal sealed class OpenGLRenderTarget : OpenGLTexture2D, IRenderTarget
|
||||
{
|
||||
private readonly IGL_OpenGL _openGL;
|
||||
private readonly GL GL;
|
||||
|
||||
public readonly uint FBO;
|
||||
|
||||
public OpenGLRenderTarget(IGL_OpenGL openGL, GL gl, int width, int height)
|
||||
: base(gl, width, height)
|
||||
{
|
||||
_openGL = openGL;
|
||||
GL = gl;
|
||||
|
||||
// create the FBO
|
||||
FBO = GL.GenFramebuffer();
|
||||
Bind();
|
||||
|
||||
// bind the tex to the FBO
|
||||
GL.FramebufferTexture2D(FramebufferTarget.Framebuffer, FramebufferAttachment.ColorAttachment0, TextureTarget.Texture2D, TexID, 0);
|
||||
|
||||
// do something, I guess say which color buffers are used by the framebuffer
|
||||
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
||||
|
||||
if ((FramebufferStatus)GL.CheckFramebufferStatus(FramebufferTarget.Framebuffer) != FramebufferStatus.Complete)
|
||||
{
|
||||
Dispose();
|
||||
throw new InvalidOperationException($"Error creating framebuffer (at {nameof(GL.CheckFramebufferStatus)})");
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
GL.DeleteFramebuffer(FBO);
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, FBO);
|
||||
_openGL.DefaultRenderTargetBound = false;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
=> $"OpenGL RenderTarget: {Width}x{Height}";
|
||||
}
|
||||
}
|
|
@ -44,7 +44,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
IsUpsideDown = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
public virtual void Dispose()
|
||||
=> GL.DeleteTexture(TexID);
|
||||
|
||||
public unsafe BitmapBuffer Resolve()
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace BizHawk.Bizware.Graphics
|
||||
{
|
||||
public class RenderTarget : IDisposable
|
||||
{
|
||||
public RenderTarget(IGL owner, object opaque, ITexture2D tex)
|
||||
{
|
||||
Owner = owner;
|
||||
Opaque = opaque;
|
||||
Texture2D = tex;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"GL RT: {Texture2D.Width}x{Texture2D.Height}";
|
||||
}
|
||||
|
||||
public object Opaque { get; }
|
||||
public IGL Owner { get; }
|
||||
public ITexture2D Texture2D { get; }
|
||||
|
||||
public void Unbind()
|
||||
{
|
||||
Owner.BindRenderTarget(null);
|
||||
}
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
Owner.BindRenderTarget(this);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Owner.FreeRenderTarget(this);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -32,14 +32,14 @@ namespace BizHawk.Client.Common
|
|||
|
||||
protected class DisplayManagerRenderTargetProvider : IRenderTargetProvider
|
||||
{
|
||||
private readonly Func<Size, RenderTarget> _callback;
|
||||
private readonly Func<Size, IRenderTarget> _callback;
|
||||
|
||||
RenderTarget IRenderTargetProvider.Get(Size size)
|
||||
public IRenderTarget Get(Size size)
|
||||
{
|
||||
return _callback(size);
|
||||
}
|
||||
|
||||
public DisplayManagerRenderTargetProvider(Func<Size, RenderTarget> callback)
|
||||
public DisplayManagerRenderTargetProvider(Func<Size, IRenderTarget> callback)
|
||||
{
|
||||
_callback = callback;
|
||||
}
|
||||
|
@ -864,7 +864,7 @@ namespace BizHawk.Client.Common
|
|||
public void Blank()
|
||||
{
|
||||
ActivateGraphicsControlContext();
|
||||
_gl.BindRenderTarget(null);
|
||||
_gl.BindDefaultRenderTarget();
|
||||
_gl.ClearColor(Color.Black);
|
||||
SwapBuffersOfGraphicsControl();
|
||||
}
|
||||
|
@ -880,11 +880,11 @@ namespace BizHawk.Client.Common
|
|||
|
||||
RunFilterChainSteps(ref rtCounter, out var rtCurr, out _);
|
||||
|
||||
job.OffscreenBb = rtCurr.Texture2D.Resolve();
|
||||
job.OffscreenBb = rtCurr.Resolve();
|
||||
job.OffscreenBb.DiscardAlpha();
|
||||
}
|
||||
|
||||
protected void RunFilterChainSteps(ref int rtCounter, out RenderTarget rtCurr, out bool inFinalTarget)
|
||||
protected void RunFilterChainSteps(ref int rtCounter, out IRenderTarget rtCurr, out bool inFinalTarget)
|
||||
{
|
||||
ITexture2D texCurr = null;
|
||||
rtCurr = null;
|
||||
|
@ -907,7 +907,7 @@ namespace BizHawk.Client.Common
|
|||
break;
|
||||
case FilterProgram.ProgramStepType.FinalTarget:
|
||||
_currentFilterProgram.CurrRenderTarget = rtCurr = null;
|
||||
_gl.BindRenderTarget(rtCurr);
|
||||
_gl.BindDefaultRenderTarget();
|
||||
inFinalTarget = true;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -38,7 +38,7 @@ namespace BizHawk.Client.Common.FilterManager
|
|||
|
||||
public interface IRenderTargetProvider
|
||||
{
|
||||
RenderTarget Get(Size size);
|
||||
IRenderTarget Get(Size size);
|
||||
}
|
||||
|
||||
public class FilterProgram
|
||||
|
@ -69,9 +69,9 @@ namespace BizHawk.Client.Common.FilterManager
|
|||
public IGL GL;
|
||||
public IRenderTargetProvider RenderTargetProvider;
|
||||
|
||||
public RenderTarget CurrRenderTarget;
|
||||
public IRenderTarget CurrRenderTarget;
|
||||
|
||||
public RenderTarget GetTempTarget(int width, int height)
|
||||
public IRenderTarget GetTempTarget(int width, int height)
|
||||
{
|
||||
return RenderTargetProvider.Get(new(width, height));
|
||||
}
|
||||
|
|
|
@ -111,7 +111,7 @@ namespace BizHawk.Client.Common.Filters
|
|||
}
|
||||
|
||||
// TODO - why a different param order than DeclareOutput?
|
||||
protected RenderTarget GetTempTarget(int width, int height)
|
||||
protected IRenderTarget GetTempTarget(int width, int height)
|
||||
{
|
||||
return FilterProgram.GetTempTarget(width, height);
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace BizHawk.Client.Common.Filters
|
|||
|
||||
public override void Run()
|
||||
{
|
||||
YieldOutput(FilterProgram.CurrRenderTarget.Texture2D);
|
||||
YieldOutput(FilterProgram.CurrRenderTarget);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,26 +30,26 @@ namespace BizHawk.Client.Common
|
|||
|
||||
private void ResetList()
|
||||
{
|
||||
_currentRenderTargets = new List<RenderTarget> { null, null };
|
||||
_currentRenderTargets = new List<IRenderTarget> { null, null };
|
||||
}
|
||||
|
||||
private readonly IGL _gl;
|
||||
private List<RenderTarget> _currentRenderTargets;
|
||||
private List<IRenderTarget> _currentRenderTargets;
|
||||
|
||||
public RenderTarget Get(Size dimensions)
|
||||
public IRenderTarget Get(Size dimensions)
|
||||
{
|
||||
return Get(dimensions.Width, dimensions.Height);
|
||||
}
|
||||
|
||||
public RenderTarget Get(int width, int height)
|
||||
public IRenderTarget Get(int width, int height)
|
||||
{
|
||||
//get the current entry
|
||||
var currentRenderTarget = _currentRenderTargets[0];
|
||||
|
||||
//check if its rotten and needs recreating
|
||||
if (currentRenderTarget == null
|
||||
|| currentRenderTarget.Texture2D.Width != width
|
||||
|| currentRenderTarget.Texture2D.Height != height)
|
||||
|| currentRenderTarget.Width != width
|
||||
|| currentRenderTarget.Height != height)
|
||||
{
|
||||
// needs recreating. be sure to kill the old one...
|
||||
currentRenderTarget?.Dispose();
|
||||
|
|
|
@ -99,7 +99,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
if (job.Offscreen)
|
||||
{
|
||||
job.OffscreenBb = rtCurr.Texture2D.Resolve();
|
||||
job.OffscreenBb = rtCurr.Resolve();
|
||||
job.OffscreenBb.DiscardAlpha();
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
private readonly IGL _gl;
|
||||
private readonly GraphicsControl _graphicsControl;
|
||||
private RenderTarget _rt;
|
||||
private IRenderTarget _rt;
|
||||
private readonly GuiRenderer _guiRenderer;
|
||||
|
||||
protected override void OnPaint(PaintEventArgs e)
|
||||
|
@ -75,7 +75,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
{
|
||||
if (_retain)
|
||||
{
|
||||
_rt.Unbind();
|
||||
_gl.BindDefaultRenderTarget();
|
||||
}
|
||||
|
||||
_graphicsControl.End();
|
||||
|
@ -91,7 +91,7 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
|
||||
// if we're retaining, then we cant draw until we unbind! its semantically a bit odd, but we expect users to call SwapBuffers() before end, so we cant unbind in End() even thoug hit makes a bit more sense.
|
||||
_rt.Unbind();
|
||||
_gl.BindDefaultRenderTarget();
|
||||
Draw();
|
||||
}
|
||||
|
||||
|
@ -104,9 +104,9 @@ namespace BizHawk.Client.EmuHawk
|
|||
|
||||
_guiRenderer.Begin(Width, Height);
|
||||
_guiRenderer.DisableBlending();
|
||||
_guiRenderer.Draw(_rt.Texture2D);
|
||||
_guiRenderer.Draw(_rt);
|
||||
_guiRenderer.End();
|
||||
_graphicsControl.SwapBuffers();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue