diff --git a/app/main.cpp b/app/main.cpp index bcf1705c..3229dd0a 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -476,11 +476,7 @@ int main(int argc, char *argv[]) #endif } - // Nvidia's proprietary driver has broken EGL support on X11, so don't use it. - // This will break the EGLRenderer, but that's fine on Nvidia because they - // support both VDPAU and Vulkan renderers instead. - // https://github.com/moonlight-stream/moonlight-qt/issues/1751 - if (!WMUtils::isRunningX11NvidiaProprietaryDriver()) { + if (WMUtils::isEGLSafe()) { // Some ARM and RISC-V embedded devices don't have working GLX which can cause // SDL to fail to find a working OpenGL implementation at all. Let's force EGL // on all platforms for both SDL and Qt. This also avoids GLX-EGL interop issues diff --git a/app/streaming/video/ffmpeg-renderers/eglvid.cpp b/app/streaming/video/ffmpeg-renderers/eglvid.cpp index 7c919c84..cbf976cf 100644 --- a/app/streaming/video/ffmpeg-renderers/eglvid.cpp +++ b/app/streaming/video/ffmpeg-renderers/eglvid.cpp @@ -2,6 +2,7 @@ #include "eglvid.h" #include "path.h" +#include "utils.h" #include "streaming/session.h" #include "streaming/streamutils.h" @@ -436,8 +437,7 @@ bool EGLRenderer::initialize(PDECODER_PARAMETERS params) // If we're using X11 GLX (both in SDL and Qt), don't use this renderer. // Switching between EGL and GLX can cause interoperability issues. - if (strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0 && - !SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) { + if (!WMUtils::isEGLSafe()) { EGL_LOG(Warn, "Disabled due to use of GLX"); return false; } diff --git a/app/utils.h b/app/utils.h index f234dc76..d303444b 100644 --- a/app/utils.h +++ b/app/utils.h @@ -7,9 +7,10 @@ namespace WMUtils { bool isRunningX11(); - bool isRunningX11NvidiaProprietaryDriver(); + bool isRunningNvidiaProprietaryDriver(); bool isRunningWayland(); bool isRunningWindowManager(); bool isRunningDesktopEnvironment(); + bool isEGLSafe(); QString getDrmCardOverride(); } diff --git a/app/wm.cpp b/app/wm.cpp index 704b7152..54e3fc3c 100644 --- a/app/wm.cpp +++ b/app/wm.cpp @@ -18,6 +18,10 @@ #include #endif +#ifdef HAVE_EGL +#include +#endif + #define VALUE_SET 0x01 #define VALUE_TRUE 0x02 @@ -42,43 +46,39 @@ bool WMUtils::isRunningX11() } return !!(val & VALUE_TRUE); -#endif - +#else return false; +#endif } -bool WMUtils::isRunningX11NvidiaProprietaryDriver() +bool WMUtils::isRunningNvidiaProprietaryDriver() { -#ifdef HAS_X11 - static SDL_atomic_t isRunningOnX11NvidiaDriver; +#ifdef HAVE_EGL + static SDL_atomic_t isRunningOnNvidiaDriver; // If the value is not set yet, populate it now. - int val = SDL_AtomicGet(&isRunningOnX11NvidiaDriver); + int val = SDL_AtomicGet(&isRunningOnNvidiaDriver); if (!(val & VALUE_SET)) { - Display* display = XOpenDisplay(nullptr); bool nvidiaDriver = false; - if (display != nullptr) { - int opcode, event, error; - - // We use the presence of the NV-CONTROL extension to indicate - // that the Nvidia proprietary driver is in use on native X11 - nvidiaDriver = XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error); - - XCloseDisplay(display); + EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (display != EGL_NO_DISPLAY && eglInitialize(display, nullptr, nullptr)) { + const char* vendorString = eglQueryString(display, EGL_VENDOR); + nvidiaDriver = vendorString && strstr(vendorString, "NVIDIA") != NULL; + 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 | (nvidiaDriver ? VALUE_TRUE : 0); - SDL_AtomicSet(&isRunningOnX11NvidiaDriver, val); + SDL_AtomicSet(&isRunningOnNvidiaDriver, val); } return !!(val & VALUE_TRUE); -#endif - +#else return false; +#endif } bool WMUtils::isRunningWayland() @@ -102,9 +102,9 @@ bool WMUtils::isRunningWayland() } return !!(val & VALUE_TRUE); -#endif - +#else return false; +#endif } bool WMUtils::isRunningWindowManager() @@ -176,3 +176,14 @@ QString WMUtils::getDrmCardOverride() return QString(); } + +bool WMUtils::isEGLSafe() +{ + // We can use EGL if: + // a) We're not using X11/Wayland (EGLFS requires it) + // b) We're using Wayland (even XWayland is fine) + // c) We're using X11 but not the Nvidia proprietary driver + // + // https://github.com/moonlight-stream/moonlight-qt/issues/1751 + return !WMUtils::isRunningWindowManager() || WMUtils::isRunningWayland() || !WMUtils::isRunningNvidiaProprietaryDriver(); +}