diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp index 61d0614724..c8d33df4ba 100644 --- a/src/gui/opengl/qopengl.cpp +++ b/src/gui/opengl/qopengl.cpp @@ -36,6 +36,7 @@ #include "qopenglcontext.h" #include "qopenglfunctions.h" +#include "qoffscreensurface.h" #include #include @@ -89,8 +90,8 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher() } /* Helpers to read out the list of features matching a device from - * a Chromium driver bug list of the format using a subset of keys - * (namely, matching by gl_vendor RegExp is not implemented): + * a Chromium driver bug list. Note that not all keys are supported and + * some may behave differently: gl_vendor is a substring match instead of regex. { "entries": [ { @@ -291,14 +292,14 @@ static bool matches(const QJsonObject &object, const QJsonValue vendorV = object.value(vendorIdKey()); if (vendorV.isString()) { - if (gpu.vendorId != vendorV.toString().toUInt(Q_NULLPTR, /* base */ 0)) - return false; + if (gpu.vendorId != vendorV.toString().toUInt(Q_NULLPTR, /* base */ 0)) + return false; } else { if (object.contains(glVendorKey())) { - qWarning().nospace() << "Id " << object.value(idKey()).toInt() - << ": Matching by " << glVendorKey() << " is not implemented."; - return false; - } + const QByteArray glVendorV = object.value(glVendorKey()).toString().toUtf8(); + if (!gpu.glVendor.contains(glVendorV)) + return false; + } } if (gpu.deviceId) { @@ -447,5 +448,30 @@ QSet QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QString &fileName return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), fileName); } +QOpenGLConfig::Gpu QOpenGLConfig::Gpu::fromContext() +{ + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + QScopedPointer tmpContext; + QScopedPointer tmpSurface; + if (!ctx) { + tmpContext.reset(new QOpenGLContext); + if (!tmpContext->create()) { + qWarning("QOpenGLConfig::Gpu::fromContext: Failed to create temporary context"); + return QOpenGLConfig::Gpu(); + } + tmpSurface.reset(new QOffscreenSurface); + tmpSurface->setFormat(tmpContext->format()); + tmpSurface->create(); + tmpContext->makeCurrent(tmpSurface.data()); + } + + QOpenGLConfig::Gpu gpu; + ctx = QOpenGLContext::currentContext(); + const GLubyte *p = ctx->functions()->glGetString(GL_VENDOR); + if (p) + gpu.glVendor = QByteArray(reinterpret_cast(p)); + + return gpu; +} QT_END_NAMESPACE diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h index e04ae05120..980e02aea6 100644 --- a/src/gui/opengl/qopengl_p.h +++ b/src/gui/opengl/qopengl_p.h @@ -74,16 +74,34 @@ private: class Q_GUI_EXPORT QOpenGLConfig { public: - struct Gpu { + struct Q_GUI_EXPORT Gpu { Gpu() : vendorId(0), deviceId(0) {} - bool isValid() const { return deviceId; } + bool isValid() const { return deviceId || !glVendor.isEmpty(); } bool equals(const Gpu &other) const { - return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion; + return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion + && glVendor == other.glVendor; } uint vendorId; uint deviceId; QVersionNumber driverVersion; + QByteArray glVendor; + + static Gpu fromDevice(uint vendorId, uint deviceId, QVersionNumber driverVersion) { + Gpu gpu; + gpu.vendorId = vendorId; + gpu.deviceId = deviceId; + gpu.driverVersion = driverVersion; + return gpu; + } + + static Gpu fromGLVendor(const QByteArray &glVendor) { + Gpu gpu; + gpu.glVendor = glVendor; + return gpu; + } + + static Gpu fromContext(); }; static QSet gpuFeatures(const Gpu &gpu, diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index f5065a22b8..2e6a43f596 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -224,10 +224,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c #elif defined(Q_OS_WINCE) return QWindowsOpenGLTester::Gles; #else - QOpenGLConfig::Gpu qgpu; - qgpu.deviceId = gpu.deviceId; - qgpu.vendorId = gpu.vendorId; - qgpu.driverVersion = gpu.driverVersion; + QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.deviceId, gpu.vendorId, gpu.driverVersion); SupportedRenderersCache *srCache = supportedRenderersCache(); SupportedRenderersCache::const_iterator it = srCache->find(qgpu); if (it != srCache->cend()) diff --git a/tests/auto/gui/qopenglconfig/buglist.json b/tests/auto/gui/qopenglconfig/buglist.json index d2d06645aa..c7b8e61bc8 100644 --- a/tests/auto/gui/qopenglconfig/buglist.json +++ b/tests/auto/gui/qopenglconfig/buglist.json @@ -101,6 +101,14 @@ "features": [ "feature1" ] + }, + { + "id": 128, + "description": "check for matching GL_VENDOR", + "gl_vendor": "The Qt Company", + "features": [ + "cool_feature" + ] } ] } diff --git a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp index bfb2623508..f88cbdc758 100644 --- a/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp +++ b/tests/auto/gui/qopenglconfig/tst_qopenglconfig.cpp @@ -217,6 +217,11 @@ void tst_QOpenGlConfig::testGlConfiguration() context.doneCurrent(); qDebug().noquote() << '\n' << result; + + // fromContext either uses the current context or creates a temporary dummy one. + QOpenGLConfig::Gpu gpu = QOpenGLConfig::Gpu::fromContext(); + qDebug().noquote() << '\n' << "GL_VENDOR queried by QOpenGLConfig::Gpu:" << gpu.glVendor; + QVERIFY(!gpu.glVendor.isEmpty()); } static inline QByteArray msgSetMismatch(const QSet &expected, @@ -235,21 +240,28 @@ void tst_QOpenGlConfig::testBugList() const QString fileName = QFINDTESTDATA("buglist.json"); QVERIFY(!fileName.isEmpty()); - QSet expectedFeatures; - expectedFeatures << "feature1"; + QSet expectedFeatures; + expectedFeatures << "feature1"; - QOpenGLConfig::Gpu gpu; - gpu.vendorId = 0x10DE; - gpu.deviceId = 0x0DE9; + QVersionNumber driverVersion(QVector() << 9 << 18 << 13 << 4460); + QOpenGLConfig::Gpu gpu = QOpenGLConfig::Gpu::fromDevice(0x10DE, 0x0DE9, driverVersion); -#ifdef Q_COMPILER_INITIALIZER_LISTS - gpu.driverVersion = QVersionNumber({9, 18, 13, 4460}); -#else - gpu.driverVersion = QVersionNumber(QVector() << 9 << 18 << 13 << 4460); -#endif - const QSet actualFeatures = - QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("win"), - QVersionNumber(6, 3), fileName); + QSet actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("win"), + QVersionNumber(6, 3), fileName); + QVERIFY2(expectedFeatures == actualFeatures, + msgSetMismatch(expectedFeatures, actualFeatures)); + + gpu = QOpenGLConfig::Gpu::fromGLVendor(QByteArrayLiteral("Somebody Else")); + expectedFeatures.clear(); + actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("linux"), + QVersionNumber(1, 0), fileName); + QVERIFY2(expectedFeatures == actualFeatures, + msgSetMismatch(expectedFeatures, actualFeatures)); + + gpu = QOpenGLConfig::Gpu::fromGLVendor(QByteArrayLiteral("The Qt Company")); + expectedFeatures = QSet() << "cool_feature"; + actualFeatures = QOpenGLConfig::gpuFeatures(gpu, QStringLiteral("linux"), + QVersionNumber(1, 0), fileName); QVERIFY2(expectedFeatures == actualFeatures, msgSetMismatch(expectedFeatures, actualFeatures)); }