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 <unicode/regex.h>
12 #include <comphelper/configuration.hxx>
13 #include <officecfg/Office/Common.hxx>
14 #include <opencl/openclconfig.hxx>
15 #include <opencl/platforminfo.hxx>
16 #include <rtl/ustring.hxx>
17 #include <sal/log.hxx>
18 #include <sal/types.h>
20 OpenCLConfig::OpenCLConfig() :
23 // This entry we have had for some time (when blacklisting was
24 // done elsewhere in the code), so presumably there is a known
25 // good reason for it.
26 maBlackList
.insert(ImplMatcher("Windows", "", "Intel\\(R\\) Corporation", "", "9\\.17\\.10\\.2884"));
28 // This is what I have tested on Linux and it works for our unit tests.
29 maWhiteList
.insert(ImplMatcher("Linux", "", "Advanced Micro Devices, Inc\\.", "", "1445\\.5 \\(sse2,avx\\)"));
31 // For now, assume that AMD, Intel and NVIDIA drivers are good
32 maWhiteList
.insert(ImplMatcher("", "", "Advanced Micro Devices, Inc\\.", "", ""));
33 maWhiteList
.insert(ImplMatcher("", "", "Intel\\(R\\) Corporation", "", ""));
34 maWhiteList
.insert(ImplMatcher("", "", "NVIDIA Corporation", "", ""));
37 bool OpenCLConfig::operator== (const OpenCLConfig
& r
) const
39 return (mbUseOpenCL
== r
.mbUseOpenCL
&&
40 maBlackList
== r
.maBlackList
&&
41 maWhiteList
== r
.maWhiteList
&&
45 bool OpenCLConfig::operator!= (const OpenCLConfig
& r
) const
47 return !operator== (r
);
52 css::uno::Sequence
<OUString
> SetOfImplMatcherToStringSequence(const OpenCLConfig::ImplMatcherSet
& rSet
)
54 css::uno::Sequence
<OUString
> result(rSet
.size());
57 for (auto i
= rSet
.cbegin(); i
!= rSet
.cend(); ++i
)
60 (*i
).maOS
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
61 (*i
).maOSVersion
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
62 (*i
).maPlatformVendor
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
63 (*i
).maDevice
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
64 (*i
).maDriverVersion
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B");
70 OUString
getToken(const OUString
& string
, sal_Int32
& index
)
72 OUString
token(string
.getToken(0, '/', index
));
76 while ((p
= token
.indexOf('%', i
)) >= 0)
79 result
+= token
.copy(i
, p
- i
);
80 if (p
< token
.getLength() - 2)
82 result
+= OUString(static_cast<sal_Unicode
>(token
.copy(p
+1, 2).toInt32(16)));
87 i
= token
.getLength();
90 result
+= token
.copy(i
);
95 OpenCLConfig::ImplMatcherSet
StringSequenceToSetOfImplMatcher(const css::uno::Sequence
<OUString
>& rSequence
)
97 OpenCLConfig::ImplMatcherSet result
;
99 for (auto i
= rSequence
.begin(); i
!= rSequence
.end(); ++i
)
101 OpenCLConfig::ImplMatcher m
;
103 m
.maOS
= getToken(*i
, index
);
104 m
.maOSVersion
= getToken(*i
, index
);
105 m
.maPlatformVendor
= getToken(*i
, index
);
106 m
.maDevice
= getToken(*i
, index
);
107 m
.maDriverVersion
= getToken(*i
, index
);
115 bool match(const OUString
& rPattern
, const OUString
& rInput
)
117 if (rPattern
.isEmpty())
120 UErrorCode
nIcuError(U_ZERO_ERROR
);
121 icu::UnicodeString
sIcuPattern(reinterpret_cast<const UChar
*>(rPattern
.getStr()), rPattern
.getLength());
122 icu::UnicodeString
sIcuInput(reinterpret_cast<const UChar
*>(rInput
.getStr()), rInput
.getLength());
123 RegexMatcher
aMatcher(sIcuPattern
, sIcuInput
, 0, nIcuError
);
125 if (U_SUCCESS(nIcuError
) && aMatcher
.matches(nIcuError
) && U_SUCCESS(nIcuError
))
131 bool match(const OpenCLConfig::ImplMatcher
& rListEntry
, const OpenCLPlatformInfo
& rPlatform
, const OpenCLDeviceInfo
& rDevice
)
134 if (!rListEntry
.maOS
.isEmpty() && rListEntry
.maOS
!= "Windows")
137 if (!rListEntry
.maOS
.isEmpty() && rListEntry
.maOS
!= "Linux")
140 if (!rListEntry
.maOS
.isEmpty() && rListEntry
.maOS
!= "OS X")
144 // OS version check not yet implemented
146 if (!match(rListEntry
.maPlatformVendor
, rPlatform
.maVendor
))
149 if (!match(rListEntry
.maDevice
, rDevice
.maName
))
152 if (!match(rListEntry
.maDriverVersion
, rDevice
.maDriver
))
158 bool match(const OpenCLConfig::ImplMatcherSet
& rList
, const OpenCLPlatformInfo
& rPlatform
, const OpenCLDeviceInfo
& rDevice
, const char* sKindOfList
)
160 for (auto i
= rList
.cbegin(); i
!= rList
.end(); ++i
)
162 SAL_INFO("opencl", "Looking for match for platform=" << rPlatform
<< ", device=" << rDevice
<<
163 " in " << sKindOfList
<< " entry=" << *i
);
165 if (match(*i
, rPlatform
, rDevice
))
167 SAL_INFO("opencl", "Match!");
174 } // anonymous namespace
176 OpenCLConfig
OpenCLConfig::get()
180 result
.mbUseOpenCL
= officecfg::Office::Common::Misc::UseOpenCL::get();
182 result
.maBlackList
= StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLBlackList::get());
183 result
.maWhiteList
= StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLWhiteList::get());
188 void OpenCLConfig::set()
190 std::shared_ptr
<comphelper::ConfigurationChanges
> batch(comphelper::ConfigurationChanges::create());
192 officecfg::Office::Common::Misc::UseOpenCL::set(mbUseOpenCL
, batch
);
193 officecfg::Office::Common::Misc::OpenCLBlackList::set(SetOfImplMatcherToStringSequence(maBlackList
), batch
);
194 officecfg::Office::Common::Misc::OpenCLWhiteList::set(SetOfImplMatcherToStringSequence(maWhiteList
), batch
);
199 bool OpenCLConfig::checkImplementation(const OpenCLPlatformInfo
& rPlatform
, const OpenCLDeviceInfo
& rDevice
) const
201 // Check blacklist of known bad OpenCL implementations
202 if (match(maBlackList
, rPlatform
, rDevice
, "blacklist"))
204 SAL_INFO("opencl", "Rejecting");
208 // Check for whitelist of known good OpenCL implementations
209 if (match(maWhiteList
, rPlatform
, rDevice
, "whitelist"))
211 SAL_INFO("opencl", "Approving");
216 SAL_INFO("opencl", "Fallback: rejecting platform=" << rPlatform
<< ", device=" << rDevice
);
220 std::ostream
& operator<<(std::ostream
& rStream
, const OpenCLConfig
& rConfig
)
223 "UseOpenCL=" << (rConfig
.mbUseOpenCL
? "YES" : "NO") << ","
224 "BlackList=" << rConfig
.maBlackList
<< ","
225 "WhiteList=" << rConfig
.maWhiteList
<<
230 std::ostream
& operator<<(std::ostream
& rStream
, const OpenCLConfig::ImplMatcher
& rImpl
)
233 "OS=" << rImpl
.maOS
<< ","
234 "OSVersion=" << rImpl
.maOSVersion
<< ","
235 "PlatformVendor=" << rImpl
.maPlatformVendor
<< ","
236 "Device=" << rImpl
.maDevice
<< ","
237 "DriverVersion=" << rImpl
.maDriverVersion
<<
243 std::ostream
& operator<<(std::ostream
& rStream
, const OpenCLConfig::ImplMatcherSet
& rSet
)
246 for (auto i
= rSet
.cbegin(); i
!= rSet
.cend(); ++i
)
248 if (i
!= rSet
.cbegin())
256 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */