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. 4 5 #include "gpu/config/gpu_control_list.h" 6 7 #include "base/cpu.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" 17 #include "third_party/re2/re2/re2.h" 18 19 namespace gpu { 20 namespace { 21 22 // Break a version string into segments. Return true if each segment is 23 // a valid number, and not all segment is 0. 24 bool ProcessVersionString(const std::string& version_string, 25 char splitter, 26 std::vector<std::string>* version) { 27 DCHECK(version); 28 base::SplitString(version_string, splitter, version); 29 if (version->size() == 0) 30 return false; 31 // If the splitter is '-', we assume it's a date with format "mm-dd-yyyy"; 32 // we split it into the order of "yyyy", "mm", "dd". 33 if (splitter == '-') { 34 std::string year = (*version)[version->size() - 1]; 35 for (int i = version->size() - 1; i > 0; --i) { 36 (*version)[i] = (*version)[i - 1]; 37 } 38 (*version)[0] = year; 39 } 40 bool all_zero = true; 41 for (size_t i = 0; i < version->size(); ++i) { 42 unsigned num = 0; 43 if (!base::StringToUint((*version)[i], &num)) 44 return false; 45 if (num) 46 all_zero = false; 47 } 48 return !all_zero; 49 } 50 51 // Compare two number strings using numerical ordering. 52 // Return 0 if number = number_ref, 53 // 1 if number > number_ref, 54 // -1 if number < number_ref. 55 int CompareNumericalNumberStrings( 56 const std::string& number, const std::string& number_ref) { 57 unsigned value1 = 0; 58 unsigned value2 = 0; 59 bool valid = base::StringToUint(number, &value1); 60 DCHECK(valid); 61 valid = base::StringToUint(number_ref, &value2); 62 DCHECK(valid); 63 if (value1 == value2) 64 return 0; 65 if (value1 > value2) 66 return 1; 67 return -1; 68 } 69 70 // Compare two number strings using lexical ordering. 71 // Return 0 if number = number_ref, 72 // 1 if number > number_ref, 73 // -1 if number < number_ref. 74 // We only compare as many digits as number_ref contains. 75 // If number_ref is xxx, it's considered as xxx* 76 // For example: CompareLexicalNumberStrings("121", "12") returns 0, 77 // CompareLexicalNumberStrings("12", "121") returns -1. 78 int CompareLexicalNumberStrings( 79 const std::string& number, const std::string& number_ref) { 80 for (size_t i = 0; i < number_ref.length(); ++i) { 81 unsigned value1 = 0; 82 if (i < number.length()) 83 value1 = number[i] - '0'; 84 unsigned value2 = number_ref[i] - '0'; 85 if (value1 > value2) 86 return 1; 87 if (value1 < value2) 88 return -1; 89 } 90 return 0; 91 } 92 93 // A mismatch is identified only if both |input| and |pattern| are not empty. 94 bool StringMismatch(const std::string& input, const std::string& pattern) { 95 if (input.empty() || pattern.empty()) 96 return false; 97 return !RE2::FullMatch(input, pattern); 98 } 99 100 const char kMultiGpuStyleStringAMDSwitchable[] = "amd_switchable"; 101 const char kMultiGpuStyleStringAMDSwitchableDiscrete[] = 102 "amd_switchable_discrete"; 103 const char kMultiGpuStyleStringAMDSwitchableIntegrated[] = 104 "amd_switchable_integrated"; 105 const char kMultiGpuStyleStringOptimus[] = "optimus"; 106 107 const char kMultiGpuCategoryStringPrimary[] = "primary"; 108 const char kMultiGpuCategoryStringSecondary[] = "secondary"; 109 const char kMultiGpuCategoryStringActive[] = "active"; 110 const char kMultiGpuCategoryStringAny[] = "any"; 111 112 const char kGLTypeStringGL[] = "gl"; 113 const char kGLTypeStringGLES[] = "gles"; 114 const char kGLTypeStringANGLE[] = "angle"; 115 116 const char kVersionStyleStringNumerical[] = "numerical"; 117 const char kVersionStyleStringLexical[] = "lexical"; 118 119 const char kOp[] = "op"; 120 121 } // namespace anonymous 122 123 GpuControlList::VersionInfo::VersionInfo( 124 const std::string& version_op, 125 const std::string& version_style, 126 const std::string& version_string, 127 const std::string& version_string2) 128 : version_style_(kVersionStyleNumerical) { 129 op_ = StringToNumericOp(version_op); 130 if (op_ == kUnknown || op_ == kAny) 131 return; 132 version_style_ = StringToVersionStyle(version_style); 133 if (!ProcessVersionString(version_string, '.', &version_)) { 134 op_ = kUnknown; 135 return; 136 } 137 if (op_ == kBetween) { 138 if (!ProcessVersionString(version_string2, '.', &version2_)) 139 op_ = kUnknown; 140 } 141 } 142 143 GpuControlList::VersionInfo::~VersionInfo() { 144 } 145 146 bool GpuControlList::VersionInfo::Contains( 147 const std::string& version_string) const { 148 return Contains(version_string, '.'); 149 } 150 151 bool GpuControlList::VersionInfo::Contains( 152 const std::string& version_string, char splitter) const { 153 if (op_ == kUnknown) 154 return false; 155 if (op_ == kAny) 156 return true; 157 std::vector<std::string> version; 158 if (!ProcessVersionString(version_string, splitter, &version)) 159 return false; 160 int relation = Compare(version, version_, version_style_); 161 if (op_ == kEQ) 162 return (relation == 0); 163 else if (op_ == kLT) 164 return (relation < 0); 165 else if (op_ == kLE) 166 return (relation <= 0); 167 else if (op_ == kGT) 168 return (relation > 0); 169 else if (op_ == kGE) 170 return (relation >= 0); 171 // op_ == kBetween 172 if (relation < 0) 173 return false; 174 return Compare(version, version2_, version_style_) <= 0; 175 } 176 177 bool GpuControlList::VersionInfo::IsValid() const { 178 return (op_ != kUnknown && version_style_ != kVersionStyleUnknown); 179 } 180 181 bool GpuControlList::VersionInfo::IsLexical() const { 182 return version_style_ == kVersionStyleLexical; 183 } 184 185 // static 186 int GpuControlList::VersionInfo::Compare( 187 const std::vector<std::string>& version, 188 const std::vector<std::string>& version_ref, 189 VersionStyle version_style) { 190 DCHECK(version.size() > 0 && version_ref.size() > 0); 191 DCHECK(version_style != kVersionStyleUnknown); 192 for (size_t i = 0; i < version_ref.size(); ++i) { 193 if (i >= version.size()) 194 return 0; 195 int ret = 0; 196 // We assume both versions are checked by ProcessVersionString(). 197 if (i > 0 && version_style == kVersionStyleLexical) 198 ret = CompareLexicalNumberStrings(version[i], version_ref[i]); 199 else 200 ret = CompareNumericalNumberStrings(version[i], version_ref[i]); 201 if (ret != 0) 202 return ret; 203 } 204 return 0; 205 } 206 207 // static 208 GpuControlList::VersionInfo::VersionStyle 209 GpuControlList::VersionInfo::StringToVersionStyle( 210 const std::string& version_style) { 211 if (version_style.empty() || version_style == kVersionStyleStringNumerical) 212 return kVersionStyleNumerical; 213 if (version_style == kVersionStyleStringLexical) 214 return kVersionStyleLexical; 215 return kVersionStyleUnknown; 216 } 217 218 GpuControlList::OsInfo::OsInfo(const std::string& os, 219 const std::string& version_op, 220 const std::string& version_string, 221 const std::string& version_string2) { 222 type_ = StringToOsType(os); 223 if (type_ != kOsUnknown) { 224 version_info_.reset(new VersionInfo( 225 version_op, std::string(), version_string, version_string2)); 226 } 227 } 228 229 GpuControlList::OsInfo::~OsInfo() {} 230 231 bool GpuControlList::OsInfo::Contains( 232 OsType type, const std::string& version) const { 233 if (!IsValid()) 234 return false; 235 if (type_ != type && type_ != kOsAny) 236 return false; 237 std::string processed_version; 238 size_t pos = version.find_first_not_of("0123456789."); 239 if (pos != std::string::npos) 240 processed_version = version.substr(0, pos); 241 else 242 processed_version = version; 243 244 return version_info_->Contains(processed_version); 245 } 246 247 bool GpuControlList::OsInfo::IsValid() const { 248 return type_ != kOsUnknown && version_info_->IsValid(); 249 } 250 251 GpuControlList::OsType GpuControlList::OsInfo::type() const { 252 return type_; 253 } 254 255 GpuControlList::OsType GpuControlList::OsInfo::StringToOsType( 256 const std::string& os) { 257 if (os == "win") 258 return kOsWin; 259 else if (os == "macosx") 260 return kOsMacosx; 261 else if (os == "android") 262 return kOsAndroid; 263 else if (os == "linux") 264 return kOsLinux; 265 else if (os == "chromeos") 266 return kOsChromeOS; 267 else if (os == "any") 268 return kOsAny; 269 return kOsUnknown; 270 } 271 272 GpuControlList::FloatInfo::FloatInfo(const std::string& float_op, 273 const std::string& float_value, 274 const std::string& float_value2) 275 : op_(kUnknown), 276 value_(0.f), 277 value2_(0.f) { 278 op_ = StringToNumericOp(float_op); 279 if (op_ == kAny) 280 return; 281 double dvalue = 0; 282 if (!base::StringToDouble(float_value, &dvalue)) { 283 op_ = kUnknown; 284 return; 285 } 286 value_ = static_cast<float>(dvalue); 287 if (op_ == kBetween) { 288 if (!base::StringToDouble(float_value2, &dvalue)) { 289 op_ = kUnknown; 290 return; 291 } 292 value2_ = static_cast<float>(dvalue); 293 } 294 } 295 296 bool GpuControlList::FloatInfo::Contains(float value) const { 297 if (op_ == kUnknown) 298 return false; 299 if (op_ == kAny) 300 return true; 301 if (op_ == kEQ) 302 return (value == value_); 303 if (op_ == kLT) 304 return (value < value_); 305 if (op_ == kLE) 306 return (value <= value_); 307 if (op_ == kGT) 308 return (value > value_); 309 if (op_ == kGE) 310 return (value >= value_); 311 DCHECK(op_ == kBetween); 312 return ((value_ <= value && value <= value2_) || 313 (value2_ <= value && value <= value_)); 314 } 315 316 bool GpuControlList::FloatInfo::IsValid() const { 317 return op_ != kUnknown; 318 } 319 320 GpuControlList::IntInfo::IntInfo(const std::string& int_op, 321 const std::string& int_value, 322 const std::string& int_value2) 323 : op_(kUnknown), 324 value_(0), 325 value2_(0) { 326 op_ = StringToNumericOp(int_op); 327 if (op_ == kAny) 328 return; 329 if (!base::StringToInt(int_value, &value_)) { 330 op_ = kUnknown; 331 return; 332 } 333 if (op_ == kBetween && 334 !base::StringToInt(int_value2, &value2_)) 335 op_ = kUnknown; 336 } 337 338 bool GpuControlList::IntInfo::Contains(int value) const { 339 if (op_ == kUnknown) 340 return false; 341 if (op_ == kAny) 342 return true; 343 if (op_ == kEQ) 344 return (value == value_); 345 if (op_ == kLT) 346 return (value < value_); 347 if (op_ == kLE) 348 return (value <= value_); 349 if (op_ == kGT) 350 return (value > value_); 351 if (op_ == kGE) 352 return (value >= value_); 353 DCHECK(op_ == kBetween); 354 return ((value_ <= value && value <= value2_) || 355 (value2_ <= value && value <= value_)); 356 } 357 358 bool GpuControlList::IntInfo::IsValid() const { 359 return op_ != kUnknown; 360 } 361 362 GpuControlList::BoolInfo::BoolInfo(bool value) : value_(value) {} 363 364 bool GpuControlList::BoolInfo::Contains(bool value) const { 365 return value_ == value; 366 } 367 368 // static 369 GpuControlList::ScopedGpuControlListEntry 370 GpuControlList::GpuControlListEntry::GetEntryFromValue( 371 const base::DictionaryValue* value, bool top_level, 372 const FeatureMap& feature_map, 373 bool supports_feature_type_all) { 374 DCHECK(value); 375 ScopedGpuControlListEntry entry(new GpuControlListEntry()); 376 377 size_t dictionary_entry_count = 0; 378 379 if (top_level) { 380 uint32 id; 381 if (!value->GetInteger("id", reinterpret_cast<int*>(&id)) || 382 !entry->SetId(id)) { 383 LOG(WARNING) << "Malformed id entry " << entry->id(); 384 return NULL; 385 } 386 dictionary_entry_count++; 387 388 bool disabled; 389 if (value->GetBoolean("disabled", &disabled)) { 390 entry->SetDisabled(disabled); 391 dictionary_entry_count++; 392 } 393 } 394 395 std::string description; 396 if (value->GetString("description", &description)) { 397 entry->description_ = description; 398 dictionary_entry_count++; 399 } else { 400 entry->description_ = "The GPU is unavailable for an unexplained reason."; 401 } 402 403 const base::ListValue* cr_bugs; 404 if (value->GetList("cr_bugs", &cr_bugs)) { 405 for (size_t i = 0; i < cr_bugs->GetSize(); ++i) { 406 int bug_id; 407 if (cr_bugs->GetInteger(i, &bug_id)) { 408 entry->cr_bugs_.push_back(bug_id); 409 } else { 410 LOG(WARNING) << "Malformed cr_bugs entry " << entry->id(); 411 return NULL; 412 } 413 } 414 dictionary_entry_count++; 415 } 416 417 const base::ListValue* webkit_bugs; 418 if (value->GetList("webkit_bugs", &webkit_bugs)) { 419 for (size_t i = 0; i < webkit_bugs->GetSize(); ++i) { 420 int bug_id; 421 if (webkit_bugs->GetInteger(i, &bug_id)) { 422 entry->webkit_bugs_.push_back(bug_id); 423 } else { 424 LOG(WARNING) << "Malformed webkit_bugs entry " << entry->id(); 425 return NULL; 426 } 427 } 428 dictionary_entry_count++; 429 } 430 431 const base::DictionaryValue* os_value = NULL; 432 if (value->GetDictionary("os", &os_value)) { 433 std::string os_type; 434 std::string os_version_op = "any"; 435 std::string os_version_string; 436 std::string os_version_string2; 437 os_value->GetString("type", &os_type); 438 const base::DictionaryValue* os_version_value = NULL; 439 if (os_value->GetDictionary("version", &os_version_value)) { 440 os_version_value->GetString(kOp, &os_version_op); 441 os_version_value->GetString("value", &os_version_string); 442 os_version_value->GetString("value2", &os_version_string2); 443 } 444 if (!entry->SetOsInfo(os_type, os_version_op, os_version_string, 445 os_version_string2)) { 446 LOG(WARNING) << "Malformed os entry " << entry->id(); 447 return NULL; 448 } 449 dictionary_entry_count++; 450 } 451 452 std::string vendor_id; 453 if (value->GetString("vendor_id", &vendor_id)) { 454 if (!entry->SetVendorId(vendor_id)) { 455 LOG(WARNING) << "Malformed vendor_id entry " << entry->id(); 456 return NULL; 457 } 458 dictionary_entry_count++; 459 } 460 461 const base::ListValue* device_id_list; 462 if (value->GetList("device_id", &device_id_list)) { 463 for (size_t i = 0; i < device_id_list->GetSize(); ++i) { 464 std::string device_id; 465 if (!device_id_list->GetString(i, &device_id) || 466 !entry->AddDeviceId(device_id)) { 467 LOG(WARNING) << "Malformed device_id entry " << entry->id(); 468 return NULL; 469 } 470 } 471 dictionary_entry_count++; 472 } 473 474 std::string multi_gpu_style; 475 if (value->GetString("multi_gpu_style", &multi_gpu_style)) { 476 if (!entry->SetMultiGpuStyle(multi_gpu_style)) { 477 LOG(WARNING) << "Malformed multi_gpu_style entry " << entry->id(); 478 return NULL; 479 } 480 dictionary_entry_count++; 481 } 482 483 std::string multi_gpu_category; 484 if (value->GetString("multi_gpu_category", &multi_gpu_category)) { 485 if (!entry->SetMultiGpuCategory(multi_gpu_category)) { 486 LOG(WARNING) << "Malformed multi_gpu_category entry " << entry->id(); 487 return NULL; 488 } 489 dictionary_entry_count++; 490 } 491 492 std::string driver_vendor_value; 493 if (value->GetString("driver_vendor", &driver_vendor_value)) { 494 if (!entry->SetDriverVendorInfo(driver_vendor_value)) { 495 LOG(WARNING) << "Malformed driver_vendor entry " << entry->id(); 496 return NULL; 497 } 498 dictionary_entry_count++; 499 } 500 501 const base::DictionaryValue* driver_version_value = NULL; 502 if (value->GetDictionary("driver_version", &driver_version_value)) { 503 std::string driver_version_op = "any"; 504 std::string driver_version_style; 505 std::string driver_version_string; 506 std::string driver_version_string2; 507 driver_version_value->GetString(kOp, &driver_version_op); 508 driver_version_value->GetString("style", &driver_version_style); 509 driver_version_value->GetString("value", &driver_version_string); 510 driver_version_value->GetString("value2", &driver_version_string2); 511 if (!entry->SetDriverVersionInfo(driver_version_op, 512 driver_version_style, 513 driver_version_string, 514 driver_version_string2)) { 515 LOG(WARNING) << "Malformed driver_version entry " << entry->id(); 516 return NULL; 517 } 518 dictionary_entry_count++; 519 } 520 521 const base::DictionaryValue* driver_date_value = NULL; 522 if (value->GetDictionary("driver_date", &driver_date_value)) { 523 std::string driver_date_op = "any"; 524 std::string driver_date_string; 525 std::string driver_date_string2; 526 driver_date_value->GetString(kOp, &driver_date_op); 527 driver_date_value->GetString("value", &driver_date_string); 528 driver_date_value->GetString("value2", &driver_date_string2); 529 if (!entry->SetDriverDateInfo(driver_date_op, driver_date_string, 530 driver_date_string2)) { 531 LOG(WARNING) << "Malformed driver_date entry " << entry->id(); 532 return NULL; 533 } 534 dictionary_entry_count++; 535 } 536 537 std::string gl_type; 538 if (value->GetString("gl_type", &gl_type)) { 539 if (!entry->SetGLType(gl_type)) { 540 LOG(WARNING) << "Malformed gl_type entry " << entry->id(); 541 return NULL; 542 } 543 dictionary_entry_count++; 544 } 545 546 const base::DictionaryValue* gl_version_value = NULL; 547 if (value->GetDictionary("gl_version", &gl_version_value)) { 548 std::string version_op = "any"; 549 std::string version_string; 550 std::string version_string2; 551 gl_version_value->GetString(kOp, &version_op); 552 gl_version_value->GetString("value", &version_string); 553 gl_version_value->GetString("value2", &version_string2); 554 if (!entry->SetGLVersionInfo( 555 version_op, version_string, version_string2)) { 556 LOG(WARNING) << "Malformed gl_version entry " << entry->id(); 557 return NULL; 558 } 559 dictionary_entry_count++; 560 } 561 562 std::string gl_vendor_value; 563 if (value->GetString("gl_vendor", &gl_vendor_value)) { 564 if (!entry->SetGLVendorInfo(gl_vendor_value)) { 565 LOG(WARNING) << "Malformed gl_vendor entry " << entry->id(); 566 return NULL; 567 } 568 dictionary_entry_count++; 569 } 570 571 std::string gl_renderer_value; 572 if (value->GetString("gl_renderer", &gl_renderer_value)) { 573 if (!entry->SetGLRendererInfo(gl_renderer_value)) { 574 LOG(WARNING) << "Malformed gl_renderer entry " << entry->id(); 575 return NULL; 576 } 577 dictionary_entry_count++; 578 } 579 580 std::string gl_extensions_value; 581 if (value->GetString("gl_extensions", &gl_extensions_value)) { 582 if (!entry->SetGLExtensionsInfo(gl_extensions_value)) { 583 LOG(WARNING) << "Malformed gl_extensions entry " << entry->id(); 584 return NULL; 585 } 586 dictionary_entry_count++; 587 } 588 589 const base::DictionaryValue* gl_reset_notification_strategy_value = NULL; 590 if (value->GetDictionary("gl_reset_notification_strategy", 591 &gl_reset_notification_strategy_value)) { 592 std::string op; 593 std::string int_value; 594 std::string int_value2; 595 gl_reset_notification_strategy_value->GetString(kOp, &op); 596 gl_reset_notification_strategy_value->GetString("value", &int_value); 597 gl_reset_notification_strategy_value->GetString("value2", &int_value2); 598 if (!entry->SetGLResetNotificationStrategyInfo( 599 op, int_value, int_value2)) { 600 LOG(WARNING) << "Malformed gl_reset_notification_strategy entry " 601 << entry->id(); 602 return NULL; 603 } 604 dictionary_entry_count++; 605 } 606 607 std::string cpu_brand_value; 608 if (value->GetString("cpu_info", &cpu_brand_value)) { 609 if (!entry->SetCpuBrand(cpu_brand_value)) { 610 LOG(WARNING) << "Malformed cpu_brand entry " << entry->id(); 611 return NULL; 612 } 613 dictionary_entry_count++; 614 } 615 616 const base::DictionaryValue* perf_graphics_value = NULL; 617 if (value->GetDictionary("perf_graphics", &perf_graphics_value)) { 618 std::string op; 619 std::string float_value; 620 std::string float_value2; 621 perf_graphics_value->GetString(kOp, &op); 622 perf_graphics_value->GetString("value", &float_value); 623 perf_graphics_value->GetString("value2", &float_value2); 624 if (!entry->SetPerfGraphicsInfo(op, float_value, float_value2)) { 625 LOG(WARNING) << "Malformed perf_graphics entry " << entry->id(); 626 return NULL; 627 } 628 dictionary_entry_count++; 629 } 630 631 const base::DictionaryValue* perf_gaming_value = NULL; 632 if (value->GetDictionary("perf_gaming", &perf_gaming_value)) { 633 std::string op; 634 std::string float_value; 635 std::string float_value2; 636 perf_gaming_value->GetString(kOp, &op); 637 perf_gaming_value->GetString("value", &float_value); 638 perf_gaming_value->GetString("value2", &float_value2); 639 if (!entry->SetPerfGamingInfo(op, float_value, float_value2)) { 640 LOG(WARNING) << "Malformed perf_gaming entry " << entry->id(); 641 return NULL; 642 } 643 dictionary_entry_count++; 644 } 645 646 const base::DictionaryValue* perf_overall_value = NULL; 647 if (value->GetDictionary("perf_overall", &perf_overall_value)) { 648 std::string op; 649 std::string float_value; 650 std::string float_value2; 651 perf_overall_value->GetString(kOp, &op); 652 perf_overall_value->GetString("value", &float_value); 653 perf_overall_value->GetString("value2", &float_value2); 654 if (!entry->SetPerfOverallInfo(op, float_value, float_value2)) { 655 LOG(WARNING) << "Malformed perf_overall entry " << entry->id(); 656 return NULL; 657 } 658 dictionary_entry_count++; 659 } 660 661 const base::ListValue* machine_model_name_list; 662 if (value->GetList("machine_model_name", &machine_model_name_list)) { 663 for (size_t i = 0; i < machine_model_name_list->GetSize(); ++i) { 664 std::string model_name; 665 if (!machine_model_name_list->GetString(i, &model_name) || 666 !entry->AddMachineModelName(model_name)) { 667 LOG(WARNING) << "Malformed machine_model_name entry " << entry->id(); 668 return NULL; 669 } 670 } 671 dictionary_entry_count++; 672 } 673 674 const base::DictionaryValue* machine_model_version_value = NULL; 675 if (value->GetDictionary( 676 "machine_model_version", &machine_model_version_value)) { 677 std::string version_op = "any"; 678 std::string version_string; 679 std::string version_string2; 680 machine_model_version_value->GetString(kOp, &version_op); 681 machine_model_version_value->GetString("value", &version_string); 682 machine_model_version_value->GetString("value2", &version_string2); 683 if (!entry->SetMachineModelVersionInfo( 684 version_op, version_string, version_string2)) { 685 LOG(WARNING) << "Malformed machine_model_version entry " << entry->id(); 686 return NULL; 687 } 688 dictionary_entry_count++; 689 } 690 691 const base::DictionaryValue* gpu_count_value = NULL; 692 if (value->GetDictionary("gpu_count", &gpu_count_value)) { 693 std::string op; 694 std::string int_value; 695 std::string int_value2; 696 gpu_count_value->GetString(kOp, &op); 697 gpu_count_value->GetString("value", &int_value); 698 gpu_count_value->GetString("value2", &int_value2); 699 if (!entry->SetGpuCountInfo(op, int_value, int_value2)) { 700 LOG(WARNING) << "Malformed gpu_count entry " << entry->id(); 701 return NULL; 702 } 703 dictionary_entry_count++; 704 } 705 706 bool direct_rendering; 707 if (value->GetBoolean("direct_rendering", &direct_rendering)) { 708 entry->SetDirectRenderingInfo(direct_rendering); 709 dictionary_entry_count++; 710 } 711 712 if (top_level) { 713 const base::ListValue* feature_value = NULL; 714 if (value->GetList("features", &feature_value)) { 715 std::vector<std::string> feature_list; 716 for (size_t i = 0; i < feature_value->GetSize(); ++i) { 717 std::string feature; 718 if (feature_value->GetString(i, &feature)) { 719 feature_list.push_back(feature); 720 } else { 721 LOG(WARNING) << "Malformed feature entry " << entry->id(); 722 return NULL; 723 } 724 } 725 if (!entry->SetFeatures( 726 feature_list, feature_map, supports_feature_type_all)) { 727 LOG(WARNING) << "Malformed feature entry " << entry->id(); 728 return NULL; 729 } 730 dictionary_entry_count++; 731 } 732 } 733 734 if (top_level) { 735 const base::ListValue* exception_list_value = NULL; 736 if (value->GetList("exceptions", &exception_list_value)) { 737 for (size_t i = 0; i < exception_list_value->GetSize(); ++i) { 738 const base::DictionaryValue* exception_value = NULL; 739 if (!exception_list_value->GetDictionary(i, &exception_value)) { 740 LOG(WARNING) << "Malformed exceptions entry " << entry->id(); 741 return NULL; 742 } 743 ScopedGpuControlListEntry exception(GetEntryFromValue( 744 exception_value, false, feature_map, supports_feature_type_all)); 745 if (exception.get() == NULL) { 746 LOG(WARNING) << "Malformed exceptions entry " << entry->id(); 747 return NULL; 748 } 749 // Exception should inherit vendor_id from parent, otherwise if only 750 // device_ids are specified in Exception, the info will be incomplete. 751 if (exception->vendor_id_ == 0 && entry->vendor_id_ != 0) 752 exception->vendor_id_ = entry->vendor_id_; 753 entry->AddException(exception); 754 } 755 dictionary_entry_count++; 756 } 757 } 758 759 if (value->size() != dictionary_entry_count) { 760 LOG(WARNING) << "Entry with unknown fields " << entry->id(); 761 return NULL; 762 } 763 764 // If GL_VERSION is specified, but no info about whether it's GL or GLES, 765 // we use the default for the platform. See GLType enum declaration. 766 if (entry->gl_version_info_.get() != NULL && entry->gl_type_ == kGLTypeNone) 767 entry->gl_type_ = GetDefaultGLType(); 768 769 return entry; 770 } 771 772 GpuControlList::GpuControlListEntry::GpuControlListEntry() 773 : id_(0), 774 disabled_(false), 775 vendor_id_(0), 776 multi_gpu_style_(kMultiGpuStyleNone), 777 multi_gpu_category_(kMultiGpuCategoryPrimary), 778 gl_type_(kGLTypeNone) { 779 } 780 781 GpuControlList::GpuControlListEntry::~GpuControlListEntry() { } 782 783 bool GpuControlList::GpuControlListEntry::SetId(uint32 id) { 784 if (id != 0) { 785 id_ = id; 786 return true; 787 } 788 return false; 789 } 790 791 void GpuControlList::GpuControlListEntry::SetDisabled(bool disabled) { 792 disabled_ = disabled; 793 } 794 795 bool GpuControlList::GpuControlListEntry::SetOsInfo( 796 const std::string& os, 797 const std::string& version_op, 798 const std::string& version_string, 799 const std::string& version_string2) { 800 os_info_.reset(new OsInfo(os, version_op, version_string, version_string2)); 801 return os_info_->IsValid(); 802 } 803 804 bool GpuControlList::GpuControlListEntry::SetVendorId( 805 const std::string& vendor_id_string) { 806 vendor_id_ = 0; 807 return base::HexStringToUInt(vendor_id_string, &vendor_id_) && 808 vendor_id_ != 0; 809 } 810 811 bool GpuControlList::GpuControlListEntry::AddDeviceId( 812 const std::string& device_id_string) { 813 uint32 device_id = 0; 814 if (base::HexStringToUInt(device_id_string, &device_id) && device_id != 0) { 815 device_id_list_.push_back(device_id); 816 return true; 817 } 818 return false; 819 } 820 821 bool GpuControlList::GpuControlListEntry::SetMultiGpuStyle( 822 const std::string& multi_gpu_style_string) { 823 MultiGpuStyle style = StringToMultiGpuStyle(multi_gpu_style_string); 824 if (style == kMultiGpuStyleNone) 825 return false; 826 multi_gpu_style_ = style; 827 return true; 828 } 829 830 bool GpuControlList::GpuControlListEntry::SetMultiGpuCategory( 831 const std::string& multi_gpu_category_string) { 832 MultiGpuCategory category = 833 StringToMultiGpuCategory(multi_gpu_category_string); 834 if (category == kMultiGpuCategoryNone) 835 return false; 836 multi_gpu_category_ = category; 837 return true; 838 } 839 840 bool GpuControlList::GpuControlListEntry::SetGLType( 841 const std::string& gl_type_string) { 842 GLType gl_type = StringToGLType(gl_type_string); 843 if (gl_type == kGLTypeNone) 844 return false; 845 gl_type_ = gl_type; 846 return true; 847 } 848 849 bool GpuControlList::GpuControlListEntry::SetDriverVendorInfo( 850 const std::string& vendor_value) { 851 driver_vendor_info_ = vendor_value; 852 return !driver_vendor_info_.empty(); 853 } 854 855 bool GpuControlList::GpuControlListEntry::SetDriverVersionInfo( 856 const std::string& version_op, 857 const std::string& version_style, 858 const std::string& version_string, 859 const std::string& version_string2) { 860 driver_version_info_.reset(new VersionInfo( 861 version_op, version_style, version_string, version_string2)); 862 return driver_version_info_->IsValid(); 863 } 864 865 bool GpuControlList::GpuControlListEntry::SetDriverDateInfo( 866 const std::string& date_op, 867 const std::string& date_string, 868 const std::string& date_string2) { 869 driver_date_info_.reset( 870 new VersionInfo(date_op, std::string(), date_string, date_string2)); 871 return driver_date_info_->IsValid(); 872 } 873 874 bool GpuControlList::GpuControlListEntry::SetGLVersionInfo( 875 const std::string& version_op, 876 const std::string& version_string, 877 const std::string& version_string2) { 878 gl_version_info_.reset(new VersionInfo( 879 version_op, std::string(), version_string, version_string2)); 880 return gl_version_info_->IsValid(); 881 } 882 883 bool GpuControlList::GpuControlListEntry::SetGLVendorInfo( 884 const std::string& vendor_value) { 885 gl_vendor_info_ = vendor_value; 886 return !gl_vendor_info_.empty(); 887 } 888 889 bool GpuControlList::GpuControlListEntry::SetGLRendererInfo( 890 const std::string& renderer_value) { 891 gl_renderer_info_ = renderer_value; 892 return !gl_renderer_info_.empty(); 893 } 894 895 bool GpuControlList::GpuControlListEntry::SetGLExtensionsInfo( 896 const std::string& extensions_value) { 897 gl_extensions_info_ = extensions_value; 898 return !gl_extensions_info_.empty(); 899 } 900 901 bool GpuControlList::GpuControlListEntry::SetGLResetNotificationStrategyInfo( 902 const std::string& op, 903 const std::string& int_string, 904 const std::string& int_string2) { 905 gl_reset_notification_strategy_info_.reset( 906 new IntInfo(op, int_string, int_string2)); 907 return gl_reset_notification_strategy_info_->IsValid(); 908 } 909 910 bool GpuControlList::GpuControlListEntry::SetCpuBrand( 911 const std::string& cpu_value) { 912 cpu_brand_ = cpu_value; 913 return !cpu_brand_.empty(); 914 } 915 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(); 922 } 923 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(); 930 } 931 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(); 938 } 939 940 bool GpuControlList::GpuControlListEntry::AddMachineModelName( 941 const std::string& model_name) { 942 if (model_name.empty()) 943 return false; 944 machine_model_name_list_.push_back(model_name); 945 return true; 946 } 947 948 bool GpuControlList::GpuControlListEntry::SetMachineModelVersionInfo( 949 const std::string& version_op, 950 const std::string& version_string, 951 const std::string& version_string2) { 952 machine_model_version_info_.reset(new VersionInfo( 953 version_op, std::string(), version_string, version_string2)); 954 return machine_model_version_info_->IsValid(); 955 } 956 957 bool GpuControlList::GpuControlListEntry::SetGpuCountInfo( 958 const std::string& op, 959 const std::string& int_string, 960 const std::string& int_string2) { 961 gpu_count_info_.reset(new IntInfo(op, int_string, int_string2)); 962 return gpu_count_info_->IsValid(); 963 } 964 965 void GpuControlList::GpuControlListEntry::SetDirectRenderingInfo(bool value) { 966 direct_rendering_info_.reset(new BoolInfo(value)); 967 } 968 969 bool GpuControlList::GpuControlListEntry::SetFeatures( 970 const std::vector<std::string>& feature_strings, 971 const FeatureMap& feature_map, 972 bool supports_feature_type_all) { 973 size_t size = feature_strings.size(); 974 if (size == 0) 975 return false; 976 features_.clear(); 977 for (size_t i = 0; i < size; ++i) { 978 int feature = 0; 979 if (supports_feature_type_all && feature_strings[i] == "all") { 980 for (FeatureMap::const_iterator iter = feature_map.begin(); 981 iter != feature_map.end(); ++iter) 982 features_.insert(iter->second); 983 continue; 984 } 985 if (!StringToFeature(feature_strings[i], &feature, feature_map)) { 986 features_.clear(); 987 return false; 988 } 989 features_.insert(feature); 990 } 991 return true; 992 } 993 994 void GpuControlList::GpuControlListEntry::AddException( 995 ScopedGpuControlListEntry exception) { 996 exceptions_.push_back(exception); 997 } 998 999 bool GpuControlList::GpuControlListEntry::GLVersionInfoMismatch( 1000 const std::string& gl_version) const { 1001 if (gl_version.empty()) 1002 return false; 1003 1004 if (gl_version_info_.get() == NULL && gl_type_ == kGLTypeNone) 1005 return false; 1006 1007 std::vector<std::string> segments; 1008 base::SplitString(gl_version, ' ', &segments); 1009 std::string number; 1010 GLType gl_type = kGLTypeNone; 1011 if (segments.size() > 2 && 1012 segments[0] == "OpenGL" && segments[1] == "ES") { 1013 number = segments[2]; 1014 gl_type = kGLTypeGLES; 1015 if (segments.size() > 3 && 1016 StartsWithASCII(segments[3], "(ANGLE", false)) { 1017 gl_type = kGLTypeANGLE; 1018 } 1019 } else { 1020 number = segments[0]; 1021 gl_type = kGLTypeGL; 1022 } 1023 1024 if (gl_type_ != kGLTypeNone && gl_type_ != gl_type) 1025 return true; 1026 if (gl_version_info_.get() != NULL && !gl_version_info_->Contains(number)) 1027 return true; 1028 return false; 1029 } 1030 1031 // static 1032 GpuControlList::GpuControlListEntry::MultiGpuStyle 1033 GpuControlList::GpuControlListEntry::StringToMultiGpuStyle( 1034 const std::string& style) { 1035 if (style == kMultiGpuStyleStringOptimus) 1036 return kMultiGpuStyleOptimus; 1037 if (style == kMultiGpuStyleStringAMDSwitchable) 1038 return kMultiGpuStyleAMDSwitchable; 1039 if (style == kMultiGpuStyleStringAMDSwitchableIntegrated) 1040 return kMultiGpuStyleAMDSwitchableIntegrated; 1041 if (style == kMultiGpuStyleStringAMDSwitchableDiscrete) 1042 return kMultiGpuStyleAMDSwitchableDiscrete; 1043 return kMultiGpuStyleNone; 1044 } 1045 1046 // static 1047 GpuControlList::GpuControlListEntry::MultiGpuCategory 1048 GpuControlList::GpuControlListEntry::StringToMultiGpuCategory( 1049 const std::string& category) { 1050 if (category == kMultiGpuCategoryStringPrimary) 1051 return kMultiGpuCategoryPrimary; 1052 if (category == kMultiGpuCategoryStringSecondary) 1053 return kMultiGpuCategorySecondary; 1054 if (category == kMultiGpuCategoryStringActive) 1055 return kMultiGpuCategoryActive; 1056 if (category == kMultiGpuCategoryStringAny) 1057 return kMultiGpuCategoryAny; 1058 return kMultiGpuCategoryNone; 1059 } 1060 1061 // static 1062 GpuControlList::GpuControlListEntry::GLType 1063 GpuControlList::GpuControlListEntry::StringToGLType( 1064 const std::string& gl_type) { 1065 if (gl_type == kGLTypeStringGL) 1066 return kGLTypeGL; 1067 if (gl_type == kGLTypeStringGLES) 1068 return kGLTypeGLES; 1069 if (gl_type == kGLTypeStringANGLE) 1070 return kGLTypeANGLE; 1071 return kGLTypeNone; 1072 } 1073 1074 // static 1075 GpuControlList::GpuControlListEntry::GLType 1076 GpuControlList::GpuControlListEntry::GetDefaultGLType() { 1077 #if defined(OS_CHROMEOS) 1078 return kGLTypeGL; 1079 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 1080 return kGLTypeGL; 1081 #elif defined(OS_MACOSX) 1082 return kGLTypeGL; 1083 #elif defined(OS_WIN) 1084 return kGLTypeANGLE; 1085 #elif defined(OS_ANDROID) 1086 return kGLTypeGLES; 1087 #else 1088 return kGLTypeNone; 1089 #endif 1090 } 1091 1092 void GpuControlList::GpuControlListEntry::LogControlListMatch( 1093 const std::string& control_list_logging_name) const { 1094 static const char kControlListMatchMessage[] = 1095 "Control list match for rule #%u in %s."; 1096 VLOG(1) << base::StringPrintf(kControlListMatchMessage, id_, 1097 control_list_logging_name.c_str()); 1098 } 1099 1100 bool GpuControlList::GpuControlListEntry::Contains( 1101 OsType os_type, const std::string& os_version, 1102 const GPUInfo& gpu_info) const { 1103 DCHECK(os_type != kOsAny); 1104 if (os_info_.get() != NULL && !os_info_->Contains(os_type, os_version)) 1105 return false; 1106 if (vendor_id_ != 0) { 1107 std::vector<GPUInfo::GPUDevice> candidates; 1108 switch (multi_gpu_category_) { 1109 case kMultiGpuCategoryPrimary: 1110 candidates.push_back(gpu_info.gpu); 1111 break; 1112 case kMultiGpuCategorySecondary: 1113 candidates = gpu_info.secondary_gpus; 1114 break; 1115 case kMultiGpuCategoryAny: 1116 candidates = gpu_info.secondary_gpus; 1117 candidates.push_back(gpu_info.gpu); 1118 break; 1119 case kMultiGpuCategoryActive: 1120 if (gpu_info.gpu.active) 1121 candidates.push_back(gpu_info.gpu); 1122 for (size_t ii = 0; ii < gpu_info.secondary_gpus.size(); ++ii) { 1123 if (gpu_info.secondary_gpus[ii].active) 1124 candidates.push_back(gpu_info.secondary_gpus[ii]); 1125 } 1126 default: 1127 break; 1128 } 1129 1130 GPUInfo::GPUDevice gpu; 1131 gpu.vendor_id = vendor_id_; 1132 bool found = false; 1133 if (device_id_list_.empty()) { 1134 for (size_t ii = 0; ii < candidates.size(); ++ii) { 1135 if (gpu.vendor_id == candidates[ii].vendor_id) { 1136 found = true; 1137 break; 1138 } 1139 } 1140 } else { 1141 for (size_t ii = 0; ii < device_id_list_.size(); ++ii) { 1142 gpu.device_id = device_id_list_[ii]; 1143 for (size_t jj = 0; jj < candidates.size(); ++jj) { 1144 if (gpu.vendor_id == candidates[jj].vendor_id && 1145 gpu.device_id == candidates[jj].device_id) { 1146 found = true; 1147 break; 1148 } 1149 } 1150 } 1151 } 1152 if (!found) 1153 return false; 1154 } 1155 switch (multi_gpu_style_) { 1156 case kMultiGpuStyleOptimus: 1157 if (!gpu_info.optimus) 1158 return false; 1159 break; 1160 case kMultiGpuStyleAMDSwitchable: 1161 if (!gpu_info.amd_switchable) 1162 return false; 1163 break; 1164 case kMultiGpuStyleAMDSwitchableDiscrete: 1165 if (!gpu_info.amd_switchable) 1166 return false; 1167 // The discrete GPU is always the primary GPU. 1168 // This is guaranteed by GpuInfoCollector. 1169 if (!gpu_info.gpu.active) 1170 return false; 1171 break; 1172 case kMultiGpuStyleAMDSwitchableIntegrated: 1173 if (!gpu_info.amd_switchable) 1174 return false; 1175 // Assume the integrated GPU is the first in the secondary GPU list. 1176 if (gpu_info.secondary_gpus.size() == 0 || 1177 !gpu_info.secondary_gpus[0].active) 1178 return false; 1179 break; 1180 case kMultiGpuStyleNone: 1181 break; 1182 } 1183 if (StringMismatch(gpu_info.driver_vendor, driver_vendor_info_)) 1184 return false; 1185 if (driver_version_info_.get() != NULL && !gpu_info.driver_version.empty()) { 1186 if (!driver_version_info_->Contains(gpu_info.driver_version)) 1187 return false; 1188 } 1189 if (driver_date_info_.get() != NULL && !gpu_info.driver_date.empty()) { 1190 if (!driver_date_info_->Contains(gpu_info.driver_date, '-')) 1191 return false; 1192 } 1193 if (GLVersionInfoMismatch(gpu_info.gl_version)) 1194 return false; 1195 if (StringMismatch(gpu_info.gl_vendor, gl_vendor_info_)) 1196 return false; 1197 if (StringMismatch(gpu_info.gl_renderer, gl_renderer_info_)) 1198 return false; 1199 if (StringMismatch(gpu_info.gl_extensions, gl_extensions_info_)) 1200 return false; 1201 if (gl_reset_notification_strategy_info_.get() != NULL && 1202 !gl_reset_notification_strategy_info_->Contains( 1203 gpu_info.gl_reset_notification_strategy)) 1204 return false; 1205 if (perf_graphics_info_.get() != NULL && 1206 (gpu_info.performance_stats.graphics == 0.0 || 1207 !perf_graphics_info_->Contains(gpu_info.performance_stats.graphics))) 1208 return false; 1209 if (perf_gaming_info_.get() != NULL && 1210 (gpu_info.performance_stats.gaming == 0.0 || 1211 !perf_gaming_info_->Contains(gpu_info.performance_stats.gaming))) 1212 return false; 1213 if (perf_overall_info_.get() != NULL && 1214 (gpu_info.performance_stats.overall == 0.0 || 1215 !perf_overall_info_->Contains(gpu_info.performance_stats.overall))) 1216 return false; 1217 if (!machine_model_name_list_.empty()) { 1218 if (gpu_info.machine_model_name.empty()) 1219 return false; 1220 bool found_match = false; 1221 for (size_t ii = 0; ii < machine_model_name_list_.size(); ++ii) { 1222 if (RE2::FullMatch(gpu_info.machine_model_name, 1223 machine_model_name_list_[ii])) { 1224 found_match = true; 1225 break; 1226 } 1227 } 1228 if (!found_match) 1229 return false; 1230 } 1231 if (machine_model_version_info_.get() != NULL && 1232 (gpu_info.machine_model_version.empty() || 1233 !machine_model_version_info_->Contains(gpu_info.machine_model_version))) 1234 return false; 1235 if (gpu_count_info_.get() != NULL && 1236 !gpu_count_info_->Contains(gpu_info.secondary_gpus.size() + 1)) 1237 return false; 1238 if (direct_rendering_info_.get() != NULL && 1239 !direct_rendering_info_->Contains(gpu_info.direct_rendering)) 1240 return false; 1241 if (!cpu_brand_.empty()) { 1242 base::CPU cpu_info; 1243 if (StringMismatch(cpu_info.cpu_brand(), cpu_brand_)) 1244 return false; 1245 } 1246 1247 for (size_t i = 0; i < exceptions_.size(); ++i) { 1248 if (exceptions_[i]->Contains(os_type, os_version, gpu_info) && 1249 !exceptions_[i]->NeedsMoreInfo(gpu_info)) 1250 return false; 1251 } 1252 return true; 1253 } 1254 1255 bool GpuControlList::GpuControlListEntry::NeedsMoreInfo( 1256 const GPUInfo& gpu_info) const { 1257 // We only check for missing info that might be collected with a gl context. 1258 // If certain info is missing due to some error, say, we fail to collect 1259 // vendor_id/device_id, then even if we launch GPU process and create a gl 1260 // context, we won't gather such missing info, so we still return false. 1261 if (!driver_vendor_info_.empty() && gpu_info.driver_vendor.empty()) 1262 return true; 1263 if (driver_version_info_.get() && gpu_info.driver_version.empty()) 1264 return true; 1265 if (!gl_vendor_info_.empty() && gpu_info.gl_vendor.empty()) 1266 return true; 1267 if (!gl_renderer_info_.empty() && gpu_info.gl_renderer.empty()) 1268 return true; 1269 for (size_t i = 0; i < exceptions_.size(); ++i) { 1270 if (exceptions_[i]->NeedsMoreInfo(gpu_info)) 1271 return true; 1272 } 1273 return false; 1274 } 1275 1276 GpuControlList::OsType GpuControlList::GpuControlListEntry::GetOsType() const { 1277 if (os_info_.get() == NULL) 1278 return kOsAny; 1279 return os_info_->type(); 1280 } 1281 1282 uint32 GpuControlList::GpuControlListEntry::id() const { 1283 return id_; 1284 } 1285 1286 bool GpuControlList::GpuControlListEntry::disabled() const { 1287 return disabled_; 1288 } 1289 1290 const std::set<int>& GpuControlList::GpuControlListEntry::features() const { 1291 return features_; 1292 } 1293 1294 void GpuControlList::GpuControlListEntry::GetFeatureNames( 1295 base::ListValue* feature_names, 1296 const FeatureMap& feature_map, 1297 bool supports_feature_type_all) const { 1298 DCHECK(feature_names); 1299 if (supports_feature_type_all && features_.size() == feature_map.size()) { 1300 feature_names->AppendString("all"); 1301 return; 1302 } 1303 for (FeatureMap::const_iterator iter = feature_map.begin(); 1304 iter != feature_map.end(); ++iter) { 1305 if (features_.count(iter->second) > 0) 1306 feature_names->AppendString(iter->first); 1307 } 1308 } 1309 1310 // static 1311 bool GpuControlList::GpuControlListEntry::StringToFeature( 1312 const std::string& feature_name, int* feature_id, 1313 const FeatureMap& feature_map) { 1314 FeatureMap::const_iterator iter = feature_map.find(feature_name); 1315 if (iter != feature_map.end()) { 1316 *feature_id = iter->second; 1317 return true; 1318 } 1319 return false; 1320 } 1321 1322 GpuControlList::GpuControlList() 1323 : max_entry_id_(0), 1324 needs_more_info_(false), 1325 supports_feature_type_all_(false), 1326 control_list_logging_enabled_(false) { 1327 } 1328 1329 GpuControlList::~GpuControlList() { 1330 Clear(); 1331 } 1332 1333 bool GpuControlList::LoadList( 1334 const std::string& json_context, 1335 GpuControlList::OsFilter os_filter) { 1336 scoped_ptr<base::Value> root; 1337 root.reset(base::JSONReader::Read(json_context)); 1338 if (root.get() == NULL || !root->IsType(base::Value::TYPE_DICTIONARY)) 1339 return false; 1340 1341 base::DictionaryValue* root_dictionary = 1342 static_cast<base::DictionaryValue*>(root.get()); 1343 DCHECK(root_dictionary); 1344 return LoadList(*root_dictionary, os_filter); 1345 } 1346 1347 bool GpuControlList::LoadList(const base::DictionaryValue& parsed_json, 1348 GpuControlList::OsFilter os_filter) { 1349 std::vector<ScopedGpuControlListEntry> entries; 1350 1351 parsed_json.GetString("version", &version_); 1352 std::vector<std::string> pieces; 1353 if (!ProcessVersionString(version_, '.', &pieces)) 1354 return false; 1355 1356 const base::ListValue* list = NULL; 1357 if (!parsed_json.GetList("entries", &list)) 1358 return false; 1359 1360 uint32 max_entry_id = 0; 1361 for (size_t i = 0; i < list->GetSize(); ++i) { 1362 const base::DictionaryValue* list_item = NULL; 1363 bool valid = list->GetDictionary(i, &list_item); 1364 if (!valid || list_item == NULL) 1365 return false; 1366 ScopedGpuControlListEntry entry(GpuControlListEntry::GetEntryFromValue( 1367 list_item, true, feature_map_, supports_feature_type_all_)); 1368 if (entry.get() == NULL) 1369 return false; 1370 if (entry->id() > max_entry_id) 1371 max_entry_id = entry->id(); 1372 entries.push_back(entry); 1373 } 1374 1375 Clear(); 1376 OsType my_os = GetOsType(); 1377 for (size_t i = 0; i < entries.size(); ++i) { 1378 OsType entry_os = entries[i]->GetOsType(); 1379 if (os_filter == GpuControlList::kAllOs || 1380 entry_os == kOsAny || entry_os == my_os) 1381 entries_.push_back(entries[i]); 1382 } 1383 max_entry_id_ = max_entry_id; 1384 return true; 1385 } 1386 1387 std::set<int> GpuControlList::MakeDecision( 1388 GpuControlList::OsType os, 1389 std::string os_version, 1390 const GPUInfo& gpu_info) { 1391 active_entries_.clear(); 1392 std::set<int> features; 1393 1394 needs_more_info_ = false; 1395 std::set<int> possible_features; 1396 1397 if (os == kOsAny) 1398 os = GetOsType(); 1399 if (os_version.empty()) 1400 os_version = base::SysInfo::OperatingSystemVersion(); 1401 1402 for (size_t i = 0; i < entries_.size(); ++i) { 1403 if (entries_[i]->Contains(os, os_version, gpu_info)) { 1404 bool needs_more_info = entries_[i]->NeedsMoreInfo(gpu_info); 1405 if (!entries_[i]->disabled()) { 1406 if (control_list_logging_enabled_) 1407 entries_[i]->LogControlListMatch(control_list_logging_name_); 1408 MergeFeatureSets(&possible_features, entries_[i]->features()); 1409 if (!needs_more_info) 1410 MergeFeatureSets(&features, entries_[i]->features()); 1411 } 1412 if (!needs_more_info) 1413 active_entries_.push_back(entries_[i]); 1414 } 1415 } 1416 1417 if (possible_features.size() > features.size()) 1418 needs_more_info_ = true; 1419 1420 return features; 1421 } 1422 1423 void GpuControlList::GetDecisionEntries( 1424 std::vector<uint32>* entry_ids, bool disabled) const { 1425 DCHECK(entry_ids); 1426 entry_ids->clear(); 1427 for (size_t i = 0; i < active_entries_.size(); ++i) { 1428 if (disabled == active_entries_[i]->disabled()) 1429 entry_ids->push_back(active_entries_[i]->id()); 1430 } 1431 } 1432 1433 void GpuControlList::GetReasons(base::ListValue* problem_list, 1434 const std::string& tag) const { 1435 DCHECK(problem_list); 1436 for (size_t i = 0; i < active_entries_.size(); ++i) { 1437 GpuControlListEntry* entry = active_entries_[i].get(); 1438 if (entry->disabled()) 1439 continue; 1440 base::DictionaryValue* problem = new base::DictionaryValue(); 1441 1442 problem->SetString("description", entry->description()); 1443 1444 base::ListValue* cr_bugs = new base::ListValue(); 1445 for (size_t j = 0; j < entry->cr_bugs().size(); ++j) 1446 cr_bugs->Append(new base::FundamentalValue(entry->cr_bugs()[j])); 1447 problem->Set("crBugs", cr_bugs); 1448 1449 base::ListValue* webkit_bugs = new base::ListValue(); 1450 for (size_t j = 0; j < entry->webkit_bugs().size(); ++j) { 1451 webkit_bugs->Append(new base::FundamentalValue(entry->webkit_bugs()[j])); 1452 } 1453 problem->Set("webkitBugs", webkit_bugs); 1454 1455 base::ListValue* features = new base::ListValue(); 1456 entry->GetFeatureNames(features, feature_map_, supports_feature_type_all_); 1457 problem->Set("affectedGpuSettings", features); 1458 1459 DCHECK(tag == "workarounds" || tag == "disabledFeatures"); 1460 problem->SetString("tag", tag); 1461 1462 problem_list->Append(problem); 1463 } 1464 } 1465 1466 size_t GpuControlList::num_entries() const { 1467 return entries_.size(); 1468 } 1469 1470 uint32 GpuControlList::max_entry_id() const { 1471 return max_entry_id_; 1472 } 1473 1474 std::string GpuControlList::version() const { 1475 return version_; 1476 } 1477 1478 GpuControlList::OsType GpuControlList::GetOsType() { 1479 #if defined(OS_CHROMEOS) 1480 return kOsChromeOS; 1481 #elif defined(OS_WIN) 1482 return kOsWin; 1483 #elif defined(OS_ANDROID) 1484 return kOsAndroid; 1485 #elif defined(OS_LINUX) || defined(OS_OPENBSD) 1486 return kOsLinux; 1487 #elif defined(OS_MACOSX) 1488 return kOsMacosx; 1489 #else 1490 return kOsUnknown; 1491 #endif 1492 } 1493 1494 void GpuControlList::Clear() { 1495 entries_.clear(); 1496 active_entries_.clear(); 1497 max_entry_id_ = 0; 1498 } 1499 1500 // static 1501 GpuControlList::NumericOp GpuControlList::StringToNumericOp( 1502 const std::string& op) { 1503 if (op == "=") 1504 return kEQ; 1505 if (op == "<") 1506 return kLT; 1507 if (op == "<=") 1508 return kLE; 1509 if (op == ">") 1510 return kGT; 1511 if (op == ">=") 1512 return kGE; 1513 if (op == "any") 1514 return kAny; 1515 if (op == "between") 1516 return kBetween; 1517 return kUnknown; 1518 } 1519 1520 void GpuControlList::AddSupportedFeature( 1521 const std::string& feature_name, int feature_id) { 1522 feature_map_[feature_name] = feature_id; 1523 } 1524 1525 void GpuControlList::set_supports_feature_type_all(bool supported) { 1526 supports_feature_type_all_ = supported; 1527 } 1528 1529 } // namespace gpu 1530 1531