diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2019-09-30 13:35:44 +0000 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2019-10-01 09:47:33 +0000 |
commit | 6b3de85f2b12a001a8f7a55da917a6f2fa004dcd (patch) | |
tree | 01e6d52c433adae07b74ab9fe3fc6295192d2760 /src/plugins/platforms/windows/qwindowsopengltester.cpp | |
parent | b0042601ed8056c9ed6056c26f71dfa9fbc951ce (diff) |
Revert "Windows QPA: Preferably use DXGI to obtain adapter info"
This reverts commit 94902905ec203626abc050744d14898674dc2bbd.
The patch caused various test failures on Windows 7 in the CI system in qtdeclarative and qt3d.
Without the patch we ended up using openglsw32.dll, with this patch we get
qt.qpa.gl unknown - supportedRenderers GpuDescription(vendorId=0x0, deviceId=0x0, subSysId=0x0, revision=0, driver: \"\", version=, \"\"\"\") 0 renderer: QFlags(0x8|0x20)
and then end up using ANGLE, which fails.
Change-Id: I97c51f9c360461e1a05722d02d50c2450ca87b78
Task-number: QTBUG-78832
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'src/plugins/platforms/windows/qwindowsopengltester.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowsopengltester.cpp | 256 |
1 files changed, 23 insertions, 233 deletions
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp index 63ecbfe0ea..afc1991e2c 100644 --- a/src/plugins/platforms/windows/qwindowsopengltester.cpp +++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp @@ -47,7 +47,6 @@ #include <QtCore/qfile.h> #include <QtCore/qfileinfo.h> #include <QtCore/qstandardpaths.h> -#include <QtCore/qlibrary.h> #include <QtCore/qlibraryinfo.h> #include <QtCore/qhash.h> @@ -58,8 +57,6 @@ #include <QtCore/qt_windows.h> #include <private/qsystemlibrary_p.h> #include <d3d9.h> -#include <d3d10.h> -#include <dxgi.h> QT_BEGIN_NAMESPACE @@ -83,259 +80,52 @@ static GpuDescription adapterIdentifierToGpuDescription(const D3DADAPTER_IDENTIF return result; } -class QGraphicsAdapterInfo +class QDirect3D9Handle { public: - Q_DISABLE_COPY_MOVE(QGraphicsAdapterInfo) + Q_DISABLE_COPY_MOVE(QDirect3D9Handle) - QGraphicsAdapterInfo(); - ~QGraphicsAdapterInfo(); + QDirect3D9Handle(); + ~QDirect3D9Handle(); - bool isValid() const; + bool isValid() const { return m_direct3D9 != nullptr; } - UINT adapterCount() const; + UINT adapterCount() const { return m_direct3D9 ? m_direct3D9->GetAdapterCount() : 0u; } bool retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const; private: - QSystemLibrary m_dxgilib; - IDXGIFactory1 *m_dxgiFactory1 = nullptr; - QSystemLibrary m_d3d9lib; IDirect3D9 *m_direct3D9 = nullptr; - - /* This is a value from the DXGI_ADAPTER_FLAG enum. - * However, it's not available in dxgi.h from MinGW, - * so define it here in any case. */ - enum { DXGI_ADAPTER_FLAG_SOFTWARE = 2 }; - - UINT adapterCountDXGI() const; - bool retrieveAdapterIdentifierDXGI(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const; - - UINT adapterCountD3D9() const; - bool retrieveAdapterIdentifierD3D9(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const; }; -QGraphicsAdapterInfo::QGraphicsAdapterInfo() : - m_dxgilib(QStringLiteral("dxgi")), +QDirect3D9Handle::QDirect3D9Handle() : m_d3d9lib(QStringLiteral("d3d9")) { - using PtrCreateDXGIFactory1 = HRESULT (WINAPI *)(REFIID, void**); + using PtrDirect3DCreate9 = IDirect3D9 *(WINAPI *)(UINT); - if (m_dxgilib.load()) { - if (auto createDXGIFactory1 = (PtrCreateDXGIFactory1)m_dxgilib.resolve("CreateDXGIFactory1")) - createDXGIFactory1(IID_PPV_ARGS(&m_dxgiFactory1)); - } - - if (!m_dxgiFactory1) { - using PtrDirect3DCreate9 = IDirect3D9 *(WINAPI *)(UINT); - - if (m_d3d9lib.load()) { - if (auto direct3DCreate9 = (PtrDirect3DCreate9)m_d3d9lib.resolve("Direct3DCreate9")) - m_direct3D9 = direct3DCreate9(D3D_SDK_VERSION); - } + if (m_d3d9lib.load()) { + if (auto direct3DCreate9 = (PtrDirect3DCreate9)m_d3d9lib.resolve("Direct3DCreate9")) + m_direct3D9 = direct3DCreate9(D3D_SDK_VERSION); } } -QGraphicsAdapterInfo::~QGraphicsAdapterInfo() +QDirect3D9Handle::~QDirect3D9Handle() { - if (m_dxgiFactory1) - m_dxgiFactory1->Release(); if (m_direct3D9) m_direct3D9->Release(); } -bool QGraphicsAdapterInfo::isValid() const -{ - return m_dxgiFactory1 != nullptr || m_direct3D9 != nullptr; -} - -UINT QGraphicsAdapterInfo::adapterCount() const -{ - if (m_dxgiFactory1) - return adapterCountDXGI(); - if (m_direct3D9) - return adapterCountD3D9(); - return 0; -} - -bool QGraphicsAdapterInfo::retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const -{ - if (m_dxgiFactory1) - return retrieveAdapterIdentifierDXGI(n, adapterIdentifier); - if (m_direct3D9) - return retrieveAdapterIdentifierD3D9(n, adapterIdentifier); - return false; -} - -UINT QGraphicsAdapterInfo::adapterCountDXGI() const -{ - /* DXGI doesn't have an adapterCount(), instead we have to call EnumAdapters1() - * until DXGI_ERROR_NOT_FOUND is returned. */ - UINT n = 0; - - IDXGIAdapter1 *adapter; - while (SUCCEEDED(m_dxgiFactory1->EnumAdapters1(n, &adapter))) { - adapter->Release(); - ++n; - } - - return n; -} - -// Detect whether we are running under 64-bit Windows. -static bool isWow64Process() -{ - typedef BOOL (WINAPI *IsWow64ProcessPtr)(HANDLE hProcess, PBOOL Wow64Process); - IsWow64ProcessPtr IsWow64Process = (IsWow64ProcessPtr)QLibrary::resolve( - QStringLiteral("kernel32.dll"), "IsWow64Process"); - - if (IsWow64Process) { - BOOL IsWow64 = FALSE; - if (IsWow64Process(GetCurrentProcess(), &IsWow64)) - return IsWow64; - } - return false; -} - -// Read a string value from registry -static QString regGetString(HKEY key, const wchar_t* valueName) -{ - QVarLengthArray<wchar_t, MAX_PATH> buf (MAX_PATH); - LRESULT res; - DWORD bufSize = buf.size() * sizeof(wchar_t); - res = RegGetValue(key, nullptr, valueName, - RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ, nullptr, - buf.data(), &bufSize); - if (res == ERROR_MORE_DATA) { - buf.resize(bufSize / sizeof(wchar_t)); - bufSize = buf.size() * sizeof(wchar_t); - res = RegGetValue(key, nullptr, valueName, - RRF_RT_REG_SZ | RRF_RT_REG_MULTI_SZ, nullptr, - buf.data(), &bufSize); - } - /* In case of REG_MULTI_SZ, this returns just the first string, - * but that is sufficient for our purposes. */ - if (res == ERROR_SUCCESS) - return QString::fromWCharArray(buf.data()); - return QString(); -} - -// Read driver name given a DeviceKey -static QString retrieveDriverName(const wchar_t *driverKey) -{ - /* Kernel-style prefix, maps to HKLM - * (see https://docs.microsoft.com/en-us/windows-hardware/drivers/kernel/registry-key-object-routines) */ - static const wchar_t prefixMappingHKLM[] = L"\\Registry\\Machine\\"; - const size_t prefixMappingHKLMLen = wcslen(prefixMappingHKLM); - if (wcsnicmp(driverKey, prefixMappingHKLM, prefixMappingHKLMLen) != 0) - return QString(); - - driverKey += prefixMappingHKLMLen; - QString driverPath; - HKEY key; - if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, driverKey, 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS) { - const wchar_t *valueName = - isWow64Process() ? L"UserModeDriverNameWow" : L"UserModeDriverName"; - driverPath = regGetString(key, valueName); - RegCloseKey(key); - } - if (!driverPath.isEmpty()) { - int fileNameSep = driverPath.lastIndexOf(QLatin1Char('\\')); - if (fileNameSep >= 0) - driverPath = driverPath.mid(fileNameSep + 1); - return driverPath; - } - return QString(); -} - -// Retrieve driver name for a display device from registry. -static QString driverNameForDevice(const wchar_t *displayDevice) -{ - QString driverName; - DISPLAY_DEVICE dd; - memset(&dd, 0, sizeof(dd)); - dd.cb = sizeof(dd); - for (int dev = 0; EnumDisplayDevices(nullptr, dev, &dd, 0); ++dev) { - if (wcsicmp(displayDevice, dd.DeviceName) == 0) { - // DeviceKey is documented as "internal", but it's a registry key in kernel format - driverName = retrieveDriverName(dd.DeviceKey); - break; - } - } - if (driverName.isEmpty()) { - /* Fall back to driver name from EnumDisplaySettings. - * This is only a fallback as on Windows 10 this just returns an device-independent - * name. OTOH, it's possible to recognize RDP connections from the driver name. */ - DEVMODE devMode; - if (EnumDisplaySettings(displayDevice, ENUM_CURRENT_SETTINGS, &devMode)) - driverName = QString::fromWCharArray(devMode.dmDeviceName); - } - return driverName; -} - -bool QGraphicsAdapterInfo::retrieveAdapterIdentifierDXGI(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const -{ - IDXGIAdapter1 *adapter; - if (FAILED(m_dxgiFactory1->EnumAdapters1(n, &adapter))) - return false; - - bool result = false; - - DXGI_ADAPTER_DESC1 adapterDesc; - if (SUCCEEDED(adapter->GetDesc1(&adapterDesc))) { - if ((adapterDesc.VendorId != 0) && (adapterDesc.DeviceId != 0) // Don't use adapter description of Software Devices - && ((adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) == 0)) { - memset(adapterIdentifier, 0, sizeof(*adapterIdentifier)); - WideCharToMultiByte(1252, 0, adapterDesc.Description, -1, - adapterIdentifier->Description, - sizeof(adapterIdentifier->Description), nullptr, nullptr); - adapterIdentifier->Description[sizeof(adapterIdentifier->Description) - 1] = 0; - adapterIdentifier->VendorId = adapterDesc.VendorId; - adapterIdentifier->DeviceId = adapterDesc.DeviceId; - adapterIdentifier->SubSysId = adapterDesc.SubSysId; - adapterIdentifier->Revision = adapterDesc.Revision; - - LARGE_INTEGER umdVersion; - if (SUCCEEDED(adapter->CheckInterfaceSupport(__uuidof(ID3D10Device), &umdVersion))) { - adapterIdentifier->DriverVersion = umdVersion; - result = true; - } - - /* DXGI doesn't expose the driver name, but we can get it from the registry. - * But we need a device name to follow. */ - IDXGIOutput *output = nullptr; - if (SUCCEEDED(adapter->EnumOutputs (0, &output))) { - DXGI_OUTPUT_DESC outputDesc; - if (SUCCEEDED(output->GetDesc (&outputDesc))) { - QString driverName = driverNameForDevice(outputDesc.DeviceName); - qstrncpy(adapterIdentifier->Driver, driverName.toLatin1().constData(), - sizeof(adapterIdentifier->Driver)); - } - output->Release(); - } - } - } - - adapter->Release(); - - return result; -} - -UINT QGraphicsAdapterInfo::adapterCountD3D9() const -{ - return m_direct3D9->GetAdapterCount(); -} - -bool QGraphicsAdapterInfo::retrieveAdapterIdentifierD3D9(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const +bool QDirect3D9Handle::retrieveAdapterIdentifier(UINT n, D3DADAPTER_IDENTIFIER9 *adapterIdentifier) const { - return SUCCEEDED(m_direct3D9->GetAdapterIdentifier(n, 0, adapterIdentifier)); + return m_direct3D9 + && SUCCEEDED(m_direct3D9->GetAdapterIdentifier(n, 0, adapterIdentifier)); } GpuDescription GpuDescription::detect() { GpuDescription result; - QGraphicsAdapterInfo adapterInfo; - if (!adapterInfo.isValid()) + QDirect3D9Handle direct3D9; + if (!direct3D9.isValid()) return result; D3DADAPTER_IDENTIFIER9 adapterIdentifier; @@ -346,7 +136,7 @@ GpuDescription GpuDescription::detect() // 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. - if (adapterInfo.retrieveAdapterIdentifier(0, &adapterIdentifier)) { + if (direct3D9.retrieveAdapterIdentifier(0, &adapterIdentifier)) { result = adapterIdentifierToGpuDescription(adapterIdentifier); isAMD = result.vendorId == VENDOR_ID_AMD; } @@ -355,9 +145,9 @@ GpuDescription GpuDescription::detect() // 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 = adapterInfo.adapterCount(); + const UINT adapterCount = direct3D9.adapterCount(); for (UINT adp = 1; adp < adapterCount; ++adp) { - if (adapterInfo.retrieveAdapterIdentifier(adp, &adapterIdentifier) + if (direct3D9.retrieveAdapterIdentifier(adp, &adapterIdentifier) && adapterIdentifier.VendorId != VENDOR_ID_AMD) { // Bingo. Now figure out the display for the AMD card. DISPLAY_DEVICE dd; @@ -382,11 +172,11 @@ GpuDescription GpuDescription::detect() QVector<GpuDescription> GpuDescription::detectAll() { QVector<GpuDescription> result; - QGraphicsAdapterInfo adapterInfo; - if (const UINT adapterCount = adapterInfo.adapterCount()) { + QDirect3D9Handle direct3D9; + if (const UINT adapterCount = direct3D9.adapterCount()) { for (UINT adp = 0; adp < adapterCount; ++adp) { D3DADAPTER_IDENTIFIER9 adapterIdentifier; - if (adapterInfo.retrieveAdapterIdentifier(adp, &adapterIdentifier)) + if (direct3D9.retrieveAdapterIdentifier(adp, &adapterIdentifier)) result.append(adapterIdentifierToGpuDescription(adapterIdentifier)); } } |