diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs index 718afc4a94..f556949cfa 100644 --- a/src/Avalonia.OpenGL/GlInterface.cs +++ b/src/Avalonia.OpenGL/GlInterface.cs @@ -9,12 +9,14 @@ namespace Avalonia.OpenGL public class GlInterface : GlInterfaceBase { public string Version { get; } + public string Vendor { get; } + public string Renderer { get; } public GlInterface(Func getProcAddress) : base(getProcAddress) { - var versionPtr = GetString(GlConsts.GL_VERSION); - if (versionPtr != IntPtr.Zero) - Version = Marshal.PtrToStringAnsi(versionPtr); + Version = GetString(GlConsts.GL_VERSION); + Renderer = GetString(GlConsts.GL_RENDERER); + Vendor = GetString(GlConsts.GL_VENDOR); } public GlInterface(Func n) : this(ConvertNative(n)) @@ -54,7 +56,15 @@ namespace Avalonia.OpenGL public delegate IntPtr GlGetString(int v); [GlEntryPoint("glGetString")] - public GlGetString GetString { get; } + public GlGetString GetStringNative { get; } + + public string GetString(int v) + { + var ptr = GetStringNative(v); + if (ptr != IntPtr.Zero) + return Marshal.PtrToStringAnsi(ptr); + return null; + } public delegate void GlGetIntegerv(int name, out int rv); [GlEntryPoint("glGetIntegerv")] diff --git a/src/Avalonia.X11/Glx/GlxDisplay.cs b/src/Avalonia.X11/Glx/GlxDisplay.cs index 5602b33280..04f2a7137c 100644 --- a/src/Avalonia.X11/Glx/GlxDisplay.cs +++ b/src/Avalonia.X11/Glx/GlxDisplay.cs @@ -90,6 +90,19 @@ namespace Avalonia.X11.Glx GlInterface = new GlInterface(GlxInterface.GlxGetProcAddress); if (GlInterface.Version == null) throw new OpenGlException("GL version string is null, aborting"); + if (GlInterface.Renderer == null) + throw new OpenGlException("GL renderer string is null, aborting"); + + if (Environment.GetEnvironmentVariable("AVALONIA_GLX_IGNORE_RENDERER_BLACKLIST") != "1") + { + var blacklist = AvaloniaLocator.Current.GetService() + ?.GlxRendererBlacklist; + if (blacklist != null) + foreach(var item in blacklist) + if (GlInterface.Renderer.Contains(item)) + throw new OpenGlException($"Renderer '{GlInterface.Renderer}' is blacklisted by '{item}'"); + } + } public void ClearContext() => Glx.MakeContextCurrent(_x11.Display, diff --git a/src/Avalonia.X11/X11Platform.cs b/src/Avalonia.X11/X11Platform.cs index cf5902eff7..7bdc61eb28 100644 --- a/src/Avalonia.X11/X11Platform.cs +++ b/src/Avalonia.X11/X11Platform.cs @@ -96,6 +96,14 @@ namespace Avalonia { public bool UseEGL { get; set; } public bool UseGpu { get; set; } = true; + + public List GlxRendererBlacklist { get; set; } = new List + { + // llvmpipe is a software GL rasterizer. If it's returned by glGetString, + // that usually means that something in the system is horribly misconfigured + // and sometimes attempts to use GLX might cause a segfault + "llvmpipe" + }; public string WmClass { get; set; } = Assembly.GetEntryAssembly()?.GetName()?.Name ?? "AvaloniaApplication"; public bool? EnableMultiTouch { get; set; } }