From 60fae3540de9acb08dca80fd328c56a0f517f21d Mon Sep 17 00:00:00 2001 From: CasualPokePlayer <50538166+CasualPokePlayer@users.noreply.github.com> Date: Wed, 4 Sep 2024 12:27:32 -0700 Subject: [PATCH] Prefer EGL over GLX should fix Nvidia proprietary driver issues on XWayland --- .../OpenGL/SDL2OpenGLContext.cs | 72 +++++++++++++++++-- 1 file changed, 66 insertions(+), 6 deletions(-) diff --git a/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs b/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs index bd52d1b7fb..fe29fe3924 100644 --- a/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs +++ b/src/BizHawk.Bizware.Graphics/OpenGL/SDL2OpenGLContext.cs @@ -5,6 +5,8 @@ using Silk.NET.OpenGL; #endif +using BizHawk.Common; + using static SDL2.SDL; namespace BizHawk.Bizware.Graphics @@ -16,16 +18,59 @@ public class SDL2OpenGLContext : IDisposable { static SDL2OpenGLContext() { + if (OSTailoredCode.IsUnixHost) + { + // make sure that Linux uses the x11 video driver + // we need this as mono winforms uses x11 + // and the user could potentially try to force the wayland video driver via env vars + SDL_SetHint("SDL_VIDEODRIVER", "x11"); + // try to use EGL if it is available + // GLX is the old API, and is the more or less "deprecated" at this point, and potentially more buggy with some drivers + // we do need to a bit more work, in case EGL is not actually available or potentially doesn't have desktop GL support + SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "1"); + } + // init SDL video if (SDL_Init(SDL_INIT_VIDEO) != 0) { throw new($"Could not init SDL video! SDL Error: {SDL_GetError()}"); } - // load the default OpenGL library - if (SDL_GL_LoadLibrary(null) != 0) + if (OSTailoredCode.IsUnixHost) + { + // if we fail to load EGL, we'll just try again with GLX... + var loadGlx = SDL_GL_LoadLibrary(null) != 0; + + if (!loadGlx) + { + try + { + // check if we can actually create a desktop GL context + using var glContext = new SDL2OpenGLContext(3, 2, true); + } + catch + { + // failed to create a context, fallback to GLX + loadGlx = true; + } + } + + if (loadGlx) + { + SDL_SetHint(SDL_HINT_VIDEO_X11_FORCE_EGL, "0"); + if (SDL_GL_LoadLibrary(null) != 0) + { + throw new($"Could not load default OpenGL library! SDL Error: {SDL_GetError()}"); + } + } + } + else { - throw new($"Could not load default OpenGL library! SDL Error: {SDL_GetError()}"); + // load the default OpenGL library + if (SDL_GL_LoadLibrary(null) != 0) + { + throw new($"Could not load default OpenGL library! SDL Error: {SDL_GetError()}"); + } } // we will be turning a foreign window into an SDL window @@ -53,7 +98,6 @@ private static void SetAttributes(int majorVersion, int minorVersion, bool coreP || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_GREEN_SIZE, 8) is not 0 || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_BLUE_SIZE, 8) is not 0 || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_ALPHA_SIZE, 0) is not 0 - || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_DEPTH_SIZE, 24) is not 0 || SDL_GL_SetAttribute(SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1) is not 0) { throw new($"Could not set GL attributes! SDL Error: {SDL_GetError()}"); @@ -122,7 +166,15 @@ public SDL2OpenGLContext(IntPtr nativeWindowhandle, int majorVersion, int minorV throw new($"Could not create SDL Window! SDL Error: {SDL_GetError()}"); } - CreateContext(); + try + { + CreateContext(); + } + catch + { + Dispose(); + throw; + } } public SDL2OpenGLContext(int majorVersion, int minorVersion, bool coreProfile) @@ -138,7 +190,15 @@ public SDL2OpenGLContext(int majorVersion, int minorVersion, bool coreProfile) throw new($"Could not create SDL Window! SDL Error: {SDL_GetError()}"); } - CreateContext(); + try + { + CreateContext(); + } + catch + { + Dispose(); + throw; + } } public void Dispose()