diff --git a/Source/OpenTK/Platform/IWindowInfo.cs b/Source/OpenTK/Platform/IWindowInfo.cs index 90d6df36..47d8e552 100644 --- a/Source/OpenTK/Platform/IWindowInfo.cs +++ b/Source/OpenTK/Platform/IWindowInfo.cs @@ -11,11 +11,16 @@ using System.Text; namespace OpenTK.Platform { /// - /// This interface supports OpenTK, and is not intended for use by OpenTK programs. + /// Provides a platform independent mechanism to interact with System.Windows.Forms.Control, + /// System.Windows.Forms.NativeWindow and OpenTK.GameWindow low-level implementation data. /// public interface IWindowInfo { 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/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs index 54b3a633..941722d4 100644 --- a/Source/OpenTK/Platform/Utilities.cs +++ b/Source/OpenTK/Platform/Utilities.cs @@ -82,11 +82,6 @@ namespace OpenTK.Platform private static Platform platform = Platform.Unknown; - public static IWindowInfo GetWindowInfo(Form form) - { - throw new NotImplementedException(); - } - #region public static IntPtr GetAddress(string function) /// diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs index 58af5fbd..5cd46ffb 100644 --- a/Source/OpenTK/Platform/Windows/WinGLContext.cs +++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs @@ -13,16 +13,19 @@ using System.Runtime.InteropServices; using OpenTK.OpenGL; using System.Diagnostics; - namespace OpenTK.Platform.Windows { - public sealed class WinGLContext : OpenTK.Platform.IGLContext, IDisposable + /// + /// Provides methods to create and control an opengl context on the Windows platform. + /// This class supports OpenTK, and is not intended for use by OpenTK programs. + /// + internal sealed class WinGLContext : OpenTK.Platform.IGLContext, IDisposable { private IntPtr deviceContext; private IntPtr renderContext; static private IntPtr opengl32Handle; static private readonly string opengl32Name = "OPENGL32.DLL"; - private IntPtr windowHandle; + private WindowInfo windowInfo = new WindowInfo(); private DisplayMode mode; @@ -30,25 +33,33 @@ namespace OpenTK.Platform.Windows #region --- Contructors --- - public WinGLContext() - : this(new DisplayMode(640, 480, new ColorMode(32), 16, 0, 0, 2, false, false, false, 0.0f)) + internal WinGLContext() + : this(new DisplayMode(640, 480)) { } - public WinGLContext(DisplayMode mode) + internal WinGLContext(DisplayMode mode) { - Trace.WriteLine(String.Format("Creating opengl context (driver: {0})", this.ToString())); + //Trace.WriteLine(String.Format("Creating opengl context (driver: {0})", this.ToString())); + this.mode = mode; + } + + public WinGLContext(DisplayMode mode, IWindowInfo info) + { + this.windowInfo = info as WindowInfo; this.mode = mode; } #endregion - #region public void PrepareContext(IntPtr handle) + #region private void PrepareContext() - public void PrepareContext(IntPtr handle) + private void PrepareContext() { - this.windowHandle = handle; - Debug.WriteLine(String.Format("OpenGL context is bound to handle: {0}", windowHandle)); + if (this.windowInfo.Handle == IntPtr.Zero) + throw new ApplicationException("No Window Handle specified for opengl context."); + + Debug.WriteLine(String.Format("OpenGL context is bound to handle: {0}", this.windowInfo.Handle)); // Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl. if (opengl32Handle == IntPtr.Zero) @@ -68,7 +79,7 @@ namespace OpenTK.Platform.Windows Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle)); } - deviceContext = API.GetDC(windowHandle); + deviceContext = API.GetDC(this.windowInfo.Handle); Debug.WriteLine(String.Format("Device context: {0}", deviceContext)); Debug.Write("Setting pixel format... "); @@ -152,6 +163,8 @@ namespace OpenTK.Platform.Windows public void CreateContext() { + this.PrepareContext(); + Debug.Write("Creating render context... "); // Do not rely on OpenTK.Platform.Windows.Wgl - the context is not ready yet, // and Wgl extensions will fail to load. @@ -302,7 +315,7 @@ namespace OpenTK.Platform.Windows if (deviceContext != IntPtr.Zero) { - if (!API.ReleaseDC(windowHandle, deviceContext)) + if (!API.ReleaseDC(this.windowInfo.Handle, deviceContext)) { //throw new ApplicationException("Could not release device context. Error: " + Marshal.GetLastWin32Error()); //Debug.Print("Could not destroy the device context. Error: {0}", Marshal.GetLastWin32Error()); diff --git a/Source/OpenTK/Platform/Windows/WinGLControl.cs b/Source/OpenTK/Platform/Windows/WinGLControl.cs index 5a17c5bb..73c2c665 100644 --- a/Source/OpenTK/Platform/Windows/WinGLControl.cs +++ b/Source/OpenTK/Platform/Windows/WinGLControl.cs @@ -35,8 +35,6 @@ namespace OpenTK.Platform.Windows c.HandleCreated += new EventHandler(c_HandleCreated); c.HandleDestroyed += new EventHandler(c_HandleDestroyed); - - glContext = new WinGLContext(mode); } #endregion @@ -48,7 +46,10 @@ namespace OpenTK.Platform.Windows try { - glContext.PrepareContext((sender as Control).Handle); + if (glContext != null) + glContext.Dispose(); + + glContext = new WinGLContext(mode, new WindowInfo(sender as Control)); glContext.CreateContext(); glContext.MakeCurrent(); } diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index 3d970fe9..4d379a6d 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -215,6 +215,7 @@ namespace OpenTK.Platform.Windows public IWindowInfo WindowInfo { get { return window; } + private set { window = value as WindowInfo; } } #endregion @@ -287,16 +288,14 @@ namespace OpenTK.Platform.Windows public void OnCreate(EventArgs e) { - window = new WindowInfo(); - window.Handle = this.Handle; - window.Parent = null; + this.WindowInfo = new WindowInfo(this); Debug.Print("Window created: {0}", window); try { - glContext = new WinGLContext(this.mode); - glContext.PrepareContext(this.Handle); + glContext = new WinGLContext(this.mode, this.WindowInfo); + //glContext.PrepareContext(this.Handle); glContext.CreateContext(); //glContext.MakeCurrent(); GL.LoadAll(); diff --git a/Source/OpenTK/Platform/Windows/WindowInfo.cs b/Source/OpenTK/Platform/Windows/WindowInfo.cs index 8ccb435a..895b6941 100644 --- a/Source/OpenTK/Platform/Windows/WindowInfo.cs +++ b/Source/OpenTK/Platform/Windows/WindowInfo.cs @@ -7,18 +7,59 @@ using System; using System.Collections.Generic; using System.Text; +using System.Windows.Forms; namespace OpenTK.Platform.Windows { /// - /// Describes a Windows window. + /// 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 class WindowInfo : IWindowInfo + internal sealed class WindowInfo : IWindowInfo { private IntPtr handle; private WindowInfo parent; + public WindowInfo() + { + } + + public WindowInfo(IWindowInfo info) + { + if (info == null) + throw new ArgumentException("WindowInfo cannot be null."); + + this.Handle = info.Handle; + this.Parent = info.Parent; + } + + public WindowInfo(Control control) + { + if (control == null) + throw new ArgumentException("Control cannot be null."); + + this.Handle = control.Handle; + this.Parent = control.Parent != null ? new WindowInfo(control.Parent) : this.Parent; + } + + public WindowInfo(NativeWindow window) + { + if (window == null) + throw new ArgumentException("NativeWindow cannot be null."); + + this.Handle = window.Handle; + this.Parent = null; + } + + public WindowInfo(GameWindow window) + { + if (window == null) + throw new ArgumentException("GameWindow cannot be null."); + + this.Handle = window.WindowInfo.Handle; + this.Parent = window.WindowInfo.Parent; + } + #region --- IWindowInfo Members --- public IntPtr Handle @@ -30,7 +71,57 @@ namespace OpenTK.Platform.Windows public IWindowInfo Parent { get { return parent; } - internal set { parent = value as WindowInfo; } + internal set + { + parent = value as WindowInfo; + } + } + + public void 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); + } + } + + public void GetInfoFrom(NativeWindow window) + { + if (window == null) + throw new ArgumentException("NativeWindow cannot be null."); + + this.Handle = window.Handle; + this.Parent = null; + } + + public void 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; + } + + public void GetInfoFrom(IWindowInfo info) + { + if (info == null) + throw new ArgumentException("IWindowInfo cannot be null."); + + this.Handle = info.Handle; + this.Parent = info.Parent; } #endregion @@ -40,6 +131,5 @@ namespace OpenTK.Platform.Windows return String.Format("Windows.WindowInfo: Handle {0}, Parent ({1})", this.Handle, this.Parent != null ? this.Parent.ToString() : "null"); } - } } diff --git a/Source/OpenTK/Platform/X11/WindowInfo.cs b/Source/OpenTK/Platform/X11/WindowInfo.cs index b3b7ac73..fb84586d 100644 --- a/Source/OpenTK/Platform/X11/WindowInfo.cs +++ b/Source/OpenTK/Platform/X11/WindowInfo.cs @@ -7,44 +7,99 @@ using System; using System.Collections.Generic; using System.Text; +using System.Windows.Forms; namespace OpenTK.Platform.X11 { /// - /// Describes an X11 window. + /// 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. /// - public class WindowInfo : IWindowInfo + internal sealed class WindowInfo : IWindowInfo { - public WindowInfo() - { - visinfo = new XVisualInfo(); - } - - public WindowInfo(WindowInfo parent) - { - this.Handle = parent.Handle; - this.TopLevelWindow = parent.TopLevelWindow; - this.Screen = parent.Screen; - this.Display = parent.Display; - this.RootWindow = parent.RootWindow; - this.VisualInfo = parent.VisualInfo; - this.Parent = parent; - } - private IntPtr rootWindow, handle, topLevelWindow, display; private int screen; private WindowInfo parent; private XVisualInfo visinfo; - public IntPtr RootWindow { get { return rootWindow; } set { rootWindow = value; } } - public IntPtr TopLevelWindow { get { return topLevelWindow; } set { topLevelWindow = value; } } - public IntPtr Display { get { return display; } set { display = value; } } - public int Screen { get { return screen; } set { screen = value; } } - public XVisualInfo VisualInfo { get { return visinfo; } set { visinfo = value; } } + public WindowInfo() + { + visinfo = new XVisualInfo(); + } - public IntPtr Handle { get { return handle; } set { handle = value; } } - public IWindowInfo Parent { get { return parent; } set { parent = value as WindowInfo; } } + public WindowInfo(Control control) + { + throw new NotImplementedException(); + } + + public WindowInfo(NativeWindow window) + { + throw new NotImplementedException(); + } + + public WindowInfo(GameWindow window) + { + throw new NotImplementedException(); + } + + public WindowInfo(WindowInfo info) + { + this.GetInfoFrom(info); + } + + #region --- IWindowInfo Members --- + + public void GetInfoFrom(Control control) + { + if (control == null) + throw new ArgumentException("GameWindow cannot be null."); + + throw new NotImplementedException(); + } + + public void GetInfoFrom(NativeWindow window) + { + if (window == null) + throw new ArgumentException("GameWindow cannot be null."); + + throw new NotImplementedException(); + } + + public void GetInfoFrom(GameWindow window) + { + if (window == null) + throw new ArgumentException("GameWindow cannot be null."); + + this.GetInfoFrom(window.WindowInfo as X11.WindowInfo); + } + + public void GetInfoFrom(IWindowInfo info) + { + if (info == null) + throw new ArgumentException("WindowInfo cannot be null"); + + WindowInfo winfo = info as WindowInfo; + + this.Handle = info.Handle; + this.Parent = info.Parent; + + this.RootWindow = winfo.RootWindow; + this.TopLevelWindow = winfo.TopLevelWindow; + this.Display = winfo.Display; + this.Screen = winfo.Screen; + 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; } } + public IntPtr TopLevelWindow { get { return topLevelWindow; } internal set { topLevelWindow = value; } } + public IntPtr Display { get { return display; } internal set { display = value; } } + public int Screen { get { return screen; } internal set { screen = value; } } + public XVisualInfo VisualInfo { get { return visinfo; } internal set { visinfo = value; } } public override string ToString() { diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index ee5cb3cb..7220fb2e 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -15,29 +15,55 @@ using OpenTK.OpenGL; namespace OpenTK.Platform.X11 { /// - /// Provides methods to create and control an opengl context on X11. + /// Provides methods to create and control an opengl context on the X11 platform. + /// This class supports OpenTK, and is not intended for use by OpenTK programs. /// - public sealed class X11GLContext : OpenTK.Platform.IGLContext + internal sealed class X11GLContext : OpenTK.Platform.IGLContext { private IntPtr context; private DisplayMode mode; - internal WindowInfo windowInfo; - - internal IntPtr visual; + private WindowInfo windowInfo; + private IntPtr visual; private bool disposed; - #region --- Public Constructor --- + #region --- Constructors --- - internal X11GLContext() - : this(new DisplayMode()) + internal X11GLContext() : this(new DisplayMode(), new WindowInfo()) { } - internal X11GLContext(DisplayMode mode) + internal X11GLContext(DisplayMode mode) : this(mode, new WindowInfo()) { - this.windowInfo = new WindowInfo(); + } + + internal X11GLContext(DisplayMode mode, IWindowInfo info) + { + if (info == null) + throw new ArgumentException("IWindowInfo cannot be null."); + + this.windowInfo = info as WindowInfo; this.mode = mode; + this.ChooseContext(); + } + + #endregion + + #region internal XVisualInfo VisualInfo + + internal XVisualInfo VisualInfo + { + get { return windowInfo.VisualInfo; } + } + + #endregion + + #region internal IntPtr Handle + + internal IntPtr Handle + { + get { return windowInfo.Handle; } + set { windowInfo.Handle = value; } } #endregion @@ -62,12 +88,10 @@ namespace OpenTK.Platform.X11 #endregion - #region internal void PrepareContext(X11.WindowInfo info) + #region private void PrepareContext() - internal void PrepareContext(X11.WindowInfo info) + private void ChooseContext() { - this.windowInfo = new WindowInfo(info); - List visualAttributes = new List(); if (mode == null) diff --git a/Source/OpenTK/Platform/X11/X11GLControl.cs b/Source/OpenTK/Platform/X11/X11GLControl.cs index d2f8ff8d..29bb7a97 100644 --- a/Source/OpenTK/Platform/X11/X11GLControl.cs +++ b/Source/OpenTK/Platform/X11/X11GLControl.cs @@ -25,6 +25,8 @@ namespace OpenTK.Platform.X11 #region --- Contructors --- + #region public X11GLControl(UserControl c) + public X11GLControl(UserControl c) { Debug.WriteLine("Creating opengl control (X11GLControl driver)"); @@ -37,44 +39,42 @@ namespace OpenTK.Platform.X11 throw new ArgumentException("UserControl c may not be null."); } - //this.mode = mode; - glContext = new X11GLContext(null); - c.HandleCreated += new EventHandler(c_HandleCreated); c.HandleDestroyed += new EventHandler(c_HandleDestroyed); xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); - Debug.Write("System.Windows.Forms.XplatUIX11: "); + if (xplatui == null) + throw new ApplicationException("Could not get System.Windows.Forms.XplatUIX11 through reflection. Unsupported platform or Mono runtime version, aborting."); + + info.Display = (IntPtr)xplatui.GetField("DisplayHandle", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + info.RootWindow = (IntPtr)xplatui.GetField("RootWindow", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + info.Screen = (int)xplatui.GetField("ScreenNo", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + Debug.Print("Data read from System.Windows.Forms.XplatUIX11: {0}", info.ToString()); - if (xplatui != null) - { - info.Display = (IntPtr)xplatui.GetField("DisplayHandle", - System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + //this.mode = mode; + glContext = new X11GLContext(null, info); + //glContext.PrepareContext(info); + + info.VisualInfo = glContext.VisualInfo; - info.RootWindow = (IntPtr)xplatui.GetField("RootWindow", - System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + Debug.Print("Setting XplatUIX11.CustomVisual"); + xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + .SetValue(null, info.VisualInfo.visual); - info.Screen = (int)xplatui.GetField("ScreenNo", - System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); - - Debug.Print("Display: {0}, Screen: {1}, Root Window: {2}, GLControl: {3}", - info.Display, info.Screen, info.RootWindow, info.Handle); - - glContext.PrepareContext(info); - info.VisualInfo = glContext.windowInfo.VisualInfo; - - Debug.Print("Setting XplatUIX11.CustomVisual"); - xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) - .SetValue(null, info.VisualInfo.visual); - - Debug.Print("Setting XplatUIX11.CustomColormap"); - xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) - .SetValue(null, API.CreateColormap(info.Display, info.RootWindow, info.VisualInfo.visual, 0)); - } + Debug.Print("Setting XplatUIX11.CustomColormap"); + xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + .SetValue(null, API.CreateColormap(info.Display, info.RootWindow, info.VisualInfo.visual, 0)); Debug.Unindent(); } + #endregion + + #region void c_HandleCreated(object sender, EventArgs e) + void c_HandleCreated(object sender, EventArgs e) { UserControl c = (sender as UserControl); @@ -83,7 +83,7 @@ namespace OpenTK.Platform.X11 try { - glContext.windowInfo.Handle = info.Handle = (sender as UserControl).Handle; + glContext.Handle = info.Handle = (sender as UserControl).Handle; glContext.CreateContext(null, true); glContext.MakeCurrent(); } @@ -98,12 +98,18 @@ namespace OpenTK.Platform.X11 } } + #endregion + + #region void c_HandleDestroyed(object sender, EventArgs e) + void c_HandleDestroyed(object sender, EventArgs e) { Debug.Print("X11GLControl handle destroyed, disposing X11GLContext."); glContext.Dispose(); } + #endregion + #region private IntPtr FindColormap() /// @@ -122,7 +128,7 @@ namespace OpenTK.Platform.X11 return Functions.XDefaultColormap(info.Display, info.Screen); } - return API.CreateColormap(info.Display, info.RootWindow, glContext.windowInfo.VisualInfo.visual, 0/*AllocNone*/); + return API.CreateColormap(info.Display, info.RootWindow, glContext.VisualInfo.visual, 0/*AllocNone*/); } #endregion diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index 1fbe1290..bd55e0f8 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -255,9 +255,9 @@ namespace OpenTK.Platform.X11 Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen, window.RootWindow); - glContext = new X11GLContext(mode); - glContext.PrepareContext(window); - window.VisualInfo = glContext.windowInfo.VisualInfo; + glContext = new X11GLContext(mode, window); + //glContext.PrepareContext(window); + window.VisualInfo = glContext.VisualInfo; // Create a window on this display using the visual above Debug.Write("Opening render window... "); @@ -303,7 +303,7 @@ namespace OpenTK.Platform.X11 Debug.Print("done! (id: {0})", window.Handle); - glContext.windowInfo.Handle = window.Handle; + glContext.Handle = window.Handle; glContext.CreateContext(null, true); glContext.MakeCurrent();