[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.)
This commit is contained in:
Stefanos A. 2014-07-19 20:39:17 +02:00
parent a13a2f8e66
commit d75a2ce439
5 changed files with 199 additions and 206 deletions

View file

@ -248,11 +248,7 @@ namespace OpenTK.Platform
window.Screen = screen; window.Screen = screen;
window.Handle = windowHandle; window.Handle = windowHandle;
window.RootWindow = rootWindow; window.RootWindow = rootWindow;
if (visualInfo != IntPtr.Zero) window.Visual = visualInfo;
{
window.VisualInfo = (X11.XVisualInfo)Marshal.PtrToStructure(visualInfo, typeof(X11.XVisualInfo));
}
return window; return window;
} }

View file

@ -78,13 +78,26 @@ namespace OpenTK.Platform.X11
} }
} }
Mode = ModeSelector.SelectGraphicsMode( IntPtr visual = IntPtr.Zero;
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, IntPtr fbconfig = IntPtr.Zero;
mode.AccumulatorFormat, mode.Buffers, mode.Stereo);
// 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 = (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 ? ContextHandle shareHandle = shared != null ?
(shared as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero; (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 // 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. // 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. // 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... "); Handle = CreateContextAttribs(Display, currentWindow.Screen,
fbconfig, direct, major, minor, flags, shareHandle);
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);
}
}
}
} }
if (Handle == ContextHandle.Zero) if (Handle == ContextHandle.Zero)
{ {
Debug.Write("Using legacy context creation... "); Handle = CreateContextLegacy(Display, currentWindow.VisualInfo, direct, shareHandle);
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));
}
}
} }
if (Handle != ContextHandle.Zero) if (Handle != ContextHandle.Zero)
@ -208,6 +152,74 @@ namespace OpenTK.Platform.X11
#region --- Private Methods --- #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,
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 IntPtr Display
{ {
get { return display; } get { return display; }
@ -221,38 +233,14 @@ namespace OpenTK.Platform.X11
} }
} }
#region XVisualInfo SelectVisual(GraphicsMode mode, X11WindowInfo currentWindow) static ArbCreateContext GetARBContextFlags(GraphicsContextFlags flags)
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)
{ {
ArbCreateContext result = 0; ArbCreateContext result = 0;
result |= (flags & GraphicsContextFlags.Debug) != 0 ? ArbCreateContext.DebugBit : 0; result |= (flags & GraphicsContextFlags.Debug) != 0 ? ArbCreateContext.DebugBit : 0;
return result; return result;
} }
ArbCreateContext GetARBProfileFlags(GraphicsContextFlags flags) static ArbCreateContext GetARBProfileFlags(GraphicsContextFlags flags)
{ {
ArbCreateContext result = 0; ArbCreateContext result = 0;
result |= (flags & GraphicsContextFlags.ForwardCompatible) != 0 ? result |= (flags & GraphicsContextFlags.ForwardCompatible) != 0 ?

View file

@ -140,7 +140,7 @@ namespace OpenTK.Platform.X11
#region Constructors #region Constructors
public X11GLNative(int x, int y, int width, int height, string title, 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() : this()
{ {
if (width <= 0) if (width <= 0)
@ -154,17 +154,13 @@ namespace OpenTK.Platform.X11
using (new XLock(window.Display)) using (new XLock(window.Display))
{ {
if (!mode.Index.HasValue) IntPtr visual;
{ IntPtr fbconfig;
mode = new X11GraphicsMode().SelectGraphicsMode( window.GraphicsMode = new X11GraphicsMode()
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, .SelectGraphicsMode(mode, out visual, out fbconfig);
mode.AccumulatorFormat, mode.Buffers, mode.Stereo);
}
info.VisualID = mode.Index.Value; window.Visual = visual;
int dummy; window.FBConfig = fbconfig;
window.VisualInfo = (XVisualInfo)Marshal.PtrToStructure(
Functions.XGetVisualInfo(window.Display, XVisualInfoMask.ID, ref info, out dummy), typeof(XVisualInfo));
// Create a window on this display using the visual above // Create a window on this display using the visual above
Debug.Write("Opening render window... "); Debug.Write("Opening render window... ");

View file

@ -16,7 +16,7 @@ using OpenTK.Graphics;
namespace OpenTK.Platform.X11 namespace OpenTK.Platform.X11
{ {
class X11GraphicsMode : IGraphicsMode class X11GraphicsMode
{ {
// Todo: Add custom visual selection algorithm, instead of ChooseFBConfig/ChooseVisual. // 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 // 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 #region IGraphicsMode Members
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum, public GraphicsMode SelectGraphicsMode(GraphicsMode desired_mode, out IntPtr visual, out IntPtr fbconfig)
int buffers, bool stereo)
{ {
GraphicsMode gfx; GraphicsMode gfx;
// The actual GraphicsMode that will be selected. GraphicsMode mode = new GraphicsMode(desired_mode);
IntPtr visual = IntPtr.Zero; visual = IntPtr.Zero;
fbconfig = IntPtr.Zero;
IntPtr display = API.DefaultDisplay; IntPtr display = API.DefaultDisplay;
do do
{ {
// Try to select a visual using Glx.ChooseFBConfig and Glx.GetVisualFromFBConfig. // 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. // 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) if (visual == IntPtr.Zero)
visual = SelectVisualUsingChooseVisual(color, depth, stencil, samples, accum, buffers, stereo); visual = SelectVisual(mode);
if (visual == IntPtr.Zero) if (visual == IntPtr.Zero)
{ {
// Relax parameters and retry // 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."); throw new GraphicsModeException("Requested GraphicsMode not available.");
} }
} }
while (visual == IntPtr.Zero); while (visual == IntPtr.Zero);
XVisualInfo info = (XVisualInfo)Marshal.PtrToStructure(visual, typeof(XVisualInfo)); 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: // See what we *really* got:
int r, g, b, a; int r, g, b, a;
Glx.GetConfig(display, ref info, GLXAttribute.ALPHA_SIZE, out 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_RED_SIZE, out ar);
Glx.GetConfig(display, ref info, GLXAttribute.ACCUM_GREEN_SIZE, out ag); 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.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.DEPTH_SIZE, out depth);
Glx.GetConfig(display, ref info, GLXAttribute.STENCIL_SIZE, out stencil); 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.SAMPLES, out samples);
Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers); Glx.GetConfig(display, ref info, GLXAttribute.DOUBLEBUFFER, out buffers);
++buffers;
// the above lines returns 0 - false and 1 - true.
int st; int st;
Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st); Glx.GetConfig(display, ref info, GLXAttribute.STEREO, out st);
stereo = st != 0;
// Note: Glx.GetConfig return buffers = 0 (false) or 1 (true).
gfx = new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples, // OpenTK expects buffers = 1 (single-) or 2 (double-buffering),
new ColorFormat(ar, ag, ab, aa), buffers, stereo); // so increase the GLX value by one.
return new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples,
using (new XLock(display)) new ColorFormat(ar, ag, ab, aa), buffers + 1, st != 0);
{
Functions.XFree(visual);
}
return gfx;
} }
#endregion IntPtr SelectFBConfig(GraphicsMode mode)
#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)
{ {
Debug.Print("Selecting FB config for {0}", mode);
List<int> visualAttributes = new List<int>(); List<int> visualAttributes = new List<int>();
IntPtr visual = IntPtr.Zero; IntPtr visual = IntPtr.Zero;
Debug.Print("Bits per pixel: {0}", color.BitsPerPixel); if (mode.ColorFormat.BitsPerPixel > 0)
if (color.BitsPerPixel > 0)
{ {
if (!color.IsIndexed) if (!mode.ColorFormat.IsIndexed)
{ {
visualAttributes.Add((int)GLXAttribute.RGBA); visualAttributes.Add((int)GLXAttribute.RENDER_TYPE);
visualAttributes.Add(1); visualAttributes.Add((int)GLXRenderTypeMask.RGBA_BIT);
} }
visualAttributes.Add((int)GLXAttribute.RED_SIZE); visualAttributes.Add((int)GLXAttribute.RED_SIZE);
visualAttributes.Add(color.Red); visualAttributes.Add(mode.ColorFormat.Red);
visualAttributes.Add((int)GLXAttribute.GREEN_SIZE); visualAttributes.Add((int)GLXAttribute.GREEN_SIZE);
visualAttributes.Add(color.Green); visualAttributes.Add(mode.ColorFormat.Green);
visualAttributes.Add((int)GLXAttribute.BLUE_SIZE); visualAttributes.Add((int)GLXAttribute.BLUE_SIZE);
visualAttributes.Add(color.Blue); visualAttributes.Add(mode.ColorFormat.Blue);
visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE);
visualAttributes.Add(color.Alpha); visualAttributes.Add(mode.ColorFormat.Alpha);
} }
Debug.Print("Depth: {0}", depth); if (mode.Depth > 0)
if (depth > 0)
{ {
visualAttributes.Add((int)GLXAttribute.DEPTH_SIZE); 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((int)GLXAttribute.DOUBLEBUFFER);
visualAttributes.Add(1); visualAttributes.Add(1);
} }
if (stencil > 1) if (mode.Stereo)
{ {
visualAttributes.Add((int)GLXAttribute.STENCIL_SIZE); 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((int)GLXAttribute.ACCUM_ALPHA_SIZE);
visualAttributes.Add(accum.Alpha); visualAttributes.Add(mode.AccumulatorFormat.Alpha);
visualAttributes.Add((int)GLXAttribute.ACCUM_BLUE_SIZE); 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((int)GLXAttribute.ACCUM_GREEN_SIZE);
visualAttributes.Add(accum.Green); visualAttributes.Add(mode.AccumulatorFormat.Green);
visualAttributes.Add((int)GLXAttribute.ACCUM_RED_SIZE); 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((int)GLXAttribute.SAMPLE_BUFFERS);
visualAttributes.Add(1); visualAttributes.Add(1);
visualAttributes.Add((int)GLXAttribute.SAMPLES); visualAttributes.Add((int)GLXAttribute.SAMPLES);
visualAttributes.Add(samples); visualAttributes.Add(mode.Samples);
} }
if (stereo) if (mode.Stereo)
{ {
visualAttributes.Add((int)GLXAttribute.STEREO); visualAttributes.Add((int)GLXAttribute.STEREO);
visualAttributes.Add(1); visualAttributes.Add(1);
@ -173,6 +169,7 @@ namespace OpenTK.Platform.X11
// Select a visual that matches the parameters set by the user. // Select a visual that matches the parameters set by the user.
IntPtr display = API.DefaultDisplay; IntPtr display = API.DefaultDisplay;
IntPtr result = IntPtr.Zero;
using (new XLock(display)) using (new XLock(display))
{ {
try try
@ -180,7 +177,7 @@ namespace OpenTK.Platform.X11
int screen = Functions.XDefaultScreen(display); int screen = Functions.XDefaultScreen(display);
IntPtr root = Functions.XRootWindow(display, screen); IntPtr root = Functions.XRootWindow(display, screen);
Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root); Debug.Print("Display: {0}, Screen: {1}, RootWindow: {2}", display, screen, root);
unsafe unsafe
{ {
Debug.Print("Getting FB config."); Debug.Print("Getting FB config.");
@ -190,81 +187,82 @@ namespace OpenTK.Platform.X11
if (fbcount > 0 && fbconfigs != null) if (fbcount > 0 && fbconfigs != null)
{ {
// We want to use the first GLXFBConfig from the fbconfigs array (the first one is the best match). // 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); Functions.XFree((IntPtr)fbconfigs);
} }
else
{
Debug.Print("No matching FB config found.");
}
} }
} }
catch (EntryPointNotFoundException) catch (EntryPointNotFoundException)
{ {
Debug.Print("Function glXChooseFBConfig not supported."); 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 SelectVisual(GraphicsMode mode)
IntPtr SelectVisualUsingChooseVisual(ColorFormat color, int depth, int stencil, int samples, ColorFormat accum,
int buffers, bool stereo)
{ {
Debug.Print("Selecting FB config for {0}", mode);
List<int> visualAttributes = new List<int>(); List<int> visualAttributes = new List<int>();
Debug.Print("Bits per pixel: {0}", color.BitsPerPixel); if (mode.ColorFormat.BitsPerPixel > 0)
if (color.BitsPerPixel > 0)
{ {
if (!color.IsIndexed) if (!mode.ColorFormat.IsIndexed)
visualAttributes.Add((int)GLXAttribute.RGBA); visualAttributes.Add((int)GLXAttribute.RGBA);
visualAttributes.Add((int)GLXAttribute.RED_SIZE); visualAttributes.Add((int)GLXAttribute.RED_SIZE);
visualAttributes.Add(color.Red); visualAttributes.Add(mode.ColorFormat.Red);
visualAttributes.Add((int)GLXAttribute.GREEN_SIZE); visualAttributes.Add((int)GLXAttribute.GREEN_SIZE);
visualAttributes.Add(color.Green); visualAttributes.Add(mode.ColorFormat.Green);
visualAttributes.Add((int)GLXAttribute.BLUE_SIZE); visualAttributes.Add((int)GLXAttribute.BLUE_SIZE);
visualAttributes.Add(color.Blue); visualAttributes.Add(mode.ColorFormat.Blue);
visualAttributes.Add((int)GLXAttribute.ALPHA_SIZE); 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((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((int)GLXAttribute.DOUBLEBUFFER);
if (stencil > 1) if (mode.Stencil > 1)
{ {
visualAttributes.Add((int)GLXAttribute.STENCIL_SIZE); 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((int)GLXAttribute.ACCUM_ALPHA_SIZE);
visualAttributes.Add(accum.Alpha); visualAttributes.Add(mode.AccumulatorFormat.Alpha);
visualAttributes.Add((int)GLXAttribute.ACCUM_BLUE_SIZE); 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((int)GLXAttribute.ACCUM_GREEN_SIZE);
visualAttributes.Add(accum.Green); visualAttributes.Add(mode.AccumulatorFormat.Green);
visualAttributes.Add((int)GLXAttribute.ACCUM_RED_SIZE); 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((int)GLXAttribute.SAMPLE_BUFFERS);
visualAttributes.Add(1); visualAttributes.Add(1);
visualAttributes.Add((int)GLXAttribute.SAMPLES); visualAttributes.Add((int)GLXAttribute.SAMPLES);
visualAttributes.Add(samples); visualAttributes.Add(mode.Samples);
} }
if (stereo) if (mode.Stereo)
visualAttributes.Add((int)GLXAttribute.STEREO); visualAttributes.Add((int)GLXAttribute.STEREO);
visualAttributes.Add(0); visualAttributes.Add(0);

View file

@ -27,6 +27,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
namespace OpenTK.Platform.X11 namespace OpenTK.Platform.X11
@ -87,7 +88,17 @@ namespace OpenTK.Platform.X11
/// <summary>Gets or sets the X11 screen.</summary> /// <summary>Gets or sets the X11 screen.</summary>
public int Screen { get { return screen; } set { screen = value; } } public int Screen { get { return screen; } set { screen = value; } }
/// <summary>Gets or sets the X11 VisualInfo.</summary> /// <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> /// <summary>Gets or sets the X11 EventMask.</summary>
public EventMask EventMask { get { return eventMask; } set { eventMask = value; } } public EventMask EventMask { get { return eventMask; } set { eventMask = value; } }
@ -96,6 +107,10 @@ namespace OpenTK.Platform.X11
// (e.g. MonoGame) // (e.g. MonoGame)
public IntPtr WindowHandle { get { return Handle; } set { Handle = value; } } 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 #endregion
#region --- IDisposable Members --- #region --- IDisposable Members ---