diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs index 6c0b93f6..1fd39b2d 100644 --- a/Source/OpenTK/Graphics/GraphicsContext.cs +++ b/Source/OpenTK/Graphics/GraphicsContext.cs @@ -39,14 +39,13 @@ namespace OpenTK.Graphics /// public sealed class GraphicsContext : IGraphicsContext, IGraphicsContextInternal { + public delegate IntPtr GetAddressDelegate(string function); + public delegate ContextHandle GetCurrentContextDelegate(); + #region --- Fields --- IGraphicsContext implementation; // The actual render context implementation for the underlying platform. bool disposed; - // Indicates that this context was created through external means, e.g. Tao.Sdl or GLWidget#. - // In this case, We'll assume that the external program will manage the lifetime of this - // context - we'll not destroy it manually. - readonly bool IsExternal; bool check_errors = true; // Cache for the context handle. We need this for RemoveContext() // in case the user does not call Dispose(). When this happens, @@ -67,17 +66,6 @@ namespace OpenTK.Graphics #region --- Constructors --- - // Necessary to allow creation of dummy GraphicsContexts (see CreateDummyContext static method). - GraphicsContext(ContextHandle handle) - { - implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle); - - lock (SyncRoot) - { - AddContext(this); - } - } - /// /// Constructs a new GraphicsContext with the specified GraphicsMode and attaches it to the specified window. /// @@ -163,12 +151,65 @@ namespace OpenTK.Graphics } } + /// + /// Initializes a new instance of the class using + /// an external context handle that was created by a third-party library. + /// + /// + /// A valid, unique handle for an external OpenGL context, or ContextHandle.Zero to use the current context. + /// It is an error to specify a handle that has been created through OpenTK or that has been passed to OpenTK before. + /// + /// + /// A GetAddressDelegate instance that accepts the name of an OpenGL function and returns + /// a valid function pointer, or IntPtr.Zero if that function is not supported. This delegate should be + /// implemented using the same toolkit that created the OpenGL context (i.e. if the context was created with + /// SDL_GL_CreateContext(), then this delegate should use SDL_GL_GetProcAddress() to retrieve function + /// pointers.) + /// + /// + /// A GetCurrentContextDelegate instance that returns the handle of the current OpenGL context, + /// or IntPtr.Zero if no context is current on the calling thread. This delegate should be implemented + /// using the same toolkit that created the OpenGL context (i.e. if the context was created with + /// SDL_GL_CreateContext(), then this delegate should use SDL_GL_GetCurrentContext() to retrieve + /// the current context.) + /// + public GraphicsContext(ContextHandle handle, GetAddressDelegate getAddress, GetCurrentContextDelegate getCurrent) + { + if (getAddress == null || getCurrent == null) + throw new ArgumentNullException(); + + lock (SyncRoot) + { + // Replace a zero-handle by the current context, if any + if (handle == ContextHandle.Zero) + { + handle = getCurrent(); + } + + // Make sure this handle corresponds to a valid, unique OpenGL context + if (handle == ContextHandle.Zero) + { + throw new GraphicsContextMissingException(); + } + else if (available_contexts.ContainsKey(handle)) + { + throw new InvalidOperationException("Context handle has already been added"); + } + + // We have a valid handle for an external OpenGL context, wrap it into a + // DummyGLContext instance. + implementation = new Platform.Dummy.DummyGLContext(handle, getAddress); + GetCurrentContext = getCurrent ?? GetCurrentContext; + AddContext(this); + } + implementation.LoadAll(); + } + /// /// Constructs a new GraphicsContext from a pre-existing context created outside of OpenTK. /// /// The handle of the existing context. This must be a valid, unique handle that is not known to OpenTK. - /// The window this context is bound to. This must be a valid window obtained through Utilities.CreateWindowInfo. - /// Occurs if handle is identical to a context already registered with OpenTK. + /// This parameter is reserved. public GraphicsContext(ContextHandle handle, IWindowInfo window) : this(handle, window, null, 1, 0, GraphicsContextFlags.Default) { } @@ -177,40 +218,14 @@ namespace OpenTK.Graphics /// Constructs a new GraphicsContext from a pre-existing context created outside of OpenTK. /// /// The handle of the existing context. This must be a valid, unique handle that is not known to OpenTK. - /// The window this context is bound to. This must be a valid window obtained through Utilities.CreateWindowInfo. - /// A different context that shares resources with this instance, if any. - /// Pass null if the context is not shared or if this is the first GraphicsContext instruct you construct. - /// The major version of the context (e.g. "2" for "2.1"). - /// The minor version of the context (e.g. "1" for "2.1"). - /// A bitwise combination of that describe this context. - /// Occurs if handle is identical to a context already registered with OpenTK. + /// This parameter is reserved. + /// This parameter is reserved. + /// This parameter is reserved. + /// This parameter is reserved. + /// This parameter is reserved.. public GraphicsContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags) - : this(handle) - { - lock (SyncRoot) - { - IsExternal = true; - - if (handle == ContextHandle.Zero) - { - implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle); - } - else if (available_contexts.ContainsKey(handle)) - { - throw new GraphicsContextException("Context already exists."); - } - else - { - switch ((flags & GraphicsContextFlags.Embedded) == GraphicsContextFlags.Embedded) - { - case false: implementation = Factory.Default.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break; - case true: implementation = Factory.Embedded.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break; - } - } - - (this as IGraphicsContextInternal).LoadAll(); - } - } + : this(handle, Platform.Utilities.CreateGetAddress(), Factory.Default.CreateGetCurrentGraphicsContext()) + { } #endregion @@ -309,6 +324,7 @@ namespace OpenTK.Graphics /// Instances created by this method will not be functional. Instance methods will have no effect. /// This method requires that a context is current on the calling thread. /// + [Obsolete("Use GraphicsContext(ContextHandle, IWindowInfo) constructor instead")] public static GraphicsContext CreateDummyContext() { ContextHandle handle = GetCurrentContext(); @@ -326,12 +342,13 @@ namespace OpenTK.Graphics /// /// Instances created by this method will not be functional. Instance methods will have no effect. /// + [Obsolete("Use GraphicsContext(ContextHandle, IWindowInfo) constructor instead")] public static GraphicsContext CreateDummyContext(ContextHandle handle) { if (handle == ContextHandle.Zero) throw new ArgumentOutOfRangeException("handle"); - return new GraphicsContext(handle); + return new GraphicsContext(handle, (IWindowInfo)null); } #endregion @@ -352,7 +369,6 @@ namespace OpenTK.Graphics #region public static IGraphicsContext CurrentContext - internal delegate ContextHandle GetCurrentContextDelegate(); internal static GetCurrentContextDelegate GetCurrentContext; ///