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("number", &os_version_string
);
490 os_version_value
->GetString("number2", &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("number", &driver_version_string
);
562 driver_version_value
->GetString("number2", &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("number", &driver_date_string
);
580 driver_date_value
->GetString("number2", &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
* cpu_brand_value
= NULL
;
629 if (value
->GetDictionary("cpu_info", &cpu_brand_value
)) {
631 std::string cpu_value
;
632 cpu_brand_value
->GetString(kOp
, &cpu_op
);
633 cpu_brand_value
->GetString("value", &cpu_value
);
634 if (!entry
->SetCpuBrand(cpu_op
, cpu_value
)) {
635 LOG(WARNING
) << "Malformed cpu_brand entry " << entry
->id();
638 dictionary_entry_count
++;
641 const base::DictionaryValue
* perf_graphics_value
= NULL
;
642 if (value
->GetDictionary("perf_graphics", &perf_graphics_value
)) {
644 std::string float_value
;
645 std::string float_value2
;
646 perf_graphics_value
->GetString(kOp
, &op
);
647 perf_graphics_value
->GetString("value", &float_value
);
648 perf_graphics_value
->GetString("value2", &float_value2
);
649 if (!entry
->SetPerfGraphicsInfo(op
, float_value
, float_value2
)) {
650 LOG(WARNING
) << "Malformed perf_graphics entry " << entry
->id();
653 dictionary_entry_count
++;
656 const base::DictionaryValue
* perf_gaming_value
= NULL
;
657 if (value
->GetDictionary("perf_gaming", &perf_gaming_value
)) {
659 std::string float_value
;
660 std::string float_value2
;
661 perf_gaming_value
->GetString(kOp
, &op
);
662 perf_gaming_value
->GetString("value", &float_value
);
663 perf_gaming_value
->GetString("value2", &float_value2
);
664 if (!entry
->SetPerfGamingInfo(op
, float_value
, float_value2
)) {
665 LOG(WARNING
) << "Malformed perf_gaming entry " << entry
->id();
668 dictionary_entry_count
++;
671 const base::DictionaryValue
* perf_overall_value
= NULL
;
672 if (value
->GetDictionary("perf_overall", &perf_overall_value
)) {
674 std::string float_value
;
675 std::string float_value2
;
676 perf_overall_value
->GetString(kOp
, &op
);
677 perf_overall_value
->GetString("value", &float_value
);
678 perf_overall_value
->GetString("value2", &float_value2
);
679 if (!entry
->SetPerfOverallInfo(op
, float_value
, float_value2
)) {
680 LOG(WARNING
) << "Malformed perf_overall entry " << entry
->id();
683 dictionary_entry_count
++;
686 const base::DictionaryValue
* machine_model_value
= NULL
;
687 if (value
->GetDictionary("machine_model", &machine_model_value
)) {
689 std::string name_value
;
690 const base::DictionaryValue
* name
= NULL
;
691 if (machine_model_value
->GetDictionary("name", &name
)) {
692 name
->GetString(kOp
, &name_op
);
693 name
->GetString("value", &name_value
);
696 std::string version_op
= "any";
697 std::string version_string
;
698 std::string version_string2
;
699 const base::DictionaryValue
* version_value
= NULL
;
700 if (machine_model_value
->GetDictionary("version", &version_value
)) {
701 version_value
->GetString(kOp
, &version_op
);
702 version_value
->GetString("number", &version_string
);
703 version_value
->GetString("number2", &version_string2
);
705 if (!entry
->SetMachineModelInfo(
706 name_op
, name_value
, version_op
, version_string
, version_string2
)) {
707 LOG(WARNING
) << "Malformed machine_model entry " << entry
->id();
710 dictionary_entry_count
++;
713 const base::DictionaryValue
* gpu_count_value
= NULL
;
714 if (value
->GetDictionary("gpu_count", &gpu_count_value
)) {
716 std::string int_value
;
717 std::string int_value2
;
718 gpu_count_value
->GetString(kOp
, &op
);
719 gpu_count_value
->GetString("value", &int_value
);
720 gpu_count_value
->GetString("value2", &int_value2
);
721 if (!entry
->SetGpuCountInfo(op
, int_value
, int_value2
)) {
722 LOG(WARNING
) << "Malformed gpu_count entry " << entry
->id();
725 dictionary_entry_count
++;
729 const base::ListValue
* feature_value
= NULL
;
730 if (value
->GetList("features", &feature_value
)) {
731 std::vector
<std::string
> feature_list
;
732 for (size_t i
= 0; i
< feature_value
->GetSize(); ++i
) {
734 if (feature_value
->GetString(i
, &feature
)) {
735 feature_list
.push_back(feature
);
737 LOG(WARNING
) << "Malformed feature entry " << entry
->id();
741 if (!entry
->SetFeatures(
742 feature_list
, feature_map
, supports_feature_type_all
)) {
743 LOG(WARNING
) << "Malformed feature entry " << entry
->id();
746 dictionary_entry_count
++;
751 const base::ListValue
* exception_list_value
= NULL
;
752 if (value
->GetList("exceptions", &exception_list_value
)) {
753 for (size_t i
= 0; i
< exception_list_value
->GetSize(); ++i
) {
754 const base::DictionaryValue
* exception_value
= NULL
;
755 if (!exception_list_value
->GetDictionary(i
, &exception_value
)) {
756 LOG(WARNING
) << "Malformed exceptions entry " << entry
->id();
759 ScopedGpuControlListEntry
exception(GetEntryFromValue(
760 exception_value
, false, feature_map
, supports_feature_type_all
));
761 if (exception
.get() == NULL
) {
762 LOG(WARNING
) << "Malformed exceptions entry " << entry
->id();
765 // Exception should inherit vendor_id from parent, otherwise if only
766 // device_ids are specified in Exception, the info will be incomplete.
767 if (exception
->vendor_id_
== 0 && entry
->vendor_id_
!= 0)
768 exception
->vendor_id_
= entry
->vendor_id_
;
769 if (exception
->contains_unknown_fields_
) {
770 LOG(WARNING
) << "Exception with unknown fields " << entry
->id();
771 entry
->contains_unknown_fields_
= true;
773 entry
->AddException(exception
);
776 dictionary_entry_count
++;
779 const base::DictionaryValue
* browser_version_value
= NULL
;
780 // browser_version is processed in LoadGpuControlList().
781 if (value
->GetDictionary("browser_version", &browser_version_value
))
782 dictionary_entry_count
++;
785 if (value
->size() != dictionary_entry_count
) {
786 LOG(WARNING
) << "Entry with unknown fields " << entry
->id();
787 entry
->contains_unknown_fields_
= true;
792 GpuControlList::GpuControlListEntry::GpuControlListEntry()
796 multi_gpu_style_(kMultiGpuStyleNone
),
797 multi_gpu_category_(kMultiGpuCategoryPrimary
),
798 contains_unknown_fields_(false),
799 contains_unknown_features_(false) {
802 GpuControlList::GpuControlListEntry::~GpuControlListEntry() { }
804 bool GpuControlList::GpuControlListEntry::SetId(uint32 id
) {
812 void GpuControlList::GpuControlListEntry::SetDisabled(bool disabled
) {
813 disabled_
= disabled
;
816 bool GpuControlList::GpuControlListEntry::SetOsInfo(
817 const std::string
& os
,
818 const std::string
& version_op
,
819 const std::string
& version_string
,
820 const std::string
& version_string2
) {
821 os_info_
.reset(new OsInfo(os
, version_op
, version_string
, version_string2
));
822 return os_info_
->IsValid();
825 bool GpuControlList::GpuControlListEntry::SetVendorId(
826 const std::string
& vendor_id_string
) {
828 return base::HexStringToInt(vendor_id_string
,
829 reinterpret_cast<int*>(&vendor_id_
));
832 bool GpuControlList::GpuControlListEntry::AddDeviceId(
833 const std::string
& device_id_string
) {
834 uint32 device_id
= 0;
835 if (base::HexStringToInt(device_id_string
,
836 reinterpret_cast<int*>(&device_id
))) {
837 device_id_list_
.push_back(device_id
);
843 bool GpuControlList::GpuControlListEntry::SetMultiGpuStyle(
844 const std::string
& multi_gpu_style_string
) {
845 MultiGpuStyle style
= StringToMultiGpuStyle(multi_gpu_style_string
);
846 if (style
== kMultiGpuStyleNone
)
848 multi_gpu_style_
= style
;
852 bool GpuControlList::GpuControlListEntry::SetMultiGpuCategory(
853 const std::string
& multi_gpu_category_string
) {
854 MultiGpuCategory category
=
855 StringToMultiGpuCategory(multi_gpu_category_string
);
856 if (category
== kMultiGpuCategoryNone
)
858 multi_gpu_category_
= category
;
862 bool GpuControlList::GpuControlListEntry::SetDriverVendorInfo(
863 const std::string
& vendor_op
,
864 const std::string
& vendor_value
) {
865 driver_vendor_info_
.reset(new StringInfo(vendor_op
, vendor_value
));
866 return driver_vendor_info_
->IsValid();
869 bool GpuControlList::GpuControlListEntry::SetDriverVersionInfo(
870 const std::string
& version_op
,
871 const std::string
& version_style
,
872 const std::string
& version_string
,
873 const std::string
& version_string2
) {
874 driver_version_info_
.reset(new VersionInfo(
875 version_op
, version_style
, version_string
, version_string2
));
876 return driver_version_info_
->IsValid();
879 bool GpuControlList::GpuControlListEntry::SetDriverDateInfo(
880 const std::string
& date_op
,
881 const std::string
& date_string
,
882 const std::string
& date_string2
) {
883 driver_date_info_
.reset(
884 new VersionInfo(date_op
, std::string(), date_string
, date_string2
));
885 return driver_date_info_
->IsValid();
888 bool GpuControlList::GpuControlListEntry::SetGLVendorInfo(
889 const std::string
& vendor_op
,
890 const std::string
& vendor_value
) {
891 gl_vendor_info_
.reset(new StringInfo(vendor_op
, vendor_value
));
892 return gl_vendor_info_
->IsValid();
895 bool GpuControlList::GpuControlListEntry::SetGLRendererInfo(
896 const std::string
& renderer_op
,
897 const std::string
& renderer_value
) {
898 gl_renderer_info_
.reset(new StringInfo(renderer_op
, renderer_value
));
899 return gl_renderer_info_
->IsValid();
902 bool GpuControlList::GpuControlListEntry::SetGLExtensionsInfo(
903 const std::string
& extensions_op
,
904 const std::string
& extensions_value
) {
905 gl_extensions_info_
.reset(new StringInfo(extensions_op
, extensions_value
));
906 return gl_extensions_info_
->IsValid();
909 bool GpuControlList::GpuControlListEntry::SetCpuBrand(
910 const std::string
& cpu_op
,
911 const std::string
& cpu_value
) {
912 cpu_brand_
.reset(new StringInfo(cpu_op
, cpu_value
));
913 return cpu_brand_
->IsValid();
916 bool GpuControlList::GpuControlListEntry::SetPerfGraphicsInfo(
917 const std::string
& op
,
918 const std::string
& float_string
,
919 const std::string
& float_string2
) {
920 perf_graphics_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
921 return perf_graphics_info_
->IsValid();
924 bool GpuControlList::GpuControlListEntry::SetPerfGamingInfo(
925 const std::string
& op
,
926 const std::string
& float_string
,
927 const std::string
& float_string2
) {
928 perf_gaming_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
929 return perf_gaming_info_
->IsValid();
932 bool GpuControlList::GpuControlListEntry::SetPerfOverallInfo(
933 const std::string
& op
,
934 const std::string
& float_string
,
935 const std::string
& float_string2
) {
936 perf_overall_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
937 return perf_overall_info_
->IsValid();
940 bool GpuControlList::GpuControlListEntry::SetMachineModelInfo(
941 const std::string
& name_op
,
942 const std::string
& name_value
,
943 const std::string
& version_op
,
944 const std::string
& version_string
,
945 const std::string
& version_string2
) {
946 machine_model_info_
.reset(new MachineModelInfo(
947 name_op
, name_value
, version_op
, version_string
, version_string2
));
948 return machine_model_info_
->IsValid();
951 bool GpuControlList::GpuControlListEntry::SetGpuCountInfo(
952 const std::string
& op
,
953 const std::string
& int_string
,
954 const std::string
& int_string2
) {
955 gpu_count_info_
.reset(new IntInfo(op
, int_string
, int_string2
));
956 return gpu_count_info_
->IsValid();
959 bool GpuControlList::GpuControlListEntry::SetFeatures(
960 const std::vector
<std::string
>& feature_strings
,
961 const FeatureMap
& feature_map
,
962 bool supports_feature_type_all
) {
963 size_t size
= feature_strings
.size();
967 for (size_t i
= 0; i
< size
; ++i
) {
969 if (supports_feature_type_all
&& feature_strings
[i
] == "all") {
970 for (FeatureMap::const_iterator iter
= feature_map
.begin();
971 iter
!= feature_map
.end(); ++iter
)
972 features_
.insert(iter
->second
);
975 if (StringToFeature(feature_strings
[i
], &feature
, feature_map
))
976 features_
.insert(feature
);
978 contains_unknown_features_
= true;
983 void GpuControlList::GpuControlListEntry::AddException(
984 ScopedGpuControlListEntry exception
) {
985 exceptions_
.push_back(exception
);
989 GpuControlList::GpuControlListEntry::MultiGpuStyle
990 GpuControlList::GpuControlListEntry::StringToMultiGpuStyle(
991 const std::string
& style
) {
992 if (style
== kMultiGpuStyleStringOptimus
)
993 return kMultiGpuStyleOptimus
;
994 if (style
== kMultiGpuStyleStringAMDSwitchable
)
995 return kMultiGpuStyleAMDSwitchable
;
996 return kMultiGpuStyleNone
;
1000 GpuControlList::GpuControlListEntry::MultiGpuCategory
1001 GpuControlList::GpuControlListEntry::StringToMultiGpuCategory(
1002 const std::string
& category
) {
1003 if (category
== kMultiGpuCategoryStringPrimary
)
1004 return kMultiGpuCategoryPrimary
;
1005 if (category
== kMultiGpuCategoryStringSecondary
)
1006 return kMultiGpuCategorySecondary
;
1007 if (category
== kMultiGpuCategoryStringAny
)
1008 return kMultiGpuCategoryAny
;
1009 return kMultiGpuCategoryNone
;
1012 bool GpuControlList::GpuControlListEntry::Contains(
1013 OsType os_type
, const std::string
& os_version
,
1014 const GPUInfo
& gpu_info
) const {
1015 DCHECK(os_type
!= kOsAny
);
1016 if (os_info_
.get() != NULL
&& !os_info_
->Contains(os_type
, os_version
))
1018 bool is_not_primary_gpu
=
1019 GpuUnmatched(vendor_id_
, device_id_list_
, gpu_info
.gpu
);
1020 bool is_not_secondary_gpu
= true;
1021 for (size_t i
= 0; i
< gpu_info
.secondary_gpus
.size(); ++i
) {
1022 is_not_secondary_gpu
= is_not_secondary_gpu
&&
1023 GpuUnmatched(vendor_id_
, device_id_list_
, gpu_info
.secondary_gpus
[i
]);
1025 switch (multi_gpu_category_
) {
1026 case kMultiGpuCategoryPrimary
:
1027 if (is_not_primary_gpu
)
1030 case kMultiGpuCategorySecondary
:
1031 if (is_not_secondary_gpu
)
1034 case kMultiGpuCategoryAny
:
1035 if (is_not_primary_gpu
&& is_not_secondary_gpu
)
1038 case kMultiGpuCategoryNone
:
1041 switch (multi_gpu_style_
) {
1042 case kMultiGpuStyleOptimus
:
1043 if (!gpu_info
.optimus
)
1046 case kMultiGpuStyleAMDSwitchable
:
1047 if (!gpu_info
.amd_switchable
)
1050 case kMultiGpuStyleNone
:
1053 if (driver_vendor_info_
.get() != NULL
&& !gpu_info
.driver_vendor
.empty() &&
1054 !driver_vendor_info_
->Contains(gpu_info
.driver_vendor
))
1056 if (driver_version_info_
.get() != NULL
&& !gpu_info
.driver_version
.empty()) {
1057 if (!driver_version_info_
->Contains(gpu_info
.driver_version
))
1060 if (driver_date_info_
.get() != NULL
&& !gpu_info
.driver_date
.empty()) {
1061 if (!driver_date_info_
->Contains(gpu_info
.driver_date
, '-'))
1064 if (gl_vendor_info_
.get() != NULL
&& !gpu_info
.gl_vendor
.empty() &&
1065 !gl_vendor_info_
->Contains(gpu_info
.gl_vendor
))
1067 if (gl_renderer_info_
.get() != NULL
&& !gpu_info
.gl_renderer
.empty() &&
1068 !gl_renderer_info_
->Contains(gpu_info
.gl_renderer
))
1070 if (gl_extensions_info_
.get() != NULL
&& !gpu_info
.gl_extensions
.empty() &&
1071 !gl_extensions_info_
->Contains(gpu_info
.gl_extensions
))
1073 if (perf_graphics_info_
.get() != NULL
&&
1074 (gpu_info
.performance_stats
.graphics
== 0.0 ||
1075 !perf_graphics_info_
->Contains(gpu_info
.performance_stats
.graphics
)))
1077 if (perf_gaming_info_
.get() != NULL
&&
1078 (gpu_info
.performance_stats
.gaming
== 0.0 ||
1079 !perf_gaming_info_
->Contains(gpu_info
.performance_stats
.gaming
)))
1081 if (perf_overall_info_
.get() != NULL
&&
1082 (gpu_info
.performance_stats
.overall
== 0.0 ||
1083 !perf_overall_info_
->Contains(gpu_info
.performance_stats
.overall
)))
1085 if (machine_model_info_
.get() != NULL
) {
1086 std::vector
<std::string
> name_version
;
1087 base::SplitString(gpu_info
.machine_model
, ' ', &name_version
);
1088 if (name_version
.size() == 2 &&
1089 !machine_model_info_
->Contains(name_version
[0], name_version
[1]))
1092 if (gpu_count_info_
.get() != NULL
&&
1093 !gpu_count_info_
->Contains(gpu_info
.secondary_gpus
.size() + 1))
1095 if (cpu_brand_
.get() != NULL
) {
1097 if (!cpu_brand_
->Contains(cpu_info
.cpu_brand()))
1101 for (size_t i
= 0; i
< exceptions_
.size(); ++i
) {
1102 if (exceptions_
[i
]->Contains(os_type
, os_version
, gpu_info
) &&
1103 !exceptions_
[i
]->NeedsMoreInfo(gpu_info
))
1109 bool GpuControlList::GpuControlListEntry::NeedsMoreInfo(
1110 const GPUInfo
& gpu_info
) const {
1111 // We only check for missing info that might be collected with a gl context.
1112 // If certain info is missing due to some error, say, we fail to collect
1113 // vendor_id/device_id, then even if we launch GPU process and create a gl
1114 // context, we won't gather such missing info, so we still return false.
1115 if (driver_vendor_info_
.get() && gpu_info
.driver_vendor
.empty())
1117 if (driver_version_info_
.get() && gpu_info
.driver_version
.empty())
1119 if (gl_vendor_info_
.get() && gpu_info
.gl_vendor
.empty())
1121 if (gl_renderer_info_
.get() && gpu_info
.gl_renderer
.empty())
1123 for (size_t i
= 0; i
< exceptions_
.size(); ++i
) {
1124 if (exceptions_
[i
]->NeedsMoreInfo(gpu_info
))
1130 GpuControlList::OsType
GpuControlList::GpuControlListEntry::GetOsType() const {
1131 if (os_info_
.get() == NULL
)
1133 return os_info_
->type();
1136 uint32
GpuControlList::GpuControlListEntry::id() const {
1140 bool GpuControlList::GpuControlListEntry::disabled() const {
1144 const std::set
<int>& GpuControlList::GpuControlListEntry::features() const {
1149 bool GpuControlList::GpuControlListEntry::StringToFeature(
1150 const std::string
& feature_name
, int* feature_id
,
1151 const FeatureMap
& feature_map
) {
1152 FeatureMap::const_iterator iter
= feature_map
.find(feature_name
);
1153 if (iter
!= feature_map
.end()) {
1154 *feature_id
= iter
->second
;
1160 GpuControlList::GpuControlList()
1162 contains_unknown_fields_(false),
1163 needs_more_info_(false),
1164 supports_feature_type_all_(false) {
1167 GpuControlList::~GpuControlList() {
1171 bool GpuControlList::LoadList(
1172 const std::string
& json_context
, GpuControlList::OsFilter os_filter
) {
1173 const std::string browser_version_string
= "0";
1174 return LoadList(browser_version_string
, json_context
, os_filter
);
1177 bool GpuControlList::LoadList(
1178 const std::string
& browser_version_string
,
1179 const std::string
& json_context
,
1180 GpuControlList::OsFilter os_filter
) {
1181 std::vector
<std::string
> pieces
;
1182 if (!ProcessVersionString(browser_version_string
, '.', &pieces
))
1184 browser_version_
= browser_version_string
;
1186 scoped_ptr
<base::Value
> root
;
1187 root
.reset(base::JSONReader::Read(json_context
));
1188 if (root
.get() == NULL
|| !root
->IsType(base::Value::TYPE_DICTIONARY
))
1191 base::DictionaryValue
* root_dictionary
=
1192 static_cast<base::DictionaryValue
*>(root
.get());
1193 DCHECK(root_dictionary
);
1194 return LoadList(*root_dictionary
, os_filter
);
1197 bool GpuControlList::LoadList(const base::DictionaryValue
& parsed_json
,
1198 GpuControlList::OsFilter os_filter
) {
1199 std::vector
<ScopedGpuControlListEntry
> entries
;
1201 parsed_json
.GetString("version", &version_
);
1202 std::vector
<std::string
> pieces
;
1203 if (!ProcessVersionString(version_
, '.', &pieces
))
1206 const base::ListValue
* list
= NULL
;
1207 if (!parsed_json
.GetList("entries", &list
))
1210 uint32 max_entry_id
= 0;
1211 bool contains_unknown_fields
= false;
1212 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
1213 const base::DictionaryValue
* list_item
= NULL
;
1214 bool valid
= list
->GetDictionary(i
, &list_item
);
1215 if (!valid
|| list_item
== NULL
)
1217 // Check browser version compatibility: if the entry is not for the
1218 // current browser version, don't process it.
1219 BrowserVersionSupport browser_version_support
=
1220 IsEntrySupportedByCurrentBrowserVersion(list_item
);
1221 if (browser_version_support
== kMalformed
)
1223 if (browser_version_support
== kUnsupported
)
1225 DCHECK(browser_version_support
== kSupported
);
1226 ScopedGpuControlListEntry
entry(GpuControlListEntry::GetEntryFromValue(
1227 list_item
, true, feature_map_
, supports_feature_type_all_
));
1228 if (entry
.get() == NULL
)
1230 if (entry
->id() > max_entry_id
)
1231 max_entry_id
= entry
->id();
1232 // If an unknown field is encountered, skip the entry; if an unknown
1233 // feature is encountered, ignore the feature, but keep the entry.
1234 if (entry
->contains_unknown_fields()) {
1235 contains_unknown_fields
= true;
1238 if (entry
->contains_unknown_features())
1239 contains_unknown_fields
= true;
1240 entries
.push_back(entry
);
1244 OsType my_os
= GetOsType();
1245 for (size_t i
= 0; i
< entries
.size(); ++i
) {
1246 OsType entry_os
= entries
[i
]->GetOsType();
1247 if (os_filter
== GpuControlList::kAllOs
||
1248 entry_os
== kOsAny
|| entry_os
== my_os
)
1249 entries_
.push_back(entries
[i
]);
1251 max_entry_id_
= max_entry_id
;
1252 contains_unknown_fields_
= contains_unknown_fields
;
1256 std::set
<int> GpuControlList::MakeDecision(
1257 GpuControlList::OsType os
,
1258 std::string os_version
,
1259 const GPUInfo
& gpu_info
) {
1260 active_entries_
.clear();
1261 std::set
<int> features
;
1263 needs_more_info_
= false;
1264 std::set
<int> possible_features
;
1268 if (os_version
.empty()) {
1269 os_version
= base::SysInfo::OperatingSystemVersion();
1270 size_t pos
= os_version
.find_first_not_of("0123456789.");
1271 if (pos
!= std::string::npos
)
1272 os_version
= os_version
.substr(0, pos
);
1274 std::vector
<std::string
> pieces
;
1275 if (!ProcessVersionString(os_version
, '.', &pieces
))
1278 for (size_t i
= 0; i
< entries_
.size(); ++i
) {
1279 if (entries_
[i
]->Contains(os
, os_version
, gpu_info
)) {
1280 if (!entries_
[i
]->disabled()) {
1281 MergeFeatureSets(&possible_features
, entries_
[i
]->features());
1282 if (!entries_
[i
]->NeedsMoreInfo(gpu_info
))
1283 MergeFeatureSets(&features
, entries_
[i
]->features());
1285 active_entries_
.push_back(entries_
[i
]);
1289 if (possible_features
.size() > features
.size())
1290 needs_more_info_
= true;
1295 void GpuControlList::GetDecisionEntries(
1296 std::vector
<uint32
>* entry_ids
, bool disabled
) const {
1299 for (size_t i
= 0; i
< active_entries_
.size(); ++i
) {
1300 if (disabled
== active_entries_
[i
]->disabled())
1301 entry_ids
->push_back(active_entries_
[i
]->id());
1305 void GpuControlList::GetReasons(base::ListValue
* problem_list
) const {
1306 DCHECK(problem_list
);
1307 for (size_t i
= 0; i
< active_entries_
.size(); ++i
) {
1308 GpuControlListEntry
* entry
= active_entries_
[i
].get();
1309 if (entry
->disabled())
1311 base::DictionaryValue
* problem
= new base::DictionaryValue();
1313 problem
->SetString("description", entry
->description());
1315 base::ListValue
* cr_bugs
= new base::ListValue();
1316 for (size_t j
= 0; j
< entry
->cr_bugs().size(); ++j
)
1317 cr_bugs
->Append(new base::FundamentalValue(entry
->cr_bugs()[j
]));
1318 problem
->Set("crBugs", cr_bugs
);
1320 base::ListValue
* webkit_bugs
= new base::ListValue();
1321 for (size_t j
= 0; j
< entry
->webkit_bugs().size(); ++j
) {
1322 webkit_bugs
->Append(new base::FundamentalValue(entry
->webkit_bugs()[j
]));
1324 problem
->Set("webkitBugs", webkit_bugs
);
1326 problem_list
->Append(problem
);
1330 size_t GpuControlList::num_entries() const {
1331 return entries_
.size();
1334 uint32
GpuControlList::max_entry_id() const {
1335 return max_entry_id_
;
1338 std::string
GpuControlList::version() const {
1342 GpuControlList::OsType
GpuControlList::GetOsType() {
1343 #if defined(OS_CHROMEOS)
1345 #elif defined(OS_WIN)
1347 #elif defined(OS_ANDROID)
1349 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
1351 #elif defined(OS_MACOSX)
1358 void GpuControlList::Clear() {
1360 active_entries_
.clear();
1362 contains_unknown_fields_
= false;
1365 GpuControlList::BrowserVersionSupport
1366 GpuControlList::IsEntrySupportedByCurrentBrowserVersion(
1367 const base::DictionaryValue
* value
) {
1369 const base::DictionaryValue
* browser_version_value
= NULL
;
1370 if (value
->GetDictionary("browser_version", &browser_version_value
)) {
1371 std::string version_op
= "any";
1372 std::string version_string
;
1373 std::string version_string2
;
1374 browser_version_value
->GetString(kOp
, &version_op
);
1375 browser_version_value
->GetString("number", &version_string
);
1376 browser_version_value
->GetString("number2", &version_string2
);
1377 scoped_ptr
<VersionInfo
> browser_version_info
;
1378 browser_version_info
.reset(new VersionInfo(
1379 version_op
, std::string(), version_string
, version_string2
));
1380 if (!browser_version_info
->IsValid())
1382 if (browser_version_info
->Contains(browser_version_
))
1384 return kUnsupported
;
1390 GpuControlList::NumericOp
GpuControlList::StringToNumericOp(
1391 const std::string
& op
) {
1404 if (op
== "between")
1409 void GpuControlList::AddSupportedFeature(
1410 const std::string
& feature_name
, int feature_id
) {
1411 feature_map_
[feature_name
] = feature_id
;
1414 void GpuControlList::set_supports_feature_type_all(bool supported
) {
1415 supports_feature_type_all_
= supported
;