#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.Text; using OpenTK.Platform; namespace OpenTK.Graphics { /// /// Represents and provides methods to manipulate an OpenGL render context. /// public sealed class GraphicsContext : IGraphicsContext, IGLContextInternal, IGLContextCreationHack { IGraphicsContext implementation; // The actual render context implementation for the underlying platform. List dispose_queue = new List(); bool disposed; static bool share_contexts = true; static object context_lock = new object(); static Dictionary available_contexts = new Dictionary(); // Contains all available OpenGL contexts. #region public GraphicsContext(DisplayMode mode, IWindowInfo window) /// /// Constructs a new GraphicsContext with the specified DisplayMode, and bound to the specified IWindowInfo. /// /// /// public GraphicsContext(DisplayMode mode, IWindowInfo window) : this(mode.ToGraphicsFormat(), window) { } public GraphicsContext(GraphicsFormat format, IWindowInfo window) { //if (available_contexts.Count == 0) // available_contexts.Add(IntPtr.Zero, new WeakReference(null)); IGraphicsContext share = null; if (GraphicsContext.ShareContexts) { lock (context_lock) { // A small hack to create a shared context with the first available context. foreach (WeakReference r in GraphicsContext.available_contexts.Values) { share = (IGraphicsContext)r.Target; break; } } } if (Configuration.RunningOnWindows) implementation = new OpenTK.Platform.Windows.WinGLContext(format, window, share); else if (Configuration.RunningOnX11) implementation = new OpenTK.Platform.X11.X11GLContext(); else throw new PlatformNotSupportedException("Your platform is not supported currently. Please, refer to http://www.opentk.com for more information."); } #endregion #region void ContextDestroyed(IGraphicsContext context, EventArgs e) /// /// Handles the Destroy event. /// /// The OpenTK.Platform.IGraphicsContext that was destroyed. /// Not used. void ContextDestroyed(IGraphicsContext context, EventArgs e) { this.Destroy -= ContextDestroyed; available_contexts.Remove(((IGLContextInternal)this).Context); } #endregion #region --- Public Members --- #region public static IGraphicsContext CurrentContext internal delegate ContextHandle GetCurrentContextDelegate(); internal static GetCurrentContextDelegate GetCurrentContext; /// /// Gets or sets the current GraphicsContext in the calling thread. /// public static GraphicsContext CurrentContext { get { if (available_contexts.Count > 0) return (GraphicsContext)available_contexts[GetCurrentContext()].Target; //return (GraphicsContext)available_contexts[((IGLContextInternal)available_contexts[IntPtr.Zero].Target).GetCurrentContext()].Target; return null; //return (GraphicsContext)available_contexts[StaticGetCurrentContext().ToInt64()].Target; } set { if (value != null) value.MakeCurrent(); else if (CurrentContext != null) CurrentContext.IsCurrent = false; } } #endregion #region public static bool ShareContexts /// Gets or sets a System.Boolean, indicating whether GLContexts are shared /// /// If ShareContexts is true, new GLContexts will share resources. If this value is /// false, new GLContexts will not share resources. /// Changing this value will not affect already created GLContexts. /// public static bool ShareContexts { get { return share_contexts; } set { share_contexts = value; } } #endregion #region public static AvailableDisplayFormats #endregion #endregion #region --- IGraphicsContext Members --- /// /// Creates an OpenGL context. /// public void CreateContext() { CreateContext(true, null); } /// /// 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). /// /// public void CreateContext(bool direct) { CreateContext(direct, null); } /// /// Creates an OpenGL context with the specified direct/indirect rendering mode and sharing state with the /// specified IGraphicsContext. /// /// Set to true for direct rendering or false otherwise. /// The source IGraphicsContext to share state from.. /// public void CreateContext(bool direct, IGraphicsContext source) { implementation.CreateContext(direct, source); this.Destroy += ContextDestroyed; available_contexts.Add((this as IGLContextInternal).Context, new WeakReference(this)); //OpenTK.Graphics.OpenGL.GL.Clear(OpenTK.Graphics.OpenGL.ClearBufferMask.ColorBufferBit); //if (StaticGetCurrentContext == null) // StaticGetCurrentContext = implementation.GetCurrentContext; } /// /// Swaps buffers on a context. This presents the rendered scene to the user. /// public void SwapBuffers() { implementation.SwapBuffers(); } /// /// Makes this context the current rendering target. /// public void MakeCurrent() { implementation.MakeCurrent(); } /// /// Gets a System.Boolean indicating whether this Context is current in the calling thread. /// public bool IsCurrent { get { return implementation.IsCurrent; } set { implementation.IsCurrent = value; } } /// /// Raised when a Context is destroyed. /// public event DestroyEvent Destroy { add { implementation.Destroy += value; } remove { implementation.Destroy -= value; } } /// /// Gets or sets a value indicating whether VSync is enabled. /// public bool VSync { get { return implementation.VSync; } set { implementation.VSync = value; } } #endregion #region --- IGLContextInternal Members --- /// /// Gets a handle to the OpenGL rendering context. /// ContextHandle IGLContextInternal.Context { get { return ((IGLContextInternal)implementation).Context; } } /// /// Gets the IWindowInfo describing the window associated with this context. /// IWindowInfo IGLContextInternal.Info { get { return (implementation as IGLContextInternal).Info; } //internal set { (implementation as IGLContextInternal).Info = value; } } /// /// Gets the DisplayMode of the context. /// GraphicsFormat IGLContextInternal.GraphicsFormat { get { return (implementation as IGLContextInternal).GraphicsFormat; } } ///// ///// Gets a System.IntPtr containing the handle to the OpenGL context which is current in the ///// calling thread, or IntPtr.Zero if no OpenGL context is current. ///// ///// A System.IntPtr that holds the handle to the current OpenGL context. //ContextHandle IGLContextInternal.GetCurrentContext() //{ // return (implementation as IGLContextInternal).GetCurrentContext(); //} /// /// Registers an OpenGL resource for disposal. /// /// The OpenGL resource to dispose. void IGLContextInternal.RegisterForDisposal(IDisposable resource) { GC.KeepAlive(resource); dispose_queue.Add(resource); } /// /// Disposes all registered OpenGL resources. /// void IGLContextInternal.DisposeResources() { foreach (IDisposable resource in dispose_queue) resource.Dispose(); dispose_queue.Clear(); } /// /// Returns the display modes supported by the current opengl context. /// /// An IEnumerable containing all supported display modes. IEnumerable IGLContextInternal.GetDisplayModes() { return (implementation as IGLContextInternal).GetDisplayModes(); } /// /// Gets the address of an OpenGL extension function. /// /// The name of the OpenGL function (e.g. "glGetString") /// /// A pointer to the specified function or IntPtr.Zero if the function isn't /// available in the current opengl context. /// /// IntPtr IGLContextInternal.GetAddress(string function) { return (implementation as IGLContextInternal).GetAddress(function); } #endregion #region --- IGLContextCreationHack Members --- bool IGLContextCreationHack.SelectDisplayMode(DisplayMode mode, IWindowInfo info) { return (implementation as IGLContextCreationHack).SelectDisplayMode(mode, info); } void IGLContextCreationHack.SetWindowHandle(IntPtr handle) { (implementation as IGLContextCreationHack).SetWindowHandle(handle); } #endregion #region --- IDisposable Members --- /// /// Disposes of the GraphicsContext. /// public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } void Dispose(bool manual) { if (!disposed) { // TODO: Check if this is safe //if (manual) if (implementation != null) implementation.Dispose(); disposed = true; } } ~GraphicsContext() { this.Dispose(false); } #endregion } /// Represents errors related to Graphics operations. public class GraphicsException : Exception { public GraphicsException() : base() { } public GraphicsException(string message) : base(message) { } } }