diff --git a/Source/OpenTK/Platform/X11/X11GLControl.cs b/Source/OpenTK/Platform/X11/X11GLControl.cs new file mode 100644 index 00000000..c0317db3 --- /dev/null +++ b/Source/OpenTK/Platform/X11/X11GLControl.cs @@ -0,0 +1,84 @@ +#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.Windows.Forms; +using System.Runtime.InteropServices; + +using OpenTK.Graphics; + +namespace OpenTK.Platform.X11 +{ + class X11GLControl : IGLControl + { + GraphicsMode mode; + Control control; + IntPtr display; + + internal X11GLControl(GraphicsMode mode, Control control) + { + this.mode = mode; + this.control = control; + + X11WindowInfo window = (X11WindowInfo)this.WindowInfo; + + 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)); + + Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); + xplatui.GetField("CustomVisual", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + .SetValue(null, window.VisualInfo.visual); + xplatui.GetField("CustomColormap", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic) + .SetValue(null, API.CreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0)); + } + + #region --- IGLControl Members --- + + public GraphicsContext CreateContext() + { + return new GraphicsContext(mode, this.WindowInfo); + } + + public bool IsIdle + { + get { return Functions.XPending(display) == 0; } + } + + public IWindowInfo WindowInfo + { + get + { + 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."); + + X11WindowInfo window = new X11WindowInfo(control.Handle, null); + + display = + 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); + + if (control.IsHandleCreated) + window.WindowHandle = control.Handle; + + return window; + } + } + + #endregion + } +} diff --git a/Source/OpenTK/Platform/X11/X11GLControlHelper.cs b/Source/OpenTK/Platform/X11/X11GLControlHelper.cs new file mode 100644 index 00000000..24f975fb --- /dev/null +++ b/Source/OpenTK/Platform/X11/X11GLControlHelper.cs @@ -0,0 +1,63 @@ +#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.Windows.Forms; + +namespace OpenTK.Platform.X11 +{ + /// + /// Utility to obtain IWindowInfo from a System.Windows.Forms.Control on Mono/X11. + internal sealed class X11GLControlHelper : IGLControlHelper + { + Control control; + IntPtr display; + + public X11GLControlHelper(Control c) + { + } + + #region IGLControlHelper Members + + public IWindowInfo WindowInfo + { + get + { + X11WindowInfo window = new X11WindowInfo(); + Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); + if (xplatui == null) + throw new ApplicationException("Could not get System.Windows.Forms.XplatUIX11 through reflection. Unsupported platform or Mono runtime version, aborting."); + + display = + 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); + + return (IWindowInfo)window; + } + } + + public bool IsIdle + { + get + { + lock (Functions.Lock) + { + return Functions.XPending(display) == 0; + } + } + } + + #endregion + } +} diff --git a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs new file mode 100644 index 00000000..66c40d31 --- /dev/null +++ b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs @@ -0,0 +1,127 @@ +#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; +using System.Diagnostics; + +using OpenTK.Graphics; + +namespace OpenTK.Platform.X11 +{ + class X11GraphicsMode : IGraphicsMode + { + internal X11GraphicsMode() + { + } + + public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, + int buffers, bool stereo) + { + List visualAttributes = new List(); + + if (color.BitsPerPixel > 0) + { + if (!color.IsIndexed) + visualAttributes.Add((int)GLXAttribute.RGBA); + visualAttributes.Add((int)GLXAttribute.RED_SIZE); + visualAttributes.Add(color.Red); + visualAttributes.Add((int)GLXAttribute.GREEN_SIZE); + visualAttributes.Add(color.Green); + visualAttributes.Add((int)GLXAttribute.BLUE_SIZE); + visualAttributes.Add(color.Blue); + visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); + visualAttributes.Add(color.Alpha); + } + + if (depth > 0) + { + visualAttributes.Add((int)GLXAttribute.DEPTH_SIZE); + visualAttributes.Add(depth); + } + + if (buffers > 1) + visualAttributes.Add((int)GLXAttribute.DOUBLEBUFFER); + + if (stencil > 1) + { + visualAttributes.Add((int)GLXAttribute.STENCIL_SIZE); + visualAttributes.Add(stencil); + } + + if (accum.BitsPerPixel > 0) + { + visualAttributes.Add((int)GLXAttribute.ACCUM_ALPHA_SIZE); + visualAttributes.Add(accum.Alpha); + visualAttributes.Add((int)GLXAttribute.ACCUM_BLUE_SIZE); + visualAttributes.Add(accum.Blue); + visualAttributes.Add((int)GLXAttribute.ACCUM_GREEN_SIZE); + visualAttributes.Add(accum.Green); + visualAttributes.Add((int)GLXAttribute.ACCUM_RED_SIZE); + visualAttributes.Add(accum.Red); + } + + if (stereo) + visualAttributes.Add((int)GLXAttribute.STEREO); + + visualAttributes.Add((int)0); + + // Prepare Windows.Forms for creating OpenGL drawables. + // We reuse the display connection. + // TODO: Multiple screens. + Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms"); + IntPtr display = (IntPtr)xplatui.GetField("DisplayHandle", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + IntPtr root = (IntPtr)xplatui.GetField("RootWindow", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + int screen = (int)xplatui.GetField("ScreenNo", + System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null); + + Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root); + + IntPtr visual = Glx.ChooseVisual(display, screen, visualAttributes.ToArray()); + + if (visual == IntPtr.Zero) + throw new GraphicsContextException("Requested GraphicsMode not available."); + + XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo)); + + // See what we *really* got: + int r, g, b, a; + Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out a); + Glx.GetConfig(display, ref info, GLXAttribute.RED_SIZE, out r); + Glx.GetConfig(display, ref info, GLXAttribute.GREEN_SIZE, out g); + Glx.GetConfig(display, ref info, GLXAttribute.BLUE_SIZE, out b); + int ar, ag, ab, aa; + Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_ALPHA_SIZE, out aa); + Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_RED_SIZE, out ar); + Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_GREEN_SIZE, out ag); + Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_BLUE_SIZE, out ab); + Glx.GetConfig(display, ref info, GLXAttribute.DEPTH_SIZE, out depth); + Glx.GetConfig(display, ref info, GLXAttribute.STENCIL_SIZE, out stencil); + Glx.GetConfig(display, ref info, GLXAttribute.SAMPLES, out samples); + Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers); + ++buffers; // the above lines returns 0 - false and 1 - true. + int st; + Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st); + stereo = st != 0; + + GraphicsMode gfx = new GraphicsMode(info.visualid, new ColorFormat(r, g, b, a), depth, stencil, samples, + new ColorFormat(ar, ag, ab, aa), buffers, stereo); + + 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, API.CreateColormap(display, root, visual, 0)); + + return gfx; + } + } +}