Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(103)

Side by Side Diff: chrome/browser/gpu_blacklist.cc

Issue 10908110: Move gpu blacklist to content side. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/gpu_blacklist.h ('k') | chrome/browser/gpu_blacklist_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/command_line.h"
8 #include "base/json/json_reader.h"
9 #include "base/logging.h"
10 #include "base/string_number_conversions.h"
11 #include "base/string_split.h"
12 #include "base/string_util.h"
13 #include "base/sys_info.h"
14 #include "base/version.h"
15 #include "chrome/browser/gpu_util.h"
16 #include "chrome/common/chrome_version_info.h"
17 #include "content/public/browser/gpu_data_manager.h"
18 #include "content/public/common/content_switches.h"
19 #include "content/public/common/gpu_info.h"
20
21 using content::GpuDataManager;
22 using content::GpuFeatureType;
23
24 namespace {
25
26 // Encode a date as Version, where [0] is year, [1] is month, and [2] is day.
27 void GetDateFromString(const std::string& date_string, Version* version) {
28 // TODO(zmo): verify if in Windows registry, driver dates are always in the
29 // format of "mm-dd-yyyy".
30 std::vector<std::string> pieces;
31 base::SplitString(date_string, '-', &pieces);
32 if (pieces.size() != 3) {
33 *version = Version();
34 return;
35 }
36 std::string date_as_version_string = pieces[2];
37 for (size_t i = 0; i < 2; ++i) {
38 date_as_version_string += ".";
39 date_as_version_string += pieces[i];
40 }
41 *version = Version(date_as_version_string);
42 }
43
44 // We assume the input format is major.minor, and we treat major version
45 // as numerical and minor as lexical.
46 // Otherwise we simply return the original string.
47 // For example, if input numerical is 8.103, returned lexical is 8.1.0.3.
48 std::string NumericalToLexical(const std::string& numerical) {
49 std::string lexical;
50 bool valid = true;
51 size_t pos = numerical.find_first_of('.');
52 if (pos != std::string::npos && pos + 1 < numerical.length()) {
53 lexical = numerical.substr(0, pos);
54 for (size_t i = pos + 1; i < numerical.length(); ++i) {
55 if (!IsAsciiDigit(numerical[i])) {
56 valid = false;
57 break;
58 }
59 lexical += '.';
60 lexical += numerical[i];
61 }
62 } else {
63 valid = false;
64 }
65 if (valid)
66 return lexical;
67 return numerical;
68 }
69
70 bool GpuUnmatched(uint32 vendor_id, const std::vector<uint32>& device_id_list,
71 const content::GPUInfo::GPUDevice& gpu) {
72 if (vendor_id == 0)
73 return false;
74 if (vendor_id != gpu.vendor_id)
75 return true;
76 bool device_specified = false;
77 for (size_t i = 0; i < device_id_list.size(); ++i) {
78 if (device_id_list[i] == 0)
79 continue;
80 if (device_id_list[i] == gpu.device_id)
81 return false;
82 device_specified = true;
83 }
84 return device_specified;
85 }
86
87 const char kMultiGpuStyleStringAMDSwitchable[] = "amd_switchable";
88 const char kMultiGpuStyleStringOptimus[] = "optimus";
89
90 const char kMultiGpuCategoryStringPrimary[] = "primary";
91 const char kMultiGpuCategoryStringSecondary[] = "secondary";
92 const char kMultiGpuCategoryStringAny[] = "any";
93
94 const char kVersionStyleStringNumerical[] = "numerical";
95 const char kVersionStyleStringLexical[] = "lexical";
96
97 } // namespace anonymous
98
99 GpuBlacklist::VersionInfo::VersionInfo(
100 const std::string& version_op,
101 const std::string& version_style,
102 const std::string& version_string,
103 const std::string& version_string2)
104 : version_style_(kVersionStyleNumerical) {
105 op_ = StringToNumericOp(version_op);
106 if (op_ == kUnknown || op_ == kAny)
107 return;
108 version_style_ = StringToVersionStyle(version_style);
109 std::string processed_version_string, processed_version_string2;
110 if (version_style_ == kVersionStyleLexical) {
111 processed_version_string = NumericalToLexical(version_string);
112 processed_version_string2 = NumericalToLexical(version_string2);
113 } else {
114 processed_version_string = version_string;
115 processed_version_string2 = version_string2;
116 }
117 version_.reset(new Version(processed_version_string));
118 if (!version_->IsValid()) {
119 op_ = kUnknown;
120 return;
121 }
122 if (op_ == kBetween) {
123 version2_.reset(new Version(processed_version_string2));
124 if (!version2_->IsValid())
125 op_ = kUnknown;
126 }
127 }
128
129 GpuBlacklist::VersionInfo::~VersionInfo() {
130 }
131
132 bool GpuBlacklist::VersionInfo::Contains(const Version& version) const {
133 if (op_ == kUnknown)
134 return false;
135 if (op_ == kAny)
136 return true;
137 if (op_ == kEQ) {
138 // Handles cases where 10.6 is considered as containing 10.6.*.
139 const std::vector<uint16>& components_reference = version_->components();
140 const std::vector<uint16>& components = version.components();
141 for (size_t i = 0; i < components_reference.size(); ++i) {
142 if (i >= components.size() && components_reference[i] != 0)
143 return false;
144 if (components[i] != components_reference[i])
145 return false;
146 }
147 return true;
148 }
149 int relation = version.CompareTo(*version_);
150 if (op_ == kEQ)
151 return (relation == 0);
152 else if (op_ == kLT)
153 return (relation < 0);
154 else if (op_ == kLE)
155 return (relation <= 0);
156 else if (op_ == kGT)
157 return (relation > 0);
158 else if (op_ == kGE)
159 return (relation >= 0);
160 // op_ == kBetween
161 if (relation < 0)
162 return false;
163 return version.CompareTo(*version2_) <= 0;
164 }
165
166 bool GpuBlacklist::VersionInfo::IsValid() const {
167 return (op_ != kUnknown && version_style_ != kVersionStyleUnknown);
168 }
169
170 bool GpuBlacklist::VersionInfo::IsLexical() const {
171 return version_style_ == kVersionStyleLexical;
172 }
173
174 // static
175 GpuBlacklist::VersionInfo::VersionStyle
176 GpuBlacklist::VersionInfo::StringToVersionStyle(
177 const std::string& version_style) {
178 if (version_style.empty() || version_style == kVersionStyleStringNumerical)
179 return kVersionStyleNumerical;
180 if (version_style == kVersionStyleStringLexical)
181 return kVersionStyleLexical;
182 return kVersionStyleUnknown;
183 }
184
185 GpuBlacklist::OsInfo::OsInfo(const std::string& os,
186 const std::string& version_op,
187 const std::string& version_string,
188 const std::string& version_string2) {
189 type_ = StringToOsType(os);
190 if (type_ != kOsUnknown) {
191 version_info_.reset(
192 new VersionInfo(version_op, "", version_string, version_string2));
193 }
194 }
195
196 GpuBlacklist::OsInfo::~OsInfo() {}
197
198 bool GpuBlacklist::OsInfo::Contains(OsType type,
199 const Version& version) const {
200 if (!IsValid())
201 return false;
202 if (type_ != type && type_ != kOsAny)
203 return false;
204 return version_info_->Contains(version);
205 }
206
207 bool GpuBlacklist::OsInfo::IsValid() const {
208 return type_ != kOsUnknown && version_info_->IsValid();
209 }
210
211 GpuBlacklist::OsType GpuBlacklist::OsInfo::type() const {
212 return type_;
213 }
214
215 GpuBlacklist::OsType GpuBlacklist::OsInfo::StringToOsType(
216 const std::string& os) {
217 if (os == "win")
218 return kOsWin;
219 else if (os == "macosx")
220 return kOsMacosx;
221 else if (os == "linux")
222 return kOsLinux;
223 else if (os == "chromeos")
224 return kOsChromeOS;
225 else if (os == "any")
226 return kOsAny;
227 return kOsUnknown;
228 }
229
230 GpuBlacklist::StringInfo::StringInfo(const std::string& string_op,
231 const std::string& string_value) {
232 op_ = StringToOp(string_op);
233 value_ = StringToLowerASCII(string_value);
234 }
235
236 bool GpuBlacklist::StringInfo::Contains(const std::string& value) const {
237 std::string my_value = StringToLowerASCII(value);
238 switch (op_) {
239 case kContains:
240 return strstr(my_value.c_str(), value_.c_str()) != NULL;
241 case kBeginWith:
242 return StartsWithASCII(my_value, value_, false);
243 case kEndWith:
244 return EndsWith(my_value, value_, false);
245 case kEQ:
246 return value_ == my_value;
247 default:
248 return false;
249 }
250 }
251
252 bool GpuBlacklist::StringInfo::IsValid() const {
253 return op_ != kUnknown;
254 }
255
256 GpuBlacklist::StringInfo::Op GpuBlacklist::StringInfo::StringToOp(
257 const std::string& string_op) {
258 if (string_op == "=")
259 return kEQ;
260 else if (string_op == "contains")
261 return kContains;
262 else if (string_op == "beginwith")
263 return kBeginWith;
264 else if (string_op == "endwith")
265 return kEndWith;
266 return kUnknown;
267 }
268
269 GpuBlacklist::FloatInfo::FloatInfo(const std::string& float_op,
270 const std::string& float_value,
271 const std::string& float_value2)
272 : op_(kUnknown),
273 value_(0.f),
274 value2_(0.f) {
275 double dvalue = 0;
276 if (!base::StringToDouble(float_value, &dvalue)) {
277 op_ = kUnknown;
278 return;
279 }
280 value_ = static_cast<float>(dvalue);
281 op_ = StringToNumericOp(float_op);
282 if (op_ == kBetween) {
283 if (!base::StringToDouble(float_value2, &dvalue)) {
284 op_ = kUnknown;
285 return;
286 }
287 value2_ = static_cast<float>(dvalue);
288 }
289 }
290
291 bool GpuBlacklist::FloatInfo::Contains(float value) const {
292 if (op_ == kUnknown)
293 return false;
294 if (op_ == kAny)
295 return true;
296 if (op_ == kEQ)
297 return (value == value_);
298 if (op_ == kLT)
299 return (value < value_);
300 if (op_ == kLE)
301 return (value <= value_);
302 if (op_ == kGT)
303 return (value > value_);
304 if (op_ == kGE)
305 return (value >= value_);
306 DCHECK(op_ == kBetween);
307 return ((value_ <= value && value <= value2_) ||
308 (value2_ <= value && value <= value_));
309 }
310
311 bool GpuBlacklist::FloatInfo::IsValid() const {
312 return op_ != kUnknown;
313 }
314
315 // static
316 GpuBlacklist::ScopedGpuBlacklistEntry
317 GpuBlacklist::GpuBlacklistEntry::GetGpuBlacklistEntryFromValue(
318 const DictionaryValue* value, bool top_level) {
319 DCHECK(value);
320 ScopedGpuBlacklistEntry entry(new GpuBlacklistEntry());
321
322 size_t dictionary_entry_count = 0;
323
324 if (top_level) {
325 uint32 id;
326 if (!value->GetInteger("id", reinterpret_cast<int*>(&id)) ||
327 !entry->SetId(id)) {
328 LOG(WARNING) << "Malformed id entry " << entry->id();
329 return NULL;
330 }
331 dictionary_entry_count++;
332
333 bool disabled;
334 if (value->GetBoolean("disabled", &disabled)) {
335 entry->SetDisabled(disabled);
336 dictionary_entry_count++;
337 }
338 }
339
340 std::string description;
341 if (value->GetString("description", &description)) {
342 entry->description_ = description;
343 dictionary_entry_count++;
344 } else {
345 entry->description_ = "The GPU is unavailable for an unexplained reason.";
346 }
347
348 const ListValue* cr_bugs;
349 if (value->GetList("cr_bugs", &cr_bugs)) {
350 for (size_t i = 0; i < cr_bugs->GetSize(); ++i) {
351 int bug_id;
352 if (cr_bugs->GetInteger(i, &bug_id)) {
353 entry->cr_bugs_.push_back(bug_id);
354 } else {
355 LOG(WARNING) << "Malformed cr_bugs entry " << entry->id();
356 return NULL;
357 }
358 }
359 dictionary_entry_count++;
360 }
361
362 const ListValue* webkit_bugs;
363 if (value->GetList("webkit_bugs", &webkit_bugs)) {
364 for (size_t i = 0; i < webkit_bugs->GetSize(); ++i) {
365 int bug_id;
366 if (webkit_bugs->GetInteger(i, &bug_id)) {
367 entry->webkit_bugs_.push_back(bug_id);
368 } else {
369 LOG(WARNING) << "Malformed webkit_bugs entry " << entry->id();
370 return NULL;
371 }
372 }
373 dictionary_entry_count++;
374 }
375
376 const DictionaryValue* os_value = NULL;
377 if (value->GetDictionary("os", &os_value)) {
378 std::string os_type;
379 std::string os_version_op = "any";
380 std::string os_version_string;
381 std::string os_version_string2;
382 os_value->GetString("type", &os_type);
383 const DictionaryValue* os_version_value = NULL;
384 if (os_value->GetDictionary("version", &os_version_value)) {
385 os_version_value->GetString("op", &os_version_op);
386 os_version_value->GetString("number", &os_version_string);
387 os_version_value->GetString("number2", &os_version_string2);
388 }
389 if (!entry->SetOsInfo(os_type, os_version_op, os_version_string,
390 os_version_string2)) {
391 LOG(WARNING) << "Malformed os entry " << entry->id();
392 return NULL;
393 }
394 dictionary_entry_count++;
395 }
396
397 std::string vendor_id;
398 if (value->GetString("vendor_id", &vendor_id)) {
399 if (!entry->SetVendorId(vendor_id)) {
400 LOG(WARNING) << "Malformed vendor_id entry " << entry->id();
401 return NULL;
402 }
403 dictionary_entry_count++;
404 }
405
406 const ListValue* device_id_list;
407 if (value->GetList("device_id", &device_id_list)) {
408 for (size_t i = 0; i < device_id_list->GetSize(); ++i) {
409 std::string device_id;
410 if (!device_id_list->GetString(i, &device_id) ||
411 !entry->AddDeviceId(device_id)) {
412 LOG(WARNING) << "Malformed device_id entry " << entry->id();
413 return NULL;
414 }
415 }
416 dictionary_entry_count++;
417 }
418
419 std::string multi_gpu_style;
420 if (value->GetString("multi_gpu_style", &multi_gpu_style)) {
421 if (!entry->SetMultiGpuStyle(multi_gpu_style)) {
422 LOG(WARNING) << "Malformed multi_gpu_style entry " << entry->id();
423 return NULL;
424 }
425 dictionary_entry_count++;
426 }
427
428 std::string multi_gpu_category;
429 if (value->GetString("multi_gpu_category", &multi_gpu_category)) {
430 if (!entry->SetMultiGpuCategory(multi_gpu_category)) {
431 LOG(WARNING) << "Malformed multi_gpu_category entry " << entry->id();
432 return NULL;
433 }
434 dictionary_entry_count++;
435 }
436
437 const DictionaryValue* driver_vendor_value = NULL;
438 if (value->GetDictionary("driver_vendor", &driver_vendor_value)) {
439 std::string vendor_op;
440 std::string vendor_value;
441 driver_vendor_value->GetString("op", &vendor_op);
442 driver_vendor_value->GetString("value", &vendor_value);
443 if (!entry->SetDriverVendorInfo(vendor_op, vendor_value)) {
444 LOG(WARNING) << "Malformed driver_vendor entry " << entry->id();
445 return NULL;
446 }
447 dictionary_entry_count++;
448 }
449
450 const DictionaryValue* driver_version_value = NULL;
451 if (value->GetDictionary("driver_version", &driver_version_value)) {
452 std::string driver_version_op = "any";
453 std::string driver_version_style;
454 std::string driver_version_string;
455 std::string driver_version_string2;
456 driver_version_value->GetString("op", &driver_version_op);
457 driver_version_value->GetString("style", &driver_version_style);
458 driver_version_value->GetString("number", &driver_version_string);
459 driver_version_value->GetString("number2", &driver_version_string2);
460 if (!entry->SetDriverVersionInfo(driver_version_op,
461 driver_version_style,
462 driver_version_string,
463 driver_version_string2)) {
464 LOG(WARNING) << "Malformed driver_version entry " << entry->id();
465 return NULL;
466 }
467 dictionary_entry_count++;
468 }
469
470 const DictionaryValue* driver_date_value = NULL;
471 if (value->GetDictionary("driver_date", &driver_date_value)) {
472 std::string driver_date_op = "any";
473 std::string driver_date_string;
474 std::string driver_date_string2;
475 driver_date_value->GetString("op", &driver_date_op);
476 driver_date_value->GetString("number", &driver_date_string);
477 driver_date_value->GetString("number2", &driver_date_string2);
478 if (!entry->SetDriverDateInfo(driver_date_op, driver_date_string,
479 driver_date_string2)) {
480 LOG(WARNING) << "Malformed driver_date entry " << entry->id();
481 return NULL;
482 }
483 dictionary_entry_count++;
484 }
485
486 const DictionaryValue* gl_vendor_value = NULL;
487 if (value->GetDictionary("gl_vendor", &gl_vendor_value)) {
488 std::string vendor_op;
489 std::string vendor_value;
490 gl_vendor_value->GetString("op", &vendor_op);
491 gl_vendor_value->GetString("value", &vendor_value);
492 if (!entry->SetGLVendorInfo(vendor_op, vendor_value)) {
493 LOG(WARNING) << "Malformed gl_vendor entry " << entry->id();
494 return NULL;
495 }
496 dictionary_entry_count++;
497 }
498
499 const DictionaryValue* gl_renderer_value = NULL;
500 if (value->GetDictionary("gl_renderer", &gl_renderer_value)) {
501 std::string renderer_op;
502 std::string renderer_value;
503 gl_renderer_value->GetString("op", &renderer_op);
504 gl_renderer_value->GetString("value", &renderer_value);
505 if (!entry->SetGLRendererInfo(renderer_op, renderer_value)) {
506 LOG(WARNING) << "Malformed gl_renderer entry " << entry->id();
507 return NULL;
508 }
509 dictionary_entry_count++;
510 }
511
512 const DictionaryValue* perf_graphics_value = NULL;
513 if (value->GetDictionary("perf_graphics", &perf_graphics_value)) {
514 std::string op;
515 std::string float_value;
516 std::string float_value2;
517 perf_graphics_value->GetString("op", &op);
518 perf_graphics_value->GetString("value", &float_value);
519 perf_graphics_value->GetString("value2", &float_value2);
520 if (!entry->SetPerfGraphicsInfo(op, float_value, float_value2)) {
521 LOG(WARNING) << "Malformed perf_graphics entry " << entry->id();
522 return NULL;
523 }
524 dictionary_entry_count++;
525 }
526
527 const DictionaryValue* perf_gaming_value = NULL;
528 if (value->GetDictionary("perf_gaming", &perf_gaming_value)) {
529 std::string op;
530 std::string float_value;
531 std::string float_value2;
532 perf_gaming_value->GetString("op", &op);
533 perf_gaming_value->GetString("value", &float_value);
534 perf_gaming_value->GetString("value2", &float_value2);
535 if (!entry->SetPerfGamingInfo(op, float_value, float_value2)) {
536 LOG(WARNING) << "Malformed perf_gaming entry " << entry->id();
537 return NULL;
538 }
539 dictionary_entry_count++;
540 }
541
542 const DictionaryValue* perf_overall_value = NULL;
543 if (value->GetDictionary("perf_overall", &perf_overall_value)) {
544 std::string op;
545 std::string float_value;
546 std::string float_value2;
547 perf_overall_value->GetString("op", &op);
548 perf_overall_value->GetString("value", &float_value);
549 perf_overall_value->GetString("value2", &float_value2);
550 if (!entry->SetPerfOverallInfo(op, float_value, float_value2)) {
551 LOG(WARNING) << "Malformed perf_overall entry " << entry->id();
552 return NULL;
553 }
554 dictionary_entry_count++;
555 }
556
557 if (top_level) {
558 const ListValue* blacklist_value = NULL;
559 if (!value->GetList("blacklist", &blacklist_value)) {
560 LOG(WARNING) << "Malformed blacklist entry " << entry->id();
561 return NULL;
562 }
563 std::vector<std::string> blacklist;
564 for (size_t i = 0; i < blacklist_value->GetSize(); ++i) {
565 std::string feature;
566 if (blacklist_value->GetString(i, &feature)) {
567 blacklist.push_back(feature);
568 } else {
569 LOG(WARNING) << "Malformed blacklist entry " << entry->id();
570 return NULL;
571 }
572 }
573 if (!entry->SetBlacklistedFeatures(blacklist)) {
574 LOG(WARNING) << "Malformed blacklist entry " << entry->id();
575 return NULL;
576 }
577 dictionary_entry_count++;
578 }
579
580 if (top_level) {
581 const ListValue* exception_list_value = NULL;
582 if (value->GetList("exceptions", &exception_list_value)) {
583 for (size_t i = 0; i < exception_list_value->GetSize(); ++i) {
584 const DictionaryValue* exception_value = NULL;
585 if (!exception_list_value->GetDictionary(i, &exception_value)) {
586 LOG(WARNING) << "Malformed exceptions entry " << entry->id();
587 return NULL;
588 }
589 ScopedGpuBlacklistEntry exception(
590 GetGpuBlacklistEntryFromValue(exception_value, false));
591 if (exception == NULL) {
592 LOG(WARNING) << "Malformed exceptions entry " << entry->id();
593 return NULL;
594 }
595 if (exception->contains_unknown_fields_) {
596 LOG(WARNING) << "Exception with unknown fields " << entry->id();
597 entry->contains_unknown_fields_ = true;
598 } else {
599 entry->AddException(exception);
600 }
601 }
602 dictionary_entry_count++;
603 }
604
605 const DictionaryValue* browser_version_value = NULL;
606 // browser_version is processed in LoadGpuBlacklist().
607 if (value->GetDictionary("browser_version", &browser_version_value))
608 dictionary_entry_count++;
609 }
610
611 if (value->size() != dictionary_entry_count) {
612 LOG(WARNING) << "Entry with unknown fields " << entry->id();
613 entry->contains_unknown_fields_ = true;
614 }
615 return entry;
616 }
617
618 GpuBlacklist::GpuBlacklistEntry::GpuBlacklistEntry()
619 : id_(0),
620 disabled_(false),
621 vendor_id_(0),
622 multi_gpu_style_(kMultiGpuStyleNone),
623 multi_gpu_category_(kMultiGpuCategoryPrimary),
624 feature_type_(content::GPU_FEATURE_TYPE_UNKNOWN),
625 contains_unknown_fields_(false),
626 contains_unknown_features_(false) {
627 }
628
629 GpuBlacklist::GpuBlacklistEntry::~GpuBlacklistEntry() { }
630
631 bool GpuBlacklist::GpuBlacklistEntry::SetId(uint32 id) {
632 if (id != 0) {
633 id_ = id;
634 return true;
635 }
636 return false;
637 }
638
639 void GpuBlacklist::GpuBlacklistEntry::SetDisabled(bool disabled) {
640 disabled_ = disabled;
641 }
642
643 bool GpuBlacklist::GpuBlacklistEntry::SetOsInfo(
644 const std::string& os,
645 const std::string& version_op,
646 const std::string& version_string,
647 const std::string& version_string2) {
648 os_info_.reset(new OsInfo(os, version_op, version_string, version_string2));
649 return os_info_->IsValid();
650 }
651
652 bool GpuBlacklist::GpuBlacklistEntry::SetVendorId(
653 const std::string& vendor_id_string) {
654 vendor_id_ = 0;
655 return base::HexStringToInt(vendor_id_string,
656 reinterpret_cast<int*>(&vendor_id_));
657 }
658
659 bool GpuBlacklist::GpuBlacklistEntry::AddDeviceId(
660 const std::string& device_id_string) {
661 uint32 device_id = 0;
662 if (base::HexStringToInt(device_id_string,
663 reinterpret_cast<int*>(&device_id))) {
664 device_id_list_.push_back(device_id);
665 return true;
666 }
667 return false;
668 }
669
670 bool GpuBlacklist::GpuBlacklistEntry::SetMultiGpuStyle(
671 const std::string& multi_gpu_style_string) {
672 MultiGpuStyle style = StringToMultiGpuStyle(multi_gpu_style_string);
673 if (style == kMultiGpuStyleNone)
674 return false;
675 multi_gpu_style_ = style;
676 return true;
677 }
678
679 bool GpuBlacklist::GpuBlacklistEntry::SetMultiGpuCategory(
680 const std::string& multi_gpu_category_string) {
681 MultiGpuCategory category =
682 StringToMultiGpuCategory(multi_gpu_category_string);
683 if (category == kMultiGpuCategoryNone)
684 return false;
685 multi_gpu_category_ = category;
686 return true;
687 }
688
689 bool GpuBlacklist::GpuBlacklistEntry::SetDriverVendorInfo(
690 const std::string& vendor_op,
691 const std::string& vendor_value) {
692 driver_vendor_info_.reset(
693 new StringInfo(vendor_op, vendor_value));
694 return driver_vendor_info_->IsValid();
695 }
696
697 bool GpuBlacklist::GpuBlacklistEntry::SetDriverVersionInfo(
698 const std::string& version_op,
699 const std::string& version_style,
700 const std::string& version_string,
701 const std::string& version_string2) {
702 driver_version_info_.reset(new VersionInfo(
703 version_op, version_style, version_string, version_string2));
704 return driver_version_info_->IsValid();
705 }
706
707 bool GpuBlacklist::GpuBlacklistEntry::SetDriverDateInfo(
708 const std::string& date_op,
709 const std::string& date_string,
710 const std::string& date_string2) {
711 driver_date_info_.reset(
712 new VersionInfo(date_op, "", date_string, date_string2));
713 return driver_date_info_->IsValid();
714 }
715
716 bool GpuBlacklist::GpuBlacklistEntry::SetGLVendorInfo(
717 const std::string& vendor_op,
718 const std::string& vendor_value) {
719 gl_vendor_info_.reset(
720 new StringInfo(vendor_op, vendor_value));
721 return gl_vendor_info_->IsValid();
722 }
723
724 bool GpuBlacklist::GpuBlacklistEntry::SetGLRendererInfo(
725 const std::string& renderer_op,
726 const std::string& renderer_value) {
727 gl_renderer_info_.reset(
728 new StringInfo(renderer_op, renderer_value));
729 return gl_renderer_info_->IsValid();
730 }
731
732 bool GpuBlacklist::GpuBlacklistEntry::SetPerfGraphicsInfo(
733 const std::string& op,
734 const std::string& float_string,
735 const std::string& float_string2) {
736 perf_graphics_info_.reset(
737 new FloatInfo(op, float_string, float_string2));
738 return perf_graphics_info_->IsValid();
739 }
740
741 bool GpuBlacklist::GpuBlacklistEntry::SetPerfGamingInfo(
742 const std::string& op,
743 const std::string& float_string,
744 const std::string& float_string2) {
745 perf_gaming_info_.reset(
746 new FloatInfo(op, float_string, float_string2));
747 return perf_gaming_info_->IsValid();
748 }
749
750 bool GpuBlacklist::GpuBlacklistEntry::SetPerfOverallInfo(
751 const std::string& op,
752 const std::string& float_string,
753 const std::string& float_string2) {
754 perf_overall_info_.reset(
755 new FloatInfo(op, float_string, float_string2));
756 return perf_overall_info_->IsValid();
757 }
758
759 bool GpuBlacklist::GpuBlacklistEntry::SetBlacklistedFeatures(
760 const std::vector<std::string>& blacklisted_features) {
761 size_t size = blacklisted_features.size();
762 if (size == 0)
763 return false;
764 int feature_type = content::GPU_FEATURE_TYPE_UNKNOWN;
765 for (size_t i = 0; i < size; ++i) {
766 GpuFeatureType type =
767 gpu_util::StringToGpuFeatureType(blacklisted_features[i]);
768 switch (type) {
769 case content::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS:
770 case content::GPU_FEATURE_TYPE_ACCELERATED_COMPOSITING:
771 case content::GPU_FEATURE_TYPE_WEBGL:
772 case content::GPU_FEATURE_TYPE_MULTISAMPLING:
773 case content::GPU_FEATURE_TYPE_FLASH3D:
774 case content::GPU_FEATURE_TYPE_FLASH_STAGE3D:
775 case content::GPU_FEATURE_TYPE_TEXTURE_SHARING:
776 case content::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_DECODE:
777 case content::GPU_FEATURE_TYPE_ALL:
778 feature_type |= type;
779 break;
780 case content::GPU_FEATURE_TYPE_UNKNOWN:
781 contains_unknown_features_ = true;
782 break;
783 }
784 }
785 feature_type_ = static_cast<GpuFeatureType>(feature_type);
786 return true;
787 }
788
789 void GpuBlacklist::GpuBlacklistEntry::AddException(
790 ScopedGpuBlacklistEntry exception) {
791 exceptions_.push_back(exception);
792 }
793
794 // static
795 GpuBlacklist::GpuBlacklistEntry::MultiGpuStyle
796 GpuBlacklist::GpuBlacklistEntry::StringToMultiGpuStyle(
797 const std::string& style) {
798 if (style == kMultiGpuStyleStringOptimus)
799 return kMultiGpuStyleOptimus;
800 if (style == kMultiGpuStyleStringAMDSwitchable)
801 return kMultiGpuStyleAMDSwitchable;
802 return kMultiGpuStyleNone;
803 }
804
805 // static
806 GpuBlacklist::GpuBlacklistEntry::MultiGpuCategory
807 GpuBlacklist::GpuBlacklistEntry::StringToMultiGpuCategory(
808 const std::string& category) {
809 if (category == kMultiGpuCategoryStringPrimary)
810 return kMultiGpuCategoryPrimary;
811 if (category == kMultiGpuCategoryStringSecondary)
812 return kMultiGpuCategorySecondary;
813 if (category == kMultiGpuCategoryStringAny)
814 return kMultiGpuCategoryAny;
815 return kMultiGpuCategoryNone;
816 }
817
818 bool GpuBlacklist::GpuBlacklistEntry::Contains(
819 OsType os_type, const Version& os_version,
820 const content::GPUInfo& gpu_info) const {
821 DCHECK(os_type != kOsAny);
822 if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version))
823 return false;
824 bool is_not_primary_gpu =
825 GpuUnmatched(vendor_id_, device_id_list_, gpu_info.gpu);
826 bool is_not_secondary_gpu = true;
827 for (size_t i = 0; i < gpu_info.secondary_gpus.size(); ++i) {
828 is_not_secondary_gpu = is_not_secondary_gpu &&
829 GpuUnmatched(vendor_id_, device_id_list_, gpu_info.secondary_gpus[i]);
830 }
831 switch (multi_gpu_category_) {
832 case kMultiGpuCategoryPrimary:
833 if (is_not_primary_gpu)
834 return false;
835 break;
836 case kMultiGpuCategorySecondary:
837 if (is_not_secondary_gpu)
838 return false;
839 break;
840 case kMultiGpuCategoryAny:
841 if (is_not_primary_gpu && is_not_secondary_gpu)
842 return false;
843 break;
844 default:
845 break;
846 }
847 switch (multi_gpu_style_) {
848 case kMultiGpuStyleOptimus:
849 if (!gpu_info.optimus)
850 return false;
851 break;
852 case kMultiGpuStyleAMDSwitchable:
853 if (!gpu_info.amd_switchable)
854 return false;
855 break;
856 default:
857 break;
858 }
859 if (driver_vendor_info_.get() != NULL &&
860 !driver_vendor_info_->Contains(gpu_info.driver_vendor))
861 return false;
862 if (driver_version_info_.get() != NULL) {
863 std::string processed_driver_version;
864 if (driver_version_info_->IsLexical())
865 processed_driver_version = NumericalToLexical(gpu_info.driver_version);
866 else
867 processed_driver_version = gpu_info.driver_version;
868 Version driver_version(processed_driver_version);
869 if (!driver_version.IsValid() ||
870 !driver_version_info_->Contains(driver_version))
871 return false;
872 }
873 if (driver_date_info_.get() != NULL) {
874 Version driver_date;
875 GetDateFromString(gpu_info.driver_date, &driver_date);
876 if (!driver_date.IsValid() || !driver_date_info_->Contains(driver_date))
877 return false;
878 }
879 if (gl_vendor_info_.get() != NULL &&
880 !gl_vendor_info_->Contains(gpu_info.gl_vendor))
881 return false;
882 if (gl_renderer_info_.get() != NULL &&
883 !gl_renderer_info_->Contains(gpu_info.gl_renderer))
884 return false;
885 if (perf_graphics_info_.get() != NULL &&
886 (gpu_info.performance_stats.graphics == 0.0 ||
887 !perf_graphics_info_->Contains(gpu_info.performance_stats.graphics)))
888 return false;
889 if (perf_gaming_info_.get() != NULL &&
890 (gpu_info.performance_stats.gaming == 0.0 ||
891 !perf_gaming_info_->Contains(gpu_info.performance_stats.gaming)))
892 return false;
893 if (perf_overall_info_.get() != NULL &&
894 (gpu_info.performance_stats.overall == 0.0 ||
895 !perf_overall_info_->Contains(gpu_info.performance_stats.overall)))
896 return false;
897 for (size_t i = 0; i < exceptions_.size(); ++i) {
898 if (exceptions_[i]->Contains(os_type, os_version, gpu_info))
899 return false;
900 }
901 return true;
902 }
903
904 GpuBlacklist::OsType GpuBlacklist::GpuBlacklistEntry::GetOsType() const {
905 if (os_info_.get() == NULL)
906 return kOsAny;
907 return os_info_->type();
908 }
909
910 uint32 GpuBlacklist::GpuBlacklistEntry::id() const {
911 return id_;
912 }
913
914 bool GpuBlacklist::GpuBlacklistEntry::disabled() const {
915 return disabled_;
916 }
917
918 GpuFeatureType GpuBlacklist::GpuBlacklistEntry::GetGpuFeatureType() const {
919 return feature_type_;
920 }
921
922 // static
923 GpuBlacklist* GpuBlacklist::GetInstance() {
924 return Singleton<GpuBlacklist>::get();
925 }
926
927 GpuBlacklist::GpuBlacklist()
928 : max_entry_id_(0),
929 contains_unknown_fields_(false) {
930 GpuDataManager::GetInstance()->AddObserver(this);
931 }
932
933 GpuBlacklist::~GpuBlacklist() {
934 Clear();
935 GpuDataManager::GetInstance()->RemoveObserver(this);
936 }
937
938 bool GpuBlacklist::LoadGpuBlacklist(
939 const std::string& json_context, GpuBlacklist::OsFilter os_filter) {
940 chrome::VersionInfo chrome_version_info;
941 std::string chrome_version_string =
942 chrome_version_info.is_valid() ? chrome_version_info.Version() : "0";
943 return LoadGpuBlacklist(chrome_version_string, json_context, os_filter);
944 }
945
946 bool GpuBlacklist::LoadGpuBlacklist(
947 const std::string& browser_version_string,
948 const std::string& json_context,
949 GpuBlacklist::OsFilter os_filter) {
950 browser_version_.reset(new Version(browser_version_string));
951 DCHECK(browser_version_->IsValid());
952
953 scoped_ptr<Value> root;
954 root.reset(base::JSONReader::Read(json_context));
955 if (root.get() == NULL || !root->IsType(Value::TYPE_DICTIONARY))
956 return false;
957
958 DictionaryValue* root_dictionary = static_cast<DictionaryValue*>(root.get());
959 DCHECK(root_dictionary);
960 return LoadGpuBlacklist(*root_dictionary, os_filter);
961 }
962
963 bool GpuBlacklist::LoadGpuBlacklist(
964 const DictionaryValue& parsed_json, GpuBlacklist::OsFilter os_filter) {
965 std::vector<ScopedGpuBlacklistEntry> entries;
966
967 std::string version_string;
968 parsed_json.GetString("version", &version_string);
969 version_.reset(new Version(version_string));
970 if (!version_->IsValid())
971 return false;
972
973 const ListValue* list = NULL;
974 if (!parsed_json.GetList("entries", &list))
975 return false;
976
977 uint32 max_entry_id = 0;
978 bool contains_unknown_fields = false;
979 for (size_t i = 0; i < list->GetSize(); ++i) {
980 const DictionaryValue* list_item = NULL;
981 bool valid = list->GetDictionary(i, &list_item);
982 if (!valid || list_item == NULL)
983 return false;
984 // Check browser version compatibility: if the entry is not for the
985 // current browser version, don't process it.
986 BrowserVersionSupport browser_version_support =
987 IsEntrySupportedByCurrentBrowserVersion(list_item);
988 if (browser_version_support == kMalformed)
989 return false;
990 if (browser_version_support == kUnsupported)
991 continue;
992 DCHECK(browser_version_support == kSupported);
993 ScopedGpuBlacklistEntry entry(
994 GpuBlacklistEntry::GetGpuBlacklistEntryFromValue(list_item, true));
995 if (entry == NULL)
996 return false;
997 if (entry->id() > max_entry_id)
998 max_entry_id = entry->id();
999 // If an unknown field is encountered, skip the entry; if an unknown
1000 // feature is encountered, ignore the feature, but keep the entry.
1001 if (entry->contains_unknown_fields()) {
1002 contains_unknown_fields = true;
1003 continue;
1004 }
1005 if (entry->contains_unknown_features())
1006 contains_unknown_fields = true;
1007 entries.push_back(entry);
1008 }
1009
1010 Clear();
1011 OsType my_os = GetOsType();
1012 for (size_t i = 0; i < entries.size(); ++i) {
1013 OsType entry_os = entries[i]->GetOsType();
1014 if (os_filter == GpuBlacklist::kAllOs ||
1015 entry_os == kOsAny || entry_os == my_os)
1016 blacklist_.push_back(entries[i]);
1017 }
1018 max_entry_id_ = max_entry_id;
1019 contains_unknown_fields_ = contains_unknown_fields;
1020 return true;
1021 }
1022
1023 GpuFeatureType GpuBlacklist::DetermineGpuFeatureType(
1024 GpuBlacklist::OsType os,
1025 Version* os_version,
1026 const content::GPUInfo& gpu_info) {
1027 active_entries_.clear();
1028 int type = 0;
1029
1030 if (os == kOsAny)
1031 os = GetOsType();
1032 scoped_ptr<Version> my_os_version;
1033 if (os_version == NULL) {
1034 std::string version_string = base::SysInfo::OperatingSystemVersion();
1035 size_t pos = version_string.find_first_not_of("0123456789.");
1036 if (pos != std::string::npos)
1037 version_string = version_string.substr(0, pos);
1038 my_os_version.reset(new Version(version_string));
1039 os_version = my_os_version.get();
1040 }
1041 DCHECK(os_version != NULL);
1042
1043 for (size_t i = 0; i < blacklist_.size(); ++i) {
1044 if (blacklist_[i]->Contains(os, *os_version, gpu_info)) {
1045 if (!blacklist_[i]->disabled())
1046 type |= blacklist_[i]->GetGpuFeatureType();
1047 active_entries_.push_back(blacklist_[i]);
1048 }
1049 }
1050 return static_cast<GpuFeatureType>(type);
1051 }
1052
1053 void GpuBlacklist::UpdateGpuDataManager() {
1054 content::GpuFeatureType feature_type = DetermineGpuFeatureType(
1055 GpuBlacklist::kOsAny, NULL, GpuDataManager::GetInstance()->GetGPUInfo());
1056 GpuDataManager::GetInstance()->SetPreliminaryBlacklistedFeatures(
1057 feature_type);
1058 gpu_util::UpdateStats();
1059 }
1060
1061 void GpuBlacklist::GetGpuFeatureTypeEntries(
1062 content::GpuFeatureType feature,
1063 std::vector<uint32>& entry_ids,
1064 bool disabled) const {
1065 entry_ids.clear();
1066 for (size_t i = 0; i < active_entries_.size(); ++i) {
1067 if (((feature & active_entries_[i]->GetGpuFeatureType()) != 0) &&
1068 disabled == active_entries_[i]->disabled())
1069 entry_ids.push_back(active_entries_[i]->id());
1070 }
1071 }
1072
1073 void GpuBlacklist::GetBlacklistReasons(ListValue* problem_list) const {
1074 DCHECK(problem_list);
1075 for (size_t i = 0; i < active_entries_.size(); ++i) {
1076 GpuBlacklistEntry* entry = active_entries_[i];
1077 if (entry->disabled())
1078 continue;
1079 DictionaryValue* problem = new DictionaryValue();
1080
1081 problem->SetString("description", entry->description());
1082
1083 ListValue* cr_bugs = new ListValue();
1084 for (size_t j = 0; j < entry->cr_bugs().size(); ++j)
1085 cr_bugs->Append(Value::CreateIntegerValue(entry->cr_bugs()[j]));
1086 problem->Set("crBugs", cr_bugs);
1087
1088 ListValue* webkit_bugs = new ListValue();
1089 for (size_t j = 0; j < entry->webkit_bugs().size(); ++j) {
1090 webkit_bugs->Append(Value::CreateIntegerValue(
1091 entry->webkit_bugs()[j]));
1092 }
1093 problem->Set("webkitBugs", webkit_bugs);
1094
1095 problem_list->Append(problem);
1096 }
1097 }
1098
1099 size_t GpuBlacklist::num_entries() const {
1100 return blacklist_.size();
1101 }
1102
1103 uint32 GpuBlacklist::max_entry_id() const {
1104 return max_entry_id_;
1105 }
1106
1107 std::string GpuBlacklist::GetVersion() const {
1108 if (version_.get() == NULL)
1109 return std::string();
1110 const std::vector<uint16>& components_reference = version_->components();
1111 if (components_reference.size() != 2)
1112 return std::string();
1113
1114 std::string version_string =
1115 base::UintToString(static_cast<unsigned>(components_reference[0])) +
1116 "." +
1117 base::UintToString(static_cast<unsigned>(components_reference[1]));
1118 return version_string;
1119 }
1120
1121 GpuBlacklist::OsType GpuBlacklist::GetOsType() {
1122 #if defined(OS_CHROMEOS)
1123 return kOsChromeOS;
1124 #elif defined(OS_WIN)
1125 return kOsWin;
1126 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
1127 return kOsLinux;
1128 #elif defined(OS_MACOSX)
1129 return kOsMacosx;
1130 #else
1131 return kOsUnknown;
1132 #endif
1133 }
1134
1135 void GpuBlacklist::Clear() {
1136 blacklist_.clear();
1137 active_entries_.clear();
1138 max_entry_id_ = 0;
1139 contains_unknown_fields_ = false;
1140 }
1141
1142 GpuBlacklist::BrowserVersionSupport
1143 GpuBlacklist::IsEntrySupportedByCurrentBrowserVersion(
1144 const DictionaryValue* value) {
1145 DCHECK(value);
1146 const DictionaryValue* browser_version_value = NULL;
1147 if (value->GetDictionary("browser_version", &browser_version_value)) {
1148 std::string version_op = "any";
1149 std::string version_string;
1150 std::string version_string2;
1151 browser_version_value->GetString("op", &version_op);
1152 browser_version_value->GetString("number", &version_string);
1153 browser_version_value->GetString("number2", &version_string2);
1154 scoped_ptr<VersionInfo> browser_version_info;
1155 browser_version_info.reset(
1156 new VersionInfo(version_op, "", version_string, version_string2));
1157 if (!browser_version_info->IsValid())
1158 return kMalformed;
1159 if (browser_version_info->Contains(*browser_version_))
1160 return kSupported;
1161 return kUnsupported;
1162 }
1163 return kSupported;
1164 }
1165
1166 void GpuBlacklist::OnGpuInfoUpdate() {
1167 UpdateGpuDataManager();
1168 }
1169
1170 // static
1171 GpuBlacklist::NumericOp GpuBlacklist::StringToNumericOp(
1172 const std::string& op) {
1173 if (op == "=")
1174 return kEQ;
1175 if (op == "<")
1176 return kLT;
1177 if (op == "<=")
1178 return kLE;
1179 if (op == ">")
1180 return kGT;
1181 if (op == ">=")
1182 return kGE;
1183 if (op == "any")
1184 return kAny;
1185 if (op == "between")
1186 return kBetween;
1187 return kUnknown;
1188 }
OLDNEW
« no previous file with comments | « chrome/browser/gpu_blacklist.h ('k') | chrome/browser/gpu_blacklist_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698