diff options
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/inc/opengl/win/WinDeviceInfo.hxx | 3 | ||||
-rw-r--r-- | vcl/opengl/win/WinDeviceInfo.cxx | 67 | ||||
-rw-r--r-- | vcl/opengl/win/backlist.xml | 10 | ||||
-rw-r--r-- | vcl/opengl/win/blocklist_parser.cxx | 304 | ||||
-rw-r--r-- | vcl/opengl/win/blocklist_parser.hxx | 44 |
6 files changed, 396 insertions, 33 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index 0ce40d39eb46..82fa50913cc5 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -663,6 +663,7 @@ ifeq ($(OS),WNT) $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/opengl/win/gdiimpl \ vcl/opengl/win/WinDeviceInfo \ + vcl/opengl/win/blocklist_parser \ vcl/win/source/app/saldata \ vcl/win/source/app/salinfo \ vcl/win/source/app/salinst \ diff --git a/vcl/inc/opengl/win/WinDeviceInfo.hxx b/vcl/inc/opengl/win/WinDeviceInfo.hxx index 21f14d9272bd..801329ae7073 100644 --- a/vcl/inc/opengl/win/WinDeviceInfo.hxx +++ b/vcl/inc/opengl/win/WinDeviceInfo.hxx @@ -73,6 +73,8 @@ enum DeviceVendor { DeviceVendorMax }; +bool ParseDriverVersion(const OUString& rString, uint64_t& rVersion); + struct DriverInfo { typedef std::vector<OUString> DeviceFamilyVector; @@ -114,6 +116,7 @@ struct DriverInfo static DeviceFamilyVector* mpDeviceFamilies[DeviceFamilyMax]; OUString maSuggestedVersion; + OUString maMsg; }; #define GFX_DRIVER_VERSION(a,b,c,d) \ diff --git a/vcl/opengl/win/WinDeviceInfo.cxx b/vcl/opengl/win/WinDeviceInfo.cxx index 91033243abec..1c02b0c0f3ab 100644 --- a/vcl/opengl/win/WinDeviceInfo.cxx +++ b/vcl/opengl/win/WinDeviceInfo.cxx @@ -339,9 +339,35 @@ bool SplitDriverVersion(const char *aSource, char *aAStr, char *aBStr, char *aCS return true; } -bool ParseDriverVersion(const OUString& aVersion, uint64_t *aNumericVersion) +/* Other interesting places for info: + * IDXGIAdapter::GetDesc() + * IDirectDraw7::GetAvailableVidMem() + * e->GetAvailableTextureMem() + * */ + +template<typename T> void appendIntegerWithPadding(OUString& rString, T value, sal_uInt32 nChars) +{ + rString += "0x"; + OUString aValue = OUString::number(value, 16); + sal_Int32 nLength = aValue.getLength(); + sal_uInt32 nPadLength = nChars - nLength; + assert(nPadLength >= 0); + OUStringBuffer aBuffer; + for (sal_uInt32 i = 0; i < nPadLength; ++i) + { + aBuffer.append("0"); + } + rString += aBuffer.makeStringAndClear() + aValue; +} + +#define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\" +} + +namespace wgl { + +bool ParseDriverVersion(const OUString& aVersion, uint64_t& rNumericVersion) { - *aNumericVersion = 0; + rNumericVersion = 0; #if defined(WIN32) int a, b, c, d; @@ -365,37 +391,12 @@ bool ParseDriverVersion(const OUString& aVersion, uint64_t *aNumericVersion) if (c < 0 || c > 0xffff) return false; if (d < 0 || d > 0xffff) return false; - *aNumericVersion = GFX_DRIVER_VERSION(a, b, c, d); + rNumericVersion = GFX_DRIVER_VERSION(a, b, c, d); return true; #else return false; #endif } -/* Other interesting places for info: - * IDXGIAdapter::GetDesc() - * IDirectDraw7::GetAvailableVidMem() - * e->GetAvailableTextureMem() - * */ - -template<typename T> void appendIntegerWithPadding(OUString& rString, T value, sal_uInt32 nChars) -{ - rString += "0x"; - OUString aValue = OUString::number(value, 16); - sal_Int32 nLength = aValue.getLength(); - sal_uInt32 nPadLength = nChars - nLength; - assert(nPadLength >= 0); - OUStringBuffer aBuffer; - for (sal_uInt32 i = 0; i < nPadLength; ++i) - { - aBuffer.append("0"); - } - rString += aBuffer.makeStringAndClear() + aValue; -} - -#define DEVICE_KEY_PREFIX L"\\Registry\\Machine\\" -} - -namespace wgl { uint64_t DriverInfo::allDriverVersions = ~(uint64_t(0)); DriverInfo::DeviceFamilyVector* const DriverInfo::allDevices = nullptr; @@ -627,7 +628,7 @@ WinOpenGLDeviceInfo::~WinOpenGLDeviceInfo() bool WinOpenGLDeviceInfo::FindBlocklistedDeviceInList() { uint64_t driverVersion; - ParseDriverVersion(maDriverVersion, &driverVersion); + wgl::ParseDriverVersion(maDriverVersion, driverVersion); wgl::OperatingSystem eOS = WindowsVersionToOperatingSystem(mnWindowsVersion); bool match = false; @@ -1014,10 +1015,10 @@ void WinOpenGLDeviceInfo::GetData() uint64_t dllNumericVersion = 0, dllNumericVersion2 = 0, driverNumericVersion = 0, knownSafeMismatchVersion = 0; - ParseDriverVersion(aDLLVersion, &dllNumericVersion); - ParseDriverVersion(aDLLVersion2, &dllNumericVersion2); - ParseDriverVersion(maDriverVersion, &driverNumericVersion); - ParseDriverVersion("9.17.10.0", &knownSafeMismatchVersion); + wgl::ParseDriverVersion(aDLLVersion, dllNumericVersion); + wgl::ParseDriverVersion(aDLLVersion2, dllNumericVersion2); + wgl::ParseDriverVersion(maDriverVersion, driverNumericVersion); + wgl::ParseDriverVersion("9.17.10.0", knownSafeMismatchVersion); // If there's a driver version mismatch, consider this harmful only when // the driver version is less than knownSafeMismatchVersion. See the diff --git a/vcl/opengl/win/backlist.xml b/vcl/opengl/win/backlist.xml new file mode 100644 index 000000000000..b4cac2b1402c --- /dev/null +++ b/vcl/opengl/win/backlist.xml @@ -0,0 +1,10 @@ +<root> + <whitelist> + <device os="7" vendor="intel" compare="equal" version="10.18.10.3412"> + <msg>Moggi's Windows OpenGL driver</msg> + </device> + </whitelist> + <blacklist> + + </blacklist> +</root> diff --git a/vcl/opengl/win/blocklist_parser.cxx b/vcl/opengl/win/blocklist_parser.cxx new file mode 100644 index 000000000000..35301737bb09 --- /dev/null +++ b/vcl/opengl/win/blocklist_parser.cxx @@ -0,0 +1,304 @@ +/* -*- 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 "blocklist_parser.hxx" + +WinBlocklistParser::WinBlocklistParser(const OUString& rURL, + std::vector<wgl::DriverInfo>& rDriverList): + maURL(rURL), + mrDriverList(rDriverList) +{ +} + +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 == "xp") + { + return wgl::DRIVER_OS_WINDOWS_XP; + } + else if (rString == "server2003") + { + return wgl::DRIVER_OS_WINDOWS_SERVER_2003; + } + else if (rString == "vista") + { + return wgl::DRIVER_OS_WINDOWS_VISTA; + } + 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; + } + + 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(); +} + +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 WinBlocklistParser::handleDevice(wgl::DriverInfo& rDriver, xmlreader::XmlReader& rReader) +{ + if (meBlockType == BlockType::WHITELIST) + { + rDriver.mbWhitelisted = true; + } + else if (meBlockType == BlockType::UNKNOWN) + { + throw InvalidFileException(); + } + + xmlreader::Span name; + int nsId; + + while (rReader.nextAttribute(&nsId, &name)) + { + if (name.equals("os")) + { + xmlreader::Span name = rReader.getAttributeValue(false); + OString sOS(name.begin, name.length); + rDriver.meOperatingSystem = getOperatingSystem(sOS); + } + else if (name.equals("vendor")) + { + name = rReader.getAttributeValue(false); + OString sVendor(name.begin, name.length); + + // TODO: moggi: check that only valid vendors are imported + OUString aVendor = OStringToOUString(sVendor, RTL_TEXTENCODING_UTF8); + rDriver.maAdapterVendor = aVendor; + } + else if (name.equals("device")) + { + name = rReader.getAttributeValue(false); + OString sDevice(name.begin, name.length); + } + else if (name.equals("compare")) + { + name = rReader.getAttributeValue(false); + OString sCompare(name.begin, name.length); + rDriver.meComparisonOp = getComparison(sCompare); + } + else if (name.equals("version")) + { + name = rReader.getAttributeValue(false); + OString sVersion(name.begin, name.length); + rDriver.mnDriverVersion = getVersion(sVersion); + } + else if (name.equals("minVersion")) + { + name = rReader.getAttributeValue(false); + OString sMinVersion(name.begin, name.length); + rDriver.mnDriverVersion = getVersion(sMinVersion); + } + else if (name.equals("maxVersion")) + { + name = rReader.getAttributeValue(false); + OString sMaxVersion(name.begin, name.length); + rDriver.mnDriverVersionMax = getVersion(sMaxVersion); + } + } + + int nLevel = 1; + bool bInMsg = false; + 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) + { + ++nLevel; + if (nLevel > 2) + throw InvalidFileException(); + + if (name.equals("msg")) + { + bInMsg = true; + } + 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::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.equals("device")) + { + wgl::DriverInfo aDriver; + handleDevice(aDriver, rReader); + mrDriverList.push_back(aDriver); + } + else if (name.equals("deviceRange")) + { + wgl::DriverInfo aDriver; + handleDevice(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.equals("whitelist")) + { + meBlockType = BlockType::WHITELIST; + handleList(rReader); + } + else if (name.equals("blacklist")) + { + meBlockType = BlockType::BLACKLIST; + handleList(rReader); + } + else if (name.equals("root")) + { + } + else + { + throw InvalidFileException(); + } + } + else if (res == xmlreader::XmlReader::RESULT_END) + { + if (name.equals("whitelist") + || + name.equals("blacklist")) + { + meBlockType = BlockType::UNKNOWN; + } + } + else if (res == xmlreader::XmlReader::RESULT_DONE) + { + break; + } + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/opengl/win/blocklist_parser.hxx b/vcl/opengl/win/blocklist_parser.hxx new file mode 100644 index 000000000000..c34af0ad3403 --- /dev/null +++ b/vcl/opengl/win/blocklist_parser.hxx @@ -0,0 +1,44 @@ +/* -*- 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/WinDeviceInfo.hxx" + +#include <xmlreader/xmlreader.hxx> + +#include <vector> + +class InvalidFileException +{ +}; + +class WinBlocklistParser +{ + WinBlocklistParser(const OUString& rURL, std::vector<wgl::DriverInfo>& rDriverList); + void parse(); + +private: + void handleDevice(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: */ |