From 11126c8a844afc080ff1533429585308435e2fbe Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Fri, 11 Jan 2008 20:31:59 +0000 Subject: [PATCH] Resolved crash on second context creation. Explicitly implemented internal interfaces. --- Source/OpenTK/GLContext.cs | 292 +++++++++++++++++++++++++++---------- 1 file changed, 211 insertions(+), 81 deletions(-) diff --git a/Source/OpenTK/GLContext.cs b/Source/OpenTK/GLContext.cs index 8332b73b..ad2c4d8d 100644 --- a/Source/OpenTK/GLContext.cs +++ b/Source/OpenTK/GLContext.cs @@ -15,16 +15,18 @@ namespace OpenTK /// /// Represents and provides methods to manipulate an OpenGL render context. /// - public class GLContext : IGLContext + public sealed class GLContext : IGLContext, IGLContextInternal, IGLContextCreationHack { IGLContext implementation; // The actual render context implementation for the underlying platform. List dispose_queue = new List(); - - static SortedList available_contexts = - new SortedList(); // Contains all available OpenGL contexts. - delegate IntPtr GetCurrentContextDelegate(); - static GetCurrentContextDelegate StaticGetCurrentContext; + bool disposed; + + static Dictionary available_contexts = + new Dictionary(); // Contains all available OpenGL contexts. + + //delegate IntPtr GetCurrentContextDelegate(); + //static GetCurrentContextDelegate StaticGetCurrentContext; #region public GLContext(DisplayMode mode, IWindowInfo window) @@ -35,65 +37,73 @@ namespace OpenTK /// 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 + /// + /// Handles the Destroy event. + /// + /// The OpenTK.Platform.IGLContext that was destroyed. + /// Not used. + 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; + + /// + /// Returns the context which is current in the calling thread. + /// + 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 --- - /// - /// Gets a handle to the OpenGL rendering context. - /// - public IntPtr Context - { - get { return implementation.Context; } - } - - /// - /// Gets the IWindowInfo describing the window associated with this context. - /// - public IWindowInfo Info - { - get { return implementation.Info; } - } - - /// - /// Gets the DisplayMode of the context. - /// - public DisplayMode Mode - { - get { return implementation.Mode; } - } - /// /// Creates an OpenGL context. /// @@ -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; } /// @@ -162,16 +173,6 @@ namespace OpenTK get { return implementation.IsCurrent; } } - /// - /// 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. - /// - /// A System.IntPtr that holds the handle to the current OpenGL context. - public IntPtr GetCurrentContext() - { - return implementation.GetCurrentContext(); - } - /// /// Raised when a Context is destroyed. /// @@ -181,29 +182,6 @@ namespace OpenTK remove { implementation.Destroy -= value; } } - /// - /// Gets the address of an OpenGL extension function. - /// - /// The name of the OpenGL function (e.g. "glGetString") - /// - /// A pointer to the specified function or IntPtr.Zero if the function isn't - /// available in the current opengl context. - /// - /// - public IntPtr GetAddress(string function) - { - return implementation.GetAddress(function); - } - - /// - /// Returns the display modes supported by the current opengl context. - /// - /// An IEnumerable containing all supported display modes. - public IEnumerable GetDisplayModes() - { - return implementation.GetDisplayModes(); - } - /// /// Gets or sets a value indicating whether VSync is enabled. /// @@ -213,11 +191,50 @@ namespace OpenTK set { implementation.VSync = value; } } + #endregion + + #region --- IGLContextInternal Members --- + + /// + /// Gets a handle to the OpenGL rendering context. + /// + ContextHandle IGLContextInternal.Context + { + get { return ((IGLContextInternal)implementation).Context; } + } + + /// + /// Gets the IWindowInfo describing the window associated with this context. + /// + IWindowInfo IGLContextInternal.Info + { + get { return (implementation as IGLContextInternal).Info; } + //internal set { (implementation as IGLContextInternal).Info = value; } + } + + /// + /// Gets the DisplayMode of the context. + /// + DisplayMode IGLContextInternal.Mode + { + get { return (implementation as IGLContextInternal).Mode; } + } + + /// + /// 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. + /// + /// A System.IntPtr that holds the handle to the current OpenGL context. + ContextHandle IGLContextInternal.GetCurrentContext() + { + return (implementation as IGLContextInternal).GetCurrentContext(); + } + /// /// Registers an OpenGL resource for disposal. /// /// The OpenGL resource to dispose. - public void RegisterForDisposal(IDisposable resource) + void IGLContextInternal.RegisterForDisposal(IDisposable resource) { GC.KeepAlive(resource); dispose_queue.Add(resource); @@ -226,28 +243,141 @@ namespace OpenTK /// /// Disposes all registered OpenGL resources. /// - public void DisposeResources() + void IGLContextInternal.DisposeResources() { foreach (IDisposable resource in dispose_queue) - { resource.Dispose(); - } + dispose_queue.Clear(); } + /// + /// Returns the display modes supported by the current opengl context. + /// + /// An IEnumerable containing all supported display modes. + IEnumerable IGLContextInternal.GetDisplayModes() + { + return (implementation as IGLContextInternal).GetDisplayModes(); + } + + /// + /// Gets the address of an OpenGL extension function. + /// + /// The name of the OpenGL function (e.g. "glGetString") + /// + /// A pointer to the specified function or IntPtr.Zero if the function isn't + /// available in the current opengl context. + /// + /// + 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 --- /// /// Disposes of the GLContext. /// 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 +{ + IntPtr handle; + public IntPtr Handle { get { return handle; } } + + public ContextHandle() /*: base(IntPtr.Zero, true)*/ { } + public ContextHandle(IntPtr h) { handle = h; } + + #region IComparable 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); + } + + + +}