OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/browser/gpu_blacklist.h" | |
6 | |
7 #include "base/json/json_reader.h" | |
8 #include "base/logging.h" | |
9 #include "base/stringprintf.h" | |
10 #include "base/string_number_conversions.h" | |
11 #include "base/sys_info.h" | |
12 #include "base/values.h" | |
13 #include "base/version.h" | |
14 #include "chrome/common/gpu_info.h" | |
15 | |
16 GpuBlacklist::VersionInfo::VersionInfo(const std::string& version_op, | |
17 const std::string& version_string, | |
18 const std::string& version_string2) { | |
19 op_ = StringToOp(version_op); | |
20 if (op_ == kUnknown || op_ == kAny) | |
21 return; | |
22 version_.reset(Version::GetVersionFromString(version_string)); | |
23 if (version_.get() == NULL) { | |
24 op_ = kUnknown; | |
25 return; | |
26 } | |
27 if (op_ == kBetween) { | |
28 version2_.reset(Version::GetVersionFromString(version_string2)); | |
29 if (version2_.get() == NULL) | |
30 op_ = kUnknown; | |
31 } | |
32 } | |
33 | |
34 GpuBlacklist::VersionInfo::~VersionInfo() { | |
35 } | |
36 | |
37 bool GpuBlacklist::VersionInfo::Contains(const Version& version) const { | |
38 if (op_ == kUnknown) | |
39 return false; | |
40 if (op_ == kAny) | |
41 return true; | |
42 if (op_ == kEQ) { | |
43 // Handles cases where 10.6 is considered as containing 10.6.*. | |
44 const std::vector<uint16>& components_reference = version_->components(); | |
45 const std::vector<uint16>& components = version.components(); | |
46 for (size_t i = 0; i < components_reference.size(); ++i) { | |
47 if (i >= components.size() && components_reference[i] != 0) | |
48 return false; | |
49 if (components[i] != components_reference[i]) | |
50 return false; | |
51 } | |
52 return true; | |
53 } | |
54 int relation = version.CompareTo(*version_); | |
55 if (op_ == kEQ) | |
56 return (relation == 0); | |
57 else if (op_ == kLT) | |
58 return (relation < 0); | |
59 else if (op_ == kLE) | |
60 return (relation <= 0); | |
61 else if (op_ == kGT) | |
62 return (relation > 0); | |
63 else if (op_ == kGE) | |
64 return (relation >= 0); | |
65 // op_ == kBetween | |
66 if (relation < 0) | |
67 return false; | |
68 return version.CompareTo(*version2_) <= 0; | |
69 } | |
70 | |
71 bool GpuBlacklist::VersionInfo::IsValid() const { | |
72 return op_ != kUnknown; | |
73 } | |
74 | |
75 GpuBlacklist::VersionInfo::Op GpuBlacklist::VersionInfo::StringToOp( | |
76 const std::string& version_op) { | |
77 if (version_op == "=") | |
78 return kEQ; | |
79 else if (version_op == "<") | |
80 return kLT; | |
81 else if (version_op == "<=") | |
82 return kLE; | |
83 else if (version_op == ">") | |
84 return kGT; | |
85 else if (version_op == ">=") | |
86 return kGE; | |
87 else if (version_op == "any") | |
88 return kAny; | |
89 else if (version_op == "between") | |
90 return kBetween; | |
91 return kUnknown; | |
92 } | |
93 | |
94 GpuBlacklist::OsInfo::OsInfo(const std::string& os, | |
95 const std::string& version_op, | |
96 const std::string& version_string, | |
97 const std::string& version_string2) { | |
98 type_ = StringToOsType(os); | |
99 if (type_ != kOsUnknown) { | |
100 version_info_.reset( | |
101 new VersionInfo(version_op, version_string, version_string2)); | |
102 } | |
103 } | |
104 | |
105 bool GpuBlacklist::OsInfo::Contains(OsType type, | |
106 const Version& version) const { | |
107 if (!IsValid()) | |
108 return false; | |
109 if (type_ != type && type_ != kOsAny) | |
110 return false; | |
111 return version_info_->Contains(version); | |
112 } | |
113 | |
114 bool GpuBlacklist::OsInfo::IsValid() const { | |
115 return type_ != kOsUnknown && version_info_->IsValid(); | |
116 } | |
117 | |
118 GpuBlacklist::OsType GpuBlacklist::OsInfo::type() const { | |
119 return type_; | |
120 } | |
121 | |
122 GpuBlacklist::GpuBlacklistEntry* | |
123 GpuBlacklist::GpuBlacklistEntry::GetGpuBlacklistEntryFromValue( | |
124 DictionaryValue* value) { | |
125 if (value == NULL) | |
126 return NULL; | |
127 | |
128 GpuBlacklistEntry* entry = new GpuBlacklistEntry(); | |
129 | |
130 DictionaryValue* os_value = NULL; | |
131 if (value->GetDictionary("os", &os_value)) { | |
132 std::string os_type = ""; | |
vangelis
2010/12/08 00:17:38
I think the default value for an std::string is th
Zhenyao Mo
2010/12/09 00:06:06
Done.
| |
133 std::string os_version_op = "any"; | |
134 std::string os_version_string = ""; | |
135 std::string os_version_string2 = ""; | |
136 os_value->GetString("type", &os_type); | |
137 DictionaryValue* os_version_value = NULL; | |
138 if (os_value->GetDictionary("version", &os_version_value)) { | |
139 os_version_value->GetString("op", &os_version_op); | |
140 os_version_value->GetString("number", &os_version_string); | |
141 os_version_value->GetString("number2", &os_version_string2); | |
142 } | |
143 if (!entry->SetOsInfo(os_type, os_version_op, os_version_string, | |
144 os_version_string2)) { | |
145 delete entry; | |
146 return NULL; | |
147 } | |
148 } | |
149 | |
150 std::string vendor_id = ""; | |
151 if (value->GetString("vendor_id", &vendor_id)) { | |
152 if (!entry->SetVendorId(vendor_id)) { | |
153 delete entry; | |
154 return NULL; | |
155 } | |
156 } | |
157 | |
158 std::string device_id = ""; | |
159 if (value->GetString("device_id", &device_id)) { | |
160 if (!entry->SetDeviceId(device_id)) { | |
161 delete entry; | |
162 return NULL; | |
163 } | |
164 } | |
165 | |
166 DictionaryValue* driver_version_value = NULL; | |
167 if (value->GetDictionary("driver_version", &driver_version_value)) { | |
168 std::string driver_version_op = "any"; | |
169 std::string driver_version_string = ""; | |
170 std::string driver_version_string2 = ""; | |
171 driver_version_value->GetString("op", &driver_version_op); | |
172 driver_version_value->GetString("number", &driver_version_string); | |
173 driver_version_value->GetString("number2", &driver_version_string2); | |
174 if (!entry->SetDriverVersionInfo(driver_version_op, driver_version_string, | |
175 driver_version_string2)) { | |
176 delete entry; | |
177 return NULL; | |
178 } | |
179 } | |
180 | |
181 ListValue* blacklist_value = NULL; | |
182 if (!value->GetList("blacklist", &blacklist_value)) { | |
183 delete entry; | |
184 return NULL; | |
185 } | |
186 std::vector<std::string> blacklist; | |
187 for (size_t i = 0; i < blacklist_value->GetSize(); ++i) { | |
188 std::string feature = ""; | |
189 if (blacklist_value->GetString(i, &feature)) { | |
190 blacklist.push_back(feature); | |
191 } else { | |
192 delete entry; | |
193 return NULL; | |
194 } | |
195 } | |
196 if (!entry->SetBlacklistedFeatures(blacklist)) { | |
197 delete entry; | |
198 return NULL; | |
199 } | |
200 | |
201 return entry; | |
202 } | |
203 | |
204 GpuBlacklist::GpuBlacklistEntry::GpuBlacklistEntry() | |
205 : vendor_id_(0), | |
206 device_id_(0) { | |
207 } | |
208 | |
209 bool GpuBlacklist::GpuBlacklistEntry::SetOsInfo( | |
210 const std::string& os, | |
211 const std::string& version_op, | |
212 const std::string& version_string, | |
213 const std::string& version_string2) { | |
214 os_info_.reset(new OsInfo(os, version_op, version_string, version_string2)); | |
215 return os_info_->IsValid(); | |
216 } | |
217 | |
218 bool GpuBlacklist::GpuBlacklistEntry::SetVendorId( | |
219 const std::string& vendor_id_string) { | |
220 vendor_id_ = 0; | |
221 return base::HexStringToInt(vendor_id_string, | |
222 reinterpret_cast<int*>(&vendor_id_)); | |
223 } | |
224 | |
225 bool GpuBlacklist::GpuBlacklistEntry::SetDeviceId( | |
226 const std::string& device_id_string) { | |
227 device_id_ = 0; | |
228 return base::HexStringToInt(device_id_string, | |
229 reinterpret_cast<int*>(&device_id_)); | |
230 } | |
231 | |
232 bool GpuBlacklist::GpuBlacklistEntry::SetDriverVersionInfo( | |
233 const std::string& version_op, | |
234 const std::string& version_string, | |
235 const std::string& version_string2) { | |
236 driver_version_info_.reset( | |
237 new VersionInfo(version_op, version_string, version_string2)); | |
238 return driver_version_info_->IsValid(); | |
239 } | |
240 | |
241 bool GpuBlacklist::GpuBlacklistEntry::SetBlacklistedFeatures( | |
242 const std::vector<std::string>& blacklisted_features) { | |
243 size_t size = blacklisted_features.size(); | |
244 if (size == 0) | |
245 return false; | |
246 bool accelerated_2d_canvas = false; | |
247 bool accelerated_compositing = false; | |
248 bool webgl = false; | |
249 for (size_t i = 0; i < size; ++i) { | |
250 GpuFeatureFlags::GpuFeatureType type = | |
251 GpuFeatureFlags::StringToGpuFeatureType(blacklisted_features[i]); | |
252 switch (type) { | |
253 case GpuFeatureFlags::kGpuFeatureAny: | |
254 if (size == 1) { | |
255 feature_flags_.reset(new GpuFeatureFlags()); | |
256 feature_flags_->SetFlags(true, true, true); | |
257 return true; | |
258 } | |
259 return false; | |
260 case GpuFeatureFlags::kGpuFeatureAccelerated2dCanvas: | |
261 accelerated_2d_canvas = true; | |
262 break; | |
263 case GpuFeatureFlags::kGpuFeatureAcceleratedCompositing: | |
264 accelerated_compositing = true; | |
265 break; | |
266 case GpuFeatureFlags::kGpuFeatureWebgl: | |
267 webgl = true; | |
268 break; | |
269 default: | |
270 return false; | |
271 } | |
272 } | |
273 feature_flags_.reset(new GpuFeatureFlags()); | |
274 feature_flags_->SetFlags(accelerated_2d_canvas, | |
275 accelerated_compositing, | |
276 webgl); | |
277 return true; | |
278 } | |
279 | |
280 bool GpuBlacklist::GpuBlacklistEntry::Contains( | |
281 OsType os_type, const Version& os_version, | |
282 uint32 vendor_id, uint32 device_id, | |
283 const Version& driver_version) const { | |
284 DCHECK(os_type != kOsAny); | |
285 if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version)) | |
286 return false; | |
287 if (vendor_id_ != 0 && vendor_id_ != vendor_id) | |
288 return false; | |
289 if (device_id_ != 0 && device_id_ != device_id) | |
290 return false; | |
291 if (driver_version_info_.get() == NULL) | |
292 return true; | |
293 return driver_version_info_->Contains(driver_version); | |
294 } | |
295 | |
296 GpuBlacklist::OsType GpuBlacklist::GpuBlacklistEntry::GetOsType() const { | |
297 if (os_info_.get() == NULL) | |
298 return kOsUnknown; | |
299 return os_info_->type(); | |
300 } | |
301 | |
302 GpuFeatureFlags GpuBlacklist::GpuBlacklistEntry::GetGpuFeatureFlags() const { | |
303 return *feature_flags_; | |
304 } | |
305 | |
306 GpuBlacklist::GpuBlacklist() { | |
307 } | |
308 | |
309 GpuBlacklist::~GpuBlacklist() { | |
310 Clear(); | |
311 } | |
312 | |
313 bool GpuBlacklist::LoadGpuBlacklist(const std::string& json_context, | |
314 bool current_os_only) { | |
315 std::vector<GpuBlacklistEntry*> entries; | |
316 scoped_ptr<Value> root; | |
317 root.reset(base::JSONReader::Read(json_context, false)); | |
318 if (root.get() == NULL || !root->IsType(Value::TYPE_DICTIONARY)) | |
319 return false; | |
320 | |
321 ListValue* list = NULL; | |
322 static_cast<DictionaryValue*>(root.get())->GetList("entries", &list); | |
323 if (list == NULL) | |
324 return false; | |
325 | |
326 for (size_t i = 0; i < list->GetSize(); ++i) { | |
327 DictionaryValue* list_item = NULL; | |
328 bool valid = list->GetDictionary(i, &list_item); | |
329 if (!valid) | |
330 break; | |
331 GpuBlacklistEntry* entry = | |
332 GpuBlacklistEntry::GetGpuBlacklistEntryFromValue(list_item); | |
333 if (entry == NULL) | |
334 break; | |
335 entries.push_back(entry); | |
336 } | |
337 | |
338 if (entries.size() < list->GetSize()) { | |
339 for (size_t i = 0; i < entries.size(); ++i) | |
340 delete entries[i]; | |
341 return false; | |
342 } | |
343 | |
344 Clear(); | |
345 // Don't apply GPU blacklist for a non-registered OS. | |
346 OsType os_filter = GetOsType(); | |
347 if (os_filter != kOsUnknown) { | |
348 for (size_t i = 0; i < entries.size(); ++i) { | |
349 OsType entry_os = entries[i]->GetOsType(); | |
350 if (!current_os_only || | |
351 entry_os == kOsAny || entry_os == os_filter) | |
352 blacklist_.push_back(entries[i]); | |
353 } | |
354 } | |
355 return true; | |
356 } | |
357 | |
358 GpuFeatureFlags GpuBlacklist::DetermineGpuFeatureFlags( | |
359 GpuBlacklist::OsType os, | |
360 Version* os_version, | |
361 const GPUInfo& gpu_info) const { | |
362 GpuFeatureFlags flags; | |
363 if (os == kOsAny) | |
364 os = GetOsType(); | |
365 scoped_ptr<Version> my_os_version; | |
366 if (os_version == NULL) { | |
367 std::string version_string; | |
368 #if defined(OS_MACOSX) | |
369 // Seems like base::SysInfo::OperatingSystemVersion() returns the wrong | |
370 // version in MacOsx. | |
371 int32 version_major, version_minor, version_bugfix; | |
372 base::SysInfo::OperatingSystemVersionNumbers( | |
373 &version_major, &version_minor, &version_bugfix); | |
374 version_string = base::StringPrintf("%d.%d.%d", | |
375 version_major, | |
376 version_minor, | |
377 version_bugfix); | |
378 #else | |
379 version_string = base::SysInfo::OperatingSystemVersion(); | |
380 #endif | |
381 my_os_version.reset(Version::GetVersionFromString(version_string)); | |
382 os_version = my_os_version.get(); | |
383 } | |
384 for (size_t i = 0; i < blacklist_.size(); ++i) { | |
385 scoped_ptr<Version> driver_version( | |
386 Version::GetVersionFromString(gpu_info.driver_version())); | |
387 if (blacklist_[i]->Contains(os, *os_version, | |
388 gpu_info.vendor_id(), gpu_info.device_id(), | |
389 *driver_version)) { | |
390 flags.Combine(blacklist_[i]->GetGpuFeatureFlags()); | |
391 } | |
392 } | |
393 return flags; | |
394 } | |
395 | |
396 GpuBlacklist::OsType GpuBlacklist::StringToOsType(const std::string& os) { | |
397 if (os == "win") | |
398 return kOsWin; | |
399 else if (os == "macosx") | |
400 return kOsMacosx; | |
401 else if (os == "linux") | |
402 return kOsLinux; | |
403 else if (os == "any") | |
404 return kOsAny; | |
405 return kOsUnknown; | |
406 } | |
407 | |
408 GpuBlacklist::OsType GpuBlacklist::GetOsType() { | |
409 #if defined(OS_WIN) | |
410 return kOsWin; | |
411 #elif defined(OS_LINUX) | |
412 return kOsLinux; | |
413 #elif defined(OS_MACOSX) | |
414 return kOsMacosx; | |
415 #else | |
416 return kOsUnknown; | |
417 #endif | |
418 } | |
419 | |
420 void GpuBlacklist::Clear() { | |
421 for (size_t i = 0; i < blacklist_.size(); ++i) | |
422 delete blacklist_[i]; | |
423 blacklist_.clear(); | |
424 } | |
425 | |
OLD | NEW |