diff --git a/Source/OpenTK/Platform/DummyGLContext.cs b/Source/OpenTK/Platform/DummyGLContext.cs index ccdc1da1..0f95ac21 100644 --- a/Source/OpenTK/Platform/DummyGLContext.cs +++ b/Source/OpenTK/Platform/DummyGLContext.cs @@ -9,33 +9,30 @@ namespace OpenTK.Platform /// internal sealed class DummyGLContext : IGLContext { + WindowInfo info = new WindowInfo(); + DisplayMode mode = new DisplayMode(); + #region --- IGLContext Members --- - public void SwapBuffers() - { - } + public IntPtr Context { get { return IntPtr.Zero; } } + public IWindowInfo Info { get { return info; } } + public DisplayMode Mode { get { return mode; } } - public void MakeCurrent() - { - } + public void CreateContext() { } + public void CreateContext(bool direct) { } + public void CreateContext(bool direct, IGLContext source) { } - public IntPtr GetAddress(string function) - { - return IntPtr.Zero; - } + public void SwapBuffers() { } + public void MakeCurrent() { } - public IEnumerable GetDisplayModes() - { - throw new Exception("The method or operation is not implemented."); - } + public IntPtr GetAddress(string function) { return IntPtr.Zero; } + public IEnumerable GetDisplayModes() { return null; } #endregion #region --- IDisposable Members --- - public void Dispose() - { - } + public void Dispose() { } #endregion } diff --git a/Source/OpenTK/Platform/GLContext.cs b/Source/OpenTK/Platform/GLContext.cs new file mode 100644 index 00000000..0edf4aae --- /dev/null +++ b/Source/OpenTK/Platform/GLContext.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Platform +{ + public class GLContext : IGLContext + { + private IGLContext implementation; + + public GLContext(DisplayMode mode, IWindowInfo window) + { + + } + + #region --- IGLContext Members --- + + public IntPtr Context + { + get { return implementation.Context; } + } + + public IWindowInfo Info + { + get { throw new Exception("The method or operation is not implemented."); } + } + + public DisplayMode Mode + { + get { throw new Exception("The method or operation is not implemented."); } + } + + public void CreateContext() + { + throw new Exception("The method or operation is not implemented."); + } + + public void CreateContext(bool direct) + { + throw new Exception("The method or operation is not implemented."); + } + + public void CreateContext(bool direct, IGLContext source) + { + throw new Exception("The method or operation is not implemented."); + } + + public void SwapBuffers() + { + throw new Exception("The method or operation is not implemented."); + } + + public void MakeCurrent() + { + throw new Exception("The method or operation is not implemented."); + } + + public IntPtr GetAddress(string function) + { + throw new Exception("The method or operation is not implemented."); + } + + public IEnumerable GetDisplayModes() + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + throw new Exception("The method or operation is not implemented."); + } + + #endregion + } +} diff --git a/Source/OpenTK/Platform/IGLContext.cs b/Source/OpenTK/Platform/IGLContext.cs index 4bb6244c..086abd95 100644 --- a/Source/OpenTK/Platform/IGLContext.cs +++ b/Source/OpenTK/Platform/IGLContext.cs @@ -10,10 +10,59 @@ using System.Text; namespace OpenTK.Platform { + /// + /// Provides methods for creating and interacting with an OpenGL context. + /// public interface IGLContext : IDisposable { /// - /// Swaps buffers on a context. This presents the rendered scene to the user. + /// Gets a handle to the OpenGL rendering context. + /// + IntPtr Context { get; } + + /// + /// Gets the IWindowInfo describing the window associated with this context. + /// + IWindowInfo Info { get; } + + /// + /// Gets the DisplayMode of the context. + /// + DisplayMode Mode { get; } + + /// + /// Creates an OpenGL context. + /// + void CreateContext(); + + /// + /// Creates an OpenGL context with a direct or indirect rendering mode. This parameter is ignored + /// on Windows platforms (direct mode only). + /// + /// Set to true for direct rendering or false otherwise. + /// + /// + /// Direct rendering is the default rendering mode for OpenTK, since it can provide higher performance + /// in some circumastances. + /// + /// + /// The 'direct' parameter is a hint, and will ignored if the specified mode is not supported (e.g. setting + /// indirect rendering on Windows platforms). + /// + /// + void CreateContext(bool direct); + + /// + /// Creates an OpenGL context with the specified direct/indirect rendering mode and sharing state with the + /// specified IGLContext. + /// + /// Set to true for direct rendering or false otherwise. + /// The source IGLContext to share state from.. + /// + void CreateContext(bool direct, IGLContext source); + + /// + /// Swaps buffers on a context. This presents the rendered scene to the user. /// void SwapBuffers(); diff --git a/Source/OpenTK/Platform/IMutableWindowInfo.cs b/Source/OpenTK/Platform/IMutableWindowInfo.cs new file mode 100644 index 00000000..be38194b --- /dev/null +++ b/Source/OpenTK/Platform/IMutableWindowInfo.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenTK.Platform +{ + /// + /// Provides methods to + /// + public interface IMutableWindowInfo : IWindowInfo + { + IWindowInfo GetInfoFrom(System.Windows.Forms.Control control); + IWindowInfo GetInfoFrom(System.Windows.Forms.NativeWindow window); + IWindowInfo GetInfoFrom(OpenTK.GameWindow window); + IWindowInfo GetInfoFrom(IWindowInfo info); + void CopyInfoFrom(IWindowInfo info); + } +} diff --git a/Source/OpenTK/Platform/IWindowInfo.cs b/Source/OpenTK/Platform/IWindowInfo.cs index 47d8e552..b868b817 100644 --- a/Source/OpenTK/Platform/IWindowInfo.cs +++ b/Source/OpenTK/Platform/IWindowInfo.cs @@ -18,9 +18,5 @@ namespace OpenTK.Platform { IntPtr Handle { get; } IWindowInfo Parent { get; } - void GetInfoFrom(System.Windows.Forms.Control control); - void GetInfoFrom(System.Windows.Forms.NativeWindow window); - void GetInfoFrom(OpenTK.GameWindow window); - void GetInfoFrom(IWindowInfo info); } } diff --git a/Source/OpenTK/Platform/WindowInfo.cs b/Source/OpenTK/Platform/WindowInfo.cs index 230eabdc..41d06222 100644 --- a/Source/OpenTK/Platform/WindowInfo.cs +++ b/Source/OpenTK/Platform/WindowInfo.cs @@ -8,9 +8,9 @@ namespace OpenTK.Platform /// /// Describes a Windows.Form.Control, Windows.Forms.NativeWindow or OpenTK.GameWindow. /// - public sealed class WindowInfo : IWindowInfo + public sealed class WindowInfo : IMutableWindowInfo { - IWindowInfo implementation; + IMutableWindowInfo implementation; #region --- Constructors --- @@ -45,7 +45,7 @@ namespace OpenTK.Platform /// The System.Windows.Forms.Control to get info from. public WindowInfo(Control control) : this() { - implementation.GetInfoFrom(control); + implementation.CopyInfoFrom(implementation.GetInfoFrom(control)); } /// @@ -86,40 +86,49 @@ namespace OpenTK.Platform get { return implementation.Parent; } } + #endregion + + #region --- IMutableWindowInfo Members --- + /// /// Updates the WindowInfo to describe the specified Control. /// /// The System.Windows.Forms.Control to describe. - public void GetInfoFrom(Control control) + public IWindowInfo GetInfoFrom(Control control) { - implementation.GetInfoFrom(control); + return implementation.GetInfoFrom(control); } /// /// Updates the WindowInfo to describe the specified NativeWindow. /// /// The System.Windows.Forms.NativeWindow to describe. - public void GetInfoFrom(NativeWindow window) + public IWindowInfo GetInfoFrom(NativeWindow window) { - implementation.GetInfoFrom(window); + return implementation.GetInfoFrom(window); } /// /// Updates the WindowInfo to describe the specified GameWindow. /// /// The OpenTK.GameWindow to describe. - public void GetInfoFrom(GameWindow window) + public IWindowInfo GetInfoFrom(GameWindow window) { - implementation.GetInfoFrom(window); + return implementation.GetInfoFrom(window); } /// /// Updates the WindowInfo using the specified WindowInfo. /// /// The OpenTK.Platform.Window to get information from. - public void GetInfoFrom(IWindowInfo info) + public IWindowInfo GetInfoFrom(IWindowInfo info) { - implementation.GetInfoFrom(info); + return implementation.GetInfoFrom(info); + } + + public void CopyInfoFrom(IWindowInfo info) + { + implementation.CopyInfoFrom(info); } #endregion diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs index 5cd46ffb..a758c845 100644 --- a/Source/OpenTK/Platform/Windows/WinGLContext.cs +++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs @@ -5,13 +5,17 @@ */ #endregion +#region --- Using Directives --- + using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; +using System.Diagnostics; using OpenTK.OpenGL; -using System.Diagnostics; + +#endregion namespace OpenTK.Platform.Windows { @@ -24,7 +28,7 @@ namespace OpenTK.Platform.Windows private IntPtr deviceContext; private IntPtr renderContext; static private IntPtr opengl32Handle; - static private readonly string opengl32Name = "OPENGL32.DLL"; + private const string opengl32Name = "OPENGL32.DLL"; private WindowInfo windowInfo = new WindowInfo(); private DisplayMode mode; @@ -157,11 +161,59 @@ namespace OpenTK.Platform.Windows Debug.Print("done! (format: {0})", pixel); } + #endregion + + #region --- IGLContext Members --- + + #region public IntPtr Context + + public IntPtr Context + { + get { return renderContext; } + private set { renderContext = value; } + } + + #endregion + + #region public IWindowInfo Info + + public IWindowInfo Info + { + get { return windowInfo; } + } + + #endregion + + #region public DisplayMode Mode + + public DisplayMode Mode + { + get { return new DisplayMode(mode); } + } + #endregion #region public void CreateContext() public void CreateContext() + { + this.CreateContext(true, null); + } + + #endregion + + #region public void CreateContext(bool direct) + + public void CreateContext(bool direct) + { + this.CreateContext(direct, null); + } + + #endregion + + #region public void CreateContext(bool direct, IGLContext source) + + public void CreateContext(bool direct, IGLContext source) { this.PrepareContext(); @@ -175,16 +227,20 @@ namespace OpenTK.Platform.Windows } else { - throw new ApplicationException("Could not create opengl Rendering Context."); + throw new ApplicationException("Could not create OpenGL render context (Wgl.CreateContext() return 0)."); } Wgl.Imports.MakeCurrent(deviceContext, renderContext); Wgl.LoadAll(); + + if (source != null) + { + Debug.Print("Sharing state with context {0}", (source as WinGLContext).Context); + Wgl.Imports.ShareLists(renderContext, (source as WinGLContext).Context); + } } #endregion - #region --- IGLContext Members --- - #region public void SwapBuffers() public void SwapBuffers() diff --git a/Source/OpenTK/Platform/Windows/WindowInfo.cs b/Source/OpenTK/Platform/Windows/WindowInfo.cs index 895b6941..c8e5ba47 100644 --- a/Source/OpenTK/Platform/Windows/WindowInfo.cs +++ b/Source/OpenTK/Platform/Windows/WindowInfo.cs @@ -15,7 +15,7 @@ namespace OpenTK.Platform.Windows /// Describes a Windows.Form.Control, Windows.Forms.NativeWindow or OpenTK.GameWindow on the Windows platform. /// This class supports OpenTK, and is not intended for use by OpenTK programs. /// - internal sealed class WindowInfo : IWindowInfo + internal sealed class WindowInfo : IMutableWindowInfo { private IntPtr handle; private WindowInfo parent; @@ -24,6 +24,12 @@ namespace OpenTK.Platform.Windows { } + public WindowInfo(IntPtr handle, IWindowInfo parent) + { + this.Handle = handle; + this.Parent = parent; + } + public WindowInfo(IWindowInfo info) { if (info == null) @@ -77,51 +83,47 @@ namespace OpenTK.Platform.Windows } } - public void GetInfoFrom(Control control) + public IWindowInfo GetInfoFrom(Control control) { if (control == null) throw new ArgumentException("Control cannot be null."); - this.Handle = control.Handle; if (control.Parent == null) { - this.Parent = null; - } - else - { - if (this.Parent == null) - this.Parent = new WindowInfo(control.Parent); - else - this.Parent.GetInfoFrom(control.Parent); + return new WindowInfo(control.Handle, null); } + + return new WindowInfo(control.Handle, GetInfoFrom(control.Parent)); } - public void GetInfoFrom(NativeWindow window) + public IWindowInfo GetInfoFrom(NativeWindow window) { if (window == null) throw new ArgumentException("NativeWindow cannot be null."); - this.Handle = window.Handle; - this.Parent = null; + return new WindowInfo(window.Handle, null); } - public void GetInfoFrom(GameWindow window) + public IWindowInfo GetInfoFrom(GameWindow window) { if (window == null) throw new ArgumentException("GameWindow cannot be null."); - WindowInfo info = (window.WindowInfo as Windows.WindowInfo); - this.Handle = info.Handle; - this.Parent = info.Parent; + return GetInfoFrom(window.WindowInfo as Windows.WindowInfo); } - public void GetInfoFrom(IWindowInfo info) + public IWindowInfo GetInfoFrom(IWindowInfo info) { if (info == null) throw new ArgumentException("IWindowInfo cannot be null."); - + + return info; + } + + public void CopyInfoFrom(IWindowInfo info) + { this.Handle = info.Handle; - this.Parent = info.Parent; + this.Parent = info.Parent; } #endregion diff --git a/Source/OpenTK/Platform/X11/WindowInfo.cs b/Source/OpenTK/Platform/X11/WindowInfo.cs index fb84586d..5e77d808 100644 --- a/Source/OpenTK/Platform/X11/WindowInfo.cs +++ b/Source/OpenTK/Platform/X11/WindowInfo.cs @@ -15,7 +15,7 @@ namespace OpenTK.Platform.X11 /// Describes a Windows.Form.Control, Windows.Forms.NativeWindow or OpenTK.GameWindow on the X11 platform. /// This class supports OpenTK, and is not intended for use by OpenTK programs. /// - internal sealed class WindowInfo : IWindowInfo + internal sealed class WindowInfo : IMutableWindowInfo { private IntPtr rootWindow, handle, topLevelWindow, display; private int screen; @@ -49,7 +49,14 @@ namespace OpenTK.Platform.X11 #region --- IWindowInfo Members --- - public void GetInfoFrom(Control control) + public IntPtr Handle { get { return handle; } internal set { handle = value; } } + public IWindowInfo Parent { get { return parent; } internal set { parent = value as WindowInfo; } } + + #endregion + + #region --- IMutableWindowInfo Members --- + + public IWindowInfo GetInfoFrom(Control control) { if (control == null) throw new ArgumentException("GameWindow cannot be null."); @@ -57,7 +64,7 @@ namespace OpenTK.Platform.X11 throw new NotImplementedException(); } - public void GetInfoFrom(NativeWindow window) + public IWindowInfo GetInfoFrom(NativeWindow window) { if (window == null) throw new ArgumentException("GameWindow cannot be null."); @@ -65,24 +72,29 @@ namespace OpenTK.Platform.X11 throw new NotImplementedException(); } - public void GetInfoFrom(GameWindow window) + public IWindowInfo GetInfoFrom(GameWindow window) { if (window == null) throw new ArgumentException("GameWindow cannot be null."); - this.GetInfoFrom(window.WindowInfo as X11.WindowInfo); + return this.GetInfoFrom(window.WindowInfo as X11.WindowInfo); } - public void GetInfoFrom(IWindowInfo info) + public IWindowInfo GetInfoFrom(IWindowInfo info) { if (info == null) throw new ArgumentException("WindowInfo cannot be null"); - WindowInfo winfo = info as WindowInfo; + return info; + } + public void CopyInfoFrom(IWindowInfo info) + { this.Handle = info.Handle; this.Parent = info.Parent; + WindowInfo winfo = info as WindowInfo; + this.RootWindow = winfo.RootWindow; this.TopLevelWindow = winfo.TopLevelWindow; this.Display = winfo.Display; @@ -90,9 +102,6 @@ namespace OpenTK.Platform.X11 this.VisualInfo = winfo.VisualInfo; } - public IntPtr Handle { get { return handle; } internal set { handle = value; } } - public IWindowInfo Parent { get { return parent; } internal set { parent = value as WindowInfo; } } - #endregion public IntPtr RootWindow { get { return rootWindow; } internal set { rootWindow = value; } } diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index 7220fb2e..d0cb8642 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -37,7 +37,7 @@ namespace OpenTK.Platform.X11 { } - internal X11GLContext(DisplayMode mode, IWindowInfo info) + public X11GLContext(DisplayMode mode, IWindowInfo info) { if (info == null) throw new ArgumentException("IWindowInfo cannot be null."); @@ -49,44 +49,24 @@ namespace OpenTK.Platform.X11 #endregion - #region internal XVisualInfo VisualInfo + //#region private XVisualInfo VisualInfo - internal XVisualInfo VisualInfo - { - get { return windowInfo.VisualInfo; } - } + //private XVisualInfo VisualInfo + //{ + // get { return windowInfo.VisualInfo; } + //} - #endregion + //#endregion - #region internal IntPtr Handle + //#region private IntPtr Handle - internal IntPtr Handle - { - get { return windowInfo.Handle; } - set { windowInfo.Handle = value; } - } + //private IntPtr Handle + //{ + // get { return windowInfo.Handle; } + // set { windowInfo.Handle = value; } + //} - #endregion - - #region internal DisplayMode Mode - - internal DisplayMode Mode - { - get { return mode; } - set - { - if (context == IntPtr.Zero) - { - mode = value; - } - else - { - Debug.Print("Cannot change DisplayMode of an existing context."); - } - } - } - - #endregion + //#endregion #region private void PrepareContext() @@ -138,34 +118,98 @@ namespace OpenTK.Platform.X11 #endregion - #region internal void CreateContext(X11GLContext shareContext, bool direct) + #region --- IGLContext Members --- - internal void CreateContext(X11GLContext shareContext, bool direct) + #region public IntPtr Context + + public IntPtr Context { - Debug.WriteLine("Creating opengl context."); - Debug.Indent(); + get { return context; } + private set { context = value; } + } - IntPtr shareHandle = shareContext != null ? shareContext.windowInfo.Handle : IntPtr.Zero; - Debug.WriteLine(shareHandle == IntPtr.Zero ? "Context is not shared." : - String.Format("Context is shared with context: {0}", shareHandle)); + #endregion - Debug.WriteLine(direct ? "Context is direct." : "Context is indirect."); + #region public DisplayMode Mode - context = Glx.CreateContext(windowInfo.Display, visual, shareHandle, direct); - Debug.Unindent(); - if (context != IntPtr.Zero) + public DisplayMode Mode + { + get { return mode; } + private set { - Debug.WriteLine(String.Format("New opengl context created. (id: {0})", context)); - } - else - { - throw new ApplicationException("Glx.CreateContext call failed (returned 0)."); + if (context == IntPtr.Zero) + { + mode = value; + } + else + { + Debug.Print("Cannot change DisplayMode of an existing context."); + } } } #endregion - #region --- IGLContext Members --- + #region public IWindowInfo Info + + public IWindowInfo Info { get { return windowInfo; } } + + #endregion + + public void CreateContext() + { + this.CreateContext(true, null); + } + + public void CreateContext(bool direct) + { + this.CreateContext(direct, null); + } + + #region public void CreateContext(bool direct, IGLContext shareContext) + + public void CreateContext(bool direct, IGLContext shareContext) + { + try + { + Debug.WriteLine("Creating opengl context."); + Debug.Indent(); + + IntPtr shareHandle = shareContext != null ? (shareContext as X11GLContext).Context: IntPtr.Zero; + + Debug.Write(direct ? "Context is direct, " : "Context is indirect, "); + Debug.WriteLine(shareHandle == IntPtr.Zero ? "not shared." : + String.Format("shared with ({0}).", shareHandle)); + + // Try to call Glx.CreateContext with the specified parameters. + context = Glx.CreateContext(windowInfo.Display, visual, shareHandle, direct); + + // Context creation succeeded, return. + if (context != IntPtr.Zero) + { + Debug.Print("New opengl context created. (id: {0})", context); + return; + } + // Context creation failed. Retry with a non-shared context with the + // direct/indirect rendering mode flipped. + Debug.Print("Cotnext creation failed, retrying with a non-shared, {0} context.", + !direct ? "direct" : "indirect"); + context = Glx.CreateContext(windowInfo.Display, visual, IntPtr.Zero, !direct); + if (context != IntPtr.Zero) + { + Debug.Print("New opengl context created. (id: {0})", context); + return; + } + + throw new ApplicationException("Glx.CreateContext call failed (returned 0)."); + } + finally + { + Debug.Unindent(); + } + } + + #endregion #region public void SwapBuffers() diff --git a/Source/OpenTK/Platform/X11/X11GLControl.cs b/Source/OpenTK/Platform/X11/X11GLControl.cs index 29bb7a97..a51855d6 100644 --- a/Source/OpenTK/Platform/X11/X11GLControl.cs +++ b/Source/OpenTK/Platform/X11/X11GLControl.cs @@ -18,7 +18,7 @@ namespace OpenTK.Platform.X11 WindowInfo info = new WindowInfo(); //DisplayMode mode; private Type xplatui; - X11GLContext glContext; + IGLContext glContext; private bool disposed; private bool fullscreen; @@ -55,10 +55,10 @@ namespace OpenTK.Platform.X11 Debug.Print("Data read from System.Windows.Forms.XplatUIX11: {0}", info.ToString()); //this.mode = mode; - glContext = new X11GLContext(null, info); + glContext = new GLContext(null, info); //glContext.PrepareContext(info); - info.VisualInfo = glContext.VisualInfo; + info.VisualInfo = (glContext.Info as X11.WindowInfo).VisualInfo; Debug.Print("Setting XplatUIX11.CustomVisual"); xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) @@ -83,8 +83,8 @@ namespace OpenTK.Platform.X11 try { - glContext.Handle = info.Handle = (sender as UserControl).Handle; - glContext.CreateContext(null, true); + (glContext.Info as X11.WindowInfo).Handle = info.Handle = (sender as UserControl).Handle; + glContext.CreateContext(true, null); glContext.MakeCurrent(); } catch (ApplicationException expt) @@ -128,7 +128,8 @@ namespace OpenTK.Platform.X11 return Functions.XDefaultColormap(info.Display, info.Screen); } - return API.CreateColormap(info.Display, info.RootWindow, glContext.VisualInfo.visual, 0/*AllocNone*/); + return API.CreateColormap(info.Display, info.RootWindow, + (glContext.Info as X11.WindowInfo).VisualInfo.visual, 0/*AllocNone*/); } #endregion diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index bd55e0f8..e165d1e1 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -257,7 +257,7 @@ namespace OpenTK.Platform.X11 glContext = new X11GLContext(mode, window); //glContext.PrepareContext(window); - window.VisualInfo = glContext.VisualInfo; + window.VisualInfo = (glContext.Info as X11.WindowInfo).VisualInfo; // Create a window on this display using the visual above Debug.Write("Opening render window... "); @@ -303,9 +303,8 @@ namespace OpenTK.Platform.X11 Debug.Print("done! (id: {0})", window.Handle); - glContext.Handle = window.Handle; - glContext.CreateContext(null, true); - + (glContext.Info as X11.WindowInfo).Handle = window.Handle; + glContext.CreateContext(true, null); glContext.MakeCurrent(); API.MapRaised(window.Display, window.Handle);