From 4a2a223751c25f8b314a9afc63e19b46fa2564e7 Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Sat, 7 Mar 2009 10:36:51 +0000 Subject: [PATCH] Added the capability to specify the desired OpenGL version and parameters (debug / forward-compatible context). Added OpenGL 3.0 support for GLX contexts. Added support for creating dummy contexts (useful if you are creating contexts from an external library). Cleaned up unused and stale code. --- Source/OpenTK/Graphics/GraphicsContext.cs | 86 ++++++---- .../OpenTK/Graphics/GraphicsContextFlags.cs | 57 +++++++ .../OpenTK/Graphics/GraphicsContextVersion.cs | 82 +++++++++ Source/OpenTK/Graphics/IGraphicsContext.cs | 8 +- .../OpenTK/Platform/Dummy/DummyGLContext.cs | 8 +- Source/OpenTK/Platform/Factory.cs | 6 +- Source/OpenTK/Platform/IPlatformFactory.cs | 2 +- Source/OpenTK/Platform/MacOS/AglContext.cs | 6 +- .../OpenTK/Platform/MacOS/CarbonGLNative.cs | 4 +- Source/OpenTK/Platform/MacOS/MacOSFactory.cs | 2 +- Source/OpenTK/Platform/Windows/WinFactory.cs | 4 +- .../OpenTK/Platform/Windows/WinGLContext.cs | 80 +++------ Source/OpenTK/Platform/X11/Bindings/Glx.cs | 19 ++- Source/OpenTK/Platform/X11/GlxHelper.cs | 2 +- Source/OpenTK/Platform/X11/X11Factory.cs | 4 +- Source/OpenTK/Platform/X11/X11GLContext.cs | 158 +++++++++++------- 16 files changed, 356 insertions(+), 172 deletions(-) create mode 100644 Source/OpenTK/Graphics/GraphicsContextFlags.cs create mode 100644 Source/OpenTK/Graphics/GraphicsContextVersion.cs diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs index 17f584e1..f50e97e4 100644 --- a/Source/OpenTK/Graphics/GraphicsContext.cs +++ b/Source/OpenTK/Graphics/GraphicsContext.cs @@ -20,6 +20,8 @@ namespace OpenTK.Graphics /// public sealed class GraphicsContext : IGraphicsContext, IGraphicsContextInternal { + #region --- Fields --- + IGraphicsContext implementation; // The actual render context implementation for the underlying platform. List dispose_queue = new List(); bool disposed; @@ -30,18 +32,38 @@ namespace OpenTK.Graphics static bool share_contexts = true; static bool direct_rendering = true; - static object context_lock = new object(); + readonly static object context_lock = new object(); // Maps OS-specific context handles to GraphicsContext weak references. - static Dictionary available_contexts = new Dictionary(); + readonly static Dictionary available_contexts = new Dictionary(); - #region public GraphicsContext(GraphicsMode format, IWindowInfo window) + #endregion + + #region --- Constructors --- + + // Necessary to allow creation of dummy GraphicsContexts (see CreateDummyContext static method). + GraphicsContext() { } /// - /// Constructs a new GraphicsContext with the specified format, and attaches it to the specified window. + /// Constructs a new GraphicsContext with the specified GraphicsMode and attaches it to the specified window. /// /// The OpenTK.Graphics.GraphicsMode of the GraphicsContext. /// The OpenTK.Platform.IWindowInfo to attach the GraphicsContext to. public GraphicsContext(GraphicsMode mode, IWindowInfo window) + : this(mode, window, 1, 0, GraphicsContextFlags.Default) + { } + + /// + /// Constructs a new GraphicsContext with the specified GraphicsMode, version and flags, and attaches it to the specified window. + /// + /// The OpenTK.Graphics.GraphicsMode of the GraphicsContext. + /// The OpenTK.Platform.IWindowInfo to attach the GraphicsContext to. + /// The major version of the new GraphicsContext. + /// The minor version of the new GraphicsContext. + /// The GraphicsContextFlags for the GraphicsContext. + /// + /// Different hardware supports different flags, major and minor versions. Invalid parameters will be silently ignored. + /// + public GraphicsContext(GraphicsMode mode, IWindowInfo window, int major, int minor, GraphicsContextFlags flags) { bool designMode = false; if (mode == null && window == null) @@ -49,6 +71,12 @@ namespace OpenTK.Graphics else if (mode == null) throw new ArgumentNullException("mode", "Must be a valid GraphicsMode."); else if (window == null) throw new ArgumentNullException("window", "Must point to a valid window."); + // Silently ignore invalid major and minor versions. + if (major <= 0) + major = 1; + if (minor < 0) + minor = 0; + Debug.Print("Creating GraphicsContext."); try { @@ -70,10 +98,11 @@ namespace OpenTK.Graphics } } + // Todo: Add a DummyFactory implementing IPlatformFactory. if (designMode) implementation = new Platform.Dummy.DummyGLContext(mode); else - implementation = Factory.CreateGLContext(mode, window, shareContext, DirectRendering); + implementation = Factory.CreateGLContext(mode, window, shareContext, DirectRendering, major, minor, flags); lock (context_lock) { @@ -89,36 +118,20 @@ namespace OpenTK.Graphics #endregion - #region private GraphicsContext() - - private GraphicsContext() - { } - - #endregion + #region --- Static Members --- /// - /// Attempts to create a GraphicsContext object from an existing OpenGL context. + /// Creates a dummy GraphicsContext to allow OpenTK to work with contexts created by external libraries. /// - /// The window this context is bound to. - /// A new GraphicsContext object, describing the current OpenGL context. + /// A new, dummy GraphicsContext instance. /// - /// Use this function to interoperate with OpenGL contexts created outside of OpenTK. - /// The new GraphicsContext is added to the list of available OpenTK contexts. - /// Make sure to call the Dispose() method once this context is destroyed. - /// You may not call this method more than once on the same context. Doing so will throw an exception. + /// Instances created by this methodwill not be functional. Instance methods will have no effect. /// - public static GraphicsContext CreateFromCurrentThread(IWindowInfo window) + public static GraphicsContext CreateDummyContext() { - Debug.Print("Creating context from current thread."); - GraphicsContext context = new GraphicsContext(); context.is_external = true; - if (Configuration.RunningOnWindows) - context.implementation = new OpenTK.Platform.Windows.WinGLContext(window); - else if (Configuration.RunningOnX11) - context.implementation = new OpenTK.Platform.X11.X11GLContext(window); - else - throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information."); + context.implementation = new OpenTK.Platform.Dummy.DummyGLContext(GraphicsMode.Default); lock (context_lock) { @@ -128,6 +141,10 @@ namespace OpenTK.Graphics return context; } + #endregion + + #region --- Private Members --- + #region void ContextDestroyed(IGraphicsContext context, EventArgs e) /// @@ -143,6 +160,8 @@ namespace OpenTK.Graphics #endregion + #endregion + #region --- Public Members --- #region public static IGraphicsContext CurrentContext @@ -232,10 +251,6 @@ namespace OpenTK.Graphics #endregion - internal IGraphicsContext Implementation - { - get { return implementation; } - } #region --- IGraphicsContext Members --- /// @@ -329,6 +344,15 @@ namespace OpenTK.Graphics #region --- IGraphicsContextInternal Members --- + #region Implementation + + IGraphicsContext IGraphicsContextInternal.Implementation + { + get { return implementation; } + } + + #endregion + #region void LoadAll() void IGraphicsContextInternal.LoadAll() diff --git a/Source/OpenTK/Graphics/GraphicsContextFlags.cs b/Source/OpenTK/Graphics/GraphicsContextFlags.cs new file mode 100644 index 00000000..d580ffce --- /dev/null +++ b/Source/OpenTK/Graphics/GraphicsContextFlags.cs @@ -0,0 +1,57 @@ +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Graphics +{ + /// + /// Enumerates various flags that affect the creation of new GraphicsContexts. + /// + [Flags] + public enum GraphicsContextFlags + { + /// + /// The default value of the GraphicsContextFlags enumeration. + /// + Default = 0x0000, + /// + /// Indicates that this is a debug GraphicsContext. Debug contexts may provide + /// additional debugging information at the cost of performance. + /// + /// + Debug = 0x0001, + /// + /// Indicates that this is a forward compatible GraphicsContext. Forward-compatible contexts + /// do not support functionality marked as deprecated in the current GraphicsContextVersion. + /// + /// Forward-compatible contexts are defined only for OpenGL versions 3.0 and later. + ForwardCompatible = 0x0002 + } +} diff --git a/Source/OpenTK/Graphics/GraphicsContextVersion.cs b/Source/OpenTK/Graphics/GraphicsContextVersion.cs new file mode 100644 index 00000000..8febbfbc --- /dev/null +++ b/Source/OpenTK/Graphics/GraphicsContextVersion.cs @@ -0,0 +1,82 @@ +#region License +// +// The Open Toolkit Library License +// +// Copyright (c) 2006 - 2008 the Open Toolkit library, except where noted. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do +// so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. +// +#endregion + +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Graphics +{ + /// + /// Defines the version information of a GraphicsContext. + /// + public sealed class GraphicsContextVersion + { + #region Fields + + int minor, major; + string vendor = String.Empty, renderer = String.Empty; + + #endregion + + #region Constructors + + internal GraphicsContextVersion(int minor, int major, string vendor, string renderer) + { + Minor = minor; + Major = major; + Vendor = vendor; + Renderer = renderer; + } + + #endregion + + #region Public Members + + /// + /// Gets a System.Int32 indicating the minor version of a GraphicsContext instance. + /// + public int Minor { get { return minor; } private set { minor = value; } } + + /// + /// Gets a System.Int32 indicating the major version of a GraphicsContext instance. + /// + public int Major { get { return major; } private set { major = value; } } + + /// + /// Gets a System.String indicating the vendor of a GraphicsContext instance. + /// + public string Vendor { get { return vendor; } private set { vendor = value; } } + + /// + /// Gets a System.String indicating the renderer of a GraphicsContext instance. + /// + public string Renderer { get { return renderer; } private set { renderer = value; } } + + #endregion + } +} diff --git a/Source/OpenTK/Graphics/IGraphicsContext.cs b/Source/OpenTK/Graphics/IGraphicsContext.cs index f32e3261..449551c8 100644 --- a/Source/OpenTK/Graphics/IGraphicsContext.cs +++ b/Source/OpenTK/Graphics/IGraphicsContext.cs @@ -63,6 +63,8 @@ namespace OpenTK.Graphics /// public interface IGraphicsContextInternal { + IGraphicsContext Implementation { get; } + ///// ///// Creates an OpenGL context with the specified direct/indirect rendering mode and sharing state with the ///// specified IGraphicsContext. @@ -80,9 +82,9 @@ namespace OpenTK.Graphics /// ContextHandle Context { get; } - /// - /// Gets the IWindowInfo describing the window associated with this context. - /// + // + // Gets the IWindowInfo describing the window associated with this context. + // //IWindowInfo Info { get; } /// Gets the GraphicsMode of the context. diff --git a/Source/OpenTK/Platform/Dummy/DummyGLContext.cs b/Source/OpenTK/Platform/Dummy/DummyGLContext.cs index ecfaa963..694006e5 100644 --- a/Source/OpenTK/Platform/Dummy/DummyGLContext.cs +++ b/Source/OpenTK/Platform/Dummy/DummyGLContext.cs @@ -81,7 +81,12 @@ namespace OpenTK.Platform.Dummy #region IGraphicsContextInternal Members - public void LoadAll() + IGraphicsContext IGraphicsContextInternal.Implementation + { + get { return this; } + } + + void IGraphicsContextInternal.LoadAll() { } @@ -91,6 +96,5 @@ namespace OpenTK.Platform.Dummy } #endregion - } } diff --git a/Source/OpenTK/Platform/Factory.cs b/Source/OpenTK/Platform/Factory.cs index 735d58b2..424adc57 100644 --- a/Source/OpenTK/Platform/Factory.cs +++ b/Source/OpenTK/Platform/Factory.cs @@ -33,9 +33,9 @@ namespace OpenTK.Platform return implementation.CreateDisplayDeviceDriver(); } - internal static IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering) + internal static IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) { - return implementation.CreateGLContext(mode, window, shareContext, directRendering); + return implementation.CreateGLContext(mode, window, shareContext, directRendering, major, minor, flags); } internal static IGraphicsMode CreateGraphicsMode() @@ -62,7 +62,7 @@ namespace OpenTK.Platform throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information."); } - public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering) + public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering, int major, int minor, GraphicsContextFlags flags) { throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information."); } diff --git a/Source/OpenTK/Platform/IPlatformFactory.cs b/Source/OpenTK/Platform/IPlatformFactory.cs index c324fcdd..f913c79d 100644 --- a/Source/OpenTK/Platform/IPlatformFactory.cs +++ b/Source/OpenTK/Platform/IPlatformFactory.cs @@ -12,7 +12,7 @@ namespace OpenTK.Platform OpenTK.Graphics.IDisplayDeviceDriver CreateDisplayDeviceDriver(); - OpenTK.Graphics.IGraphicsContext CreateGLContext(OpenTK.Graphics.GraphicsMode mode, IWindowInfo window, OpenTK.Graphics.IGraphicsContext shareContext, bool DirectRendering); + OpenTK.Graphics.IGraphicsContext CreateGLContext(OpenTK.Graphics.GraphicsMode mode, IWindowInfo window, OpenTK.Graphics.IGraphicsContext shareContext, bool DirectRendering, int major, int minor, OpenTK.Graphics.GraphicsContextFlags flags); OpenTK.Graphics.IGraphicsMode CreateGraphicsMode(); } diff --git a/Source/OpenTK/Platform/MacOS/AglContext.cs b/Source/OpenTK/Platform/MacOS/AglContext.cs index 3250c7d1..6a850f20 100644 --- a/Source/OpenTK/Platform/MacOS/AglContext.cs +++ b/Source/OpenTK/Platform/MacOS/AglContext.cs @@ -389,6 +389,11 @@ namespace OpenTK.Platform.MacOS #region IGraphicsContextInternal Members + IGraphicsContext IGraphicsContextInternal.Implementation + { + get { return this; } + } + void IGraphicsContextInternal.LoadAll() { GL.LoadAll(); @@ -421,6 +426,5 @@ namespace OpenTK.Platform.MacOS } #endregion - } } diff --git a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs index 64e7e024..8231a062 100644 --- a/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs +++ b/Source/OpenTK/Platform/MacOS/CarbonGLNative.cs @@ -728,7 +728,7 @@ namespace OpenTK.Platform.MacOS private void SetFullscreen() { - ((AglContext)context.Implementation).SetFullScreen(window); + ((AglContext)(context as IGraphicsContextInternal).Implementation).SetFullScreen(window); mWindowedWidth = mWidth; mWindowedHeight = mHeight; @@ -743,7 +743,7 @@ namespace OpenTK.Platform.MacOS } private void UnsetFullscreen() { - ((AglContext)context.Implementation).UnsetFullScreen(window); + ((AglContext)(context as IGraphicsContextInternal).Implementation).UnsetFullScreen(window); SetSize(mWindowedWidth, mWindowedHeight); } diff --git a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs index 1b2030e2..fa3bdec7 100644 --- a/Source/OpenTK/Platform/MacOS/MacOSFactory.cs +++ b/Source/OpenTK/Platform/MacOS/MacOSFactory.cs @@ -25,7 +25,7 @@ namespace OpenTK.Platform.MacOS return new QuartzDisplayDeviceDriver(); } - public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering) + public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering, int major, int minor, GraphicsContextFlags flags) { return new AglContext(mode, window, shareContext); } diff --git a/Source/OpenTK/Platform/Windows/WinFactory.cs b/Source/OpenTK/Platform/Windows/WinFactory.cs index b5f080ed..61496e4f 100644 --- a/Source/OpenTK/Platform/Windows/WinFactory.cs +++ b/Source/OpenTK/Platform/Windows/WinFactory.cs @@ -26,9 +26,9 @@ using OpenTK.Input; return new WinDisplayDeviceDriver(); } - public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering) + public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags) { - return new WinGLContext(mode, window, shareContext); + return new WinGLContext(mode, window, shareContext, major, minor, flags); } public IGraphicsMode CreateGraphicsMode() diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs index 47fd9945..26af453f 100644 --- a/Source/OpenTK/Platform/Windows/WinGLContext.cs +++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs @@ -59,7 +59,8 @@ namespace OpenTK.Platform.Windows } } - public WinGLContext(GraphicsMode format, IWindowInfo window, IGraphicsContext sharedContext) + public WinGLContext(GraphicsMode format, IWindowInfo window, IGraphicsContext sharedContext, + int major, int minor, GraphicsContextFlags flags) { if (window == null) throw new ArgumentNullException("window", "Must point to a valid window."); @@ -91,17 +92,24 @@ namespace OpenTK.Platform.Windows { try { - Debug.Write("Attempting to create GL3 render context... "); + Debug.WriteLine("Using WGL_ARB_create_context..."); + + List attributes = new List(); + attributes.Add((int)ArbCreateContext.MajorVersion); + attributes.Add(major); + attributes.Add((int)ArbCreateContext.MinorVersion); + attributes.Add(minor); + if (flags != 0) + { + attributes.Add((int)ArbCreateContext.Flags); + attributes.Add((int)flags); + } + renderContext = new ContextHandle( Wgl.Arb.CreateContextAttribs( currentWindow.DeviceContext, sharedContext != null ? (sharedContext as IGraphicsContextInternal).Context.Handle : IntPtr.Zero, - new int[] - { - (int)ArbCreateContext.MajorVersion, 3, - (int)ArbCreateContext.MinorVersion, 0, - 0 - })); + attributes.ToArray())); } catch (EntryPointNotFoundException e) { Debug.Print(e.ToString()); } catch (NullReferenceException e) { Debug.Print(e.ToString()); } @@ -129,50 +137,10 @@ namespace OpenTK.Platform.Windows } } - public WinGLContext(IWindowInfo window) - { - if (window == null) throw new ArgumentNullException("window"); - - renderContext = new ContextHandle(Wgl.GetCurrentContext()); - if (renderContext == ContextHandle.Zero) - throw new InvalidOperationException("No OpenGL context is current in the calling thread."); - - currentWindow = (WinWindowInfo)window; - } - #endregion #region --- IGraphicsContext Members --- - #region public void CreateContext() - - public void CreateContext() - { - throw new NotSupportedException(); - //this.CreateContext(true, null); - } - - #endregion - - #region public void CreateContext(bool direct) - - public void CreateContext(bool direct) - { - throw new NotSupportedException(); - //this.CreateContext(direct, null); - } - - #endregion - - #region public void CreateContext(bool direct, IGraphicsContext source) - - public void CreateContext(bool direct, IGraphicsContext source) - { - throw new NotSupportedException(); - } - - #endregion - #region public void SwapBuffers() public void SwapBuffers() @@ -253,13 +221,21 @@ namespace OpenTK.Platform.Windows } #endregion - public event DestroyEvent Destroy; #endregion #region --- IGLContextInternal Members --- + #region Implementation + + IGraphicsContext IGraphicsContextInternal.Implementation + { + get { return this; } + } + + #endregion + #region void LoadAll() void IGraphicsContextInternal.LoadAll() @@ -481,12 +457,6 @@ namespace OpenTK.Platform.Windows #endregion - #endregion - - #region IGraphicsContext Members - - - #endregion } } diff --git a/Source/OpenTK/Platform/X11/Bindings/Glx.cs b/Source/OpenTK/Platform/X11/Bindings/Glx.cs index df5d38d4..29c69464 100644 --- a/Source/OpenTK/Platform/X11/Bindings/Glx.cs +++ b/Source/OpenTK/Platform/X11/Bindings/Glx.cs @@ -227,6 +227,17 @@ namespace OpenTK.Platform.X11 PIXMAP_BIT_SGIX = 0x00000002, } + public enum ArbCreateContext : int + { + DebugBit = 0x0001, + ForwardCompatibleBit = 0x0002, + MajorVersion = 0x2091, + MinorVersion = 0x2092, + LayerPlane = 0x2093, + Flags = 0x2094, + ErrorInvalidVersion = 0x2095, + } + #endregion /// @@ -322,7 +333,7 @@ namespace OpenTK.Platform.X11 unsafe public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs) { - return Delegates.glxCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs); + return Delegates.glXCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs); } public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int[] attribs) @@ -331,7 +342,7 @@ namespace OpenTK.Platform.X11 { fixed (int* attribs_ptr = attribs) { - return Delegates.glxCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs_ptr); + return Delegates.glXCreateContextAttribsARB(display, fbconfig, share_context, direct, attribs_ptr); } } } @@ -339,7 +350,7 @@ namespace OpenTK.Platform.X11 #endregion } - partial class Delegates + internal static partial class Delegates { [SuppressUnmanagedCodeSecurity] public delegate int SwapIntervalSGI(int interval); @@ -347,7 +358,7 @@ namespace OpenTK.Platform.X11 [SuppressUnmanagedCodeSecurity] unsafe public delegate IntPtr CreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs); - unsafe public static CreateContextAttribsARB glxCreateContextAttribsARB = null; + unsafe public static CreateContextAttribsARB glXCreateContextAttribsARB = null; } #endregion diff --git a/Source/OpenTK/Platform/X11/GlxHelper.cs b/Source/OpenTK/Platform/X11/GlxHelper.cs index 88d13368..b2de144d 100644 --- a/Source/OpenTK/Platform/X11/GlxHelper.cs +++ b/Source/OpenTK/Platform/X11/GlxHelper.cs @@ -36,7 +36,7 @@ namespace OpenTK.Platform.X11 static Delegate LoadDelegate(string name, Type signature) { Delegate d; - string realName = name.StartsWith("glx") ? name.Substring(3) : name; + string realName = name.ToLower().StartsWith("glx") ? name.Substring(3) : name; if (typeof(Glx).GetMethod(realName, BindingFlags.NonPublic | BindingFlags.Static) != null) diff --git a/Source/OpenTK/Platform/X11/X11Factory.cs b/Source/OpenTK/Platform/X11/X11Factory.cs index 522dbc57..5e80af87 100644 --- a/Source/OpenTK/Platform/X11/X11Factory.cs +++ b/Source/OpenTK/Platform/X11/X11Factory.cs @@ -25,9 +25,9 @@ namespace OpenTK.Platform.X11 return new X11XrandrDisplayDevice(); } - public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering) + public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering, int major, int minor, GraphicsContextFlags flags) { - return new X11GLContext(mode, window, shareContext, DirectRendering); + return new X11GLContext(mode, window, shareContext, DirectRendering, major, minor, flags); } public IGraphicsMode CreateGraphicsMode() diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index 23b80404..5659d9f8 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -22,11 +22,10 @@ namespace OpenTK.Platform.X11 internal sealed class X11GLContext : IGraphicsContext, IGraphicsContextInternal { ContextHandle context; - //X11WindowInfo window; X11WindowInfo currentWindow; - //IntPtr visual; bool vsync_supported; int vsync_interval; + bool glx_loaded; bool disposed; @@ -39,28 +38,98 @@ namespace OpenTK.Platform.X11 GraphicsContext.GetCurrentContext = X11GLContext.GetCurrentContext; } - public X11GLContext(GraphicsMode mode, IWindowInfo info, IGraphicsContext shared, bool directRendering) + public X11GLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shared, bool direct, + int major, int minor, GraphicsContextFlags flags) { - //if (mode == null) mode = GraphicsMode.Default; - if (info == null) throw new ArgumentNullException("info", "Should point to a valid window."); + if (mode == null) + throw new ArgumentNullException("mode"); + if (window == null) + throw new ArgumentNullException("window"); - currentWindow = (X11WindowInfo)info; + currentWindow = (X11WindowInfo)window; currentWindow.VisualInfo = SelectVisual(mode, currentWindow); - Debug.Print("Chose visual: {0}", currentWindow.VisualInfo); + ContextHandle shareHandle = shared != null ? + (shared as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero; - CreateContext(shared, directRendering, currentWindow); - } + Debug.Write("Creating X11GLContext context: "); + Debug.Write(direct ? "direct, " : "indirect, "); + Debug.WriteLine(shareHandle.Handle == IntPtr.Zero ? "not shared... " : + String.Format("shared with ({0})... ", shareHandle)); - public X11GLContext(IWindowInfo window) - { - if (window == null) throw new ArgumentNullException("window"); + if (!glx_loaded) + { + Debug.WriteLine("Loading GLX extensions."); + + // Create a temporary context to obtain the necessary function pointers. + XVisualInfo visual = currentWindow.VisualInfo; + IntPtr ctx = Glx.CreateContext(currentWindow.Display, ref visual, IntPtr.Zero, true); + if (ctx == IntPtr.Zero) + ctx = Glx.CreateContext(currentWindow.Display, ref visual, IntPtr.Zero, false); - //renderContext = Glx.GetCurrentContext(); - //if (renderContext == IntPtr.Zero) - // throw new InvalidOperationException("No OpenGL context is current in the calling thread."); + if (ctx != IntPtr.Zero) + { + Glx.LoadAll(); + Glx.MakeCurrent(currentWindow.Display, IntPtr.Zero, IntPtr.Zero); + Glx.DestroyContext(currentWindow.Display, ctx); + glx_loaded = true; + } + } - //currentWindow = window; + // Try using the new context creation method. If it fails, fall back to the old one. + // For each of these methods, we try two times to create a context: + // one with the "direct" flag intact, the other with the flag inversed. + if (Glx.Delegates.glXCreateContextAttribsARB != null) + { + Debug.WriteLine("Using GLX_ARB_create_context..."); + + unsafe + { + // We need the FB config for the current GraphicsMode. + int count; + IntPtr* fbconfigs = Glx.ChooseFBConfig(currentWindow.Display, currentWindow.Screen, + new int[] { (int)GLXAttribute.VISUAL_ID, (int)mode.Index, 0 }, out count); + + if (count > 0) + { + List attributes = new List(); + attributes.Add((int)ArbCreateContext.MajorVersion); + attributes.Add(major); + attributes.Add((int)ArbCreateContext.MinorVersion); + attributes.Add(minor); + if (flags != 0) + { + attributes.Add((int)ArbCreateContext.Flags); + attributes.Add((int)flags); + } + + context = new ContextHandle(Glx.Arb.CreateContextAttribs(currentWindow.Display, *fbconfigs, + shareHandle.Handle, direct, attributes.ToArray())); + + if (context == ContextHandle.Zero) + context = new ContextHandle(Glx.Arb.CreateContextAttribs(currentWindow.Display, *fbconfigs, + shareHandle.Handle, !direct, attributes.ToArray())); + + Functions.XFree((IntPtr)fbconfigs); + } + } + } + + if (context == ContextHandle.Zero) + { + Debug.WriteLine("Using legacy context creation."); + + XVisualInfo info = currentWindow.VisualInfo; // Cannot pass a Property by reference. + context = new ContextHandle(Glx.CreateContext(currentWindow.Display, ref info, shareHandle.Handle, direct)); + + if (context == ContextHandle.Zero) + context = new ContextHandle(Glx.CreateContext(currentWindow.Display, ref info, IntPtr.Zero, !direct)); + } + + if (context != ContextHandle.Zero) + Debug.Print("Success! (id: {0})", context); + else + throw new GraphicsContextException("Failed to create OpenGL context. Glx.CreateContext call returned 0."); } #endregion @@ -91,54 +160,6 @@ namespace OpenTK.Platform.X11 #endregion - #region void CreateContext(IGraphicsContext shareContext, bool direct) - - void CreateContext(IGraphicsContext shareContext, bool direct, X11WindowInfo window) - { - try - { - ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : - (ContextHandle)IntPtr.Zero; - - Debug.Write("Creating OpenGL context: "); - Debug.Write(direct ? "direct, " : "indirect, "); - Debug.Write(shareHandle.Handle == IntPtr.Zero ? "not shared... " : - String.Format("shared with ({0})... ", shareHandle)); - - lock (API.Lock) - { - XVisualInfo info = window.VisualInfo; // Cannot pass a Property by reference. - context = new ContextHandle(Glx.CreateContext(window.Display, ref info, shareHandle.Handle, direct)); - - // Context creation succeeded, return. - if (context != ContextHandle.Zero) - { - Debug.Print("done! (id: {0})", context); - return; - } - - // Context creation failed. Retry with a non-shared context with the direct/indirect bit flipped. - Debug.Print("failed."); - Debug.Write(String.Format("Creating OpenGL context: {0}, not shared... ", !direct ? "direct" : "indirect")); - context = new ContextHandle(Glx.CreateContext(window.Display, ref info, IntPtr.Zero, !direct)); - if (context != ContextHandle.Zero) - { - Debug.Print("done! (id: {0})", context); - return; - } - } - - Debug.Print("failed."); - throw new GraphicsModeException("Failed to create OpenGL context. Glx.CreateContext call returned 0."); - } - finally - { - //Debug.Unindent(); - } - } - - #endregion - bool SupportsExtension(X11WindowInfo window, string e) { string extensions = Glx.QueryExtensionsString(window.Display, window.Screen); @@ -255,6 +276,15 @@ namespace OpenTK.Platform.X11 #region --- IGLContextInternal Members --- + #region Implementation + + IGraphicsContext IGraphicsContextInternal.Implementation + { + get { return this; } + } + + #endregion + #region void LoadAll() void IGraphicsContextInternal.LoadAll()