From 88905cb6aa964d2e159ea2e9ddafa92b83e96681 Mon Sep 17 00:00:00 2001 From: thefiddler Date: Mon, 12 May 2014 13:59:48 +0200 Subject: [PATCH] [X11] Fixed GLX extension loading GLX is now using the new extension loading mechanism, and the entry point names now much the available slots. --- Source/OpenTK/Platform/X11/Bindings/Glx.cs | 90 ++++++++++++++++------ Source/OpenTK/Platform/X11/X11GLContext.cs | 33 ++++---- 2 files changed, 87 insertions(+), 36 deletions(-) diff --git a/Source/OpenTK/Platform/X11/Bindings/Glx.cs b/Source/OpenTK/Platform/X11/Bindings/Glx.cs index 27c83695..dbd0c6e8 100644 --- a/Source/OpenTK/Platform/X11/Bindings/Glx.cs +++ b/Source/OpenTK/Platform/X11/Bindings/Glx.cs @@ -259,32 +259,75 @@ namespace OpenTK.Platform.X11 /// /// Provides access to GLX functions. /// - class Glx + class Glx : Graphics.GraphicsBindingsBase { const string Library = "libGL.so.1"; + static readonly object sync_root = new object(); - static string[] EntryPointNames = new string[] + static readonly byte[] EntryPointNames = new byte[] { - "glXCreateContextAttribs", - "glXSwapIntervalEXT", - "glXGetSwapIntervalEXT", - "glXSwapIntervalMESA", - "glXGetSwapIntervalMESA", - "glXSwapIntervalOML", - "glXGetSwapIntervalOML", - "glXSwapIntervalSGI", - "glXGetSwapIntervalSGI", + // glXCreateContextAttribsARB + 0x67, 0x6c, 0x58, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x41, 0x74, 0x74, 0x72, 0x69, 0x62, 0x73, 0x41, 0x52, 0x42, 0, + // glXSwapIntervalEXT + 0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x45, 0x58, 0x54, 0, + // glXGetSwapIntervalEXT + 0x67, 0x6c, 0x58, 0x47, 0x65, 0x74, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x45, 0x58, 0x54, 0, + // glXSwapIntervalMESA + 0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x45, 0x53, 0x41, 0, + // glXGetSwapIntervalMESA + 0x67, 0x6c, 0x58, 0x47, 0x65, 0x74, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x4d, 0x45, 0x53, 0x41, 0, + // glXSwapIntervalSGI + 0x67, 0x6c, 0x58, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x47, 0x49, 0, + // glXGetSwapIntervalSGI + 0x67, 0x6c, 0x58, 0x47, 0x65, 0x74, 0x53, 0x77, 0x61, 0x70, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x47, 0x49, 0, }; - static IntPtr[] EntryPoints = new IntPtr[EntryPointNames.Length]; + static readonly int[] EntryPointOffsets = new int[7]; + static IntPtr[] EntryPoints = new IntPtr[7]; - static Glx() + internal Glx() { // GLX entry points are not bound to a context. // This means we can load them without creating // a context first! (unlike WGL) - for (int i = 0; i < EntryPointNames.Length; i++) + _EntryPointsInstance = EntryPoints; + _EntryPointNamesInstance = EntryPointNames; + _EntryPointNameOffsetsInstance = EntryPointOffsets; + + // Writing the entry point name offsets + // by hand is error prone. Do it in code + // instead: + int offset = 0; + for (int i = 0, j = 0; i < EntryPointNames.Length; i++) { - EntryPoints[i] = Arb.GetProcAddress(EntryPointNames[i]); + if (EntryPointNames[i] == 0) + { + EntryPointOffsets[j++] = offset; + offset = i + 1; + } + } + } + + protected override object SyncRoot { get { return sync_root; } } + + protected override IntPtr GetAddress(string funcname) + { + return Arb.GetProcAddress(funcname); + } + + internal override void LoadEntryPoints() + { + unsafe + { + fixed (byte* name = _EntryPointNamesInstance) + { + for (int i = 0; i < _EntryPointsInstance.Length; i++) + { + System.Diagnostics.Debug.WriteLine(Marshal.PtrToStringAnsi( + new IntPtr(name + _EntryPointNameOffsetsInstance[i]))); + _EntryPointsInstance[i] = Arb.GetProcAddress( + new IntPtr(name + _EntryPointNameOffsetsInstance[i])); + } + } } } @@ -409,6 +452,9 @@ namespace OpenTK.Platform.X11 [DllImport(Library, EntryPoint = "glXGetProcAddressARB")] public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName); + [DllImport(Library, EntryPoint = "glXGetProcAddressARB")] + public static extern IntPtr GetProcAddress(IntPtr procName); + #endregion } @@ -458,25 +504,25 @@ namespace OpenTK.Platform.X11 } [Slot(0)] - [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] + [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] internal unsafe static extern IntPtr glXCreateContextAttribsARB(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs); [Slot(1)] - [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] + [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] internal static extern ErrorCode glXSwapIntervalEXT(int interval); [Slot(2)] - [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] + [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] internal static extern int glXGetSwapIntervalEXT(); [Slot(3)] - [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] + [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] internal static extern ErrorCode glXSwapIntervalMESA(int interval); [Slot(4)] - [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] + [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] internal static extern int glXGetSwapIntervalMESA(); [Slot(5)] - [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] + [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] internal static extern ErrorCode glXSwapIntervalSGI(int interval); [Slot(6)] - [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Winapi)] + [DllImport(Library, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] internal static extern int glXGetSwapIntervalSGI(); #endregion diff --git a/Source/OpenTK/Platform/X11/X11GLContext.cs b/Source/OpenTK/Platform/X11/X11GLContext.cs index 9596f0e3..18594eb5 100644 --- a/Source/OpenTK/Platform/X11/X11GLContext.cs +++ b/Source/OpenTK/Platform/X11/X11GLContext.cs @@ -41,6 +41,11 @@ namespace OpenTK.Platform.X11 #region --- Constructors --- + static X11GLContext() + { + new Glx().LoadEntryPoints(); + } + public X11GLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shared, bool direct, int major, int minor, GraphicsContextFlags flags) { @@ -258,8 +263,7 @@ namespace OpenTK.Platform.X11 { return SupportsExtension(display, window, "GLX_ARB_create_context") && - SupportsExtension(display, window, "GLX_ARB_create_context_profile") && - Glx.SupportsFunction("glXCreateContextAttribsARB"); + SupportsExtension(display, window, "GLX_ARB_create_context_profile"); } #endregion @@ -402,23 +406,24 @@ namespace OpenTK.Platform.X11 public override void LoadAll() { + // Note: GLX entry points are always available, even + // for extensions that are not currently supported by + // the underlying driver. This means we can only check + // the extension strings for support, not the entry + // points themselves. vsync_ext_supported = - SupportsExtension(display, currentWindow, "GLX_EXT_swap_control") && - Glx.SupportsFunction("glXSwapIntervalEXT") && - Glx.SupportsFunction("glXGetSwapIntervalEXT"); + SupportsExtension(display, currentWindow, "GLX_EXT_swap_control"); vsync_mesa_supported = - SupportsExtension(display, currentWindow, "GLX_MESA_swap_control") && - Glx.SupportsFunction("glXSwapIntervalMESA") && - Glx.SupportsFunction("glXGetSwapIntervalMESA"); + SupportsExtension(display, currentWindow, "GLX_MESA_swap_control"); vsync_sgi_supported = - SupportsExtension(display, currentWindow, "GLX_SGI_swap_control") && - Glx.SupportsFunction("glXSwapIntervalSGI"); - Debug.Print("Context supports vsync: {0}.", - vsync_ext_supported || vsync_mesa_supported || vsync_ext_supported); - + SupportsExtension(display, currentWindow, "GLX_SGI_swap_control"); vsync_tear_supported = SupportsExtension(display, currentWindow, "GLX_EXT_swap_control_tear"); - Debug.Print("Context supports vsync tear: {0}.", vsync_tear_supported); + + Debug.Print("Context supports vsync: {0}.", + vsync_ext_supported || vsync_mesa_supported || vsync_sgi_supported); + Debug.Print("Context supports adaptive vsync: {0}.", + vsync_tear_supported); base.LoadAll(); }