#region --- License --- /* Licensed under the MIT/X11 license. * Copyright (c) 2006-2008 the OpenTK Team. * This notice may not be removed from any source distribution. * See license.txt for licensing detailed licensing details. */ #endregion using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; using OpenTK.Platform; using OpenTK.Graphics; using System.Diagnostics; namespace OpenTK { /// /// Defines a UserControl with OpenGL rendering capabilities. /// public partial class GLControl : UserControl { IGraphicsContext context; IGLControl implementation; GraphicsMode format; IWindowInfo window_info; int major, minor; GraphicsContextFlags flags; #region --- Constructors --- /// /// Constructs a new GLControl. /// public GLControl() : this(GraphicsMode.Default) { } /// /// Constructs a new GLControl with the specified GraphicsMode. /// /// The OpenTK.Graphics.GraphicsMode of the control. public GLControl(GraphicsMode mode) : this(mode, 1, 0, GraphicsContextFlags.Default) { } /// /// Constructs a new GLControl with the specified GraphicsMode. /// /// The OpenTK.Graphics.GraphicsMode of the control. /// The major version for the OpenGL GraphicsContext. /// The minor version for the OpenGL GraphicsContext. /// The GraphicsContextFlags for the OpenGL GraphicsContext. public GLControl(GraphicsMode mode, int major, int minor, GraphicsContextFlags flags) { SetStyle(ControlStyles.Opaque, true); SetStyle(ControlStyles.UserPaint, true); SetStyle(ControlStyles.AllPaintingInWmPaint, true); DoubleBuffered = false; InitializeComponent(); this.format = mode; this.major = major; this.minor = minor; this.flags = flags; // On Windows, you first need to create the window, then set the pixel format. // On X11, you first need to select the visual, then create the window. // On OSX, the pixel format needs to be selected before the GL context. // Right now, pixel formats/visuals are selected during context creation. In the future, // it would be better to decouple selection from context creation, which will allow us // to clean up this hacky code. The best option is to do this along with multisampling // support. if (DesignMode) implementation = new Platform.Dummy.DummyGLControl(); else implementation = Platform.Factory.Default.CreateGLControl(mode, this); this.CreateControl(); } #endregion #region --- Protected Methods --- /// Raises the HandleCreated event. /// Not used. protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); this.Context = implementation.CreateContext(major, minor, flags); this.window_info = implementation.WindowInfo; this.MakeCurrent(); ((IGraphicsContextInternal)this.Context).LoadAll(); } /// Raises the HandleDestroyed event. /// Not used. protected override void OnHandleDestroyed(EventArgs e) { base.OnHandleDestroyed(e); if (this.Context != null) { this.Context.Dispose(); this.Context = null; } this.window_info.Dispose(); this.window_info = null; } /// /// Raises the System.Windows.Forms.Control.Paint event. /// /// A System.Windows.Forms.PaintEventArgs that contains the event data. protected override void OnPaint(PaintEventArgs e) { if (DesignMode) e.Graphics.Clear(BackColor); base.OnPaint(e); } /// /// Raises the Resize event. /// /// A System.EventArgs that contains the event data. protected override void OnResize(EventArgs e) { if (context != null) context.Update(window_info); base.OnResize(e); } /// /// Raises the ParentChanged event. /// /// A System.EventArgs that contains the event data. protected override void OnParentChanged(EventArgs e) { if (context != null) context.Update(window_info); base.OnParentChanged(e); } #endregion #region --- Public Methods --- #region public void SwapBuffers() /// /// Swaps the front and back buffers, presenting the rendered scene to the screen. /// public void SwapBuffers() { Context.SwapBuffers(); } #endregion #region public void MakeCurrent() /// /// Makes the underlying this GLControl current in the calling thread. /// All OpenGL commands issued are hereafter interpreted by this GLControl. /// public void MakeCurrent() { this.Context.MakeCurrent(this.window_info); } #endregion #region public bool IsIdle /// /// Gets a value indicating whether the current thread contains pending system messages. /// [Browsable(false)] public bool IsIdle { get { return implementation.IsIdle; } } #endregion #region public IGraphicsContext Context /// /// Gets an interface to the underlying GraphicsContext used by this GLControl. /// [Browsable(false)] public IGraphicsContext Context { get { return context; } private set { context = value; } } #endregion #region public float AspectRatio /// /// Gets the aspect ratio of this GLControl. /// [Description("The aspect ratio of the client area 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. /// [Description("Indicates whether GLControl updates are synced to the monitor's refresh.")] public bool VSync { get { if (Context != null) return Context.VSync; return false; } set { if (Context != null) Context.VSync = value; } } #endregion #region public GraphicsMode GraphicsMode /// /// Gets the GraphicsMode of the GraphicsContext attached to this GLControl. /// /// /// To change the GraphicsMode, you must destroy and recreate the GLControl. /// public GraphicsMode GraphicsMode { get { return Context.GraphicsMode; } } #endregion #region public Bitmap GrabScreenshot() /// Grabs a screenshot of the frontbuffer contents. /// A System.Drawing.Bitmap, containing the contents of the frontbuffer. /// /// Occurs when no OpenTK.Graphics.GraphicsContext is current in the calling thread. /// [Obsolete] public Bitmap GrabScreenshot() { throw new NotImplementedException(); //Bitmap bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height); //System.Drawing.Imaging.BitmapData data = // bmp.LockBits(this.ClientRectangle, System.Drawing.Imaging.ImageLockMode.WriteOnly, // System.Drawing.Imaging.PixelFormat.Format24bppRgb); //GL.ReadPixels(0, 0, this.ClientSize.Width, this.ClientSize.Height, PixelFormat.Bgr, PixelType.UnsignedByte, // data.Scan0); //bmp.UnlockBits(data); //bmp.RotateFlip(RotateFlipType.RotateNoneFlipY); //return bmp; } #endregion #endregion } }