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