diff --git a/Source/OpenTK/GLControl.Designer.cs b/Source/OpenTK/GLControl.Designer.cs index 8ef3fc05..8a009a78 100644 --- a/Source/OpenTK/GLControl.Designer.cs +++ b/Source/OpenTK/GLControl.Designer.cs @@ -1,6 +1,4 @@ -using System; - -namespace OpenTK +namespace OpenTK { partial class GLControl { @@ -32,12 +30,12 @@ namespace OpenTK { this.SuspendLayout(); // - // GLControl + // NewGLControl // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.BackColor = System.Drawing.Color.Black; - this.Name = "GLControl"; + this.Name = "NewGLControl"; this.ResumeLayout(false); } diff --git a/Source/OpenTK/GLControl.cs b/Source/OpenTK/GLControl.cs index 3869c4dc..7379ff6d 100644 --- a/Source/OpenTK/GLControl.cs +++ b/Source/OpenTK/GLControl.cs @@ -4,115 +4,140 @@ */ #endregion -#region --- Using Directives --- - using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; +using System.Data; using System.Text; using System.Windows.Forms; -using System.Diagnostics; using OpenTK.Platform; -using OpenTK.OpenGL; - -#endregion namespace OpenTK { - // TODO: Document the GLControl class. - /// - /// Defines a UserControl with opengl rendering capabilities. + /// Defines a UserControl with OpenGL rendering capabilities. /// - public partial class GLControl : UserControl, IGLControl + public partial class GLControl : UserControl { - #region --- Private Fields --- + IGLContext context; + IPlatformIdle idle; - private IGLControl glControl; + #region --- Constructor --- - #endregion - - #region --- Contructors --- - - /// - /// Constructs a new GLControl. - /// public GLControl() - :this(new DisplayMode()) - { - } - - /// - /// Constructs a new GLControl, with the specified DisplayMode. - /// - /// The DisplayMode of the control. - public GLControl(DisplayMode mode) { InitializeComponent(); - this.Visible = false; - this.Fullscreen = mode.Fullscreen; - this.SetStyle(ControlStyles.UserPaint, true); this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); - //this.SetStyle(ControlStyles.OptimizedDoubleBuffer, true); } #endregion + #region --- Context Setup --- + + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + + // For maximum compatibility we do not set a specific depth for the DisplayMode. + // The driver is free to find the best match. + WindowInfo info = new WindowInfo(this); + if (!this.DesignMode) + { + context = new GLContext(new DisplayMode(), info); + context.CreateContext(); + idle = new PlatformIdle(info); + } + else + { + context = new DummyGLContext(); + idle = new DummyPlatformIdle(); + } + } + + protected override void OnHandleDestroyed(EventArgs e) + { + base.OnHandleDestroyed(e); + + context.Dispose(); + } + + #endregion + + #region --- Public Properties --- + + #region public bool IsIdle + + /// + /// Gets a value indicating whether the current thread contains pending system messages. + /// + public bool IsIdle + { + get { return idle.IsIdle; } + } + + #endregion + + #region public IGLContext Context + + /// + /// Gets an interface to the underlying GLContext used by this GLControl. + /// + public IGLContext Context + { + get { return context; } + } + + #endregion + + #region public float AspectRatio + + /// + /// Gets the aspect ratio of this GLControl. + /// + public float AspectRatio + { + get + { + return this.ClientSize.Width / (float)this.ClientSize.Height; + } + } + + #endregion + + #region public bool VSync + + /// + /// Gets or sets a value indicating whether vsync is active for this GLControl. + /// + public bool VSync + { + get + { + if (Context != null) + return Context.VSync; + return false; + } + set + { + if (Context != null) + Context.VSync = value; + } + } + + #endregion + + #endregion + #region --- Public Methods --- - #region public void CreateContext() - - /// - /// Forces the creation of the opengl rendering context. - /// - public void CreateContext() - { - if (glControl != null) - { - throw new ApplicationException("Attempted to create GLControl more than once."); - } - - if (this.DesignMode) - { - glControl = new DummyGLControl(); - } - else - { - switch (Environment.OSVersion.Platform) - { - case PlatformID.Win32NT: - case PlatformID.Win32Windows: - glControl = new OpenTK.Platform.Windows.WinGLControl(this, new DisplayMode(Width, Height)); - break; - - case PlatformID.Unix: - case (PlatformID)128: // some older versions of Mono reported 128. - glControl = new OpenTK.Platform.X11.X11GLControl(this); - break; - - default: - throw new PlatformNotSupportedException("Your operating system is not currently supported. We are sorry for the inconvenience."); - } - } - - this.Visible = true; - this.CreateControl(); - - GL.LoadAll(); - Glu.LoadAll(); - this.OnResize(EventArgs.Empty); - } - - #endregion - #region public void SwapBuffers() /// - /// Swaps the front and back buffers, and presents the rendered scene to the screen. + /// Swaps the front and back buffers, presenting the rendered scene to the screen. /// public void SwapBuffers() { @@ -124,8 +149,8 @@ namespace OpenTK #region public void MakeCurrent() /// - /// Makes the underlying GLContext of this GLControl current. All OpenGL commands issued - /// from this point are interpreted by this GLContext. + /// Makes the underlying this GLControl current in the calling thread. + /// All OpenGL commands issued are hereafter interpreted by this GLControl. /// public void MakeCurrent() { @@ -135,147 +160,114 @@ namespace OpenTK #endregion #endregion + } - #region --- Public Properties --- + #region internal interface IPlatformIdle - /// - /// Gets the AspectRatio of the control this GLContext object - /// renders to. This is usually used in a call to Glu.Perspective. - /// - public double AspectRatio + internal interface IPlatformIdle + { + bool IsIdle { get; } + } + + internal class WinPlatformIdle : IPlatformIdle + { + OpenTK.Platform.Windows.MSG msg = new OpenTK.Platform.Windows.MSG(); + object get_lock = new object(); + IntPtr handle; + + public WinPlatformIdle(IWindowInfo info) { - get - { - return this.Width / (double)this.Height; - } + handle = info.Handle; } - /// - /// Gets or sets the display mode of the control. - /// - public bool Fullscreen + #region IPlatformIdle Members + + public bool IsIdle { - get + get { - return false; - //throw new NotImplementedException(); - } - set - { - //throw new NotImplementedException(); + lock (get_lock) + { + return !OpenTK.Platform.Windows.Functions.PeekMessage(ref msg, IntPtr.Zero, 0, 0, 0); + } } } #endregion + } - #region --- IGLControl Members --- + internal class X11PlatformIdle : IPlatformIdle + { + object get_lock = new object(); + IntPtr display; - #region public bool IsIdle + public X11PlatformIdle(IWindowInfo info) + { + display = (info as OpenTK.Platform.X11.WindowInfo).Display; + } + + #region IPlatformIdle Members - /// - /// Gets the idle status of the control. - /// public bool IsIdle { get { - if (glControl == null) - this.CreateContext(); - - return glControl.IsIdle; + lock (get_lock) + { + return OpenTK.Platform.X11.Functions.XPending(display) == 0; + } } } #endregion - - #region public IGLContext Context - - /// - /// Gets the opengl context associated with this control. - /// - public IGLContext Context - { - get - { - if (glControl == null) - this.CreateContext(); - - return glControl.Context; - } - } - - #endregion - - #region DisplayMode changes - - /// - /// Selects the fullscreen DisplayMode closest to the DisplayMode requested. - /// - /// - /// The fullscreen DisplayMode to match, or null to get the current screen DisplayMode. - /// - /// The DisplayMode closest to the requested one, or null if no DisplayModes are available. - /// - /// SetDisplayMode - /// - public DisplayMode SelectDisplayMode(DisplayMode mode) - { - throw new NotImplementedException(); - //return glWindow.SelectDisplayMode(mode); - } - - /// - /// Selects the fullscreen DisplayMode closest to the DisplayMode requested, accoriding to the specified - /// parameters. - /// - /// - /// The fullscreen DisplayMode to match, or null to get the current screen DisplayMode. - /// - /// - /// The DisplayModeMatchOptions flags that indicate how to search for the requested DisplayMode. - /// - /// - /// The DisplayMode closest to the requested one, or null if no DisplayModes are available or - /// DisplayModeMatchOptions.ExactMatch was passed. - /// - /// - /// SetDisplayMode - /// - public DisplayMode SelectDisplayMode(DisplayMode mode, DisplayModeMatchOptions options) - { - throw new NotImplementedException(); - //return glWindow.SelectDisplayMode(mode, options); - } - - /// - /// Sets the requested DisplayMode. - /// - /// - /// The fulscreen DisplayMode to set. Passing null will return the application to windowed - /// mode. - /// - /// - /// Use SelectDisplayMode to select one of the available fullscreen modes. - /// - /// If the mode requested is not available, this function will throw a - /// DisplayModeNotAvailable exception. - /// - /// - /// Pass null to return to windowed mode. The previous desktop DisplayMode will be automatically reset by this - /// function. This function cannot be used to permanently change the user's desktop DisplayMode. - /// - /// SelectDisplayMode - /// DisplayModeNotAvailable exception - /// - public void SetDisplayMode(DisplayMode mode) - { - throw new NotImplementedException(); - //glWindow.SetDisplayMode(mode); - } - - #endregion - - #endregion - } + + internal class PlatformIdle : IPlatformIdle + { + IPlatformIdle implementation; + + public PlatformIdle(IWindowInfo info) + { + switch (System.Environment.OSVersion.Platform) + { + case PlatformID.Unix: + case (PlatformID)128: + implementation = new X11PlatformIdle(info); + break; + + case PlatformID.Win32NT: + case PlatformID.Win32S: + case PlatformID.Win32Windows: + case PlatformID.WinCE: + implementation = new WinPlatformIdle(info); + break; + + default: + throw new PlatformNotSupportedException(); + } + } + + #region IPlatformIdle Members + + public bool IsIdle + { + get { return implementation.IsIdle; } + } + + #endregion + } + + internal class DummyPlatformIdle : IPlatformIdle + { + #region IPlatformIdle Members + + public bool IsIdle + { + get { return false; } + } + + #endregion + } + + #endregion } diff --git a/Source/OpenTK/Platform/DummyGLControl.cs b/Source/OpenTK/Platform/DummyGLControl.cs deleted file mode 100644 index c0476de6..00000000 --- a/Source/OpenTK/Platform/DummyGLControl.cs +++ /dev/null @@ -1,53 +0,0 @@ -#region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Text; - -namespace OpenTK.Platform -{ - /// - /// An IGLControl implementation to be used inside the Visual Studio designer. - /// - internal sealed class DummyGLControl : IGLControl - { - bool fullscreen; - IGLContext glContext = new DummyGLContext(); - - #region --- IGLControl Members --- - - public bool IsIdle - { - get - { - return false; - } - } - - public bool Fullscreen - { - get - { - return fullscreen; - } - set - { - fullscreen = value; - } - } - - public IGLContext Context - { - get - { - return glContext; - } - } - - #endregion - } -} diff --git a/Source/OpenTK/Platform/IGLControl.cs b/Source/OpenTK/Platform/IGLControl.cs deleted file mode 100644 index d5461e7c..00000000 --- a/Source/OpenTK/Platform/IGLControl.cs +++ /dev/null @@ -1,21 +0,0 @@ -#region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Text; - -using OpenTK.OpenGL; - -namespace OpenTK.Platform -{ - public interface IGLControl - { - bool IsIdle { get; } - bool Fullscreen { get; set; } - IGLContext Context { get; } - } -} diff --git a/Source/OpenTK/Platform/Windows/WinGLControl.cs b/Source/OpenTK/Platform/Windows/WinGLControl.cs deleted file mode 100644 index 8d8620d6..00000000 --- a/Source/OpenTK/Platform/Windows/WinGLControl.cs +++ /dev/null @@ -1,144 +0,0 @@ -#region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * Contributions from Erik Ylvisaker - * See license.txt for license info - */ -#endregion - -#region --- Using directives --- - -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows.Forms; -using System.Diagnostics; - -#endregion - -namespace OpenTK.Platform.Windows -{ - sealed class WinGLControl : IGLControl, IDisposable - { - private WinGLContext glContext; - private bool fullscreen; - private ResizeEventArgs resizeEventArgs = new ResizeEventArgs(); - private DisplayMode mode; - - private bool disposed; - private MSG msg; // Used only by the IsIdle event. - - #region --- Constructors --- - - public WinGLControl(UserControl c, DisplayMode mode) - { - this.mode = mode; - - c.HandleCreated += new EventHandler(c_HandleCreated); - c.HandleDestroyed += new EventHandler(c_HandleDestroyed); - } - - #endregion - - void c_HandleCreated(object sender, EventArgs e) - { - Debug.Print("GLControl handle created, creating WinGLContext."); - Debug.Indent(); - - try - { - if (glContext != null) - glContext.Dispose(); - - glContext = new WinGLContext(mode, new WindowInfo(sender as Control)); - glContext.CreateContext(); - glContext.MakeCurrent(); - } - catch (ApplicationException expt) - { - Debug.Print(expt.ToString()); - throw; - } - finally - { - Debug.Unindent(); - } - } - - void c_HandleDestroyed(object sender, EventArgs e) - { - glContext.Dispose(); - } - - #region --- IGLControl members --- - - #region public bool IsIdle - - public bool IsIdle - { - get - { - return !Functions.PeekMessage(ref msg, IntPtr.Zero, 0, 0, 0); - } - } - - #endregion - - #region public bool Fullscreen - - public bool Fullscreen - { - get - { - return fullscreen; - } - set - { - fullscreen = false; - //throw new NotImplementedException(); - } - } - - #endregion - - #region public IGLContext Context - - public IGLContext Context - { - get { return glContext; } - } - - #endregion - - #endregion - - #region --- IDisposable Members --- - - public void Dispose() - { - this.Dispose(true); - //GC.SuppressFinalize(this); - } - - private void Dispose(bool calledManually) - { - if (!disposed) - { - // Clean unmanaged resources here: - - if (calledManually) - { - // Safe to clean managed resources - glContext.Dispose(); - } - disposed = true; - } - } - /* - ~WinGLControl() - { - Dispose(false); - } - */ - #endregion - } -} diff --git a/Source/OpenTK/Platform/X11/X11GLControl.cs b/Source/OpenTK/Platform/X11/X11GLControl.cs deleted file mode 100644 index a51855d6..00000000 --- a/Source/OpenTK/Platform/X11/X11GLControl.cs +++ /dev/null @@ -1,223 +0,0 @@ -#region --- License --- -/* Copyright (c) 2007 Stefanos Apostolopoulos - * See license.txt for license info - */ -#endregion - -using System; -using System.Collections.Generic; -using System.Text; -using System.Windows.Forms; -using System.Drawing; -using System.Diagnostics; - -namespace OpenTK.Platform.X11 -{ - sealed class X11GLControl : IGLControl - { - WindowInfo info = new WindowInfo(); - //DisplayMode mode; - private Type xplatui; - IGLContext glContext; - - private bool disposed; - private bool fullscreen; - - #region --- Contructors --- - - #region public X11GLControl(UserControl c) - - public X11GLControl(UserControl c) - { - Debug.WriteLine("Creating opengl control (X11GLControl driver)"); - Debug.Indent(); - - Utilities.ThrowOnX11Error = true; - - if (c == null/* || c.TopLevelControl == null*/) - { - throw new ArgumentException("UserControl c may not be null."); - } - - c.HandleCreated += new EventHandler(c_HandleCreated); - c.HandleDestroyed += new EventHandler(c_HandleDestroyed); - - xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); - 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()); - - //this.mode = mode; - glContext = new GLContext(null, info); - //glContext.PrepareContext(info); - - info.VisualInfo = (glContext.Info as X11.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.Unindent(); - } - - #endregion - - #region void c_HandleCreated(object sender, EventArgs e) - - void c_HandleCreated(object sender, EventArgs e) - { - UserControl c = (sender as UserControl); - Debug.Print("GLControl handle created, creating X11GLContext."); - Debug.Indent(); - - try - { - (glContext.Info as X11.WindowInfo).Handle = info.Handle = (sender as UserControl).Handle; - glContext.CreateContext(true, null); - glContext.MakeCurrent(); - } - catch (ApplicationException expt) - { - Debug.Print(expt.ToString()); - throw; - } - finally - { - Debug.Unindent(); - } - } - - #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() - - /// - /// Finds a colormap suitable for use with the GLControl. - /// - /// A pointer to the colormap - /// - /// If the visual of the GLControl matches the default visual, the function returns - /// the default colormap (i.e. the colormap of the root window). Otherwise, it creates - /// a new, private colormap. - /// - private IntPtr FindColormap() - { - if (info.VisualInfo.visual == Functions.XDefaultVisual(info.Display, info.Screen)) - { - return Functions.XDefaultColormap(info.Display, info.Screen); - } - - return API.CreateColormap(info.Display, info.RootWindow, - (glContext.Info as X11.WindowInfo).VisualInfo.visual, 0/*AllocNone*/); - } - - #endregion - - #endregion - - #region --- IGLControl Members --- - - public event CreateEvent Create; - - private void OnCreate(object sender, EventArgs e) - { - if (this.Create != null) - this.Create(sender, e); - } - - #region public bool IsIdle - - public bool IsIdle - { - get - { - return API.Pending(info.Display) == 0; - } - } - - #endregion - - #region public bool Fullscreen - - public bool Fullscreen - { - get - { - return fullscreen; - } - set - { - //throw new Exception("The method or operation is not implemented."); - fullscreen = false; - } - } - - #endregion - - #region public IGLContext Context - - public IGLContext Context - { - get - { - return glContext; - } - } - - #endregion - - #endregion - - #region --- IDisposable Members --- - - public void Dispose() - { - this.Dispose(true); - GC.SuppressFinalize(this); - } - - private void Dispose(bool manuallyCalled) - { - if (!disposed) - { - // Clean unmanaged resources: - // Nothing - - if (manuallyCalled) - { - // Clean managed resources, too - glContext.Dispose(); - } - } - disposed = true; - } - - ~X11GLControl() - { - this.Dispose(false); - } - - #endregion - } -}