Merge pull request #153 from thefiddler/xwindowfix

[X11] INativeWindow fixes
This commit is contained in:
thefiddler 2014-07-20 11:46:43 +02:00
commit 358b4ddf35
6 changed files with 224 additions and 211 deletions

View file

@ -77,7 +77,22 @@ namespace OpenTK
if (control == null)
throw new ArgumentNullException("control");
this.mode = mode;
// Note: the X11 window is created with a default XVisualInfo,
// that is not necessarily compatible with the desired GraphicsMode.
// This manifests in Nvidia binary drivers that fail in Glx.MakeCurrent()
// when GraphicsMode has a 32bpp color format.
// To work around this issue, we implicitly select a 24bpp color format when 32bpp is
// requested - this appears to work correctly in all cases.
// (The loss of the alpha channel does not matter, since WinForms do not support
// translucent windows on X11 in the first place.)
this.mode = new GraphicsMode(
new ColorFormat(mode.ColorFormat.Red, mode.ColorFormat.Green, mode.ColorFormat.Blue, 0),
mode.Depth,
mode.Stencil,
mode.Samples,
mode.AccumulatorFormat,
mode.Buffers,
mode.Stereo);
if (xplatui == null) throw new PlatformNotSupportedException(
"System.Windows.Forms.XplatUIX11 missing. Unsupported platform or Mono runtime version, aborting.");
@ -105,6 +120,8 @@ namespace OpenTK
info = (XVisualInfo)Marshal.PtrToStructure(infoPtr, typeof(XVisualInfo));
// set the X11 colormap.
// Note: this only affects windows created in the future
// (do we even need this here?)
SetStaticFieldValue(xplatui, "CustomVisual", info.Visual);
SetStaticFieldValue(xplatui, "CustomColormap", XCreateColormap(display, rootWindow, info.Visual, 0));

View file

@ -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;
}

View file

@ -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 == null || !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<int> attributes = new List<int>();
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, " <attribList> specifies a list of attributes for the context.
// The list consists of a sequence of <name,value> 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, visual, direct, shareHandle);
}
if (Handle != ContextHandle.Zero)
@ -208,6 +152,73 @@ 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<int> attributes = new List<int>();
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, " <attribList> specifies a list of attributes for the context.
// The list consists of a sequence of <name,value> 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,
IntPtr info, bool direct, ContextHandle shareContext)
{
Debug.Write("Using legacy context creation... ");
IntPtr context;
using (new XLock(display))
{
context = Glx.CreateContext(display, info, shareContext.Handle, direct);
if (context == IntPtr.Zero)
{
Debug.WriteLine(String.Format("failed. Trying direct: {0}... ", !direct));
context = Glx.CreateContext(display, info, shareContext.Handle, !direct);
}
}
return new ContextHandle(context);
}
IntPtr Display
{
get { return display; }
@ -221,38 +232,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 ?

View file

@ -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... ");
@ -825,7 +821,7 @@ namespace OpenTK.Platform.X11
case XEventName.ClientMessage:
if (!isExiting && e.ClientMessageEvent.ptr1 == _atom_wm_destroy)
{
Debug.WriteLine("Exit message received.");
Debug.Print("[X11] Exit message received for window {0:X} on display {1:X}", window.Handle, window.Display);
CancelEventArgs ce = new CancelEventArgs();
OnClosing(ce);
@ -892,7 +888,7 @@ namespace OpenTK.Platform.X11
int x = e.MotionEvent.x;
int y = e.MotionEvent.y;
if (x != 0 || y != 0)
if (x != MouseState.X || y != MouseState.Y)
{
OnMouseMove(
MathHelper.Clamp(x, 0, Width),
@ -1624,6 +1620,8 @@ namespace OpenTK.Platform.X11
public void Exit()
{
Debug.Print("[X11] Sending exit message window {0:X} on display {1:X}", window.Handle, window.Display);
XEvent ev = new XEvent();
ev.type = XEventName.ClientMessage;
ev.ClientMessageEvent.format = 32;
@ -1644,10 +1642,12 @@ namespace OpenTK.Platform.X11
public void DestroyWindow()
{
Debug.WriteLine("X11GLNative shutdown sequence initiated.");
Debug.Print("[X11] Destroying window {0:X} on display {1:X}", window.Handle, window.Display);
using (new XLock(window.Display))
{
Functions.XSync(window.Display, true);
Functions.XUnmapWindow(window.Display, window.Handle);
Functions.XSync(window.Display, false);
Functions.XDestroyWindow(window.Display, window.Handle);
exists = false;
}

View file

@ -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;
// 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);
}
#endregion
#region Private Members
// 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<int> visualAttributes = new List<int>();
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)
{
Debug.Print("Selecting FB config for {0}", mode);
List<int> visualAttributes = new List<int>();
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((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);

View file

@ -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
/// <summary>Gets or sets the X11 screen.</summary>
public int Screen { get { return screen; } set { screen = value; } }
/// <summary>Gets or sets the X11 VisualInfo.</summary>
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);
}
}
/// <summary>Gets or sets the X11 EventMask.</summary>
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 ---