fix D3D9 crashing on minimize
This commit is contained in:
parent
56ac05f9a3
commit
ae42858560
|
@ -1,16 +1,17 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Drawing;
|
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace BizHawk.Bizware.Graphics.Controls
|
namespace BizHawk.Bizware.Graphics.Controls
|
||||||
{
|
{
|
||||||
internal sealed class D3D9Control : GraphicsControl
|
internal sealed class D3D9Control : GraphicsControl
|
||||||
{
|
{
|
||||||
private readonly Func<IntPtr, D3D9SwapChain> _createSwapChain;
|
private readonly Func<D3D9SwapChain.ControlParameters, D3D9SwapChain> _createSwapChain;
|
||||||
private D3D9SwapChain _swapChain;
|
private D3D9SwapChain _swapChain;
|
||||||
private bool Vsync;
|
private bool Vsync;
|
||||||
|
|
||||||
public D3D9Control(Func<IntPtr, D3D9SwapChain> createSwapChain)
|
private D3D9SwapChain.ControlParameters ControlParameters => new(Handle, Width, Height, Vsync);
|
||||||
|
|
||||||
|
public D3D9Control(Func<D3D9SwapChain.ControlParameters, D3D9SwapChain> createSwapChain)
|
||||||
{
|
{
|
||||||
_createSwapChain = createSwapChain;
|
_createSwapChain = createSwapChain;
|
||||||
|
|
||||||
|
@ -21,12 +22,10 @@ namespace BizHawk.Bizware.Graphics.Controls
|
||||||
DoubleBuffered = false;
|
DoubleBuffered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Size DefaultSize => new(1, 1);
|
|
||||||
|
|
||||||
protected override void OnHandleCreated(EventArgs e)
|
protected override void OnHandleCreated(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnHandleCreated(e);
|
base.OnHandleCreated(e);
|
||||||
_swapChain = _createSwapChain(Handle);
|
_swapChain = _createSwapChain(ControlParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnHandleDestroyed(EventArgs e)
|
protected override void OnHandleDestroyed(EventArgs e)
|
||||||
|
@ -39,7 +38,7 @@ namespace BizHawk.Bizware.Graphics.Controls
|
||||||
protected override void OnResize(EventArgs e)
|
protected override void OnResize(EventArgs e)
|
||||||
{
|
{
|
||||||
base.OnResize(e);
|
base.OnResize(e);
|
||||||
_swapChain.Refresh(Vsync);
|
_swapChain.Refresh(ControlParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetVsync(bool state)
|
public override void SetVsync(bool state)
|
||||||
|
@ -47,7 +46,7 @@ namespace BizHawk.Bizware.Graphics.Controls
|
||||||
if (Vsync != state)
|
if (Vsync != state)
|
||||||
{
|
{
|
||||||
Vsync = state;
|
Vsync = state;
|
||||||
_swapChain.Refresh(Vsync);
|
_swapChain.Refresh(ControlParameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,6 +57,6 @@ namespace BizHawk.Bizware.Graphics.Controls
|
||||||
=> _swapChain.SetBackBuffer();
|
=> _swapChain.SetBackBuffer();
|
||||||
|
|
||||||
public override void SwapBuffers()
|
public override void SwapBuffers()
|
||||||
=> _swapChain.PresentBuffer();
|
=> _swapChain.PresentBuffer(ControlParameters);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,16 +7,32 @@ namespace BizHawk.Bizware.Graphics
|
||||||
{
|
{
|
||||||
public sealed class D3D9SwapChain : IDisposable
|
public sealed class D3D9SwapChain : IDisposable
|
||||||
{
|
{
|
||||||
|
public readonly struct ControlParameters
|
||||||
|
{
|
||||||
|
public readonly IntPtr Handle;
|
||||||
|
public readonly int Width;
|
||||||
|
public readonly int Height;
|
||||||
|
public readonly bool Vsync;
|
||||||
|
|
||||||
|
public ControlParameters(IntPtr handle, int width, int height, bool vsync)
|
||||||
|
{
|
||||||
|
Handle = handle;
|
||||||
|
Width = Math.Max(width, 1);
|
||||||
|
Height = Math.Max(height, 1);
|
||||||
|
Vsync = vsync;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private const int D3DERR_DEVICELOST = unchecked((int)0x88760868);
|
private const int D3DERR_DEVICELOST = unchecked((int)0x88760868);
|
||||||
|
|
||||||
private readonly Device _device;
|
private readonly Device _device;
|
||||||
private readonly Func<PresentParameters, SwapChain> _resetDeviceCallback;
|
private readonly Func<ControlParameters, SwapChain> _resetDeviceCallback;
|
||||||
private readonly Func<PresentParameters, SwapChain> _resetSwapChainCallback;
|
private readonly Func<ControlParameters, SwapChain> _resetSwapChainCallback;
|
||||||
|
|
||||||
private SwapChain _swapChain;
|
private SwapChain _swapChain;
|
||||||
|
|
||||||
internal D3D9SwapChain(Device device, SwapChain swapChain,
|
internal D3D9SwapChain(Device device, SwapChain swapChain,
|
||||||
Func<PresentParameters, SwapChain> resetDeviceCallback, Func<PresentParameters, SwapChain> resetSwapChainCallback)
|
Func<ControlParameters, SwapChain> resetDeviceCallback, Func<ControlParameters, SwapChain> resetSwapChainCallback)
|
||||||
{
|
{
|
||||||
_device = device;
|
_device = device;
|
||||||
_swapChain = swapChain;
|
_swapChain = swapChain;
|
||||||
|
@ -37,7 +53,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
_device.DepthStencilSurface = null;
|
_device.DepthStencilSurface = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PresentBuffer()
|
public void PresentBuffer(ControlParameters cp)
|
||||||
{
|
{
|
||||||
SetBackBuffer();
|
SetBackBuffer();
|
||||||
|
|
||||||
|
@ -49,19 +65,12 @@ namespace BizHawk.Bizware.Graphics
|
||||||
{
|
{
|
||||||
if (ex.ResultCode.Code == D3DERR_DEVICELOST)
|
if (ex.ResultCode.Code == D3DERR_DEVICELOST)
|
||||||
{
|
{
|
||||||
var pp = _swapChain.PresentParameters;
|
_swapChain = _resetDeviceCallback(cp);
|
||||||
pp.BackBufferWidth = pp.BackBufferHeight = 0;
|
|
||||||
_swapChain = _resetDeviceCallback(pp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Refresh(bool vsync)
|
public void Refresh(ControlParameters cp)
|
||||||
{
|
=> _swapChain = _resetSwapChainCallback(cp);
|
||||||
var pp = _swapChain.PresentParameters;
|
|
||||||
pp.BackBufferWidth = pp.BackBufferHeight = 0;
|
|
||||||
pp.PresentationInterval = vsync ? PresentInterval.One : PresentInterval.Immediate;
|
|
||||||
_swapChain = _resetSwapChainCallback(pp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace BizHawk.Bizware.Graphics
|
||||||
private const int D3DERR_DEVICENOTRESET = unchecked((int)0x88760869);
|
private const int D3DERR_DEVICENOTRESET = unchecked((int)0x88760869);
|
||||||
|
|
||||||
private Device _device;
|
private Device _device;
|
||||||
|
private Size _maxWindowSize;
|
||||||
private SwapChain _controlSwapchain;
|
private SwapChain _controlSwapchain;
|
||||||
|
|
||||||
private IntPtr _offscreenSdl2Window;
|
private IntPtr _offscreenSdl2Window;
|
||||||
|
@ -105,6 +106,11 @@ namespace BizHawk.Bizware.Graphics
|
||||||
|
|
||||||
flags |= CreateFlags.FpuPreserve;
|
flags |= CreateFlags.FpuPreserve;
|
||||||
_device = new(d3d9, 0, DeviceType.Hardware, pp.DeviceWindowHandle, flags, pp);
|
_device = new(d3d9, 0, DeviceType.Hardware, pp.DeviceWindowHandle, flags, pp);
|
||||||
|
|
||||||
|
// save the maximum size a window backbuffer can be
|
||||||
|
// this allows us to avoid resetting the swapchain on resizing the window
|
||||||
|
var displayMode = d3d9.Adapters[0].CurrentDisplayMode;
|
||||||
|
_maxWindowSize = new(displayMode.Width, displayMode.Height);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PresentParameters MakePresentParameters()
|
private PresentParameters MakePresentParameters()
|
||||||
|
@ -119,7 +125,22 @@ namespace BizHawk.Bizware.Graphics
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private SwapChain ResetDevice(PresentParameters swapChainPresentParameters)
|
private static PresentParameters MakePresentParameters(D3D9SwapChain.ControlParameters cp)
|
||||||
|
{
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
BackBufferWidth = cp.Width,
|
||||||
|
BackBufferHeight = cp.Height,
|
||||||
|
BackBufferFormat = Format.X8R8G8B8,
|
||||||
|
BackBufferCount = 2,
|
||||||
|
SwapEffect = SwapEffect.Discard,
|
||||||
|
DeviceWindowHandle = cp.Handle,
|
||||||
|
Windowed = true,
|
||||||
|
PresentationInterval = cp.Vsync ? PresentInterval.One : PresentInterval.Immediate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private SwapChain ResetDevice(D3D9SwapChain.ControlParameters cp)
|
||||||
{
|
{
|
||||||
SuspendRenderTargets();
|
SuspendRenderTargets();
|
||||||
_controlSwapchain.Dispose();
|
_controlSwapchain.Dispose();
|
||||||
|
@ -151,35 +172,29 @@ namespace BizHawk.Bizware.Graphics
|
||||||
}
|
}
|
||||||
|
|
||||||
ResumeRenderTargets();
|
ResumeRenderTargets();
|
||||||
_controlSwapchain = new(_device, swapChainPresentParameters);
|
|
||||||
|
|
||||||
return _controlSwapchain;
|
pp = MakePresentParameters(cp);
|
||||||
}
|
|
||||||
|
|
||||||
private SwapChain ResetSwapChain(PresentParameters pp)
|
|
||||||
{
|
|
||||||
_controlSwapchain.Dispose();
|
|
||||||
_controlSwapchain = new(_device, pp);
|
_controlSwapchain = new(_device, pp);
|
||||||
return _controlSwapchain;
|
return _controlSwapchain;
|
||||||
}
|
}
|
||||||
|
|
||||||
public D3D9SwapChain CreateSwapChain(IntPtr handle)
|
private SwapChain ResetSwapChain(D3D9SwapChain.ControlParameters cp)
|
||||||
|
{
|
||||||
|
_controlSwapchain.Dispose();
|
||||||
|
|
||||||
|
var pp = MakePresentParameters(cp);
|
||||||
|
_controlSwapchain = new(_device, pp);
|
||||||
|
return _controlSwapchain;
|
||||||
|
}
|
||||||
|
|
||||||
|
public D3D9SwapChain CreateSwapChain(D3D9SwapChain.ControlParameters cp)
|
||||||
{
|
{
|
||||||
if (_controlSwapchain != null)
|
if (_controlSwapchain != null)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"{nameof(IGL_D3D9)} can only have 1 control swap chain");
|
throw new InvalidOperationException($"{nameof(IGL_D3D9)} can only have 1 control swap chain");
|
||||||
}
|
}
|
||||||
|
|
||||||
var pp = new PresentParameters
|
var pp = MakePresentParameters(cp);
|
||||||
{
|
|
||||||
BackBufferCount = 1,
|
|
||||||
BackBufferFormat = Format.X8R8G8B8,
|
|
||||||
SwapEffect = SwapEffect.Discard,
|
|
||||||
DeviceWindowHandle = handle,
|
|
||||||
Windowed = true,
|
|
||||||
PresentationInterval = PresentInterval.Immediate
|
|
||||||
};
|
|
||||||
|
|
||||||
_controlSwapchain = new(_device, pp);
|
_controlSwapchain = new(_device, pp);
|
||||||
return new(_device, _controlSwapchain, ResetDevice, ResetSwapChain);
|
return new(_device, _controlSwapchain, ResetDevice, ResetSwapChain);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue