diff --git a/src/Avalonia.X11/Glx/Glx.cs b/src/Avalonia.X11/Glx/Glx.cs index 2382d66a84..de558e8e6a 100644 --- a/src/Avalonia.X11/Glx/Glx.cs +++ b/src/Avalonia.X11/Glx/Glx.cs @@ -18,7 +18,10 @@ namespace Avalonia.X11.Glx [DllImport(libGL, EntryPoint = "glXCreateContext")] public static extern IntPtr GlxCreateContext(IntPtr dpy, XVisualInfo* vis, IntPtr shareList, bool direct); - + + [DllImport(libGL, EntryPoint = "glXCreateContextAttribsARB")] + public static extern IntPtr GlxCreateContextAttribsARB(IntPtr dpy, IntPtr fbconfig, IntPtr shareList, + bool direct, int[] attribs); [DllImport(libGL, EntryPoint = "glXGetProcAddress")] public static extern IntPtr GlxGetProcAddress(Utf8Buffer buffer); diff --git a/src/Avalonia.X11/Glx/GlxConsts.cs b/src/Avalonia.X11/Glx/GlxConsts.cs index 71f6636371..65f253696a 100644 --- a/src/Avalonia.X11/Glx/GlxConsts.cs +++ b/src/Avalonia.X11/Glx/GlxConsts.cs @@ -93,5 +93,14 @@ namespace Avalonia.X11.Glx public const int GLX_SAMPLES = 0x186a1 /*100001*/; public const int GLX_PbufferClobber = 0; public const int GLX_BufferSwapComplete = 1; + public const int GLX_CONTEXT_DEBUG_BIT_ARB = 0x00000001; + public const int GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB = 0x00000002; + public const int GLX_CONTEXT_MAJOR_VERSION_ARB = 0x2091; + public const int GLX_CONTEXT_MINOR_VERSION_ARB = 0x2092; + public const int GLX_CONTEXT_FLAGS_ARB = 0x2094; + public const int GLX_CONTEXT_CORE_PROFILE_BIT_ARB = 0x00000001; + public const int GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB = 0x00000002; + public const int GLX_CONTEXT_PROFILE_MASK_ARB = 0x9126; + } } diff --git a/src/Avalonia.X11/Glx/GlxDisplay.cs b/src/Avalonia.X11/Glx/GlxDisplay.cs index 7ca2136709..7e6d2328e5 100644 --- a/src/Avalonia.X11/Glx/GlxDisplay.cs +++ b/src/Avalonia.X11/Glx/GlxDisplay.cs @@ -89,10 +89,38 @@ namespace Avalonia.X11.Glx public GlxContext CreateContext(IGlContext share) { var sharelist = ((GlxContext)share)?.Handle ?? IntPtr.Zero; - var h = GlxCreateContext(_x11.Display, _visual, sharelist, true); - if (h == IntPtr.Zero) + IntPtr handle = default; + foreach (var ver in new[] + { + new Version(4, 0), new Version(3, 2), + new Version(3, 0), new Version(2, 0) + }) + { + + var attrs = new[] + { + GLX_CONTEXT_MAJOR_VERSION_ARB, ver.Major, + GLX_CONTEXT_MINOR_VERSION_ARB, ver.Minor, + GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + 0 + }; + try + { + handle = GlxCreateContextAttribsARB(_x11.Display, _fbconfig, sharelist, true, attrs); + if (handle != IntPtr.Zero) + break; + } + catch + { + break; + } + } + + if(handle == IntPtr.Zero) + handle = GlxCreateContext(_x11.Display, _visual, sharelist, true); + if (handle == IntPtr.Zero) throw new OpenGlException("Unable to create direct GLX context"); - return new GlxContext(h, this, _x11); + return new GlxContext(handle, this, _x11); } public void SwapBuffers(IntPtr xid) => GlxSwapBuffers(_x11.Display, xid);