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 <boost/shared_ptr.hpp>
11 #include <unicode/regex.h>
13 #include <comphelper/configuration.hxx>
14 #include <officecfg/Office/Common.hxx>
15 #include <opencl/openclconfig.hxx>
16 #include <opencl/platforminfo.hxx>
17 #include <rtl/ustring.hxx>
18 #include <sal/log.hxx>
19 #include <sal/types.h>
21 OpenCLConfig::OpenCLConfig() :
24 // This entry we have had for some time (when blacklisting was
25 // done elsewhere in the code), so presumably there is a known
26 // good reason for it.
27 maBlackList
.insert(ImplMatcher("Windows", "", "Intel\\(R\\) Corporation", "", "9\\.17\\.10\\.2884"));
29 // This is what I have tested on Linux and it works for our unit tests.
30 maWhiteList
.insert(ImplMatcher("Linux", "", "Advanced Micro Devices, Inc\\.", "", "1445\\.5 \\(sse2,avx\\)"));
32 // For now, assume that AMD, Intel and NVIDIA drivers are good
33 maWhiteList
.insert(ImplMatcher("", "", "Advanced Micro Devices, Inc\\.", "", ""));
34 maWhiteList
.insert(ImplMatcher("", "", "Intel\\(R\\) Corporation", "", ""));
35 maWhiteList
.insert(ImplMatcher("", "", "NVIDIA Corporation", "", ""));
38 bool OpenCLConfig::operator== (const OpenCLConfig
& r
) const
40 return (mbUseOpenCL
== r
.mbUseOpenCL
&&
41 maBlackList
== r
.maBlackList
&&
42 maWhiteList
== r
.maWhiteList
&&
46 bool OpenCLConfig::operator!= (const OpenCLConfig
& r
) const
48 return !operator== (r
);
53 css::uno::Sequence
<OUString
> SetOfImplMatcherToStringSequence(const OpenCLConfig::ImplMatcherSet
& rSet
)
55 css::uno::Sequence
<OUString
> result(rSet
.size());
58 for (auto i
= rSet
.cbegin(); i
!= rSet
.cend(); ++i
)
61 (*i
).maOS
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
62 (*i
).maOSVersion
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
63 (*i
).maPlatformVendor
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
64 (*i
).maDevice
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
65 (*i
).maDriverVersion
.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B");
71 OUString
getToken(const OUString
& string
, sal_Int32
& index
)
73 OUString
token(string
.getToken(0, '/', index
));
77 while ((p
= token
.indexOf('%', i
)) >= 0)
80 result
+= token
.copy(i
, p
- i
);
81 if (p
< token
.getLength() - 2)
83 result
+= OUString(static_cast<sal_Unicode
>(token
.copy(p
+1, 2).toInt32(16)));
88 i
= token
.getLength();
91 result
+= token
.copy(i
);
96 OpenCLConfig::ImplMatcherSet
StringSequenceToSetOfImplMatcher(const css::uno::Sequence
<OUString
>& rSequence
)
98 OpenCLConfig::ImplMatcherSet result
;
100 for (auto i
= rSequence
.begin(); i
!= rSequence
.end(); ++i
)
102 OpenCLConfig::ImplMatcher m
;
104 m
.maOS
= getToken(*i
, index
);
105 m
.maOSVersion
= getToken(*i
, index
);
106 m
.maPlatformVendor
= getToken(*i
, index
);
107 m
.maDevice
= getToken(*i
, index
);
108 m
.maDriverVersion
= getToken(*i
, index
);
116 bool match(const OUString
& rPattern
, const OUString
& rInput
)
118 if (rPattern
.isEmpty())
121 UErrorCode
nIcuError(U_ZERO_ERROR
);
122 icu::UnicodeString
sIcuPattern(reinterpret_cast<const UChar
*>(rPattern
.getStr()), rPattern
.getLength());
123 icu::UnicodeString
sIcuInput(reinterpret_cast<const UChar
*>(rInput
.getStr()), rInput
.getLength());
124 RegexMatcher
aMatcher(sIcuPattern
, sIcuInput
, 0, nIcuError
);
126 if (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 (auto i
= rList
.cbegin(); i
!= rList
.end(); ++i
)
163 SAL_INFO("opencl", "Looking for match for platform=" << rPlatform
<< ", device=" << rDevice
<<
164 " in " << sKindOfList
<< " entry=" << *i
);
166 if (match(*i
, 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: */