Resolved crash on second context creation. Explicitly implemented internal interfaces.
This commit is contained in:
parent
1c6c2c4776
commit
11126c8a84
1 changed files with 211 additions and 81 deletions
|
@ -15,16 +15,18 @@ namespace OpenTK
|
|||
/// <summary>
|
||||
/// Represents and provides methods to manipulate an OpenGL render context.
|
||||
/// </summary>
|
||||
public class GLContext : IGLContext
|
||||
public sealed class GLContext : IGLContext, IGLContextInternal, IGLContextCreationHack
|
||||
{
|
||||
IGLContext implementation; // The actual render context implementation for the underlying platform.
|
||||
List<IDisposable> dispose_queue = new List<IDisposable>();
|
||||
|
||||
static SortedList<long, WeakReference> available_contexts =
|
||||
new SortedList<long, WeakReference>(); // Contains all available OpenGL contexts.
|
||||
|
||||
delegate IntPtr GetCurrentContextDelegate();
|
||||
static GetCurrentContextDelegate StaticGetCurrentContext;
|
||||
bool disposed;
|
||||
|
||||
static Dictionary<ContextHandle, WeakReference> available_contexts =
|
||||
new Dictionary<ContextHandle, WeakReference>(); // Contains all available OpenGL contexts.
|
||||
|
||||
//delegate IntPtr GetCurrentContextDelegate();
|
||||
//static GetCurrentContextDelegate StaticGetCurrentContext;
|
||||
|
||||
#region public GLContext(DisplayMode mode, IWindowInfo window)
|
||||
|
||||
|
@ -35,65 +37,73 @@ namespace OpenTK
|
|||
/// <param name="window"></param>
|
||||
public GLContext(DisplayMode mode, IWindowInfo window)
|
||||
{
|
||||
if (available_contexts.Count == 0)
|
||||
available_contexts.Add(0, new WeakReference(null));
|
||||
//if (available_contexts.Count == 0)
|
||||
// available_contexts.Add(IntPtr.Zero, new WeakReference(null));
|
||||
|
||||
switch (Environment.OSVersion.Platform)
|
||||
{
|
||||
case PlatformID.Unix:
|
||||
case (PlatformID)128:
|
||||
implementation = new OpenTK.Platform.X11.X11GLContext(mode, window);
|
||||
implementation = new OpenTK.Platform.X11.X11GLContext();
|
||||
break;
|
||||
|
||||
case PlatformID.Win32NT:
|
||||
case PlatformID.Win32S:
|
||||
case PlatformID.Win32Windows:
|
||||
case PlatformID.WinCE:
|
||||
implementation = new OpenTK.Platform.Windows.WinGLContext(mode, window);
|
||||
implementation = new OpenTK.Platform.Windows.WinGLContext();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new PlatformNotSupportedException("Your platform is not supported currently. Please, refer to http://opentk.sourceforge.net for more information.");
|
||||
throw new PlatformNotSupportedException("Your platform is not supported currently. Please, refer to http://www.opentk.com for more information.");
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region public static IGLContext CurrentContext
|
||||
#region void ContextDestroyed(IGLContext context, EventArgs e)
|
||||
|
||||
public static GLContext CurrentContext
|
||||
/// <summary>
|
||||
/// Handles the Destroy event.
|
||||
/// </summary>
|
||||
/// <param name="context">The OpenTK.Platform.IGLContext that was destroyed.</param>
|
||||
/// <param name="e">Not used.</param>
|
||||
void ContextDestroyed(IGLContext context, EventArgs e)
|
||||
{
|
||||
get { return (GLContext)available_contexts[StaticGetCurrentContext().ToInt64()].Target; }
|
||||
this.Destroy -= ContextDestroyed;
|
||||
available_contexts.Remove(((IGLContextInternal)this).Context);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Public Members ---
|
||||
|
||||
#region public static IGLContext CurrentContext
|
||||
|
||||
internal delegate ContextHandle GetCurrentContextDelegate();
|
||||
internal static GetCurrentContextDelegate GetCurrentContext;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the context which is current in the calling thread.
|
||||
/// </summary>
|
||||
public static GLContext CurrentContext
|
||||
{
|
||||
get
|
||||
{
|
||||
if (available_contexts.Count > 0)
|
||||
return (GLContext)available_contexts[GetCurrentContext()].Target;
|
||||
//return (GLContext)available_contexts[((IGLContextInternal)available_contexts[IntPtr.Zero].Target).GetCurrentContext()].Target;
|
||||
return null;
|
||||
//return (GLContext)available_contexts[StaticGetCurrentContext().ToInt64()].Target;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- IGLContext Members ---
|
||||
|
||||
/// <summary>
|
||||
/// Gets a handle to the OpenGL rendering context.
|
||||
/// </summary>
|
||||
public IntPtr Context
|
||||
{
|
||||
get { return implementation.Context; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IWindowInfo describing the window associated with this context.
|
||||
/// </summary>
|
||||
public IWindowInfo Info
|
||||
{
|
||||
get { return implementation.Info; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DisplayMode of the context.
|
||||
/// </summary>
|
||||
public DisplayMode Mode
|
||||
{
|
||||
get { return implementation.Mode; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an OpenGL context.
|
||||
/// </summary>
|
||||
|
@ -132,10 +142,11 @@ namespace OpenTK
|
|||
public void CreateContext(bool direct, IGLContext source)
|
||||
{
|
||||
implementation.CreateContext(direct, source);
|
||||
this.Destroy += ContextDestroyed;
|
||||
|
||||
available_contexts.Add(Context.ToInt64(), new WeakReference(this));
|
||||
if (StaticGetCurrentContext == null)
|
||||
StaticGetCurrentContext = implementation.GetCurrentContext;
|
||||
available_contexts.Add((this as IGLContextInternal).Context, new WeakReference(this));
|
||||
//if (StaticGetCurrentContext == null)
|
||||
// StaticGetCurrentContext = implementation.GetCurrentContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -162,16 +173,6 @@ namespace OpenTK
|
|||
get { return implementation.IsCurrent; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a System.IntPtr containing the handle to the OpenGL context which is current in the
|
||||
/// calling thread, or IntPtr.Zero if no OpenGL context is current.
|
||||
/// </summary>
|
||||
/// <returns>A System.IntPtr that holds the handle to the current OpenGL context.</returns>
|
||||
public IntPtr GetCurrentContext()
|
||||
{
|
||||
return implementation.GetCurrentContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raised when a Context is destroyed.
|
||||
/// </summary>
|
||||
|
@ -181,29 +182,6 @@ namespace OpenTK
|
|||
remove { implementation.Destroy -= value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of an OpenGL extension function.
|
||||
/// </summary>
|
||||
/// <param name="function">The name of the OpenGL function (e.g. "glGetString")</param>
|
||||
/// <returns>
|
||||
/// A pointer to the specified function or IntPtr.Zero if the function isn't
|
||||
/// available in the current opengl context.
|
||||
/// </returns>
|
||||
/// <see cref="Marshal.GetDelegateForFunctionPointer"/>
|
||||
public IntPtr GetAddress(string function)
|
||||
{
|
||||
return implementation.GetAddress(function);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the display modes supported by the current opengl context.
|
||||
/// </summary>
|
||||
/// <returns>An IEnumerable containing all supported display modes.</returns>
|
||||
public IEnumerable<DisplayMode> GetDisplayModes()
|
||||
{
|
||||
return implementation.GetDisplayModes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether VSync is enabled.
|
||||
/// </summary>
|
||||
|
@ -213,11 +191,50 @@ namespace OpenTK
|
|||
set { implementation.VSync = value; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- IGLContextInternal Members ---
|
||||
|
||||
/// <summary>
|
||||
/// Gets a handle to the OpenGL rendering context.
|
||||
/// </summary>
|
||||
ContextHandle IGLContextInternal.Context
|
||||
{
|
||||
get { return ((IGLContextInternal)implementation).Context; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the IWindowInfo describing the window associated with this context.
|
||||
/// </summary>
|
||||
IWindowInfo IGLContextInternal.Info
|
||||
{
|
||||
get { return (implementation as IGLContextInternal).Info; }
|
||||
//internal set { (implementation as IGLContextInternal).Info = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the DisplayMode of the context.
|
||||
/// </summary>
|
||||
DisplayMode IGLContextInternal.Mode
|
||||
{
|
||||
get { return (implementation as IGLContextInternal).Mode; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a System.IntPtr containing the handle to the OpenGL context which is current in the
|
||||
/// calling thread, or IntPtr.Zero if no OpenGL context is current.
|
||||
/// </summary>
|
||||
/// <returns>A System.IntPtr that holds the handle to the current OpenGL context.</returns>
|
||||
ContextHandle IGLContextInternal.GetCurrentContext()
|
||||
{
|
||||
return (implementation as IGLContextInternal).GetCurrentContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Registers an OpenGL resource for disposal.
|
||||
/// </summary>
|
||||
/// <param name="resource">The OpenGL resource to dispose.</param>
|
||||
public void RegisterForDisposal(IDisposable resource)
|
||||
void IGLContextInternal.RegisterForDisposal(IDisposable resource)
|
||||
{
|
||||
GC.KeepAlive(resource);
|
||||
dispose_queue.Add(resource);
|
||||
|
@ -226,28 +243,141 @@ namespace OpenTK
|
|||
/// <summary>
|
||||
/// Disposes all registered OpenGL resources.
|
||||
/// </summary>
|
||||
public void DisposeResources()
|
||||
void IGLContextInternal.DisposeResources()
|
||||
{
|
||||
foreach (IDisposable resource in dispose_queue)
|
||||
{
|
||||
resource.Dispose();
|
||||
}
|
||||
|
||||
dispose_queue.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the display modes supported by the current opengl context.
|
||||
/// </summary>
|
||||
/// <returns>An IEnumerable containing all supported display modes.</returns>
|
||||
IEnumerable<DisplayMode> IGLContextInternal.GetDisplayModes()
|
||||
{
|
||||
return (implementation as IGLContextInternal).GetDisplayModes();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the address of an OpenGL extension function.
|
||||
/// </summary>
|
||||
/// <param name="function">The name of the OpenGL function (e.g. "glGetString")</param>
|
||||
/// <returns>
|
||||
/// A pointer to the specified function or IntPtr.Zero if the function isn't
|
||||
/// available in the current opengl context.
|
||||
/// </returns>
|
||||
/// <see cref="Marshal.GetDelegateForFunctionPointer"/>
|
||||
IntPtr IGLContextInternal.GetAddress(string function)
|
||||
{
|
||||
return (implementation as IGLContextInternal).GetAddress(function);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
#region --- IGLContextCreationHack Members ---
|
||||
|
||||
bool IGLContextCreationHack.SelectDisplayMode(DisplayMode mode, IWindowInfo info)
|
||||
{
|
||||
return (implementation as IGLContextCreationHack).SelectDisplayMode(mode, info);
|
||||
}
|
||||
|
||||
void IGLContextCreationHack.SetWindowHandle(IntPtr handle)
|
||||
{
|
||||
(implementation as IGLContextCreationHack).SetWindowHandle(handle);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- IDisposable Members ---
|
||||
|
||||
/// <summary>
|
||||
/// Disposes of the GLContext.
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
available_contexts.Remove(Context.ToInt64());
|
||||
implementation.Dispose();
|
||||
this.Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
void Dispose(bool manual)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
// TODO: Check if this is safe
|
||||
//if (manual)
|
||||
{
|
||||
implementation.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~GLContext()
|
||||
{
|
||||
this.Dispose(false);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
internal class ContextHandle : /*System.Runtime.InteropServices.SafeHandle,*/ IComparable<ContextHandle>
|
||||
{
|
||||
IntPtr handle;
|
||||
public IntPtr Handle { get { return handle; } }
|
||||
|
||||
public ContextHandle() /*: base(IntPtr.Zero, true)*/ { }
|
||||
public ContextHandle(IntPtr h) { handle = h; }
|
||||
|
||||
#region IComparable<ContextHandle> Members
|
||||
|
||||
public int CompareTo(ContextHandle other)
|
||||
{
|
||||
unsafe { return (int)((int*)other.handle.ToPointer() - (int*)this.handle.ToPointer()); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Handle.ToString();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is ContextHandle)
|
||||
return this.Handle == ((ContextHandle)obj).Handle;
|
||||
return false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Handle.GetHashCode();
|
||||
}
|
||||
|
||||
/*
|
||||
public override bool IsInvalid
|
||||
{
|
||||
get { return handle == IntPtr.Zero; }
|
||||
}
|
||||
|
||||
protected override bool ReleaseHandle()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
*/
|
||||
|
||||
public static implicit operator IntPtr(ContextHandle c)
|
||||
{
|
||||
return c.handle;
|
||||
}
|
||||
|
||||
public static implicit operator ContextHandle(IntPtr p)
|
||||
{
|
||||
return new ContextHandle(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue