diff --git a/BizHawk.Client.Common/GLManager.cs b/BizHawk.Client.Common/GLManager.cs
index 44440f04b5..de6826d67d 100644
--- a/BizHawk.Client.Common/GLManager.cs
+++ b/BizHawk.Client.Common/GLManager.cs
@@ -7,13 +7,17 @@ namespace BizHawk.Client.Common
///
/// This singleton class manages OpenGL contexts, in an effort to minimize context changes.
///
- public class GLManager
+ public class GLManager : IDisposable
{
private GLManager()
{
}
+ public void Dispose()
+ {
+ }
+
public static GLManager Instance { get; private set; }
public static void CreateInstance()
diff --git a/BizHawk.Client.EmuHawk/Program.cs b/BizHawk.Client.EmuHawk/Program.cs
index 88f7971321..cd4b51be9b 100644
--- a/BizHawk.Client.EmuHawk/Program.cs
+++ b/BizHawk.Client.EmuHawk/Program.cs
@@ -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
diff --git a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs
index 6b4c699cfd..27ee3d6cbf 100644
--- a/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs
+++ b/Bizware/BizHawk.Bizware.BizwareGL.SlimDX/IGL_SlimDX9.cs
@@ -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 Handlers = new Dictionary();
+
+ 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);