d3d display method: do a better job of surviving device resets
This commit is contained in:
parent
1ee56ea4ef
commit
1e07625d1d
|
@ -7,13 +7,17 @@ namespace BizHawk.Client.Common
|
|||
/// <summary>
|
||||
/// This singleton class manages OpenGL contexts, in an effort to minimize context changes.
|
||||
/// </summary>
|
||||
public class GLManager
|
||||
public class GLManager : IDisposable
|
||||
{
|
||||
private GLManager()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public static GLManager Instance { get; private set; }
|
||||
|
||||
public static void CreateInstance()
|
||||
|
|
|
@ -220,7 +220,17 @@ namespace BizHawk.Client.EmuHawk
|
|||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
//cleanup:
|
||||
//cleanup IGL stuff so we can get better refcounts when exiting process, for debugging
|
||||
//DOESNT WORK FOR SOME REASON
|
||||
//GlobalWin.IGL_GL = new Bizware.BizwareGL.Drivers.OpenTK.IGL_TK();
|
||||
//GLManager.Instance.Dispose();
|
||||
//if (GlobalWin.IGL_GL != GlobalWin.GL)
|
||||
// GlobalWin.GL.Dispose();
|
||||
//((IDisposable)GlobalWin.IGL_GL).Dispose();
|
||||
|
||||
} //SubMain
|
||||
|
||||
//declared here instead of a more usual place to avoid dependencies on the more usual place
|
||||
#if WINDOWS
|
||||
|
|
|
@ -62,18 +62,41 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
|||
}
|
||||
}
|
||||
|
||||
PresentParameters MakePresentParameters()
|
||||
{
|
||||
return new PresentParameters
|
||||
{
|
||||
BackBufferWidth = 8,
|
||||
BackBufferHeight = 8,
|
||||
DeviceWindowHandle = OffscreenNativeWindow.WindowInfo.Handle,
|
||||
PresentationInterval = PresentInterval.Immediate,
|
||||
EnableAutoDepthStencil = false
|
||||
};
|
||||
}
|
||||
|
||||
void ResetDevice()
|
||||
{
|
||||
ResetHandlers.Reset();
|
||||
for(;;)
|
||||
{
|
||||
var pp = MakePresentParameters();
|
||||
try
|
||||
{
|
||||
dev.Reset(pp);
|
||||
}
|
||||
catch { }
|
||||
if (dev.TestCooperativeLevel().IsSuccess)
|
||||
break;
|
||||
System.Threading.Thread.Sleep(100);
|
||||
}
|
||||
ResetHandlers.Restore();
|
||||
}
|
||||
|
||||
public void CreateDevice()
|
||||
{
|
||||
DestroyDevice();
|
||||
|
||||
//just create some present params so we can get the device created
|
||||
var pp = new PresentParameters
|
||||
{
|
||||
BackBufferWidth = 8,
|
||||
BackBufferHeight = 8,
|
||||
DeviceWindowHandle = OffscreenNativeWindow.WindowInfo.Handle,
|
||||
PresentationInterval = PresentInterval.Immediate
|
||||
};
|
||||
var pp = MakePresentParameters();
|
||||
|
||||
var flags = CreateFlags.SoftwareVertexProcessing;
|
||||
if ((d3d.GetDeviceCaps(0, DeviceType.Hardware).DeviceCaps & DeviceCaps.HWTransformAndLight) != 0)
|
||||
|
@ -85,6 +108,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
|||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
ResetHandlers.Reset();
|
||||
DestroyDevice();
|
||||
d3d.Dispose();
|
||||
}
|
||||
|
||||
public void Clear(OpenTK.Graphics.OpenGL.ClearBufferMask mask)
|
||||
|
@ -737,7 +763,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
|||
public void BeginControl(GLControlWrapper_SlimDX9 control)
|
||||
{
|
||||
_CurrentControl = control;
|
||||
dev.SetRenderTarget(0, control.SwapChain.GetBackBuffer(0));
|
||||
var bb = control.SwapChain.GetBackBuffer(0);
|
||||
dev.SetRenderTarget(0, bb);
|
||||
bb.Dispose();
|
||||
}
|
||||
|
||||
public void EndControl(GLControlWrapper_SlimDX9 control)
|
||||
|
@ -745,13 +773,28 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
|||
if (control != _CurrentControl)
|
||||
throw new InvalidOperationException();
|
||||
|
||||
var bb = dev.GetBackBuffer(0,0);
|
||||
dev.SetRenderTarget(0,bb);
|
||||
bb.Dispose();
|
||||
|
||||
_CurrentControl = null;
|
||||
}
|
||||
|
||||
public void SwapControl(GLControlWrapper_SlimDX9 control)
|
||||
{
|
||||
control.SwapChain.Present(Present.None);
|
||||
EndControl(control);
|
||||
|
||||
try
|
||||
{
|
||||
var result = control.SwapChain.Present(Present.None);
|
||||
}
|
||||
catch(d3d9.Direct3D9Exception ex)
|
||||
{
|
||||
if (ex.ResultCode.Name == "D3DERR_DEVICELOST")
|
||||
ResetDevice();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void FreeRenderTarget(RenderTarget rt)
|
||||
{
|
||||
|
@ -777,7 +820,9 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
|||
|
||||
if (rt == null)
|
||||
{
|
||||
dev.SetRenderTarget(0, _CurrentControl.SwapChain.GetBackBuffer(0));
|
||||
var bb = _CurrentControl.SwapChain.GetBackBuffer(0);
|
||||
dev.SetRenderTarget(0, bb);
|
||||
bb.Dispose();
|
||||
dev.DepthStencilSurface = null;
|
||||
return;
|
||||
}
|
||||
|
@ -795,6 +840,7 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
|||
control.SwapChain.Dispose();
|
||||
control.SwapChain = null;
|
||||
}
|
||||
ResetHandlers.Remove(control, "SwapChain");
|
||||
|
||||
var pp = new PresentParameters
|
||||
{
|
||||
|
@ -808,8 +854,66 @@ namespace BizHawk.Bizware.BizwareGL.Drivers.SlimDX
|
|||
};
|
||||
|
||||
control.SwapChain = new SwapChain(dev, pp);
|
||||
ResetHandlers.Add(control, "SwapChain", () => { control.SwapChain.Dispose(); control.SwapChain = null; }, () => RefreshControlSwapChain(control));
|
||||
}
|
||||
|
||||
DeviceLostHandler ResetHandlers = new DeviceLostHandler();
|
||||
|
||||
class DeviceLostHandler
|
||||
{
|
||||
class ResetHandlerKey
|
||||
{
|
||||
public string Label;
|
||||
public object Object;
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Label.GetHashCode() ^ Object.GetHashCode();
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj == null) return false;
|
||||
var key = obj as ResetHandlerKey;
|
||||
return key.Label == Label && key.Object == Object;
|
||||
}
|
||||
}
|
||||
|
||||
class HandlerSet
|
||||
{
|
||||
public Action Reset, Restore;
|
||||
}
|
||||
|
||||
Dictionary<ResetHandlerKey, HandlerSet> Handlers = new Dictionary<ResetHandlerKey, HandlerSet>();
|
||||
|
||||
public void Add(object o, string label, Action reset, Action restore)
|
||||
{
|
||||
ResetHandlerKey hkey = new ResetHandlerKey() { Object = o, Label = label };
|
||||
Handlers[hkey] = new HandlerSet { Reset = reset, Restore = restore };
|
||||
}
|
||||
|
||||
public void Remove(object o, string label)
|
||||
{
|
||||
ResetHandlerKey hkey = new ResetHandlerKey() { Object = o, Label = label };
|
||||
if(Handlers.ContainsKey(hkey))
|
||||
Handlers.Remove(hkey);
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
foreach (var handler in Handlers)
|
||||
handler.Value.Reset();
|
||||
}
|
||||
|
||||
public void Restore()
|
||||
{
|
||||
var todo = Handlers.ToArray();
|
||||
Handlers.Clear();
|
||||
foreach (var item in todo)
|
||||
item.Value.Restore();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public IGraphicsControl Internal_CreateGraphicsControl()
|
||||
{
|
||||
var ret = new GLControlWrapper_SlimDX9(this);
|
||||
|
|
Loading…
Reference in New Issue