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()