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 <Friedemann.Kleint@theqtcompany.com>
bb10
Laszlo Agocs 2015-03-09 13:54:29 +01:00
parent 22afbc1536
commit 85620bd788
7 changed files with 96 additions and 40 deletions

View File

@ -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<QString> 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

View File

@ -0,0 +1,5 @@
<RCC>
<qresource prefix="/qt-project.org/windows/openglblacklists">
<file alias="default.json">openglblacklists/default.json</file>
</qresource>
</RCC>

View File

@ -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"
]
}
]
}

View File

@ -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 &paramL
: 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

View File

@ -42,14 +42,16 @@
#include <QtCore/QFileInfo>
#include <QtCore/QStandardPaths>
#include <QtCore/QLibraryInfo>
#include <QtCore/QHash>
#ifndef QT_NO_OPENGL
#include <private/qopengl_p.h>
#endif
#ifndef Q_OS_WINCE
# include <QtCore/qt_windows.h>
# include <private/qsystemlibrary_p.h>
# include <d3d9.h>
# include <GL/gl.h>
#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<QOpenGLConfig::Gpu, QWindowsOpenGLTester::Renderers> 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<QString> features = QOpenGLConfig::gpuFeatures(qgpu, fileName);
if (features.contains(QStringLiteral("disable_desktopgl"))) { // Qt-specific
qCWarning(lcQpaGl) << "Disabling Desktop GL: " << gpu;
*result &= ~QWindowsOpenGLTester::DesktopGl;
}
if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword
qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu;
*result &= ~QWindowsOpenGLTester::GlesMask;
} else {
if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword
qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu;
*result &= ~QWindowsOpenGLTester::AngleRendererD3d11;
}
if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific
qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu;
*result &= ~QWindowsOpenGLTester::AngleRendererD3d9;
}
}
}
#endif // !Q_OS_WINCE
SupportedRenderersCache *srCache = supportedRenderersCache();
SupportedRenderersCache::const_iterator it = srCache->find(qgpu);
if (it != srCache->cend())
return *it;
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())
if (!glesOnly && testDesktopGL())
result |= QWindowsOpenGLTester::DesktopGl;
readDriverBugList(gpu, &result);
QSet<QString> 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;
}
if (features.contains(QStringLiteral("disable_angle"))) { // Qt-specific keyword
qCWarning(lcQpaGl) << "Disabling ANGLE: " << gpu;
result &= ~QWindowsOpenGLTester::GlesMask;
} else {
if (features.contains(QStringLiteral("disable_d3d11"))) { // standard keyword
qCWarning(lcQpaGl) << "Disabling D3D11: " << gpu;
result &= ~QWindowsOpenGLTester::AngleRendererD3d11;
}
if (features.contains(QStringLiteral("disable_d3d9"))) { // Qt-specific
qCWarning(lcQpaGl) << "Disabling D3D9: " << gpu;
result &= ~QWindowsOpenGLTester::AngleRendererD3d9;
}
}
srCache->insert(qgpu, result);
return result;
#else // !Q_OS_WINCE
return QWindowsOpenGLTester::Gles;

View File

@ -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();
};

View File

@ -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