mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-02-24 17:36:55 +00:00
Fix exceptions on reused OpenGL context handles
Implementations may reuse OpenGL context handles that have been destroyed. If a context is finalized but not Disposed, then OpenTK may keep a reference to the old context handle, causing a crash when the same handle is returned for a new context. To fix that, new context handles will now replace old handles in case of a clash.
This commit is contained in:
parent
08701d318c
commit
b7af883cff
|
@ -66,7 +66,7 @@ namespace OpenTK.Graphics
|
||||||
|
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
available_contexts.Add((implementation as IGraphicsContextInternal).Context, new WeakReference(this));
|
AddContext(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ namespace OpenTK.Graphics
|
||||||
implementation = factory.CreateGLContext(mode, window, shareContext, direct_rendering, major, minor, flags);
|
implementation = factory.CreateGLContext(mode, window, shareContext, direct_rendering, major, minor, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this));
|
AddContext(this);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -198,8 +198,7 @@ namespace OpenTK.Graphics
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
available_contexts.Add((implementation as IGraphicsContextInternal).Context, new WeakReference(this));
|
AddContext(this);
|
||||||
|
|
||||||
(this as IGraphicsContextInternal).LoadAll();
|
(this as IGraphicsContextInternal).LoadAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,6 +240,34 @@ namespace OpenTK.Graphics
|
||||||
|
|
||||||
#region Private Members
|
#region Private Members
|
||||||
|
|
||||||
|
static void AddContext(IGraphicsContextInternal context)
|
||||||
|
{
|
||||||
|
ContextHandle ctx = context.Context;
|
||||||
|
if (!available_contexts.ContainsKey(ctx))
|
||||||
|
{
|
||||||
|
available_contexts.Add(ctx, new WeakReference(context));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Print("A GraphicsContext with handle {0} already exists.", ctx);
|
||||||
|
Debug.Print("Did you forget to call Dispose()?");
|
||||||
|
available_contexts[ctx] = new WeakReference(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RemoveContext(IGraphicsContextInternal context)
|
||||||
|
{
|
||||||
|
ContextHandle ctx = context.Context;
|
||||||
|
if (available_contexts.ContainsKey(ctx))
|
||||||
|
{
|
||||||
|
available_contexts.Remove(ctx);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Print("Tried to remove non-existent GraphicsContext handle {0}. Call Dispose() to avoid this error.", ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static IGraphicsContext FindSharedContext()
|
static IGraphicsContext FindSharedContext()
|
||||||
{
|
{
|
||||||
if (GraphicsContext.ShareContexts)
|
if (GraphicsContext.ShareContexts)
|
||||||
|
@ -394,29 +421,6 @@ namespace OpenTK.Graphics
|
||||||
get { return check_errors; }
|
get { return check_errors; }
|
||||||
set { check_errors = value; }
|
set { check_errors = value; }
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// Creates an OpenGL context with the specified direct/indirect rendering mode and sharing state with the
|
|
||||||
/// specified IGraphicsContext.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="direct">Set to true for direct rendering or false otherwise.</param>
|
|
||||||
/// <param name="source">The source IGraphicsContext to share state from.</param>.
|
|
||||||
/// <remarks>
|
|
||||||
/// <para>
|
|
||||||
/// Direct rendering is the default rendering mode for OpenTK, since it can provide higher performance
|
|
||||||
/// in some circumastances.
|
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// The 'direct' parameter is a hint, and will ignored if the specified mode is not supported (e.g. setting
|
|
||||||
/// indirect rendering on Windows platforms).
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
|
||||||
void CreateContext(bool direct, IGraphicsContext source)
|
|
||||||
{
|
|
||||||
lock (SyncRoot)
|
|
||||||
{
|
|
||||||
available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Swaps buffers on a context. This presents the rendered scene to the user.
|
/// Swaps buffers on a context. This presents the rendered scene to the user.
|
||||||
|
@ -569,21 +573,33 @@ namespace OpenTK.Graphics
|
||||||
{
|
{
|
||||||
if (!IsDisposed)
|
if (!IsDisposed)
|
||||||
{
|
{
|
||||||
Debug.Print("Disposing context {0}.", (this as IGraphicsContextInternal).Context.ToString());
|
|
||||||
lock (SyncRoot)
|
lock (SyncRoot)
|
||||||
{
|
{
|
||||||
available_contexts.Remove((this as IGraphicsContextInternal).Context);
|
RemoveContext(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Note: we cannot dispose the implementation
|
||||||
|
// from a different thread. See wglDeleteContext.
|
||||||
|
// This is also known to crash GLX implementations.
|
||||||
if (manual && !IsExternal)
|
if (manual && !IsExternal)
|
||||||
{
|
{
|
||||||
|
Debug.Print("Disposing context {0}.", (this as IGraphicsContextInternal).Context.ToString());
|
||||||
if (implementation != null)
|
if (implementation != null)
|
||||||
implementation.Dispose();
|
implementation.Dispose();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.WriteLine("GraphicsContext leaked, did you forget to call Dispose()?");
|
||||||
|
}
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~GraphicsContext()
|
||||||
|
{
|
||||||
|
Dispose(false);
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue