This commit is contained in:
thefiddler 2013-11-10 19:11:05 +01:00
commit 2c9d574b08
15 changed files with 190 additions and 136 deletions

View file

@ -38,7 +38,10 @@ namespace OpenTK
/// <summary>Provides information about the underlying OS and runtime.</summary> /// <summary>Provides information about the underlying OS and runtime.</summary>
public static class Configuration public static class Configuration
{ {
static bool runningOnWindows, runningOnUnix, runningOnX11, runningOnMacOS, runningOnLinux, runningOnMono; static bool runningOnWindows, runningOnUnix, runningOnX11, runningOnMacOS, runningOnLinux;
static bool runningOnMono;
static bool runningOnAndroid;
static bool? sdl2supported;
volatile static bool initialized; volatile static bool initialized;
readonly static object InitLock = new object(); readonly static object InitLock = new object();
@ -114,6 +117,26 @@ namespace OpenTK
#endregion #endregion
#region public static bool RunningOnAndroid
/// <summary>
/// Gets a <c>System.Boolean</c> indicating whether
/// OpenTK is running on an Android device.
/// </summary>
public static bool RunningOnAndroid
{
get
{
#if ANDROID
return true;
#else
return false;
#endif
}
}
#endregion
#region --- Private Methods --- #region --- Private Methods ---
#region private static string DetectUnixKernel() #region private static string DetectUnixKernel()

View file

@ -12,7 +12,7 @@ namespace OpenTK.Graphics.ES11
public sealed partial class GL : GraphicsBindingsBase public sealed partial class GL : GraphicsBindingsBase
{ {
const string Library = "libGLES.dll"; const string Library = "GLESv1_CM";
static readonly object sync_root = new object(); static readonly object sync_root = new object();
#region --- Protected Members --- #region --- Protected Members ---

View file

@ -180,6 +180,10 @@ namespace OpenTK.Input
get { return Wheel; } get { return Wheel; }
} }
/// <summary>
/// Gets a value indicating whether this instance is connected.
/// </summary>
/// <value><c>true</c> if this instance is connected; otherwise, <c>false</c>.</value>
public bool IsConnected public bool IsConnected
{ {
get { return is_connected; } get { return is_connected; }

View file

@ -5,6 +5,7 @@
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/> <dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/> <dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/> <dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/> <dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" /> <dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" /> <dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />

View file

@ -47,18 +47,18 @@ namespace OpenTK.Platform.MacOS
// Todo: keep track of which display adapter was specified when the context was created. // Todo: keep track of which display adapter was specified when the context was created.
// IntPtr displayID; // IntPtr displayID;
GraphicsMode graphics_mode;
CarbonWindowInfo carbonWindow; CarbonWindowInfo carbonWindow;
IntPtr shareContextRef; IntPtr shareContextRef;
DisplayDevice device; DisplayDevice device;
bool mIsFullscreen = false; bool mIsFullscreen = false;
readonly MacOSGraphicsMode ModeSelector = new MacOSGraphicsMode();
public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext) public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext)
{ {
Debug.Print("Context Type: {0}", shareContext); Debug.Print("Context Type: {0}", shareContext);
Debug.Print("Window info: {0}", window); Debug.Print("Window info: {0}", window);
this.graphics_mode = mode;
this.carbonWindow = (CarbonWindowInfo)window; this.carbonWindow = (CarbonWindowInfo)window;
if (shareContext is AglContext) if (shareContext is AglContext)
@ -105,50 +105,7 @@ namespace OpenTK.Platform.MacOS
} }
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen) void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen)
{ {
List<int> aglAttributes = new List<int>();
Debug.Print("AGL pixel format attributes:"); Debug.Print("AGL pixel format attributes:");
Debug.Indent();
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RED_SIZE, mode.ColorFormat.Red);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_GREEN_SIZE, mode.ColorFormat.Green);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_BLUE_SIZE, mode.ColorFormat.Blue);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ALPHA_SIZE, mode.ColorFormat.Alpha);
if (mode.Depth > 0)
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DEPTH_SIZE, mode.Depth);
if (mode.Stencil > 0)
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_STENCIL_SIZE, mode.Stencil);
if (mode.AccumulatorFormat.BitsPerPixel > 0)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE, mode.AccumulatorFormat.Red);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_GREEN_SIZE, mode.AccumulatorFormat.Green);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE, mode.AccumulatorFormat.Blue);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE, mode.AccumulatorFormat.Alpha);
}
if (mode.Samples > 1)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLE_BUFFERS_ARB, 1);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLES_ARB, mode.Samples);
}
if (fullscreen)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
}
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
Debug.Unindent();
Debug.Write("Attribute array: ");
for (int i = 0; i < aglAttributes.Count; i++)
Debug.Write(aglAttributes[i].ToString() + " ");
Debug.WriteLine("");
AGLPixelFormat myAGLPixelFormat; AGLPixelFormat myAGLPixelFormat;
@ -166,11 +123,13 @@ namespace OpenTK.Platform.MacOS
if (status != OSStatus.NoError) if (status != OSStatus.NoError)
throw new MacOSException(status, "DMGetGDeviceByDisplayID failed."); throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
myAGLPixelFormat = Agl.aglChoosePixelFormat(ref gdevice, 1, aglAttributes.ToArray()); myAGLPixelFormat = ModeSelector.SelectPixelFormat(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
true, gdevice);
Agl.AglError err = Agl.GetError(); Agl.AglError err = Agl.GetError();
if (myAGLPixelFormat == IntPtr.Zero || err == Agl.AglError.BadPixelFormat)
if (err == Agl.AglError.BadPixelFormat)
{ {
Debug.Print("Failed to create full screen pixel format."); Debug.Print("Failed to create full screen pixel format.");
Debug.Print("Trying again to create a non-fullscreen pixel format."); Debug.Print("Trying again to create a non-fullscreen pixel format.");
@ -179,21 +138,23 @@ namespace OpenTK.Platform.MacOS
return; return;
} }
} }
else else
{ {
myAGLPixelFormat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, aglAttributes.ToArray()); myAGLPixelFormat = ModeSelector.SelectPixelFormat(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
false, IntPtr.Zero);
MyAGLReportError("aglChoosePixelFormat"); MyAGLReportError("aglChoosePixelFormat");
} }
Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef); Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef);
// create the context and share it with the share reference. // create the context and share it with the share reference.
Handle = new ContextHandle(Agl.aglCreateContext(myAGLPixelFormat, shareContextRef)); Handle = new ContextHandle(Agl.aglCreateContext(myAGLPixelFormat, shareContextRef));
MyAGLReportError("aglCreateContext"); MyAGLReportError("aglCreateContext");
Mode = ModeSelector.GetGraphicsModeFromPixelFormat(myAGLPixelFormat);
// Free the pixel format from memory. // Free the pixel format from memory.
Agl.aglDestroyPixelFormat(myAGLPixelFormat); Agl.aglDestroyPixelFormat(myAGLPixelFormat);
MyAGLReportError("aglDestroyPixelFormat"); MyAGLReportError("aglDestroyPixelFormat");
@ -205,7 +166,6 @@ namespace OpenTK.Platform.MacOS
Update(carbonWindow); Update(carbonWindow);
MakeCurrent(carbonWindow); MakeCurrent(carbonWindow);
Debug.Print("context: {0}", Handle.Handle); Debug.Print("context: {0}", Handle.Handle);
} }
@ -290,10 +250,11 @@ namespace OpenTK.Platform.MacOS
windowPort = API.GetWindowPort(controlOwner); windowPort = API.GetWindowPort(controlOwner);
} }
else else
{
windowPort = API.GetWindowPort(carbonWindow.Handle); windowPort = API.GetWindowPort(carbonWindow.Handle);
}
return windowPort; return windowPort;
} }
public override void Update(IWindowInfo window) public override void Update(IWindowInfo window)

View file

@ -76,7 +76,7 @@ namespace OpenTK.Platform.MacOS
public virtual IGraphicsMode CreateGraphicsMode() public virtual IGraphicsMode CreateGraphicsMode()
{ {
return new MacOSGraphicsMode(); throw new NotSupportedException();
} }
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver() public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()

View file

@ -42,15 +42,17 @@ namespace OpenTK.Platform.MacOS
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil,
int samples, ColorFormat accum, int buffers, bool stereo) int samples, ColorFormat accum, int buffers, bool stereo)
{ {
IntPtr pixelformat = SelectPixelFormat(color, depth, stencil, samples, accum, buffers, stereo); IntPtr pixelformat = SelectPixelFormat(
color, depth, stencil, samples, accum, buffers, stereo,
false, IntPtr.Zero);
return GetGraphicsModeFromPixelFormat(pixelformat); return GetGraphicsModeFromPixelFormat(pixelformat);
} }
#endregion #endregion
#region Private Members #region Internal Members
GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat) internal GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat)
{ {
int r, g, b, a; int r, g, b, a;
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_RED_SIZE, out r); Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_RED_SIZE, out r);
@ -73,8 +75,8 @@ namespace OpenTK.Platform.MacOS
depth, stencil, samples, new ColorFormat(ar, ag, ab, aa), buffers + 1, stereo != 0); depth, stencil, samples, new ColorFormat(ar, ag, ab, aa), buffers + 1, stereo != 0);
} }
IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples, internal IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples,
ColorFormat accum, int buffers, bool stereo) ColorFormat accum, int buffers, bool stereo, bool fullscreen, IntPtr device)
{ {
List<int> attribs = new List<int>(); List<int> attribs = new List<int>();
@ -140,14 +142,22 @@ namespace OpenTK.Platform.MacOS
attribs.Add((int)Agl.PixelFormatAttribute.AGL_STEREO); attribs.Add((int)Agl.PixelFormatAttribute.AGL_STEREO);
} }
if (fullscreen)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_FULLSCREEN);
}
attribs.Add(0); attribs.Add(0);
attribs.Add(0); attribs.Add(0);
IntPtr pixelformat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, attribs.ToArray()); IntPtr pixelformat = IntPtr.Zero;
if (pixelformat == IntPtr.Zero) if (device != IntPtr.Zero)
{ {
throw new GraphicsModeException(String.Format( pixelformat = Agl.aglChoosePixelFormat(ref device, 0, attribs.ToArray());
"[Error] Failed to select GraphicsMode, error {0}.", Agl.GetError())); }
else
{
pixelformat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, attribs.ToArray());
} }
return pixelformat; return pixelformat;
} }

View file

@ -23,6 +23,9 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE. // OTHER DEALINGS IN THE SOFTWARE.
// //
using System.Runtime.InteropServices;
#endregion #endregion
using System; using System;
@ -301,6 +304,9 @@ namespace OpenTK.Platform.SDL2
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetAttribute", ExactSpelling = true)] [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetAttribute", ExactSpelling = true)]
public static extern int GetAttribute(ContextAttribute attr, out int value); public static extern int GetAttribute(ContextAttribute attr, out int value);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
public static extern IntPtr GetCurrentContext();
[SuppressUnmanagedCodeSecurity] [SuppressUnmanagedCodeSecurity]
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetDrawableSize", ExactSpelling = true)] [DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetDrawableSize", ExactSpelling = true)]
public static extern void GetDrawableSize(IntPtr window, out int w, out int h); public static extern void GetDrawableSize(IntPtr window, out int w, out int h);
@ -1177,6 +1183,25 @@ namespace OpenTK.Platform.SDL2
public uint Which; public uint Which;
public int X; public int X;
public int Y; public int Y;
public enum EventType : uint
{
/* Touch events */
FingerDown = 0x700,
FingerUp,
FingerMotion,
/* Gesture events */
DollarGesture = 0x800,
DollarRecord,
MultiGesture,
}
public const uint TouchMouseID = 0xffffffff;
public static class GL
{
}
} }
struct Rect struct Rect

View file

@ -69,17 +69,7 @@ namespace OpenTK.Platform.SDL2
// so we need to implement our own. // so we need to implement our own.
return (GraphicsContext.GetCurrentContextDelegate)delegate return (GraphicsContext.GetCurrentContextDelegate)delegate
{ {
IntPtr current; return Sdl2GraphicsContext.GetCurrentContext();
if (Configuration.RunningOnWindows)
current = OpenTK.Platform.Windows.Wgl.Imports.GetCurrentContext();
else if (Configuration.RunningOnX11)
current = OpenTK.Platform.X11.Glx.GetCurrentContext();
else if (Configuration.RunningOnMacOS)
current = OpenTK.Platform.MacOS.Cgl.GetCurrentContext();
else
throw new NotSupportedException("Unknown platform, please report to http://www.opentk.com");
return new ContextHandle(current);
}; };
} }

View file

@ -65,16 +65,17 @@ namespace OpenTK.Platform.SDL2
{ {
SetGLAttributes(mode, shareContext, major, minor, flags); SetGLAttributes(mode, shareContext, major, minor, flags);
SdlContext = new ContextHandle(SDL.GL.CreateContext(Window.Handle)); SdlContext = new ContextHandle(SDL.GL.CreateContext(Window.Handle));
if (SdlContext == ContextHandle.Zero)
{
var error = SDL.GetError();
Debug.Print("SDL2 failed to create OpenGL context: {0}", error);
throw new GraphicsContextException(error);
}
Mode = GetGLAttributes(SdlContext, out flags); Mode = GetGLAttributes(SdlContext, out flags);
Debug.Print("SDL2 created GraphicsContext (mode: {0}) (flags: {1}", Debug.Print("SDL2 created GraphicsContext (mode: {0}) (flags: {1})",
Mode, flags); Mode, flags);
} }
if (SdlContext == ContextHandle.Zero)
{
var error = SDL.GetError();
Debug.Print("SDL2 failed to create OpenGL context: {0}", error);
throw new GraphicsContextException(error);
}
Handle = GraphicsContext.GetCurrentContext(); Handle = GraphicsContext.GetCurrentContext();
} }
@ -254,6 +255,15 @@ namespace OpenTK.Platform.SDL2
#endregion #endregion
#region Public Members
public static ContextHandle GetCurrentContext()
{
return new ContextHandle(SDL.GL.GetCurrentContext());
}
#endregion
#region GraphicsContextBase Members #region GraphicsContextBase Members
public override void SwapBuffers() public override void SwapBuffers()

View file

@ -231,11 +231,14 @@ namespace OpenTK.Platform.X11
{ {
DebugBit = 0x0001, DebugBit = 0x0001,
ForwardCompatibleBit = 0x0002, ForwardCompatibleBit = 0x0002,
CoreProfileBit = 0x00000001,
CompatibilityProfileBit = 0x00000002,
MajorVersion = 0x2091, MajorVersion = 0x2091,
MinorVersion = 0x2092, MinorVersion = 0x2092,
LayerPlane = 0x2093, LayerPlane = 0x2093,
Flags = 0x2094, Flags = 0x2094,
ErrorInvalidVersion = 0x2095, ErrorInvalidVersion = 0x2095,
ProfileMask = 0x9126
} }
enum ErrorCode : int enum ErrorCode : int
@ -349,7 +352,7 @@ namespace OpenTK.Platform.X11
public partial class Arb public partial class Arb
{ {
#region CreateContextAttribs #region CreateContextAttri
unsafe public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs) unsafe public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs)
{ {
@ -368,6 +371,19 @@ namespace OpenTK.Platform.X11
} }
#endregion #endregion
#region GetProcAddress
// The linux OpenGL ABI 3.6 (1999) requires
// that glXGetProcAddressARB be available as
// a static export. The same is *not* true
// for glXGetProcAddress, so we should use
// glXGetProcAddressARB instead.
// See http://www.opengl.org/registry/ABI/
[DllImport(Library, EntryPoint = "glXGetProcAddressARB")]
public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName);
#endregion
} }
internal static partial class Delegates internal static partial class Delegates

View file

@ -20,17 +20,28 @@ namespace OpenTK.Platform.X11
const string Library = "libGL.so.1"; const string Library = "libGL.so.1";
static readonly object sync_root = new object(); static readonly object sync_root = new object();
// Disable BeforeFieldInit optimization. static Glx()
static Glx() { } {
// GLX entry points are not bound to a context.
// This means we can load them without creating
// a context first! (unlike WGL)
// See
// for more details.
Debug.WriteLine("Loading GLX entry points.");
new Glx().LoadEntryPoints();
}
protected override object SyncRoot protected override object SyncRoot
{ {
get { return sync_root; } get { return sync_root; }
} }
protected override IntPtr GetAddress (string funcname) protected override IntPtr GetAddress(string funcname)
{ {
return Glx.GetProcAddress(funcname); // We must use glXGetProcAddressARB, *not*
// glXGetProcAddress. See comment on function
// signature.
return Glx.Arb.GetProcAddress(funcname);
} }
#if false #if false

View file

@ -77,7 +77,7 @@ namespace OpenTK.Platform.X11
public virtual IGraphicsMode CreateGraphicsMode() public virtual IGraphicsMode CreateGraphicsMode()
{ {
return new X11GraphicsMode(); throw new NotSupportedException();
} }
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver() public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()

View file

@ -31,7 +31,7 @@ namespace OpenTK.Platform.X11
X11WindowInfo currentWindow; X11WindowInfo currentWindow;
bool vsync_supported; bool vsync_supported;
int swap_interval = 1; // As defined in GLX_SGI_swap_control int swap_interval = 1; // As defined in GLX_SGI_swap_control
bool glx_loaded; readonly X11GraphicsMode ModeSelector = new X11GraphicsMode();
#endregion #endregion
@ -45,14 +45,16 @@ namespace OpenTK.Platform.X11
if (window == null) if (window == null)
throw new ArgumentNullException("window"); throw new ArgumentNullException("window");
Mode = mode; Mode = ModeSelector.SelectGraphicsMode(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo);
// Do not move this lower, as almost everything requires the Display // Do not move this lower, as almost everything requires the Display
// property to be correctly set. // property to be correctly set.
Display = ((X11WindowInfo)window).Display; Display = ((X11WindowInfo)window).Display;
currentWindow = (X11WindowInfo)window; currentWindow = (X11WindowInfo)window;
currentWindow.VisualInfo = SelectVisual(mode, currentWindow); currentWindow.VisualInfo = SelectVisual(Mode, currentWindow);
ContextHandle shareHandle = shared != null ? ContextHandle shareHandle = shared != null ?
(shared as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero; (shared as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
@ -62,40 +64,13 @@ namespace OpenTK.Platform.X11
Debug.WriteLine(shareHandle.Handle == IntPtr.Zero ? "not shared... " : Debug.WriteLine(shareHandle.Handle == IntPtr.Zero ? "not shared... " :
String.Format("shared with ({0})... ", shareHandle)); String.Format("shared with ({0})... ", shareHandle));
if (!glx_loaded)
{
Debug.WriteLine("Creating temporary context to load GLX extensions.");
// Create a temporary context to obtain the necessary function pointers.
XVisualInfo visual = currentWindow.VisualInfo;
IntPtr ctx = IntPtr.Zero;
using (new XLock(Display))
{
ctx = Glx.CreateContext(Display, ref visual, IntPtr.Zero, true);
if (ctx == IntPtr.Zero)
ctx = Glx.CreateContext(Display, ref visual, IntPtr.Zero, false);
}
if (ctx != IntPtr.Zero)
{
new Glx().LoadEntryPoints();
using (new XLock(Display))
{
Glx.MakeCurrent(Display, IntPtr.Zero, IntPtr.Zero);
//Glx.DestroyContext(Display, ctx);
}
glx_loaded = true;
}
}
// Try using the new context creation method. If it fails, fall back to the old one. // Try using the new context creation method. If it fails, fall back to the old one.
// For each of these methods, we try two times to create a context: // For each of these methods, we try two times to create a context:
// one with the "direct" flag intact, the other with the flag inversed. // one with the "direct" flag intact, the other with the flag inversed.
// 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. Use legacy context // GLX_ARB_create_context, including hideous input lag, no vsync and other madness.
// 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) && Glx.Delegates.glXCreateContextAttribsARB != null) if ((major * 10 + minor >= 30) && SupportsCreateContextAttribs(Display, currentWindow))
{ {
Debug.Write("Using GLX_ARB_create_context... "); Debug.Write("Using GLX_ARB_create_context... ");
@ -106,7 +81,7 @@ namespace OpenTK.Platform.X11
IntPtr* fbconfigs = Glx.ChooseFBConfig(Display, currentWindow.Screen, IntPtr* fbconfigs = Glx.ChooseFBConfig(Display, currentWindow.Screen,
new int[] { new int[] {
(int)GLXAttribute.VISUAL_ID, (int)GLXAttribute.VISUAL_ID,
(int)mode.Index, (int)Mode.Index,
0 0
}, out count); }, out count);
@ -119,9 +94,10 @@ namespace OpenTK.Platform.X11
attributes.Add(minor); attributes.Add(minor);
if (flags != 0) if (flags != 0)
{ {
#warning "This is not entirely correct: Embedded is not a valid flag! We need to add a GetARBContextFlags(GraphicsContextFlags) method."
attributes.Add((int)ArbCreateContext.Flags); attributes.Add((int)ArbCreateContext.Flags);
attributes.Add((int)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. // 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 // The list consists of a sequence of <name,value> pairs terminated by the
@ -240,23 +216,46 @@ namespace OpenTK.Platform.X11
#endregion #endregion
bool SupportsExtension(X11WindowInfo window, string e) ArbCreateContext GetARBContextFlags(GraphicsContextFlags flags)
{
ArbCreateContext result = 0;
result |= (flags & GraphicsContextFlags.Debug) != 0 ? ArbCreateContext.DebugBit : 0;
return result;
}
ArbCreateContext GetARBProfileFlags(GraphicsContextFlags flags)
{
ArbCreateContext result = 0;
result |= (flags & GraphicsContextFlags.ForwardCompatible) != 0 ?
ArbCreateContext.ForwardCompatibleBit : ArbCreateContext.CompatibilityProfileBit;
return result;
}
static bool SupportsExtension(IntPtr display, X11WindowInfo window, string e)
{ {
if (window == null) if (window == null)
throw new ArgumentNullException("window"); throw new ArgumentNullException("window");
if (e == null) if (e == null)
throw new ArgumentNullException("e"); throw new ArgumentNullException("e");
if (window.Display != Display) if (window.Display != display)
throw new InvalidOperationException(); throw new InvalidOperationException();
string extensions = null; string extensions = null;
using (new XLock(Display)) using (new XLock(display))
{ {
extensions = Glx.QueryExtensionsString(Display, window.Screen); extensions = Glx.QueryExtensionsString(display, window.Screen);
} }
return !String.IsNullOrEmpty(extensions) && extensions.Contains(e); return !String.IsNullOrEmpty(extensions) && extensions.Contains(e);
} }
static bool SupportsCreateContextAttribs(IntPtr display, X11WindowInfo window)
{
return
SupportsExtension(display, window, "GLX_ARB_create_context") &&
SupportsExtension(display, window, "GLX_ARB_create_context_profile") &&
Glx.Delegates.glXCreateContextAttribsARB != null;
}
#endregion #endregion
#region --- IGraphicsContext Members --- #region --- IGraphicsContext Members ---

View file

@ -144,7 +144,11 @@ namespace OpenTK.Platform.X11
using (new XLock(window.Display)) using (new XLock(window.Display))
{ {
if (!mode.Index.HasValue) if (!mode.Index.HasValue)
throw new GraphicsModeException("Invalid or unsupported GraphicsMode."); {
mode = new X11GraphicsMode().SelectGraphicsMode(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo);
}
info.VisualID = mode.Index.Value; info.VisualID = mode.Index.Value;
int dummy; int dummy;
@ -1347,8 +1351,8 @@ namespace OpenTK.Platform.X11
public event EventHandler<EventArgs> WindowBorderChanged = delegate { }; public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
public event EventHandler<EventArgs> WindowStateChanged = delegate { }; public event EventHandler<EventArgs> WindowStateChanged = delegate { };
public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { }; public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { };
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { }; public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { }; public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
public event EventHandler<EventArgs> MouseEnter = delegate { }; public event EventHandler<EventArgs> MouseEnter = delegate { };
public event EventHandler<EventArgs> MouseLeave = delegate { }; public event EventHandler<EventArgs> MouseLeave = delegate { };