diff --git a/GLWidget/GLWidget.cs b/GLWidget/GLWidget.cs
index 175b6e1..440f425 100644
--- a/GLWidget/GLWidget.cs
+++ b/GLWidget/GLWidget.cs
@@ -35,437 +35,535 @@ using System.ComponentModel;
using OpenTK.Graphics;
-using OpenTK.Graphics.OpenGL;
-
+using OpenTK.Platform;
using Gtk;
-using Cairo;
-using GLib;
-using Gdk;
-using OpenGL;
-using System.Diagnostics;
-using OpenTK.Mathematics;
namespace OpenTK
{
- [ToolboxItem(true)]
- public class GLWidget : DrawingArea
- {
- private static bool xThreadInit;
+ [ToolboxItem(true)]
+ public class GLWidget : DrawingArea
+ {
- ///
- /// Get or set the OpenGL minimum color buffer bits.
- ///
- [Property("color-bits")]
- public uint ColorBits
- {
- get { return (_ColorBits); }
- set { _ColorBits = value; }
- }
+ #region Static attrs.
- ///
- /// The OpenGL color buffer bits.
- ///
- private uint _ColorBits = 24;
+ private static int _graphicsContextCount;
+ private static bool _sharedContextInitialized;
- ///
- /// Get or set the OpenGL minimum depth buffer bits.
- ///
- [Property("depth-bits")]
- public uint DepthBits
- {
- get { return (_DepthBits); }
- set { _DepthBits = value; }
- }
-
- ///
- /// The OpenGL color buffer bits.
- ///
- private uint _DepthBits;
-
- ///
- /// Get or set the OpenGL minimum stencil buffer bits.
- ///
- [Property("stencil-bits")]
- public uint StencilBits
- {
- get { return (_StencilBits); }
- set { _StencilBits = value; }
- }
-
- ///
- /// The OpenGL color buffer bits.
- ///
- private uint _StencilBits;
-
- ///
- /// Get or set the OpenGL minimum multisample buffer "bits".
- ///
- [Property("multisample-bits")]
- public uint MultisampleBits
- {
- get { return (_MultisampleBits); }
- set { _MultisampleBits = value; }
- }
-
- ///
- /// The OpenGL multisample buffer bits.
- ///
- private uint _MultisampleBits;
-
- ///
- /// Get or set the OpenGL swap buffers interval.
- ///
- [Property("swap-interval")]
- public int SwapInterval
- {
- get { return (_SwapInterval); }
- set { _SwapInterval = value; }
- }
-
- ///
- /// The OpenGL swap buffers interval.
- ///
- private int _SwapInterval = 1;
-
- ///
- /// The describing the minimum pixel format required by this control.
- ///
- private DevicePixelFormat ControlPixelFormat
- {
- get
- {
- DevicePixelFormat controlReqFormat = new DevicePixelFormat();
-
- controlReqFormat.RgbaUnsigned = true;
- controlReqFormat.RenderWindow = true;
-
- controlReqFormat.ColorBits = (int)ColorBits;
- controlReqFormat.DepthBits = (int)DepthBits;
- controlReqFormat.StencilBits = (int)StencilBits;
- controlReqFormat.MultisampleBits = (int)MultisampleBits;
- controlReqFormat.DoubleBuffer = true;
-
- return (controlReqFormat);
- }
- }
-
-
-
- #region Static attrs.
- public bool HandleRendering { get; set; } = false;
+ public bool IsRenderHandler { get; set; } = false;
#endregion
#region Attributes
+ private IGraphicsContext _graphicsContext;
+ private IWindowInfo _windowInfo;
private bool _initialized;
- #endregion
+ #endregion
- #region Properties
+ #region Properties
- /// The major version of OpenGL to use.
- public int GLVersionMajor { get; set; }
+ /// Use a single buffer versus a double buffer.
+ [Browsable(true)]
+ public bool SingleBuffer { get; set; }
- /// The minor version of OpenGL to use.
- public int GLVersionMinor { get; set; }
+ /// Color Buffer Bits-Per-Pixel
+ public int ColorBPP { get; set; }
- private DeviceContext _deviceContext;
- private IntPtr _graphicsContext;
- private int _error;
+ /// Accumulation Buffer Bits-Per-Pixel
+ public int AccumulatorBPP { get; set; }
- private IGraphicsContext _context;
- private GLContext _gdkGlContext;
+ /// Depth Buffer Bits-Per-Pixel
+ public int DepthBPP { get; set; }
- public bool ForwardCompatible { get; }
- public DeviceContext DeviceContext { get => _deviceContext; set => _deviceContext = value; }
+ /// Stencil Buffer Bits-Per-Pixel
+ public int StencilBPP { get; set; }
+
+ /// Number of samples
+ public int Samples { get; set; }
+
+ /// Indicates if steropic renderering is enabled
+ public bool Stereo { get; set; }
+
+ /// The major version of OpenGL to use.
+ public int GLVersionMajor { get; set; }
+
+ /// The minor version of OpenGL to use.
+ public int GLVersionMinor { get; set; }
+
+ public GraphicsContextFlags GraphicsContextFlags
+ {
+ get;
+ set;
+ }
#endregion
#region Construction/Destruction
- /// Constructs a new GLWidget
- public GLWidget() : this(new Version(4, 0), true)
+ /// Constructs a new GLWidget.
+ public GLWidget()
+ : this(GraphicsMode.Default)
+ {
+ }
+
+ /// Constructs a new GLWidget using a given GraphicsMode
+ public GLWidget(GraphicsMode graphicsMode)
+ : this(graphicsMode, 1, 0, GraphicsContextFlags.Default)
{
- /*this.ColorBits = 32;
- this.DepthBits = 24;
- this.StencilBits = 8;*/
}
/// Constructs a new GLWidget
- public GLWidget(Version apiVersion, bool forwardCompatible)
- {
- GLVersionMajor = apiVersion.Major;
- GLVersionMinor = apiVersion.Minor;
- ForwardCompatible = forwardCompatible;
- }
+ public GLWidget(GraphicsMode graphicsMode, int glVersionMajor, int glVersionMinor, GraphicsContextFlags graphicsContextFlags)
+ {
+ SingleBuffer = graphicsMode.Buffers == 1;
+ ColorBPP = graphicsMode.ColorFormat.BitsPerPixel;
+ AccumulatorBPP = graphicsMode.AccumulatorFormat.BitsPerPixel;
+ DepthBPP = graphicsMode.Depth;
+ StencilBPP = graphicsMode.Stencil;
+ Samples = graphicsMode.Samples;
+ Stereo = graphicsMode.Stereo;
- ~GLWidget()
- {
- Dispose(false);
- }
-
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- OnShuttingDown();
+ GLVersionMajor = glVersionMajor;
+ GLVersionMinor = glVersionMinor;
+ GraphicsContextFlags = graphicsContextFlags;
+ }
- DeviceContext?.DeleteContext(_graphicsContext);
+ ~GLWidget()
+ {
+ Dispose(false);
+ }
- DeviceContext?.Dispose();
+ public void MakeCurrent()
+ {
+ GraphicsContext.MakeCurrent(_windowInfo);
+ }
- _gdkGlContext?.Dispose();
+ public void ClearCurrent()
+ {
+ GraphicsContext.MakeCurrent(null);
+ }
+
+ public void Swapbuffers()
+ {
+ GraphicsContext.SwapBuffers();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ try
+ {
+ GraphicsContext.MakeCurrent(WindowInfo);
+ }
+ catch (Exception ex)
+ {
+
+ }
+
+ OnShuttingDown();
+
+ if (OpenTK.Graphics.GraphicsContext.ShareContexts && (Interlocked.Decrement(ref _graphicsContextCount) == 0))
+ {
+ OnGraphicsContextShuttingDown();
+ _sharedContextInitialized = false;
+ }
+
+ GraphicsContext.Dispose();
}
- }
+ }
- #endregion
+ #endregion
- #region New Events
+ #region New Events
- // Called when the first GraphicsContext is created in the case of GraphicsContext.ShareContexts == True;
- public static event EventHandler GraphicsContextInitialized;
+ // Called when the first GraphicsContext is created in the case of GraphicsContext.ShareContexts == True;
+ public static event EventHandler GraphicsContextInitialized;
+
+ private static void OnGraphicsContextInitialized()
+ {
+ if (GraphicsContextInitialized != null)
+ {
+ GraphicsContextInitialized(null, EventArgs.Empty);
+ }
+ }
// Called when the first GraphicsContext is being destroyed in the case of GraphicsContext.ShareContexts == True;
public static event EventHandler GraphicsContextShuttingDown;
+ private static void OnGraphicsContextShuttingDown()
+ {
+ if (GraphicsContextShuttingDown != null)
+ {
+ GraphicsContextShuttingDown(null, EventArgs.Empty);
+ }
+ }
+
// Called when this GLWidget has a valid GraphicsContext
public event EventHandler Initialized;
- protected virtual void OnInitialized()
- {
- if (Initialized != null)
- {
- Initialized(this, EventArgs.Empty);
- }
- }
-
- // Called when this GLWidget needs to render a frame
- public event EventHandler RenderFrame;
-
- protected virtual void OnRenderFrame()
- {
- RenderFrame?.Invoke(this, EventArgs.Empty);
+ protected virtual void OnInitialized()
+ {
+ if (Initialized != null)
+ {
+ Initialized(this, EventArgs.Empty);
+ }
}
- // Called when this GLWidget is being Disposed
- public event EventHandler ShuttingDown;
+ // Called when this GLWidget needs to render a frame
+ public event EventHandler RenderFrame;
- protected virtual void OnShuttingDown()
- {
- if (ShuttingDown != null)
- {
- ShuttingDown(this, EventArgs.Empty);
- }
- }
+ protected virtual void OnRenderFrame()
+ {
+ if (RenderFrame != null)
+ {
+ RenderFrame(this, EventArgs.Empty);
+ }
+ }
- #endregion
+ // Called when this GLWidget is being Disposed
+ public event EventHandler ShuttingDown;
- // Called when the widget needs to be (fully or partially) redrawn.
+ protected virtual void OnShuttingDown()
+ {
+ if (ShuttingDown != null)
+ {
+ ShuttingDown(this, EventArgs.Empty);
+ }
+ }
- protected override bool OnDrawn(Cairo.Context cr)
- {
- if (!_initialized)
- Initialize();
+ #endregion
- ClearCurrent();
+ // Called when a widget is realized. (window handles and such are valid)
+ // protected override void OnRealized() { base.OnRealized(); }
+
+ // Called when the widget needs to be (fully or partially) redrawn.
+
+ protected override bool OnDrawn(Cairo.Context cr)
+ {
+ if (!_initialized)
+ Initialize();
+ else if (!IsRenderHandler)
+ GraphicsContext.MakeCurrent(WindowInfo);
return true;
- }
-
- public void Swapbuffers()
- {
- _context?.SwapBuffers();
}
- public void MakeCurrent()
- {
- ClearCurrent();
-
- _context?.MakeCurrent();
-
- _error = Marshal.GetLastWin32Error();
- }
-
- public void ClearCurrent()
- {
- if (GTKBindingHelper.CurrentPlatform == OSPlatform.Windows)
- {
- DeviceContext?.MakeCurrent(IntPtr.Zero);
- }
- else
- {
- Gdk.GLContext.ClearCurrent();
- }
- }
-
- private void CreateContext()
- {
- if (_graphicsContext != IntPtr.Zero)
- throw new InvalidOperationException("context already created");
-
- IntPtr sharingContext = IntPtr.Zero;
-
- if (Gl.PlatformExtensions.CreateContext_ARB)
- {
- List attributes = new List();
- uint contextProfile = 0, contextFlags = 0;
- bool debuggerAttached = Debugger.IsAttached;
-
- #region WGL_ARB_create_context|GLX_ARB_create_context
-
- #endregion
-
- #region WGL_ARB_create_context_profile|GLX_ARB_create_context_profile
-
- if (Gl.PlatformExtensions.CreateContextProfile_ARB)
- {
-
- }
-
- #endregion
-
- #region WGL_ARB_create_context_robustness|GLX_ARB_create_context_robustness
-
- if (Gl.PlatformExtensions.CreateContextRobustness_ARB)
- {
-
- }
-
- #endregion
-
- Debug.Assert(Wgl.CONTEXT_FLAGS_ARB == Glx.CONTEXT_FLAGS_ARB);
- if (contextFlags != 0)
- attributes.AddRange(new int[] { Wgl.CONTEXT_FLAGS_ARB, unchecked((int)contextFlags) });
-
- Debug.Assert(Wgl.CONTEXT_PROFILE_MASK_ARB == Glx.CONTEXT_PROFILE_MASK_ARB);
- Debug.Assert(contextProfile == 0 || Gl.PlatformExtensions.CreateContextProfile_ARB);
- if (contextProfile != 0)
- attributes.AddRange(new int[] { Wgl.CONTEXT_PROFILE_MASK_ARB, unchecked((int)contextProfile) });
-
- attributes.Add(0);
-
- if ((_graphicsContext = _deviceContext.CreateContextAttrib(sharingContext, attributes.ToArray())) == IntPtr.Zero)
- throw new InvalidOperationException(String.Format("unable to create render context ({0})", Gl.GetError()));
- }
- else
- {
- // Create OpenGL context using compatibility profile
- if ((_graphicsContext = _deviceContext.CreateContext(sharingContext)) == IntPtr.Zero)
- throw new InvalidOperationException("unable to create render context");
- }
- }
-
- private void CreateDeviceContext(DevicePixelFormat controlReqFormat)
- {
- #region Create device context
-
- DeviceContext = DeviceContext.Create(GTKBindingHelper.GetDisplayHandle(Display.Handle), GTKBindingHelper.GetWindowHandle(Window.Handle));
- DeviceContext.IncRef();
-
- #endregion
-
- #region Set pixel format
-
- DevicePixelFormatCollection pixelFormats = DeviceContext.PixelsFormats;
- List matchingPixelFormats = pixelFormats.Choose(controlReqFormat);
-
- if ((matchingPixelFormats.Count == 0) && controlReqFormat.MultisampleBits > 0)
- {
- // Try to select the maximum multisample configuration
- int multisampleBits = 0;
-
- pixelFormats.ForEach(delegate (DevicePixelFormat item) { multisampleBits = Math.Max(multisampleBits, item.MultisampleBits); });
-
- controlReqFormat.MultisampleBits = multisampleBits;
-
- matchingPixelFormats = pixelFormats.Choose(controlReqFormat);
- }
-
- if ((matchingPixelFormats.Count == 0) && controlReqFormat.DoubleBuffer)
- {
- // Try single buffered pixel formats
- controlReqFormat.DoubleBuffer = false;
-
- matchingPixelFormats = pixelFormats.Choose(controlReqFormat);
- if (matchingPixelFormats.Count == 0)
- throw new InvalidOperationException(String.Format("unable to find a suitable pixel format: {0}", pixelFormats.GuessChooseError(controlReqFormat)));
- }
- else if (matchingPixelFormats.Count == 0)
- throw new InvalidOperationException(String.Format("unable to find a suitable pixel format: {0}", pixelFormats.GuessChooseError(controlReqFormat)));
-
- DeviceContext.SetPixelFormat(matchingPixelFormats[0]);
-
- #endregion
-
- #region Set V-Sync
-
- if (Gl.PlatformExtensions.SwapControl)
- {
- int swapInterval = SwapInterval;
-
- // Mask value in case it is not supported
- if (!Gl.PlatformExtensions.SwapControlTear && swapInterval == -1)
- swapInterval = 1;
-
- DeviceContext.SwapInterval(swapInterval);
- }
-
- #endregion
- }
-
- private void CreateGdkGlContext()
+ // Called on Resize
+ protected override bool OnConfigureEvent(Gdk.EventConfigure evnt)
{
- _gdkGlContext = Window.CreateGlContext();
+ if (GraphicsContext != null)
+ {
+ GraphicsContext.Update(WindowInfo);
+ }
- _gdkGlContext.SetRequiredVersion(GLVersionMajor, GLVersionMinor);
-
- _gdkGlContext.ForwardCompatible = ForwardCompatible;
-
- _gdkGlContext.SetUseEs(0);
-
- _gdkGlContext.Realize();
-
- _gdkGlContext.MakeCurrent();
+ return true;
}
private void Initialize()
- {
- ClearCurrent();
+ {
+ _initialized = true;
- Khronos.KhronosApi.LogEnabled = true;
-
- Window.EnsureNative();
-
- if (GTKBindingHelper.CurrentPlatform == OSPlatform.Windows)
+ // If this looks uninitialized... initialize.
+ if (ColorBPP == 0)
{
- CreateDeviceContext(ControlPixelFormat);
+ ColorBPP = 32;
- CreateContext();
-
- DeviceContext.MakeCurrent(_graphicsContext);
- }
- else {
- GraphicsContext.Display = Display.Handle;
-
- CreateGdkGlContext();
+ if (DepthBPP == 0)
+ {
+ DepthBPP = 16;
+ }
}
- _context = GraphicsContext.GetCurrentContext(Window.Handle);
+ ColorFormat colorBufferColorFormat = new ColorFormat(ColorBPP);
- MakeCurrent();
+ ColorFormat accumulationColorFormat = new ColorFormat(AccumulatorBPP);
- GTKBindingHelper.InitializeGlBindings();
+ int buffers = 2;
+ if (SingleBuffer)
+ {
+ buffers--;
+ }
+
+ GraphicsMode graphicsMode = new GraphicsMode(colorBufferColorFormat, DepthBPP, StencilBPP, Samples, accumulationColorFormat, buffers, Stereo);
+
+ this.Window.EnsureNative();
+
+ // IWindowInfo
+ if (OpenTK.Configuration.RunningOnWindows)
+ {
+ WindowInfo = InitializeWindows();
+ }
+ else if (OpenTK.Configuration.RunningOnMacOS)
+ {
+ WindowInfo = InitializeOSX();
+ }
+ else
+ {
+ WindowInfo = InitializeX(graphicsMode);
+ }
+
+ // GraphicsContext
+ GraphicsContext = new GraphicsContext(graphicsMode, WindowInfo, GLVersionMajor, GLVersionMinor, GraphicsContextFlags);
+ GraphicsContext.MakeCurrent(WindowInfo);
+
+ if (OpenTK.Graphics.GraphicsContext.ShareContexts)
+ {
+ Interlocked.Increment(ref _graphicsContextCount);
+
+ if (!_sharedContextInitialized)
+ {
+ _sharedContextInitialized = true;
+ ((IGraphicsContextInternal)GraphicsContext).LoadAll();
+ OnGraphicsContextInitialized();
+ }
+ }
+ else
+ {
+ ((IGraphicsContextInternal)GraphicsContext).LoadAll();
+ OnGraphicsContextInitialized();
+ }
OnInitialized();
+ }
- OpenTK.GraphicsContext.GetCurrentContext(Window.Handle).SwapInterval(1);
+ #region Windows Specific initalization
- ClearCurrent();
+ IWindowInfo InitializeWindows()
+ {
+ IntPtr windowHandle = gdk_win32_window_get_handle(this.Window.Handle);
+ return Utilities.CreateWindowsWindowInfo(windowHandle);
+ }
- _initialized = true;
+ [SuppressUnmanagedCodeSecurity, DllImport("libgdk-3-0.dll")]
+ public static extern IntPtr gdk_win32_window_get_handle(IntPtr d);
- }
- }
+ #endregion
+
+ #region OSX Specific Initialization
+
+ IWindowInfo InitializeOSX()
+ {
+ IntPtr windowHandle = gdk_quartz_window_get_nswindow(this.Window.Handle);
+ //IntPtr viewHandle = gdk_quartz_window_get_nsview(this.GdkWindow.Handle);
+ return Utilities.CreateMacOSWindowInfo(windowHandle);
+ }
+
+ [SuppressUnmanagedCodeSecurity, DllImport("libgdk-3.0.dylib")]
+ static extern IntPtr gdk_quartz_window_get_nswindow(IntPtr handle);
+
+ [SuppressUnmanagedCodeSecurity, DllImport("libgdk-3.0.dylib")]
+ static extern IntPtr gdk_quartz_window_get_nsview(IntPtr handle);
+
+ #endregion
+
+ #region X Specific Initialization
+
+ const string UnixLibGdkName = "libgdk-3.so.0";
+
+ const string UnixLibX11Name = "libX11.so.6";
+ const string UnixLibGLName = "libGL.so.1";
+
+ const int GLX_NONE = 0;
+ const int GLX_USE_GL = 1;
+ const int GLX_BUFFER_SIZE = 2;
+ const int GLX_LEVEL = 3;
+ const int GLX_RGBA = 4;
+ const int GLX_DOUBLEBUFFER = 5;
+ const int GLX_STEREO = 6;
+ const int GLX_AUX_BUFFERS = 7;
+ const int GLX_RED_SIZE = 8;
+ const int GLX_GREEN_SIZE = 9;
+ const int GLX_BLUE_SIZE = 10;
+ const int GLX_ALPHA_SIZE = 11;
+ const int GLX_DEPTH_SIZE = 12;
+ const int GLX_STENCIL_SIZE = 13;
+ const int GLX_ACCUM_RED_SIZE = 14;
+ const int GLX_ACCUM_GREEN_SIZE = 15;
+ const int GLX_ACCUM_BLUE_SIZE = 16;
+ const int GLX_ACCUM_ALPHA_SIZE = 17;
+
+ public enum XVisualClass
+ {
+ StaticGray = 0,
+ GrayScale = 1,
+ StaticColor = 2,
+ PseudoColor = 3,
+ TrueColor = 4,
+ DirectColor = 5,
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ struct XVisualInfo
+ {
+ public IntPtr Visual;
+ public IntPtr VisualID;
+ public int Screen;
+ public int Depth;
+ public XVisualClass Class;
+ public long RedMask;
+ public long GreenMask;
+ public long blueMask;
+ public int ColormapSize;
+ public int BitsPerRgb;
+
+ public override string ToString()
+ {
+ return $"id ({VisualID}), screen ({Screen}), depth ({Depth}), class ({Class})";
+ }
+ }
+
+ [Flags]
+ internal enum XVisualInfoMask
+ {
+ No = 0x0,
+ ID = 0x1,
+ Screen = 0x2,
+ Depth = 0x4,
+ Class = 0x8,
+ Red = 0x10,
+ Green = 0x20,
+ Blue = 0x40,
+ ColormapSize = 0x80,
+ BitsPerRGB = 0x100,
+ All = 0x1FF,
+ }
+
+ private IWindowInfo InitializeX(GraphicsMode mode)
+ {
+ IntPtr display = gdk_x11_display_get_xdisplay(Display.Handle);
+ int screen = Screen.Number;
+
+ IntPtr windowHandle = gdk_x11_window_get_xid(Window.Handle);
+ IntPtr rootWindow = gdk_x11_window_get_xid(RootWindow.Handle);
+
+ IntPtr visualInfo;
+
+ if (mode.Index.HasValue)
+ {
+ XVisualInfo info = new XVisualInfo();
+ info.VisualID = mode.Index.Value;
+ int dummy;
+ visualInfo = XGetVisualInfo(display, XVisualInfoMask.ID, ref info, out dummy);
+ }
+ else
+ {
+ visualInfo = GetVisualInfo(display);
+ }
+
+ IWindowInfo retval = Utilities.CreateX11WindowInfo(display, screen, windowHandle, rootWindow, visualInfo);
+ XFree(visualInfo);
+
+ return retval;
+ }
+
+ private 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);
+ }
+
+ private IntPtr GetVisualInfo(IntPtr display)
+ {
+ try
+ {
+ int[] attributes = AttributeList.ToArray();
+ return glXChooseVisual(display, Screen.Number, attributes);
+ }
+ catch (DllNotFoundException e)
+ {
+ throw new DllNotFoundException("OpenGL dll not found!", e);
+ }
+ catch (EntryPointNotFoundException enf)
+ {
+ throw new EntryPointNotFoundException("Glx entry point not found!", enf);
+ }
+ }
+
+ private List AttributeList
+ {
+ get
+ {
+ List attributeList = new List(24);
+
+ attributeList.Add(GLX_RGBA);
+
+ if (!SingleBuffer)
+ attributeList.Add(GLX_DOUBLEBUFFER);
+
+ if (Stereo)
+ attributeList.Add(GLX_STEREO);
+
+ attributeList.Add(GLX_RED_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_GREEN_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_BLUE_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_ALPHA_SIZE);
+ attributeList.Add(ColorBPP / 4); // TODO support 16-bit
+
+ attributeList.Add(GLX_DEPTH_SIZE);
+ attributeList.Add(DepthBPP);
+
+ attributeList.Add(GLX_STENCIL_SIZE);
+ attributeList.Add(StencilBPP);
+
+ attributeList.Add(GLX_ACCUM_RED_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_ACCUM_GREEN_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_ACCUM_BLUE_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_ACCUM_ALPHA_SIZE);
+ attributeList.Add(AccumulatorBPP / 4);// TODO support 16-bit
+
+ attributeList.Add(GLX_NONE);
+
+ return attributeList;
+ }
+ }
+
+ public IGraphicsContext GraphicsContext { get => _graphicsContext; set => _graphicsContext = value; }
+ public IWindowInfo WindowInfo { get => _windowInfo; set => _windowInfo = value; }
+
+ [DllImport(UnixLibX11Name, EntryPoint = "XGetVisualInfo")]
+ private static extern IntPtr XGetVisualInfoInternal(IntPtr display, IntPtr vinfo_mask, ref XVisualInfo template, out int nitems);
+
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibX11Name)]
+ private static extern void XFree(IntPtr handle);
+
+ /// Returns the X resource (window or pixmap) belonging to a GdkDrawable.
+ /// XID gdk_x11_drawable_get_xid(GdkDrawable *drawable);
+ /// The GdkDrawable.
+ /// The ID of drawable's X resource.
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
+ private static extern IntPtr gdk_x11_drawable_get_xid(IntPtr gdkDisplay);
+
+ /// Returns the X resource (window or pixmap) belonging to a GdkDrawable.
+ /// XID gdk_x11_drawable_get_xid(GdkDrawable *drawable);
+ /// The GdkDrawable.
+ /// The ID of drawable's X resource.
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
+ private static extern IntPtr gdk_x11_window_get_xid(IntPtr gdkDisplay);
+
+ /// Returns the X display of a GdkDisplay.
+ /// Display* gdk_x11_display_get_xdisplay(GdkDisplay *display);
+ /// The GdkDrawable.
+ /// The X Display of the GdkDisplay.
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGdkName)]
+ private static extern IntPtr gdk_x11_display_get_xdisplay(IntPtr gdkDisplay);
+
+ [SuppressUnmanagedCodeSecurity, DllImport(UnixLibGLName)]
+ private static extern IntPtr glXChooseVisual(IntPtr display, int screen, int[] attr);
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/GLWidget/GLWidget.csproj b/GLWidget/GLWidget.csproj
index 9225855..b86b1cb 100644
--- a/GLWidget/GLWidget.csproj
+++ b/GLWidget/GLWidget.csproj
@@ -5,11 +5,13 @@
GLWigdet for GTKSharp, using Opentk.
1.0.3.2
https://github.com/Ryujinx/GLWidget
+ True
-
-
-
-
+
+
+
+
+
\ No newline at end of file
diff --git a/GLWidget/GTKBindingHelper.cs b/GLWidget/GTKBindingHelper.cs
index 2329753..a07b450 100644
--- a/GLWidget/GTKBindingHelper.cs
+++ b/GLWidget/GTKBindingHelper.cs
@@ -47,32 +47,16 @@ namespace OpenTK
{
if (CurrentPlatform == OSPlatform.Windows)
{
- var addr = GetProcAddressWgl(procName);
- if (addr == null || addr == IntPtr.Zero)
- {
- var library = UnsafeNativeMethods.LoadLibrary(WglLibrary);
-
- addr = UnsafeNativeMethods.GetProcAddress(library, procName);
- }
-
- if (addr != IntPtr.Zero)
- {
- Loaded = true;
- }
- return addr;
+ IntPtr library = OpenTK.Platform.Windows.Functions.LoadLibrary(WglLibrary);
+ return OpenTK.Platform.Windows.Functions.GetProcAddress(library, procName);
}
else if (CurrentPlatform == OSPlatform.Linux)
{
- return GetProcAddressGlx(procName);
+ return OpenTK.Platform.X11.Glx.GetProcAddress(procName);
}
else if(CurrentPlatform == OSPlatform.OSX)
{
- var osxAddr = GetProcAddressOSX(procName);
- if (osxAddr != IntPtr.Zero)
- {
- Loaded = true;
- }
- return osxAddr;
+ return OpenTK.Platform.MacOS.NS.GetAddress(procName);
}
else
{
diff --git a/GLWidget/GraphicsContext.cs b/GLWidget/GraphicsContext.cs
index f9f9961..90cf619 100644
--- a/GLWidget/GraphicsContext.cs
+++ b/GLWidget/GraphicsContext.cs
@@ -6,7 +6,7 @@ using static OpenTK.GTKBindingHelper;
namespace OpenTK
{
- public interface IGraphicsContext
+ public interface ILegacyGraphicsContext
{
void MakeCurrent();
void SwapBuffers();
@@ -14,7 +14,7 @@ namespace OpenTK
void SwapInterval(int interval);
}
- public abstract class GraphicsContext : IGraphicsContext
+ public abstract class LegacyGraphicsContext : ILegacyGraphicsContext
{
public static IntPtr Display{ get; set; }
@@ -40,7 +40,7 @@ namespace OpenTK
}
}
- public static IGraphicsContext GetCurrentContext(IntPtr handle)
+ public static ILegacyGraphicsContext GetCurrentContext(IntPtr handle)
{
var currentPlatform = CurrentPlatform;
@@ -66,7 +66,7 @@ namespace OpenTK
public abstract void SwapInterval(int interval);
}
- public class WglGraphicsContext : GraphicsContext
+ public class WglGraphicsContext : LegacyGraphicsContext
{
private delegate int wglSwapIntervalExtDelegate(int interval);
private static wglSwapIntervalExtDelegate wglSwapIntervalExt = null;
@@ -120,7 +120,7 @@ namespace OpenTK
}
}
- public class GlxGraphicsContext : GraphicsContext
+ public class GlxGraphicsContext : LegacyGraphicsContext
{
private IntPtr _windowHandle;
@@ -162,7 +162,7 @@ namespace OpenTK
}
}
- public class CglGraphicsContext : GraphicsContext
+ public class CglGraphicsContext : LegacyGraphicsContext
{
private IntPtr _windowHandle;
diff --git a/GLWidget/OpenTK/BindingsBase.cs b/GLWidget/OpenTK/BindingsBase.cs
new file mode 100644
index 0000000..aa40693
--- /dev/null
+++ b/GLWidget/OpenTK/BindingsBase.cs
@@ -0,0 +1,210 @@
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2009 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Text;
+using System.Runtime.InteropServices;
+
+namespace OpenTK
+{
+ ///
+ /// Provides a common foundation for all flat API bindings and implements the extension loading interface.
+ ///
+ public abstract class LegacyBindingsBase
+ {
+ ///
+ /// Constructs a new BindingsBase instance.
+ ///
+ public LegacyBindingsBase()
+ {
+ }
+
+ ///
+ /// Gets or sets a that indicates whether the list of supported extensions may have changed.
+ ///
+ protected bool RebuildExtensionList { get; set; } = true;
+
+ ///
+ /// Retrieves an unmanaged function pointer to the specified function.
+ ///
+ ///
+ /// A that defines the name of the function.
+ ///
+ ///
+ /// A that contains the address of funcname or IntPtr.Zero,
+ /// if the function is not supported by the drivers.
+ ///
+ ///
+ /// Note: some drivers are known to return non-zero values for unsupported functions.
+ /// Typical values include 1 and 2 - inheritors are advised to check for and ignore these
+ /// values.
+ ///
+ public abstract IntPtr GetAddress(string funcname);
+
+ ///
+ /// Gets an object that can be used to synchronize access to the bindings implementation.
+ ///
+ /// This object should be unique across bindings but consistent between bindings
+ /// of the same type. For example, ES10.GL, OpenGL.GL and CL10.CL should all return
+ /// unique objects, but all instances of ES10.GL should return the same object.
+ protected abstract object SyncRoot { get; }
+
+ ///
+ /// Marshals a pointer to a null-terminated byte array to a new System.String.
+ /// This method supports OpenTK and is not intended to be called by user code.
+ ///
+ /// A pointer to a null-terminated byte array.
+ ///
+ /// A System.String with the data from .
+ ///
+ protected static string MarshalPtrToString(IntPtr ptr)
+ {
+ if (ptr == IntPtr.Zero)
+ {
+ throw new ArgumentException("ptr");
+ }
+
+ unsafe
+ {
+ sbyte* str = (sbyte*)ptr;
+ int len = 0;
+ while (*str != 0)
+ {
+ ++len;
+ ++str;
+ }
+
+ return new string((sbyte*)ptr, 0, len, Encoding.UTF8);
+ }
+ }
+
+ ///
+ /// Marshal a System.String to unmanaged memory.
+ /// The resulting string is encoded in UTF8 and must be freed
+ /// with FreeStringPtr.
+ ///
+ /// The System.String to marshal.
+ ///
+ /// An unmanaged pointer containing the marshalled string.
+ /// This pointer must be freed with FreeStringPtr
+ ///
+ protected static IntPtr MarshalStringToPtr(string str)
+ {
+ if (String.IsNullOrEmpty(str))
+ {
+ return IntPtr.Zero;
+ }
+
+ // Allocate a buffer big enough to hold the marshalled string.
+ // GetMaxByteCount() appears to allocate space for the final NUL
+ // character, but allocate an extra one just in case (who knows
+ // what old Mono version would do here.)
+ int max_count = Encoding.UTF8.GetMaxByteCount(str.Length) + 1;
+ IntPtr ptr = Marshal.AllocHGlobal(max_count);
+ if (ptr == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+
+ // Pin the managed string and convert it to UTF8 using
+ // the pointer overload of System.Encoding.UTF8.GetBytes().
+ unsafe
+ {
+ fixed (char* pstr = str)
+ {
+ int actual_count = Encoding.UTF8.GetBytes(pstr, str.Length, (byte*)ptr, max_count);
+ Marshal.WriteByte(ptr, actual_count, 0); // Append '\0' at the end of the string
+ return ptr;
+ }
+ }
+ }
+
+ ///
+ /// Frees a marshalled string that allocated by MarshalStringToPtr.
+ ///
+ /// An unmanaged pointer allocated with MarshalStringToPtr
+ protected static void FreeStringPtr(IntPtr ptr)
+ {
+ Marshal.FreeHGlobal(ptr);
+ }
+
+ ///
+ /// Marshals a System.String array to unmanaged memory by calling
+ /// Marshal.AllocHGlobal for each element.
+ ///
+ /// An unmanaged pointer to an array of null-terminated strings
+ /// The string array to marshal.
+ protected static IntPtr MarshalStringArrayToPtr(string[] str_array)
+ {
+ IntPtr ptr = IntPtr.Zero;
+ if (str_array != null && str_array.Length != 0)
+ {
+ ptr = Marshal.AllocHGlobal(str_array.Length * IntPtr.Size);
+ if (ptr == IntPtr.Zero)
+ {
+ throw new OutOfMemoryException();
+ }
+
+ int i = 0;
+ try
+ {
+ for (i = 0; i < str_array.Length; i++)
+ {
+ IntPtr str = MarshalStringToPtr(str_array[i]);
+ Marshal.WriteIntPtr(ptr, i * IntPtr.Size, str);
+ }
+ }
+ catch (OutOfMemoryException)
+ {
+ for (i = i - 1; i >= 0; --i)
+ {
+ Marshal.FreeHGlobal(Marshal.ReadIntPtr(ptr, i * IntPtr.Size));
+ }
+
+ Marshal.FreeHGlobal(ptr);
+
+ throw;
+ }
+ }
+ return ptr;
+ }
+
+ ///
+ /// Frees a marshalled string that allocated by MarshalStringArrayToPtr.
+ ///
+ /// An unmanaged pointer allocated with MarshalStringArrayToPtr
+ /// The length of the string array.
+ protected static void FreeStringArrayPtr(IntPtr ptr, int length)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ Marshal.FreeHGlobal(Marshal.ReadIntPtr(ptr, i * IntPtr.Size));
+ }
+ Marshal.FreeHGlobal(ptr);
+ }
+
+ internal abstract void LoadEntryPoints();
+ }
+}
diff --git a/GLWidget/OpenTK/Configuration.cs b/GLWidget/OpenTK/Configuration.cs
new file mode 100644
index 0000000..b5d2f2f
--- /dev/null
+++ b/GLWidget/OpenTK/Configuration.cs
@@ -0,0 +1,197 @@
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2009 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace OpenTK
+{
+ ///
+ /// Provides information about the underlying OS and runtime.
+ /// You must call Toolkit.Init before accessing members
+ /// of this class.
+ ///
+ public sealed class Configuration
+ {
+ private static bool runningOnUnix, runningOnMacOS, runningOnLinux;
+ private volatile static bool initialized;
+ private readonly static object InitLock = new object();
+
+ private Configuration() { }
+
+ /// Gets a System.Boolean indicating whether OpenTK is running on a Windows platform.
+ public static bool RunningOnWindows { get; private set; }
+
+ /// Gets a System.Boolean indicating whether OpenTK is running on an X11 platform.
+ public static bool RunningOnX11 { get; private set; }
+
+ ///
+ /// Gets a indicating whether OpenTK is running on a Unix platform.
+ ///
+ public static bool RunningOnUnix
+ {
+ get { return runningOnUnix; }
+ }
+
+ /// Gets a System.Boolean indicating whether OpenTK is running on the Linux kernel.
+ public static bool RunningOnLinux { get { return runningOnLinux; } }
+
+ /// Gets a System.Boolean indicating whether OpenTK is running on a MacOS platform.
+ public static bool RunningOnMacOS { get { return runningOnMacOS; } }
+
+ ///
+ /// Gets a System.Boolean indicating whether OpenTK is running on the Mono runtime.
+ ///
+ public static bool RunningOnMono { get; private set; }
+
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
+ private struct utsname
+ {
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string sysname;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string nodename;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string release;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string version;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
+ public string machine;
+
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
+ public string extraJustInCase;
+
+ }
+
+ ///
+ /// Detects the unix kernel by p/invoking uname (libc).
+ ///
+ ///
+ private static string DetectUnixKernel()
+ {
+ Debug.Print("Size: {0}", Marshal.SizeOf(typeof(utsname)).ToString());
+ Debug.Flush();
+ utsname uts = new utsname();
+ uname(out uts);
+
+ Debug.WriteLine("System:");
+ Debug.Indent();
+ Debug.WriteLine(uts.sysname);
+ Debug.WriteLine(uts.nodename);
+ Debug.WriteLine(uts.release);
+ Debug.WriteLine(uts.version);
+ Debug.WriteLine(uts.machine);
+ Debug.Unindent();
+
+ return uts.sysname.ToString();
+ }
+
+ [DllImport("libc")]
+ private static extern void uname(out utsname uname_struct);
+
+ private static bool DetectMono()
+ {
+ // Detect the Mono runtime (code taken from http://mono.wikia.com/wiki/Detecting_if_program_is_running_in_Mono).
+ Type t = Type.GetType("Mono.Runtime");
+ return t != null;
+ }
+
+ private static void DetectUnix(out bool unix, out bool linux, out bool macos)
+ {
+ unix = linux = macos = false;
+
+ string kernel_name = DetectUnixKernel();
+ switch (kernel_name)
+ {
+ case null:
+ case "":
+ throw new PlatformNotSupportedException(
+ "Unknown platform. Please file a bug report at https://github.com/opentk/opentk/issues");
+
+ case "Linux":
+ linux = unix = true;
+ break;
+
+ case "Darwin":
+ macos = unix = true;
+ break;
+
+ default:
+ unix = true;
+ break;
+ }
+ }
+
+ private static bool DetectWindows()
+ {
+ return
+ System.Environment.OSVersion.Platform == PlatformID.Win32NT ||
+ System.Environment.OSVersion.Platform == PlatformID.Win32S ||
+ System.Environment.OSVersion.Platform == PlatformID.Win32Windows ||
+ System.Environment.OSVersion.Platform == PlatformID.WinCE;
+ }
+
+ private static bool DetectX11()
+ {
+ // Detect whether X is present.
+ try { return OpenTK.Platform.X11.API.DefaultDisplay != IntPtr.Zero; }
+ catch { return false; }
+ }
+
+ // Detects the underlying OS and runtime.
+ internal static void Init(ToolkitOptions options)
+ {
+ lock (InitLock)
+ {
+ if (!initialized)
+ {
+ RunningOnMono = DetectMono();
+ RunningOnWindows = DetectWindows();
+ if (!RunningOnWindows)
+ {
+ DetectUnix(out runningOnUnix, out runningOnLinux, out runningOnMacOS);
+ }
+
+ if ((runningOnLinux) || options.Backend == PlatformBackend.PreferX11)
+ {
+ RunningOnX11 = DetectX11();
+ }
+
+ initialized = true;
+ Debug.Print("Detected configuration: {0} / {1}",
+ RunningOnWindows ? "Windows" : RunningOnLinux ? "Linux" : RunningOnMacOS ? "MacOS" :
+ runningOnUnix ? "Unix" : RunningOnX11 ? "X11" : "Unknown Platform",
+ RunningOnMono ? "Mono" : ".Net");
+ }
+ }
+ }
+ }
+}
diff --git a/GLWidget/OpenTK/ContextHandle.cs b/GLWidget/OpenTK/ContextHandle.cs
new file mode 100644
index 0000000..fd10e32
--- /dev/null
+++ b/GLWidget/OpenTK/ContextHandle.cs
@@ -0,0 +1,127 @@
+/* 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.
+ */
+
+using System;
+
+namespace OpenTK
+{
+ ///
+ /// Represents a handle to an OpenGL or OpenAL context.
+ ///
+ public struct ContextHandle : IComparable, IEquatable
+ {
+ private IntPtr handle;
+
+ ///
+ /// Gets a System.IntPtr that represents the handle of this ContextHandle.
+ ///
+ public IntPtr Handle { get { return handle; } }
+
+ /// A read-only field that represents a handle that has been initialized to zero.
+ public static readonly ContextHandle Zero = new ContextHandle(IntPtr.Zero);
+
+ ///
+ /// Constructs a new instance with the specified handle.
+ ///
+ /// A System.IntPtr containing the value for this instance.
+ public ContextHandle(IntPtr h) { handle = h; }
+
+ ///
+ /// Converts this instance to its equivalent string representation.
+ ///
+ /// A System.String that contains the string representation of this instance.
+ public override string ToString()
+ {
+ return Handle.ToString();
+ }
+
+ ///
+ /// Compares this instance to the specified object.
+ ///
+ /// The System.Object to compare to.
+ /// True if obj is a ContextHandle that is equal to this instance; false otherwise.
+ public override bool Equals(object obj)
+ {
+ if (obj is ContextHandle)
+ {
+ return this.Equals((ContextHandle)obj);
+ }
+ return false;
+ }
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ /// A System.Int32 with the hash code of this instance.
+ public override int GetHashCode()
+ {
+ return Handle.GetHashCode();
+ }
+
+ ///
+ /// Converts the specified ContextHandle to the equivalent IntPtr.
+ ///
+ /// The ContextHandle to convert.
+ /// A System.IntPtr equivalent to the specified ContextHandle.
+ public static explicit operator IntPtr(ContextHandle c)
+ {
+ return c != ContextHandle.Zero ? c.handle : IntPtr.Zero;
+ }
+
+ ///
+ /// Converts the specified IntPtr to the equivalent ContextHandle.
+ ///
+ /// The System.IntPtr to convert.
+ /// A ContextHandle equivalent to the specified IntPtr.
+ public static explicit operator ContextHandle(IntPtr p)
+ {
+ return new ContextHandle(p);
+ }
+
+ ///
+ /// Compares two ContextHandles for equality.
+ ///
+ /// The ContextHandle to compare.
+ /// The ContextHandle to compare to.
+ /// True if left is equal to right; false otherwise.
+ public static bool operator ==(ContextHandle left, ContextHandle right)
+ {
+ return left.Equals(right);
+ }
+
+ ///
+ /// Compares two ContextHandles for inequality.
+ ///
+ /// The ContextHandle to compare.
+ /// The ContextHandle to compare to.
+ /// True if left is not equal to right; false otherwise.
+ public static bool operator !=(ContextHandle left, ContextHandle right)
+ {
+ return !left.Equals(right);
+ }
+
+ ///
+ /// Compares the numerical value of this instance to the specified ContextHandle and
+ /// returns a value indicating their relative order.
+ ///
+ /// The ContextHandle to compare to.
+ /// Less than 0, if this instance is less than other; 0 if both are equal; Greater than 0 if other is greater than this instance.
+ public int CompareTo(ContextHandle other)
+ {
+ unsafe { return (int)((int*)other.handle.ToPointer() - (int*)this.handle.ToPointer()); }
+ }
+
+ ///
+ /// Compares this instance to the specified ContextHandle for equality.
+ ///
+ /// The ContextHandle to compare to.
+ /// True if this instance is equal to other; false otherwise.
+ public bool Equals(ContextHandle other)
+ {
+ return Handle == other.Handle;
+ }
+ }
+}
diff --git a/GLWidget/OpenTK/DisplayDevice.cs b/GLWidget/OpenTK/DisplayDevice.cs
new file mode 100644
index 0000000..180c484
--- /dev/null
+++ b/GLWidget/OpenTK/DisplayDevice.cs
@@ -0,0 +1,445 @@
+//
+// The Open Toolkit Library License
+//
+// Copyright (c) 2006 - 2010 the Open Toolkit library.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do
+// so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+// OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace OpenTK
+{
+ ///
+ /// Defines a display device on the underlying system, and provides
+ /// methods to query and change its display parameters.
+ ///
+ public class DisplayDevice
+ {
+ // TODO: Add properties that describe the 'usable' size of the Display, i.e. the maximized size without the taskbar etc.
+ // TODO: Does not detect changes to primary device.
+
+ private bool primary;
+ private Rectangle bounds;
+ private DisplayResolution current_resolution = new DisplayResolution();
+ private List available_resolutions = new List();
+ private IList available_resolutions_readonly;
+
+ internal object Id; // A platform-specific id for this monitor
+
+ private static readonly object display_lock = new object();
+ private static DisplayDevice primary_display;
+
+ private static Platform.IDisplayDeviceDriver implementation;
+
+ static DisplayDevice()
+ {
+ implementation = Platform.Factory.Default.CreateDisplayDeviceDriver();
+ }
+
+ internal DisplayDevice()
+ {
+ available_resolutions_readonly = available_resolutions.AsReadOnly();
+ }
+
+ internal DisplayDevice(DisplayResolution currentResolution, bool primary,
+ IEnumerable availableResolutions, Rectangle bounds,
+ object id)
+ : this()
+ {
+ // Todo: Consolidate current resolution with bounds? Can they fall out of sync right now?
+ this.current_resolution = currentResolution;
+ IsPrimary = primary;
+ this.available_resolutions.AddRange(availableResolutions);
+ #pragma warning disable 612,618
+ this.bounds = bounds == Rectangle.Empty ? currentResolution.Bounds : bounds;
+ #pragma warning restore 612,618
+ this.Id = id;
+ }
+
+ ///
+ /// Gets the bounds of this instance in pixel coordinates..
+ ///
+ public Rectangle Bounds
+ {
+ get { return bounds; }
+ internal set
+ {
+ bounds = value;
+ current_resolution.Height = bounds.Height;
+ current_resolution.Width = bounds.Width;
+ }
+ }
+
+ /// Gets a System.Int32 that contains the width of this display in pixels.
+ public int Width { get { return current_resolution.Width; } }
+
+ /// Gets a System.Int32 that contains the height of this display in pixels.
+ public int Height { get { return current_resolution.Height; } }
+
+ /// Gets a System.Int32 that contains number of bits per pixel of this display. Typical values include 8, 16, 24 and 32.
+ public int BitsPerPixel
+ {
+ get { return current_resolution.BitsPerPixel; }
+ internal set { current_resolution.BitsPerPixel = value; }
+ }
+
+ ///
+ /// Gets a System.Single representing the vertical refresh rate of this display.
+ ///
+ public float RefreshRate
+ {
+ get { return current_resolution.RefreshRate; }
+ internal set { current_resolution.RefreshRate = value; }
+ }
+
+ /// Gets a System.Boolean that indicates whether this Display is the primary Display in systems with multiple Displays.
+ public bool IsPrimary
+ {
+ get { return primary; }
+ internal set
+ {
+ if (value && primary_display != null && primary_display != this)
+ {
+ primary_display.IsPrimary = false;
+ }
+
+ lock (display_lock)
+ {
+ primary = value;
+ if (value)
+ {
+ primary_display = this;
+ }
+ }
+ }
+ }
+
+ ///
+ /// Selects an available resolution that matches the specified parameters.
+ ///
+ /// The width of the requested resolution in pixels.
+ /// The height of the requested resolution in pixels.
+ /// The bits per pixel of the requested resolution.
+ /// The refresh rate of the requested resolution in hertz.
+ /// The requested DisplayResolution or null if the parameters cannot be met.
+ ///
+ /// If a matching resolution is not found, this function will retry ignoring the specified refresh rate,
+ /// bits per pixel and resolution, in this order. If a matching resolution still doesn't exist, this function will
+ /// return the current resolution.
+ /// A parameter set to 0 or negative numbers will not be used in the search (e.g. if refreshRate is 0,
+ /// any refresh rate will be considered valid).
+ /// This function allocates memory.
+ ///
+ public DisplayResolution SelectResolution(int width, int height, int bitsPerPixel, float refreshRate)
+ {
+ DisplayResolution resolution = FindResolution(width, height, bitsPerPixel, refreshRate);
+ if (resolution == null)
+ {
+ resolution = FindResolution(width, height, bitsPerPixel, 0);
+ }
+ if (resolution == null)
+ {
+ resolution = FindResolution(width, height, 0, 0);
+ }
+ if (resolution == null)
+ {
+ return current_resolution;
+ }
+ return resolution;
+ }
+
+ ///
+ /// Gets the list of objects available on this device.
+ ///
+ public IList AvailableResolutions
+ {
+ get { return available_resolutions_readonly; }
+ internal set
+ {
+ available_resolutions = (List)value;
+ available_resolutions_readonly = available_resolutions.AsReadOnly();
+ }
+ }
+
+ /// Changes the resolution of the DisplayDevice.
+ /// The resolution to set.
+ /// Thrown if the requested resolution could not be set.
+ /// If the specified resolution is null, this function will restore the original DisplayResolution.
+ public void ChangeResolution(DisplayResolution resolution)
+ {
+ if (resolution == null)
+ {
+ this.RestoreResolution();
+ }
+
+ if (resolution == current_resolution)
+ {
+ return;
+ }
+
+ //effect.FadeOut();
+
+ if (implementation.TryChangeResolution(this, resolution))
+ {
+ if (OriginalResolution == null)
+ {
+ OriginalResolution = current_resolution;
+ }
+ current_resolution = resolution;
+ }
+ else
+ {
+ throw new Graphics.GraphicsModeException(String.Format("Device {0}: Failed to change resolution to {1}.",
+ this, resolution));
+ }
+
+ //effect.FadeIn();
+ }
+
+ /// Changes the resolution of the DisplayDevice.
+ /// The new width of the DisplayDevice.
+ /// The new height of the DisplayDevice.
+ /// The new bits per pixel of the DisplayDevice.
+ /// The new refresh rate of the DisplayDevice.
+ /// Thrown if the requested resolution could not be set.
+ public void ChangeResolution(int width, int height, int bitsPerPixel, float refreshRate)
+ {
+ this.ChangeResolution(this.SelectResolution(width, height, bitsPerPixel, refreshRate));
+ }
+
+ /// Restores the original resolution of the DisplayDevice.
+ /// Thrown if the original resolution could not be restored.
+ public void RestoreResolution()
+ {
+ if (OriginalResolution != null)
+ {
+ //effect.FadeOut();
+
+ if (implementation.TryRestoreResolution(this))
+ {
+ current_resolution = OriginalResolution;
+ OriginalResolution = null;
+ }
+ else
+ {
+ throw new Graphics.GraphicsModeException(String.Format("Device {0}: Failed to restore resolution.", this));
+ }
+
+ //effect.FadeIn();
+ }
+ }
+
+ /// Gets the default (primary) display of this system.
+ public static DisplayDevice Default
+ {
+ get { return implementation.GetDisplay(DisplayIndex.Primary); }
+ }
+
+ ///
+ /// Gets the for the specified .
+ ///
+ /// The that defines the desired display.
+ /// A or null, if no device corresponds to the specified index.
+ public static DisplayDevice GetDisplay(DisplayIndex index)
+ {
+ return implementation.GetDisplay(index);
+ }
+
+ ///
+ /// Gets the original resolution of this instance.
+ ///
+ internal DisplayResolution OriginalResolution { get; set; }
+
+ internal static DisplayDevice FromPoint(int x, int y)
+ {
+ for (DisplayIndex i = DisplayIndex.First; i < DisplayIndex.Sixth; i++)
+ {
+ DisplayDevice display = DisplayDevice.GetDisplay(i);
+ if (display != null)
+ {
+ if (display.Bounds.Contains(x, y))
+ {
+ return display;
+ }
+ }
+ }
+ return null;
+ }
+
+ private DisplayResolution FindResolution(int width, int height, int bitsPerPixel, float refreshRate)
+ {
+ return available_resolutions.Find(delegate(DisplayResolution test)
+ {
+ return
+ ((width > 0 && width == test.Width) || width == 0) &&
+ ((height > 0 && height == test.Height) || height == 0) &&
+ ((bitsPerPixel > 0 && bitsPerPixel == test.BitsPerPixel) || bitsPerPixel == 0) &&
+ ((refreshRate > 0 && System.Math.Abs(refreshRate - test.RefreshRate) < 1.0) || refreshRate == 0);
+ });
+ }
+
+ ///
+ /// Returns a System.String representing this DisplayDevice.
+ ///
+ /// A System.String representing this DisplayDevice.
+ public override string ToString()
+ {
+ return String.Format("{0}: {1} ({2} modes available)", IsPrimary ? "Primary" : "Secondary",
+ Bounds.ToString(), available_resolutions.Count);
+ }
+
+ ///// Determines whether the specified DisplayDevices are equal.
+ ///// The System.Object to check against.
+ ///// True if the System.Object is an equal DisplayDevice; false otherwise.
+ //public override bool Equals(object obj)
+ //{
+ // if (obj is DisplayDevice)
+ // {
+ // DisplayDevice dev = (DisplayDevice)obj;
+ // return
+ // IsPrimary == dev.IsPrimary &&
+ // current_resolution == dev.current_resolution &&
+ // available_resolutions.Count == dev.available_resolutions.Count;
+ // }
+
+ // return false;
+ //}
+
+ ///// Returns a unique hash representing this DisplayDevice.
+ ///// A System.Int32 that may serve as a hash code for this DisplayDevice.
+ ////public override int GetHashCode()
+ //{
+ // return current_resolution.GetHashCode() ^ IsPrimary.GetHashCode() ^ available_resolutions.Count;
+ //}
+ }
+#if false
+ class FadeEffect : IDisposable
+ {
+ List