Version 6.4.0.0.beta1, tag libreoffice-6.4.0.0.beta1
[LibreOffice.git] / opencl / source / openclconfig.cxx
blob643d9fc2a8a190f097b2151cbd0c291bc2e5f8c8
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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() :
26 mbUseOpenCL(true)
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);
54 namespace {
56 css::uno::Sequence<OUString> SetOfImplMatcherToStringSequence(const OpenCLConfig::ImplMatcherSet& rSet)
58 css::uno::Sequence<OUString> result(rSet.size());
60 size_t n(0);
61 for (const auto& rItem : rSet)
63 result[n++] =
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");
71 return result;
74 OUString getToken(const OUString& string, sal_Int32& index)
76 OUString token(string.getToken(0, '/', index));
77 OUStringBuffer result;
78 sal_Int32 i(0);
79 sal_Int32 p;
80 while ((p = token.indexOf('%', i)) >= 0)
82 if (p > i)
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)));
87 i = p + 3;
89 else
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;
106 sal_Int32 index(0);
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);
113 result.insert(m);
116 return result;
119 bool match(const OUString& rPattern, const OUString& rInput)
121 if (rPattern.isEmpty())
122 return true;
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)
134 #if defined(_WIN32)
135 if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "Windows")
136 return false;
137 #elif defined LINUX
138 if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "Linux")
139 return false;
140 #elif defined MACOSX
141 if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "OS X")
142 return false;
143 #endif
145 // OS version check not yet implemented
147 if (!match(rListEntry.maPlatformVendor, rPlatform.maVendor))
148 return false;
150 if (!match(rListEntry.maDevice, rDevice.maName))
151 return false;
153 if (!match(rListEntry.maDriverVersion, rDevice.maDriver))
154 return false;
156 return true;
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!");
169 return true;
172 return false;
175 } // anonymous namespace
177 OpenCLConfig OpenCLConfig::get()
179 OpenCLConfig result;
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());
186 return result;
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);
197 batch->commit();
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");
206 return true;
209 // Check for whitelist of known good OpenCL implementations
210 if (match(maWhiteList, rPlatform, rDevice, "whitelist"))
212 SAL_INFO("opencl", "Approving");
213 return false;
216 // Fallback: reject
217 SAL_INFO("opencl", "Fallback: rejecting platform=" << rPlatform << ", device=" << rDevice);
218 return true;
221 std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig& rConfig)
223 rStream << "{"
224 "UseOpenCL=" << (rConfig.mbUseOpenCL ? "YES" : "NO") << ","
225 "BlackList=" << rConfig.maBlackList << ","
226 "WhiteList=" << rConfig.maWhiteList <<
227 "}";
228 return rStream;
231 std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcher& rImpl)
233 rStream << "{"
234 "OS=" << rImpl.maOS << ","
235 "OSVersion=" << rImpl.maOSVersion << ","
236 "PlatformVendor=" << rImpl.maPlatformVendor << ","
237 "Device=" << rImpl.maDevice << ","
238 "DriverVersion=" << rImpl.maDriverVersion <<
239 "}";
241 return rStream;
244 std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcherSet& rSet)
246 rStream << "{";
247 for (auto i = rSet.cbegin(); i != rSet.cend(); ++i)
249 if (i != rSet.cbegin())
250 rStream << ",";
251 rStream << *i;
253 rStream << "}";
254 return rStream;
257 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */