diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsopengltester.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsopengltester.cpp | 112 |
1 files changed, 77 insertions, 35 deletions
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index c52e4e612e..3efccf0f32 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -40,15 +40,15 @@ #include "qwindowsopengltester.h" #include "qwindowscontext.h" -#include <QtCore/QVariantMap> -#include <QtCore/QDebug> -#include <QtCore/QTextStream> -#include <QtCore/QCoreApplication> -#include <QtCore/QFile> -#include <QtCore/QFileInfo> -#include <QtCore/QStandardPaths> -#include <QtCore/QLibraryInfo> -#include <QtCore/QHash> +#include <QtCore/qvariant.h> +#include <QtCore/qdebug.h> +#include <QtCore/qtextstream.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qfile.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qstandardpaths.h> +#include <QtCore/qlibraryinfo.h> +#include <QtCore/qhash.h> #ifndef QT_NO_OPENGL #include <private/qopengl_p.h> @@ -60,6 +60,8 @@ QT_BEGIN_NAMESPACE +static const DWORD VENDOR_ID_AMD = 0x1002; + GpuDescription GpuDescription::detect() { typedef IDirect3D9 * (WINAPI *PtrDirect3DCreate9)(UINT); @@ -74,9 +76,16 @@ GpuDescription GpuDescription::detect() IDirect3D9 *direct3D9 = direct3DCreate9(D3D_SDK_VERSION); if (!direct3D9) return result; + D3DADAPTER_IDENTIFIER9 adapterIdentifier; - const HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier); - direct3D9->Release(); + bool isAMD = false; + // Adapter "0" is D3DADAPTER_DEFAULT which returns the default adapter. In + // multi-GPU, multi-screen setups this is the GPU that is associated with + // the "main display" in the Display Settings, and this is the GPU OpenGL + // and D3D uses by default. Therefore querying any additional adapters is + // futile and not useful for our purposes in general, except for + // identifying a few special cases later on. + HRESULT hr = direct3D9->GetAdapterIdentifier(0, 0, &adapterIdentifier); if (SUCCEEDED(hr)) { result.vendorId = adapterIdentifier.VendorId; result.deviceId = adapterIdentifier.DeviceId; @@ -90,7 +99,37 @@ GpuDescription GpuDescription::detect() result.driverVersion = QVersionNumber(version); result.driverName = adapterIdentifier.Driver; result.description = adapterIdentifier.Description; + isAMD = result.vendorId == VENDOR_ID_AMD; + } + + // Detect QTBUG-50371 (having AMD as the default adapter results in a crash + // when starting apps on a screen connected to the Intel card) by looking + // for a default AMD adapter and an additional non-AMD one. + if (isAMD) { + const UINT adapterCount = direct3D9->GetAdapterCount(); + for (UINT adp = 1; adp < adapterCount; ++adp) { + hr = direct3D9->GetAdapterIdentifier(adp, 0, &adapterIdentifier); + if (SUCCEEDED(hr)) { + if (adapterIdentifier.VendorId != VENDOR_ID_AMD) { + // Bingo. Now figure out the display for the AMD card. + DISPLAY_DEVICE dd; + memset(&dd, 0, sizeof(dd)); + dd.cb = sizeof(dd); + for (int dev = 0; EnumDisplayDevices(nullptr, dev, &dd, 0); ++dev) { + if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { + // DeviceName is something like \\.\DISPLAY1 which can be used to + // match with the MONITORINFOEX::szDevice queried by QWindowsScreen. + result.gpuSuitableScreen = QString::fromWCharArray(dd.DeviceName); + break; + } + } + break; + } + } + } } + + direct3D9->Release(); return result; } @@ -103,7 +142,8 @@ QDebug operator<<(QDebug d, const GpuDescription &gd) << ", deviceId=" << gd.deviceId << ", subSysId=" << gd.subSysId << dec << noshowbase << ", revision=" << gd.revision << ", driver: " << gd.driverName - << ", version=" << gd.driverVersion << ", " << gd.description << ')'; + << ", version=" << gd.driverVersion << ", " << gd.description + << gd.gpuSuitableScreen << ')'; return d; } #endif // !QT_NO_DEBUG_STREAM @@ -113,15 +153,17 @@ QString GpuDescription::toString() const { QString result; QTextStream str(&result); - str << " Card name: " << description - << "\n Driver Name: " << driverName - << "\n Driver Version: " << driverVersion.toString() - << "\n Vendor ID: 0x" << qSetPadChar(QLatin1Char('0')) + str << " Card name : " << description + << "\n Driver Name : " << driverName + << "\n Driver Version : " << driverVersion.toString() + << "\n Vendor ID : 0x" << qSetPadChar(QLatin1Char('0')) << uppercasedigits << hex << qSetFieldWidth(4) << vendorId - << "\n Device ID: 0x" << qSetFieldWidth(4) << deviceId - << "\n SubSys ID: 0x" << qSetFieldWidth(8) << subSysId - << "\n Revision ID: 0x" << qSetFieldWidth(4) << revision + << "\n Device ID : 0x" << qSetFieldWidth(4) << deviceId + << "\n SubSys ID : 0x" << qSetFieldWidth(8) << subSysId + << "\n Revision ID : 0x" << qSetFieldWidth(4) << revision << dec; + if (!gpuSuitableScreen.isEmpty()) + str << "\nGL windows forced to screen: " << gpuSuitableScreen; return result; } @@ -205,11 +247,12 @@ typedef QHash<QOpenGLConfig::Gpu, QWindowsOpenGLTester::Renderers> SupportedRend Q_GLOBAL_STATIC(SupportedRenderersCache, supportedRenderersCache) #endif -QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu, bool glesOnly) +QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(const GpuDescription &gpu, + Renderer requested) { - Q_UNUSED(gpu) - Q_UNUSED(glesOnly) #if defined(QT_NO_OPENGL) + Q_UNUSED(gpu) + Q_UNUSED(requested) return 0; #else QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.vendorId, gpu.deviceId, gpu.driverVersion, gpu.description); @@ -223,8 +266,11 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c | QWindowsOpenGLTester::AngleRendererD3d11Warp | QWindowsOpenGLTester::SoftwareRasterizer); - if (!glesOnly && testDesktopGL()) - result |= QWindowsOpenGLTester::DesktopGl; + // Don't test for GL if explicitly requested or GLES only is requested + if (requested == DesktopGl + || ((requested & GlesMask) == 0 && testDesktopGL())) { + result |= QWindowsOpenGLTester::DesktopGl; + } const char bugListFileVar[] = "QT_OPENGL_BUGLIST"; QString buglistFileName = QStringLiteral(":/qt-project.org/windows/openglblacklists/default.json"); @@ -259,24 +305,20 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c qCDebug(lcQpaGl) << "Disabling rotation: " << gpu; result |= DisableRotationFlag; } + if (features.contains(QStringLiteral("disable_program_cache"))) { + qCDebug(lcQpaGl) << "Disabling program cache: " << gpu; + result |= DisableProgramCacheFlag; + } srCache->insert(qgpu, result); return result; #endif // !QT_NO_OPENGL } -QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedGlesRenderers() -{ - const GpuDescription gpu = GpuDescription::detect(); - const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, true); - qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; - return result; -} - -QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers() +QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::supportedRenderers(Renderer requested) { const GpuDescription gpu = GpuDescription::detect(); - const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, false); - qCDebug(lcQpaGl) << __FUNCTION__ << gpu << "renderer: " << result; + const QWindowsOpenGLTester::Renderers result = detectSupportedRenderers(gpu, requested); + qCDebug(lcQpaGl) << __FUNCTION__ << gpu << requested << "renderer: " << result; return result; } |