diff --git a/Source/OpenTK/BindingsBase.cs b/Source/OpenTK/BindingsBase.cs index 4c968a65..60b0716f 100644 --- a/Source/OpenTK/BindingsBase.cs +++ b/Source/OpenTK/BindingsBase.cs @@ -123,9 +123,9 @@ namespace OpenTK #region Internal Members - #region LoadAll + #region LoadEntryPoints - internal void LoadAll() + internal void LoadEntryPoints() { // Using reflection is more than 3 times faster than directly loading delegates on the first // run, probably due to code generation overhead. Subsequent runs are faster with direct loading @@ -164,12 +164,9 @@ namespace OpenTK #endregion - #region Load + #region LoadEntryPoint - /// - /// Loads all extension and core functions. - /// - internal bool Load(string function) + internal bool LoadEntryPoint(string function) { FieldInfo f = DelegatesClass.GetField(function, BindingFlags.Static | BindingFlags.NonPublic); if (f == null) diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs index c6ef8501..57a0934c 100644 --- a/Source/OpenTK/Graphics/GraphicsContext.cs +++ b/Source/OpenTK/Graphics/GraphicsContext.cs @@ -27,7 +27,7 @@ namespace OpenTK.Graphics // 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. - //bool is_external; + readonly bool IsExternal; bool check_errors = true; static bool share_contexts = true; @@ -101,17 +101,8 @@ namespace OpenTK.Graphics Debug.Print("GraphicsContextFlags: {0}", flags); Debug.Print("Requested version: {0}.{1}", major, minor); - IGraphicsContext shareContext = null; - if (GraphicsContext.ShareContexts) - { - // A small hack to create a shared context with the first available context. - foreach (WeakReference r in GraphicsContext.available_contexts.Values) - { - shareContext = (IGraphicsContext)r.Target; - break; - } - } - + IGraphicsContext shareContext = shareContext = FindSharedContext(); + // Todo: Add a DummyFactory implementing IPlatformFactory. if (designMode) implementation = new Platform.Dummy.DummyGLContext(); @@ -131,6 +122,50 @@ namespace OpenTK.Graphics } } + public GraphicsContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags) + { + 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; + } + } + + available_contexts.Add((implementation as IGraphicsContextInternal).Context, new WeakReference(this)); + } + } + + #endregion + + #region Private Members + + static IGraphicsContext FindSharedContext() + { + if (GraphicsContext.ShareContexts) + { + // A small hack to create a shared context with the first available context. + foreach (WeakReference r in GraphicsContext.available_contexts.Values) + { + return (IGraphicsContext)r.Target; + } + } + return null; + } + #endregion #region --- Static Members --- @@ -420,7 +455,7 @@ namespace OpenTK.Graphics available_contexts.Remove((this as IGraphicsContextInternal).Context); } - if (manual) + if (manual && !IsExternal) { if (implementation != null) implementation.Dispose(); @@ -429,11 +464,6 @@ namespace OpenTK.Graphics } } - //~GraphicsContext() - //{ - // this.Dispose(false); - //} - #endregion } } diff --git a/Source/OpenTK/Graphics/OpenGL/GLHelper.cs b/Source/OpenTK/Graphics/OpenGL/GLHelper.cs index af8421b1..32b5165e 100644 --- a/Source/OpenTK/Graphics/OpenGL/GLHelper.cs +++ b/Source/OpenTK/Graphics/OpenGL/GLHelper.cs @@ -66,276 +66,18 @@ namespace OpenTK.Graphics.OpenGL #endregion #region --- Public Members --- -#if false - #region public static bool SupportsExtension(string name) /// - /// Determines whether the specified OpenGL extension category is available in - /// the current OpenGL context. Equivalent to IsExtensionSupported(name, true) + /// Loads all OpenGL entry points (core and extension). + /// This method is provided for compatibility purposes with older OpenTK versions. /// - /// The string for the OpenGL extension category (eg. "GL_ARB_multitexture") - /// True if the specified extension is available, false otherwise. - public static bool SupportsExtension(string name) + public static void LoadAll() { - if (RebuildExtensionList) - BuildExtensionList(); - - lock (gl_lock) - { - sb.Remove(0, sb.Length); - if (!name.StartsWith("GL_")) - sb.Append("gl_"); - sb.Append(name.ToLower()); - sb.Replace("_", String.Empty); - - // Search the cache for the string. - return AvailableExtensions.ContainsKey(sb.ToString()); - } + new GL().LoadEntryPoints(); } #endregion - #region public static Delegate GetDelegate(string name) - - /// - /// Returns a System.Delegate wrapping the specified OpenGL function. You must use the - /// base OpenGL name of the function (e.g. "glVertex3fv" instead of "Vertex3"). - /// - /// The name of the OpenGL function (eg. "glNewList") - /// - /// A System.Delegate that can be used to call this OpenGL function or null, if the specified - /// function name does not correspond to an OpenGL function or if the function is not - /// supported by the video drivers. - /// - public static Delegate GetDelegate(string name) - { - FieldInfo info = typeof(Delegates).GetField(name, BindingFlags.Static | BindingFlags.NonPublic); - if (info == null) - return null; - return (Delegate)info.GetValue(null); - } - - #endregion - - #region public static bool SupportsFunction(string function) - - /// - /// Checks if a given OpenGL function is supported by the current context - /// - /// The name of the OpenGL function (i.e. glShaderSource) - /// True if the function is supported, false otherwise - public static bool SupportsFunction(string function) - { - lock (gl_lock) - { - if (function == null) - throw new ArgumentNullException("function"); - - sb.Remove(0, sb.Length); - if (!function.StartsWith("gl")) - sb.Append("gl"); - sb.Append(function); - FieldInfo f = DelegatesClass.GetField(sb.ToString(), BindingFlags.Static | BindingFlags.NonPublic); - if (f == null) - return false; - - return f.GetValue(null) != null; - } - } - - #endregion - - #region public static bool SupportsFunction(string function, string extension) - - /// - /// Checks if a given OpenGL function is supported by the current context - /// - /// The name of the OpenGL function (e.g. glShaderSource) - /// The name of the extension catagory (e.g. ARB, EXT, ATI, ...) - /// True if the function is supported, false otherwise - public static bool SupportsFunction(string function, string extension) - { - lock (gl_lock) - { - if (function == null) - throw new ArgumentNullException("function"); - if (extension == null) - throw new ArgumentNullException("extension"); - - sb.Remove(0, sb.Length); - if (!function.StartsWith("gl")) - sb.Append("gl"); - sb.Append(function); - if (!function.EndsWith(extension)) - sb.Append(extension); - - FieldInfo f = delegatesClass.GetField(sb.ToString(), BindingFlags.Static | BindingFlags.NonPublic); - if (f == null) - return false; - - return f.GetValue(null) != null; - } - } - - #endregion - - #region static bool SupportsFunction(MethodInfo function) - - /// - /// Checks if a given OpenGL function is supported by the current context. - /// - /// The System.Reflection.MethodInfo for the OpenGL function. - /// True if the function is supported, false otherwise. - static bool SupportsFunction(MethodInfo function) - { - if (function == null) - throw new ArgumentNullException("function"); - - AutoGeneratedAttribute[] attr = (AutoGeneratedAttribute[]) - function.GetCustomAttributes(typeof(AutoGeneratedAttribute), false); - if (attr.Length == 0) - return false; - - return SupportsFunction(attr[0].EntryPoint); - } - - #endregion - - #region private static void BuildExtensionList() - - /// - /// Builds a cache of the supported extensions to speed up searches. - /// - private static void BuildExtensionList() - { - // Assumes there is an opengl context current. - AvailableExtensions.Clear(); - string version_string = GL.GetString(StringName.Version); - if (String.IsNullOrEmpty(version_string)) - { - throw new ApplicationException("Failed to build extension list. Is there an opengl context current?"); - } - - string version; - - // Most drivers return the version in the 3 first characters of the version string, - // (e.g. on Ati X1950 with Catalyst 7.10 -> "2.0.6956 Release"). However, Mesa seems - // to do something strange: "1.4 (2.1 Mesa 7.0.1).". - // Update: this seems to occur with indirect rendering. E.g. Ati 8.2: 1.4 (2.1.7281 ...) - // We'll do some trickery to get the second number (2.1), but this may break on - // some implementations... - //if (version_string.ToLower().Contains("mesa")) - { - int index = version_string.IndexOf('('); - if (index != -1) - version = version_string.Substring(index + 1, 3); - else - version = version_string.TrimStart(' '); - } - //else - // version = version_string.TrimStart(' '); - - if (version.StartsWith("1.1")) - { - AvailableExtensions.Add("glversion11", true); - } - else if (version.StartsWith("1.2")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - } - else if (version.StartsWith("1.3")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - } - else if (version.StartsWith("1.4")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - AvailableExtensions.Add("glversion14", true); - } - else if (version.StartsWith("1.5")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - AvailableExtensions.Add("glversion14", true); - AvailableExtensions.Add("glversion15", true); - } - else if (version.StartsWith("2.0")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - AvailableExtensions.Add("glversion14", true); - AvailableExtensions.Add("glversion15", true); - AvailableExtensions.Add("glversion20", true); - } - else if (version.StartsWith("2.1")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - AvailableExtensions.Add("glversion14", true); - AvailableExtensions.Add("glversion15", true); - AvailableExtensions.Add("glversion20", true); - AvailableExtensions.Add("glversion21", true); - } - else if (version.StartsWith("3.0")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - AvailableExtensions.Add("glversion14", true); - AvailableExtensions.Add("glversion15", true); - AvailableExtensions.Add("glversion20", true); - AvailableExtensions.Add("glversion21", true); - AvailableExtensions.Add("glversion30", true); - } - else if (version.StartsWith("3.1")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - AvailableExtensions.Add("glversion14", true); - AvailableExtensions.Add("glversion15", true); - AvailableExtensions.Add("glversion20", true); - AvailableExtensions.Add("glversion21", true); - AvailableExtensions.Add("glversion30", true); - AvailableExtensions.Add("glversion31", true); - } - else if (version.StartsWith("3.2")) - { - AvailableExtensions.Add("glversion11", true); - AvailableExtensions.Add("glversion12", true); - AvailableExtensions.Add("glversion13", true); - AvailableExtensions.Add("glversion14", true); - AvailableExtensions.Add("glversion15", true); - AvailableExtensions.Add("glversion20", true); - AvailableExtensions.Add("glversion21", true); - AvailableExtensions.Add("glversion30", true); - AvailableExtensions.Add("glversion31", true); - AvailableExtensions.Add("glversion32", true); - } - - string extension_string = GL.GetString(StringName.Extensions); - if (String.IsNullOrEmpty(extension_string)) - return; // no extensions are available - - string[] extensions = extension_string.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string ext in extensions) - AvailableExtensions.Add(ext.Replace("_", String.Empty).ToLower(), true); - - //rebuildExtensionList = false; - } - - #endregion -#endif - #endregion - #region --- Protected Members --- /// diff --git a/Source/OpenTK/Platform/DesktopGraphicsContext.cs b/Source/OpenTK/Platform/DesktopGraphicsContext.cs index d40824c3..18b459da 100644 --- a/Source/OpenTK/Platform/DesktopGraphicsContext.cs +++ b/Source/OpenTK/Platform/DesktopGraphicsContext.cs @@ -35,7 +35,7 @@ namespace OpenTK.Platform { public override void LoadAll() { - new OpenTK.Graphics.OpenGL.GL().LoadAll(); + new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints(); } } } diff --git a/Source/OpenTK/Platform/Dummy/DummyGLContext.cs b/Source/OpenTK/Platform/Dummy/DummyGLContext.cs index a017b9b5..563ccf03 100644 --- a/Source/OpenTK/Platform/Dummy/DummyGLContext.cs +++ b/Source/OpenTK/Platform/Dummy/DummyGLContext.cs @@ -26,8 +26,8 @@ namespace OpenTK.Platform.Dummy #region --- Constructors --- public DummyGLContext() + : this(new ContextHandle(new IntPtr(++handle_count))) { - Handle = new ContextHandle(new IntPtr(++handle_count)); Mode = new GraphicsMode(new IntPtr(2), 32, 16, 0, 0, 0, 2, false); } diff --git a/Source/OpenTK/Platform/EmbeddedGraphicsContext.cs b/Source/OpenTK/Platform/EmbeddedGraphicsContext.cs index 928c2a15..2ac37638 100644 --- a/Source/OpenTK/Platform/EmbeddedGraphicsContext.cs +++ b/Source/OpenTK/Platform/EmbeddedGraphicsContext.cs @@ -35,9 +35,9 @@ namespace OpenTK.Platform { public override void LoadAll() { - new OpenTK.Graphics.ES10.GL().LoadAll(); - new OpenTK.Graphics.ES11.GL().LoadAll(); - new OpenTK.Graphics.ES20.GL().LoadAll(); + new OpenTK.Graphics.ES10.GL().LoadEntryPoints(); + new OpenTK.Graphics.ES11.GL().LoadEntryPoints(); + new OpenTK.Graphics.ES20.GL().LoadEntryPoints(); } } } \ No newline at end of file diff --git a/Source/OpenTK/Platform/Factory.cs b/Source/OpenTK/Platform/Factory.cs index 2e67b8fe..591dabef 100644 --- a/Source/OpenTK/Platform/Factory.cs +++ b/Source/OpenTK/Platform/Factory.cs @@ -99,6 +99,11 @@ namespace OpenTK.Platform return default_implementation.CreateGLContext(mode, window, shareContext, directRendering, major, minor, flags); } + public IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) + { + return default_implementation.CreateGLContext(handle, window, shareContext, directRendering, major, minor, flags); + } + public GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() { return default_implementation.CreateGetCurrentGraphicsContext(); @@ -139,6 +144,11 @@ namespace OpenTK.Platform throw new PlatformNotSupportedException(error_string); } + public IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) + { + throw new PlatformNotSupportedException(error_string); + } + public IGraphicsContext CreateESContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags) { throw new PlatformNotSupportedException(error_string); diff --git a/Source/OpenTK/Platform/IPlatformFactory.cs b/Source/OpenTK/Platform/IPlatformFactory.cs index f0678473..8bd81b5a 100644 --- a/Source/OpenTK/Platform/IPlatformFactory.cs +++ b/Source/OpenTK/Platform/IPlatformFactory.cs @@ -41,6 +41,8 @@ namespace OpenTK.Platform IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags); + IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags); + GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext(); IGraphicsMode CreateGraphicsMode(); diff --git a/Source/OpenTK/Platform/MacOS/AglContext.cs b/Source/OpenTK/Platform/MacOS/AglContext.cs index 8b98de1f..36872054 100644 --- a/Source/OpenTK/Platform/MacOS/AglContext.cs +++ b/Source/OpenTK/Platform/MacOS/AglContext.cs @@ -47,6 +47,17 @@ namespace OpenTK.Platform.MacOS CreateContext(mode, carbonWindow, shareContextRef, true); } + public AglContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext) + { + if (handle == ContextHandle.Zero) + throw new ArgumentException("handle"); + if (window == null) + throw new ArgumentNullException("window"); + + Handle = handle; + carbonWindow = (CarbonWindowInfo)window; + } + private void AddPixelAttrib(List aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute) { diff --git a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs index 02f3be41..00282dd1 100644 --- a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs +++ b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs @@ -52,6 +52,11 @@ namespace OpenTK.Platform.MacOS return new AglContext(mode, window, shareContext); } + public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) + { + return new AglContext(handle, window, shareContext); + } + public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() { return (GraphicsContext.GetCurrentContextDelegate)delegate diff --git a/Source/OpenTK/Platform/Windows/WinFactory.cs b/Source/OpenTK/Platform/Windows/WinFactory.cs index abf23979..461e5be2 100644 --- a/Source/OpenTK/Platform/Windows/WinFactory.cs +++ b/Source/OpenTK/Platform/Windows/WinFactory.cs @@ -53,6 +53,11 @@ namespace OpenTK.Platform.Windows return new WinGLContext(mode, (WinWindowInfo)window, shareContext, major, minor, flags); } + public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) + { + return new WinGLContext(handle, (WinWindowInfo)window, shareContext, major, minor, flags); + } + public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() { return (GraphicsContext.GetCurrentContextDelegate)delegate diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs index 9588f855..254a3ec9 100644 --- a/Source/OpenTK/Platform/Windows/WinGLContext.cs +++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs @@ -141,6 +141,17 @@ namespace OpenTK.Platform.Windows } } + public WinGLContext(ContextHandle handle, WinWindowInfo window, IGraphicsContext sharedContext, + int major, int minor, GraphicsContextFlags flags) + { + if (handle == ContextHandle.Zero) + throw new ArgumentException("handle"); + if (window == null) + throw new ArgumentNullException("window"); + + Handle = handle; + } + #endregion #region --- IGraphicsContext Members --- diff --git a/Source/OpenTK/Platform/X11/X11Factory.cs b/Source/OpenTK/Platform/X11/X11Factory.cs index 0574aa07..a713e95d 100644 --- a/Source/OpenTK/Platform/X11/X11Factory.cs +++ b/Source/OpenTK/Platform/X11/X11Factory.cs @@ -60,6 +60,11 @@ namespace OpenTK.Platform.X11 return new X11GLContext(mode, window, shareContext, directRendering, major, minor, flags); } + public virtual IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) + { + return new X11GLContext(handle, window, shareContext, directRendering, major, minor, flags); + } + public virtual GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext() { return (GraphicsContext.GetCurrentContextDelegate)delegate diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index aa0e0591..c22d47fc 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -73,7 +73,7 @@ namespace OpenTK.Platform.X11 if (ctx != IntPtr.Zero) { - new Glx().LoadAll(); + new Glx().LoadEntryPoints(); Glx.MakeCurrent(Display, IntPtr.Zero, IntPtr.Zero); //Glx.DestroyContext(Display, ctx); glx_loaded = true; @@ -162,6 +162,19 @@ namespace OpenTK.Platform.X11 Debug.Print("Warning: Context is not direct."); } + public X11GLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shared, bool direct, + int major, int minor, GraphicsContextFlags flags) + { + if (handle == ContextHandle.Zero) + throw new ArgumentException("handle"); + if (window == null) + throw new ArgumentNullException("window"); + + Handle = handle; + currentWindow = (X11WindowInfo)window; + Display = currentWindow.Display; + } + #endregion #region --- Private Methods --- @@ -318,7 +331,7 @@ namespace OpenTK.Platform.X11 public override void LoadAll() { - new Glx().LoadAll(); + new Glx().LoadEntryPoints(); vsync_supported = this.GetAddress("glXSwapIntervalSGI") != IntPtr.Zero; Debug.Print("Context supports vsync: {0}.", vsync_supported);