From d75a2ce43909d62a258c7a8af08a589a2225e334 Mon Sep 17 00:00:00 2001 From: "Stefanos A." Date: Sat, 19 Jul 2014 20:39:17 +0200 Subject: [PATCH] [X11] Fix for issue #143 OpenTK will now use the same GLXFBConfig to create the INativeWindow and IGraphicsContext on Linux/X11. This resolves an issue where OpenGL 3.x contexts could not be created on some graphics drivers (e.g. nvidia binary.) --- Source/OpenTK/Platform/Utilities.cs | 6 +- Source/OpenTK/Platform/X11/X11GLContext.cs | 196 ++++++++++++-------------- Source/OpenTK/Platform/X11/X11GLNative.cs | 18 +-- Source/OpenTK/Platform/X11/X11GraphicsMode.cs | 168 +++++++++++----------- Source/OpenTK/Platform/X11/X11WindowInfo.cs | 17 ++- 5 files changed, 199 insertions(+), 206 deletions(-) diff --git a/Source/OpenTK/Platform/Utilities.cs b/Source/OpenTK/Platform/Utilities.cs index a7b801e..cae7ba5 100644 --- a/Source/OpenTK/Platform/Utilities.cs +++ b/Source/OpenTK/Platform/Utilities.cs @@ -248,11 +248,7 @@ namespace OpenTK.Platform window.Screen = screen; window.Handle = windowHandle; window.RootWindow = rootWindow; - if (visualInfo != IntPtr.Zero) - { - window.VisualInfo = (X11.XVisualInfo)Marshal.PtrToStructure(visualInfo, typeof(X11.XVisualInfo)); - } - + window.Visual = visualInfo; return window; } diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index a600b8b..a1c95a3 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -78,13 +78,26 @@ namespace OpenTK.Platform.X11 } } - Mode = ModeSelector.SelectGraphicsMode( - mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, - mode.AccumulatorFormat, mode.Buffers, mode.Stereo); + IntPtr visual = IntPtr.Zero; + IntPtr fbconfig = IntPtr.Zero; + // Once a window has a visual, we cannot use a different + // visual on the OpenGL context, or glXMakeCurrent might fail. + // Note: we should only check X11WindowInfo.Visual, as that + // is the only property that can be set by Utilities.CreateX11WindowInfo. currentWindow = (X11WindowInfo)window; - currentWindow.VisualInfo = SelectVisual(Mode, currentWindow); - + if (currentWindow.Visual != IntPtr.Zero) + { + visual = currentWindow.Visual; + fbconfig = currentWindow.FBConfig; + Mode = currentWindow.GraphicsMode; + } + + if (!Mode.Index.HasValue) + { + Mode = ModeSelector.SelectGraphicsMode(mode, out visual, out fbconfig); + } + ContextHandle shareHandle = shared != null ? (shared as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero; @@ -99,84 +112,15 @@ namespace OpenTK.Platform.X11 // HACK: It seems that Catalyst 9.1 - 9.4 on Linux have problems with contexts created through // GLX_ARB_create_context, including hideous input lag, no vsync and other madness. // Use legacy context creation if the user doesn't request a 3.0+ context. - if ((major * 10 + minor >= 30) && SupportsCreateContextAttribs(Display, currentWindow)) + if (fbconfig != IntPtr.Zero && (major * 10 + minor >= 30) && SupportsCreateContextAttribs(Display, currentWindow)) { - Debug.Write("Using GLX_ARB_create_context... "); - - unsafe - { - // We need the FB config for the current GraphicsMode. - int count; - IntPtr* fbconfigs = Glx.ChooseFBConfig(Display, currentWindow.Screen, - new int[] { - (int)GLXAttribute.VISUAL_ID, - (int)Mode.Index, - 0 - }, out count); - - if (count > 0) - { - List attributes = new List(); - attributes.Add((int)ArbCreateContext.MajorVersion); - attributes.Add(major); - attributes.Add((int)ArbCreateContext.MinorVersion); - attributes.Add(minor); - if (flags != 0) - { - attributes.Add((int)ArbCreateContext.Flags); - attributes.Add((int)GetARBContextFlags(flags)); - attributes.Add((int)ArbCreateContext.ProfileMask); - attributes.Add((int)GetARBProfileFlags(flags)); - } - // According to the docs, " specifies a list of attributes for the context. - // The list consists of a sequence of pairs terminated by the - // value 0. [...]" - // Is this a single 0, or a <0, 0> pair? (Defensive coding: add two zeroes just in case). - attributes.Add(0); - attributes.Add(0); - - using (new XLock(Display)) - { - Handle = new ContextHandle(Glx.Arb.CreateContextAttribs(Display, *fbconfigs, - shareHandle.Handle, direct, attributes.ToArray())); - - if (Handle == ContextHandle.Zero) - { - Debug.Write(String.Format("failed. Trying direct: {0}... ", !direct)); - Handle = new ContextHandle(Glx.Arb.CreateContextAttribs(Display, *fbconfigs, - shareHandle.Handle, !direct, attributes.ToArray())); - } - } - - if (Handle == ContextHandle.Zero) - Debug.WriteLine("failed."); - else - Debug.WriteLine("success!"); - - using (new XLock(Display)) - { - Functions.XFree((IntPtr)fbconfigs); - } - } - } + Handle = CreateContextAttribs(Display, currentWindow.Screen, + fbconfig, direct, major, minor, flags, shareHandle); } if (Handle == ContextHandle.Zero) { - Debug.Write("Using legacy context creation... "); - - XVisualInfo info = currentWindow.VisualInfo; - using (new XLock(Display)) - { - // Cannot pass a Property by reference. - Handle = new ContextHandle(Glx.CreateContext(Display, ref info, shareHandle.Handle, direct)); - - if (Handle == ContextHandle.Zero) - { - Debug.WriteLine(String.Format("failed. Trying direct: {0}... ", !direct)); - Handle = new ContextHandle(Glx.CreateContext(Display, ref info, IntPtr.Zero, !direct)); - } - } + Handle = CreateContextLegacy(Display, currentWindow.VisualInfo, direct, shareHandle); } if (Handle != ContextHandle.Zero) @@ -208,6 +152,74 @@ namespace OpenTK.Platform.X11 #region --- Private Methods --- + static ContextHandle CreateContextAttribs( + IntPtr display, int screen, IntPtr fbconfig, + bool direct, int major, int minor, + GraphicsContextFlags flags, ContextHandle shareContext) + { + Debug.Write("Using GLX_ARB_create_context... "); + IntPtr context = IntPtr.Zero; + + { + // We need the FB config for the current GraphicsMode. + List attributes = new List(); + attributes.Add((int)ArbCreateContext.MajorVersion); + attributes.Add(major); + attributes.Add((int)ArbCreateContext.MinorVersion); + attributes.Add(minor); + if (flags != 0) + { + attributes.Add((int)ArbCreateContext.Flags); + attributes.Add((int)GetARBContextFlags(flags)); + attributes.Add((int)ArbCreateContext.ProfileMask); + attributes.Add((int)GetARBProfileFlags(flags)); + } + // According to the docs, " specifies a list of attributes for the context. + // The list consists of a sequence of pairs terminated by the + // value 0. [...]" + // Is this a single 0, or a <0, 0> pair? (Defensive coding: add two zeroes just in case). + attributes.Add(0); + attributes.Add(0); + + using (new XLock(display)) + { + context = Glx.Arb.CreateContextAttribs(display, fbconfig, shareContext.Handle, direct, attributes.ToArray()); + if (context == IntPtr.Zero) + { + Debug.Write(String.Format("failed. Trying direct: {0}... ", !direct)); + context = Glx.Arb.CreateContextAttribs(display, fbconfig, shareContext.Handle, !direct, attributes.ToArray()); + } + } + + if (context == IntPtr.Zero) + Debug.WriteLine("failed."); + else + Debug.WriteLine("success!"); + } + + return new ContextHandle(context); + } + + static ContextHandle CreateContextLegacy(IntPtr display, + XVisualInfo info, bool direct, ContextHandle shareContext) + { + Debug.Write("Using legacy context creation... "); + IntPtr context; + + using (new XLock(display)) + { + // Cannot pass a Property by reference. + context = Glx.CreateContext(display, ref info, shareContext.Handle, direct); + if (context == IntPtr.Zero) + { + Debug.WriteLine(String.Format("failed. Trying direct: {0}... ", !direct)); + context = Glx.CreateContext(display, ref info, IntPtr.Zero, !direct); + } + } + + return new ContextHandle(context); + } + IntPtr Display { get { return display; } @@ -221,38 +233,14 @@ namespace OpenTK.Platform.X11 } } - #region XVisualInfo SelectVisual(GraphicsMode mode, X11WindowInfo currentWindow) - - XVisualInfo SelectVisual(GraphicsMode mode, X11WindowInfo currentWindow) - { - XVisualInfo info = new XVisualInfo(); - info.VisualID = (IntPtr)mode.Index; - info.Screen = currentWindow.Screen; - int items; - - lock (API.Lock) - { - IntPtr vs = Functions.XGetVisualInfo(Display, XVisualInfoMask.ID | XVisualInfoMask.Screen, ref info, out items); - if (items == 0) - throw new GraphicsModeException(String.Format("Invalid GraphicsMode specified ({0}).", mode)); - - info = (XVisualInfo)Marshal.PtrToStructure(vs, typeof(XVisualInfo)); - Functions.XFree(vs); - } - - return info; - } - - #endregion - - ArbCreateContext GetARBContextFlags(GraphicsContextFlags flags) + static ArbCreateContext GetARBContextFlags(GraphicsContextFlags flags) { ArbCreateContext result = 0; result |= (flags & GraphicsContextFlags.Debug) != 0 ? ArbCreateContext.DebugBit : 0; return result; } - ArbCreateContext GetARBProfileFlags(GraphicsContextFlags flags) + static ArbCreateContext GetARBProfileFlags(GraphicsContextFlags flags) { ArbCreateContext result = 0; result |= (flags & GraphicsContextFlags.ForwardCompatible) != 0 ? diff --git a/Source/OpenTK/Platform/X11/X11GLNative.cs b/Source/OpenTK/Platform/X11/X11GLNative.cs index 9ae0784..388c45a 100644 --- a/Source/OpenTK/Platform/X11/X11GLNative.cs +++ b/Source/OpenTK/Platform/X11/X11GLNative.cs @@ -140,7 +140,7 @@ namespace OpenTK.Platform.X11 #region Constructors public X11GLNative(int x, int y, int width, int height, string title, - GraphicsMode mode,GameWindowFlags options, DisplayDevice device) + GraphicsMode mode, GameWindowFlags options, DisplayDevice device) : this() { if (width <= 0) @@ -154,17 +154,13 @@ namespace OpenTK.Platform.X11 using (new XLock(window.Display)) { - if (!mode.Index.HasValue) - { - mode = new X11GraphicsMode().SelectGraphicsMode( - mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, - mode.AccumulatorFormat, mode.Buffers, mode.Stereo); - } + IntPtr visual; + IntPtr fbconfig; + window.GraphicsMode = new X11GraphicsMode() + .SelectGraphicsMode(mode, out visual, out fbconfig); - info.VisualID = mode.Index.Value; - int dummy; - window.VisualInfo = (XVisualInfo)Marshal.PtrToStructure( - Functions.XGetVisualInfo(window.Display, XVisualInfoMask.ID, ref info, out dummy), typeof(XVisualInfo)); + window.Visual = visual; + window.FBConfig = fbconfig; // Create a window on this display using the visual above Debug.Write("Opening render window... "); diff --git a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs index 000f45e..9a76447 100644 --- a/Source/OpenTK/Platform/X11/X11GraphicsMode.cs +++ b/Source/OpenTK/Platform/X11/X11GraphicsMode.cs @@ -16,7 +16,7 @@ using OpenTK.Graphics; namespace OpenTK.Platform.X11 { - class X11GraphicsMode : IGraphicsMode + class X11GraphicsMode { // Todo: Add custom visual selection algorithm, instead of ChooseFBConfig/ChooseVisual. // It seems the Choose* methods do not take multisampling into account (at least on some @@ -32,34 +32,45 @@ namespace OpenTK.Platform.X11 #region IGraphicsMode Members - public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, - int buffers, bool stereo) + public GraphicsMode SelectGraphicsMode(GraphicsMode desired_mode, out IntPtr visual, out IntPtr fbconfig) { GraphicsMode gfx; - // The actual GraphicsMode that will be selected. - IntPtr visual = IntPtr.Zero; + GraphicsMode mode = new GraphicsMode(desired_mode); + visual = IntPtr.Zero; + fbconfig = IntPtr.Zero; IntPtr display = API.DefaultDisplay; do { // Try to select a visual using Glx.ChooseFBConfig and Glx.GetVisualFromFBConfig. // This is only supported on GLX 1.3 - if it fails, fall back to Glx.ChooseVisual. - visual = SelectVisualUsingFBConfig(color, depth, stencil, samples, accum, buffers, stereo); + fbconfig = SelectFBConfig(mode); + if (fbconfig != IntPtr.Zero) + visual = Glx.GetVisualFromFBConfig(display, fbconfig); if (visual == IntPtr.Zero) - visual = SelectVisualUsingChooseVisual(color, depth, stencil, samples, accum, buffers, stereo); + visual = SelectVisual(mode); if (visual == IntPtr.Zero) { // Relax parameters and retry - if (!Utilities.RelaxGraphicsMode(ref color, ref depth, ref stencil, ref samples, ref accum, ref buffers, ref stereo)) + if (!Utilities.RelaxGraphicsMode(ref mode)) throw new GraphicsModeException("Requested GraphicsMode not available."); } } while (visual == IntPtr.Zero); XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo)); + gfx = CreateGraphicsMode(display, ref info); + return gfx; + } + + #endregion + + #region Private Members + static GraphicsMode CreateGraphicsMode(IntPtr display, ref XVisualInfo info) + { // See what we *really* got: int r, g, b, a; Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out a); @@ -71,99 +82,84 @@ namespace OpenTK.Platform.X11 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); + int depth, stencil, samples, buffers; 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; - - gfx = new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples, - new ColorFormat(ar, ag, ab, aa), buffers, stereo); - - using (new XLock(display)) - { - Functions.XFree(visual); - } - - return gfx; - } - - #endregion - #region Private Members + // Note: Glx.GetConfig return buffers = 0 (false) or 1 (true). + // OpenTK expects buffers = 1 (single-) or 2 (double-buffering), + // so increase the GLX value by one. + return new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples, + new ColorFormat(ar, ag, ab, aa), buffers + 1, st != 0); + } - // See http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.opengl/doc/openglrf/glXChooseFBConfig.htm - // for the attribute declarations. Note that the attributes are different than those used in Glx.ChooseVisual. - IntPtr SelectVisualUsingFBConfig(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, - int buffers, bool stereo) + IntPtr SelectFBConfig(GraphicsMode mode) { + Debug.Print("Selecting FB config for {0}", mode); + List visualAttributes = new List(); IntPtr visual = IntPtr.Zero; - Debug.Print("Bits per pixel: {0}", color.BitsPerPixel); - - if (color.BitsPerPixel > 0) + if (mode.ColorFormat.BitsPerPixel > 0) { - if (!color.IsIndexed) + if (!mode.ColorFormat.IsIndexed) { - visualAttributes.Add((int)GLXAttribute.RGBA); - visualAttributes.Add(1); + visualAttributes.Add((int)GLXAttribute.RENDER_TYPE); + visualAttributes.Add((int)GLXRenderTypeMask.RGBA_BIT); } visualAttributes.Add((int)GLXAttribute.RED_SIZE); - visualAttributes.Add(color.Red); + visualAttributes.Add(mode.ColorFormat.Red); visualAttributes.Add((int)GLXAttribute.GREEN_SIZE); - visualAttributes.Add(color.Green); + visualAttributes.Add(mode.ColorFormat.Green); visualAttributes.Add((int)GLXAttribute.BLUE_SIZE); - visualAttributes.Add(color.Blue); + visualAttributes.Add(mode.ColorFormat.Blue); visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); - visualAttributes.Add(color.Alpha); + visualAttributes.Add(mode.ColorFormat.Alpha); } - Debug.Print("Depth: {0}", depth); - - if (depth > 0) + if (mode.Depth > 0) { visualAttributes.Add((int)GLXAttribute.DEPTH_SIZE); - visualAttributes.Add(depth); + visualAttributes.Add(mode.Depth); } - if (buffers > 1) + if (mode.Buffers > 1) { visualAttributes.Add((int)GLXAttribute.DOUBLEBUFFER); visualAttributes.Add(1); } - if (stencil > 1) + if (mode.Stereo) { visualAttributes.Add((int)GLXAttribute.STENCIL_SIZE); - visualAttributes.Add(stencil); + visualAttributes.Add(mode.Stereo ? 1 : 0); } - if (accum.BitsPerPixel > 0) + if (mode.AccumulatorFormat.BitsPerPixel > 0) { visualAttributes.Add((int)GLXAttribute.ACCUM_ALPHA_SIZE); - visualAttributes.Add(accum.Alpha); + visualAttributes.Add(mode.AccumulatorFormat.Alpha); visualAttributes.Add((int)GLXAttribute.ACCUM_BLUE_SIZE); - visualAttributes.Add(accum.Blue); + visualAttributes.Add(mode.AccumulatorFormat.Blue); visualAttributes.Add((int)GLXAttribute.ACCUM_GREEN_SIZE); - visualAttributes.Add(accum.Green); + visualAttributes.Add(mode.AccumulatorFormat.Green); visualAttributes.Add((int)GLXAttribute.ACCUM_RED_SIZE); - visualAttributes.Add(accum.Red); + visualAttributes.Add(mode.AccumulatorFormat.Red); } - - if (samples > 0) + + if (mode.Samples > 0) { visualAttributes.Add((int)GLXAttribute.SAMPLE_BUFFERS); visualAttributes.Add(1); visualAttributes.Add((int)GLXAttribute.SAMPLES); - visualAttributes.Add(samples); + visualAttributes.Add(mode.Samples); } - if (stereo) + if (mode.Stereo) { visualAttributes.Add((int)GLXAttribute.STEREO); visualAttributes.Add(1); @@ -173,6 +169,7 @@ namespace OpenTK.Platform.X11 // Select a visual that matches the parameters set by the user. IntPtr display = API.DefaultDisplay; + IntPtr result = IntPtr.Zero; using (new XLock(display)) { try @@ -180,7 +177,7 @@ namespace OpenTK.Platform.X11 int screen = Functions.XDefaultScreen(display); IntPtr root = Functions.XRootWindow(display, screen); Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root); - + unsafe { Debug.Print("Getting FB config."); @@ -190,81 +187,82 @@ namespace OpenTK.Platform.X11 if (fbcount > 0 && fbconfigs != null) { // We want to use the first GLXFBConfig from the fbconfigs array (the first one is the best match). - visual = Glx.GetVisualFromFBConfig(display, *fbconfigs); + Debug.Print("Selected FB config: {0}", *fbconfigs); + result = *fbconfigs; Functions.XFree((IntPtr)fbconfigs); } + else + { + Debug.Print("No matching FB config found."); + } } } catch (EntryPointNotFoundException) { Debug.Print("Function glXChooseFBConfig not supported."); - return IntPtr.Zero; } } - return visual; + return result; } - // See http://publib.boulder.ibm.com/infocenter/systems/index.jsp?topic=/com.ibm.aix.opengl/doc/openglrf/glXChooseVisual.htm - IntPtr SelectVisualUsingChooseVisual(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, - int buffers, bool stereo) + IntPtr SelectVisual(GraphicsMode mode) { - List visualAttributes = new List(); + Debug.Print("Selecting FB config for {0}", mode); - Debug.Print("Bits per pixel: {0}", color.BitsPerPixel); + List visualAttributes = new List(); - if (color.BitsPerPixel > 0) + if (mode.ColorFormat.BitsPerPixel > 0) { - if (!color.IsIndexed) + if (!mode.ColorFormat.IsIndexed) visualAttributes.Add((int)GLXAttribute.RGBA); visualAttributes.Add((int)GLXAttribute.RED_SIZE); - visualAttributes.Add(color.Red); + visualAttributes.Add(mode.ColorFormat.Red); visualAttributes.Add((int)GLXAttribute.GREEN_SIZE); - visualAttributes.Add(color.Green); + visualAttributes.Add(mode.ColorFormat.Green); visualAttributes.Add((int)GLXAttribute.BLUE_SIZE); - visualAttributes.Add(color.Blue); + visualAttributes.Add(mode.ColorFormat.Blue); visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); - visualAttributes.Add(color.Alpha); + visualAttributes.Add(mode.ColorFormat.Alpha); } - Debug.Print("Depth: {0}", depth); - if (depth > 0) + if (mode.Depth > 0) { visualAttributes.Add((int)GLXAttribute.DEPTH_SIZE); - visualAttributes.Add(depth); + visualAttributes.Add(mode.Depth); } - if (buffers > 1) + if (mode.Buffers > 1) visualAttributes.Add((int)GLXAttribute.DOUBLEBUFFER); - if (stencil > 1) + if (mode.Stencil > 1) { visualAttributes.Add((int)GLXAttribute.STENCIL_SIZE); - visualAttributes.Add(stencil); + visualAttributes.Add(mode.Stencil); } - if (accum.BitsPerPixel > 0) + if (mode.AccumulatorFormat.BitsPerPixel > 0) { visualAttributes.Add((int)GLXAttribute.ACCUM_ALPHA_SIZE); - visualAttributes.Add(accum.Alpha); + visualAttributes.Add(mode.AccumulatorFormat.Alpha); visualAttributes.Add((int)GLXAttribute.ACCUM_BLUE_SIZE); - visualAttributes.Add(accum.Blue); + visualAttributes.Add(mode.AccumulatorFormat.Blue); visualAttributes.Add((int)GLXAttribute.ACCUM_GREEN_SIZE); - visualAttributes.Add(accum.Green); + visualAttributes.Add(mode.AccumulatorFormat.Green); visualAttributes.Add((int)GLXAttribute.ACCUM_RED_SIZE); - visualAttributes.Add(accum.Red); + visualAttributes.Add(mode.AccumulatorFormat.Red); } - - if (samples > 0) + + if (mode.Samples > 0) { visualAttributes.Add((int)GLXAttribute.SAMPLE_BUFFERS); visualAttributes.Add(1); visualAttributes.Add((int)GLXAttribute.SAMPLES); - visualAttributes.Add(samples); + visualAttributes.Add(mode.Samples); } - if (stereo) + if (mode.Stereo) visualAttributes.Add((int)GLXAttribute.STEREO); visualAttributes.Add(0); diff --git a/Source/OpenTK/Platform/X11/X11WindowInfo.cs b/Source/OpenTK/Platform/X11/X11WindowInfo.cs index 740e51d..2b5b19a 100644 --- a/Source/OpenTK/Platform/X11/X11WindowInfo.cs +++ b/Source/OpenTK/Platform/X11/X11WindowInfo.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Runtime.InteropServices; using System.Text; namespace OpenTK.Platform.X11 @@ -87,7 +88,17 @@ namespace OpenTK.Platform.X11 /// Gets or sets the X11 screen. public int Screen { get { return screen; } set { screen = value; } } /// Gets or sets the X11 VisualInfo. - public XVisualInfo VisualInfo { get { return visualInfo; } set { visualInfo = value; } } + public XVisualInfo VisualInfo + { + get + { + if (Visual != IntPtr.Zero) + { + return (XVisualInfo)Marshal.PtrToStructure(Visual, typeof(XVisualInfo)); + } + return default(XVisualInfo); + } + } /// Gets or sets the X11 EventMask. public EventMask EventMask { get { return eventMask; } set { eventMask = value; } } @@ -96,6 +107,10 @@ namespace OpenTK.Platform.X11 // (e.g. MonoGame) public IntPtr WindowHandle { get { return Handle; } set { Handle = value; } } + public IntPtr Visual { get; set; } + public IntPtr FBConfig { get; set; } + public Graphics.GraphicsMode GraphicsMode { get; set; } + #endregion #region --- IDisposable Members --- -- 2.7.4