summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk2
-rw-r--r--vcl/Module_vcl.mk4
-rw-r--r--vcl/Package_skia_blacklist.mk16
-rw-r--r--vcl/inc/driverblocklist.hxx158
-rw-r--r--vcl/inc/opengl/win/WinDeviceInfo.hxx113
-rw-r--r--vcl/inc/opengl/win/blocklist_parser.hxx42
-rw-r--r--vcl/opengl/win/WinDeviceInfo.cxx411
-rw-r--r--vcl/opengl/win/blocklist_parser.cxx351
-rw-r--r--vcl/qa/cppunit/blocklistparsertest.cxx94
-rw-r--r--vcl/skia/SkiaHelper.cxx39
-rw-r--r--vcl/skia/skia_blacklist_vulkan.xml30
-rw-r--r--vcl/source/helper/driverblocklist.cxx711
-rw-r--r--vcl/source/opengl/OpenGLHelper.cxx4
13 files changed, 1004 insertions, 971 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 1b5a6db8ec65..ca818e271c22 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -369,6 +369,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/helper/canvastools \
vcl/source/helper/commandinfoprovider \
vcl/source/helper/displayconnectiondispatch \
+ vcl/source/helper/driverblocklist \
vcl/source/helper/errcode \
vcl/source/helper/evntpost \
vcl/source/helper/lazydelete \
@@ -702,7 +703,6 @@ endif
ifeq ($(OS),WNT)
$(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/opengl/win/WinDeviceInfo \
- vcl/opengl/win/blocklist_parser \
vcl/source/app/salplug \
))
diff --git a/vcl/Module_vcl.mk b/vcl/Module_vcl.mk
index 5620f188c7f2..9736be35fedf 100644
--- a/vcl/Module_vcl.mk
+++ b/vcl/Module_vcl.mk
@@ -27,6 +27,8 @@ $(eval $(call gb_Module_add_targets,vcl,\
UIConfig_vcl \
$(if $(filter WNT,$(OS)), \
Package_opengl_blacklist ) \
+ $(if $(filter SKIA,$(BUILD_TYPE)), \
+ Package_skia_blacklist ) \
$(if $(filter DESKTOP,$(BUILD_TYPE)), \
StaticLibrary_vclmain \
$(if $(ENABLE_MACOSX_SANDBOX),, \
@@ -204,6 +206,7 @@ $(eval $(call gb_Module_add_check_targets,vcl,\
CppunitTest_vcl_png_test \
CppunitTest_vcl_widget_definition_reader_test \
CppunitTest_vcl_backend_test \
+ CppunitTest_vcl_blocklistparser_test \
))
ifeq ($(USING_X11),TRUE)
@@ -222,7 +225,6 @@ endif
ifeq ($(OS),WNT)
$(eval $(call gb_Module_add_check_targets,vcl,\
CppunitTest_vcl_timer \
- CppunitTest_vcl_blocklistparser_test \
))
endif
diff --git a/vcl/Package_skia_blacklist.mk b/vcl/Package_skia_blacklist.mk
new file mode 100644
index 000000000000..611766eb7aa3
--- /dev/null
+++ b/vcl/Package_skia_blacklist.mk
@@ -0,0 +1,16 @@
+# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
+#
+# This file is part of the LibreOffice project.
+#
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+#
+
+$(eval $(call gb_Package_Package,vcl_skia_blacklist,$(SRCDIR)/vcl/skia))
+
+$(eval $(call gb_Package_add_files,vcl_skia_blacklist,$(LIBO_SHARE_FOLDER)/skia,\
+ skia_blacklist_vulkan.xml \
+))
+
+# vim: set noet sw=4 ts=4:
diff --git a/vcl/inc/driverblocklist.hxx b/vcl/inc/driverblocklist.hxx
new file mode 100644
index 000000000000..e8f99378fa24
--- /dev/null
+++ b/vcl/inc/driverblocklist.hxx
@@ -0,0 +1,158 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_VCL_DRIVERBLOCKLIST_HXX
+#define INCLUDED_VCL_DRIVERBLOCKLIST_HXX
+
+#include <vcl/dllapi.h>
+#include <xmlreader/xmlreader.hxx>
+#include <vector>
+
+namespace DriverBlocklist
+{
+VCL_DLLPUBLIC bool IsDeviceBlocked(const OUString& blocklistURL, const OUString& driverVersion,
+ const OUString& vendorId, const OUString& deviceId);
+
+#ifdef _WIN32
+VCL_DLLPUBLIC int32_t GetWindowsVersion();
+#endif
+
+// The rest should be private (only for the unittest).
+
+struct InvalidFileException
+{
+};
+
+enum OperatingSystem
+{
+ DRIVER_OS_UNKNOWN = 0,
+ DRIVER_OS_WINDOWS_7,
+ DRIVER_OS_WINDOWS_8,
+ DRIVER_OS_WINDOWS_8_1,
+ DRIVER_OS_WINDOWS_10,
+ DRIVER_OS_LINUX,
+ DRIVER_OS_OSX_10_5,
+ DRIVER_OS_OSX_10_6,
+ DRIVER_OS_OSX_10_7,
+ DRIVER_OS_OSX_10_8,
+ DRIVER_OS_ANDROID,
+ DRIVER_OS_ALL
+};
+
+enum VersionComparisonOp
+{
+ DRIVER_LESS_THAN, // driver < version
+ DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
+ DRIVER_GREATER_THAN, // driver > version
+ DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
+ DRIVER_EQUAL, // driver == version
+ DRIVER_NOT_EQUAL, // driver != version
+ DRIVER_BETWEEN_EXCLUSIVE, // driver > version && driver < versionMax
+ DRIVER_BETWEEN_INCLUSIVE, // driver >= version && driver <= versionMax
+ DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
+ DRIVER_COMPARISON_IGNORED
+};
+
+enum DeviceVendor
+{
+ VendorAll,
+ VendorIntel,
+ VendorNVIDIA,
+ VendorAMD,
+ VendorATI,
+ VendorMicrosoft,
+};
+const int DeviceVendorMax = VendorMicrosoft + 1;
+
+struct DriverInfo
+{
+ DriverInfo(OperatingSystem os, const OUString& vendor, VersionComparisonOp op,
+ uint64_t driverVersion, bool bWhiteListed = false,
+ const char* suggestedVersion = nullptr);
+
+ DriverInfo();
+
+ OperatingSystem meOperatingSystem;
+ OUString maAdapterVendor;
+ std::vector<OUString> maDevices;
+
+ bool mbWhitelisted;
+
+ VersionComparisonOp meComparisonOp;
+
+ /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
+ uint64_t mnDriverVersion;
+ uint64_t mnDriverVersionMax;
+ static uint64_t allDriverVersions;
+
+ OUString maSuggestedVersion;
+ OUString maMsg;
+};
+
+class VCL_DLLPUBLIC Parser
+{
+public:
+ Parser(const OUString& rURL, std::vector<DriverInfo>& rDriverList);
+ bool parse();
+
+private:
+ void handleEntry(DriverInfo& rDriver, xmlreader::XmlReader& rReader);
+ void handleList(xmlreader::XmlReader& rReader);
+ void handleContent(xmlreader::XmlReader& rReader);
+ static void handleDevices(DriverInfo& rDriver, xmlreader::XmlReader& rReader);
+
+ enum class BlockType
+ {
+ WHITELIST,
+ BLACKLIST,
+ UNKNOWN
+ };
+
+ BlockType meBlockType;
+ std::vector<DriverInfo>& mrDriverList;
+ OUString maURL;
+};
+
+OUString VCL_DLLPUBLIC GetVendorId(DeviceVendor id);
+
+bool VCL_DLLPUBLIC FindBlocklistedDeviceInList(std::vector<DriverInfo>& aDeviceInfos,
+ OUString const& sDriverVersion,
+ OUString const& sAdapterVendorID,
+ OUString const& sAdapterDeviceID,
+ OperatingSystem system,
+ const OUString& blocklistURL = OUString());
+
+#define GFX_DRIVER_VERSION(a, b, c, d) \
+ ((uint64_t(a) << 48) | (uint64_t(b) << 32) | (uint64_t(c) << 16) | uint64_t(d))
+
+inline uint64_t V(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
+{
+ // We make sure every driver number is padded by 0s, this will allow us the
+ // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
+ // more extensive explanation of this approach.
+ while (b > 0 && b < 1000)
+ {
+ b *= 10;
+ }
+ while (c > 0 && c < 1000)
+ {
+ c *= 10;
+ }
+ while (d > 0 && d < 1000)
+ {
+ d *= 10;
+ }
+ return GFX_DRIVER_VERSION(a, b, c, d);
+}
+
+} // namespace
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/opengl/win/WinDeviceInfo.hxx b/vcl/inc/opengl/win/WinDeviceInfo.hxx
index 773be7af0f7d..04d97406b54a 100644
--- a/vcl/inc/opengl/win/WinDeviceInfo.hxx
+++ b/vcl/inc/opengl/win/WinDeviceInfo.hxx
@@ -13,108 +13,12 @@
#include <vcl/dllapi.h>
#include <opengl/DeviceInfo.hxx>
+#include <driverblocklist.hxx>
#include <rtl/ustring.hxx>
#include <vector>
#include <cstdint>
-namespace wgl {
-
-enum OperatingSystem {
- DRIVER_OS_UNKNOWN = 0,
- DRIVER_OS_WINDOWS_7,
- DRIVER_OS_WINDOWS_8,
- DRIVER_OS_WINDOWS_8_1,
- DRIVER_OS_WINDOWS_10,
- DRIVER_OS_LINUX,
- DRIVER_OS_OS_X_10_5,
- DRIVER_OS_OS_X_10_6,
- DRIVER_OS_OS_X_10_7,
- DRIVER_OS_OS_X_10_8,
- DRIVER_OS_ANDROID,
- DRIVER_OS_ALL
-};
-
-enum VersionComparisonOp {
- DRIVER_LESS_THAN, // driver < version
- DRIVER_LESS_THAN_OR_EQUAL, // driver <= version
- DRIVER_GREATER_THAN, // driver > version
- DRIVER_GREATER_THAN_OR_EQUAL, // driver >= version
- DRIVER_EQUAL, // driver == version
- DRIVER_NOT_EQUAL, // driver != version
- DRIVER_BETWEEN_EXCLUSIVE, // driver > version && driver < versionMax
- DRIVER_BETWEEN_INCLUSIVE, // driver >= version && driver <= versionMax
- DRIVER_BETWEEN_INCLUSIVE_START, // driver >= version && driver < versionMax
- DRIVER_COMPARISON_IGNORED
-};
-
-enum DeviceVendor {
- VendorAll,
- VendorIntel,
- VendorNVIDIA,
- VendorAMD,
- VendorATI,
- VendorMicrosoft,
- DeviceVendorMax
-};
-
-bool ParseDriverVersion(const OUString& rString, uint64_t& rVersion);
-
-struct VCL_DLLPUBLIC DriverInfo
-{
-
- DriverInfo(OperatingSystem os, const OUString& vendor, VersionComparisonOp op,
- uint64_t driverVersion, bool bWhiteListed = false, const char *suggestedVersion = nullptr);
-
- DriverInfo();
- virtual ~DriverInfo();
-
- OperatingSystem meOperatingSystem;
- uint32_t mnOperatingSystemVersion;
-
- OUString maAdapterVendor;
-
- std::vector<OUString> maDevices;
-
- // Whether the mDevices array should be deleted when this structure is
- // deallocated. False by default.
- bool mbDeleteDevices;
-
- bool mbWhitelisted;
-
- VersionComparisonOp meComparisonOp;
-
- /* versions are assumed to be A.B.C.D packed as 0xAAAABBBBCCCCDDDD */
- uint64_t mnDriverVersion;
- uint64_t mnDriverVersionMax;
- static uint64_t allDriverVersions;
-
- OUString maSuggestedVersion;
- OUString maMsg;
-};
-
-#define GFX_DRIVER_VERSION(a,b,c,d) \
- ((uint64_t(a)<<48) | (uint64_t(b)<<32) | (uint64_t(c)<<16) | uint64_t(d))
-
-inline VCL_DLLPUBLIC uint64_t V(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
-{
- // We make sure every driver number is padded by 0s, this will allow us the
- // easiest 'compare as if decimals' approach. See ParseDriverVersion for a
- // more extensive explanation of this approach.
- while (b > 0 && b < 1000) {
- b *= 10;
- }
- while (c > 0 && c < 1000) {
- c *= 10;
- }
- while (d > 0 && d < 1000) {
- d *= 10;
- }
- return GFX_DRIVER_VERSION(a, b, c, d);
-}
-
-}
-
class VCL_DLLPUBLIC WinOpenGLDeviceInfo : public OpenGLDeviceInfo
{
private:
@@ -140,22 +44,16 @@ private:
OUString maDeviceString;
OUString maDeviceString2;
- uint32_t mnWindowsVersion;
bool mbHasDualGPU;
bool mbRDP;
void GetData();
- static void FillBlacklist();
bool FindBlocklistedDeviceInList();
- static OUString* mpDeviceVendors[wgl::DeviceVendorMax];
- static std::vector<wgl::DriverInfo> maDriverInfo;
-
public:
WinOpenGLDeviceInfo();
- static OUString GetDeviceVendor(wgl::DeviceVendor eVendor);
virtual ~WinOpenGLDeviceInfo() override;
virtual bool isDeviceBlocked() override;
@@ -198,15 +96,6 @@ public:
{
return maDeviceString;
}
-
- sal_uInt32 GetWindowsVersion() const
- {
- return mnWindowsVersion;
- }
-
- static bool FindBlocklistedDeviceInList(std::vector<wgl::DriverInfo>& aDeviceInfos,
- OUString const & sDriverVersion, OUString const & sAdapterVendorID,
- OUString const & sAdapterDeviceID, uint32_t nWindowsVersion);
};
#endif
diff --git a/vcl/inc/opengl/win/blocklist_parser.hxx b/vcl/inc/opengl/win/blocklist_parser.hxx
deleted file mode 100644
index 1d1ea314d6f7..000000000000
--- a/vcl/inc/opengl/win/blocklist_parser.hxx
+++ /dev/null
@@ -1,42 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-#include <vcl/dllapi.h>
-#include <xmlreader/xmlreader.hxx>
-#include <vector>
-#include <opengl/win/WinDeviceInfo.hxx>
-
-class InvalidFileException
-{
-};
-
-class VCL_DLLPUBLIC WinBlocklistParser
-{
-public:
- WinBlocklistParser(const OUString& rURL, std::vector<wgl::DriverInfo>& rDriverList);
- void parse();
-
-private:
- void handleEntry(wgl::DriverInfo& rDriver, xmlreader::XmlReader& rReader);
- void handleList(xmlreader::XmlReader& rReader);
- void handleContent(xmlreader::XmlReader& rReader);
-
- enum class BlockType
- {
- WHITELIST,
- BLACKLIST,
- UNKNOWN
- };
-
- BlockType meBlockType;
- std::vector<wgl::DriverInfo>& mrDriverList;
- OUString maURL;
-};
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/win/WinDeviceInfo.cxx b/vcl/opengl/win/WinDeviceInfo.cxx
index 0e466ecd6d4e..3fb4035ec58c 100644
--- a/vcl/opengl/win/WinDeviceInfo.cxx
+++ b/vcl/opengl/win/WinDeviceInfo.cxx
@@ -9,7 +9,7 @@
#include <opengl/win/WinDeviceInfo.hxx>
-#include <opengl/win/blocklist_parser.hxx>
+#include <driverblocklist.hxx>
#include <config_folders.h>
#if !defined WIN32_LEAN_AND_MEAN
@@ -31,23 +31,8 @@
#include <desktop/crashreport.hxx>
-OUString* WinOpenGLDeviceInfo::mpDeviceVendors[wgl::DeviceVendorMax];
-std::vector<wgl::DriverInfo> WinOpenGLDeviceInfo::maDriverInfo;
-
namespace {
-/*
- * Compute the length of an array with constant length. (Use of this method
- * with a non-array pointer will not compile.)
- *
- * Beware of the implicit trailing '\0' when using this with string constants.
-*/
-template<typename T, size_t N>
-size_t ArrayLength(T (&)[N])
-{
- return N;
-}
-
bool GetKeyValue(const WCHAR* keyLocation, const WCHAR* keyName, OUString& destString, int type)
{
HKEY key;
@@ -146,142 +131,6 @@ uint32_t ParseIDFromDeviceID(const OUString &key, const char *prefix, int length
return id.toUInt32(16);
}
-// OS version in 16.16 major/minor form
-// based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
-enum {
- kWindowsUnknown = 0,
- kWindows7 = 0x00060001,
- kWindows8 = 0x00060002,
- kWindows8_1 = 0x00060003,
- kWindows10 = 0x000A0000 // Major 10 Minor 0
-};
-
-
-wgl::OperatingSystem WindowsVersionToOperatingSystem(int32_t aWindowsVersion)
-{
- switch(aWindowsVersion)
- {
- case kWindows7:
- return wgl::DRIVER_OS_WINDOWS_7;
- case kWindows8:
- return wgl::DRIVER_OS_WINDOWS_8;
- case kWindows8_1:
- return wgl::DRIVER_OS_WINDOWS_8_1;
- case kWindows10:
- return wgl::DRIVER_OS_WINDOWS_10;
- case kWindowsUnknown:
- default:
- return wgl::DRIVER_OS_UNKNOWN;
- };
-}
-
-
-int32_t WindowsOSVersion()
-{
- static int32_t winVersion = [&]()
- {
- // GetVersion(Ex) and VersionHelpers (based on VerifyVersionInfo) API are
- // subject to manifest-based behavior since Windows 8.1, so give wrong results.
- // Another approach would be to use NetWkstaGetInfo, but that has some small
- // reported delays (some milliseconds), and might get slower in domains with
- // poor network connections.
- // So go with a solution described at https://msdn.microsoft.com/en-us/library/ms724429
- HINSTANCE hLibrary = LoadLibraryW(L"kernel32.dll");
- if (hLibrary != nullptr)
- {
- wchar_t szPath[MAX_PATH];
- DWORD dwCount = GetModuleFileNameW(hLibrary, szPath, SAL_N_ELEMENTS(szPath));
- FreeLibrary(hLibrary);
- if (dwCount != 0 && dwCount < SAL_N_ELEMENTS(szPath))
- {
- dwCount = GetFileVersionInfoSizeW(szPath, nullptr);
- if (dwCount != 0)
- {
- std::unique_ptr<char[]> ver(new char[dwCount]);
- if (GetFileVersionInfoW(szPath, 0, dwCount, ver.get()) != FALSE)
- {
- void* pBlock = nullptr;
- UINT dwBlockSz = 0;
- if (VerQueryValueW(ver.get(), L"\\", &pBlock, &dwBlockSz) != FALSE && dwBlockSz >= sizeof(VS_FIXEDFILEINFO))
- {
- VS_FIXEDFILEINFO *vinfo = static_cast<VS_FIXEDFILEINFO *>(pBlock);
- return int32_t(vinfo->dwProductVersionMS);
- }
- }
- }
- }
- }
- return int32_t(kWindowsUnknown);
- }();
-
- return winVersion;
-}
-
-// This allows us to pad driver version 'substrings' with 0s, this
-// effectively allows us to treat the version numbers as 'decimals'. This is
-// a little strange but this method seems to do the right thing for all
-// different vendor's driver strings. i.e. .98 will become 9800, which is
-// larger than .978 which would become 9780.
-void PadDriverDecimal(char *aString)
-{
- for (int i = 0; i < 4; i++)
- {
- if (!aString[i])
- {
- for (int c = i; c < 4; c++)
- {
- aString[c] = '0';
- }
- break;
- }
- }
- aString[4] = 0;
-}
-
-// All destination string storage needs to have at least 5 bytes available.
-bool SplitDriverVersion(const char *aSource, char *aAStr, char *aBStr, char *aCStr, char *aDStr)
-{
- // sscanf doesn't do what we want here to we parse this manually.
- int len = strlen(aSource);
- char *dest[4] = { aAStr, aBStr, aCStr, aDStr };
- unsigned destIdx = 0;
- unsigned destPos = 0;
-
- for (int i = 0; i < len; i++)
- {
- if (destIdx >= ArrayLength(dest))
- {
- // Invalid format found. Ensure we don't access dest beyond bounds.
- return false;
- }
-
- if (aSource[i] == '.')
- {
- dest[destIdx++][destPos] = 0;
- destPos = 0;
- continue;
- }
-
- if (destPos > 3)
- {
- // Ignore more than 4 chars. Ensure we never access dest[destIdx]
- // beyond its bounds.
- continue;
- }
-
- dest[destIdx][destPos++] = aSource[i];
- }
-
- // Add last terminator.
- dest[destIdx][destPos] = 0;
-
- if (destIdx != ArrayLength(dest) - 1)
- {
- return false;
- }
- return true;
-}
-
/* Other interesting places for info:
* IDXGIAdapter::GetDesc()
* IDirectDraw7::GetAvailableVidMem()
@@ -306,202 +155,28 @@ template<typename T> void appendIntegerWithPadding(OUString& rString, T value, s
#define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\"
}
-namespace wgl {
-
-bool ParseDriverVersion(const OUString& aVersion, uint64_t& rNumericVersion)
-{
- rNumericVersion = 0;
-
-#if defined(_WIN32)
- int a, b, c, d;
- char aStr[8], bStr[8], cStr[8], dStr[8];
- /* honestly, why do I even bother */
- OString aOVersion = OUStringToOString(aVersion, RTL_TEXTENCODING_UTF8);
- if (!SplitDriverVersion(aOVersion.getStr(), aStr, bStr, cStr, dStr))
- return false;
-
- PadDriverDecimal(bStr);
- PadDriverDecimal(cStr);
- PadDriverDecimal(dStr);
-
- a = atoi(aStr);
- b = atoi(bStr);
- c = atoi(cStr);
- d = atoi(dStr);
-
- if (a < 0 || a > 0xffff) return false;
- if (b < 0 || b > 0xffff) return false;
- if (c < 0 || c > 0xffff) return false;
- if (d < 0 || d > 0xffff) return false;
-
- rNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
- return true;
-#else
- return false;
-#endif
-}
-
-uint64_t DriverInfo::allDriverVersions = ~(uint64_t(0));
-
-DriverInfo::DriverInfo()
- : meOperatingSystem(wgl::DRIVER_OS_UNKNOWN),
- mnOperatingSystemVersion(0),
- maAdapterVendor(WinOpenGLDeviceInfo::GetDeviceVendor(VendorAll)),
- mbWhitelisted(false),
- meComparisonOp(DRIVER_COMPARISON_IGNORED),
- mnDriverVersion(0),
- mnDriverVersionMax(0)
-{}
-
-DriverInfo::DriverInfo(OperatingSystem os, const OUString& vendor,
- VersionComparisonOp op,
- uint64_t driverVersion,
- bool bWhitelisted,
- const char *suggestedVersion /* = nullptr */)
- : meOperatingSystem(os),
- mnOperatingSystemVersion(0),
- maAdapterVendor(vendor),
- mbWhitelisted(bWhitelisted),
- meComparisonOp(op),
- mnDriverVersion(driverVersion),
- mnDriverVersionMax(0)
-{
- if (suggestedVersion)
- maSuggestedVersion = OStringToOUString(OString(suggestedVersion), RTL_TEXTENCODING_UTF8);
-}
-
-DriverInfo::~DriverInfo()
-{
-}
-
-}
-
WinOpenGLDeviceInfo::WinOpenGLDeviceInfo():
mbHasDualGPU(false),
mbRDP(false)
{
GetData();
- FillBlacklist();
}
WinOpenGLDeviceInfo::~WinOpenGLDeviceInfo()
{
}
-namespace {
-
-struct compareIgnoreAsciiCase
+static OUString getBlacklistFile()
{
- explicit compareIgnoreAsciiCase(const OUString& rString)
- : maString(rString)
- {
- }
-
- bool operator()(const OUString& rCompare)
- {
- return maString.equalsIgnoreAsciiCase(rCompare);
- }
-
-private:
- OUString maString;
-};
-
-}
-
-bool WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(std::vector<wgl::DriverInfo>& aDeviceInfos,
- OUString const & sDriverVersion, OUString const & sAdapterVendorID,
- OUString const & sAdapterDeviceID, uint32_t nWindowsVersion)
-{
- uint64_t driverVersion;
- wgl::ParseDriverVersion(sDriverVersion, driverVersion);
-
- wgl::OperatingSystem eOS = WindowsVersionToOperatingSystem(nWindowsVersion);
- bool match = false;
- for (std::vector<wgl::DriverInfo>::size_type i = 0; i < aDeviceInfos.size(); i++)
- {
- if (aDeviceInfos[i].meOperatingSystem != wgl::DRIVER_OS_ALL &&
- aDeviceInfos[i].meOperatingSystem != eOS)
- {
- continue;
- }
-
- if (aDeviceInfos[i].mnOperatingSystemVersion && aDeviceInfos[i].mnOperatingSystemVersion != nWindowsVersion)
- {
- continue;
- }
-
- if (!aDeviceInfos[i].maAdapterVendor.equalsIgnoreAsciiCase(GetDeviceVendor(wgl::VendorAll)) &&
- !aDeviceInfos[i].maAdapterVendor.equalsIgnoreAsciiCase(sAdapterVendorID))
- {
- continue;
- }
-
- if (std::none_of(aDeviceInfos[i].maDevices.begin(), aDeviceInfos[i].maDevices.end(), compareIgnoreAsciiCase("all")) &&
- std::none_of(aDeviceInfos[i].maDevices.begin(), aDeviceInfos[i].maDevices.end(), compareIgnoreAsciiCase(sAdapterDeviceID)))
- {
- continue;
- }
-
- switch (aDeviceInfos[i].meComparisonOp)
- {
- case wgl::DRIVER_LESS_THAN:
- match = driverVersion < aDeviceInfos[i].mnDriverVersion;
- break;
- case wgl::DRIVER_LESS_THAN_OR_EQUAL:
- match = driverVersion <= aDeviceInfos[i].mnDriverVersion;
- break;
- case wgl::DRIVER_GREATER_THAN:
- match = driverVersion > aDeviceInfos[i].mnDriverVersion;
- break;
- case wgl::DRIVER_GREATER_THAN_OR_EQUAL:
- match = driverVersion >= aDeviceInfos[i].mnDriverVersion;
- break;
- case wgl::DRIVER_EQUAL:
- match = driverVersion == aDeviceInfos[i].mnDriverVersion;
- break;
- case wgl::DRIVER_NOT_EQUAL:
- match = driverVersion != aDeviceInfos[i].mnDriverVersion;
- break;
- case wgl::DRIVER_BETWEEN_EXCLUSIVE:
- match = driverVersion > aDeviceInfos[i].mnDriverVersion && driverVersion < aDeviceInfos[i].mnDriverVersionMax;
- break;
- case wgl::DRIVER_BETWEEN_INCLUSIVE:
- match = driverVersion >= aDeviceInfos[i].mnDriverVersion && driverVersion <= aDeviceInfos[i].mnDriverVersionMax;
- break;
- case wgl::DRIVER_BETWEEN_INCLUSIVE_START:
- match = driverVersion >= aDeviceInfos[i].mnDriverVersion && driverVersion < aDeviceInfos[i].mnDriverVersionMax;
- break;
- case wgl::DRIVER_COMPARISON_IGNORED:
- // We don't have a comparison op, so we match everything.
- match = true;
- break;
- default:
- SAL_WARN("vcl.opengl", "Bogus op in GfxDriverInfo");
- break;
- }
-
- if (match || aDeviceInfos[i].mnDriverVersion == wgl::DriverInfo::allDriverVersions)
- {
- // white listed drivers
- if (aDeviceInfos[i].mbWhitelisted)
- {
- SAL_WARN("vcl.opengl", "whitelisted driver");
- return false;
- }
-
- match = true;
- SAL_WARN("vcl.opengl", "use : " << aDeviceInfos[i].maSuggestedVersion);
- break;
- }
- }
+ OUString url("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER);
+ rtl::Bootstrap::expandMacros(url);
- SAL_INFO("vcl.opengl", (match ? "BLACKLISTED" : "not blacklisted"));
- return match;
+ return url + "/opengl/opengl_blacklist_windows.xml";
}
bool WinOpenGLDeviceInfo::FindBlocklistedDeviceInList()
{
- return FindBlocklistedDeviceInList(maDriverInfo, maDriverVersion, maAdapterVendorID, maAdapterDeviceID, mnWindowsVersion);
+ return DriverBlocklist::IsDeviceBlocked( getBlacklistFile(), maDriverVersion, maAdapterVendorID, maAdapterDeviceID);
}
namespace {
@@ -573,7 +248,6 @@ void WinOpenGLDeviceInfo::GetData()
DISPLAY_DEVICEW displayDevice;
displayDevice.cb = sizeof(displayDevice);
- mnWindowsVersion = WindowsOSVersion();
int deviceIndex = 0;
while (EnumDisplayDevicesW(nullptr, deviceIndex, &displayDevice, 0))
@@ -587,8 +261,8 @@ void WinOpenGLDeviceInfo::GetData()
// make sure the string is null terminated
// (using the term "null" here to mean a zero UTF-16 unit)
- if (wcsnlen(displayDevice.DeviceKey, ArrayLength(displayDevice.DeviceKey))
- == ArrayLength(displayDevice.DeviceKey))
+ if (wcsnlen(displayDevice.DeviceKey, SAL_N_ELEMENTS(displayDevice.DeviceKey))
+ == SAL_N_ELEMENTS(displayDevice.DeviceKey))
{
// we did not find a null
SAL_WARN("vcl.opengl", "string not null terminated");
@@ -598,14 +272,14 @@ void WinOpenGLDeviceInfo::GetData()
/* DeviceKey is "reserved" according to MSDN so we'll be careful with it */
/* check that DeviceKey begins with DEVICE_KEY_PREFIX */
/* some systems have a DeviceKey starting with \REGISTRY\Machine\ so we need to compare case insensitively */
- if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, ArrayLength(DEVICE_KEY_PREFIX)-1) != 0)
+ if (_wcsnicmp(displayDevice.DeviceKey, DEVICE_KEY_PREFIX, SAL_N_ELEMENTS(DEVICE_KEY_PREFIX)-1) != 0)
{
SAL_WARN("vcl.opengl", "incorrect DeviceKey");
return;
}
// chop off DEVICE_KEY_PREFIX
- maDeviceKey = o3tl::toU(displayDevice.DeviceKey) + ArrayLength(DEVICE_KEY_PREFIX)-1;
+ maDeviceKey = o3tl::toU(displayDevice.DeviceKey) + SAL_N_ELEMENTS(DEVICE_KEY_PREFIX)-1;
maDeviceID = o3tl::toU(displayDevice.DeviceID);
maDeviceString = o3tl::toU(displayDevice.DeviceString);
@@ -816,69 +490,4 @@ void WinOpenGLDeviceInfo::GetData()
}
}
-OUString WinOpenGLDeviceInfo::GetDeviceVendor(wgl::DeviceVendor id)
-{
- assert(id >= 0 && id < wgl::DeviceVendorMax);
-
- if (mpDeviceVendors[id])
- return *mpDeviceVendors[id];
-
- mpDeviceVendors[id] = new OUString();
-
- switch (id)
- {
- case wgl::VendorAll:
- *mpDeviceVendors[id] = "";
- break;
- case wgl::VendorIntel:
- *mpDeviceVendors[id] = "0x8086";
- break;
- case wgl::VendorNVIDIA:
- *mpDeviceVendors[id] = "0x10de";
- break;
- case wgl::VendorAMD:
- *mpDeviceVendors[id] = "0x1022";
- break;
- case wgl::VendorATI:
- *mpDeviceVendors[id] = "0x1002";
- break;
- case wgl::VendorMicrosoft:
- *mpDeviceVendors[id] = "0x1414";
- break;
- case wgl::DeviceVendorMax: // Suppress a warning.
- break;
- }
-
- return *mpDeviceVendors[id];
-}
-
-namespace {
-
-
-OUString getBlacklistFile()
-{
- OUString url("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER);
- rtl::Bootstrap::expandMacros(url);
-
- return url + "/opengl/opengl_blacklist_windows.xml";
-}
-
-
-}
-
-void WinOpenGLDeviceInfo::FillBlacklist()
-{
- OUString aURL = getBlacklistFile();
- WinBlocklistParser aParser(aURL, maDriverInfo);
- try {
- aParser.parse();
- }
- catch (...)
- {
- SAL_WARN("vcl.opengl", "error parsing blacklist");
- maDriverInfo.clear();
- }
-}
-
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/opengl/win/blocklist_parser.cxx b/vcl/opengl/win/blocklist_parser.cxx
deleted file mode 100644
index 79e49f540028..000000000000
--- a/vcl/opengl/win/blocklist_parser.cxx
+++ /dev/null
@@ -1,351 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- */
-
-#include <opengl/win/blocklist_parser.hxx>
-
-#include <sal/log.hxx>
-
-WinBlocklistParser::WinBlocklistParser(const OUString& rURL,
- std::vector<wgl::DriverInfo>& rDriverList)
- : meBlockType(BlockType::UNKNOWN)
- , mrDriverList(rDriverList)
- , maURL(rURL)
-{
-}
-
-void WinBlocklistParser::parse()
-{
- xmlreader::XmlReader aReader(maURL);
- handleContent(aReader);
-}
-
-namespace {
-
-wgl::OperatingSystem getOperatingSystem(const OString& rString)
-{
- if (rString == "all")
- {
- return wgl::DRIVER_OS_ALL;
- }
- else if (rString == "7")
- {
- return wgl::DRIVER_OS_WINDOWS_7;
- }
- else if (rString == "8")
- {
- return wgl::DRIVER_OS_WINDOWS_8;
- }
- else if (rString == "8_1")
- {
- return wgl::DRIVER_OS_WINDOWS_8_1;
- }
- else if (rString == "10")
- {
- return wgl::DRIVER_OS_WINDOWS_10;
- }
-
- return wgl::DRIVER_OS_UNKNOWN;
-}
-
-wgl::VersionComparisonOp getComparison(const OString& rString)
-{
- if (rString == "less")
- {
- return wgl::DRIVER_LESS_THAN;
- }
- else if (rString == "less_equal")
- {
- return wgl::DRIVER_LESS_THAN_OR_EQUAL;
- }
- else if (rString == "greater")
- {
- return wgl::DRIVER_GREATER_THAN;
- }
- else if (rString == "greater_equal")
- {
- return wgl::DRIVER_GREATER_THAN_OR_EQUAL;
- }
- else if (rString == "equal")
- {
- return wgl::DRIVER_EQUAL;
- }
- else if (rString == "not_equal")
- {
- return wgl::DRIVER_NOT_EQUAL;
- }
- else if (rString == "between_exclusive")
- {
- return wgl::DRIVER_BETWEEN_EXCLUSIVE;
- }
- else if (rString == "between_inclusive")
- {
- return wgl::DRIVER_BETWEEN_INCLUSIVE;
- }
- else if (rString == "between_inclusive_start")
- {
- return wgl::DRIVER_BETWEEN_INCLUSIVE_START;
- }
-
- throw InvalidFileException();
-}
-
-OUString getVendor(const OString& rString)
-{
- if (rString == "all")
- {
- return "";
- }
- else if (rString == "intel")
- {
- return "0x8086";
- }
- else if (rString == "nvidia")
- {
- return "0x10de";
- }
- else if (rString == "amd")
- {
- return "0x1022";
- }
- else if (rString == "ati")
- {
- return "0x1002";
- }
- else if (rString == "microsoft")
- {
- return "0x1414";
- }
- else
- {
- // Allow having simply the hex number as such there, too. After all, it's hex numbers that
- // are output to opengl_device.log.
- return OStringToOUString(rString, RTL_TEXTENCODING_UTF8);
- }
-}
-
-uint64_t getVersion(const OString& rString)
-{
- OUString aString = OStringToOUString(rString, RTL_TEXTENCODING_UTF8);
- uint64_t nVersion;
- bool bResult = wgl::ParseDriverVersion(aString, nVersion);
-
- if (!bResult)
- {
- throw InvalidFileException();
- }
-
- return nVersion;
-}
-
-void handleDevices(wgl::DriverInfo& rDriver, xmlreader::XmlReader& rReader)
-{
- int nLevel = 1;
- bool bInMsg = false;
-
- while(true)
- {
- xmlreader::Span name;
- int nsId;
-
- xmlreader::XmlReader::Result res = rReader.nextItem(
- xmlreader::XmlReader::Text::Normalized, &name, &nsId);
-
- if (res == xmlreader::XmlReader::Result::Begin)
- {
- ++nLevel;
- if (nLevel > 2)
- throw InvalidFileException();
-
- if (name == "msg")
- {
- bInMsg = true;
- }
- else if (name == "device")
- {
- int nsIdDeveice;
- while (rReader.nextAttribute(&nsIdDeveice, &name))
- {
- if (name == "id")
- {
- name = rReader.getAttributeValue(false);
- OString aDeviceId(name.begin, name.length);
- rDriver.maDevices.push_back(OStringToOUString(aDeviceId, RTL_TEXTENCODING_UTF8));
- }
- }
- }
- else
- throw InvalidFileException();
- }
- else if (res == xmlreader::XmlReader::Result::End)
- {
- --nLevel;
- bInMsg = false;
- if (!nLevel)
- break;
- }
- else if (res == xmlreader::XmlReader::Result::Text)
- {
- if (bInMsg)
- {
- OString sMsg(name.begin, name.length);
- rDriver.maMsg = OStringToOUString(sMsg, RTL_TEXTENCODING_UTF8);
- }
- }
- }
-}
-
-}
-
-void WinBlocklistParser::handleEntry(wgl::DriverInfo& rDriver, xmlreader::XmlReader& rReader)
-{
- if (meBlockType == BlockType::WHITELIST)
- {
- rDriver.mbWhitelisted = true;
- }
- else if (meBlockType == BlockType::BLACKLIST)
- {
- rDriver.mbWhitelisted = false;
- }
- else if (meBlockType == BlockType::UNKNOWN)
- {
- throw InvalidFileException();
- }
-
- xmlreader::Span name;
- int nsId;
-
- while (rReader.nextAttribute(&nsId, &name))
- {
- if (name == "os")
- {
- name = rReader.getAttributeValue(false);
- OString sOS(name.begin, name.length);
- rDriver.meOperatingSystem = getOperatingSystem(sOS);
- }
- else if (name == "vendor")
- {
- name = rReader.getAttributeValue(false);
- OString sVendor(name.begin, name.length);
- rDriver.maAdapterVendor = getVendor(sVendor);
- }
- else if (name == "compare")
- {
- name = rReader.getAttributeValue(false);
- OString sCompare(name.begin, name.length);
- rDriver.meComparisonOp = getComparison(sCompare);
- }
- else if (name == "version")
- {
- name = rReader.getAttributeValue(false);
- OString sVersion(name.begin, name.length);
- rDriver.mnDriverVersion = getVersion(sVersion);
- }
- else if (name == "minVersion")
- {
- name = rReader.getAttributeValue(false);
- OString sMinVersion(name.begin, name.length);
- rDriver.mnDriverVersion = getVersion(sMinVersion);
- }
- else if (name == "maxVersion")
- {
- name = rReader.getAttributeValue(false);
- OString sMaxVersion(name.begin, name.length);
- rDriver.mnDriverVersionMax = getVersion(sMaxVersion);
- }
- else
- {
- OString aAttrName(name.begin, name.length);
- SAL_WARN("vcl.opengl", "unsupported attribute: " << aAttrName);
- }
- }
-
- handleDevices(rDriver, rReader);
-}
-
-void WinBlocklistParser::handleList(xmlreader::XmlReader& rReader)
-{
- xmlreader::Span name;
- int nsId;
-
- while (true)
- {
- xmlreader::XmlReader::Result res = rReader.nextItem(
- xmlreader::XmlReader::Text::NONE, &name, &nsId);
-
- if (res == xmlreader::XmlReader::Result::Begin)
- {
- if (name == "entry")
- {
- wgl::DriverInfo aDriver;
- handleEntry(aDriver, rReader);
- mrDriverList.push_back(aDriver);
- }
- else if (name == "entryRange")
- {
- wgl::DriverInfo aDriver;
- handleEntry(aDriver, rReader);
- mrDriverList.push_back(aDriver);
- }
- else
- {
- throw InvalidFileException();
- }
- }
- else if (res == xmlreader::XmlReader::Result::End)
- {
- break;
- }
- }
-}
-
-void WinBlocklistParser::handleContent(xmlreader::XmlReader& rReader)
-{
- while (true)
- {
- xmlreader::Span name;
- int nsId;
-
- xmlreader::XmlReader::Result res = rReader.nextItem(
- xmlreader::XmlReader::Text::NONE, &name, &nsId);
-
- if (res == xmlreader::XmlReader::Result::Begin)
- {
- if (name == "whitelist")
- {
- meBlockType = BlockType::WHITELIST;
- handleList(rReader);
- }
- else if (name == "blacklist")
- {
- meBlockType = BlockType::BLACKLIST;
- handleList(rReader);
- }
- else if (name == "root")
- {
- }
- else
- {
- throw InvalidFileException();
- }
- }
- else if (res == xmlreader::XmlReader::Result::End)
- {
- if (name == "whitelist" || name == "blacklist")
- {
- meBlockType = BlockType::UNKNOWN;
- }
- }
- else if (res == xmlreader::XmlReader::Result::Done)
- {
- break;
- }
- }
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/qa/cppunit/blocklistparsertest.cxx b/vcl/qa/cppunit/blocklistparsertest.cxx
index 7d99e87f3750..1a22d61e3577 100644
--- a/vcl/qa/cppunit/blocklistparsertest.cxx
+++ b/vcl/qa/cppunit/blocklistparsertest.cxx
@@ -16,7 +16,9 @@
#include <unotest/bootstrapfixturebase.hxx>
-#include <opengl/win/blocklist_parser.hxx>
+#include <driverblocklist.hxx>
+
+using namespace DriverBlocklist;
namespace
{
@@ -34,9 +36,9 @@ class BlocklistParserTest : public test::BootstrapFixtureBase
void BlocklistParserTest::testParse()
{
- std::vector<wgl::DriverInfo> aDriveInfos;
+ std::vector<DriverInfo> aDriveInfos;
- WinBlocklistParser aBlocklistParser(m_directories.getURLFromSrc("vcl/qa/cppunit/") + "test_blocklist_parse.xml", aDriveInfos);
+ Parser aBlocklistParser(m_directories.getURLFromSrc("vcl/qa/cppunit/") + "test_blocklist_parse.xml", aDriveInfos);
aBlocklistParser.parse();
size_t const n = aDriveInfos.size();
@@ -46,91 +48,87 @@ void BlocklistParserTest::testParse()
for (bool bIsWhitelisted : {true, false})
{
- wgl::DriverInfo& aDriveInfo = aDriveInfos[i++];
+ DriverInfo& aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
- CPPUNIT_ASSERT_EQUAL(WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorAll), aDriveInfo.maAdapterVendor); // "all"
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_LESS_THAN, aDriveInfo.meComparisonOp);
- CPPUNIT_ASSERT_EQUAL(wgl::V(10,20,30,40), aDriveInfo.mnDriverVersion);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor); // "all"
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_LESS_THAN, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(V(10,20,30,40), aDriveInfo.mnDriverVersion);
aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
- CPPUNIT_ASSERT_EQUAL(WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorNVIDIA), aDriveInfo.maAdapterVendor);
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_EQUAL, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorNVIDIA), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_EQUAL, aDriveInfo.meComparisonOp);
aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
- CPPUNIT_ASSERT_EQUAL(WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorMicrosoft), aDriveInfo.maAdapterVendor);
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_NOT_EQUAL, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorMicrosoft), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_NOT_EQUAL, aDriveInfo.meComparisonOp);
aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
CPPUNIT_ASSERT_EQUAL(OUString("0xcafe"), aDriveInfo.maAdapterVendor);
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_NOT_EQUAL, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_NOT_EQUAL, aDriveInfo.meComparisonOp);
aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
- CPPUNIT_ASSERT_EQUAL(WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorAll), aDriveInfo.maAdapterVendor);
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_BETWEEN_EXCLUSIVE, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_BETWEEN_EXCLUSIVE, aDriveInfo.meComparisonOp);
aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
- CPPUNIT_ASSERT_EQUAL(WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorAll), aDriveInfo.maAdapterVendor);
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_BETWEEN_INCLUSIVE, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_BETWEEN_INCLUSIVE, aDriveInfo.meComparisonOp);
aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
- CPPUNIT_ASSERT_EQUAL(WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorAll), aDriveInfo.maAdapterVendor);
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_BETWEEN_INCLUSIVE_START, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_BETWEEN_INCLUSIVE_START, aDriveInfo.meComparisonOp);
aDriveInfo = aDriveInfos[i++];
CPPUNIT_ASSERT_EQUAL(bIsWhitelisted, aDriveInfo.mbWhitelisted);
- CPPUNIT_ASSERT_EQUAL(WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorAll), aDriveInfo.maAdapterVendor);
- CPPUNIT_ASSERT_EQUAL(wgl::VersionComparisonOp::DRIVER_COMPARISON_IGNORED, aDriveInfo.meComparisonOp);
+ CPPUNIT_ASSERT_EQUAL(GetVendorId(VendorAll), aDriveInfo.maAdapterVendor);
+ CPPUNIT_ASSERT_EQUAL(VersionComparisonOp::DRIVER_COMPARISON_IGNORED, aDriveInfo.meComparisonOp);
}
}
void BlocklistParserTest::testEvaluate()
{
- std::vector<wgl::DriverInfo> aDriveInfos;
+ std::vector<DriverInfo> aDriveInfos;
- WinBlocklistParser aBlocklistParser(m_directories.getURLFromSrc("vcl/qa/cppunit/") + "test_blocklist_evaluate.xml", aDriveInfos);
+ Parser aBlocklistParser(m_directories.getURLFromSrc("vcl/qa/cppunit/") + "test_blocklist_evaluate.xml", aDriveInfos);
aBlocklistParser.parse();
- OUString vendorAMD = WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorAMD);
- OUString vendorNVIDIA = WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorNVIDIA);
- OUString vendorIntel = WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorIntel);
- OUString vendorMicrosoft = WinOpenGLDeviceInfo::GetDeviceVendor(wgl::VendorMicrosoft);
-
- uint32_t const osWindows7 = 0x00060001;
- uint32_t const osWindows8 = 0x00060002;
- uint32_t const osWindows10 = 0x000A0000;
+ OUString vendorAMD = GetVendorId(VendorAMD);
+ OUString vendorNVIDIA = GetVendorId(VendorNVIDIA);
+ OUString vendorIntel = GetVendorId(VendorIntel);
+ OUString vendorMicrosoft = GetVendorId(VendorMicrosoft);
// Check OS
- CPPUNIT_ASSERT_EQUAL(false, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.40", vendorNVIDIA, "all", osWindows7));
- CPPUNIT_ASSERT_EQUAL(false, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.40", vendorNVIDIA, "all", osWindows8));
- CPPUNIT_ASSERT_EQUAL(false, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.40", vendorNVIDIA, "all", osWindows10));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.40", vendorNVIDIA, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.40", vendorNVIDIA, "all", DRIVER_OS_WINDOWS_8));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.40", vendorNVIDIA, "all", DRIVER_OS_WINDOWS_10));
// Check Vendors
- CPPUNIT_ASSERT_EQUAL(true, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.40", vendorMicrosoft, "all", osWindows7));
- CPPUNIT_ASSERT_EQUAL(true, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.40", vendorMicrosoft, "all", osWindows10));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.40", vendorMicrosoft, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.40", vendorMicrosoft, "all", DRIVER_OS_WINDOWS_10));
// Check Versions
- CPPUNIT_ASSERT_EQUAL(true, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.39", vendorAMD, "all", osWindows7));
- CPPUNIT_ASSERT_EQUAL(false, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.40", vendorAMD, "all", osWindows7));
- CPPUNIT_ASSERT_EQUAL(false, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "10.20.30.41", vendorAMD, "all", osWindows7));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.39", vendorAMD, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.40", vendorAMD, "all", DRIVER_OS_WINDOWS_7));
+ CPPUNIT_ASSERT_EQUAL(false, FindBlocklistedDeviceInList(
+ aDriveInfos, "10.20.30.41", vendorAMD, "all", DRIVER_OS_WINDOWS_7));
// Check
- CPPUNIT_ASSERT_EQUAL(true, WinOpenGLDeviceInfo::FindBlocklistedDeviceInList(
- aDriveInfos, "9.17.10.4229", vendorIntel, "all", osWindows7));
+ CPPUNIT_ASSERT_EQUAL(true, FindBlocklistedDeviceInList(
+ aDriveInfos, "9.17.10.4229", vendorIntel, "all", DRIVER_OS_WINDOWS_7));
}
diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx
index 0404a52f98cc..c305c5275ea5 100644
--- a/vcl/skia/SkiaHelper.cxx
+++ b/vcl/skia/SkiaHelper.cxx
@@ -9,13 +9,6 @@
#include <vcl/skia/SkiaHelper.hxx>
-#include <vcl/svapp.hxx>
-#include <desktop/crashreport.hxx>
-#include <officecfg/Office/Common.hxx>
-#include <watchdog.hxx>
-#include <skia/zone.hxx>
-#include <sal/log.hxx>
-
#if !HAVE_FEATURE_SKIA
namespace SkiaHelper
@@ -26,7 +19,16 @@ bool isVCLSkiaEnabled() { return false; }
#else
+#include <rtl/bootstrap.hxx>
+#include <vcl/svapp.hxx>
+#include <desktop/crashreport.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <watchdog.hxx>
+#include <skia/zone.hxx>
+#include <sal/log.hxx>
+#include <driverblocklist.hxx>
#include <skia/utils.hxx>
+#include <config_folders.h>
#include <SkSurface.h>
@@ -36,20 +38,31 @@ bool isVCLSkiaEnabled() { return false; }
namespace SkiaHelper
{
+static OUString getBlacklistFile()
+{
+ OUString url("$BRAND_BASE_DIR/" LIBO_SHARE_FOLDER);
+ rtl::Bootstrap::expandMacros(url);
+
+ return url + "/skia/skia_blacklist_vulkan.xml";
+}
+
static bool isVulkanBlacklisted(const VkPhysicalDeviceProperties& props)
{
static const char* const types[]
= { "other", "integrated", "discrete", "virtual", "cpu", "??" }; // VkPhysicalDeviceType
+ OUString driverVersion = OUString::number(props.driverVersion >> 22) + "."
+ + OUString::number((props.driverVersion >> 12) & 0x3ff) + "."
+ + OUString::number(props.driverVersion & 0xfff);
+ OUString vendorId = "0x" + OUString::number(props.vendorID, 16);
+ OUString deviceId = "0x" + OUString::number(props.deviceID, 16);
SAL_INFO("vcl.skia",
"Vulkan API version: "
<< (props.apiVersion >> 22) << "." << ((props.apiVersion >> 12) & 0x3ff) << "."
- << (props.apiVersion & 0xfff) << ", driver version: "
- << (props.driverVersion >> 22) << "." << ((props.driverVersion >> 12) & 0x3ff)
- << "." << (props.driverVersion & 0xfff) << std::hex << ", vendor: 0x"
- << props.vendorID << ", device: 0x" << props.deviceID << std::dec
- << ", type: " << types[std::min<unsigned>(props.deviceType, SAL_N_ELEMENTS(types))]
+ << (props.apiVersion & 0xfff) << ", driver version: " << driverVersion
+ << ", vendor: " << vendorId << ", device: " << deviceId << ", type: "
+ << types[std::min<unsigned>(props.deviceType, SAL_N_ELEMENTS(types) - 1)]
<< ", name: " << props.deviceName);
- return false;
+ return DriverBlocklist::IsDeviceBlocked(getBlacklistFile(), driverVersion, vendorId, deviceId);
}
static void checkDeviceBlacklisted()
diff --git a/vcl/skia/skia_blacklist_vulkan.xml b/vcl/skia/skia_blacklist_vulkan.xml
new file mode 100644
index 000000000000..2c7714a38f8a
--- /dev/null
+++ b/vcl/skia/skia_blacklist_vulkan.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+* This file is part of the LibreOffice project.
+*
+* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this
+* file, You can obtain one at http://mozilla.org/MPL/2.0/.
+-->
+
+<!--
+ entry attributes:
+ os - "all", "7", "8", "8_1", "10", "linux"
+ vendor - "all", "intel", "ati", "amd", "nvidia", "microsoft"
+ compare - "less", "less_equal", "greater", "greater_equal", "equal", "not_equal", "between_exclusive", "between_inclusive", "between_inclusive_start"
+ version
+ minVersion
+ maxVersion
+-->
+
+<root>
+ <whitelist>
+ </whitelist>
+ <blacklist>
+<!-- example:
+ <entry os="all" vendor="ati" compare="equal" version="2.0.106">
+ <device id="all"/>
+ </entry>
+-->
+ </blacklist>
+</root>
diff --git a/vcl/source/helper/driverblocklist.cxx b/vcl/source/helper/driverblocklist.cxx
new file mode 100644
index 000000000000..a63fdc00cd30
--- /dev/null
+++ b/vcl/source/helper/driverblocklist.cxx
@@ -0,0 +1,711 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#include <driverblocklist.hxx>
+
+#include <algorithm>
+
+#include <sal/log.hxx>
+
+#ifdef _WIN32
+#if !defined WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#endif
+
+namespace DriverBlocklist
+{
+static OperatingSystem getOperatingSystem(const OString& rString)
+{
+ if (rString == "all")
+ return DRIVER_OS_ALL;
+ else if (rString == "7")
+ return DRIVER_OS_WINDOWS_7;
+ else if (rString == "8")
+ return DRIVER_OS_WINDOWS_8;
+ else if (rString == "8_1")
+ return DRIVER_OS_WINDOWS_8_1;
+ else if (rString == "10")
+ return DRIVER_OS_WINDOWS_10;
+ else if (rString == "linux")
+ return DRIVER_OS_LINUX;
+ else if (rString == "osx_10_5")
+ return DRIVER_OS_OSX_10_5;
+ else if (rString == "osx_10_6")
+ return DRIVER_OS_OSX_10_6;
+ else if (rString == "osx_10_7")
+ return DRIVER_OS_OSX_10_7;
+ else if (rString == "osx_10_8")
+ return DRIVER_OS_OSX_10_8;
+ else if (rString == "android")
+ return DRIVER_OS_ANDROID;
+ return DRIVER_OS_UNKNOWN;
+}
+
+static VersionComparisonOp getComparison(const OString& rString)
+{
+ if (rString == "less")
+ {
+ return DRIVER_LESS_THAN;
+ }
+ else if (rString == "less_equal")
+ {
+ return DRIVER_LESS_THAN_OR_EQUAL;
+ }
+ else if (rString == "greater")
+ {
+ return DRIVER_GREATER_THAN;
+ }
+ else if (rString == "greater_equal")
+ {
+ return DRIVER_GREATER_THAN_OR_EQUAL;
+ }
+ else if (rString == "equal")
+ {
+ return DRIVER_EQUAL;
+ }
+ else if (rString == "not_equal")
+ {
+ return DRIVER_NOT_EQUAL;
+ }
+ else if (rString == "between_exclusive")
+ {
+ return DRIVER_BETWEEN_EXCLUSIVE;
+ }
+ else if (rString == "between_inclusive")
+ {
+ return DRIVER_BETWEEN_INCLUSIVE;
+ }
+ else if (rString == "between_inclusive_start")
+ {
+ return DRIVER_BETWEEN_INCLUSIVE_START;
+ }
+
+ throw InvalidFileException();
+}
+
+static OUString GetVendorId(const OString& rString)
+{
+ if (rString == "all")
+ {
+ return "";
+ }
+ else if (rString == "intel")
+ {
+ return "0x8086";
+ }
+ else if (rString == "nvidia")
+ {
+ return "0x10de";
+ }
+ else if (rString == "amd")
+ {
+ return "0x1022";
+ }
+ else if (rString == "ati")
+ {
+ return "0x1002";
+ }
+ else if (rString == "microsoft")
+ {
+ return "0x1414";
+ }
+ else
+ {
+ // Allow having simply the hex number as such there, too.
+ return OStringToOUString(rString, RTL_TEXTENCODING_UTF8);
+ }
+}
+
+OUString GetVendorId(DeviceVendor id)
+{
+ assert(id >= 0 && id < DeviceVendorMax);
+
+ switch (id)
+ {
+ case VendorAll:
+ return "";
+ case VendorIntel:
+ return "0x8086";
+ case VendorNVIDIA:
+ return "0x10de";
+ case VendorAMD:
+ return "0x1022";
+ case VendorATI:
+ return "0x1002";
+ case VendorMicrosoft:
+ return "0x1414";
+ }
+ abort();
+}
+
+Parser::Parser(const OUString& rURL, std::vector<DriverInfo>& rDriverList)
+ : meBlockType(BlockType::UNKNOWN)
+ , mrDriverList(rDriverList)
+ , maURL(rURL)
+{
+}
+
+bool Parser::parse()
+{
+ try
+ {
+ xmlreader::XmlReader aReader(maURL);
+ handleContent(aReader);
+ }
+ catch (...)
+ {
+ mrDriverList.clear();
+ return false;
+ }
+ return true;
+}
+
+// This allows us to pad driver version 'substrings' with 0s, this
+// effectively allows us to treat the version numbers as 'decimals'. This is
+// a little strange but this method seems to do the right thing for all
+// different vendor's driver strings. i.e. .98 will become 9800, which is
+// larger than .978 which would become 9780.
+static void PadDriverDecimal(char* aString)
+{
+ for (int i = 0; i < 4; i++)
+ {
+ if (!aString[i])
+ {
+ for (int c = i; c < 4; c++)
+ {
+ aString[c] = '0';
+ }
+ break;
+ }
+ }
+ aString[4] = 0;
+}
+
+// All destination string storage needs to have at least 5 bytes available.
+static bool SplitDriverVersion(const char* aSource, char* aAStr, char* aBStr, char* aCStr,
+ char* aDStr)
+{
+ // sscanf doesn't do what we want here to we parse this manually.
+ int len = strlen(aSource);
+ char* dest[4] = { aAStr, aBStr, aCStr, aDStr };
+ unsigned destIdx = 0;
+ unsigned destPos = 0;
+
+ for (int i = 0; i < len; i++)
+ {
+ if (destIdx >= SAL_N_ELEMENTS(dest))
+ {
+ // Invalid format found. Ensure we don't access dest beyond bounds.
+ return false;
+ }
+
+ if (aSource[i] == '.')
+ {
+ dest[destIdx++][destPos] = 0;
+ destPos = 0;
+ continue;
+ }
+
+ if (destPos > 3)
+ {
+ // Ignore more than 4 chars. Ensure we never access dest[destIdx]
+ // beyond its bounds.
+ continue;
+ }
+
+ dest[destIdx][destPos++] = aSource[i];
+ }
+
+ // Add last terminator.
+ dest[destIdx][destPos] = 0;
+
+ // Vulkan version numbers have only 3 fields.
+ if (destIdx == SAL_N_ELEMENTS(dest) - 2)
+ dest[destIdx++][0] = '\0';
+ if (destIdx != SAL_N_ELEMENTS(dest) - 1)
+ {
+ return false;
+ }
+ return true;
+}
+
+static bool ParseDriverVersion(const OUString& aVersion, uint64_t& rNumericVersion)
+{
+ rNumericVersion = 0;
+
+ int a, b, c, d;
+ char aStr[8], bStr[8], cStr[8], dStr[8];
+ /* honestly, why do I even bother */
+ OString aOVersion = OUStringToOString(aVersion, RTL_TEXTENCODING_UTF8);
+ if (!SplitDriverVersion(aOVersion.getStr(), aStr, bStr, cStr, dStr))
+ return false;
+
+ PadDriverDecimal(bStr);
+ PadDriverDecimal(cStr);
+ PadDriverDecimal(dStr);
+
+ a = atoi(aStr);
+ b = atoi(bStr);
+ c = atoi(cStr);
+ d = atoi(dStr);
+
+ if (a < 0 || a > 0xffff)
+ return false;
+ if (b < 0 || b > 0xffff)
+ return false;
+ if (c < 0 || c > 0xffff)
+ return false;
+ if (d < 0 || d > 0xffff)
+ return false;
+
+ rNumericVersion = GFX_DRIVER_VERSION(a, b, c, d);
+ return true;
+}
+
+static uint64_t getVersion(const OString& rString)
+{
+ OUString aString = OStringToOUString(rString, RTL_TEXTENCODING_UTF8);
+ uint64_t nVersion;
+ bool bResult = ParseDriverVersion(aString, nVersion);
+
+ if (!bResult)
+ {
+ throw InvalidFileException();
+ }
+
+ return nVersion;
+}
+
+void Parser::handleDevices(DriverInfo& rDriver, xmlreader::XmlReader& rReader)
+{
+ int nLevel = 1;
+ bool bInMsg = false;
+
+ while (true)
+ {
+ xmlreader::Span name;
+ int nsId;
+
+ xmlreader::XmlReader::Result res
+ = rReader.nextItem(xmlreader::XmlReader::Text::Normalized, &name, &nsId);
+
+ if (res == xmlreader::XmlReader::Result::Begin)
+ {
+ ++nLevel;
+ if (nLevel > 2)
+ throw InvalidFileException();
+
+ if (name == "msg")
+ {
+ bInMsg = true;
+ }
+ else if (name == "device")
+ {
+ int nsIdDeveice;
+ while (rReader.nextAttribute(&nsIdDeveice, &name))
+ {
+ if (name == "id")
+ {
+ name = rReader.getAttributeValue(false);
+ OString aDeviceId(name.begin, name.length);
+ rDriver.maDevices.push_back(
+ OStringToOUString(aDeviceId, RTL_TEXTENCODING_UTF8));
+ }
+ }
+ }
+ else
+ throw InvalidFileException();
+ }
+ else if (res == xmlreader::XmlReader::Result::End)
+ {
+ --nLevel;
+ bInMsg = false;
+ if (!nLevel)
+ break;
+ }
+ else if (res == xmlreader::XmlReader::Result::Text)
+ {
+ if (bInMsg)
+ {
+ OString sMsg(name.begin, name.length);
+ rDriver.maMsg = OStringToOUString(sMsg, RTL_TEXTENCODING_UTF8);
+ }
+ }
+ }
+}
+
+void Parser::handleEntry(DriverInfo& rDriver, xmlreader::XmlReader& rReader)
+{
+ if (meBlockType == BlockType::WHITELIST)
+ {
+ rDriver.mbWhitelisted = true;
+ }
+ else if (meBlockType == BlockType::BLACKLIST)
+ {
+ rDriver.mbWhitelisted = false;
+ }
+ else if (meBlockType == BlockType::UNKNOWN)
+ {
+ throw InvalidFileException();
+ }
+
+ xmlreader::Span name;
+ int nsId;
+
+ while (rReader.nextAttribute(&nsId, &name))
+ {
+ if (name == "os")
+ {
+ name = rReader.getAttributeValue(false);
+ OString sOS(name.begin, name.length);
+ rDriver.meOperatingSystem = getOperatingSystem(sOS);
+ }
+ else if (name == "vendor")
+ {
+ name = rReader.getAttributeValue(false);
+ OString sVendor(name.begin, name.length);
+ rDriver.maAdapterVendor = GetVendorId(sVendor);
+ }
+ else if (name == "compare")
+ {
+ name = rReader.getAttributeValue(false);
+ OString sCompare(name.begin, name.length);
+ rDriver.meComparisonOp = getComparison(sCompare);
+ }
+ else if (name == "version")
+ {
+ name = rReader.getAttributeValue(false);
+ OString sVersion(name.begin, name.length);
+ rDriver.mnDriverVersion = getVersion(sVersion);
+ }
+ else if (name == "minVersion")
+ {
+ name = rReader.getAttributeValue(false);
+ OString sMinVersion(name.begin, name.length);
+ rDriver.mnDriverVersion = getVersion(sMinVersion);
+ }
+ else if (name == "maxVersion")
+ {
+ name = rReader.getAttributeValue(false);
+ OString sMaxVersion(name.begin, name.length);
+ rDriver.mnDriverVersionMax = getVersion(sMaxVersion);
+ }
+ else
+ {
+ OString aAttrName(name.begin, name.length);
+ SAL_WARN("vcl.driver", "unsupported attribute: " << aAttrName);
+ }
+ }
+
+ handleDevices(rDriver, rReader);
+}
+
+void Parser::handleList(xmlreader::XmlReader& rReader)
+{
+ xmlreader::Span name;
+ int nsId;
+
+ while (true)
+ {
+ xmlreader::XmlReader::Result res
+ = rReader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
+
+ if (res == xmlreader::XmlReader::Result::Begin)
+ {
+ if (name == "entry")
+ {
+ DriverInfo aDriver;
+ handleEntry(aDriver, rReader);
+ mrDriverList.push_back(aDriver);
+ }
+ else if (name == "entryRange")
+ {
+ DriverInfo aDriver;
+ handleEntry(aDriver, rReader);
+ mrDriverList.push_back(aDriver);
+ }
+ else
+ {
+ throw InvalidFileException();
+ }
+ }
+ else if (res == xmlreader::XmlReader::Result::End)
+ {
+ break;
+ }
+ }
+}
+
+void Parser::handleContent(xmlreader::XmlReader& rReader)
+{
+ while (true)
+ {
+ xmlreader::Span name;
+ int nsId;
+
+ xmlreader::XmlReader::Result res
+ = rReader.nextItem(xmlreader::XmlReader::Text::NONE, &name, &nsId);
+
+ if (res == xmlreader::XmlReader::Result::Begin)
+ {
+ if (name == "whitelist")
+ {
+ meBlockType = BlockType::WHITELIST;
+ handleList(rReader);
+ }
+ else if (name == "blacklist")
+ {
+ meBlockType = BlockType::BLACKLIST;
+ handleList(rReader);
+ }
+ else if (name == "root")
+ {
+ }
+ else
+ {
+ throw InvalidFileException();
+ }
+ }
+ else if (res == xmlreader::XmlReader::Result::End)
+ {
+ if (name == "whitelist" || name == "blacklist")
+ {
+ meBlockType = BlockType::UNKNOWN;
+ }
+ }
+ else if (res == xmlreader::XmlReader::Result::Done)
+ {
+ break;
+ }
+ }
+}
+
+static OperatingSystem getOperatingSystem()
+{
+#ifdef _WIN32
+ // OS version in 16.16 major/minor form
+ // based on http://msdn.microsoft.com/en-us/library/ms724834(VS.85).aspx
+ switch (DriverBlocklist::GetWindowsVersion())
+ {
+ case 0x00060001:
+ return DRIVER_OS_WINDOWS_7;
+ case 0x00060002:
+ return DRIVER_OS_WINDOWS_8;
+ case 0x00060003:
+ return DRIVER_OS_WINDOWS_8_1;
+ case 0x000A0000: // Major 10 Minor 0
+ return DRIVER_OS_WINDOWS_10;
+ default:
+ return DRIVER_OS_UNKNOWN;
+ }
+#elif defined LINUX
+ return DRIVER_OS_LINUX;
+#else
+ return DRIVER_OS_UNKNOWN;
+#endif
+}
+
+namespace
+{
+struct compareIgnoreAsciiCase
+{
+ explicit compareIgnoreAsciiCase(const OUString& rString)
+ : maString(rString)
+ {
+ }
+
+ bool operator()(const OUString& rCompare) { return maString.equalsIgnoreAsciiCase(rCompare); }
+
+private:
+ OUString maString;
+};
+}
+
+const uint64_t allDriverVersions = ~(uint64_t(0));
+
+DriverInfo::DriverInfo()
+ : meOperatingSystem(DRIVER_OS_UNKNOWN)
+ , maAdapterVendor(GetVendorId(VendorAll))
+ , mbWhitelisted(false)
+ , meComparisonOp(DRIVER_COMPARISON_IGNORED)
+ , mnDriverVersion(0)
+ , mnDriverVersionMax(0)
+{
+}
+
+DriverInfo::DriverInfo(OperatingSystem os, const OUString& vendor, VersionComparisonOp op,
+ uint64_t driverVersion, bool bWhitelisted,
+ const char* suggestedVersion /* = nullptr */)
+ : meOperatingSystem(os)
+ , maAdapterVendor(vendor)
+ , mbWhitelisted(bWhitelisted)
+ , meComparisonOp(op)
+ , mnDriverVersion(driverVersion)
+ , mnDriverVersionMax(0)
+{
+ if (suggestedVersion)
+ maSuggestedVersion = OStringToOUString(OString(suggestedVersion), RTL_TEXTENCODING_UTF8);
+}
+
+bool FindBlocklistedDeviceInList(std::vector<DriverInfo>& aDeviceInfos,
+ OUString const& sDriverVersion, OUString const& sAdapterVendorID,
+ OUString const& sAdapterDeviceID, OperatingSystem system,
+ const OUString& blocklistURL)
+{
+ uint64_t driverVersion;
+ ParseDriverVersion(sDriverVersion, driverVersion);
+
+ bool match = false;
+ for (std::vector<DriverInfo>::size_type i = 0; i < aDeviceInfos.size(); i++)
+ {
+ if (aDeviceInfos[i].meOperatingSystem != DRIVER_OS_ALL
+ && aDeviceInfos[i].meOperatingSystem != system)
+ {
+ continue;
+ }
+
+ if (!aDeviceInfos[i].maAdapterVendor.equalsIgnoreAsciiCase(GetVendorId(VendorAll))
+ && !aDeviceInfos[i].maAdapterVendor.equalsIgnoreAsciiCase(sAdapterVendorID))
+ {
+ continue;
+ }
+
+ if (std::none_of(aDeviceInfos[i].maDevices.begin(), aDeviceInfos[i].maDevices.end(),
+ compareIgnoreAsciiCase("all"))
+ && std::none_of(aDeviceInfos[i].maDevices.begin(), aDeviceInfos[i].maDevices.end(),
+ compareIgnoreAsciiCase(sAdapterDeviceID)))
+ {
+ continue;
+ }
+
+ switch (aDeviceInfos[i].meComparisonOp)
+ {
+ case DRIVER_LESS_THAN:
+ match = driverVersion < aDeviceInfos[i].mnDriverVersion;
+ break;
+ case DRIVER_LESS_THAN_OR_EQUAL:
+ match = driverVersion <= aDeviceInfos[i].mnDriverVersion;
+ break;
+ case DRIVER_GREATER_THAN:
+ match = driverVersion > aDeviceInfos[i].mnDriverVersion;
+ break;
+ case DRIVER_GREATER_THAN_OR_EQUAL:
+ match = driverVersion >= aDeviceInfos[i].mnDriverVersion;
+ break;
+ case DRIVER_EQUAL:
+ match = driverVersion == aDeviceInfos[i].mnDriverVersion;
+ break;
+ case DRIVER_NOT_EQUAL:
+ match = driverVersion != aDeviceInfos[i].mnDriverVersion;
+ break;
+ case DRIVER_BETWEEN_EXCLUSIVE:
+ match = driverVersion > aDeviceInfos[i].mnDriverVersion
+ && driverVersion < aDeviceInfos[i].mnDriverVersionMax;
+ break;
+ case DRIVER_BETWEEN_INCLUSIVE:
+ match = driverVersion >= aDeviceInfos[i].mnDriverVersion
+ && driverVersion <= aDeviceInfos[i].mnDriverVersionMax;
+ break;
+ case DRIVER_BETWEEN_INCLUSIVE_START:
+ match = driverVersion >= aDeviceInfos[i].mnDriverVersion
+ && driverVersion < aDeviceInfos[i].mnDriverVersionMax;
+ break;
+ case DRIVER_COMPARISON_IGNORED:
+ // We don't have a comparison op, so we match everything.
+ match = true;
+ break;
+ default:
+ SAL_WARN("vcl.driver", "Bogus op in " << blocklistURL);
+ break;
+ }
+
+ if (match || aDeviceInfos[i].mnDriverVersion == allDriverVersions)
+ {
+ // white listed drivers
+ if (aDeviceInfos[i].mbWhitelisted)
+ {
+ SAL_INFO("vcl.driver", "whitelisted driver");
+ return false;
+ }
+
+ match = true;
+ if (!aDeviceInfos[i].maSuggestedVersion.isEmpty())
+ {
+ SAL_WARN("vcl.driver", "use : " << aDeviceInfos[i].maSuggestedVersion);
+ }
+ break;
+ }
+ }
+
+ SAL_INFO("vcl.driver", (match ? "blacklisted" : "not blacklisted") << " in " << blocklistURL);
+ return match;
+}
+
+bool IsDeviceBlocked(const OUString& blocklistURL, const OUString& driverVersion,
+ const OUString& vendorId, const OUString& deviceId)
+{
+ std::vector<DriverInfo> driverList;
+ Parser parser(blocklistURL, driverList);
+ if (!parser.parse())
+ {
+ SAL_WARN("vcl.driver", "error parsing blacklist " << blocklistURL);
+ return false;
+ }
+ return FindBlocklistedDeviceInList(driverList, driverVersion, vendorId, deviceId,
+ getOperatingSystem(), blocklistURL);
+}
+
+#ifdef _WIN32
+int32_t GetWindowsVersion()
+{
+ static int32_t winVersion = [&]() {
+ // GetVersion(Ex) and VersionHelpers (based on VerifyVersionInfo) API are
+ // subject to manifest-based behavior since Windows 8.1, so give wrong results.
+ // Another approach would be to use NetWkstaGetInfo, but that has some small
+ // reported delays (some milliseconds), and might get slower in domains with
+ // poor network connections.
+ // So go with a solution described at https://msdn.microsoft.com/en-us/library/ms724429
+ HINSTANCE hLibrary = LoadLibraryW(L"kernel32.dll");
+ if (hLibrary != nullptr)
+ {
+ wchar_t szPath[MAX_PATH];
+ DWORD dwCount = GetModuleFileNameW(hLibrary, szPath, SAL_N_ELEMENTS(szPath));
+ FreeLibrary(hLibrary);
+ if (dwCount != 0 && dwCount < SAL_N_ELEMENTS(szPath))
+ {
+ dwCount = GetFileVersionInfoSizeW(szPath, nullptr);
+ if (dwCount != 0)
+ {
+ std::unique_ptr<char[]> ver(new char[dwCount]);
+ if (GetFileVersionInfoW(szPath, 0, dwCount, ver.get()) != FALSE)
+ {
+ void* pBlock = nullptr;
+ UINT dwBlockSz = 0;
+ if (VerQueryValueW(ver.get(), L"\\", &pBlock, &dwBlockSz) != FALSE
+ && dwBlockSz >= sizeof(VS_FIXEDFILEINFO))
+ {
+ VS_FIXEDFILEINFO* vinfo = static_cast<VS_FIXEDFILEINFO*>(pBlock);
+ return int32_t(vinfo->dwProductVersionMS);
+ }
+ }
+ }
+ }
+ }
+ return 0;
+ }();
+
+ return winVersion;
+}
+#endif
+
+} // namespace
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/opengl/OpenGLHelper.cxx b/vcl/source/opengl/OpenGLHelper.cxx
index 081bf240cc8b..ece8e9d6c440 100644
--- a/vcl/source/opengl/OpenGLHelper.cxx
+++ b/vcl/source/opengl/OpenGLHelper.cxx
@@ -209,7 +209,7 @@ namespace
return OUStringToOString(aInfo.GetAdapterVendorID(), RTL_TEXTENCODING_UTF8) +
OUStringToOString(aInfo.GetAdapterDeviceID(), RTL_TEXTENCODING_UTF8) +
OUStringToOString(aInfo.GetDriverVersion(), RTL_TEXTENCODING_UTF8) +
- OString::number(aInfo.GetWindowsVersion());
+ OString::number(DriverBlocklist::GetWindowsVersion());
#else
return rtl::OStringView(reinterpret_cast<const char*>(glGetString(GL_VENDOR))) +
reinterpret_cast<const char*>(glGetString(GL_RENDERER)) +
@@ -767,7 +767,7 @@ bool OpenGLHelper::isDeviceBlacklisted()
WinOpenGLDeviceInfo aInfo;
bBlacklisted = aInfo.isDeviceBlocked();
- if (aInfo.GetWindowsVersion() == 0x00060001 && /* Windows 7 */
+ if (DriverBlocklist::GetWindowsVersion() == 0x00060001 && /* Windows 7 */
(aInfo.GetAdapterVendorID() == "0x1002" || aInfo.GetAdapterVendorID() == "0x1022")) /* AMD */
{
SAL_INFO("vcl.opengl", "Relaxing watchdog timings.");