From 223c74264816afc4b1fe7b9d99b5d7d1c16a484a Mon Sep 17 00:00:00 2001 From: the_fiddler Date: Mon, 3 Mar 2008 12:44:56 +0000 Subject: [PATCH] Renamed ColorDepth to ColorFormat, to avoid class with System.Drawing.ColorDepth. Update X11 stack to use System.Windows.Forms.XPlatUI for its Display, Screen and RootWindow. Fixed mode setting for X11GLControl. Fixed X11 shutdown (was generating X11 errors). Added DeviceContext getter to WinWindowInfo. Made IWindowInfo disposable. Added documentation to many public methods. Worked around a Mono 1.2.4 bug with Handle creation on Windows.Forms.Control. Updated GL.BuildExtensionList to correctly parse GL_VERSION when in indirect rendering mode. Fixed crash errors in X11GLContext.CreateContext and X11GraphicsMode. Added a ref overload to Glx.ChooseVisual() IGraphicsContext.MakeCurrent now takes an IWindowInfo parameter. This allows the user to change to window is context is bound to (untested). Renamed XyzWindowInfo.Handle to XyzWindowInfo.WindowHandle. --- Source/OpenTK/ColorMode.cs | 2 +- Source/OpenTK/Configuration.cs | 9 +- Source/OpenTK/DisplayMode.cs | 2 +- Source/OpenTK/GLControl.cs | 125 ++++++-- Source/OpenTK/GameWindow.cs | 65 ++-- Source/OpenTK/Graphics/ColorDepth.cs | 32 +- Source/OpenTK/Graphics/DisplayDevice.cs | 1 + Source/OpenTK/Graphics/GraphicsContext.cs | 57 ++-- Source/OpenTK/Graphics/GraphicsMode.cs | 291 +++++++++++------- Source/OpenTK/Graphics/IGraphicsContext.cs | 7 +- Source/OpenTK/Graphics/OpenGL/GL/GLHelper.cs | 7 +- Source/OpenTK/Platform/DummyGLContext.cs | 6 +- Source/OpenTK/Platform/IWindowInfo.cs | 5 +- Source/OpenTK/Platform/Windows/WMInput.cs | 2 +- Source/OpenTK/Platform/Windows/WglHelper.cs | 2 +- .../OpenTK/Platform/Windows/WinGLContext.cs | 291 +++++------------- .../Platform/Windows/WinGLControlHelper.cs | 10 +- Source/OpenTK/Platform/Windows/WinGLNative.cs | 10 +- Source/OpenTK/Platform/Windows/WinRawInput.cs | 2 +- .../OpenTK/Platform/Windows/WinWindowInfo.cs | 66 +++- Source/OpenTK/Platform/X11/API.cs | 23 +- Source/OpenTK/Platform/X11/Functions.cs | 24 +- Source/OpenTK/Platform/X11/Glx.cs | 25 +- Source/OpenTK/Platform/X11/X11GLContext.cs | 181 ++++------- Source/OpenTK/Platform/X11/X11GLNative.cs | 74 +++-- Source/OpenTK/Platform/X11/X11WindowInfo.cs | 24 +- 26 files changed, 709 insertions(+), 634 deletions(-) diff --git a/Source/OpenTK/ColorMode.cs b/Source/OpenTK/ColorMode.cs index d3817fd8..eab4652d 100644 --- a/Source/OpenTK/ColorMode.cs +++ b/Source/OpenTK/ColorMode.cs @@ -14,7 +14,7 @@ namespace OpenTK /// A ColorMode contains Red, Green, Blue and Alpha components that descibe /// the allocated bits per pixel for the corresponding color. /// - [Obsolete("Use OpenTK.Graphics.ColorDepth instead.")] + [Obsolete("Use OpenTK.Graphics.ColorFormat instead.")] public sealed class ColorMode { byte red, green, blue, alpha; diff --git a/Source/OpenTK/Configuration.cs b/Source/OpenTK/Configuration.cs index 7e4de1cd..9c993e9c 100644 --- a/Source/OpenTK/Configuration.cs +++ b/Source/OpenTK/Configuration.cs @@ -18,7 +18,7 @@ namespace OpenTK /// Contains configuration options for OpenTK. internal static class Configuration { - static bool runningOnWindows, runningOnX11, runningOnOSX; + static bool runningOnWindows, runningOnX11, runningOnOSX, runningOnLinux; #region --- Constructors --- @@ -71,6 +71,13 @@ namespace OpenTK #endregion + #region internal static bool RunningOnLinux + + /// Gets a System.Boolean indicating whether OpenTK is running on an X11 platform. + internal static bool RunningOnLinux { get { return runningOnLinux; } } + + #endregion + #region internal static bool RunningOnOSX /// Gets a System.Boolean indicating whether OpenTK is running on an OSX platform. diff --git a/Source/OpenTK/DisplayMode.cs b/Source/OpenTK/DisplayMode.cs index f5fe4c7d..4560fb17 100644 --- a/Source/OpenTK/DisplayMode.cs +++ b/Source/OpenTK/DisplayMode.cs @@ -231,7 +231,7 @@ namespace OpenTK private set { this.refreshRate = value; } } - #region public ColorDepth Color + #region public ColorFormat Color [Obsolete("Use GraphicsMode.Color instead.")] public ColorMode Color diff --git a/Source/OpenTK/GLControl.cs b/Source/OpenTK/GLControl.cs index 491caf45..a0dc10b4 100644 --- a/Source/OpenTK/GLControl.cs +++ b/Source/OpenTK/GLControl.cs @@ -1,6 +1,8 @@ #region --- License --- -/* Copyright (c) 2006, 2007 Stefanos Apostolopoulos - * See license.txt for license info +/* 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 @@ -15,6 +17,7 @@ using System.Windows.Forms; using OpenTK.Platform; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL; +using System.Diagnostics; namespace OpenTK { @@ -24,8 +27,9 @@ namespace OpenTK public partial class GLControl : UserControl { IGraphicsContext context; + IGLControl implementation; GraphicsMode format; - IGLControlHelper helper; + IWindowInfo window_info; #region --- Constructor --- @@ -36,15 +40,17 @@ namespace OpenTK : this(GraphicsMode.Default) { } - /// - /// Constructs a new GLControl with the specified DisplayMode. - /// - /// + /// This method is obsolete and will be removed in future versions. + /// Obsolete. public GLControl(DisplayMode mode) : this(mode.ToGraphicsMode()) { } - public GLControl(GraphicsMode format) + /// + /// Constructs a new GLControl with the specified GraphicsMode. + /// + /// The OpenTK.Graphics.GraphicsMode of the control. + public GLControl(GraphicsMode mode) { InitializeComponent(); @@ -53,7 +59,21 @@ namespace OpenTK this.SetStyle(ControlStyles.AllPaintingInWmPaint, true); DoubleBuffered = false; - this.format = format; + this.format = mode; + + // 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, ??? + // 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 (Configuration.RunningOnWindows) + implementation = new OpenTK.Platform.Windows.WinGLControl(mode, this); + else if (Configuration.RunningOnX11) + implementation = new OpenTK.Platform.X11.X11GLControl(mode, this); + else if (Configuration.RunningOnOSX) + throw new PlatformNotSupportedException("Refer to http://www.opentk.com for more information."); this.CreateControl(); } @@ -62,23 +82,50 @@ namespace OpenTK #region --- Protected Methods --- + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + // Workaround Mono 1.2.4 bug where the OnHandleCreated event isn't raised at the correct time. + if (this.Context == null) + { + if (!DesignMode) + this.Context = implementation.CreateContext(); + else + this.Context = new DummyGLContext(null); + + this.window_info = implementation.WindowInfo; + this.MakeCurrent(); + ((IGraphicsContextInternal)this.Context).LoadAll(); + } + } + + /// Raises the HandleCreated event. + /// Not used. protected override void OnHandleCreated(EventArgs e) { base.OnHandleCreated(e); - if (Configuration.RunningOnWindows) - helper = new Platform.Windows.WinGLControlHelper(this); - else if (Configuration.RunningOnX11) - throw new NotImplementedException(); - //helper = new Platform.X11.X11GLControlHelper(this); - else if (Configuration.RunningOnOSX) - throw new NotImplementedException(); - this.CreateContext(); + // On Mono 1.2.4 the Resize event is raised before this :/ + //if (!DesignMode) + // this.Context = implementation.CreateContext(); + //else + // this.Context = new DummyGLContext(null); + + //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); - this.DestroyContext(); + if (this.Context != null) + { + this.Context.Dispose(); + this.Context = null; + } + this.window_info = null; } #endregion @@ -105,7 +152,7 @@ namespace OpenTK /// public void MakeCurrent() { - Context.MakeCurrent(); + this.Context.MakeCurrent(this.window_info); } #endregion @@ -117,19 +164,44 @@ namespace OpenTK /// public void CreateContext() { - if (context != null) - throw new InvalidOperationException("GLControl already contains an OpenGL context."); - if (format == null) - format = GraphicsMode.Default; + if (context != null) throw new InvalidOperationException("GLControl already contains an OpenGL context."); + if (format == null) format = GraphicsMode.Default; if (!this.DesignMode) { // Note: Mono's implementation of Windows.Forms on X11 does not allow the context to // have a different colordepth from the parent window. - context = new GraphicsContext(format, helper.WindowInfo); + //context = new GraphicsContext(format, helper.WindowInfo); + if (Configuration.RunningOnX11) + { + //OpenTK.Platform.X11.X11WindowInfo info = + // (context as IGraphicsContextInternal).Info as OpenTK.Platform.X11.X11WindowInfo; + //IntPtr visual = info.VisualInfo.visual; + //IntPtr colormap = OpenTK.Platform.X11.API.CreateColormap(info.Display, info.RootWindow, visual, 0); + //IntPtr visual = ((OpenTK.Platform.X11.X11WindowInfo)helper.WindowInfo).VisualInfo.visual; + //IntPtr colormap = OpenTK.Platform.X11.API.CreateColormap(info.Display, info.RootWindow, visual, 0); + + //Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); + //if (xplatui == null) + // throw new PlatformNotSupportedException( + // "System.Windows.Forms.XplatUIX11 missing. Unsupported platform or Mono runtime version, aborting."); + + //xplatui.GetField("CustomVisual", + // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + // .SetValue(null, visual); + + //xplatui.GetField("CustomColormap", + // System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + // .SetValue(null, colormap); + + //Debug.Print("Mono/X11 System.Windows.Forms custom visual and colormap installed succesfully."); + } } else context = new DummyGLContext(format); + + this.MakeCurrent(); + (context as IGraphicsContextInternal).LoadAll(); } #endregion @@ -156,7 +228,7 @@ namespace OpenTK [Browsable(false)] public bool IsIdle { - get { return helper.IsIdle; } + get { return implementation.IsIdle; } } #endregion @@ -233,6 +305,9 @@ namespace OpenTK /// 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. + /// public Bitmap GrabScreenshot() { Bitmap bmp = new Bitmap(this.ClientSize.Width, this.ClientSize.Height); diff --git a/Source/OpenTK/GameWindow.cs b/Source/OpenTK/GameWindow.cs index 862747ca..d076a1f8 100644 --- a/Source/OpenTK/GameWindow.cs +++ b/Source/OpenTK/GameWindow.cs @@ -81,21 +81,6 @@ namespace OpenTK #endregion - #region --- Private Methods --- - - bool MustResize - { - get { return glWindow.Width != this.Width || glWindow.Height != this.Height; } - } - - bool HasMainLoop - { - get { return hasMainLoop; } - set { hasMainLoop = value; } - } - - #endregion - #region --- Contructors --- #region public GameWindow() @@ -183,11 +168,8 @@ namespace OpenTK try { glWindow.CreateWindow(width, height, mode, out glContext); - Debug.Print("1"); - glContext.MakeCurrent(); - Debug.Print("2"); + glContext.MakeCurrent(this.WindowInfo); (glContext as IGraphicsContextInternal).LoadAll(); - Debug.Print("3"); } //catch (GraphicsContextException e) catch (Exception e) @@ -201,7 +183,7 @@ namespace OpenTK if ((options & GameWindowFlags.Fullscreen) != 0) { - device.ChangeResolution(width, height, mode.ColorDepth.BitsPerPixel, 0); + device.ChangeResolution(width, height, mode.ColorFormat.BitsPerPixel, 0); this.Fullscreen = true; } @@ -261,6 +243,25 @@ namespace OpenTK #endregion + #region bool MustResize + + bool MustResize + { + get { return glWindow.Width != this.Width || glWindow.Height != this.Height; } + } + + #endregion + + #region bool HasMainLoop + + bool HasMainLoop + { + get { return hasMainLoop; } + set { hasMainLoop = value; } + } + + #endregion + #endregion #region --- Public Methods --- @@ -607,7 +608,7 @@ namespace OpenTK } catch (GameWindowExitException) { - Trace.WriteLine("GameWindowExitException caught - exiting main loop."); + Debug.WriteLine("GameWindowExitException caught - exiting main loop."); } finally { @@ -616,13 +617,13 @@ namespace OpenTK OnUnloadInternal(EventArgs.Empty); - if (this.Exists) + if (Exists) { - if (Exists) - glWindow.DestroyWindow(); - while (this.Exists) - this.ProcessEvents(); + glContext.Dispose(); + glWindow.DestroyWindow(); } + while (this.Exists) + this.ProcessEvents(); } } @@ -899,7 +900,7 @@ namespace OpenTK /// Calling this function is equivalent to calling Context.SwapBuffers() public void SwapBuffers() { - Context.SwapBuffers(); + this.Context.SwapBuffers(); } #endregion @@ -1310,7 +1311,8 @@ namespace OpenTK private void DisposeInternal() { Dispose(); // User overridable Dispose method. - + Dispose(true); + GC.SuppressFinalize(this); } /// @@ -1318,8 +1320,6 @@ namespace OpenTK /// public virtual void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); } private void Dispose(bool manual) @@ -1328,9 +1328,11 @@ namespace OpenTK { if (manual) { + if (glContext != null) + glContext.Dispose(); + if (glWindow != null) { - glContext.Dispose(); glWindow.Dispose(); glWindow = null; } @@ -1339,6 +1341,7 @@ namespace OpenTK } } + /// Finalizes unmanaged resources consumed by the GameWindow. ~GameWindow() { Dispose(false); diff --git a/Source/OpenTK/Graphics/ColorDepth.cs b/Source/OpenTK/Graphics/ColorDepth.cs index c826c9ae..81f79396 100644 --- a/Source/OpenTK/Graphics/ColorDepth.cs +++ b/Source/OpenTK/Graphics/ColorDepth.cs @@ -12,12 +12,12 @@ using System.Text; namespace OpenTK.Graphics { - /// Defines the ColorDepth component of a GraphicsMode. + /// Defines the ColorFormat component of a GraphicsMode. /// - /// A ColorDepth contains Red, Green, Blue and Alpha components that descibe + /// A ColorFormat contains Red, Green, Blue and Alpha components that descibe /// the allocated bits per pixel for the corresponding color. /// - public struct ColorDepth + public struct ColorFormat { byte red, green, blue, alpha; bool isIndexed; @@ -26,10 +26,10 @@ namespace OpenTK.Graphics #region --- Constructors --- /// - /// Constructs a new ColorDepth with the specified aggregate bits per pixel. + /// Constructs a new ColorFormat with the specified aggregate bits per pixel. /// /// The bits per pixel sum for the Red, Green, Blue and Alpha color channels. - public ColorDepth(int bpp) + public ColorFormat(int bpp) { if (bpp < 0) throw new ArgumentOutOfRangeException("bpp", "Must be greater or equal to zero."); @@ -73,14 +73,14 @@ namespace OpenTK.Graphics } /// - /// Constructs a new ColorDepth with the specified bits per pixel for + /// Constructs a new ColorFormat with the specified bits per pixel for /// the Red, Green, Blue and Alpha color channels. /// /// Bits per pixel for the Red color channel. /// Bits per pixel for the Green color channel. /// Bits per pixel for the Blue color channel. /// Bits per pixel for the Alpha color channel. - public ColorDepth(int red, int green, int blue, int alpha) + public ColorFormat(int red, int green, int blue, int alpha) { if (red < 0 || green < 0 || blue < 0 || alpha < 0) throw new ArgumentOutOfRangeException("Arguments must be greater or equal to zero."); @@ -106,7 +106,7 @@ namespace OpenTK.Graphics public int Blue { get { return blue; } private set { blue = (byte)value; } } /// Gets the bits per pixel for the Alpha channel. public int Alpha { get { return alpha; } private set { alpha = (byte)value; } } - /// Gets a System.Boolean indicating whether this ColorDepth is indexed. + /// Gets a System.Boolean indicating whether this ColorFormat is indexed. public bool IsIndexed { get { return isIndexed; } private set { isIndexed = value; } } /// Gets the sum of Red, Green, Blue and Alpha bits per pixel. public int BitsPerPixel { get { return bitsPerPixel; } private set { bitsPerPixel = value; } } @@ -116,16 +116,16 @@ namespace OpenTK.Graphics #region --- Operator Overloads --- /// - /// Converts the specified bpp into a new ColorDepth. + /// Converts the specified bpp into a new ColorFormat. /// /// The bits per pixel to convert. - /// A ColorDepth with the specified bits per pixel. - public static implicit operator ColorDepth(int bpp) + /// A ColorFormat with the specified bits per pixel. + public static implicit operator ColorFormat(int bpp) { - return new ColorDepth(bpp); + return new ColorFormat(bpp); } - //public static implicit operator int(ColorDepth mode) + //public static implicit operator int(ColorFormat mode) //{ // return mode.BitsPerPixel; //} @@ -136,10 +136,10 @@ namespace OpenTK.Graphics public override bool Equals(object obj) { - return (obj is ColorDepth) ? (this == (ColorDepth)obj) : false; + return (obj is ColorFormat) ? (this == (ColorFormat)obj) : false; } - public static bool operator ==(ColorDepth left, ColorDepth right) + public static bool operator ==(ColorFormat left, ColorFormat right) { if ((object)left == (object)null && (object)right != (object)null || (object)left != (object)null && (object)right == (object)null) @@ -154,7 +154,7 @@ namespace OpenTK.Graphics left.Alpha == right.Alpha; } - public static bool operator !=(ColorDepth left, ColorDepth right) + public static bool operator !=(ColorFormat left, ColorFormat right) { return !(left == right); } diff --git a/Source/OpenTK/Graphics/DisplayDevice.cs b/Source/OpenTK/Graphics/DisplayDevice.cs index d77e2c86..2bdc6510 100644 --- a/Source/OpenTK/Graphics/DisplayDevice.cs +++ b/Source/OpenTK/Graphics/DisplayDevice.cs @@ -75,6 +75,7 @@ namespace OpenTK.Graphics Debug.Print("DisplayDevice {0} ({1}) supports {2} resolutions.", available_displays.Count, primary ? "primary" : "secondary", available_resolutions.Count); + Debug.Indent(); foreach (DisplayResolution res in available_resolutions) Debug.Print(res == current_resolution ? String.Format(">> {0} <<", res.ToString()) : res.ToString()); diff --git a/Source/OpenTK/Graphics/GraphicsContext.cs b/Source/OpenTK/Graphics/GraphicsContext.cs index 1d9ec4eb..a9f882a7 100644 --- a/Source/OpenTK/Graphics/GraphicsContext.cs +++ b/Source/OpenTK/Graphics/GraphicsContext.cs @@ -28,8 +28,7 @@ namespace OpenTK.Graphics static bool direct_rendering = true; static object context_lock = new object(); // Maps OS-specific context handles to GraphicsContext weak references. - static Dictionary available_contexts = - new Dictionary(); + static Dictionary available_contexts = new Dictionary(); #region public GraphicsContext(DisplayMode mode, IWindowInfo window) @@ -44,7 +43,9 @@ namespace OpenTK.Graphics #region public GraphicsContext(GraphicsMode format, IWindowInfo window) - /// Constructs a new GraphicsContext with the specified format, and attaches it to the specified window. + /// + /// Constructs a new GraphicsContext with the specified format, and attaches it to the specified window. + /// /// The OpenTK.Graphics.GraphicsMode of the GraphicsContext. /// The OpenTK.Platform.IWindowInfo to attach the GraphicsContext to. public GraphicsContext(GraphicsMode format, IWindowInfo window) @@ -75,8 +76,7 @@ namespace OpenTK.Graphics else if (Configuration.RunningOnX11) implementation = new OpenTK.Platform.X11.X11GLContext(format, window, shareContext, DirectRendering); else - throw new PlatformNotSupportedException( - "Your platform is not currently supported. Please, check http://www.opentk.com for an updated version."); + throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information."); available_contexts.Add((this as IGraphicsContextInternal).Context, new WeakReference(this)); //(implementation as IGraphicsContextInternal).LoadAll(); @@ -94,7 +94,7 @@ namespace OpenTK.Graphics void ContextDestroyed(IGraphicsContext context, EventArgs e) { this.Destroy -= ContextDestroyed; - available_contexts.Remove(((IGraphicsContextInternal)this).Context); + //available_contexts.Remove(((IGraphicsContextInternal)this).Context); } #endregion @@ -121,13 +121,13 @@ namespace OpenTK.Graphics } return null; } - set - { - if (value != null) - value.MakeCurrent(); - else if (CurrentContext != null) - CurrentContext.IsCurrent = false; - } + //set + //{ + // if (value != null) + // value.MakeCurrent(); + // else if (CurrentContext != null) + // CurrentContext.IsCurrent = false; + //} } #endregion @@ -229,11 +229,15 @@ namespace OpenTK.Graphics } /// - /// Makes this context the current rendering target. + /// Makes the GraphicsContext the current rendering target. /// - public void MakeCurrent() + /// A System.Platform.IWindowInfo structure for the window this context is bound to. + /// + /// You can use this method to bind the GraphicsContext to a different window than the one it was created from. + /// + public void MakeCurrent(IWindowInfo info) { - implementation.MakeCurrent(); + implementation.MakeCurrent(info); } /// @@ -242,7 +246,7 @@ namespace OpenTK.Graphics public bool IsCurrent { get { return implementation.IsCurrent; } - set { implementation.IsCurrent = value; } + //set { implementation.IsCurrent = value; } } /// @@ -283,6 +287,7 @@ namespace OpenTK.Graphics get { return ((IGraphicsContextInternal)implementation).Context; } } + /* /// /// Gets the IWindowInfo describing the window associated with this context. /// @@ -291,6 +296,7 @@ namespace OpenTK.Graphics get { return (implementation as IGraphicsContextInternal).Info; } //internal set { (implementation as IGLContextInternal).Info = value; } } + */ /// /// Gets the DisplayMode of the context. @@ -385,11 +391,15 @@ namespace OpenTK.Graphics { if (!disposed) { - // TODO: Check if this is safe - //if (manual) + if (manual) + { + Debug.WriteLine("Disposing context."); + available_contexts.Remove((this as IGraphicsContextInternal).Context); + + // TODO: Check if this is safe if (implementation != null) implementation.Dispose(); - + } disposed = true; } } @@ -402,10 +412,17 @@ namespace OpenTK.Graphics #endregion } + #region public class GraphicsException : Exception + /// Represents errors related to Graphics operations. public class GraphicsException : Exception { + /// Constructs a new GraphicsException. public GraphicsException() : base() { } + /// Constructs a new GraphicsException with the specified excpetion message. + /// public GraphicsException(string message) : base(message) { } } + + #endregion } \ No newline at end of file diff --git a/Source/OpenTK/Graphics/GraphicsMode.cs b/Source/OpenTK/Graphics/GraphicsMode.cs index f0eaea58..86aaf8e9 100644 --- a/Source/OpenTK/Graphics/GraphicsMode.cs +++ b/Source/OpenTK/Graphics/GraphicsMode.cs @@ -15,143 +15,190 @@ namespace OpenTK.Graphics /// Defines the format for graphics operations. public class GraphicsMode { - ColorDepth color_format, accumulator_format; + ColorFormat color_format, accumulator_format; int depth, stencil, buffers, samples; bool stereo; + IntPtr index; // The id of the pixel format or visual. + + static IGraphicsMode implementation; + static object mode_selection_lock = new object(); #region --- Constructors --- - #region internal GraphicsFormat(GraphicsFormat mode) + #region static GraphicsMode() + + static GraphicsMode() + { + if (Configuration.RunningOnWindows) + implementation = new OpenTK.Platform.Windows.WinGraphicsMode(); + else if (Configuration.RunningOnX11) + implementation = new OpenTK.Platform.X11.X11GraphicsMode(); + else + throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information."); + } + + #endregion + + #region internal GraphicsMode(GraphicsMode mode) - /// - /// Constructs a new GraphicsFormat from the given GraphicsFormat. - /// internal GraphicsMode(GraphicsMode mode) - : this(mode.ColorDepth, mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat, mode.Buffers, mode.Stereo) { } + : this(mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat, mode.Buffers, mode.Stereo) { } #endregion - #region public GraphicsFormat() + #region internal GraphicsMode((IntPtr index, ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo) - /// Constructs a new GraphicsFormat with sensible default parameters. - public GraphicsMode() - : this(Default) - { } - - #endregion - - #region public GraphicsFormat(ColorDepth color) - - /// Constructs a new GraphicsFormat with the specified parameters. - /// The ColorDepth of the color buffer. - public GraphicsMode(ColorDepth color) - : this(color, Default.Depth, Default.Stencil, Default.Samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) - { } - - #endregion - - #region public GraphicsFormat(ColorDepth color, int depth) - - /// Constructs a new GraphicsFormat with the specified parameters. - /// The ColorDepth of the color buffer. - /// The number of bits in the depth buffer. - public GraphicsMode(ColorDepth color, int depth) - : this(color, depth, Default.Stencil, Default.Samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) - { } - - #endregion - - #region public GraphicsFormat(ColorDepth color, int depth, int stencil) - - /// Constructs a new GraphicsFormat with the specified parameters. - /// The ColorDepth of the color buffer. - /// The number of bits in the depth buffer. - /// The number of bits in the stencil buffer. - public GraphicsMode(ColorDepth color, int depth, int stencil) - : this(color, depth, stencil, Default.Samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) - { } - - #endregion - - #region public GraphicsFormat(ColorDepth color, int depth, int stencil, int samples) - - /// Constructs a new GraphicsFormat with the specified parameters. - /// The ColorDepth of the color buffer. - /// The number of bits in the depth buffer. - /// The number of bits in the stencil buffer. - /// The number of samples for FSAA. - public GraphicsMode(ColorDepth color, int depth, int stencil, int samples) - : this(color, depth, stencil, samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) - { } - - #endregion - - #region public GraphicsFormat(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum) - - /// Constructs a new GraphicsFormat with the specified parameters. - /// The ColorDepth of the color buffer. - /// The number of bits in the depth buffer. - /// The number of bits in the stencil buffer. - /// The number of samples for FSAA. - /// The ColorDepth of the accumilliary buffer. - public GraphicsMode(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum) - : this(color, depth, stencil, samples, accum, Default.Buffers, Default.Stereo) - { } - - #endregion - - #region public GraphicsFormat(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum, int buffers) - - /// Constructs a new GraphicsFormat with the specified parameters. - /// The ColorDepth of the color buffer. - /// The number of bits in the depth buffer. - /// The number of bits in the stencil buffer. - /// The number of samples for FSAA. - /// The ColorDepth of the accumilliary buffer. - /// The number of render buffers. Typical values include one (single-), two (double-) or three (triple-buffering). - public GraphicsMode(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum, int buffers) - : this(color, depth, stencil, samples, accum, buffers, Default.Stereo) - { } - - #endregion - - #region public GraphicsFormat(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum, int buffers, bool stereo) - - /// Constructs a new GraphicsFormat with the specified parameters. - /// The ColorDepth of the color buffer. - /// The number of bits in the depth buffer. - /// The number of bits in the stencil buffer. - /// The number of samples for FSAA. - /// The ColorDepth of the accumilliary buffer. - /// Set to true for a GraphicsFormat with stereographic capabilities. - /// The number of render buffers. Typical values include one (single-), two (double-) or three (triple-buffering). - public GraphicsMode(ColorDepth color, int depth, int stencil, int samples, ColorDepth accum, int buffers, bool stereo) + internal GraphicsMode(IntPtr index, ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, + int buffers, bool stereo) { if (depth < 0) throw new ArgumentOutOfRangeException("depth", "Must be greater than, or equal to zero."); if (stencil < 0) throw new ArgumentOutOfRangeException("stencil", "Must be greater than, or equal to zero."); if (buffers <= 0) throw new ArgumentOutOfRangeException("buffers", "Must be greater than zero."); if (samples < 0) throw new ArgumentOutOfRangeException("samples", "Must be greater than, or equal to zero."); - this.ColorDepth = color; - this.Depth = depth; - this.Stencil = stencil; - this.AccumulatorFormat = accum; - this.Buffers = buffers; - this.Stereo = stereo; + // This method will search for the closest + + if (index == IntPtr.Zero) + { + GraphicsMode mode; + lock (mode_selection_lock) + { + mode = implementation.SelectGraphicsMode(color, depth, stencil, samples, accum, buffers, stereo); + } + + this.Index = mode.Index; + this.ColorFormat = mode.ColorFormat; + this.Depth = mode.Depth; + this.Stencil = mode.Stencil; + this.Samples = mode.Samples; + this.AccumulatorFormat = mode.AccumulatorFormat; + this.Buffers = mode.Buffers; + this.Stereo = mode.Stereo; + } + else + { + this.Index = index; + this.ColorFormat = color; + this.Depth = depth; + this.Stencil = stencil; + this.Samples = samples; + this.AccumulatorFormat = accum; + this.Buffers = buffers; + this.Stereo = stereo; + } } #endregion + #region public GraphicsMode() + + /// Constructs a new GraphicsMode with sensible default parameters. + public GraphicsMode() + : this(Default) + { } + + #endregion + + #region public GraphicsMode(ColorFormat color) + + /// Constructs a new GraphicsMode with the specified parameters. + /// The ColorFormat of the color buffer. + public GraphicsMode(ColorFormat color) + : this(color, Default.Depth, Default.Stencil, Default.Samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) + { } + + #endregion + + #region public GraphicsMode(ColorFormat color, int depth) + + /// Constructs a new GraphicsMode with the specified parameters. + /// The ColorFormat of the color buffer. + /// The number of bits in the depth buffer. + public GraphicsMode(ColorFormat color, int depth) + : this(color, depth, Default.Stencil, Default.Samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) + { } + + #endregion + + #region public GraphicsMode(ColorFormat color, int depth, int stencil) + + /// Constructs a new GraphicsMode with the specified parameters. + /// The ColorFormat of the color buffer. + /// The number of bits in the depth buffer. + /// The number of bits in the stencil buffer. + public GraphicsMode(ColorFormat color, int depth, int stencil) + : this(color, depth, stencil, Default.Samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) + { } + + #endregion + + #region public GraphicsMode(ColorFormat color, int depth, int stencil, int samples) + + /// Constructs a new GraphicsMode with the specified parameters. + /// The ColorFormat of the color buffer. + /// The number of bits in the depth buffer. + /// The number of bits in the stencil buffer. + /// The number of samples for FSAA. + public GraphicsMode(ColorFormat color, int depth, int stencil, int samples) + : this(color, depth, stencil, samples, Default.AccumulatorFormat, Default.Buffers, Default.Stereo) + { } + + #endregion + + #region public GraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum) + + /// Constructs a new GraphicsMode with the specified parameters. + /// The ColorFormat of the color buffer. + /// The number of bits in the depth buffer. + /// The number of bits in the stencil buffer. + /// The number of samples for FSAA. + /// The ColorFormat of the accumilliary buffer. + public GraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum) + : this(color, depth, stencil, samples, accum, Default.Buffers, Default.Stereo) + { } + + #endregion + + #region public GraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers) + + /// Constructs a new GraphicsMode with the specified parameters. + /// The ColorFormat of the color buffer. + /// The number of bits in the depth buffer. + /// The number of bits in the stencil buffer. + /// The number of samples for FSAA. + /// The ColorFormat of the accumilliary buffer. + /// The number of render buffers. Typical values include one (single-), two (double-) or three (triple-buffering). + public GraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers) + : this(color, depth, stencil, samples, accum, buffers, Default.Stereo) + { } + + #endregion + + #region public GraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo) + + /// Constructs a new GraphicsMode with the specified parameters. + /// The ColorFormat of the color buffer. + /// The number of bits in the depth buffer. + /// The number of bits in the stencil buffer. + /// The number of samples for FSAA. + /// The ColorFormat of the accumilliary buffer. + /// Set to true for a GraphicsMode with stereographic capabilities. + /// The number of render buffers. Typical values include one (single-), two (double-) or three (triple-buffering). + public GraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, int buffers, bool stereo) + : this(IntPtr.Zero, color, depth, stencil, samples, accum, buffers, stereo) { } + + #endregion + #endregion #region --- Public Methods --- - #region public int ColorDepth + #region public int ColorFormat /// - /// Gets an OpenTK.Graphics.ColorDepth that describes the color format for this GraphicsFormat. + /// Gets an OpenTK.Graphics.ColorFormat that describes the color format for this GraphicsFormat. /// - public ColorDepth ColorDepth + public ColorFormat ColorFormat { get { return color_format; } private set { color_format = value; } @@ -162,9 +209,9 @@ namespace OpenTK.Graphics #region public int AccumulatorFormat /// - /// Gets an OpenTK.Graphics.ColorDepth that describes the accumulator format for this GraphicsFormat. + /// Gets an OpenTK.Graphics.ColorFormat that describes the accumulator format for this GraphicsFormat. /// - public ColorDepth AccumulatorFormat + public ColorFormat AccumulatorFormat { get { return accumulator_format; } private set { accumulator_format = value; } @@ -200,6 +247,8 @@ namespace OpenTK.Graphics #endregion + #region public int Samples + /// /// Gets a System.Int32 that contains the number of FSAA samples per pixel for this GraphicsFormat. /// @@ -209,6 +258,8 @@ namespace OpenTK.Graphics private set { samples = value; } } + #endregion + #region public bool Stereo /// @@ -248,14 +299,28 @@ namespace OpenTK.Graphics #endregion + #region --- Internal Methods --- + + #region internal IntPtr Index + + internal IntPtr Index + { + get { return index; } + set { index = value; } + } + + #endregion + + #endregion + #region --- Overrides --- /// Returns a System.String describing the current GraphicsFormat. /// ! System.String describing the current GraphicsFormat. public override string ToString() { - return String.Format("Color: {0}, Depth: {1}, Stencil: {2}, Samples: {3}, Accum: {4}, Buffers: {5}, Stereo: {6}", - ColorDepth, Depth, Stereo, Samples, AccumulatorFormat, Buffers, Stereo); + return String.Format("Index: {0}, Color: {1}, Depth: {2}, Stencil: {3}, Samples: {4}, Accum: {5}, Buffers: {6}, Stereo: {7}", + Index, ColorFormat, Depth, Stereo, Samples, AccumulatorFormat, Buffers, Stereo); } #endregion diff --git a/Source/OpenTK/Graphics/IGraphicsContext.cs b/Source/OpenTK/Graphics/IGraphicsContext.cs index 944b2999..a718c81d 100644 --- a/Source/OpenTK/Graphics/IGraphicsContext.cs +++ b/Source/OpenTK/Graphics/IGraphicsContext.cs @@ -23,16 +23,17 @@ namespace OpenTK.Graphics void SwapBuffers(); /// Makes the GraphicsContext current in the calling thread. + /// An OpenTK.Platform.IWindowInfo structure that points to a valid window. /// /// OpenGL commands in one thread, affect the GraphicsContext which is current in that thread. /// It is an error to issue an OpenGL command in a thread without a current GraphicsContext. /// - void MakeCurrent(); + void MakeCurrent(IWindowInfo window); /// /// Gets or sets a System.Boolean indicating whether the GraphicsContext is current in the calling thread. /// - bool IsCurrent { get; set; } + bool IsCurrent { get; /*set;*/ } /// /// Raised when a Context is destroyed. @@ -82,7 +83,7 @@ namespace OpenTK.Graphics /// /// Gets the IWindowInfo describing the window associated with this context. /// - IWindowInfo Info { get; } + //IWindowInfo Info { get; } /// Gets the GraphicsMode of the context. GraphicsMode GraphicsMode { get; } diff --git a/Source/OpenTK/Graphics/OpenGL/GL/GLHelper.cs b/Source/OpenTK/Graphics/OpenGL/GL/GLHelper.cs index 441e86a0..3e444312 100644 --- a/Source/OpenTK/Graphics/OpenGL/GL/GLHelper.cs +++ b/Source/OpenTK/Graphics/OpenGL/GL/GLHelper.cs @@ -389,9 +389,10 @@ namespace OpenTK.Graphics.OpenGL // Most drivers return the version in the 3 first characters of the version string, // (e.g. on Ati X1950 with Catalyst 7.10 -> "2.0.6956 Release"). However, Mesa seems // to do something strange: "1.4 (2.1 Mesa 7.0.1).". + // Update: this seems to occur with indirect rendering. E.g. Ati 8.2: 1.4 (2.1.7281 ...) // We'll do some trickery to get the second number (2.1), but this may break on // some implementations... - if (version_string.ToLower().Contains("mesa")) + //if (version_string.ToLower().Contains("mesa")) { int index = version_string.IndexOf('('); if (index != -1) @@ -399,8 +400,8 @@ namespace OpenTK.Graphics.OpenGL else version = version_string.TrimStart(' '); } - else - version = version_string.TrimStart(' '); + //else + // version = version_string.TrimStart(' '); Debug.Print(version); diff --git a/Source/OpenTK/Platform/DummyGLContext.cs b/Source/OpenTK/Platform/DummyGLContext.cs index 8e432435..59b7a61b 100644 --- a/Source/OpenTK/Platform/DummyGLContext.cs +++ b/Source/OpenTK/Platform/DummyGLContext.cs @@ -31,12 +31,12 @@ namespace OpenTK.Platform public IntPtr Context { get { return IntPtr.Zero; } } public GraphicsMode GraphicsMode { get { return format; } } - public void CreateContext() { } - public void CreateContext(bool direct) { } + //public void CreateContext() { } + //public void CreateContext(bool direct) { } public void CreateContext(bool direct, IGraphicsContext source) { } public void SwapBuffers() { } - public void MakeCurrent() { } + public void MakeCurrent(IWindowInfo info) { } public bool IsCurrent { get { return true; } set { } } public IntPtr GetCurrentContext() { return IntPtr.Zero; } diff --git a/Source/OpenTK/Platform/IWindowInfo.cs b/Source/OpenTK/Platform/IWindowInfo.cs index b22addd2..15df450d 100644 --- a/Source/OpenTK/Platform/IWindowInfo.cs +++ b/Source/OpenTK/Platform/IWindowInfo.cs @@ -12,7 +12,10 @@ using System.Text; namespace OpenTK.Platform { - public interface IWindowInfo + /// Descibes an OS window. + public interface IWindowInfo : IDisposable { + // /// Gets a System.IntPtr which contains the handle of the window. + //IntPtr WindowHandle { get; } } } diff --git a/Source/OpenTK/Platform/Windows/WMInput.cs b/Source/OpenTK/Platform/Windows/WMInput.cs index 074e0a23..c4d4bfb1 100644 --- a/Source/OpenTK/Platform/Windows/WMInput.cs +++ b/Source/OpenTK/Platform/Windows/WMInput.cs @@ -33,7 +33,7 @@ namespace OpenTK.Platform.Windows Debug.WriteLine("Initalizing WMInput driver."); Debug.Indent(); - AssignHandle(parent.Handle); + AssignHandle(parent.WindowHandle); Debug.Print("Input window attached to parent {0}", parent); Debug.Unindent(); diff --git a/Source/OpenTK/Platform/Windows/WglHelper.cs b/Source/OpenTK/Platform/Windows/WglHelper.cs index f0b7fecf..415d56a9 100644 --- a/Source/OpenTK/Platform/Windows/WglHelper.cs +++ b/Source/OpenTK/Platform/Windows/WglHelper.cs @@ -143,7 +143,7 @@ namespace OpenTK.Platform.Windows { if (extensions == null || rebuildExtensionList) { - extensions = Wgl.Arb.GetExtensionsString(context.Device).Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); + extensions = Wgl.Arb.GetExtensionsString(context.DeviceContext).Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); Array.Sort(extensions); rebuildExtensionList = false; } diff --git a/Source/OpenTK/Platform/Windows/WinGLContext.cs b/Source/OpenTK/Platform/Windows/WinGLContext.cs index 880c4b2b..64fc9f13 100644 --- a/Source/OpenTK/Platform/Windows/WinGLContext.cs +++ b/Source/OpenTK/Platform/Windows/WinGLContext.cs @@ -24,13 +24,14 @@ namespace OpenTK.Platform.Windows /// 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 : IGraphicsContext, IGraphicsContextInternal, IGLContextCreationHack + internal sealed class WinGLContext : IGraphicsContext, IGraphicsContextInternal//, IGLContextCreationHack { - IntPtr deviceContext; + //IntPtr deviceContext; + WinWindowInfo currentWindow; ContextHandle renderContext; static IntPtr opengl32Handle; const string opengl32Name = "OPENGL32.DLL"; - WinWindowInfo windowInfo = new WinWindowInfo(); + //WinWindowInfo windowInfo = new WinWindowInfo(); GraphicsMode format; //DisplayMode mode = null; @@ -58,32 +59,24 @@ namespace OpenTK.Platform.Windows } } - GraphicsMode SelectFormat(GraphicsMode format) - { - using (WinGLNative native = new WinGLNative()) - //using (WinGLContext context = new WinGLContext(format, native.WindowInfo, null)) - { - // Find the best multisampling mode. - return format; - } - } - public WinGLContext(GraphicsMode format, IWindowInfo window, IGraphicsContext sharedContext) { - //format = this.SelectFormat(format); + if (window == null) throw new ArgumentNullException("window", "Must point to a valid window."); - this.windowInfo = (WinWindowInfo)window; - Debug.Print("OpenGL will be bound to handle: {0}", this.windowInfo.Handle); - if (this.windowInfo.Handle == IntPtr.Zero) - throw new ArgumentException("window", "Must be a valid window."); + currentWindow = (WinWindowInfo)window; + if (currentWindow.WindowHandle == IntPtr.Zero) throw new ArgumentException("window", "Must be a valid window."); - Debug.Print("Setting pixel format..."); - this.format = this.SetGraphicsModePFD(format); + Debug.Print("OpenGL will be bound to handle: {0}", currentWindow.WindowHandle); + + Debug.Print("Setting pixel format... "); + this.SetGraphicsModePFD(format, (WinWindowInfo)window); - 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. - renderContext = new ContextHandle(Wgl.Imports.CreateContext(deviceContext)); + Debug.Write("Creating render context... "); + renderContext = new ContextHandle(Wgl.Imports.CreateContext(currentWindow.DeviceContext)); + if (renderContext == IntPtr.Zero) + renderContext = new ContextHandle(Wgl.Imports.CreateContext(currentWindow.DeviceContext)); if (renderContext == IntPtr.Zero) throw new GraphicsContextException(String.Format("Context creation failed. Wgl.CreateContext() error: {0}.", Marshal.GetLastWin32Error())); @@ -134,19 +127,33 @@ namespace OpenTK.Platform.Windows public void SwapBuffers() { - Functions.SwapBuffers(deviceContext); + + Functions.SwapBuffers(currentWindow.DeviceContext); } #endregion - #region public void MakeCurrent() - - public void MakeCurrent() + #region public void MakeCurrent(IWindowInfo window) + + public void MakeCurrent(IWindowInfo window) { - if (!Wgl.Imports.MakeCurrent(deviceContext, renderContext)) + bool success; + + if (window != null) { - Debug.Print("WinGLContext.MakeCurrent() call failed. Error: {0}", Marshal.GetLastWin32Error()); + if (((WinWindowInfo)window).WindowHandle == IntPtr.Zero) + throw new ArgumentException("window", "Must point to a valid window."); + + currentWindow = (WinWindowInfo)window; + success = Wgl.Imports.MakeCurrent(((WinWindowInfo)window).DeviceContext, this.renderContext); } + else + success = Wgl.Imports.MakeCurrent(IntPtr.Zero, IntPtr.Zero); + + if (!success) + throw new GraphicsContextException(String.Format( + "Failed to make context {0} current. Error: {1}", this, Marshal.GetLastWin32Error())); + } #endregion @@ -156,6 +163,7 @@ namespace OpenTK.Platform.Windows public bool IsCurrent { get { return Wgl.GetCurrentContext() == this.renderContext; } + /* set { if (value) @@ -163,6 +171,7 @@ namespace OpenTK.Platform.Windows else Wgl.MakeCurrent(IntPtr.Zero, IntPtr.Zero); } + */ } @@ -218,12 +227,12 @@ namespace OpenTK.Platform.Windows #endregion #region IWindowInfo IGLContextInternal.Info - + /* IWindowInfo IGraphicsContextInternal.Info { get { return (IWindowInfo)windowInfo; } } - + */ #endregion #region GraphicsMode IGLContextInternal.GraphicsMode @@ -275,205 +284,49 @@ namespace OpenTK.Platform.Windows #region --- Private Methods --- - #region GraphicsMode SetGraphicsModePFD(GraphicsMode format) + #region void SetGraphicsModePFD(GraphicsMode format, WinWindowInfo window) - GraphicsMode SetGraphicsModePFD(GraphicsMode format) + void SetGraphicsModePFD(GraphicsMode mode, WinWindowInfo window) { - deviceContext = Functions.GetDC(this.windowInfo.Handle); - Debug.WriteLine(String.Format("Device context: {0}", deviceContext)); + if (mode.Index == IntPtr.Zero) throw new ArgumentException( + "mode", "The Index (pixel format) of the GraphicsMode is not set."); + if (window == null) throw new ArgumentNullException("window", "Must point to a valid window."); - Debug.Write("Setting pixel format... "); - PixelFormatDescriptor pixelFormat = new PixelFormatDescriptor(); - pixelFormat.Size = API.PixelFormatDescriptorSize; - pixelFormat.Version = API.PixelFormatDescriptorVersion; - pixelFormat.Flags = - PixelFormatDescriptorFlags.SUPPORT_OPENGL | - PixelFormatDescriptorFlags.DRAW_TO_WINDOW; - pixelFormat.ColorBits = (byte)(format.ColorDepth.Red + format.ColorDepth.Green + format.ColorDepth.Blue); - - pixelFormat.PixelType = format.ColorDepth.IsIndexed ? PixelType.INDEXED : PixelType.RGBA; - pixelFormat.PixelType = PixelType.RGBA; - pixelFormat.RedBits = (byte)format.ColorDepth.Red; - pixelFormat.GreenBits = (byte)format.ColorDepth.Green; - pixelFormat.BlueBits = (byte)format.ColorDepth.Blue; - pixelFormat.AlphaBits = (byte)format.ColorDepth.Alpha; - - if (format.AccumulatorFormat.BitsPerPixel > 0) - { - pixelFormat.AccumBits = (byte)(format.AccumulatorFormat.Red + format.AccumulatorFormat.Green + format.AccumulatorFormat.Blue); - pixelFormat.AccumRedBits = (byte)format.AccumulatorFormat.Red; - pixelFormat.AccumGreenBits = (byte)format.AccumulatorFormat.Green; - pixelFormat.AccumBlueBits = (byte)format.AccumulatorFormat.Blue; - pixelFormat.AccumAlphaBits = (byte)format.AccumulatorFormat.Alpha; - } - - pixelFormat.DepthBits = (byte)format.Depth; - pixelFormat.StencilBits = (byte)format.Stencil; - - if (format.Depth <= 0) pixelFormat.Flags |= PixelFormatDescriptorFlags.DEPTH_DONTCARE; - if (format.Stereo) pixelFormat.Flags |= PixelFormatDescriptorFlags.STEREO; - if (format.Buffers > 1) pixelFormat.Flags |= PixelFormatDescriptorFlags.DOUBLEBUFFER; - - int pixel = Functions.ChoosePixelFormat(deviceContext, ref pixelFormat); - if (pixel == 0) - throw new GraphicsModeException(String.Format("The requested format is not available: {0}.", format)); - - // Find out what we really got as a format: PixelFormatDescriptor pfd = new PixelFormatDescriptor(); - pixelFormat.Size = API.PixelFormatDescriptorSize; - pixelFormat.Version = API.PixelFormatDescriptorVersion; - Functions.DescribePixelFormat(deviceContext, pixel, API.PixelFormatDescriptorSize, ref pfd); - GraphicsMode fmt = new GraphicsMode( - new ColorDepth(pfd.RedBits, pfd.GreenBits, pfd.BlueBits, pfd.AlphaBits), - pfd.DepthBits, - pfd.StencilBits, - 0, - new ColorDepth(pfd.AccumBits), - (pfd.Flags & PixelFormatDescriptorFlags.DOUBLEBUFFER) != 0 ? 2 : 1, - (pfd.Flags & PixelFormatDescriptorFlags.STEREO) != 0); - - if (!Functions.SetPixelFormat(deviceContext, pixel, ref pixelFormat)) - throw new GraphicsContextException(String.Format("Requested GraphicsMode not available. SetPixelFormat error: {0}", - Marshal.GetLastWin32Error())); - Debug.Print("done! (format: {0})", pixel); - - return fmt; + Functions.DescribePixelFormat(window.DeviceContext, (int)mode.Index, + API.PixelFormatDescriptorSize, ref pfd); + Debug.WriteLine(mode.Index.ToString()); + if (!Functions.SetPixelFormat(window.DeviceContext, (int)mode.Index, ref pfd)) + throw new GraphicsContextException(String.Format( + "Requested GraphicsMode not available. SetPixelFormat error: {0}", Marshal.GetLastWin32Error())); } - #endregion - #region GraphicsMode SetGraphicsModeARB(GraphicsMode format) + #region void SetGraphicsModeARB(GraphicsMode format, IWindowInfo window) - GraphicsMode SetGraphicsModeARB(GraphicsMode format) + void SetGraphicsModeARB(GraphicsMode format, IWindowInfo window) { - return null; + throw new NotImplementedException(); } #endregion - - #endregion - - #region --- IGLContextCreationHack Members --- - - #region bool IGLContextCreationHack.SelectDisplayMode(DisplayMode mode, IWindowInfo info) - - /// - /// HACK! This function will be removed in 0.3.15 - /// Checks if the specified OpenTK.Platform.DisplayMode is available, and selects it if it is. - /// - /// The OpenTK.Platform.DisplayMode to select. - /// The OpenTK.Platform.IWindowInfo that describes the display to use. Note: a window handle is not necessary for this function! - /// True if the DisplayMode is available, false otherwise. - bool IGLContextCreationHack.SelectDisplayMode(DisplayMode mode, IWindowInfo info) - { - // Dynamically load the OpenGL32.dll in order to use the extension loading capabilities of Wgl. - if (opengl32Handle == IntPtr.Zero) - { - opengl32Handle = Functions.LoadLibrary(opengl32Name); - if (opengl32Handle == IntPtr.Zero) - { - //System.Diagnostics.Debug.WriteLine("LoadLibrary({0}) set error code: {1}. Will not load extensions.", _dll_name, error_code); - throw new ApplicationException(String.Format("LoadLibrary(\"{0}\") call failed with code {1}", - opengl32Name, Marshal.GetLastWin32Error())); - } - Debug.WriteLine(String.Format("Loaded opengl32.dll: {0}", opengl32Handle)); - } - deviceContext = Functions.GetDC(this.windowInfo.Handle); - Debug.WriteLine(String.Format("Device context: {0}", deviceContext)); - - Debug.Write("Setting pixel format... "); - PixelFormatDescriptor pixelFormat = new PixelFormatDescriptor(); - pixelFormat.Size = API.PixelFormatDescriptorSize; - pixelFormat.Version = API.PixelFormatDescriptorVersion; - pixelFormat.Flags = - PixelFormatDescriptorFlags.SUPPORT_OPENGL | - PixelFormatDescriptorFlags.DRAW_TO_WINDOW; - pixelFormat.ColorBits = (byte)(mode.Color.Red + mode.Color.Green + mode.Color.Blue); - if (mode.Color.IsIndexed) - { - pixelFormat.PixelType = PixelType.INDEXED; - } - else - { - pixelFormat.PixelType = PixelType.RGBA; - pixelFormat.RedBits = (byte)mode.Color.Red; - pixelFormat.GreenBits = (byte)mode.Color.Green; - pixelFormat.BlueBits = (byte)mode.Color.Blue; - pixelFormat.AlphaBits = (byte)mode.Color.Alpha; - } - - /* - if (accum != null) - { - pixelFormat.AccumBits = (byte)(accum.Red + accum.Green + accum.Blue); - pixelFormat.AccumRedBits = (byte)accum.Red; - pixelFormat.AccumGreenBits = (byte)accum.Green; - pixelFormat.AccumBlueBits = (byte)accum.Blue; - pixelFormat.AccumAlphaBits = (byte)accum.Alpha; - } - */ - pixelFormat.DepthBits = (byte)mode.DepthBits; - pixelFormat.StencilBits = (byte)mode.StencilBits; - - if (mode.DepthBits <= 0) - { - pixelFormat.Flags |= PixelFormatDescriptorFlags.DEPTH_DONTCARE; - } - - if (mode.Stereo) - { - pixelFormat.Flags |= PixelFormatDescriptorFlags.STEREO; - } - - if (mode.Buffers > 1) - { - pixelFormat.Flags |= PixelFormatDescriptorFlags.DOUBLEBUFFER; - } - - // TODO: More elaborate mode setting, using DescribePixelFormat. - /* - unsafe - { - int pixel = Wgl.Imports.ChoosePixelFormat(deviceContext, &pixelFormat); - - if (pixel == 0) - { - throw new ApplicationException("The requested pixel format is not supported by the hardware configuration."); - } - - Wgl.Imports.SetPixelFormat(deviceContext, pixel, &pixelFormat); - - Debug.WriteLine(String.Format("done! (format: {0})", pixel)); - } - */ - int pixel = Functions.ChoosePixelFormat(deviceContext, ref pixelFormat); - if (pixel == 0) - { - Debug.Print("format not available..."); - return false; - } - Functions.SetPixelFormat(deviceContext, pixel, ref pixelFormat); - - Debug.Print("done! (format: {0})", pixel); - - return true; - } - - #endregion - - void IGLContextCreationHack.SetWindowHandle(IntPtr handle) - { - this.windowInfo.Handle = handle; - } - #endregion #region --- Internal Methods --- - #region internal IntPtr Device + #region internal IntPtr DeviceContext + + internal IntPtr DeviceContext + { + get + { + if (currentWindow != null) + return currentWindow.DeviceContext; + return IntPtr.Zero; + } + } - internal IntPtr Device { get { return deviceContext; } } #endregion @@ -544,14 +397,14 @@ namespace OpenTK.Platform.Windows renderContext = null; } - if (deviceContext != IntPtr.Zero) - { - if (!Functions.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()); - } - } + //if (deviceContext != IntPtr.Zero) + //{ + // if (!Functions.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()); + // } + //} /* if (opengl32Handle != IntPtr.Zero) diff --git a/Source/OpenTK/Platform/Windows/WinGLControlHelper.cs b/Source/OpenTK/Platform/Windows/WinGLControlHelper.cs index d03efcab..23300425 100644 --- a/Source/OpenTK/Platform/Windows/WinGLControlHelper.cs +++ b/Source/OpenTK/Platform/Windows/WinGLControlHelper.cs @@ -14,17 +14,17 @@ using System.Windows.Forms; namespace OpenTK.Platform.Windows { /// - /// OpenGL capable Windows.Forms control implementation on win32. + /// Utility to obtain IWindowInfo from a System.Windows.Forms.Control on win32. internal sealed class WinGLControlHelper : IGLControlHelper { MSG msg = new MSG(); - WinWindowInfo windowInfo; + Control control; #region --- Constructors --- - internal WinGLControlHelper(Control c) + public WinGLControlHelper(Control c) { - windowInfo = new WinWindowInfo(c.Handle, null); + control = c; } #endregion @@ -32,7 +32,7 @@ namespace OpenTK.Platform.Windows #region --- IGLControlHelper Members --- /// Returns an OpenTK.Platform.IWindowInfo describing this control. - public IWindowInfo WindowInfo { get { return windowInfo; } } + public IWindowInfo WindowInfo { get { return new WinWindowInfo(control.Handle, null); } } /// Returns true if no messages are pending in the event loop. public bool IsIdle diff --git a/Source/OpenTK/Platform/Windows/WinGLNative.cs b/Source/OpenTK/Platform/Windows/WinGLNative.cs index 87fed5f6..7162299e 100644 --- a/Source/OpenTK/Platform/Windows/WinGLNative.cs +++ b/Source/OpenTK/Platform/Windows/WinGLNative.cs @@ -254,19 +254,19 @@ namespace OpenTK.Platform.Windows get { StringBuilder title = new StringBuilder(256); - Functions.GetWindowText(window.Handle, title, title.Capacity); + Functions.GetWindowText(window.WindowHandle, title, title.Capacity); return title.ToString(); } set { #if DEBUG - bool ret = Functions.SetWindowText(window.Handle, value); + bool ret = Functions.SetWindowText(window.WindowHandle, value); if (ret) - Debug.Print("Window {0} title changed to {1}.", window.Handle, value); + Debug.Print("Window {0} title changed to {1}.", window.WindowHandle, value); else - Debug.Print("Window {0} title failed to change to {1}.", window.Handle, value); + Debug.Print("Window {0} title failed to change to {1}.", window.WindowHandle, value); #else - Functions.SetWindowText(window.Handle, value); + Functions.SetWindowText(window.WindowHandle, value); #endif } } diff --git a/Source/OpenTK/Platform/Windows/WinRawInput.cs b/Source/OpenTK/Platform/Windows/WinRawInput.cs index 9a2d38a8..823c9fcb 100644 --- a/Source/OpenTK/Platform/Windows/WinRawInput.cs +++ b/Source/OpenTK/Platform/Windows/WinRawInput.cs @@ -40,7 +40,7 @@ namespace OpenTK.Platform.Windows Debug.WriteLine("Initalizing windows raw input driver."); Debug.Indent(); - AssignHandle(parent.Handle); + AssignHandle(parent.WindowHandle); Debug.Print("Input window attached to parent {0}", parent); keyboardDriver = new WinRawKeyboard(this.Handle); mouseDriver = new WinRawMouse(this.Handle); diff --git a/Source/OpenTK/Platform/Windows/WinWindowInfo.cs b/Source/OpenTK/Platform/Windows/WinWindowInfo.cs index 316a62cb..a39445b7 100644 --- a/Source/OpenTK/Platform/Windows/WinWindowInfo.cs +++ b/Source/OpenTK/Platform/Windows/WinWindowInfo.cs @@ -8,8 +8,9 @@ namespace OpenTK.Platform.Windows /// Describes a win32 window. internal sealed class WinWindowInfo : IWindowInfo { - IntPtr handle; + IntPtr handle, dc; WinWindowInfo parent; + bool disposed; #region --- Constructors --- @@ -25,10 +26,20 @@ namespace OpenTK.Platform.Windows #endregion - #region --- Methods --- + #region --- Public Methods --- - internal IntPtr Handle { get { return handle; } set { handle = value; } } - internal WinWindowInfo Parent { get { return parent; } set { parent = value; } } + public IntPtr WindowHandle { get { return handle; } set { handle = value; } } + public WinWindowInfo Parent { get { return parent; } set { parent = value; } } + public IntPtr DeviceContext + { + get + { + if (dc == IntPtr.Zero) + dc = Functions.GetDC(this.WindowHandle); + return dc; + } + //set { dc = value; } + } #region public override string ToString() @@ -37,7 +48,7 @@ namespace OpenTK.Platform.Windows public override string ToString() { return String.Format("Windows.WindowInfo: Handle {0}, Parent ({1})", - this.Handle, this.Parent != null ? this.Parent.ToString() : "null"); + this.WindowHandle, this.Parent != null ? this.Parent.ToString() : "null"); } /// Checks if this and obj reference the same win32 window. @@ -64,5 +75,50 @@ namespace OpenTK.Platform.Windows #endregion #endregion + + #region --- IDisposable --- + + #region public void Dispose() + + /// Releases the unmanaged resources consumed by this instance. + public void Dispose() + { + this.Dispose(true); + GC.SuppressFinalize(this); + } + + #endregion + + #region void Dispose(bool manual) + + void Dispose(bool manual) + { + if (!disposed) + { + if (this.dc != IntPtr.Zero) + Functions.ReleaseDC(this.handle, this.dc); + + if (manual) + { + if (parent != null) + parent.Dispose(); + } + + disposed = true; + } + } + + #endregion + + #region ~WinWindowInfo() + + ~WinWindowInfo() + { + this.Dispose(false); + } + + #endregion + + #endregion } } diff --git a/Source/OpenTK/Platform/X11/API.cs b/Source/OpenTK/Platform/X11/API.cs index de0fcad4..41a7ddec 100644 --- a/Source/OpenTK/Platform/X11/API.cs +++ b/Source/OpenTK/Platform/X11/API.cs @@ -1189,19 +1189,20 @@ XF86VidModeGetGammaRampSize( DirectColor = 5, } + [Flags] public enum XVisualInfoMask { - VisualNoMask = 0x0, - VisualIDMask = 0x1, - VisualScreenMask = 0x2, - VisualDepthMask = 0x4, - VisualClassMask = 0x8, - VisualRedMaskMask = 0x10, - VisualGreenMaskMask = 0x20, - VisualBlueMaskMask = 0x40, - VisualColormapSizeMask = 0x80, - VisualBitsPerRGBMask = 0x100, - VisualAllMask = 0x1FF, + No = 0x0, + ID = 0x1, + Screen = 0x2, + Depth = 0x4, + Class = 0x8, + Red = 0x10, + Green = 0x20, + Blue = 0x40, + ColormapSize = 0x80, + BitsPerRGB = 0x100, + All = 0x1FF, } #region public enum MouseMask diff --git a/Source/OpenTK/Platform/X11/Functions.cs b/Source/OpenTK/Platform/X11/Functions.cs index 45222b75..3ea8ec2c 100644 --- a/Source/OpenTK/Platform/X11/Functions.cs +++ b/Source/OpenTK/Platform/X11/Functions.cs @@ -1,4 +1,12 @@ -using System; +#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 System.Runtime.InteropServices; @@ -7,6 +15,8 @@ namespace OpenTK.Platform.X11 { internal static partial class Functions { + public static readonly object Lock = new object(); + [DllImport("libX11", EntryPoint = "XOpenDisplay")] public extern static IntPtr XOpenDisplay(IntPtr display); [DllImport("libX11", EntryPoint = "XCloseDisplay")] @@ -326,8 +336,14 @@ namespace OpenTK.Platform.X11 [DllImport("libX11")] public extern static void XPeekEvent(IntPtr display, ref XEvent xevent); - [DllImport("libX11")] - public static extern IntPtr XGetVisualInfo(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo vinfo_template, - out int nitems_return); + [DllImport("libX11", EntryPoint = "XGetVisualInfo")] + static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, + out int nitems); + + + public static IntPtr XGetVisualInfo(IntPtr display, XVisualInfoMask vinfo_mask, ref XVisualInfo template, out int nitems) + { + return XGetVisualInfoInternal(display, (IntPtr)(int)vinfo_mask, ref template, out nitems); + } } } diff --git a/Source/OpenTK/Platform/X11/Glx.cs b/Source/OpenTK/Platform/X11/Glx.cs index 90e146ce..4b36afb2 100644 --- a/Source/OpenTK/Platform/X11/Glx.cs +++ b/Source/OpenTK/Platform/X11/Glx.cs @@ -295,24 +295,27 @@ namespace OpenTK.Platform.X11 [DllImport(Library, EntryPoint = "glXGetProcAddress")] public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName); + [DllImport(Library, EntryPoint = "glXGetConfig")] + public static extern int GetConfig(IntPtr dpy, ref XVisualInfo vis, GLXAttribute attrib, out int value); + #region glXChooseVisual [DllImport(Library, EntryPoint = "glXChooseVisual")] public extern static IntPtr ChooseVisual(IntPtr dpy, int screen, IntPtr attriblist); [DllImport(Library, EntryPoint = "glXChooseVisual")] - public extern static IntPtr ChooseVisual(IntPtr dpy, int screen, int[] attriblist); + public extern static IntPtr ChooseVisual(IntPtr dpy, int screen, ref int attriblist); - //public static IntPtr ChooseVisual(IntPtr dpy, int screen, int[] attriblist) - //{ - // unsafe - // { - // fixed (int* attriblist_ptr = attriblist) - // { - // return ChooseVisual(dpy, screen, (IntPtr)attriblist_ptr); - // } - // } - //} + public static IntPtr ChooseVisual(IntPtr dpy, int screen, int[] attriblist) + { + unsafe + { + fixed (int* attriblist_ptr = attriblist) + { + return ChooseVisual(dpy, screen, (IntPtr)attriblist_ptr); + } + } + } #endregion diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index 1352b3fd..d2a31791 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -22,8 +22,9 @@ namespace OpenTK.Platform.X11 internal sealed class X11GLContext : IGraphicsContext, IGraphicsContextInternal { IntPtr context; - X11WindowInfo window; - IntPtr visual; + //X11WindowInfo window; + X11WindowInfo currentWindow; + //IntPtr visual; bool vsync_supported; int vsync_interval; @@ -43,122 +44,68 @@ namespace OpenTK.Platform.X11 //if (mode == null) mode = GraphicsMode.Default; if (info == null) throw new ArgumentNullException("info", "Should point to a valid window."); - window = (X11WindowInfo)info; - window.VisualInfo = SelectVisual(mode); + currentWindow = (X11WindowInfo)info; + currentWindow.VisualInfo = SelectVisual(mode, currentWindow); - Debug.Print("Chose visual: {0}", window.VisualInfo); - - CreateContext(shared, directRendering); + Debug.Print("Chose visual: {0}", currentWindow.VisualInfo); + + CreateContext(shared, directRendering, currentWindow); } #endregion #region --- Private Methods --- - #region XVisualInfo SelectVisual(GraphicsMode mode) + #region XVisualInfo SelectVisual(GraphicsMode mode, X11WindowInfo currentWindow) - XVisualInfo SelectVisual(GraphicsMode mode) + XVisualInfo SelectVisual(GraphicsMode mode, X11WindowInfo currentWindow) { - List visualAttributes = new List(); + XVisualInfo info = new XVisualInfo(); + info.visualid = (IntPtr)mode.Index; + info.screen = currentWindow.Screen; + int items; + IntPtr vs = Functions.XGetVisualInfo(currentWindow.Display, XVisualInfoMask.ID | XVisualInfoMask.Screen, ref info, out items); + if (items == 0) + throw new GraphicsModeException(String.Format("Invalid GraphicsMode specified ({0}).", mode)); - // TODO: Improve modesetting code. - if (mode == null || mode.ColorDepth.BitsPerPixel == 0) - { - // Define the bare essentials - needed for compatibility with Mono's System.Windows.Forms - Debug.Print("Mono/X11 compatibility mode."); - - visualAttributes.Add((int)GLXAttribute.RGBA); - //visualAttributes.Add((int)GLXAttribute.RED_SIZE); - //visualAttributes.Add((int)1); - //visualAttributes.Add((int)GLXAttribute.GREEN_SIZE); - //visualAttributes.Add((int)1); - //visualAttributes.Add((int)GLXAttribute.BLUE_SIZE); - //visualAttributes.Add((int)1); - visualAttributes.Add((int)GLXAttribute.DEPTH_SIZE); - visualAttributes.Add((int)1); - } - else - { - visualAttributes.Add((int)GLXAttribute.RGBA); - visualAttributes.Add((int)GLXAttribute.RED_SIZE); - visualAttributes.Add((int)mode.ColorDepth.Red); - visualAttributes.Add((int)GLXAttribute.GREEN_SIZE); - visualAttributes.Add((int)mode.ColorDepth.Green); - visualAttributes.Add((int)GLXAttribute.BLUE_SIZE); - visualAttributes.Add((int)mode.ColorDepth.Blue); - visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); - visualAttributes.Add((int)mode.ColorDepth.Alpha); - visualAttributes.Add((int)GLXAttribute.DEPTH_SIZE); - visualAttributes.Add((int)mode.Depth); - } - - if (mode.Buffers > 1) - visualAttributes.Add((int)GLXAttribute.DOUBLEBUFFER); - if (mode.Stencil > 1) - { - visualAttributes.Add((int)GLXAttribute.STENCIL_SIZE); - visualAttributes.Add(mode.Stencil); - } - if (mode.AccumulatorFormat.BitsPerPixel > 0) - { - visualAttributes.Add((int)GLXAttribute.ACCUM_ALPHA_SIZE); - visualAttributes.Add(mode.AccumulatorFormat.Alpha); - visualAttributes.Add((int)GLXAttribute.ACCUM_BLUE_SIZE); - visualAttributes.Add(mode.AccumulatorFormat.Blue); - visualAttributes.Add((int)GLXAttribute.ACCUM_GREEN_SIZE); - visualAttributes.Add(mode.AccumulatorFormat.Green); - visualAttributes.Add((int)GLXAttribute.ACCUM_RED_SIZE); - visualAttributes.Add(mode.AccumulatorFormat.Red); - } - if (mode.Stereo) - visualAttributes.Add((int)GLXAttribute.STEREO); - - visualAttributes.Add((int)0); - - visual = Glx.ChooseVisual(window.Display, window.Screen, visualAttributes.ToArray()); - - if (visual == IntPtr.Zero) - throw new GraphicsContextException(String.Format("Failed to set requested mode: {0}.", mode.ToString())); - - return (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo)); + info = (XVisualInfo)Marshal.PtrToStructure(vs, typeof(XVisualInfo)); + Functions.XFree(vs); + return info; } #endregion #region void CreateContext(IGraphicsContext shareContext, bool direct) - void CreateContext(IGraphicsContext shareContext, bool direct) + void CreateContext(IGraphicsContext shareContext, bool direct, X11WindowInfo window) { try { - ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero; + ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : + (ContextHandle)IntPtr.Zero; Debug.Write("Creating OpenGL context: "); Debug.Write(direct ? "direct, " : "indirect, "); Debug.Write(shareHandle.Handle == IntPtr.Zero ? "not shared... " : String.Format("shared with ({0})... ", shareHandle)); - // Try to call Glx.CreateContext with the specified parameters. - context = Glx.CreateContext(window.Display, visual, shareHandle.Handle, direct); + XVisualInfo info = window.VisualInfo; // Cannot pass a Property by reference. + context = Glx.CreateContext(window.Display, ref info, shareHandle.Handle, direct); // Context creation succeeded, return. if (context != IntPtr.Zero) { Debug.Print("done! (id: {0})", context); - - //this.MakeCurrent(); return; } - // Context creation failed. Retry with a non-shared context with the - // direct/indirect rendering mode flipped. + + // Context creation failed. Retry with a non-shared context with the direct/indirect bit flipped. Debug.Print("failed."); Debug.Write(String.Format("Creating OpenGL context: {0}, not shared... ", !direct ? "direct" : "indirect")); - context = Glx.CreateContext(window.Display, visual, IntPtr.Zero, !direct); + context = Glx.CreateContext(window.Display, ref info, IntPtr.Zero, !direct); if (context != IntPtr.Zero) { Debug.Print("done! (id: {0})", context); - - //this.MakeCurrent(); return; } @@ -173,7 +120,7 @@ namespace OpenTK.Platform.X11 #endregion - bool SupportsExtension(string e) + bool SupportsExtension(X11WindowInfo window, string e) { string extensions = Glx.QueryExtensionsString(window.Display, window.Screen); return !String.IsNullOrEmpty(extensions) && extensions.Contains(e); @@ -187,35 +134,35 @@ namespace OpenTK.Platform.X11 public void SwapBuffers() { - Glx.SwapBuffers(window.Display, window.Handle); + //if (window == null) throw new ArgumentNullException("window", "Must point to a valid window."); + //X11WindowInfo w = (X11WindowInfo)window; + if (currentWindow.Display == IntPtr.Zero || currentWindow.WindowHandle == IntPtr.Zero) + throw new InvalidOperationException( + String.Format("Window is invalid. Display ({0}), Handle ({1}).", currentWindow.Display, currentWindow.WindowHandle)); + Glx.SwapBuffers(currentWindow.Display, currentWindow.WindowHandle); } #endregion - #region public void MakeCurrent() + #region public void MakeCurrent(IWindowInfo window) - bool result; - public void MakeCurrent() + public void MakeCurrent(IWindowInfo window) { - Debug.Write(String.Format("Making context {0} current on thread {1} (Display: {2}, Screen: {3}, Window: {4})... ", - context, System.Threading.Thread.CurrentThread.ManagedThreadId, window.Display, window.Screen, window.Handle)); + X11WindowInfo w = (X11WindowInfo)window; + bool result; - if (window.Display != IntPtr.Zero && window.Handle != IntPtr.Zero && context != IntPtr.Zero) - { - result = Glx.MakeCurrent(window.Display, window.Handle, context); - - if (!result) - { - Debug.WriteLine("failed."); - // probably need to recreate context here. - //throw new ApplicationException(String.Format("Failed to make context {0} current on thread {1}.", - // context, System.Threading.Thread.CurrentThread.ManagedThreadId)); - } - else - { - Debug.WriteLine("done!"); - } - } + Debug.Write(String.Format("Making context {0} current on thread {1} (Display: {2}, Screen: {3}, Window: {4})... ", + context, System.Threading.Thread.CurrentThread.ManagedThreadId, w.Display, w.Screen, w.WindowHandle)); + + if (w.Display == IntPtr.Zero || w.WindowHandle == IntPtr.Zero || context == IntPtr.Zero) + throw new InvalidOperationException("Invalid display, window or context."); + + result = Glx.MakeCurrent(w.Display, w.WindowHandle, context); + + if (!result) + throw new GraphicsContextException("Failed to make context current."); + else + Debug.WriteLine("done!"); } #endregion @@ -225,13 +172,13 @@ namespace OpenTK.Platform.X11 public bool IsCurrent { get { return Glx.GetCurrentContext() == this.context; } - set - { - if (value) - Glx.MakeCurrent(window.Display, window.Handle, context); - else - Glx.MakeCurrent(window.Handle, IntPtr.Zero, IntPtr.Zero); - } + //set + //{ + // if (value) + // Glx.MakeCurrent(window.Display, window.Handle, context); + // else + // Glx.MakeCurrent(window.Handle, IntPtr.Zero, IntPtr.Zero); + //} } #endregion @@ -295,7 +242,8 @@ namespace OpenTK.Platform.X11 GL.LoadAll(); Glu.LoadAll(); Glx.LoadAll(); - vsync_supported = this.SupportsExtension("SGI_swap_control") && this.GetAddress("glXSwapControlSGI") != IntPtr.Zero; + vsync_supported = this.SupportsExtension(currentWindow, "SGI_swap_control") && + this.GetAddress("glXSwapControlSGI") != IntPtr.Zero; } #endregion @@ -321,7 +269,7 @@ namespace OpenTK.Platform.X11 #region IWindowInfo IGLContextInternal.Info - IWindowInfo IGraphicsContextInternal.Info { get { return window; } } + //IWindowInfo IGraphicsContextInternal.Info { get { return window; } } #endregion @@ -359,9 +307,10 @@ namespace OpenTK.Platform.X11 if (!disposed) { // Clean unmanaged resources: - Glx.MakeCurrent(window.Display, IntPtr.Zero, IntPtr.Zero); - Glx.DestroyContext(window.Display, context); - API.Free(visual); + + Glx.MakeCurrent(currentWindow.Display, IntPtr.Zero, IntPtr.Zero); + Glx.DestroyContext(currentWindow.Display, context); + //API.Free(visual); if (manuallyCalled) { diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index e567687e..c73f0b23 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -82,13 +82,23 @@ namespace OpenTK.Platform.X11 //Utilities.ThrowOnX11Error = true; // Not very reliable - // Open the display to the X server, and obtain the screen and root window. - window.Display = API.OpenDisplay(null); // null == default display //window.Display = API.DefaultDisplay; - if (window.Display == IntPtr.Zero) - throw new Exception("Could not open connection to X"); + // We reuse the display connection of System.Windows.Forms. + // TODO: Multiple screens. + Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); + window.Display = (IntPtr)xplatui.GetField("DisplayHandle", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + window.RootWindow = (IntPtr)xplatui.GetField("RootWindow", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + window.Screen = (int)xplatui.GetField("ScreenNo", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); - window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen; - window.RootWindow = Functions.XRootWindow(window.Display, window.Screen); // API.RootWindow; + // Open the display to the X server, and obtain the screen and root window. + //window.Display = API.OpenDisplay(null); // null == default display //window.Display = API.DefaultDisplay; + //if (window.Display == IntPtr.Zero) + // throw new Exception("Could not open connection to X"); + + //window.Screen = Functions.XDefaultScreen(window.Display); //API.DefaultScreen; + //window.RootWindow = Functions.XRootWindow(window.Display, window.Screen); // API.RootWindow; Debug.Print("Display: {0}, Screen {1}, Root window: {2}", window.Display, window.Screen, window.RootWindow); RegisterAtoms(window); @@ -136,8 +146,11 @@ namespace OpenTK.Platform.X11 Debug.Indent(); - // Create the context. This call also creates an XVisualInfo structure for us. - context = new GraphicsContext(mode, window); + XVisualInfo info = new XVisualInfo(); + info.visualid = mode.Index; + int dummy; + window.VisualInfo = (XVisualInfo)Marshal.PtrToStructure( + Functions.XGetVisualInfo(window.Display, XVisualInfoMask.ID, ref info, out dummy), typeof(XVisualInfo)); // Create a window on this display using the visual above Debug.Write("Opening render window... "); @@ -157,15 +170,17 @@ namespace OpenTK.Platform.X11 uint mask = (uint)SetWindowValuemask.ColorMap | (uint)SetWindowValuemask.EventMask | (uint)SetWindowValuemask.BackPixel | (uint)SetWindowValuemask.BorderPixel; - window.Handle = Functions.XCreateWindow(window.Display, window.RootWindow, + window.WindowHandle = Functions.XCreateWindow(window.Display, window.RootWindow, 0, 0, width, height, 0, window.VisualInfo.depth/*(int)CreateWindowArgs.CopyFromParent*/, (int)CreateWindowArgs.InputOutput, window.VisualInfo.visual, (UIntPtr)mask, ref attributes); - if (window.Handle == IntPtr.Zero) + if (window.WindowHandle == IntPtr.Zero) throw new ApplicationException("XCreateWindow call failed (returned 0)."); - XVisualInfo vis = window.VisualInfo; - Glx.CreateContext(window.Display, ref vis, IntPtr.Zero, true); + //XVisualInfo vis = window.VisualInfo; + //Glx.CreateContext(window.Display, ref vis, IntPtr.Zero, true); + + context = new GraphicsContext(mode, window); // Set the window hints XSizeHints hints = new XSizeHints(); @@ -174,12 +189,12 @@ namespace OpenTK.Platform.X11 hints.width = width; hints.height = height; hints.flags = (IntPtr)(XSizeHintsFlags.USSize | XSizeHintsFlags.USPosition); - Functions.XSetWMNormalHints(window.Display, window.Handle, ref hints); + Functions.XSetWMNormalHints(window.Display, window.WindowHandle, ref hints); // Register for window destroy notification IntPtr wm_destroy_atom = Functions.XInternAtom(window.Display, "WM_DELETE_WINDOW", true); //XWMHints hint = new XWMHints(); - Functions.XSetWMProtocols(window.Display, window.Handle, new IntPtr[] { wm_destroy_atom }, 1); + Functions.XSetWMProtocols(window.Display, window.WindowHandle, new IntPtr[] { wm_destroy_atom }, 1); Top = Left = 0; Right = Width; @@ -191,11 +206,11 @@ namespace OpenTK.Platform.X11 //Functions.XSetWMName(window.Display, window.Handle, ref text); //Functions.XSetWMProperties(display, window, name, name, 0, /*None*/ null, 0, hints); - Debug.Print("done! (id: {0})", window.Handle); + Debug.Print("done! (id: {0})", window.WindowHandle); //(glContext as IGLContextCreationHack).SetWindowHandle(window.Handle); - API.MapRaised(window.Display, window.Handle); + API.MapRaised(window.Display, window.WindowHandle); mapped = true; //context.CreateContext(true, null); @@ -245,6 +260,7 @@ namespace OpenTK.Platform.X11 exists = false; isExiting = true; Debug.Print("X11 window {0} destroyed.", e.DestroyWindowEvent.window); + window.WindowHandle = IntPtr.Zero; return; case XEventName.ConfigureNotify: @@ -384,7 +400,7 @@ namespace OpenTK.Platform.X11 /// public IntPtr Handle { - get { return this.window.Handle; } + get { return this.window.WindowHandle; } } #endregion @@ -400,7 +416,7 @@ namespace OpenTK.Platform.X11 get { IntPtr name = IntPtr.Zero; - Functions.XFetchName(window.Display, window.Handle, ref name); + Functions.XFetchName(window.Display, window.WindowHandle, ref name); if (name != IntPtr.Zero) return Marshal.PtrToStringAnsi(name); @@ -419,7 +435,7 @@ namespace OpenTK.Platform.X11 Functions.XSetWMName(window.Display, window.Handle, ref name); */ if (value != null) - Functions.XStoreName(window.Display, window.Handle, value); + Functions.XStoreName(window.Display, window.WindowHandle, value); } } @@ -439,12 +455,12 @@ namespace OpenTK.Platform.X11 { if (value && !mapped) { - Functions.XMapWindow(window.Display, window.Handle); + Functions.XMapWindow(window.Display, window.WindowHandle); mapped = true; } else if (!value && mapped) { - Functions.XUnmapWindow(window.Display, window.Handle); + Functions.XUnmapWindow(window.Display, window.WindowHandle); mapped = false; } } @@ -490,7 +506,7 @@ namespace OpenTK.Platform.X11 public void DestroyWindow() { Debug.WriteLine("X11GLNative shutdown sequence initiated."); - Functions.XDestroyWindow(window.Display, window.Handle); + Functions.XDestroyWindow(window.Display, window.WindowHandle); } #endregion @@ -647,19 +663,13 @@ namespace OpenTK.Platform.X11 { if (!disposed) { + //Functions.XUnmapWindow(window.Display, window.WindowHandle); + if (window.WindowHandle != IntPtr.Zero) + Functions.XDestroyWindow(window.Display, window.WindowHandle); + if (manuallyCalled) { - //if (glContext != null) - // glContext.Dispose(); - - // Kills connection to the X-Server. We don't want that, - // 'cause it kills the ExampleLauncher too. - //Functions.XCloseDisplay(window.Display); } - - Functions.XUnmapWindow(window.Display, window.Handle); - Functions.XDestroyWindow(window.Display, window.Handle); - disposed = true; } } diff --git a/Source/OpenTK/Platform/X11/X11WindowInfo.cs b/Source/OpenTK/Platform/X11/X11WindowInfo.cs index 11da2b38..d52eff74 100644 --- a/Source/OpenTK/Platform/X11/X11WindowInfo.cs +++ b/Source/OpenTK/Platform/X11/X11WindowInfo.cs @@ -46,10 +46,10 @@ namespace OpenTK.Platform.X11 #endregion - #region --- Methods --- + #region --- Public Methods --- /// Gets or sets the handle of the window. - public IntPtr Handle { get { return handle; } set { handle = value; } } + public IntPtr WindowHandle { get { return handle; } set { handle = value; } } /// Gets or sets the parent of the window. public X11WindowInfo Parent { get { return parent; } set { parent = value; } } /// Gets or sets the X11 root window. @@ -64,14 +64,29 @@ namespace OpenTK.Platform.X11 public EventMask EventMask { get { return eventMask; } set { eventMask = value; } } //public IntPtr TopLevelWindow { get { return topLevelWindow; } set { topLevelWindow = value; } } + #endregion + + #region --- IDisposable Members --- + + public void Dispose() + { + } + + #endregion + + #region --- Overrides --- + + #region public override string ToString() + /// Returns a System.String that represents the current window. /// A System.String that represents the current window. public override string ToString() { return String.Format("X11.WindowInfo: Display {0}, Screen {1}, Handle {2}, Parent: ({3})", - this.Display, this.Screen, this.Handle, this.Parent != null ? this.Parent.ToString() : "null"); + this.Display, this.Screen, this.WindowHandle, this.Parent != null ? this.Parent.ToString() : "null"); } - #region public override string ToString() + + #endregion /// Checks if this and obj reference the same win32 window. /// The object to check against. @@ -97,6 +112,5 @@ namespace OpenTK.Platform.X11 #endregion - #endregion } }