From 85620bd788d351018e9fa0b0f567b19a773be52b Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Mon, 9 Mar 2015 13:54:29 +0100 Subject: windows: Introduce a built-in GPU blacklist Use a built-in JSON file in case the QT_OPENGL_BUGLIST environment variable is not set. When QT_OPENGL_BUGLIST is set, the built-in list is ignored. To make the implementation simpler and more readable, some of the code in QWindowsOpenGLTester is reshuffled a bit. It also caches the results now, so it is safe and fast to call supportedRenderers() and friends multiple times. The blacklist currently contains the Intel card from QTBUG-43263 (Intel GMA / HD3000 ?) and may also apply to QTBUG-42240. [ChangeLog][QtGui] Qt now contains a built-in GPU driver blacklist for Windows that disables the usage of desktop OpenGL with some older cards that are known to be unstable with opengl32.dll. Task-number: QTBUG-42240 Task-number: QTBUG-43263 Change-Id: I1ecd65b51fca77925317d52048e7ab01d9b8797c Reviewed-by: Friedemann Kleint --- src/gui/opengl/qopengl_p.h | 18 ++++++ src/plugins/platforms/windows/openglblacklists.qrc | 5 ++ .../windows/openglblacklists/default.json | 18 ++++++ .../platforms/windows/qwindowsintegration.cpp | 8 ++- .../platforms/windows/qwindowsopengltester.cpp | 72 ++++++++++++---------- .../platforms/windows/qwindowsopengltester.h | 3 + src/plugins/platforms/windows/windows.pri | 2 + 7 files changed, 91 insertions(+), 35 deletions(-) create mode 100644 src/plugins/platforms/windows/openglblacklists.qrc create mode 100644 src/plugins/platforms/windows/openglblacklists/default.json (limited to 'src') diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h index 377440455a..e04ae05120 100644 --- a/src/gui/opengl/qopengl_p.h +++ b/src/gui/opengl/qopengl_p.h @@ -77,6 +77,9 @@ public: struct Gpu { Gpu() : vendorId(0), deviceId(0) {} bool isValid() const { return deviceId; } + bool equals(const Gpu &other) const { + return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion; + } uint vendorId; uint deviceId; @@ -93,6 +96,21 @@ public: static QSet gpuFeatures(const Gpu &gpu, const QString &fileName); }; +inline bool operator==(const QOpenGLConfig::Gpu &a, const QOpenGLConfig::Gpu &b) +{ + return a.equals(b); +} + +inline bool operator!=(const QOpenGLConfig::Gpu &a, const QOpenGLConfig::Gpu &b) +{ + return !a.equals(b); +} + +inline uint qHash(const QOpenGLConfig::Gpu &gpu) +{ + return qHash(gpu.vendorId) + qHash(gpu.deviceId) + qHash(gpu.driverVersion); +} + QT_END_NAMESPACE #endif // QOPENGL_H diff --git a/src/plugins/platforms/windows/openglblacklists.qrc b/src/plugins/platforms/windows/openglblacklists.qrc new file mode 100644 index 0000000000..9f0c186c21 --- /dev/null +++ b/src/plugins/platforms/windows/openglblacklists.qrc @@ -0,0 +1,5 @@ + + + openglblacklists/default.json + + diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json new file mode 100644 index 0000000000..0217b79ecf --- /dev/null +++ b/src/plugins/platforms/windows/openglblacklists/default.json @@ -0,0 +1,18 @@ +{ + "name": "Qt built-in GPU driver blacklist", + "version": "5.5", + "entries": [ + { + "id": 1, + "description": "Desktop OpenGL is unreliable on Intel HD3000/GMA (QTBUG-43263, QTBUG-42240)", + "vendor_id": "0x8086", + "device_id": [ "0x0A16" ], + "os": { + "type": "win" + }, + "features": [ + "disable_desktopgl" + ] + } + ] +} diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 9fd18a1ef4..1041ecf44d 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -79,9 +79,7 @@ # include "qwindowsglcontext.h" #endif -#ifndef Q_OS_WINCE -# include "qwindowsopengltester.h" -#endif +#include "qwindowsopengltester.h" QT_BEGIN_NAMESPACE @@ -209,6 +207,10 @@ QWindowsIntegrationPrivate::QWindowsIntegrationPrivate(const QStringList ¶mL : m_options(0) , m_fontDatabase(0) { +#ifndef Q_OS_WINCE + Q_INIT_RESOURCE(openglblacklists); +#endif + static bool dpiAwarenessSet = false; int tabletAbsoluteRange = -1; // Default to per-monitor awareness to avoid being scaled when monitors with different DPI diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index ba4c95544e..67548a0836 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -42,14 +42,16 @@ #include #include #include +#include +#ifndef QT_NO_OPENGL #include +#endif #ifndef Q_OS_WINCE # include # include # include -# include #endif QT_BEGIN_NAMESPACE @@ -206,56 +208,62 @@ static inline QString resolveBugListFile(const QString &fileName) return QStandardPaths::locate(QStandardPaths::ConfigLocation, fileName); } -static void readDriverBugList(const GpuDescription &gpu, - QWindowsOpenGLTester::Renderers *result) +typedef QHash SupportedRenderersCache; +Q_GLOBAL_STATIC(SupportedRenderersCache, supportedRenderersCache) + +#endif // !Q_OS_WINCE + +QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly) { - const char bugListFileVar[] = "QT_OPENGL_BUGLIST"; - if (!qEnvironmentVariableIsSet(bugListFileVar)) - return; - const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar))); - if (fileName.isEmpty()) - return; + Q_UNUSED(gpu) +#ifndef Q_OS_WINCE QOpenGLConfig::Gpu qgpu; qgpu.deviceId = gpu.deviceId; qgpu.vendorId = gpu.vendorId; qgpu.driverVersion = gpu.driverVersion; - const QSet features = QOpenGLConfig::gpuFeatures(qgpu, fileName); + SupportedRenderersCache *srCache = supportedRenderersCache(); + SupportedRenderersCache::const_iterator it = srCache->find(qgpu); + if (it != srCache->cend()) + return *it; + + QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11 + | QWindowsOpenGLTester::AngleRendererD3d9 + | QWindowsOpenGLTester::AngleRendererD3d11Warp + | QWindowsOpenGLTester::SoftwareRasterizer); + + if (!glesOnly && testDesktopGL()) + result |= QWindowsOpenGLTester::DesktopGl; + + QSet features; + const char bugListFileVar[] = "QT_OPENGL_BUGLIST"; + if (qEnvironmentVariableIsSet(bugListFileVar)) { + const QString fileName = resolveBugListFile(QFile::decodeName(qgetenv(bugListFileVar))); + if (!fileName.isEmpty()) + features = QOpenGLConfig::gpuFeatures(qgpu, fileName); + } else { + features = QOpenGLConfig::gpuFeatures(qgpu, QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json")); + } + qCDebug(lcQpaGl) << "GPU features:" << features; + if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific qCWarning(lcQpaGl) << "Disabling Desktop GL: " << gpu; - *result &= ~QWindowsOpenGLTester::DesktopGl; + result &= ~QWindowsOpenGLTester::DesktopGl; } if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu; - *result &= ~QWindowsOpenGLTester::GlesMask; + result &= ~QWindowsOpenGLTester::GlesMask; } else { if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu; - *result &= ~QWindowsOpenGLTester::AngleRendererD3d11; + result &= ~QWindowsOpenGLTester::AngleRendererD3d11; } if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu; - *result &= ~QWindowsOpenGLTester::AngleRendererD3d9; + result &= ~QWindowsOpenGLTester::AngleRendererD3d9; } } -} -#endif // !Q_OS_WINCE - -static inline QWindowsOpenGLTester::Renderers - detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly) -{ - Q_UNUSED(gpu) -#ifndef Q_OS_WINCE - // Add checks for card types with known issues here. - QWindowsOpenGLTester::Renderers result(QWindowsOpenGLTester::AngleRendererD3d11 - | QWindowsOpenGLTester::AngleRendererD3d9 - | QWindowsOpenGLTester::AngleRendererD3d11Warp - | QWindowsOpenGLTester::SoftwareRasterizer); - - if (!glesOnly && QWindowsOpenGLTester::testDesktopGL()) - result |= QWindowsOpenGLTester::DesktopGl; - - readDriverBugList(gpu, &result); + srCache->insert(qgpu, result); return result; #else // !Q_OS_WINCE return QWindowsOpenGLTester::Gles; diff --git a/src/plugins/platforms/windows/qwindowsopengltester.h b/src/plugins/platforms/windows/qwindowsopengltester.h index 7b6164946e..748885542d 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.h +++ b/src/plugins/platforms/windows/qwindowsopengltester.h @@ -80,9 +80,12 @@ public: static Renderer requestedGlesRenderer(); static Renderer requestedRenderer(); + static Renderers supportedGlesRenderers(); static Renderers supportedRenderers(); +private: + static QWindowsOpenGLTester::Renderers detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly); static bool testDesktopGL(); }; diff --git a/src/plugins/platforms/windows/windows.pri b/src/plugins/platforms/windows/windows.pri index 246598677f..77393033c7 100644 --- a/src/plugins/platforms/windows/windows.pri +++ b/src/plugins/platforms/windows/windows.pri @@ -118,6 +118,8 @@ contains(QT_CONFIG,dynamicgl) { RESOURCES += $$PWD/cursors.qrc } +!wince*: RESOURCES += $$PWD/openglblacklists.qrc + contains(QT_CONFIG, freetype) { DEFINES *= QT_NO_FONTCONFIG QT_FREETYPE_DIR = $$QT_SOURCE_TREE/src/3rdparty/freetype -- cgit v1.2.3