mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-01-09 20:55:32 +00:00
Merge pull request #153 from thefiddler/xwindowfix
[X11] INativeWindow fixes
This commit is contained in:
commit
358b4ddf35
|
@ -77,7 +77,22 @@ namespace OpenTK
|
||||||
if (control == null)
|
if (control == null)
|
||||||
throw new ArgumentNullException("control");
|
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(
|
if (xplatui == null) throw new PlatformNotSupportedException(
|
||||||
"System.Windows.Forms.XplatUIX11 missing. Unsupported platform or Mono runtime version, aborting.");
|
"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));
|
info = (XVisualInfo)Marshal.PtrToStructure(infoPtr, typeof(XVisualInfo));
|
||||||
|
|
||||||
// set the X11 colormap.
|
// 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, "CustomVisual", info.Visual);
|
||||||
SetStaticFieldValue(xplatui, "CustomColormap", XCreateColormap(display, rootWindow, info.Visual, 0));
|
SetStaticFieldValue(xplatui, "CustomColormap", XCreateColormap(display, rootWindow, info.Visual, 0));
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,12 +78,25 @@ 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 == null || !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, visual, 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,73 @@ 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,
|
||||||
|
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
|
IntPtr Display
|
||||||
{
|
{
|
||||||
get { return display; }
|
get { return display; }
|
||||||
|
@ -221,38 +232,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 ?
|
||||||
|
|
|
@ -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... ");
|
||||||
|
@ -825,7 +821,7 @@ namespace OpenTK.Platform.X11
|
||||||
case XEventName.ClientMessage:
|
case XEventName.ClientMessage:
|
||||||
if (!isExiting && e.ClientMessageEvent.ptr1 == _atom_wm_destroy)
|
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();
|
CancelEventArgs ce = new CancelEventArgs();
|
||||||
OnClosing(ce);
|
OnClosing(ce);
|
||||||
|
|
||||||
|
@ -892,7 +888,7 @@ namespace OpenTK.Platform.X11
|
||||||
int x = e.MotionEvent.x;
|
int x = e.MotionEvent.x;
|
||||||
int y = e.MotionEvent.y;
|
int y = e.MotionEvent.y;
|
||||||
|
|
||||||
if (x != 0 || y != 0)
|
if (x != MouseState.X || y != MouseState.Y)
|
||||||
{
|
{
|
||||||
OnMouseMove(
|
OnMouseMove(
|
||||||
MathHelper.Clamp(x, 0, Width),
|
MathHelper.Clamp(x, 0, Width),
|
||||||
|
@ -1624,6 +1620,8 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
public void Exit()
|
public void Exit()
|
||||||
{
|
{
|
||||||
|
Debug.Print("[X11] Sending exit message window {0:X} on display {1:X}", window.Handle, window.Display);
|
||||||
|
|
||||||
XEvent ev = new XEvent();
|
XEvent ev = new XEvent();
|
||||||
ev.type = XEventName.ClientMessage;
|
ev.type = XEventName.ClientMessage;
|
||||||
ev.ClientMessageEvent.format = 32;
|
ev.ClientMessageEvent.format = 32;
|
||||||
|
@ -1644,10 +1642,12 @@ namespace OpenTK.Platform.X11
|
||||||
|
|
||||||
public void DestroyWindow()
|
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))
|
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);
|
Functions.XDestroyWindow(window.Display, window.Handle);
|
||||||
exists = false;
|
exists = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
|
||||||
|
|
||||||
gfx = new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples,
|
// Note: Glx.GetConfig return buffers = 0 (false) or 1 (true).
|
||||||
new ColorFormat(ar, ag, ab, aa), buffers, stereo);
|
// OpenTK expects buffers = 1 (single-) or 2 (double-buffering),
|
||||||
|
// so increase the GLX value by one.
|
||||||
using (new XLock(display))
|
return new GraphicsMode(info.VisualID, new ColorFormat(r, g, b, a), depth, stencil, samples,
|
||||||
{
|
new ColorFormat(ar, ag, ab, aa), buffers + 1, st != 0);
|
||||||
Functions.XFree(visual);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return gfx;
|
IntPtr SelectFBConfig(GraphicsMode mode)
|
||||||
}
|
|
||||||
|
|
||||||
#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)
|
|
||||||
{
|
{
|
||||||
|
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
|
||||||
|
@ -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);
|
||||||
|
|
|
@ -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 ---
|
||||||
|
|
Loading…
Reference in a new issue