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/strings/stringprintf.h"
14 #include "base/sys_info.h"
15 #include "gpu/config/gpu_info.h"
16 #include "gpu/config/gpu_util.h"
21 // Break a version string into segments. Return true if each segment is
23 bool ProcessVersionString(const std::string
& version_string
,
25 std::vector
<std::string
>* version
) {
27 base::SplitString(version_string
, splitter
, version
);
28 if (version
->size() == 0)
30 // If the splitter is '-', we assume it's a date with format "mm-dd-yyyy";
31 // we split it into the order of "yyyy", "mm", "dd".
32 if (splitter
== '-') {
33 std::string year
= (*version
)[version
->size() - 1];
34 for (int i
= version
->size() - 1; i
> 0; --i
) {
35 (*version
)[i
] = (*version
)[i
- 1];
39 for (size_t i
= 0; i
< version
->size(); ++i
) {
41 if (!base::StringToUint((*version
)[i
], &num
))
47 // Compare two number strings using numerical ordering.
48 // Return 0 if number = number_ref,
49 // 1 if number > number_ref,
50 // -1 if number < number_ref.
51 int CompareNumericalNumberStrings(
52 const std::string
& number
, const std::string
& number_ref
) {
55 bool valid
= base::StringToUint(number
, &value1
);
57 valid
= base::StringToUint(number_ref
, &value2
);
66 // Compare two number strings using lexical ordering.
67 // Return 0 if number = number_ref,
68 // 1 if number > number_ref,
69 // -1 if number < number_ref.
70 // We only compare as many digits as number_ref contains.
71 // If number_ref is xxx, it's considered as xxx*
72 // For example: CompareLexicalNumberStrings("121", "12") returns 0,
73 // CompareLexicalNumberStrings("12", "121") returns -1.
74 int CompareLexicalNumberStrings(
75 const std::string
& number
, const std::string
& number_ref
) {
76 for (size_t i
= 0; i
< number_ref
.length(); ++i
) {
78 if (i
< number
.length())
79 value1
= number
[i
] - '0';
80 unsigned value2
= number_ref
[i
] - '0';
89 bool GpuUnmatched(uint32 vendor_id
, const std::vector
<uint32
>& device_id_list
,
90 const GPUInfo::GPUDevice
& gpu
) {
93 if (vendor_id
!= gpu
.vendor_id
)
95 bool device_specified
= false;
96 for (size_t i
= 0; i
< device_id_list
.size(); ++i
) {
97 if (device_id_list
[i
] == 0)
99 if (device_id_list
[i
] == gpu
.device_id
)
101 device_specified
= true;
103 return device_specified
;
106 const char kMultiGpuStyleStringAMDSwitchable
[] = "amd_switchable";
107 const char kMultiGpuStyleStringOptimus
[] = "optimus";
109 const char kMultiGpuCategoryStringPrimary
[] = "primary";
110 const char kMultiGpuCategoryStringSecondary
[] = "secondary";
111 const char kMultiGpuCategoryStringAny
[] = "any";
113 const char kVersionStyleStringNumerical
[] = "numerical";
114 const char kVersionStyleStringLexical
[] = "lexical";
116 const char kOp
[] = "op";
118 } // namespace anonymous
120 GpuControlList::VersionInfo::VersionInfo(
121 const std::string
& version_op
,
122 const std::string
& version_style
,
123 const std::string
& version_string
,
124 const std::string
& version_string2
)
125 : version_style_(kVersionStyleNumerical
) {
126 op_
= StringToNumericOp(version_op
);
127 if (op_
== kUnknown
|| op_
== kAny
)
129 version_style_
= StringToVersionStyle(version_style
);
130 if (!ProcessVersionString(version_string
, '.', &version_
)) {
134 if (op_
== kBetween
) {
135 if (!ProcessVersionString(version_string2
, '.', &version2_
))
140 GpuControlList::VersionInfo::~VersionInfo() {
143 bool GpuControlList::VersionInfo::Contains(
144 const std::string
& version_string
) const {
145 return Contains(version_string
, '.');
148 bool GpuControlList::VersionInfo::Contains(
149 const std::string
& version_string
, char splitter
) const {
154 std::vector
<std::string
> version
;
155 if (!ProcessVersionString(version_string
, splitter
, &version
))
157 int relation
= Compare(version
, version_
, version_style_
);
159 return (relation
== 0);
161 return (relation
< 0);
163 return (relation
<= 0);
165 return (relation
> 0);
167 return (relation
>= 0);
171 return Compare(version
, version2_
, version_style_
) <= 0;
174 bool GpuControlList::VersionInfo::IsValid() const {
175 return (op_
!= kUnknown
&& version_style_
!= kVersionStyleUnknown
);
178 bool GpuControlList::VersionInfo::IsLexical() const {
179 return version_style_
== kVersionStyleLexical
;
183 int GpuControlList::VersionInfo::Compare(
184 const std::vector
<std::string
>& version
,
185 const std::vector
<std::string
>& version_ref
,
186 VersionStyle version_style
) {
187 DCHECK(version
.size() > 0 && version_ref
.size() > 0);
188 DCHECK(version_style
!= kVersionStyleUnknown
);
189 for (size_t i
= 0; i
< version_ref
.size(); ++i
) {
190 if (i
>= version
.size())
193 // We assume both versions are checked by ProcessVersionString().
194 if (i
> 0 && version_style
== kVersionStyleLexical
)
195 ret
= CompareLexicalNumberStrings(version
[i
], version_ref
[i
]);
197 ret
= CompareNumericalNumberStrings(version
[i
], version_ref
[i
]);
205 GpuControlList::VersionInfo::VersionStyle
206 GpuControlList::VersionInfo::StringToVersionStyle(
207 const std::string
& version_style
) {
208 if (version_style
.empty() || version_style
== kVersionStyleStringNumerical
)
209 return kVersionStyleNumerical
;
210 if (version_style
== kVersionStyleStringLexical
)
211 return kVersionStyleLexical
;
212 return kVersionStyleUnknown
;
215 GpuControlList::OsInfo::OsInfo(const std::string
& os
,
216 const std::string
& version_op
,
217 const std::string
& version_string
,
218 const std::string
& version_string2
) {
219 type_
= StringToOsType(os
);
220 if (type_
!= kOsUnknown
) {
221 version_info_
.reset(new VersionInfo(
222 version_op
, std::string(), version_string
, version_string2
));
226 GpuControlList::OsInfo::~OsInfo() {}
228 bool GpuControlList::OsInfo::Contains(OsType type
,
229 const std::string
& version
) const {
232 if (type_
!= type
&& type_
!= kOsAny
)
234 return version_info_
->Contains(version
);
237 bool GpuControlList::OsInfo::IsValid() const {
238 return type_
!= kOsUnknown
&& version_info_
->IsValid();
241 GpuControlList::OsType
GpuControlList::OsInfo::type() const {
245 GpuControlList::OsType
GpuControlList::OsInfo::StringToOsType(
246 const std::string
& os
) {
249 else if (os
== "macosx")
251 else if (os
== "android")
253 else if (os
== "linux")
255 else if (os
== "chromeos")
257 else if (os
== "any")
262 GpuControlList::MachineModelInfo::MachineModelInfo(
263 const std::string
& name_op
,
264 const std::string
& name_value
,
265 const std::string
& version_op
,
266 const std::string
& version_string
,
267 const std::string
& version_string2
) {
268 name_info_
.reset(new StringInfo(name_op
, name_value
));
269 version_info_
.reset(new VersionInfo(
270 version_op
, std::string(), version_string
, version_string2
));
273 GpuControlList::MachineModelInfo::~MachineModelInfo() {}
275 bool GpuControlList::MachineModelInfo::Contains(
276 const std::string
& name
, const std::string
& version
) const {
279 if (!name_info_
->Contains(name
))
281 return version_info_
->Contains(version
);
284 bool GpuControlList::MachineModelInfo::IsValid() const {
285 return name_info_
->IsValid() && version_info_
->IsValid();
288 GpuControlList::StringInfo::StringInfo(const std::string
& string_op
,
289 const std::string
& string_value
) {
290 op_
= StringToOp(string_op
);
291 value_
= StringToLowerASCII(string_value
);
294 bool GpuControlList::StringInfo::Contains(const std::string
& value
) const {
295 std::string my_value
= StringToLowerASCII(value
);
298 return strstr(my_value
.c_str(), value_
.c_str()) != NULL
;
300 return StartsWithASCII(my_value
, value_
, false);
302 return EndsWith(my_value
, value_
, false);
304 return value_
== my_value
;
310 bool GpuControlList::StringInfo::IsValid() const {
311 return op_
!= kUnknown
;
314 GpuControlList::StringInfo::Op
GpuControlList::StringInfo::StringToOp(
315 const std::string
& string_op
) {
316 if (string_op
== "=")
318 else if (string_op
== "contains")
320 else if (string_op
== "beginwith")
322 else if (string_op
== "endwith")
327 GpuControlList::FloatInfo::FloatInfo(const std::string
& float_op
,
328 const std::string
& float_value
,
329 const std::string
& float_value2
)
333 op_
= StringToNumericOp(float_op
);
337 if (!base::StringToDouble(float_value
, &dvalue
)) {
341 value_
= static_cast<float>(dvalue
);
342 if (op_
== kBetween
) {
343 if (!base::StringToDouble(float_value2
, &dvalue
)) {
347 value2_
= static_cast<float>(dvalue
);
351 bool GpuControlList::FloatInfo::Contains(float value
) const {
357 return (value
== value_
);
359 return (value
< value_
);
361 return (value
<= value_
);
363 return (value
> value_
);
365 return (value
>= value_
);
366 DCHECK(op_
== kBetween
);
367 return ((value_
<= value
&& value
<= value2_
) ||
368 (value2_
<= value
&& value
<= value_
));
371 bool GpuControlList::FloatInfo::IsValid() const {
372 return op_
!= kUnknown
;
375 GpuControlList::IntInfo::IntInfo(const std::string
& int_op
,
376 const std::string
& int_value
,
377 const std::string
& int_value2
)
381 op_
= StringToNumericOp(int_op
);
384 if (!base::StringToInt(int_value
, &value_
)) {
388 if (op_
== kBetween
&&
389 !base::StringToInt(int_value2
, &value2_
))
393 bool GpuControlList::IntInfo::Contains(int value
) const {
399 return (value
== value_
);
401 return (value
< value_
);
403 return (value
<= value_
);
405 return (value
> value_
);
407 return (value
>= value_
);
408 DCHECK(op_
== kBetween
);
409 return ((value_
<= value
&& value
<= value2_
) ||
410 (value2_
<= value
&& value
<= value_
));
413 bool GpuControlList::IntInfo::IsValid() const {
414 return op_
!= kUnknown
;
418 GpuControlList::ScopedGpuControlListEntry
419 GpuControlList::GpuControlListEntry::GetEntryFromValue(
420 const base::DictionaryValue
* value
, bool top_level
,
421 const FeatureMap
& feature_map
,
422 bool supports_feature_type_all
) {
424 ScopedGpuControlListEntry
entry(new GpuControlListEntry());
426 size_t dictionary_entry_count
= 0;
430 if (!value
->GetInteger("id", reinterpret_cast<int*>(&id
)) ||
432 LOG(WARNING
) << "Malformed id entry " << entry
->id();
435 dictionary_entry_count
++;
438 if (value
->GetBoolean("disabled", &disabled
)) {
439 entry
->SetDisabled(disabled
);
440 dictionary_entry_count
++;
444 std::string description
;
445 if (value
->GetString("description", &description
)) {
446 entry
->description_
= description
;
447 dictionary_entry_count
++;
449 entry
->description_
= "The GPU is unavailable for an unexplained reason.";
452 const base::ListValue
* cr_bugs
;
453 if (value
->GetList("cr_bugs", &cr_bugs
)) {
454 for (size_t i
= 0; i
< cr_bugs
->GetSize(); ++i
) {
456 if (cr_bugs
->GetInteger(i
, &bug_id
)) {
457 entry
->cr_bugs_
.push_back(bug_id
);
459 LOG(WARNING
) << "Malformed cr_bugs entry " << entry
->id();
463 dictionary_entry_count
++;
466 const base::ListValue
* webkit_bugs
;
467 if (value
->GetList("webkit_bugs", &webkit_bugs
)) {
468 for (size_t i
= 0; i
< webkit_bugs
->GetSize(); ++i
) {
470 if (webkit_bugs
->GetInteger(i
, &bug_id
)) {
471 entry
->webkit_bugs_
.push_back(bug_id
);
473 LOG(WARNING
) << "Malformed webkit_bugs entry " << entry
->id();
477 dictionary_entry_count
++;
480 const base::DictionaryValue
* os_value
= NULL
;
481 if (value
->GetDictionary("os", &os_value
)) {
483 std::string os_version_op
= "any";
484 std::string os_version_string
;
485 std::string os_version_string2
;
486 os_value
->GetString("type", &os_type
);
487 const base::DictionaryValue
* os_version_value
= NULL
;
488 if (os_value
->GetDictionary("version", &os_version_value
)) {
489 os_version_value
->GetString(kOp
, &os_version_op
);
490 os_version_value
->GetString("value", &os_version_string
);
491 os_version_value
->GetString("value2", &os_version_string2
);
493 if (!entry
->SetOsInfo(os_type
, os_version_op
, os_version_string
,
494 os_version_string2
)) {
495 LOG(WARNING
) << "Malformed os entry " << entry
->id();
498 dictionary_entry_count
++;
501 std::string vendor_id
;
502 if (value
->GetString("vendor_id", &vendor_id
)) {
503 if (!entry
->SetVendorId(vendor_id
)) {
504 LOG(WARNING
) << "Malformed vendor_id entry " << entry
->id();
507 dictionary_entry_count
++;
510 const base::ListValue
* device_id_list
;
511 if (value
->GetList("device_id", &device_id_list
)) {
512 for (size_t i
= 0; i
< device_id_list
->GetSize(); ++i
) {
513 std::string device_id
;
514 if (!device_id_list
->GetString(i
, &device_id
) ||
515 !entry
->AddDeviceId(device_id
)) {
516 LOG(WARNING
) << "Malformed device_id entry " << entry
->id();
520 dictionary_entry_count
++;
523 std::string multi_gpu_style
;
524 if (value
->GetString("multi_gpu_style", &multi_gpu_style
)) {
525 if (!entry
->SetMultiGpuStyle(multi_gpu_style
)) {
526 LOG(WARNING
) << "Malformed multi_gpu_style entry " << entry
->id();
529 dictionary_entry_count
++;
532 std::string multi_gpu_category
;
533 if (value
->GetString("multi_gpu_category", &multi_gpu_category
)) {
534 if (!entry
->SetMultiGpuCategory(multi_gpu_category
)) {
535 LOG(WARNING
) << "Malformed multi_gpu_category entry " << entry
->id();
538 dictionary_entry_count
++;
541 const base::DictionaryValue
* driver_vendor_value
= NULL
;
542 if (value
->GetDictionary("driver_vendor", &driver_vendor_value
)) {
543 std::string vendor_op
;
544 std::string vendor_value
;
545 driver_vendor_value
->GetString(kOp
, &vendor_op
);
546 driver_vendor_value
->GetString("value", &vendor_value
);
547 if (!entry
->SetDriverVendorInfo(vendor_op
, vendor_value
)) {
548 LOG(WARNING
) << "Malformed driver_vendor entry " << entry
->id();
551 dictionary_entry_count
++;
554 const base::DictionaryValue
* driver_version_value
= NULL
;
555 if (value
->GetDictionary("driver_version", &driver_version_value
)) {
556 std::string driver_version_op
= "any";
557 std::string driver_version_style
;
558 std::string driver_version_string
;
559 std::string driver_version_string2
;
560 driver_version_value
->GetString(kOp
, &driver_version_op
);
561 driver_version_value
->GetString("style", &driver_version_style
);
562 driver_version_value
->GetString("value", &driver_version_string
);
563 driver_version_value
->GetString("value2", &driver_version_string2
);
564 if (!entry
->SetDriverVersionInfo(driver_version_op
,
565 driver_version_style
,
566 driver_version_string
,
567 driver_version_string2
)) {
568 LOG(WARNING
) << "Malformed driver_version entry " << entry
->id();
571 dictionary_entry_count
++;
574 const base::DictionaryValue
* driver_date_value
= NULL
;
575 if (value
->GetDictionary("driver_date", &driver_date_value
)) {
576 std::string driver_date_op
= "any";
577 std::string driver_date_string
;
578 std::string driver_date_string2
;
579 driver_date_value
->GetString(kOp
, &driver_date_op
);
580 driver_date_value
->GetString("value", &driver_date_string
);
581 driver_date_value
->GetString("value2", &driver_date_string2
);
582 if (!entry
->SetDriverDateInfo(driver_date_op
, driver_date_string
,
583 driver_date_string2
)) {
584 LOG(WARNING
) << "Malformed driver_date entry " << entry
->id();
587 dictionary_entry_count
++;
590 const base::DictionaryValue
* gl_vendor_value
= NULL
;
591 if (value
->GetDictionary("gl_vendor", &gl_vendor_value
)) {
592 std::string vendor_op
;
593 std::string vendor_value
;
594 gl_vendor_value
->GetString(kOp
, &vendor_op
);
595 gl_vendor_value
->GetString("value", &vendor_value
);
596 if (!entry
->SetGLVendorInfo(vendor_op
, vendor_value
)) {
597 LOG(WARNING
) << "Malformed gl_vendor entry " << entry
->id();
600 dictionary_entry_count
++;
603 const base::DictionaryValue
* gl_renderer_value
= NULL
;
604 if (value
->GetDictionary("gl_renderer", &gl_renderer_value
)) {
605 std::string renderer_op
;
606 std::string renderer_value
;
607 gl_renderer_value
->GetString(kOp
, &renderer_op
);
608 gl_renderer_value
->GetString("value", &renderer_value
);
609 if (!entry
->SetGLRendererInfo(renderer_op
, renderer_value
)) {
610 LOG(WARNING
) << "Malformed gl_renderer entry " << entry
->id();
613 dictionary_entry_count
++;
616 const base::DictionaryValue
* gl_extensions_value
= NULL
;
617 if (value
->GetDictionary("gl_extensions", &gl_extensions_value
)) {
618 std::string extensions_op
;
619 std::string extensions_value
;
620 gl_extensions_value
->GetString(kOp
, &extensions_op
);
621 gl_extensions_value
->GetString("value", &extensions_value
);
622 if (!entry
->SetGLExtensionsInfo(extensions_op
, extensions_value
)) {
623 LOG(WARNING
) << "Malformed gl_extensions entry " << entry
->id();
626 dictionary_entry_count
++;
629 const base::DictionaryValue
* gl_reset_notification_strategy_value
= NULL
;
630 if (value
->GetDictionary("gl_reset_notification_strategy",
631 &gl_reset_notification_strategy_value
)) {
633 std::string int_value
;
634 std::string int_value2
;
635 gl_reset_notification_strategy_value
->GetString(kOp
, &op
);
636 gl_reset_notification_strategy_value
->GetString("value", &int_value
);
637 gl_reset_notification_strategy_value
->GetString("value2", &int_value2
);
638 if (!entry
->SetGLResetNotificationStrategyInfo(
639 op
, int_value
, int_value2
)) {
640 LOG(WARNING
) << "Malformed gl_reset_notification_strategy entry "
644 dictionary_entry_count
++;
647 const base::DictionaryValue
* cpu_brand_value
= NULL
;
648 if (value
->GetDictionary("cpu_info", &cpu_brand_value
)) {
650 std::string cpu_value
;
651 cpu_brand_value
->GetString(kOp
, &cpu_op
);
652 cpu_brand_value
->GetString("value", &cpu_value
);
653 if (!entry
->SetCpuBrand(cpu_op
, cpu_value
)) {
654 LOG(WARNING
) << "Malformed cpu_brand entry " << entry
->id();
657 dictionary_entry_count
++;
660 const base::DictionaryValue
* perf_graphics_value
= NULL
;
661 if (value
->GetDictionary("perf_graphics", &perf_graphics_value
)) {
663 std::string float_value
;
664 std::string float_value2
;
665 perf_graphics_value
->GetString(kOp
, &op
);
666 perf_graphics_value
->GetString("value", &float_value
);
667 perf_graphics_value
->GetString("value2", &float_value2
);
668 if (!entry
->SetPerfGraphicsInfo(op
, float_value
, float_value2
)) {
669 LOG(WARNING
) << "Malformed perf_graphics entry " << entry
->id();
672 dictionary_entry_count
++;
675 const base::DictionaryValue
* perf_gaming_value
= NULL
;
676 if (value
->GetDictionary("perf_gaming", &perf_gaming_value
)) {
678 std::string float_value
;
679 std::string float_value2
;
680 perf_gaming_value
->GetString(kOp
, &op
);
681 perf_gaming_value
->GetString("value", &float_value
);
682 perf_gaming_value
->GetString("value2", &float_value2
);
683 if (!entry
->SetPerfGamingInfo(op
, float_value
, float_value2
)) {
684 LOG(WARNING
) << "Malformed perf_gaming entry " << entry
->id();
687 dictionary_entry_count
++;
690 const base::DictionaryValue
* perf_overall_value
= NULL
;
691 if (value
->GetDictionary("perf_overall", &perf_overall_value
)) {
693 std::string float_value
;
694 std::string float_value2
;
695 perf_overall_value
->GetString(kOp
, &op
);
696 perf_overall_value
->GetString("value", &float_value
);
697 perf_overall_value
->GetString("value2", &float_value2
);
698 if (!entry
->SetPerfOverallInfo(op
, float_value
, float_value2
)) {
699 LOG(WARNING
) << "Malformed perf_overall entry " << entry
->id();
702 dictionary_entry_count
++;
705 const base::DictionaryValue
* machine_model_value
= NULL
;
706 if (value
->GetDictionary("machine_model", &machine_model_value
)) {
708 std::string name_value
;
709 const base::DictionaryValue
* name
= NULL
;
710 if (machine_model_value
->GetDictionary("name", &name
)) {
711 name
->GetString(kOp
, &name_op
);
712 name
->GetString("value", &name_value
);
715 std::string version_op
= "any";
716 std::string version_string
;
717 std::string version_string2
;
718 const base::DictionaryValue
* version_value
= NULL
;
719 if (machine_model_value
->GetDictionary("version", &version_value
)) {
720 version_value
->GetString(kOp
, &version_op
);
721 version_value
->GetString("value", &version_string
);
722 version_value
->GetString("value2", &version_string2
);
724 if (!entry
->SetMachineModelInfo(
725 name_op
, name_value
, version_op
, version_string
, version_string2
)) {
726 LOG(WARNING
) << "Malformed machine_model entry " << entry
->id();
729 dictionary_entry_count
++;
732 const base::DictionaryValue
* gpu_count_value
= NULL
;
733 if (value
->GetDictionary("gpu_count", &gpu_count_value
)) {
735 std::string int_value
;
736 std::string int_value2
;
737 gpu_count_value
->GetString(kOp
, &op
);
738 gpu_count_value
->GetString("value", &int_value
);
739 gpu_count_value
->GetString("value2", &int_value2
);
740 if (!entry
->SetGpuCountInfo(op
, int_value
, int_value2
)) {
741 LOG(WARNING
) << "Malformed gpu_count entry " << entry
->id();
744 dictionary_entry_count
++;
748 const base::ListValue
* feature_value
= NULL
;
749 if (value
->GetList("features", &feature_value
)) {
750 std::vector
<std::string
> feature_list
;
751 for (size_t i
= 0; i
< feature_value
->GetSize(); ++i
) {
753 if (feature_value
->GetString(i
, &feature
)) {
754 feature_list
.push_back(feature
);
756 LOG(WARNING
) << "Malformed feature entry " << entry
->id();
760 if (!entry
->SetFeatures(
761 feature_list
, feature_map
, supports_feature_type_all
)) {
762 LOG(WARNING
) << "Malformed feature entry " << entry
->id();
765 dictionary_entry_count
++;
770 const base::ListValue
* exception_list_value
= NULL
;
771 if (value
->GetList("exceptions", &exception_list_value
)) {
772 for (size_t i
= 0; i
< exception_list_value
->GetSize(); ++i
) {
773 const base::DictionaryValue
* exception_value
= NULL
;
774 if (!exception_list_value
->GetDictionary(i
, &exception_value
)) {
775 LOG(WARNING
) << "Malformed exceptions entry " << entry
->id();
778 ScopedGpuControlListEntry
exception(GetEntryFromValue(
779 exception_value
, false, feature_map
, supports_feature_type_all
));
780 if (exception
.get() == NULL
) {
781 LOG(WARNING
) << "Malformed exceptions entry " << entry
->id();
784 // Exception should inherit vendor_id from parent, otherwise if only
785 // device_ids are specified in Exception, the info will be incomplete.
786 if (exception
->vendor_id_
== 0 && entry
->vendor_id_
!= 0)
787 exception
->vendor_id_
= entry
->vendor_id_
;
788 entry
->AddException(exception
);
790 dictionary_entry_count
++;
794 if (value
->size() != dictionary_entry_count
) {
795 LOG(WARNING
) << "Entry with unknown fields " << entry
->id();
801 GpuControlList::GpuControlListEntry::GpuControlListEntry()
805 multi_gpu_style_(kMultiGpuStyleNone
),
806 multi_gpu_category_(kMultiGpuCategoryPrimary
) {
809 GpuControlList::GpuControlListEntry::~GpuControlListEntry() { }
811 bool GpuControlList::GpuControlListEntry::SetId(uint32 id
) {
819 void GpuControlList::GpuControlListEntry::SetDisabled(bool disabled
) {
820 disabled_
= disabled
;
823 bool GpuControlList::GpuControlListEntry::SetOsInfo(
824 const std::string
& os
,
825 const std::string
& version_op
,
826 const std::string
& version_string
,
827 const std::string
& version_string2
) {
828 os_info_
.reset(new OsInfo(os
, version_op
, version_string
, version_string2
));
829 return os_info_
->IsValid();
832 bool GpuControlList::GpuControlListEntry::SetVendorId(
833 const std::string
& vendor_id_string
) {
835 return base::HexStringToUInt(vendor_id_string
, &vendor_id_
);
838 bool GpuControlList::GpuControlListEntry::AddDeviceId(
839 const std::string
& device_id_string
) {
840 uint32 device_id
= 0;
841 if (base::HexStringToUInt(device_id_string
, &device_id
)) {
842 device_id_list_
.push_back(device_id
);
848 bool GpuControlList::GpuControlListEntry::SetMultiGpuStyle(
849 const std::string
& multi_gpu_style_string
) {
850 MultiGpuStyle style
= StringToMultiGpuStyle(multi_gpu_style_string
);
851 if (style
== kMultiGpuStyleNone
)
853 multi_gpu_style_
= style
;
857 bool GpuControlList::GpuControlListEntry::SetMultiGpuCategory(
858 const std::string
& multi_gpu_category_string
) {
859 MultiGpuCategory category
=
860 StringToMultiGpuCategory(multi_gpu_category_string
);
861 if (category
== kMultiGpuCategoryNone
)
863 multi_gpu_category_
= category
;
867 bool GpuControlList::GpuControlListEntry::SetDriverVendorInfo(
868 const std::string
& vendor_op
,
869 const std::string
& vendor_value
) {
870 driver_vendor_info_
.reset(new StringInfo(vendor_op
, vendor_value
));
871 return driver_vendor_info_
->IsValid();
874 bool GpuControlList::GpuControlListEntry::SetDriverVersionInfo(
875 const std::string
& version_op
,
876 const std::string
& version_style
,
877 const std::string
& version_string
,
878 const std::string
& version_string2
) {
879 driver_version_info_
.reset(new VersionInfo(
880 version_op
, version_style
, version_string
, version_string2
));
881 return driver_version_info_
->IsValid();
884 bool GpuControlList::GpuControlListEntry::SetDriverDateInfo(
885 const std::string
& date_op
,
886 const std::string
& date_string
,
887 const std::string
& date_string2
) {
888 driver_date_info_
.reset(
889 new VersionInfo(date_op
, std::string(), date_string
, date_string2
));
890 return driver_date_info_
->IsValid();
893 bool GpuControlList::GpuControlListEntry::SetGLVendorInfo(
894 const std::string
& vendor_op
,
895 const std::string
& vendor_value
) {
896 gl_vendor_info_
.reset(new StringInfo(vendor_op
, vendor_value
));
897 return gl_vendor_info_
->IsValid();
900 bool GpuControlList::GpuControlListEntry::SetGLRendererInfo(
901 const std::string
& renderer_op
,
902 const std::string
& renderer_value
) {
903 gl_renderer_info_
.reset(new StringInfo(renderer_op
, renderer_value
));
904 return gl_renderer_info_
->IsValid();
907 bool GpuControlList::GpuControlListEntry::SetGLExtensionsInfo(
908 const std::string
& extensions_op
,
909 const std::string
& extensions_value
) {
910 gl_extensions_info_
.reset(new StringInfo(extensions_op
, extensions_value
));
911 return gl_extensions_info_
->IsValid();
914 bool GpuControlList::GpuControlListEntry::SetGLResetNotificationStrategyInfo(
915 const std::string
& op
,
916 const std::string
& int_string
,
917 const std::string
& int_string2
) {
918 gl_reset_notification_strategy_info_
.reset(
919 new IntInfo(op
, int_string
, int_string2
));
920 return gl_reset_notification_strategy_info_
->IsValid();
923 bool GpuControlList::GpuControlListEntry::SetCpuBrand(
924 const std::string
& cpu_op
,
925 const std::string
& cpu_value
) {
926 cpu_brand_
.reset(new StringInfo(cpu_op
, cpu_value
));
927 return cpu_brand_
->IsValid();
930 bool GpuControlList::GpuControlListEntry::SetPerfGraphicsInfo(
931 const std::string
& op
,
932 const std::string
& float_string
,
933 const std::string
& float_string2
) {
934 perf_graphics_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
935 return perf_graphics_info_
->IsValid();
938 bool GpuControlList::GpuControlListEntry::SetPerfGamingInfo(
939 const std::string
& op
,
940 const std::string
& float_string
,
941 const std::string
& float_string2
) {
942 perf_gaming_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
943 return perf_gaming_info_
->IsValid();
946 bool GpuControlList::GpuControlListEntry::SetPerfOverallInfo(
947 const std::string
& op
,
948 const std::string
& float_string
,
949 const std::string
& float_string2
) {
950 perf_overall_info_
.reset(new FloatInfo(op
, float_string
, float_string2
));
951 return perf_overall_info_
->IsValid();
954 bool GpuControlList::GpuControlListEntry::SetMachineModelInfo(
955 const std::string
& name_op
,
956 const std::string
& name_value
,
957 const std::string
& version_op
,
958 const std::string
& version_string
,
959 const std::string
& version_string2
) {
960 machine_model_info_
.reset(new MachineModelInfo(
961 name_op
, name_value
, version_op
, version_string
, version_string2
));
962 return machine_model_info_
->IsValid();
965 bool GpuControlList::GpuControlListEntry::SetGpuCountInfo(
966 const std::string
& op
,
967 const std::string
& int_string
,
968 const std::string
& int_string2
) {
969 gpu_count_info_
.reset(new IntInfo(op
, int_string
, int_string2
));
970 return gpu_count_info_
->IsValid();
973 bool GpuControlList::GpuControlListEntry::SetFeatures(
974 const std::vector
<std::string
>& feature_strings
,
975 const FeatureMap
& feature_map
,
976 bool supports_feature_type_all
) {
977 size_t size
= feature_strings
.size();
981 for (size_t i
= 0; i
< size
; ++i
) {
983 if (supports_feature_type_all
&& feature_strings
[i
] == "all") {
984 for (FeatureMap::const_iterator iter
= feature_map
.begin();
985 iter
!= feature_map
.end(); ++iter
)
986 features_
.insert(iter
->second
);
989 if (!StringToFeature(feature_strings
[i
], &feature
, feature_map
)) {
993 features_
.insert(feature
);
998 void GpuControlList::GpuControlListEntry::AddException(
999 ScopedGpuControlListEntry exception
) {
1000 exceptions_
.push_back(exception
);
1004 GpuControlList::GpuControlListEntry::MultiGpuStyle
1005 GpuControlList::GpuControlListEntry::StringToMultiGpuStyle(
1006 const std::string
& style
) {
1007 if (style
== kMultiGpuStyleStringOptimus
)
1008 return kMultiGpuStyleOptimus
;
1009 if (style
== kMultiGpuStyleStringAMDSwitchable
)
1010 return kMultiGpuStyleAMDSwitchable
;
1011 return kMultiGpuStyleNone
;
1015 GpuControlList::GpuControlListEntry::MultiGpuCategory
1016 GpuControlList::GpuControlListEntry::StringToMultiGpuCategory(
1017 const std::string
& category
) {
1018 if (category
== kMultiGpuCategoryStringPrimary
)
1019 return kMultiGpuCategoryPrimary
;
1020 if (category
== kMultiGpuCategoryStringSecondary
)
1021 return kMultiGpuCategorySecondary
;
1022 if (category
== kMultiGpuCategoryStringAny
)
1023 return kMultiGpuCategoryAny
;
1024 return kMultiGpuCategoryNone
;
1027 void GpuControlList::GpuControlListEntry::LogControlListMatch(
1028 const std::string
& control_list_logging_name
) const {
1029 static const char kControlListMatchMessage
[] =
1030 "Control list match for rule #%u in %s.";
1031 VLOG(1) << base::StringPrintf(kControlListMatchMessage
, id_
,
1032 control_list_logging_name
.c_str());
1035 bool GpuControlList::GpuControlListEntry::Contains(
1036 OsType os_type
, const std::string
& os_version
,
1037 const GPUInfo
& gpu_info
) const {
1038 DCHECK(os_type
!= kOsAny
);
1039 if (os_info_
.get() != NULL
&& !os_info_
->Contains(os_type
, os_version
))
1041 bool is_not_primary_gpu
=
1042 GpuUnmatched(vendor_id_
, device_id_list_
, gpu_info
.gpu
);
1043 bool is_not_secondary_gpu
= true;
1044 for (size_t i
= 0; i
< gpu_info
.secondary_gpus
.size(); ++i
) {
1045 is_not_secondary_gpu
= is_not_secondary_gpu
&&
1046 GpuUnmatched(vendor_id_
, device_id_list_
, gpu_info
.secondary_gpus
[i
]);
1048 switch (multi_gpu_category_
) {
1049 case kMultiGpuCategoryPrimary
:
1050 if (is_not_primary_gpu
)
1053 case kMultiGpuCategorySecondary
:
1054 if (is_not_secondary_gpu
)
1057 case kMultiGpuCategoryAny
:
1058 if (is_not_primary_gpu
&& is_not_secondary_gpu
)
1061 case kMultiGpuCategoryNone
:
1064 switch (multi_gpu_style_
) {
1065 case kMultiGpuStyleOptimus
:
1066 if (!gpu_info
.optimus
)
1069 case kMultiGpuStyleAMDSwitchable
:
1070 if (!gpu_info
.amd_switchable
)
1073 case kMultiGpuStyleNone
:
1076 if (driver_vendor_info_
.get() != NULL
&& !gpu_info
.driver_vendor
.empty() &&
1077 !driver_vendor_info_
->Contains(gpu_info
.driver_vendor
))
1079 if (driver_version_info_
.get() != NULL
&& !gpu_info
.driver_version
.empty()) {
1080 if (!driver_version_info_
->Contains(gpu_info
.driver_version
))
1083 if (driver_date_info_
.get() != NULL
&& !gpu_info
.driver_date
.empty()) {
1084 if (!driver_date_info_
->Contains(gpu_info
.driver_date
, '-'))
1087 if (gl_vendor_info_
.get() != NULL
&& !gpu_info
.gl_vendor
.empty() &&
1088 !gl_vendor_info_
->Contains(gpu_info
.gl_vendor
))
1090 if (gl_renderer_info_
.get() != NULL
&& !gpu_info
.gl_renderer
.empty() &&
1091 !gl_renderer_info_
->Contains(gpu_info
.gl_renderer
))
1093 if (gl_extensions_info_
.get() != NULL
&& !gpu_info
.gl_extensions
.empty() &&
1094 !gl_extensions_info_
->Contains(gpu_info
.gl_extensions
))
1096 if (gl_reset_notification_strategy_info_
.get() != NULL
&&
1097 !gl_reset_notification_strategy_info_
->Contains(
1098 gpu_info
.gl_reset_notification_strategy
))
1100 if (perf_graphics_info_
.get() != NULL
&&
1101 (gpu_info
.performance_stats
.graphics
== 0.0 ||
1102 !perf_graphics_info_
->Contains(gpu_info
.performance_stats
.graphics
)))
1104 if (perf_gaming_info_
.get() != NULL
&&
1105 (gpu_info
.performance_stats
.gaming
== 0.0 ||
1106 !perf_gaming_info_
->Contains(gpu_info
.performance_stats
.gaming
)))
1108 if (perf_overall_info_
.get() != NULL
&&
1109 (gpu_info
.performance_stats
.overall
== 0.0 ||
1110 !perf_overall_info_
->Contains(gpu_info
.performance_stats
.overall
)))
1112 if (machine_model_info_
.get() != NULL
) {
1113 std::vector
<std::string
> name_version
;
1114 base::SplitString(gpu_info
.machine_model
, ' ', &name_version
);
1115 if (name_version
.size() == 2 &&
1116 !machine_model_info_
->Contains(name_version
[0], name_version
[1]))
1119 if (gpu_count_info_
.get() != NULL
&&
1120 !gpu_count_info_
->Contains(gpu_info
.secondary_gpus
.size() + 1))
1122 if (cpu_brand_
.get() != NULL
) {
1124 if (!cpu_brand_
->Contains(cpu_info
.cpu_brand()))
1128 for (size_t i
= 0; i
< exceptions_
.size(); ++i
) {
1129 if (exceptions_
[i
]->Contains(os_type
, os_version
, gpu_info
) &&
1130 !exceptions_
[i
]->NeedsMoreInfo(gpu_info
))
1136 bool GpuControlList::GpuControlListEntry::NeedsMoreInfo(
1137 const GPUInfo
& gpu_info
) const {
1138 // We only check for missing info that might be collected with a gl context.
1139 // If certain info is missing due to some error, say, we fail to collect
1140 // vendor_id/device_id, then even if we launch GPU process and create a gl
1141 // context, we won't gather such missing info, so we still return false.
1142 if (driver_vendor_info_
.get() && gpu_info
.driver_vendor
.empty())
1144 if (driver_version_info_
.get() && gpu_info
.driver_version
.empty())
1146 if (gl_vendor_info_
.get() && gpu_info
.gl_vendor
.empty())
1148 if (gl_renderer_info_
.get() && gpu_info
.gl_renderer
.empty())
1150 for (size_t i
= 0; i
< exceptions_
.size(); ++i
) {
1151 if (exceptions_
[i
]->NeedsMoreInfo(gpu_info
))
1157 GpuControlList::OsType
GpuControlList::GpuControlListEntry::GetOsType() const {
1158 if (os_info_
.get() == NULL
)
1160 return os_info_
->type();
1163 uint32
GpuControlList::GpuControlListEntry::id() const {
1167 bool GpuControlList::GpuControlListEntry::disabled() const {
1171 const std::set
<int>& GpuControlList::GpuControlListEntry::features() const {
1176 bool GpuControlList::GpuControlListEntry::StringToFeature(
1177 const std::string
& feature_name
, int* feature_id
,
1178 const FeatureMap
& feature_map
) {
1179 FeatureMap::const_iterator iter
= feature_map
.find(feature_name
);
1180 if (iter
!= feature_map
.end()) {
1181 *feature_id
= iter
->second
;
1187 GpuControlList::GpuControlList()
1189 needs_more_info_(false),
1190 supports_feature_type_all_(false),
1191 control_list_logging_enabled_(false) {
1194 GpuControlList::~GpuControlList() {
1198 bool GpuControlList::LoadList(
1199 const std::string
& json_context
,
1200 GpuControlList::OsFilter os_filter
) {
1201 scoped_ptr
<base::Value
> root
;
1202 root
.reset(base::JSONReader::Read(json_context
));
1203 if (root
.get() == NULL
|| !root
->IsType(base::Value::TYPE_DICTIONARY
))
1206 base::DictionaryValue
* root_dictionary
=
1207 static_cast<base::DictionaryValue
*>(root
.get());
1208 DCHECK(root_dictionary
);
1209 return LoadList(*root_dictionary
, os_filter
);
1212 bool GpuControlList::LoadList(const base::DictionaryValue
& parsed_json
,
1213 GpuControlList::OsFilter os_filter
) {
1214 std::vector
<ScopedGpuControlListEntry
> entries
;
1216 parsed_json
.GetString("version", &version_
);
1217 std::vector
<std::string
> pieces
;
1218 if (!ProcessVersionString(version_
, '.', &pieces
))
1221 const base::ListValue
* list
= NULL
;
1222 if (!parsed_json
.GetList("entries", &list
))
1225 uint32 max_entry_id
= 0;
1226 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
1227 const base::DictionaryValue
* list_item
= NULL
;
1228 bool valid
= list
->GetDictionary(i
, &list_item
);
1229 if (!valid
|| list_item
== NULL
)
1231 ScopedGpuControlListEntry
entry(GpuControlListEntry::GetEntryFromValue(
1232 list_item
, true, feature_map_
, supports_feature_type_all_
));
1233 if (entry
.get() == NULL
)
1235 if (entry
->id() > max_entry_id
)
1236 max_entry_id
= entry
->id();
1237 entries
.push_back(entry
);
1241 OsType my_os
= GetOsType();
1242 for (size_t i
= 0; i
< entries
.size(); ++i
) {
1243 OsType entry_os
= entries
[i
]->GetOsType();
1244 if (os_filter
== GpuControlList::kAllOs
||
1245 entry_os
== kOsAny
|| entry_os
== my_os
)
1246 entries_
.push_back(entries
[i
]);
1248 max_entry_id_
= max_entry_id
;
1252 std::set
<int> GpuControlList::MakeDecision(
1253 GpuControlList::OsType os
,
1254 std::string os_version
,
1255 const GPUInfo
& gpu_info
) {
1256 active_entries_
.clear();
1257 std::set
<int> features
;
1259 needs_more_info_
= false;
1260 std::set
<int> possible_features
;
1264 if (os_version
.empty()) {
1265 os_version
= base::SysInfo::OperatingSystemVersion();
1266 size_t pos
= os_version
.find_first_not_of("0123456789.");
1267 if (pos
!= std::string::npos
)
1268 os_version
= os_version
.substr(0, pos
);
1270 std::vector
<std::string
> pieces
;
1271 if (!ProcessVersionString(os_version
, '.', &pieces
))
1274 for (size_t i
= 0; i
< entries_
.size(); ++i
) {
1275 if (entries_
[i
]->Contains(os
, os_version
, gpu_info
)) {
1276 if (!entries_
[i
]->disabled()) {
1277 if (control_list_logging_enabled_
)
1278 entries_
[i
]->LogControlListMatch(control_list_logging_name_
);
1279 MergeFeatureSets(&possible_features
, entries_
[i
]->features());
1280 if (!entries_
[i
]->NeedsMoreInfo(gpu_info
))
1281 MergeFeatureSets(&features
, entries_
[i
]->features());
1283 active_entries_
.push_back(entries_
[i
]);
1287 if (possible_features
.size() > features
.size())
1288 needs_more_info_
= true;
1293 void GpuControlList::GetDecisionEntries(
1294 std::vector
<uint32
>* entry_ids
, bool disabled
) const {
1297 for (size_t i
= 0; i
< active_entries_
.size(); ++i
) {
1298 if (disabled
== active_entries_
[i
]->disabled())
1299 entry_ids
->push_back(active_entries_
[i
]->id());
1303 void GpuControlList::GetReasons(base::ListValue
* problem_list
) const {
1304 DCHECK(problem_list
);
1305 for (size_t i
= 0; i
< active_entries_
.size(); ++i
) {
1306 GpuControlListEntry
* entry
= active_entries_
[i
].get();
1307 if (entry
->disabled())
1309 base::DictionaryValue
* problem
= new base::DictionaryValue();
1311 problem
->SetString("description", entry
->description());
1313 base::ListValue
* cr_bugs
= new base::ListValue();
1314 for (size_t j
= 0; j
< entry
->cr_bugs().size(); ++j
)
1315 cr_bugs
->Append(new base::FundamentalValue(entry
->cr_bugs()[j
]));
1316 problem
->Set("crBugs", cr_bugs
);
1318 base::ListValue
* webkit_bugs
= new base::ListValue();
1319 for (size_t j
= 0; j
< entry
->webkit_bugs().size(); ++j
) {
1320 webkit_bugs
->Append(new base::FundamentalValue(entry
->webkit_bugs()[j
]));
1322 problem
->Set("webkitBugs", webkit_bugs
);
1324 problem_list
->Append(problem
);
1328 size_t GpuControlList::num_entries() const {
1329 return entries_
.size();
1332 uint32
GpuControlList::max_entry_id() const {
1333 return max_entry_id_
;
1336 std::string
GpuControlList::version() const {
1340 GpuControlList::OsType
GpuControlList::GetOsType() {
1341 #if defined(OS_CHROMEOS)
1343 #elif defined(OS_WIN)
1345 #elif defined(OS_ANDROID)
1347 #elif defined(OS_LINUX) || defined(OS_OPENBSD)
1349 #elif defined(OS_MACOSX)
1356 void GpuControlList::Clear() {
1358 active_entries_
.clear();
1363 GpuControlList::NumericOp
GpuControlList::StringToNumericOp(
1364 const std::string
& op
) {
1377 if (op
== "between")
1382 void GpuControlList::AddSupportedFeature(
1383 const std::string
& feature_name
, int feature_id
) {
1384 feature_map_
[feature_name
] = feature_id
;
1387 void GpuControlList::set_supports_feature_type_all(bool supported
) {
1388 supports_feature_type_all_
= supported
;