Use EGL_VENDOR instead of NV-CONTROL for Nvidia detection
The latter will still match on a hybrid system when the iGPU's EGL implementation is in use. This scenario works properly with EGL rendering in Qt and SDL, so we want to allow that.
This commit is contained in:
parent
c92dc2495e
commit
9c6d2bab19
4 changed files with 36 additions and 28 deletions
|
|
@ -476,11 +476,7 @@ int main(int argc, char *argv[])
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nvidia's proprietary driver has broken EGL support on X11, so don't use it.
|
if (WMUtils::isEGLSafe()) {
|
||||||
// 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()) {
|
|
||||||
// Some ARM and RISC-V embedded devices don't have working GLX which can cause
|
// 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
|
// 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
|
// on all platforms for both SDL and Qt. This also avoids GLX-EGL interop issues
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
#include "eglvid.h"
|
#include "eglvid.h"
|
||||||
|
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
#include "utils.h"
|
||||||
#include "streaming/session.h"
|
#include "streaming/session.h"
|
||||||
#include "streaming/streamutils.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.
|
// 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.
|
// Switching between EGL and GLX can cause interoperability issues.
|
||||||
if (strcmp(SDL_GetCurrentVideoDriver(), "x11") == 0 &&
|
if (!WMUtils::isEGLSafe()) {
|
||||||
!SDL_GetHintBoolean(SDL_HINT_VIDEO_X11_FORCE_EGL, SDL_FALSE)) {
|
|
||||||
EGL_LOG(Warn, "Disabled due to use of GLX");
|
EGL_LOG(Warn, "Disabled due to use of GLX");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,9 +7,10 @@
|
||||||
|
|
||||||
namespace WMUtils {
|
namespace WMUtils {
|
||||||
bool isRunningX11();
|
bool isRunningX11();
|
||||||
bool isRunningX11NvidiaProprietaryDriver();
|
bool isRunningNvidiaProprietaryDriver();
|
||||||
bool isRunningWayland();
|
bool isRunningWayland();
|
||||||
bool isRunningWindowManager();
|
bool isRunningWindowManager();
|
||||||
bool isRunningDesktopEnvironment();
|
bool isRunningDesktopEnvironment();
|
||||||
|
bool isEGLSafe();
|
||||||
QString getDrmCardOverride();
|
QString getDrmCardOverride();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
51
app/wm.cpp
51
app/wm.cpp
|
|
@ -18,6 +18,10 @@
|
||||||
#include <xf86drmMode.h>
|
#include <xf86drmMode.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_EGL
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#define VALUE_SET 0x01
|
#define VALUE_SET 0x01
|
||||||
#define VALUE_TRUE 0x02
|
#define VALUE_TRUE 0x02
|
||||||
|
|
||||||
|
|
@ -42,43 +46,39 @@ bool WMUtils::isRunningX11()
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!(val & VALUE_TRUE);
|
return !!(val & VALUE_TRUE);
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WMUtils::isRunningX11NvidiaProprietaryDriver()
|
bool WMUtils::isRunningNvidiaProprietaryDriver()
|
||||||
{
|
{
|
||||||
#ifdef HAS_X11
|
#ifdef HAVE_EGL
|
||||||
static SDL_atomic_t isRunningOnX11NvidiaDriver;
|
static SDL_atomic_t isRunningOnNvidiaDriver;
|
||||||
|
|
||||||
// If the value is not set yet, populate it now.
|
// If the value is not set yet, populate it now.
|
||||||
int val = SDL_AtomicGet(&isRunningOnX11NvidiaDriver);
|
int val = SDL_AtomicGet(&isRunningOnNvidiaDriver);
|
||||||
if (!(val & VALUE_SET)) {
|
if (!(val & VALUE_SET)) {
|
||||||
Display* display = XOpenDisplay(nullptr);
|
|
||||||
bool nvidiaDriver = false;
|
bool nvidiaDriver = false;
|
||||||
|
|
||||||
if (display != nullptr) {
|
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
int opcode, event, error;
|
if (display != EGL_NO_DISPLAY && eglInitialize(display, nullptr, nullptr)) {
|
||||||
|
const char* vendorString = eglQueryString(display, EGL_VENDOR);
|
||||||
// We use the presence of the NV-CONTROL extension to indicate
|
nvidiaDriver = vendorString && strstr(vendorString, "NVIDIA") != NULL;
|
||||||
// that the Nvidia proprietary driver is in use on native X11
|
eglTerminate(display);
|
||||||
nvidiaDriver = XQueryExtension(display, "NV-CONTROL", &opcode, &event, &error);
|
|
||||||
|
|
||||||
XCloseDisplay(display);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate the value to return and have for next time.
|
// Populate the value to return and have for next time.
|
||||||
// This can race with another thread populating the same data,
|
// This can race with another thread populating the same data,
|
||||||
// but that's no big deal.
|
// but that's no big deal.
|
||||||
val = VALUE_SET | (nvidiaDriver ? VALUE_TRUE : 0);
|
val = VALUE_SET | (nvidiaDriver ? VALUE_TRUE : 0);
|
||||||
SDL_AtomicSet(&isRunningOnX11NvidiaDriver, val);
|
SDL_AtomicSet(&isRunningOnNvidiaDriver, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!(val & VALUE_TRUE);
|
return !!(val & VALUE_TRUE);
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WMUtils::isRunningWayland()
|
bool WMUtils::isRunningWayland()
|
||||||
|
|
@ -102,9 +102,9 @@ bool WMUtils::isRunningWayland()
|
||||||
}
|
}
|
||||||
|
|
||||||
return !!(val & VALUE_TRUE);
|
return !!(val & VALUE_TRUE);
|
||||||
#endif
|
#else
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WMUtils::isRunningWindowManager()
|
bool WMUtils::isRunningWindowManager()
|
||||||
|
|
@ -176,3 +176,14 @@ QString WMUtils::getDrmCardOverride()
|
||||||
|
|
||||||
return QString();
|
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();
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue