From 7edbede95d6f24ed11ba22260ec237c992a5363e Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sun, 21 Dec 2025 21:10:13 -0600 Subject: [PATCH] Force Qt to use GLES if desktop GL is not available Some platforms like the VisionFive 2 don't have working desktop GL, so they must use GLES to be able to render at all. Qt doesn't try to fall back if it fails to find a compatible EGL config, so we must do so ourselves. --- app/main.cpp | 4 +++- app/utils.h | 1 + app/wm.cpp | 39 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/app/main.cpp b/app/main.cpp index 5d0b827d..34eac3cc 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -550,7 +550,9 @@ int main(int argc, char *argv[]) #endif } - if (WMUtils::isRunningNvidiaProprietaryDriverX11() || qEnvironmentVariableIntValue("FORCE_QT_GLES")) { + if (WMUtils::isRunningNvidiaProprietaryDriverX11() || + !WMUtils::supportsDesktopGLWithEGL() || + qEnvironmentVariableIntValue("FORCE_QT_GLES")) { // The Nvidia proprietary driver causes Qt to render a black window when using // the default Desktop GL profile with EGL. AS a workaround, we default to // OpenGL ES when running on Nvidia on X11. diff --git a/app/utils.h b/app/utils.h index d589f137..c37c0dbe 100644 --- a/app/utils.h +++ b/app/utils.h @@ -8,6 +8,7 @@ namespace WMUtils { bool isRunningX11(); bool isRunningNvidiaProprietaryDriverX11(); + bool supportsDesktopGLWithEGL(); bool isRunningWayland(); bool isRunningWindowManager(); bool isRunningDesktopEnvironment(); diff --git a/app/wm.cpp b/app/wm.cpp index 7ade1d8c..33c0d52e 100644 --- a/app/wm.cpp +++ b/app/wm.cpp @@ -88,6 +88,45 @@ bool WMUtils::isRunningNvidiaProprietaryDriverX11() #endif } +bool WMUtils::supportsDesktopGLWithEGL() +{ +#ifdef HAVE_EGL + static SDL_atomic_t supportsDesktopGL; + + // If the value is not set yet, populate it now. + int val = SDL_AtomicGet(&supportsDesktopGL); + if (!(val & VALUE_SET)) { + bool desktopGL = false; + + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (display != EGL_NO_DISPLAY && eglInitialize(display, nullptr, nullptr)) { + EGLint matchingConfigs = 0; + EGLint const attribs[] = + { + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_NONE + }; + + desktopGL = eglChooseConfig(display, attribs, nullptr, 0, &matchingConfigs) == EGL_TRUE && + matchingConfigs > 0; + eglTerminate(display); + } + + // Populate the value to return and have for next time. + // This can race with another thread populating the same data, + // but that's no big deal. + val = VALUE_SET | (desktopGL ? VALUE_TRUE : 0); + SDL_AtomicSet(&supportsDesktopGL, val); + } + + return !!(val & VALUE_TRUE); +#else + // Assume it does if we can't check ourselves + return true; +#endif +} + bool WMUtils::isRunningWayland() { #ifdef HAS_WAYLAND