1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
12 #include <string_view>
14 #include <unicode/regex.h>
16 #include <comphelper/configuration.hxx>
17 #include <officecfg/Office/Common.hxx>
18 #include <opencl/openclconfig.hxx>
19 #include <opencl/platforminfo.hxx>
20 #include <rtl/ustring.hxx>
21 #include <rtl/ustrbuf.hxx>
22 #include <sal/log.hxx>
23 #include <sal/types.h>
25 OpenCLConfig::OpenCLConfig() :
28 // This entry we have had for some time (when blacklisting was
29 // done elsewhere in the code), so presumably there is a known
30 // good reason for it.
31 maBlackList
.insert(ImplMatcher("Windows", "", "Intel\\(R\\) Corporation", "", "9\\.17\\.10\\.2884"));
33 // This is what I have tested on Linux and it works for our unit tests.
34 maWhiteList
.insert(ImplMatcher("Linux", "", "Advanced Micro Devices, Inc\\.", "", "1445\\.5 \\(sse2,avx\\)"));
36 // For now, assume that AMD, Intel and NVIDIA drivers are good
37 maWhiteList
.insert(ImplMatcher("", "", "Advanced Micro Devices, Inc\\.", "", ""));
38 maWhiteList
.insert(ImplMatcher("", "", "Intel\\(R\\) Corporation", "", ""));
39 maWhiteList
.insert(ImplMatcher("", "", "NVIDIA Corporation", "", ""));
42 bool OpenCLConfig::operator== (const OpenCLConfig
& r
) const
44 return (mbUseOpenCL
== r
.mbUseOpenCL
&&
45 maBlackList
== r
.maBlackList
&&
46 maWhiteList
== r
.maWhiteList
);
49 bool OpenCLConfig::operator!= (const OpenCLConfig
& r
) const
51 return !operator== (r
);
56 css::uno::Sequence
<OUString
> SetOfImplMatcherToStringSequence(const OpenCLConfig::ImplMatcherSet
& rSet
)
58 css::uno::Sequence
<OUString
> result(rSet
.size());
61 for (const auto& rItem
: rSet
)
64 rItem
.maOS
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
65 rItem
.maOSVersion
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
66 rItem
.maPlatformVendor
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
67 rItem
.maDevice
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
68 rItem
.maDriverVersion
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B");
74 OUString
getToken(const OUString
& string
, sal_Int32
& index
)
76 OUString
token(string
.getToken(0, '/', index
));
77 OUStringBuffer result
;
80 while ((p
= token
.indexOf('%', i
)) >= 0)
83 result
.append(std::u16string_view(token
).substr(i
, p
- i
));
84 if (p
< token
.getLength() - 2)
86 result
.append(sal_Unicode(token
.copy(p
+1, 2).toInt32(16)));
91 i
= token
.getLength();
94 result
.append(std::u16string_view(token
).substr(i
));
96 return result
.makeStringAndClear();
99 OpenCLConfig::ImplMatcherSet
StringSequenceToSetOfImplMatcher(const css::uno::Sequence
<OUString
>& rSequence
)
101 OpenCLConfig::ImplMatcherSet result
;
103 for (const auto& rItem
: rSequence
)
105 OpenCLConfig::ImplMatcher m
;
107 m
.maOS
= getToken(rItem
, index
);
108 m
.maOSVersion
= getToken(rItem
, index
);
109 m
.maPlatformVendor
= getToken(rItem
, index
);
110 m
.maDevice
= getToken(rItem
, index
);
111 m
.maDriverVersion
= getToken(rItem
, index
);
119 bool match(const OUString
& rPattern
, const OUString
& rInput
)
121 if (rPattern
.isEmpty())
124 UErrorCode
nIcuError(U_ZERO_ERROR
);
125 icu::UnicodeString
sIcuPattern(reinterpret_cast<const UChar
*>(rPattern
.getStr()), rPattern
.getLength());
126 icu::UnicodeString
sIcuInput(reinterpret_cast<const UChar
*>(rInput
.getStr()), rInput
.getLength());
127 icu::RegexMatcher
aMatcher(sIcuPattern
, sIcuInput
, 0, nIcuError
);
129 return U_SUCCESS(nIcuError
) && aMatcher
.matches(nIcuError
) && U_SUCCESS(nIcuError
);
132 bool match(const OpenCLConfig::ImplMatcher
& rListEntry
, const OpenCLPlatformInfo
& rPlatform
, const OpenCLDeviceInfo
& rDevice
)
135 if (!rListEntry
.maOS
.isEmpty() && rListEntry
.maOS
!= "Windows")
138 if (!rListEntry
.maOS
.isEmpty() && rListEntry
.maOS
!= "Linux")
141 if (!rListEntry
.maOS
.isEmpty() && rListEntry
.maOS
!= "OS X")
145 // OS version check not yet implemented
147 if (!match(rListEntry
.maPlatformVendor
, rPlatform
.maVendor
))
150 if (!match(rListEntry
.maDevice
, rDevice
.maName
))
153 if (!match(rListEntry
.maDriverVersion
, rDevice
.maDriver
))
159 bool match(const OpenCLConfig::ImplMatcherSet
& rList
, const OpenCLPlatformInfo
& rPlatform
, const OpenCLDeviceInfo
& rDevice
, const char* sKindOfList
)
161 for (const auto& rListEntry
: rList
)
163 SAL_INFO("opencl", "Looking for match for platform=" << rPlatform
<< ", device=" << rDevice
<<
164 " in " << sKindOfList
<< " entry=" << rListEntry
);
166 if (match(rListEntry
, rPlatform
, rDevice
))
168 SAL_INFO("opencl", "Match!");
175 } // anonymous namespace
177 OpenCLConfig
OpenCLConfig::get()
181 result
.mbUseOpenCL
= officecfg::Office::Common::Misc::UseOpenCL::get();
183 result
.maBlackList
= StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLBlackList::get());
184 result
.maWhiteList
= StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLWhiteList::get());
189 void OpenCLConfig::set()
191 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
193 officecfg::Office::Common::Misc::UseOpenCL::set(mbUseOpenCL
, batch
);
194 officecfg::Office::Common::Misc::OpenCLBlackList::set(SetOfImplMatcherToStringSequence(maBlackList
), batch
);
195 officecfg::Office::Common::Misc::OpenCLWhiteList::set(SetOfImplMatcherToStringSequence(maWhiteList
), batch
);
200 bool OpenCLConfig::checkImplementation(const OpenCLPlatformInfo
& rPlatform
, const OpenCLDeviceInfo
& rDevice
) const
202 // Check blacklist of known bad OpenCL implementations
203 if (match(maBlackList
, rPlatform
, rDevice
, "blacklist"))
205 SAL_INFO("opencl", "Rejecting");
209 // Check for whitelist of known good OpenCL implementations
210 if (match(maWhiteList
, rPlatform
, rDevice
, "whitelist"))
212 SAL_INFO("opencl", "Approving");
217 SAL_INFO("opencl", "Fallback: rejecting platform=" << rPlatform
<< ", device=" << rDevice
);
221 std::ostream
& operator<<(std::ostream
& rStream
, const OpenCLConfig
& rConfig
)
224 "UseOpenCL=" << (rConfig
.mbUseOpenCL
? "YES" : "NO") << ","
225 "BlackList=" << rConfig
.maBlackList
<< ","
226 "WhiteList=" << rConfig
.maWhiteList
<<
231 std::ostream
& operator<<(std::ostream
& rStream
, const OpenCLConfig::ImplMatcher
& rImpl
)
234 "OS=" << rImpl
.maOS
<< ","
235 "OSVersion=" << rImpl
.maOSVersion
<< ","
236 "PlatformVendor=" << rImpl
.maPlatformVendor
<< ","
237 "Device=" << rImpl
.maDevice
<< ","
238 "DriverVersion=" << rImpl
.maDriverVersion
<<
244 std::ostream
& operator<<(std::ostream
& rStream
, const OpenCLConfig::ImplMatcherSet
& rSet
)
247 for (auto i
= rSet
.cbegin(); i
!= rSet
.cend(); ++i
)
249 if (i
!= rSet
.cbegin())
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */