LibreOffice Module opencl (master) 1
openclconfig.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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 */
9
10#include <sal/config.h>
11
12#include <unicode/regex.h>
13
15#include <officecfg/Office/Common.hxx>
18#include <rtl/ustring.hxx>
19#include <rtl/ustrbuf.hxx>
20#include <sal/log.hxx>
21#include <sal/types.h>
22#include <o3tl/string_view.hxx>
23
25 mbUseOpenCL(true)
26{
27 // This entry we have had for some time (when denylisting was
28 // done elsewhere in the code), so presumably there is a known
29 // good reason for it.
30 maDenyList.insert(ImplMatcher("Windows", "", "Intel\\(R\\) Corporation", "", "9\\.17\\.10\\.2884"));
31 // This was reported to produce bogus values in unit tests
32 maDenyList.insert(ImplMatcher("Windows", "", "Intel\\(R\\) Corporation", "", "27\\.20\\.100\\.8681"));
33
34 // For now, assume that AMD, Intel and NVIDIA drivers are good
35 maAllowList.insert(ImplMatcher("", "", "Advanced Micro Devices, Inc\\.", "", ""));
36 maAllowList.insert(ImplMatcher("", "", "Intel\\(R\\) Corporation", "", ""));
37 maAllowList.insert(ImplMatcher("", "", "NVIDIA Corporation", "", ""));
38}
39
41{
42 return (mbUseOpenCL == r.mbUseOpenCL &&
45}
46
48{
49 return !operator== (r);
50}
51
52namespace {
53
54css::uno::Sequence<OUString> SetOfImplMatcherToStringSequence(const OpenCLConfig::ImplMatcherSet& rSet)
55{
56 css::uno::Sequence<OUString> result(rSet.size());
57 auto resultRange = asNonConstRange(result);
58 size_t n(0);
59 for (const auto& rItem : rSet)
60 {
61 resultRange[n++] =
62 rItem.maOS.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
63 rItem.maOSVersion.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
64 rItem.maPlatformVendor.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
65 rItem.maDevice.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B") + "/" +
66 rItem.maDriverVersion.replaceAll("%", "%25").replaceAll("/", "%2F").replaceAll(";", "%3B");
67 }
68
69 return result;
70}
71
72OUString getToken(std::u16string_view string, sal_Int32& index)
73{
74 std::u16string_view token(o3tl::getToken(string, 0, '/', index));
75 OUStringBuffer result;
76 sal_Int32 i(0);
77 size_t p;
78 while ((p = token.find('%', i)) != std::u16string_view::npos)
79 {
80 if (static_cast<sal_Int32>(p) > i)
81 result.append(token.substr(i, p - i));
82 if (p < token.size() - 2)
83 {
84 result.append(sal_Unicode(o3tl::toInt32(token.substr(p+1, 2), 16)));
85 i = p + 3;
86 }
87 else
88 {
89 i = token.size();
90 }
91 }
92 result.append(token.substr(i));
93
94 return result.makeStringAndClear();
95}
96
97OpenCLConfig::ImplMatcherSet StringSequenceToSetOfImplMatcher(const css::uno::Sequence<OUString>& rSequence)
98{
100
101 for (const auto& rItem : rSequence)
102 {
104 sal_Int32 index(0);
105 m.maOS = getToken(rItem, index);
106 m.maOSVersion = getToken(rItem, index);
107 m.maPlatformVendor = getToken(rItem, index);
108 m.maDevice = getToken(rItem, index);
109 m.maDriverVersion = getToken(rItem, index);
110
111 result.insert(m);
112 }
113
114 return result;
115}
116
117bool match(const OUString& rPattern, const OUString& rInput)
118{
119 if (rPattern.isEmpty())
120 return true;
121
122 UErrorCode nIcuError(U_ZERO_ERROR);
123 icu::UnicodeString sIcuPattern(reinterpret_cast<const UChar*>(rPattern.getStr()), rPattern.getLength());
124 icu::UnicodeString sIcuInput(reinterpret_cast<const UChar*>(rInput.getStr()), rInput.getLength());
125 icu::RegexMatcher aMatcher(sIcuPattern, sIcuInput, 0, nIcuError);
126
127 return U_SUCCESS(nIcuError) && aMatcher.matches(nIcuError) && U_SUCCESS(nIcuError);
128}
129
130bool match(const OpenCLConfig::ImplMatcher& rListEntry, const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice)
131{
132#if defined(_WIN32)
133 if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "Windows")
134 return false;
135#elif defined LINUX
136 if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "Linux")
137 return false;
138#elif defined MACOSX
139 if (!rListEntry.maOS.isEmpty() && rListEntry.maOS != "OS X")
140 return false;
141#endif
142
143 // OS version check not yet implemented
144
145 if (!match(rListEntry.maPlatformVendor, rPlatform.maVendor))
146 return false;
147
148 if (!match(rListEntry.maDevice, rDevice.maName))
149 return false;
150
151 if (!match(rListEntry.maDriverVersion, rDevice.maDriver))
152 return false;
153
154 return true;
155}
156
157bool match(const OpenCLConfig::ImplMatcherSet& rList, const OpenCLPlatformInfo& rPlatform, const OpenCLDeviceInfo& rDevice, const char* sKindOfList)
158{
159 for (const auto& rListEntry : rList)
160 {
161 SAL_INFO("opencl", "Looking for match for platform=" << rPlatform << ", device=" << rDevice <<
162 " in " << sKindOfList << " entry=" << rListEntry);
163
164 if (match(rListEntry, rPlatform, rDevice))
165 {
166 SAL_INFO("opencl", "Match!");
167 return true;
168 }
169 }
170 return false;
171}
172
173} // anonymous namespace
174
176{
178
179 result.mbUseOpenCL = officecfg::Office::Common::Misc::UseOpenCL::get();
180
181 result.maDenyList = StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLDenyList::get());
182 result.maAllowList = StringSequenceToSetOfImplMatcher(officecfg::Office::Common::Misc::OpenCLAllowList::get());
183
184 return result;
185}
186
188{
189 std::shared_ptr<comphelper::ConfigurationChanges> batch(comphelper::ConfigurationChanges::create());
190
191 officecfg::Office::Common::Misc::UseOpenCL::set(mbUseOpenCL, batch);
192 officecfg::Office::Common::Misc::OpenCLDenyList::set(SetOfImplMatcherToStringSequence(maDenyList), batch);
193 officecfg::Office::Common::Misc::OpenCLAllowList::set(SetOfImplMatcherToStringSequence(maAllowList), batch);
194
195 batch->commit();
196}
197
199{
200 // Check denylist of known bad OpenCL implementations
201 if (match(maDenyList, rPlatform, rDevice, "denylist"))
202 {
203 SAL_INFO("opencl", "Rejecting");
204 return true;
205 }
206
207 // Check for allowlist of known good OpenCL implementations
208 if (match(maAllowList, rPlatform, rDevice, "allowlist"))
209 {
210 SAL_INFO("opencl", "Approving");
211 return false;
212 }
213
214 // Fallback: reject
215 SAL_INFO("opencl", "Fallback: rejecting platform=" << rPlatform << ", device=" << rDevice);
216 return true;
217}
218
219std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig& rConfig)
220{
221 rStream << "{"
222 "UseOpenCL=" << (rConfig.mbUseOpenCL ? "YES" : "NO") << ","
223 "DenyList=" << rConfig.maDenyList << ","
224 "AllowList=" << rConfig.maAllowList <<
225 "}";
226 return rStream;
227}
228
229std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcher& rImpl)
230{
231 rStream << "{"
232 "OS=" << rImpl.maOS << ","
233 "OSVersion=" << rImpl.maOSVersion << ","
234 "PlatformVendor=" << rImpl.maPlatformVendor << ","
235 "Device=" << rImpl.maDevice << ","
236 "DriverVersion=" << rImpl.maDriverVersion <<
237 "}";
238
239 return rStream;
240}
241
242std::ostream& operator<<(std::ostream& rStream, const OpenCLConfig::ImplMatcherSet& rSet)
243{
244 rStream << "{";
245 for (auto i = rSet.cbegin(); i != rSet.cend(); ++i)
246 {
247 if (i != rSet.cbegin())
248 rStream << ",";
249 rStream << *i;
250 }
251 rStream << "}";
252 return rStream;
253}
254
255/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static std::shared_ptr< ConfigurationChanges > create()
void * p
sal_Int64 n
#define SAL_INFO(area, stream)
sal_Int32 getToken(const Context &rContext, const char *pToken)
bool match(const sal_Unicode *pWild, const sal_Unicode *pStr, const sal_Unicode cEscape)
int i
index
m
sal_Int32 toInt32(std::u16string_view str, sal_Int16 radix=10)
std::basic_string_view< charT, traits > getToken(std::basic_string_view< charT, traits > sv, charT delimiter, std::size_t &position)
std::ostream & operator<<(std::ostream &rStream, const OpenCLConfig &rConfig)
static SfxItemSet & rSet
std::set< ImplMatcher > ImplMatcherSet
bool operator==(const OpenCLConfig &r) const
bool checkImplementation(const OpenCLPlatformInfo &rPlatform, const OpenCLDeviceInfo &rDevice) const
ImplMatcherSet maDenyList
ImplMatcherSet maAllowList
bool operator!=(const OpenCLConfig &r) const
static OpenCLConfig get()
sal_uInt16 sal_Unicode
Any result