1 // Copyright (c) 2013 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.
5 #include "gpu/config/gpu_control_list.h"
8 #include "base/json/json_reader.h"
9 #include "base/logging.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_util.h"
13 #include "base/sys_info.h"
14 #include "gpu/config/gpu_info.h"
15 #include "gpu/config/gpu_util.h"
20 // Break a version string into segments. Return true if each segment is
22 bool ProcessVersionString(const std::string
& version_string
,
24 std::vector
<std::string
>* version
) {
26 base::SplitString(version_string
, splitter
, version
);
27 if (version
->size() == 0)
29 // If the splitter is '-', we assume it's a date with format "mm-dd-yyyy";
30 // we split it into the order of "yyyy", "mm", "dd".
31 if (splitter
== '-') {
32 std::string year
= (*version
)[version
->size() - 1];
33 for (int i
= version
->size() - 1; i
> 0; --i
) {
34 (*version
)[i
] = (*version
)[i
- 1];
38 for (size_t i
= 0; i
< version
->size(); ++i
) {
40 if (!base::StringToUint((*version
)[i
], &num
))
46 // Compare two number strings using numerical ordering.
47 // Return 0 if number = number_ref,
48 // 1 if number > number_ref,
49 // -1 if number < number_ref.
50 int CompareNumericalNumberStrings(
51 const std::string
& number
, const std::string
& number_ref
) {
54 bool valid
= base::StringToUint(number
, &value1
);
56 valid
= base::StringToUint(number_ref
, &value2
);
65 // Compare two number strings using lexical ordering.
66 // Return 0 if number = number_ref,
67 // 1 if number > number_ref,
68 // -1 if number < number_ref.
69 // We only compare as many digits as number_ref contains.
70 // If number_ref is xxx, it's considered as xxx*
71 // For example: CompareLexicalNumberStrings("121", "12") returns 0,
72 // CompareLexicalNumberStrings("12", "121") returns -1.
73 int CompareLexicalNumberStrings(
74 const std::string
& number
, const std::string
& number_ref
) {
75 for (size_t i
= 0; i
< number_ref
.length(); ++i
) {
77 if (i
< number
.length())
78 value1
= number
[i
] - '0';
79 unsigned value2
= number_ref
[i
] - '0';
88 bool GpuUnmatched(uint32 vendor_id
, const std::vector
<uint32
>& device_id_list
,
89 const GPUInfo::GPUDevice
& gpu
) {
92 if (vendor_id
!= gpu
.vendor_id
)
94 bool device_specified
= false;
95 for (size_t i
= 0; i
< device_id_list
.size(); ++i
) {
96 if (device_id_list
[i
] == 0)
98 if (device_id_list
[i
] == gpu
.device_id
)
100 device_specified
= true;
102 return device_specified
;
105 const char kMultiGpuStyleStringAMDSwitchable
[] = "amd_switchable";
106 const char kMultiGpuStyleStringOptimus
[] = "optimus";
108 const char kMultiGpuCategoryStringPrimary
[] = "primary";
109 const char kMultiGpuCategoryStringSecondary
[] = "secondary";
110 const char kMultiGpuCategoryStringAny
[] = "any";
112 const char kVersionStyleStringNumerical
[] = "numerical";
113 const char kVersionStyleStringLexical
[] = "lexical";
115 const char kOp
[] = "op";
117 } // namespace anonymous
119 GpuControlList::VersionInfo::VersionInfo(
120 const std::string
& version_op
,
121 const std::string
& version_style
,
122 const std::string
& version_string
,
123 const std::string
& version_string2
)
124 : version_style_(kVersionStyleNumerical
) {
125 op_
= StringToNumericOp(version_op
);
126 if (op_
== kUnknown
|| op_
== kAny
)
128 version_style_
= StringToVersionStyle(version_style
);
129 if (!ProcessVersionString(version_string
, '.', &version_
)) {
133 if (op_
== kBetween
) {
134 if (!ProcessVersionString(version_string2
, '.', &version2_
))
139 GpuControlList::VersionInfo::~VersionInfo() {
142 bool GpuControlList::VersionInfo::Contains(
143 const std::string
& version_string
) const {
144 return Contains(version_string
, '.');
147 bool GpuControlList::VersionInfo::Contains(
148 const std::string
& version_string
, char splitter
) const {
153 std::vector
<std::string
> version
;
154 if (!ProcessVersionString(version_string
, splitter
, &version
))
156 int relation
= Compare(version
, version_
, version_style_
);
158 return (relation
== 0);
160 return (relation
< 0);
162 return (relation
<= 0);
164 return (relation
> 0);
166 return (relation
>= 0);
170 return Compare(version
, version2_
, version_style_
) <= 0;
173 bool GpuControlList::VersionInfo::IsValid() const {
174 return (op_
!= kUnknown
&& version_style_
!= kVersionStyleUnknown
);
177 bool GpuControlList::VersionInfo::IsLexical() const {
178 return version_style_
== kVersionStyleLexical
;
182 int GpuControlList::VersionInfo::Compare(
183 const std::vector
<std::string
>& version
,
184 const std::vector
<std::string
>& version_ref
,
185 VersionStyle version_style
) {
186 DCHECK(version
.size() > 0 && version_ref
.size() > 0);
187 DCHECK(version_style
!= kVersionStyleUnknown
);
188 for (size_t i
= 0; i
< version_ref
.size(); ++i
) {
189 if (i
>= version
.size())
192 // We assume both versions are checked by ProcessVersionString().
193 if (i
> 0 && version_style
== kVersionStyleLexical
)
194 ret
= CompareLexicalNumberStrings(version
[i
], version_ref
[i
]);
196 ret
= CompareNumericalNumberStrings(version
[i
], version_ref
[i
]);
204 GpuControlList::VersionInfo::VersionStyle
205 GpuControlList::VersionInfo::StringToVersionStyle(
206 const std::string
& version_style
) {
207 if (version_style
.empty() || version_style
== kVersionStyleStringNumerical
)
208 return kVersionStyleNumerical
;
209 if (version_style
== kVersionStyleStringLexical
)
210 return kVersionStyleLexical
;
211 return kVersionStyleUnknown
;
214 GpuControlList::OsInfo::OsInfo(const std::string
& os
,
215 const std::string
& version_op
,
216 const std::string
& version_string
,
217 const std::string
& version_string2
) {
218 type_
= StringToOsType(os
);
219 if (type_
!= kOsUnknown
) {
220 version_info_
.reset(new VersionInfo(
221 version_op
, std::string(), version_string
, version_string2
));
225 GpuControlList::OsInfo::~OsInfo() {}
227 bool GpuControlList::OsInfo::Contains(OsType type
,
228 const std::string
& version
) const {
231 if (type_
!= type
&& type_
!= kOsAny
)
233 return version_info_
->Contains(version
);
236 bool GpuControlList::OsInfo::IsValid() const {
237 return type_
!= kOsUnknown
&& version_info_
->IsValid();
240 GpuControlList::OsType
GpuControlList::OsInfo::type() const {
244 GpuControlList::OsType
GpuControlList::OsInfo::StringToOsType(
245 const std::string
& os
) {
248 else if (os
== "macosx")
250 else if (os
== "android")
252 else if (os
== "linux")
254 else if (os
== "chromeos")
256 else if (os
== "any")
261 GpuControlList::MachineModelInfo::MachineModelInfo(
262 const std::string
& name_op
,
263 const std::string
& name_value
,
264 const std::string
& version_op
,
265 const std::string
& version_string
,
266 const std::string
& version_string2
) {
267 name_info_
.reset(new StringInfo(name_op
, name_value
));
268 version_info_
.reset(new VersionInfo(
269 version_op
, std::string(), version_string
, version_string2
));
272 GpuControlList::MachineModelInfo::~MachineModelInfo() {}
274 bool GpuControlList::MachineModelInfo::Contains(
275 const std::string
& name
, const std::string
& version
) const {
278 if (!name_info_
->Contains(name
))
280 return version_info_
->Contains(version
);
283 bool GpuControlList::MachineModelInfo::IsValid() const {
284 return name_info_
->IsValid() && version_info_
->IsValid();
287 GpuControlList::StringInfo::StringInfo(const std::string
& string_op
,
288 const std::string
& string_value
) {
289 op_
= StringToOp(string_op
);
290 value_
= StringToLowerASCII(string_value
);
293 bool GpuControlList::StringInfo::Contains(const std::string
& value
) const {
294 std::string my_value
= StringToLowerASCII(value
);
297 return strstr(my_value
.c_str(), value_
.c_str()) != NULL
;
299 return StartsWithASCII(my_value
, value_
, false);
301 return EndsWith(my_value
, value_
, false);
303 return value_
== my_value
;
309 bool GpuControlList::StringInfo::IsValid() const {
310 return op_
!= kUnknown
;
313 GpuControlList::StringInfo::Op
GpuControlList::StringInfo::StringToOp(
314 const std::string
& string_op
) {
315 if (string_op
== "=")
317 else if (string_op
== "contains")
319 else if (string_op
== "beginwith")
321 else if (string_op
== "endwith")
326 GpuControlList::FloatInfo::FloatInfo(const std::string
& float_op
,
327 const std::string
& float_value
,
328 const std::string
& float_value2
)
332 op_
= StringToNumericOp(float_op
);
336 if (!base::StringToDouble(float_value
, &dvalue
)) {
340 value_
= static_cast<float>(dvalue
);
341 if (op_
== kBetween
) {
342 if (!base::StringToDouble(float_value2
, &dvalue
)) {
346 value2_
= static_cast<float>(dvalue
);
350 bool GpuControlList::FloatInfo::Contains(float value
) const {
356 return (value
== value_
);
358 return (value
< value_
);
360 return (value
<= value_
);
362 return (value
> value_
);
364 return (value
>= value_
);
365 DCHECK(op_
== kBetween
);
366 return ((value_
<= value
&& value
<= value2_
) ||
367 (value2_
<= value
&& value
<= value_
));
370 bool GpuControlList::FloatInfo::IsValid() const {
371 return op_
!= kUnknown
;
374 GpuControlList::IntInfo::IntInfo(const std::string
& int_op
,
375 const std::string
& int_value
,
376 const std::string
& int_value2
)
380 op_
= StringToNumericOp(int_op
);
383 if (!base::StringToInt(int_value
, &value_
)) {
387 if (op_
== kBetween
&&
388 !base::StringToInt(int_value2
, &value2_
))
392 bool GpuControlList::IntInfo::Contains(int value
) const {
398 return (value
== value_
);
400 return (value
< value_
);
402 return (value
<= value_
);
404 return (value
> value_
);
406 return (value
>= value_
);
407 DCHECK(op_
== kBetween
);
408 return ((value_
<= value
&& value
<= value2_
) ||
409 (value2_
<= value
&& value
<= value_
));
412 bool GpuControlList::IntInfo::IsValid() const {
413 return op_
!= kUnknown
;
417 GpuControlList::ScopedGpuControlListEntry
418 GpuControlList::GpuControlListEntry::GetEntryFromValue(
419 const base::DictionaryValue
* value
, bool top_level
,
420 const FeatureMap
& feature_map
,
421 bool supports_feature_type_all
) {
423 ScopedGpuControlListEntry
entry(new GpuControlListEntry());
425 size_t dictionary_entry_count
= 0;
429 if (!value
->GetInteger("id", reinterpret_cast<int*>(&id
)) ||
431 LOG(WARNING
) << "Malformed id entry " << entry
->id();
434 dictionary_entry_count
++;
437 if (value
->GetBoolean("disabled", &disabled
)) {
438 entry
->SetDisabled(disabled
);
439 dictionary_entry_count
++;
443 std::string description
;
444 if (value
->GetString("description", &description
)) {
445 entry
->description_
= description
;
446 dictionary_entry_count
++;
448 entry
->description_
= "The GPU is unavailable for an unexplained reason.";
451 const base::ListValue
* cr_bugs
;
452 if (value
->GetList("cr_bugs", &cr_bugs
)) {
453 for (size_t i
= 0; i
< cr_bugs
->GetSize(); ++i
) {
455 if (cr_bugs
->GetInteger(i
, &bug_id
)) {
456 entry
->cr_bugs_
.push_back(bug_id
);
458 LOG(WARNING
) << "Malformed cr_bugs entry " << entry
->id();
462 dictionary_entry_count
++;
465 const base::ListValue
* webkit_bugs
;
466 if (value
->GetList("webkit_bugs", &webkit_bugs
)) {
467 for (size_t i
= 0; i
< webkit_bugs
->GetSize(); ++i
) {
469 if (webkit_bugs
->GetInteger(i
, &bug_id
)) {
470 entry
->webkit_bugs_
.push_back(bug_id
);
472 LOG(WARNING
) << "Malformed webkit_bugs entry " << entry
->id();
476 dictionary_entry_count
++;
479 const base::DictionaryValue
* os_value
= NULL
;
480 if (value
->GetDictionary("os", &os_value
)) {
482 std::string os_version_op
= "any";
483 std::string os_version_string
;
484 std::string os_version_string2
;
485 os_value
->GetString("type", &os_type
);
486 const base::DictionaryValue
* os_version_value
= NULL
;
487 if (os_value
->GetDictionary("version", &os_version_value
)) {
488 os_version_value
->GetString(kOp
, &os_version_op
);
489 os_version_value
->GetString("value", &os_version_string
);
490 os_version_value
->GetString("value2", &os_version_string2
);
492 if (!entry
->SetOsInfo(os_type
, os_version_op
, os_version_string
,
493 os_version_string2
)) {
494 LOG(WARNING
) << "Malformed os entry " << entry
->id();
497 dictionary_entry_count
++;
500 std::string vendor_id
;
501 if (value
->GetString("vendor_id", &vendor_id
)) {
502 if (!entry
->SetVendorId(vendor_id
)) {
503 LOG(WARNING
) << "Malformed vendor_id entry " << entry
->id();
506 dictionary_entry_count
++;
509 const base::ListValue
* device_id_list
;
510 if (value
->GetList("device_id", &device_id_list
)) {
511 for (size_t i
= 0; i
< device_id_list
->GetSize(); ++i
) {
512 std::string device_id
;
513 if (!device_id_list
->GetString(i
, &device_id
) ||
514 !entry
->AddDeviceId(device_id
)) {
515 LOG(WARNING
) << "Malformed device_id entry " << entry
->id();
519 dictionary_entry_count
++;
522 std::string multi_gpu_style
;
523 if (value
->GetString("multi_gpu_style", &multi_gpu_style
)) {
524 if (!entry
->SetMultiGpuStyle(multi_gpu_style
)) {
525 LOG(WARNING
) << "Malformed multi_gpu_style entry " << entry
->id();
528 dictionary_entry_count
++;
531 std::string multi_gpu_category
;
532 if (value
->GetString("multi_gpu_category", &multi_gpu_category
)) {
533 if (!entry
->SetMultiGpuCategory(multi_gpu_category
)) {
534 LOG(WARNING
) << "Malformed multi_gpu_category entry " << entry
->id();
537 dictionary_entry_count
++;
540 const base::DictionaryValue
* driver_vendor_value
= NULL
;
541 if (value
->GetDictionary("driver_vendor", &driver_vendor_value
)) {
542 std::string vendor_op
;
543 std::string vendor_value
;
544 driver_vendor_value
->GetString(kOp
, &vendor_op
);
545 driver_vendor_value
->GetString("value", &vendor_value
);
546 if (!entry
->SetDriverVendorInfo(vendor_op
, vendor_value
)) {
547 LOG(WARNING
) << "Malformed driver_vendor entry " << entry
->id();
550 dictionary_entry_count
++;
553 const base::DictionaryValue
* driver_version_value
= NULL
;
554 if (value
->GetDictionary("driver_version", &driver_version_value
)) {
555 std::string driver_version_op
= "any";
556 std::string driver_version_style
;
557 std::string driver_version_string
;
558 std::string driver_version_string2
;
559 driver_version_value
->GetString(kOp
, &driver_version_op
);
560 driver_version_value
->GetString("style", &driver_version_style
);
561 driver_version_value
->GetString("value", &driver_version_string
);
562 driver_version_value
->GetString("value2", &driver_version_string2
);
563 if (!entry
->SetDriverVersionInfo(driver_version_op
,
564 driver_version_style
,
565 driver_version_string
,
566 driver_version_string2
)) {
567 LOG(WARNING
) << "Malformed driver_version entry " << entry
->id();
570 dictionary_entry_count
++;
573 const base::DictionaryValue
* driver_date_value
= NULL
;
574 if (value
->GetDictionary("driver_date", &driver_date_value
)) {
575 std::string driver_date_op
= "any";
576 std::string driver_date_string
;
577 std::string driver_date_string2
;
578 driver_date_value
->GetString(kOp
, &driver_date_op
);
579 driver_date_value
->GetString("value", &driver_date_string
);
580 driver_date_value
->GetString("value2", &driver_date_string2
);
581 if (!entry
->SetDriverDateInfo(driver_date_op
, driver_date_string
,
582 driver_date_string2
)) {
583 LOG(WARNING
) << "Malformed driver_date entry " << entry
->id();
586 dictionary_entry_count
++;
589 const base::DictionaryValue
* gl_vendor_value
= NULL
;
590 if (value
->GetDictionary("gl_vendor", &gl_vendor_value
)) {
591 std::string vendor_op
;
592 std::string vendor_value
;
593 gl_vendor_value
->GetString(kOp
, &vendor_op
);
594 gl_vendor_value
->GetString("value", &vendor_value
);
595 if (!entry
->SetGLVendorInfo(vendor_op
, vendor_value
)) {
596 LOG(WARNING
) << "Malformed gl_vendor entry " << entry
->id();
599 dictionary_entry_count
++;
602 const base::DictionaryValue
* gl_renderer_value
= NULL
;
603 if (value
->GetDictionary("gl_renderer", &gl_renderer_value
)) {
604 std::string renderer_op
;
605 std::string renderer_value
;
606 gl_renderer_value
->GetString(kOp
, &renderer_op
);
607 gl_renderer_value
->GetString("value", &renderer_value
);
608 if (!entry
->SetGLRendererInfo(renderer_op
, renderer_value
)) {
609 LOG(WARNING
) << "Malformed gl_renderer entry " << entry
->id();
612 dictionary_entry_count
++;
615 const base::DictionaryValue
* gl_extensions_value
= NULL
;
616 if (value
->GetDictionary("gl_extensions", &gl_extensions_value
)) {
617 std::string extensions_op
;
618 std::string extensions_value
;
619 gl_extensions_value
->GetString(kOp
, &extensions_op
);
620 gl_extensions_value
->GetString("value", &extensions_value
);
621 if (!entry
->SetGLExtensionsInfo(extensions_op
, extensions_value
)) {
622 LOG(WARNING
) << "Malformed gl_extensions entry " << entry
->id();
625 dictionary_entry_count
++;
628 const base::DictionaryValue
* gl_reset_notification_strategy_value
= NULL
;
629 if (value
->GetDictionary("gl_reset_notification_strategy",
630 &gl_reset_notification_strategy_value
)) {
632 std::string int_value
;
633 std::string int_value2
;
634 gl_reset_notification_strategy_value
->GetString(kOp
, &op
);
635 gl_reset_notification_strategy_value
->GetString("value", &int_value
);
636 gl_reset_notification_strategy_value
->GetString("value2", &int_value2
);
637 if (!entry
->SetGLResetNotificationStrategyInfo(
638 op
, int_value
, int_value2
)) {
639 LOG(WARNING
) << "Malformed gl_reset_notification_strategy entry "
643 dictionary_entry_count
++;
646 const base::DictionaryValue
* cpu_brand_value
= NULL
;
647 if (value
->GetDictionary("cpu_info", &cpu_brand_value
)) {
649 std::string cpu_value
;
650 cpu_brand_value
->GetString(kOp
, &cpu_op
);
651 cpu_brand_value
->GetString("value", &cpu_value
);
652 if (!entry
->SetCpuBrand(cpu_op
, cpu_value
)) {
653 LOG(WARNING
) << "Malformed cpu_brand entry " << entry
->id();
656 dictionary_entry_count
++;
659 const base::DictionaryValue
* perf_graphics_value
= NULL
;
660 if (value
->GetDictionary("perf_graphics", &perf_graphics_value
)) {
662 std::string float_value
;
663 std::string float_value2
;
664 perf_graphics_value
->GetString(kOp
, &op
);
665 perf_graphics_value
->GetString("value", &float_value
);
666 perf_graphics_value
->GetString("value2", &float_value2
);
667 if (!entry
->SetPerfGraphicsInfo(op
, float_value
, float_value2
)) {
668 LOG(WARNING
) << "Malformed perf_graphics entry " << entry
->id();
671 dictionary_entry_count
++;
674 const base::DictionaryValue
* perf_gaming_value
= NULL
;
675 if (value
->GetDictionary("perf_gaming", &perf_gaming_value
)) {
677 std::string float_value
;
678 std::string float_value2
;
679 perf_gaming_value
->GetString(kOp
, &op
);
680 perf_gaming_value
->GetString("value", &float_value
);
681 perf_gaming_value
->GetString("value2", &float_value2
);
682 if (!entry
->SetPerfGamingInfo(op
, float_value
, float_value2
)) {
683 LOG(WARNING
) << "Malformed perf_gaming entry " << entry
->id();
686 dictionary_entry_count
++;
689 const base::DictionaryValue
* perf_overall_value
= NULL
;
690 if (value
->GetDictionary("perf_overall", &perf_overall_value
)) {
692 std::string float_value
;
693 std::string float_value2
;
694 perf_overall_value
->GetString(kOp
, &op
);
695 perf_overall_value
->GetString("value", &float_value
);
696 perf_overall_value
->GetString("value2", &float_value2
);
697 if (!entry
->SetPerfOverallInfo(op
, float_value
, float_value2
)) {
698 LOG(WARNING
) << "Malformed perf_overall entry " << entry
->id();
701 dictionary_entry_count
++;
704 const base::DictionaryValue
* machine_model_value
= NULL
;
705 if (value
->GetDictionary("machine_model", &machine_model_value
)) {
707 std::string name_value
;
708 const base::DictionaryValue
* name
= NULL
;
709 if (machine_model_value
->GetDictionary("name", &name
)) {
710 name
->GetString(kOp
, &name_op
);
711 name
->GetString("value", &name_value
);
714 std::string version_op
= "any";
715 std::string version_string
;
716 std::string version_string2
;
717 const base::DictionaryValue
* version_value
= NULL
;
718 if (machine_model_value
->GetDictionary("version", &version_value
)) {
719 version_value
->GetString(kOp
, &version_op
);
720 version_value
->GetString("value", &version_string
);
721 version_value
->GetString("value2", &version_string2
);
723 if (!entry
->SetMachineModelInfo(
724 name_op
, name_value
, version_op
, version_string
, version_string2
)) {
725 LOG(WARNING
) << "Malformed machine_model entry " << entry
->id();
728 dictionary_entry_count
++;
731 const base::DictionaryValue
* gpu_count_value
= NULL
;
732 if (value
->GetDictionary("gpu_count", &gpu_count_value
)) {
734 std::string int_value
;
735 std::string int_value2
;
736 gpu_count_value
->GetString(kOp
, &op
);
737 gpu_count_value
->GetString("value", &int_value
);
738 gpu_count_value
->GetString("value2", &int_value2
);
739 if (!entry
->SetGpuCountInfo(op
, int_value
, int_value2
)) {
740 LOG(WARNING
) << "Malformed gpu_count entry " << entry
->id();
743 dictionary_entry_count
++;
747 const base::ListValue
* feature_value
= NULL
;
748 if (value
->GetList("features", &feature_value
)) {
749 std::vector
<std::string
> feature_list
;
750 for (size_t i
= 0; i
< feature_value
->GetSize(); ++i
) {
752 if (feature_value
->GetString(i
, &feature
)) {
753 feature_list
.push_back(feature
);
755 LOG(WARNING
) << "Malformed feature entry " << entry
->id();
759 if (!entry
->SetFeatures(
760 feature_list
, feature_map
, supports_feature_type_all
)) {
761 LOG(WARNING
) << "Malformed feature entry " << entry
->id();
764 dictionary_entry_count
++;
769 const base::ListValue
* exception_list_value
= NULL
;
770 if (value
->GetList("exceptions", &exception_list_value
)) {
771 for (size_t i
= 0; i
< exception_list_value
->GetSize(); ++i
) {
772 const base::DictionaryValue
* exception_value
= NULL
;
773 if (!exception_list_value
->GetDictionary(i
, &exception_value
)) {
774 LOG(WARNING
) << "Malformed exceptions entry " << entry
->id();
777 ScopedGpuControlListEntry
exception(GetEntryFromValue(
778 exception_value
, false, feature_map
, supports_feature_type_all
));
779 if (exception
.get() == NULL
) {
780 LOG(WARNING
) << "Malformed exceptions entry " << entry
->id();
783 // Exception should inherit vendor_id from parent, otherwise if only
784 // device_ids are specified in Exception, the info will be incomplete.
785 if (exception
->vendor_id_
== 0 && entry
->vendor_id_
!= 0)
786 exception
->vendor_id_
= entry
->vendor_id_
;
787 entry
->AddException(exception
);
789 dictionary_entry_count
++;
792 const base::DictionaryValue
* browser_version_value
= NULL
;
793 // browser_version is processed in LoadGpuControlList().
794 if (value
->GetDictionary("browser_version", &browser_version_value
))
795 dictionary_entry_count
++;
798 if (value
->size() != dictionary_entry_count
) {
799 LOG(WARNING
) << "Entry with unknown fields " << entry
->id();
805 GpuControlList::GpuControlListEntry::GpuControlListEntry()
809 multi_gpu_style_(kMultiGpuStyleNone
),
810 multi_gpu_category_(kMultiGpuCategoryPrimary
) {
813 GpuControlList::GpuControlListEntry::~GpuControlListEntry() { }
815 bool GpuControlList::GpuControlListEntry::SetId(uint32 id
) {
823 void GpuControlList::GpuControlListEntry::SetDisabled(bool disabled
) {
824 disabled_
= disabled
;
827 bool GpuControlList::GpuControlListEntry::SetOsInfo(
828 const std::string
& os
,
829 const std::string
& version_op
,
830 const std::string
& version_string
,
831 const std::string
& version_string2
) {
832 os_info_
.reset(new OsInfo(os
, version_op
, version_string
, version_string2
));
833 return os_info_
->IsValid();
836 bool GpuControlList::GpuControlListEntry::SetVendorId(
837 const std::string
& vendor_id_string
) {
839 return base::HexStringToInt(vendor_id_string
,
840 reinterpret_cast<int*>(&vendor_id_
));
843 bool GpuControlList::GpuControlListEntry::AddDeviceId(
844 const std::string
& device_id_string
) {
845 uint32 device_id
= 0;
846 if (base::HexStringToInt(device_id_string
,
847 reinterpret_cast<int*>(&device_id
))) {
848 device_id_list_
.push_back(device_id
);
854 bool GpuControlList::GpuControlListEntry::SetMultiGpuStyle(
855 const std::string
& multi_gpu_style_string
) {
856 MultiGpuStyle style
= StringToMultiGpuStyle(multi_gpu_style_string
);
857 if (style
== kMultiGpuStyleNone
)
859 multi_gpu_style_
= style
;
863 bool GpuControlList::GpuControlListEntry::SetMultiGpuCategory(
864 const std::string
& multi_gpu_category_string
) {
865 MultiGpuCategory category
=
866 StringToMultiGpuCategory(multi_gpu_category_string
);
867 if (category
== kMultiGpuCategoryNone
)
869 multi_gpu_category_
= category
;
873 bool GpuControlList::GpuControlListEntry::SetDriverVendorInfo(
874 const std::string
& vendor_op
,
875 const std::string
& vendor_value
) {
876 driver_vendor_info_
.reset(new StringInfo(vendor_op
, vendor_value
));
877 return driver_vendor_info_
->IsValid();
880 bool GpuControlList::GpuControlListEntry::SetDriverVersionInfo(
881 const std::string
& version_op
,
882 const std::string
& version_style
,
883 const std::string
& version_string
,
884 const std::string
& version_string2
) {
885 driver_version_info_
.reset(new VersionInfo(
886 version_op
, version_style
, version_string
, version_string2
));
887 return driver_version_info_
->IsValid();
890 bool GpuControlList::GpuControlListEntry::SetDriverDateInfo(
891 const std::string
& date_op
,
892 const std::string
& date_string
,
893 const std::string
& date_string2
) {
894 driver_date_info_
.reset(
895 new VersionInfo(date_op
, std::string(), date_string
, date_string2
));
896 return driver_date_info_
->IsValid();
899 bool GpuControlList::GpuControlListEntry::SetGLVendorInfo(
900 const std::string
& vendor_op
,
901 const std::string
& vendor_value
) {
902 gl_vendor_info_
.reset(new StringInfo(vendor_op
, vendor_value
));
903 return gl_vendor_info_
->IsValid();
906 bool GpuControlList::GpuControlListEntry::SetGLRendererInfo(
907 const std::string
& renderer_op
,
908 const std::string
& renderer_value
) {
909 gl_renderer_info_
.reset(new StringInfo(renderer_op
, renderer_value
));
910 return gl_renderer_info_
->IsValid();
913 bool GpuControlList::GpuControlListEntry::SetGLExtensionsInfo(
914 const std::string
& extensions_op
,
915 const std::string
& extensions_value
) {
916 gl_extensions_info_
.reset(new StringInfo(extensions_op
, extensions_value
));
917 return gl_extensions_info_
->IsValid();
920 bool GpuControlList::GpuControlListEntry::SetGLResetNotificationStrategyInfo(
921 const std::string
& op
,
922 const std::string
& int_string
,
923 const std::string
& int_string2
) {
924 gl_reset_notification_strategy_info_
.reset(
925 new IntInfo(op
, int_string
, int_string2
));
926 return gl_reset_notification_strategy_info_
->IsValid();
929 bool GpuControlList::GpuControlListEntry::SetCpuBrand(
930 const std::string
& cpu_op
,
931 const std::string
& cpu_value
) {
932 cpu_brand_
.reset(new StringInfo(cpu_op
, cpu_value
));
933 return cpu_brand_
->IsValid();
936 bool GpuControlList::GpuControlListEntry::SetPerfGraphicsInfo(
937 const std::string
& op
,
938 const std::string
& float_string
,
939 const std::string
& float_string2
) {
940 perf_graphics_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
941 return perf_graphics_info_
->IsValid();
944 bool GpuControlList::GpuControlListEntry::SetPerfGamingInfo(
945 const std::string
& op
,
946 const std::string
& float_string
,
947 const std::string
& float_string2
) {
948 perf_gaming_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
949 return perf_gaming_info_
->IsValid();
952 bool GpuControlList::GpuControlListEntry::SetPerfOverallInfo(
953 const std::string
& op
,
954 const std::string
& float_string
,
955 const std::string
& float_string2
) {
956 perf_overall_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
957 return perf_overall_info_
->IsValid();
960 bool GpuControlList::GpuControlListEntry::SetMachineModelInfo(
961 const std::string
& name_op
,
962 const std::string
& name_value
,
963 const std::string
& version_op
,
964 const std::string
& version_string
,
965 const std::string
& version_string2
) {
966 machine_model_info_
.reset(new MachineModelInfo(
967 name_op
, name_value
, version_op
, version_string
, version_string2
));
968 return machine_model_info_
->IsValid();
971 bool GpuControlList::GpuControlListEntry::SetGpuCountInfo(
972 const std::string
& op
,
973 const std::string
& int_string
,
974 const std::string
& int_string2
) {
975 gpu_count_info_
.reset(new IntInfo(op
, int_string
, int_string2
));
976 return gpu_count_info_
->IsValid();
979 bool GpuControlList::GpuControlListEntry::SetFeatures(
980 const std::vector
<std::string
>& feature_strings
,
981 const FeatureMap
& feature_map
,
982 bool supports_feature_type_all
) {
983 size_t size
= feature_strings
.size();
987 for (size_t i
= 0; i
< size
; ++i
) {
989 if (supports_feature_type_all
&& feature_strings
[i
] == "all") {
990 for (FeatureMap::const_iterator iter
= feature_map
.begin();
991 iter
!= feature_map
.end(); ++iter
)
992 features_
.insert(iter
->second
);
995 if (!StringToFeature(feature_strings
[i
], &feature
, feature_map
)) {
999 features_
.insert(feature
);
1004 void GpuControlList::GpuControlListEntry::AddException(
1005 ScopedGpuControlListEntry exception
) {
1006 exceptions_
.push_back(exception
);
1010 GpuControlList::GpuControlListEntry::MultiGpuStyle
1011 GpuControlList::GpuControlListEntry::StringToMultiGpuStyle(
1012 const std::string
& style
) {
1013 if (style
== kMultiGpuStyleStringOptimus
)
1014 return kMultiGpuStyleOptimus
;
1015 if (style
== kMultiGpuStyleStringAMDSwitchable
)
1016 return kMultiGpuStyleAMDSwitchable
;
1017 return kMultiGpuStyleNone
;
1021 GpuControlList::GpuControlListEntry::MultiGpuCategory
1022 GpuControlList::GpuControlListEntry::StringToMultiGpuCategory(
1023 const std::string
& category
) {
1024 if (category
== kMultiGpuCategoryStringPrimary
)
1025 return kMultiGpuCategoryPrimary
;
1026 if (category
== kMultiGpuCategoryStringSecondary
)
1027 return kMultiGpuCategorySecondary
;
1028 if (category
== kMultiGpuCategoryStringAny
)
1029 return kMultiGpuCategoryAny
;
1030 return kMultiGpuCategoryNone
;
1033 bool GpuControlList::GpuControlListEntry::Contains(
1034 OsType os_type
, const std::string
& os_version
,
1035 const GPUInfo
& gpu_info
) const {
1036 DCHECK(os_type
!= kOsAny
);
1037 if (os_info_
.get() != NULL
&& !os_info_
->Contains(os_type
, os_version
))
1039 bool is_not_primary_gpu
=
1040 GpuUnmatched(vendor_id_
, device_id_list_
, gpu_info
.gpu
);
1041 bool is_not_secondary_gpu
= true;
1042 for (size_t i
= 0; i
< gpu_info
.secondary_gpus
.size(); ++i
) {
1043 is_not_secondary_gpu
= is_not_secondary_gpu
&&
1044 GpuUnmatched(vendor_id_
, device_id_list_
, gpu_info
.secondary_gpus
[i
]);
1046 switch (multi_gpu_category_
) {
1047 case kMultiGpuCategoryPrimary
:
1048 if (is_not_primary_gpu
)
1051 case kMultiGpuCategorySecondary
:
1052 if (is_not_secondary_gpu
)
1055 case kMultiGpuCategoryAny
:
1056 if (is_not_primary_gpu
&& is_not_secondary_gpu
)
1059 case kMultiGpuCategoryNone
:
1062 switch (multi_gpu_style_
) {
1063 case kMultiGpuStyleOptimus
:
1064 if (!gpu_info
.optimus
)
1067 case kMultiGpuStyleAMDSwitchable
:
1068 if (!gpu_info
.amd_switchable
)
1071 case kMultiGpuStyleNone
:
1074 if (driver_vendor_info_
.get() != NULL
&& !gpu_info
.driver_vendor
.empty() &&
1075 !driver_vendor_info_
->Contains(gpu_info
.driver_vendor
))
1077 if (driver_version_info_
.get() != NULL
&& !gpu_info
.driver_version
.empty()) {
1078 if (!driver_version_info_
->Contains(gpu_info
.driver_version
))
1081 if (driver_date_info_
.get() != NULL
&& !gpu_info
.driver_date
.empty()) {
1082 if (!driver_date_info_
->Contains(gpu_info
.driver_date
, '-'))
1085 if (gl_vendor_info_
.get() != NULL
&& !gpu_info
.gl_vendor
.empty() &&
1086 !gl_vendor_info_
->Contains(gpu_info
.gl_vendor
))
1088 if (gl_renderer_info_
.get() != NULL
&& !gpu_info
.gl_renderer
.empty() &&
1089 !gl_renderer_info_
->Contains(gpu_info
.gl_renderer
))
1091 if (gl_extensions_info_
.get() != NULL
&& !gpu_info
.gl_extensions
.empty() &&
1092 !gl_extensions_info_
->Contains(gpu_info
.gl_extensions
))
1094 if (gl_reset_notification_strategy_info_
.get() != NULL
&&
1095 !gl_reset_notification_strategy_info_
->Contains(
1096 gpu_info
.gl_reset_notification_strategy
))
1098 if (perf_graphics_info_
.get() != NULL
&&
1099 (gpu_info
.performance_stats
.graphics
== 0.0 ||
1100 !perf_graphics_info_
->Contains(gpu_info
.performance_stats
.graphics
)))
1102 if (perf_gaming_info_
.get() != NULL
&&
1103 (gpu_info
.performance_stats
.gaming
== 0.0 ||
1104 !perf_gaming_info_
->Contains(gpu_info
.performance_stats
.gaming
)))
1106 if (perf_overall_info_
.get() != NULL
&&
1107 (gpu_info
.performance_stats
.overall
== 0.0 ||
1108 !perf_overall_info_
->Contains(gpu_info
.performance_stats
.overall
)))
1110 if (machine_model_info_
.get() != NULL
) {
1111 std::vector
<std::string
> name_version
;
1112 base::SplitString(gpu_info
.machine_model
, ' ', &name_version
);
1113 if (name_version
.size() == 2 &&
1114 !machine_model_info_
->Contains(name_version
[0], name_version
[1]))
1117 if (gpu_count_info_
.get() != NULL
&&
1118 !gpu_count_info_
->Contains(gpu_info
.secondary_gpus
.size() + 1))
1120 if (cpu_brand_
.get() != NULL
) {
1122 if (!cpu_brand_
->Contains(cpu_info
.cpu_brand()))
1126 for (size_t i
= 0; i
< exceptions_
.size(); ++i
) {
1127 if (exceptions_
[i
]->Contains(os_type
, os_version
, gpu_info
) &&
1128 !exceptions_
[i
]->NeedsMoreInfo(gpu_info
))
1134 bool GpuControlList::GpuControlListEntry::NeedsMoreInfo(
1135 const GPUInfo
& gpu_info
) const {
1136 // We only check for missing info that might be collected with a gl context.
1137 // If certain info is missing due to some error, say, we fail to collect
1138 // vendor_id/device_id, then even if we launch GPU process and create a gl
1139 // context, we won't gather such missing info, so we still return false.
1140 if (driver_vendor_info_
.get() && gpu_info
.driver_vendor
.empty())
1142 if (driver_version_info_
.get() && gpu_info
.driver_version
.empty())
1144 if (gl_vendor_info_
.get() && gpu_info
.gl_vendor
.empty())
1146 if (gl_renderer_info_
.get() && gpu_info
.gl_renderer
.empty())
1148 for (size_t i
= 0; i
< exceptions_
.size(); ++i
) {
1149 if (exceptions_
[i
]->NeedsMoreInfo(gpu_info
))
1155 GpuControlList::OsType
GpuControlList::GpuControlListEntry::GetOsType() const {
1156 if (os_info_
.get() == NULL
)
1158 return os_info_
->type();
1161 uint32
GpuControlList::GpuControlListEntry::id() const {
1165 bool GpuControlList::GpuControlListEntry::disabled() const {
1169 const std::set
<int>& GpuControlList::GpuControlListEntry::features() const {
1174 bool GpuControlList::GpuControlListEntry::StringToFeature(
1175 const std::string
& feature_name
, int* feature_id
,
1176 const FeatureMap
& feature_map
) {
1177 FeatureMap::const_iterator iter
= feature_map
.find(feature_name
);
1178 if (iter
!= feature_map
.end()) {
1179 *feature_id
= iter
->second
;
1185 GpuControlList::GpuControlList()
1187 needs_more_info_(false),
1188 supports_feature_type_all_(false) {
1191 GpuControlList::~GpuControlList() {
1195 bool GpuControlList::LoadList(
1196 const std::string
& json_context
, GpuControlList::OsFilter os_filter
) {
1197 const std::string browser_version_string
= "0";
1198 return LoadList(browser_version_string
, json_context
, os_filter
);
1201 bool GpuControlList::LoadList(
1202 const std::string
& browser_version_string
,
1203 const std::string
& json_context
,
1204 GpuControlList::OsFilter os_filter
) {
1205 std::vector
<std::string
> pieces
;
1206 if (!ProcessVersionString(browser_version_string
, '.', &pieces
))
1208 browser_version_
= browser_version_string
;
1210 scoped_ptr
<base::Value
> root
;
1211 root
.reset(base::JSONReader::Read(json_context
));
1212 if (root
.get() == NULL
|| !root
->IsType(base::Value::TYPE_DICTIONARY
))
1215 base::DictionaryValue
* root_dictionary
=
1216 static_cast<base::DictionaryValue
*>(root
.get());
1217 DCHECK(root_dictionary
);
1218 return LoadList(*root_dictionary
, os_filter
);
1221 bool GpuControlList::LoadList(const base::DictionaryValue
& parsed_json
,
1222 GpuControlList::OsFilter os_filter
) {
1223 std::vector
<ScopedGpuControlListEntry
> entries
;
1225 parsed_json
.GetString("version", &version_
);
1226 std::vector
<std::string
> pieces
;
1227 if (!ProcessVersionString(version_
, '.', &pieces
))
1230 const base::ListValue
* list
= NULL
;
1231 if (!parsed_json
.GetList("entries", &list
))
1234 uint32 max_entry_id
= 0;
1235 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
1236 const base::DictionaryValue
* list_item
= NULL
;
1237 bool valid
= list
->GetDictionary(i
, &list_item
);
1238 if (!valid
|| list_item
== NULL
)
1240 // Check browser version compatibility: if the entry is not for the
1241 // current browser version, don't process it.
1242 BrowserVersionSupport browser_version_support
=
1243 IsEntrySupportedByCurrentBrowserVersion(list_item
);
1244 if (browser_version_support
== kMalformed
)
1246 if (browser_version_support
== kUnsupported
)
1248 DCHECK(browser_version_support
== kSupported
);
1249 ScopedGpuControlListEntry
entry(GpuControlListEntry::GetEntryFromValue(
1250 list_item
, true, feature_map_
, supports_feature_type_all_
));
1251 if (entry
.get() == NULL
)
1253 if (entry
->id() > max_entry_id
)
1254 max_entry_id
= entry
->id();
1255 entries
.push_back(entry
);
1259 OsType my_os
= GetOsType();
1260 for (size_t i
= 0; i
< entries
.size(); ++i
) {
1261 OsType entry_os
= entries
[i
]->GetOsType();
1262 if (os_filter
== GpuControlList::kAllOs
||
1263 entry_os
== kOsAny
|| entry_os
== my_os
)
1264 entries_
.push_back(entries
[i
]);
1266 max_entry_id_
= max_entry_id
;
1270 std::set
<int> GpuControlList::MakeDecision(
1271 GpuControlList::OsType os
,
1272 std::string os_version
,
1273 const GPUInfo
& gpu_info
) {
1274 active_entries_
.clear();
1275 std::set
<int> features
;
1277 needs_more_info_
= false;
1278 std::set
<int> possible_features
;
1282 if (os_version
.empty()) {
1283 os_version
= base::SysInfo::OperatingSystemVersion();
1284 size_t pos
= os_version
.find_first_not_of("0123456789.");
1285 if (pos
!= std::string::npos
)
1286 os_version
= os_version
.substr(0, pos
);
1288 std::vector
<std::string
> pieces
;
1289 if (!ProcessVersionString(os_version
, '.', &pieces
))
1292 for (size_t i
= 0; i
< entries_
.size(); ++i
) {
1293 if (entries_
[i
]->Contains(os
, os_version
, gpu_info
)) {
1294 if (!entries_
[i
]->disabled()) {
1295 MergeFeatureSets(&possible_features
, entries_
[i
]->features());
1296 if (!entries_
[i
]->NeedsMoreInfo(gpu_info
))
1297 MergeFeatureSets(&features
, entries_
[i
]->features());
1299 active_entries_
.push_back(entries_
[i
]);
1303 if (possible_features
.size() > features
.size())
1304 needs_more_info_
= true;
1309 void GpuControlList::GetDecisionEntries(
1310 std::vector
<uint32
>* entry_ids
, bool disabled
) const {
1313 for (size_t i
= 0; i
< active_entries_
.size(); ++i
) {
1314 if (disabled
== active_entries_
[i
]->disabled())
1315 entry_ids
->push_back(active_entries_
[i
]->id());
1319 void GpuControlList::GetReasons(base::ListValue
* problem_list
) const {
1320 DCHECK(problem_list
);
1321 for (size_t i
= 0; i
< active_entries_
.size(); ++i
) {
1322 GpuControlListEntry
* entry
= active_entries_
[i
].get();
1323 if (entry
->disabled())
1325 base::DictionaryValue
* problem
= new base::DictionaryValue();
1327 problem
->SetString("description", entry
->description());
1329 base::ListValue
* cr_bugs
= new base::ListValue();
1330 for (size_t j
= 0; j
< entry
->cr_bugs().size(); ++j
)
1331 cr_bugs
->Append(new base::FundamentalValue(entry
->cr_bugs()[j
]));
1332 problem
->Set("crBugs", cr_bugs
);
1334 base::ListValue
* webkit_bugs
= new base::ListValue();
1335 for (size_t j
= 0; j
< entry
->webkit_bugs().size(); ++j
) {
1336 webkit_bugs
->Append(new base::FundamentalValue(entry
->webkit_bugs()[j
]));
1338 problem
->Set("webkitBugs", webkit_bugs
);
1340 problem_list
->Append(problem
);
1344 size_t GpuControlList::num_entries() const {
1345 return entries_
.size();
1348 uint32
GpuControlList::max_entry_id() const {
1349 return max_entry_id_
;
1352 std::string
GpuControlList::version() const {
1356 GpuControlList::OsType
GpuControlList::GetOsType() {
1357 #if defined(OS_CHROMEOS)
1359 #elif defined(OS_WIN)
1361 #elif defined(OS_ANDROID)
1363 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
1365 #elif defined(OS_MACOSX)
1372 void GpuControlList::Clear() {
1374 active_entries_
.clear();
1378 GpuControlList::BrowserVersionSupport
1379 GpuControlList::IsEntrySupportedByCurrentBrowserVersion(
1380 const base::DictionaryValue
* value
) {
1382 const base::DictionaryValue
* browser_version_value
= NULL
;
1383 if (value
->GetDictionary("browser_version", &browser_version_value
)) {
1384 std::string version_op
= "any";
1385 std::string version_string
;
1386 std::string version_string2
;
1387 browser_version_value
->GetString(kOp
, &version_op
);
1388 browser_version_value
->GetString("value", &version_string
);
1389 browser_version_value
->GetString("value2", &version_string2
);
1390 scoped_ptr
<VersionInfo
> browser_version_info
;
1391 browser_version_info
.reset(new VersionInfo(
1392 version_op
, std::string(), version_string
, version_string2
));
1393 if (!browser_version_info
->IsValid())
1395 if (browser_version_info
->Contains(browser_version_
))
1397 return kUnsupported
;
1403 GpuControlList::NumericOp
GpuControlList::StringToNumericOp(
1404 const std::string
& op
) {
1417 if (op
== "between")
1422 void GpuControlList::AddSupportedFeature(
1423 const std::string
& feature_name
, int feature_id
) {
1424 feature_map_
[feature_name
] = feature_id
;
1427 void GpuControlList::set_supports_feature_type_all(bool supported
) {
1428 supports_feature_type_all_
= supported
;