Add support for driver_description and os.release in GPU blacklists
os.version is the kernel version which is just not very useful or easy to
use for us. Instead, introduce a string that allows easy differentiation
between Windows 7 and 8.
From the adapter identifier the driver description is often helpful too,
especially in virtual machines.
These allow writing rules like:
{ "description": "Use WARP in some Win 8 and 8.1 VMs",
"os": { "type": "win", "release": [ "8", "8.1" ] },
"driver_description": "VMware SVGA 3D",
"features": [ "disable_desktopgl", "disable_d3d9", "disable_d3d11" ]
}
Change-Id: I196f6b44d7bb9e42ef47f61f4c28d8aa79afb7c4
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
bb10
parent
db377a4202
commit
a8a8cdd24b
|
|
@ -135,20 +135,42 @@ static const char operators[][3] = {"!=", "<", "<=", "=", ">", ">="};
|
|||
static inline QString valueKey() { return QStringLiteral("value"); }
|
||||
static inline QString opKey() { return QStringLiteral("op"); }
|
||||
static inline QString versionKey() { return QStringLiteral("version"); }
|
||||
static inline QString releaseKey() { return QStringLiteral("release"); }
|
||||
static inline QString typeKey() { return QStringLiteral("type"); }
|
||||
static inline QString osKey() { return QStringLiteral("os"); }
|
||||
static inline QString vendorIdKey() { return QStringLiteral("vendor_id"); }
|
||||
static inline QString glVendorKey() { return QStringLiteral("gl_vendor"); }
|
||||
static inline QString deviceIdKey() { return QStringLiteral("device_id"); }
|
||||
static inline QString driverVersionKey() { return QStringLiteral("driver_version"); }
|
||||
static inline QString driverDescriptionKey() { return QStringLiteral("driver_description"); }
|
||||
static inline QString featuresKey() { return QStringLiteral("features"); }
|
||||
static inline QString idKey() { return QStringLiteral("id"); }
|
||||
static inline QString descriptionKey() { return QStringLiteral("description"); }
|
||||
static inline QString exceptionsKey() { return QStringLiteral("exceptions"); }
|
||||
|
||||
typedef QJsonArray::ConstIterator JsonArrayConstIt;
|
||||
|
||||
static inline bool contains(const QJsonArray &haystack, unsigned needle)
|
||||
{
|
||||
for (JsonArrayConstIt it = haystack.constBegin(), cend = haystack.constEnd(); it != cend; ++it) {
|
||||
if (needle == it->toString().toUInt(Q_NULLPTR, /* base */ 0))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline bool contains(const QJsonArray &haystack, const QString &needle)
|
||||
{
|
||||
for (JsonArrayConstIt it = haystack.constBegin(), cend = haystack.constEnd(); it != cend; ++it) {
|
||||
if (needle == it->toString())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace {
|
||||
// VersionTerm describing a version term consisting of number and operator
|
||||
// found in "os", "driver_version", "gl_version".
|
||||
// found in os.version and driver_version.
|
||||
struct VersionTerm {
|
||||
VersionTerm() : op(NotEqual) {}
|
||||
static VersionTerm fromJson(const QJsonValue &v);
|
||||
|
|
@ -206,9 +228,38 @@ struct OsTypeTerm
|
|||
static OsTypeTerm fromJson(const QJsonValue &v);
|
||||
static QString hostOs();
|
||||
static QVersionNumber hostKernelVersion() { return QVersionNumber::fromString(QSysInfo::kernelVersion()); }
|
||||
static QString hostOsRelease() {
|
||||
QString ver;
|
||||
#ifdef Q_OS_WIN
|
||||
switch (QSysInfo::windowsVersion()) {
|
||||
case QSysInfo::WV_XP:
|
||||
case QSysInfo::WV_2003:
|
||||
ver = QStringLiteral("xp");
|
||||
break;
|
||||
case QSysInfo::WV_VISTA:
|
||||
ver = QStringLiteral("vista");
|
||||
break;
|
||||
case QSysInfo::WV_WINDOWS7:
|
||||
ver = QStringLiteral("7");
|
||||
break;
|
||||
case QSysInfo::WV_WINDOWS8:
|
||||
ver = QStringLiteral("8");
|
||||
break;
|
||||
case QSysInfo::WV_WINDOWS8_1:
|
||||
ver = QStringLiteral("8.1");
|
||||
break;
|
||||
case QSysInfo::WV_WINDOWS10:
|
||||
ver = QStringLiteral("10");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
return ver;
|
||||
}
|
||||
|
||||
bool isNull() const { return type.isEmpty(); }
|
||||
bool matches(const QString &osName, const QVersionNumber &kernelVersion) const
|
||||
bool matches(const QString &osName, const QVersionNumber &kernelVersion, const QString &osRelease) const
|
||||
{
|
||||
if (isNull() || osName.isEmpty() || kernelVersion.isNull()) {
|
||||
qWarning() << Q_FUNC_INFO << "called with invalid parameters";
|
||||
|
|
@ -216,11 +267,17 @@ struct OsTypeTerm
|
|||
}
|
||||
if (type != osName)
|
||||
return false;
|
||||
return versionTerm.isNull() || versionTerm.matches(kernelVersion);
|
||||
if (!versionTerm.isNull() && !versionTerm.matches(kernelVersion))
|
||||
return false;
|
||||
// release is a list of Windows versions where the rule should match
|
||||
if (!release.isEmpty() && !contains(release, osRelease))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
QString type;
|
||||
VersionTerm versionTerm;
|
||||
QJsonArray release;
|
||||
};
|
||||
|
||||
OsTypeTerm OsTypeTerm::fromJson(const QJsonValue &v)
|
||||
|
|
@ -231,6 +288,7 @@ OsTypeTerm OsTypeTerm::fromJson(const QJsonValue &v)
|
|||
const QJsonObject o = v.toObject();
|
||||
result.type = o.value(typeKey()).toString();
|
||||
result.versionTerm = VersionTerm::fromJson(o.value(versionKey()));
|
||||
result.release = o.value(releaseKey()).toArray();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -251,17 +309,6 @@ QString OsTypeTerm::hostOs()
|
|||
}
|
||||
} // anonymous namespace
|
||||
|
||||
typedef QJsonArray::ConstIterator JsonArrayConstIt;
|
||||
|
||||
static inline bool contains(const QJsonArray &a, unsigned needle)
|
||||
{
|
||||
for (JsonArrayConstIt it = a.constBegin(), cend = a.constEnd(); it != cend; ++it) {
|
||||
if (needle == it->toString().toUInt(Q_NULLPTR, /* base */ 0))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static QString msgSyntaxWarning(const QJsonObject &object, const QString &what)
|
||||
{
|
||||
QString result;
|
||||
|
|
@ -277,17 +324,18 @@ static QString msgSyntaxWarning(const QJsonObject &object, const QString &what)
|
|||
static bool matches(const QJsonObject &object,
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QString &osRelease,
|
||||
const QOpenGLConfig::Gpu &gpu)
|
||||
{
|
||||
const OsTypeTerm os = OsTypeTerm::fromJson(object.value(osKey()));
|
||||
if (!os.isNull() && !os.matches(osName, kernelVersion))
|
||||
if (!os.isNull() && !os.matches(osName, kernelVersion, osRelease))
|
||||
return false;
|
||||
|
||||
const QJsonValue exceptionsV = object.value(exceptionsKey());
|
||||
if (exceptionsV.isArray()) {
|
||||
const QJsonArray exceptionsA = exceptionsV.toArray();
|
||||
for (JsonArrayConstIt it = exceptionsA.constBegin(), cend = exceptionsA.constEnd(); it != cend; ++it) {
|
||||
if (matches(it->toObject(), osName, kernelVersion, gpu))
|
||||
if (matches(it->toObject(), osName, kernelVersion, osRelease, gpu))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -336,12 +384,22 @@ static bool matches(const QJsonObject &object,
|
|||
QLatin1String("Driver version must be of type object."));
|
||||
}
|
||||
}
|
||||
|
||||
if (!gpu.driverDescription.isEmpty()) {
|
||||
const QJsonValue driverDescriptionV = object.value(driverDescriptionKey());
|
||||
if (driverDescriptionV.isString()) {
|
||||
if (!gpu.driverDescription.contains(driverDescriptionV.toString().toUtf8()))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QString &osRelease,
|
||||
const QJsonDocument &doc,
|
||||
QSet<QString> *result,
|
||||
QString *errorMessage)
|
||||
|
|
@ -358,7 +416,7 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
|||
for (JsonArrayConstIt eit = entriesA.constBegin(), ecend = entriesA.constEnd(); eit != ecend; ++eit) {
|
||||
if (eit->isObject()) {
|
||||
const QJsonObject object = eit->toObject();
|
||||
if (matches(object, osName, kernelVersion, gpu)) {
|
||||
if (matches(object, osName, kernelVersion, osRelease, gpu)) {
|
||||
const QJsonValue featuresListV = object.value(featuresKey());
|
||||
if (featuresListV.isArray()) {
|
||||
const QJsonArray featuresListA = featuresListV.toArray();
|
||||
|
|
@ -374,6 +432,7 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
|||
static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QString &osRelease,
|
||||
const QByteArray &jsonAsciiData,
|
||||
QSet<QString> *result, QString *errorMessage)
|
||||
{
|
||||
|
|
@ -389,12 +448,13 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
|||
<< error.offset << ").";
|
||||
return false;
|
||||
}
|
||||
return readGpuFeatures(gpu, osName, kernelVersion, document, result, errorMessage);
|
||||
return readGpuFeatures(gpu, osName, kernelVersion, osRelease, document, result, errorMessage);
|
||||
}
|
||||
|
||||
static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QString &osRelease,
|
||||
const QString &fileName,
|
||||
QSet<QString> *result, QString *errorMessage)
|
||||
{
|
||||
|
|
@ -407,7 +467,7 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
|||
<< file.errorString();
|
||||
return false;
|
||||
}
|
||||
const bool success = readGpuFeatures(gpu, osName, kernelVersion, file.readAll(), result, errorMessage);
|
||||
const bool success = readGpuFeatures(gpu, osName, kernelVersion, osRelease, file.readAll(), result, errorMessage);
|
||||
if (!success) {
|
||||
errorMessage->prepend(QLatin1String("Error reading \"")
|
||||
+ QDir::toNativeSeparators(fileName)
|
||||
|
|
@ -417,37 +477,39 @@ static bool readGpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
|||
}
|
||||
|
||||
QSet<QString> QOpenGLConfig::gpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QJsonDocument &doc)
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QString &osRelease,
|
||||
const QJsonDocument &doc)
|
||||
{
|
||||
QSet<QString> result;
|
||||
QString errorMessage;
|
||||
if (!readGpuFeatures(gpu, osName, kernelVersion, doc, &result, &errorMessage))
|
||||
if (!readGpuFeatures(gpu, osName, kernelVersion, osRelease, doc, &result, &errorMessage))
|
||||
qWarning().noquote() << errorMessage;
|
||||
return result;
|
||||
}
|
||||
|
||||
QSet<QString> QOpenGLConfig::gpuFeatures(const QOpenGLConfig::Gpu &gpu,
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QString &fileName)
|
||||
const QString &osName,
|
||||
const QVersionNumber &kernelVersion,
|
||||
const QString &osRelease,
|
||||
const QString &fileName)
|
||||
{
|
||||
QSet<QString> result;
|
||||
QString errorMessage;
|
||||
if (!readGpuFeatures(gpu, osName, kernelVersion, fileName, &result, &errorMessage))
|
||||
if (!readGpuFeatures(gpu, osName, kernelVersion, osRelease, fileName, &result, &errorMessage))
|
||||
qWarning().noquote() << errorMessage;
|
||||
return result;
|
||||
}
|
||||
|
||||
QSet<QString> QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QJsonDocument &doc)
|
||||
{
|
||||
return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), doc);
|
||||
return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), OsTypeTerm::hostOsRelease(), doc);
|
||||
}
|
||||
|
||||
QSet<QString> QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QString &fileName)
|
||||
{
|
||||
return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), fileName);
|
||||
return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), OsTypeTerm::hostOsRelease(), fileName);
|
||||
}
|
||||
|
||||
QOpenGLConfig::Gpu QOpenGLConfig::Gpu::fromContext()
|
||||
|
|
|
|||
|
|
@ -79,19 +79,21 @@ public:
|
|||
bool isValid() const { return deviceId || !glVendor.isEmpty(); }
|
||||
bool equals(const Gpu &other) const {
|
||||
return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion
|
||||
&& glVendor == other.glVendor;
|
||||
&& driverDescription == other.driverDescription && glVendor == other.glVendor;
|
||||
}
|
||||
|
||||
uint vendorId;
|
||||
uint deviceId;
|
||||
QVersionNumber driverVersion;
|
||||
QByteArray driverDescription;
|
||||
QByteArray glVendor;
|
||||
|
||||
static Gpu fromDevice(uint vendorId, uint deviceId, QVersionNumber driverVersion) {
|
||||
static Gpu fromDevice(uint vendorId, uint deviceId, QVersionNumber driverVersion, const QByteArray &driverDescription) {
|
||||
Gpu gpu;
|
||||
gpu.vendorId = vendorId;
|
||||
gpu.deviceId = deviceId;
|
||||
gpu.driverVersion = driverVersion;
|
||||
gpu.driverDescription = driverDescription;
|
||||
return gpu;
|
||||
}
|
||||
|
||||
|
|
@ -105,10 +107,10 @@ public:
|
|||
};
|
||||
|
||||
static QSet<QString> gpuFeatures(const Gpu &gpu,
|
||||
const QString &osName, const QVersionNumber &kernelVersion,
|
||||
const QString &osName, const QVersionNumber &kernelVersion, const QString &osVersion,
|
||||
const QJsonDocument &doc);
|
||||
static QSet<QString> gpuFeatures(const Gpu &gpu,
|
||||
const QString &osName, const QVersionNumber &kernelVersion,
|
||||
const QString &osName, const QVersionNumber &kernelVersion, const QString &osVersion,
|
||||
const QString &fileName);
|
||||
static QSet<QString> gpuFeatures(const Gpu &gpu, const QJsonDocument &doc);
|
||||
static QSet<QString> gpuFeatures(const Gpu &gpu, const QString &fileName);
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
|
|||
#elif defined(Q_OS_WINCE)
|
||||
return QWindowsOpenGLTester::Gles;
|
||||
#else
|
||||
QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.deviceId, gpu.vendorId, gpu.driverVersion);
|
||||
QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.deviceId, gpu.vendorId, gpu.driverVersion, gpu.description);
|
||||
SupportedRenderersCache *srCache = supportedRenderersCache();
|
||||
SupportedRenderersCache::const_iterator it = srCache->find(qgpu);
|
||||
if (it != srCache->cend())
|
||||
|
|
|
|||
|
|
@ -102,6 +102,28 @@
|
|||
"feature1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 7,
|
||||
"description": "driver description test",
|
||||
"driver_description": "Long And Special Driver Description",
|
||||
"os": {
|
||||
"type": "win"
|
||||
},
|
||||
"features": [
|
||||
"feature2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"description": "Windows version test",
|
||||
"os": {
|
||||
"type": "win",
|
||||
"release": [ "10" ]
|
||||
},
|
||||
"features": [
|
||||
"win10_feature"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": 128,
|
||||
"description": "check for matching GL_VENDOR",
|
||||
|
|
|
|||
|
|
@ -243,25 +243,43 @@ void tst_QOpenGlConfig::testBugList()
|
|||
QSet<QString> expectedFeatures;
|
||||
expectedFeatures << "feature1";
|
||||
|
||||
// adapter info
|
||||
QVersionNumber driverVersion(QVector<int>() << 9 << 18 << 13 << 4460);
|
||||
QOpenGLConfig::Gpu gpu = QOpenGLConfig::Gpu::fromDevice(0x10DE, 0x0DE9, driverVersion);
|
||||
QOpenGLConfig::Gpu gpu = QOpenGLConfig::Gpu::fromDevice(0x10DE, 0x0DE9, driverVersion, QByteArrayLiteral("Unknown"));
|
||||
|
||||
QSet<QString> actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("win"),
|
||||
QVersionNumber(6, 3), fileName);
|
||||
QVersionNumber(6, 3), QStringLiteral("7"), fileName);
|
||||
QVERIFY2(expectedFeatures == actualFeatures,
|
||||
msgSetMismatch(expectedFeatures, actualFeatures));
|
||||
|
||||
// driver_description
|
||||
gpu = QOpenGLConfig::Gpu::fromDevice(0xDEAD, 0xBEEF, driverVersion, QByteArrayLiteral("Very Long And Special Driver Description"));
|
||||
actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("win"),
|
||||
QVersionNumber(6, 3), QStringLiteral("8"), fileName);
|
||||
expectedFeatures = QSet<QString>() << "feature2";
|
||||
QVERIFY2(expectedFeatures == actualFeatures,
|
||||
msgSetMismatch(expectedFeatures, actualFeatures));
|
||||
|
||||
// os.release
|
||||
gpu = QOpenGLConfig::Gpu::fromDevice(0xDEAD, 0xBEEF, driverVersion, QByteArrayLiteral("WinVerTest"));
|
||||
actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("win"),
|
||||
QVersionNumber(12, 34), QStringLiteral("10"), fileName);
|
||||
expectedFeatures = QSet<QString>() << "win10_feature";
|
||||
QVERIFY2(expectedFeatures == actualFeatures,
|
||||
msgSetMismatch(expectedFeatures, actualFeatures));
|
||||
|
||||
// gl_vendor
|
||||
gpu = QOpenGLConfig::Gpu::fromGLVendor(QByteArrayLiteral("Somebody Else"));
|
||||
expectedFeatures.clear();
|
||||
actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("linux"),
|
||||
QVersionNumber(1, 0), fileName);
|
||||
QVersionNumber(1, 0), QString(), fileName);
|
||||
QVERIFY2(expectedFeatures == actualFeatures,
|
||||
msgSetMismatch(expectedFeatures, actualFeatures));
|
||||
|
||||
gpu = QOpenGLConfig::Gpu::fromGLVendor(QByteArrayLiteral("The Qt Company"));
|
||||
expectedFeatures = QSet<QString>() << "cool_feature";
|
||||
actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("linux"),
|
||||
QVersionNumber(1, 0), fileName);
|
||||
QVersionNumber(1, 0), QString(), fileName);
|
||||
QVERIFY2(expectedFeatures == actualFeatures,
|
||||
msgSetMismatch(expectedFeatures, actualFeatures));
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue