fix D3D9 crashing on minimize
This commit is contained in:
parent
56ac05f9a3
commit
ae42858560
|
@ -1,16 +1,17 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace BizHawk.Bizware.Graphics.Controls
|
||||
{
|
||||
internal sealed class D3D9Control : GraphicsControl
|
||||
{
|
||||
private readonly Func<IntPtr, D3D9SwapChain> _createSwapChain;
|
||||
private readonly Func<D3D9SwapChain.ControlParameters, D3D9SwapChain> _createSwapChain;
|
||||
private D3D9SwapChain _swapChain;
|
||||
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;
|
||||
|
||||
|
@ -21,12 +22,10 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
DoubleBuffered = false;
|
||||
}
|
||||
|
||||
protected override Size DefaultSize => new(1, 1);
|
||||
|
||||
protected override void OnHandleCreated(EventArgs e)
|
||||
{
|
||||
base.OnHandleCreated(e);
|
||||
_swapChain = _createSwapChain(Handle);
|
||||
_swapChain = _createSwapChain(ControlParameters);
|
||||
}
|
||||
|
||||
protected override void OnHandleDestroyed(EventArgs e)
|
||||
|
@ -39,7 +38,7 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
protected override void OnResize(EventArgs e)
|
||||
{
|
||||
base.OnResize(e);
|
||||
_swapChain.Refresh(Vsync);
|
||||
_swapChain.Refresh(ControlParameters);
|
||||
}
|
||||
|
||||
public override void SetVsync(bool state)
|
||||
|
@ -47,7 +46,7 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
if (Vsync != state)
|
||||
{
|
||||
Vsync = state;
|
||||
_swapChain.Refresh(Vsync);
|
||||
_swapChain.Refresh(ControlParameters);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +57,6 @@ namespace BizHawk.Bizware.Graphics.Controls
|
|||
=> _swapChain.SetBackBuffer();
|
||||
|
||||
public override void SwapBuffers()
|
||||
=> _swapChain.PresentBuffer();
|
||||
=> _swapChain.PresentBuffer(ControlParameters);
|
||||
}
|
||||
}
|
|
@ -7,16 +7,32 @@ namespace BizHawk.Bizware.Graphics
|
|||
{
|
||||
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 readonly Device _device;
|
||||
private readonly Func<PresentParameters, SwapChain> _resetDeviceCallback;
|
||||
private readonly Func<PresentParameters, SwapChain> _resetSwapChainCallback;
|
||||
private readonly Func<ControlParameters, SwapChain> _resetDeviceCallback;
|
||||
private readonly Func<ControlParameters, SwapChain> _resetSwapChainCallback;
|
||||
|
||||
private 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;
|
||||
_swapChain = swapChain;
|
||||
|
@ -37,7 +53,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
_device.DepthStencilSurface = null;
|
||||
}
|
||||
|
||||
public void PresentBuffer()
|
||||
public void PresentBuffer(ControlParameters cp)
|
||||
{
|
||||
SetBackBuffer();
|
||||
|
||||
|
@ -49,19 +65,12 @@ namespace BizHawk.Bizware.Graphics
|
|||
{
|
||||
if (ex.ResultCode.Code == D3DERR_DEVICELOST)
|
||||
{
|
||||
var pp = _swapChain.PresentParameters;
|
||||
pp.BackBufferWidth = pp.BackBufferHeight = 0;
|
||||
_swapChain = _resetDeviceCallback(pp);
|
||||
_swapChain = _resetDeviceCallback(cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Refresh(bool vsync)
|
||||
{
|
||||
var pp = _swapChain.PresentParameters;
|
||||
pp.BackBufferWidth = pp.BackBufferHeight = 0;
|
||||
pp.PresentationInterval = vsync ? PresentInterval.One : PresentInterval.Immediate;
|
||||
_swapChain = _resetSwapChainCallback(pp);
|
||||
}
|
||||
public void Refresh(ControlParameters cp)
|
||||
=> _swapChain = _resetSwapChainCallback(cp);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace BizHawk.Bizware.Graphics
|
|||
private const int D3DERR_DEVICENOTRESET = unchecked((int)0x88760869);
|
||||
|
||||
private Device _device;
|
||||
private Size _maxWindowSize;
|
||||
private SwapChain _controlSwapchain;
|
||||
|
||||
private IntPtr _offscreenSdl2Window;
|
||||
|
@ -105,6 +106,11 @@ namespace BizHawk.Bizware.Graphics
|
|||
|
||||
flags |= CreateFlags.FpuPreserve;
|
||||
_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()
|
||||
|
@ -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();
|
||||
_controlSwapchain.Dispose();
|
||||
|
@ -151,35 +172,29 @@ namespace BizHawk.Bizware.Graphics
|
|||
}
|
||||
|
||||
ResumeRenderTargets();
|
||||
_controlSwapchain = new(_device, swapChainPresentParameters);
|
||||
|
||||
return _controlSwapchain;
|
||||
}
|
||||
|
||||
private SwapChain ResetSwapChain(PresentParameters pp)
|
||||
{
|
||||
_controlSwapchain.Dispose();
|
||||
pp = MakePresentParameters(cp);
|
||||
_controlSwapchain = new(_device, pp);
|
||||
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)
|
||||
{
|
||||
throw new InvalidOperationException($"{nameof(IGL_D3D9)} can only have 1 control swap chain");
|
||||
}
|
||||
|
||||
var pp = new PresentParameters
|
||||
{
|
||||
BackBufferCount = 1,
|
||||
BackBufferFormat = Format.X8R8G8B8,
|
||||
SwapEffect = SwapEffect.Discard,
|
||||
DeviceWindowHandle = handle,
|
||||
Windowed = true,
|
||||
PresentationInterval = PresentInterval.Immediate
|
||||
};
|
||||
|
||||
var pp = MakePresentParameters(cp);
|
||||
_controlSwapchain = new(_device, pp);
|
||||
return new(_device, _controlSwapchain, ResetDevice, ResetSwapChain);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue