| Index: content/gpu/gpu_info_collector_mac.mm
|
| ===================================================================
|
| --- content/gpu/gpu_info_collector_mac.mm (revision 137173)
|
| +++ content/gpu/gpu_info_collector_mac.mm (working copy)
|
| @@ -22,29 +22,23 @@
|
|
|
| namespace {
|
|
|
| -struct VideoCardInfo {
|
| - UInt32 vendor_id;
|
| - UInt32 device_id;
|
| +const UInt32 kVendorIDIntel = 0x8086;
|
| +const UInt32 kVendorIDNVidia = 0x10de;
|
| +const UInt32 kVendorIDAMD = 0x1002;
|
|
|
| - VideoCardInfo(UInt32 vendor, UInt32 device) {
|
| - vendor_id = vendor;
|
| - device_id = device;
|
| - }
|
| -};
|
| +// Return 0 if we couldn't find the property.
|
| +// The property values we use should not be 0, so it's OK to use 0 as failure.
|
| +UInt32 GetEntryProperty(io_registry_entry_t entry, CFStringRef property_name) {
|
| + base::mac::ScopedCFTypeRef<CFDataRef> data_ref(static_cast<CFDataRef>(
|
| + IORegistryEntrySearchCFProperty(entry,
|
| + kIOServicePlane,
|
| + property_name,
|
| + kCFAllocatorDefault,
|
| + kIORegistryIterateRecursively |
|
| + kIORegistryIterateParents)));
|
| + if (!data_ref)
|
| + return 0;
|
|
|
| -CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort,
|
| - CFStringRef propertyName) {
|
| - return IORegistryEntrySearchCFProperty(dspPort,
|
| - kIOServicePlane,
|
| - propertyName,
|
| - kCFAllocatorDefault,
|
| - kIORegistryIterateRecursively |
|
| - kIORegistryIterateParents);
|
| -}
|
| -
|
| -UInt32 IntValueOfCFData(CFDataRef data_ref) {
|
| - DCHECK(data_ref);
|
| -
|
| UInt32 value = 0;
|
| const UInt32* value_pointer =
|
| reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref));
|
| @@ -53,69 +47,107 @@
|
| return value;
|
| }
|
|
|
| +// Find the info of the current GPU.
|
| +content::GPUInfo::GPUDevice GetActiveGPU() {
|
| + content::GPUInfo::GPUDevice gpu;
|
| + io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
|
| + gpu.vendor_id = GetEntryProperty(dsp_port, CFSTR("vendor-id"));
|
| + gpu.device_id = GetEntryProperty(dsp_port, CFSTR("device-id"));
|
| + return gpu;
|
| +}
|
| +
|
| // Scan IO registry for PCI video cards.
|
| -// If two cards are located, assume the non-Intel card is the high-end
|
| -// one that's going to be used by Chromium GPU process.
|
| -// If more than two cards are located, return false. In such rare situation,
|
| -// video card information should be collected through identifying the currently
|
| -// in-use card as in CollectVideoCardInfo().
|
| bool CollectPCIVideoCardInfo(content::GPUInfo* gpu_info) {
|
| DCHECK(gpu_info);
|
|
|
| + // Collect all GPUs' info.
|
| // match_dictionary will be consumed by IOServiceGetMatchingServices, no need
|
| // to release it.
|
| CFMutableDictionaryRef match_dictionary = IOServiceMatching("IOPCIDevice");
|
| io_iterator_t entry_iterator;
|
| + std::vector<content::GPUInfo::GPUDevice> gpu_list;
|
| if (IOServiceGetMatchingServices(kIOMasterPortDefault,
|
| match_dictionary,
|
| - &entry_iterator) != kIOReturnSuccess)
|
| - return false;
|
| -
|
| - std::vector<VideoCardInfo> video_card_list;
|
| - io_registry_entry_t entry;
|
| - while ((entry = IOIteratorNext(entry_iterator))) {
|
| - base::mac::ScopedCFTypeRef<CFDataRef> class_code_ref(static_cast<CFDataRef>(
|
| - SearchPortForProperty(entry, CFSTR("class-code"))));
|
| - if (!class_code_ref)
|
| - continue;
|
| - UInt32 class_code = IntValueOfCFData(class_code_ref);
|
| - if (class_code != 0x30000) // DISPLAY_VGA
|
| - continue;
|
| - base::mac::ScopedCFTypeRef<CFDataRef> vendor_id_ref(static_cast<CFDataRef>(
|
| - SearchPortForProperty(entry, CFSTR("vendor-id"))));
|
| - if (!vendor_id_ref)
|
| - continue;
|
| - UInt32 vendor_id = IntValueOfCFData(vendor_id_ref);
|
| - base::mac::ScopedCFTypeRef<CFDataRef> device_id_ref(static_cast<CFDataRef>(
|
| - SearchPortForProperty(entry, CFSTR("device-id"))));
|
| - if (!device_id_ref)
|
| - continue;
|
| - UInt32 device_id = IntValueOfCFData(device_id_ref);
|
| - video_card_list.push_back(VideoCardInfo(vendor_id, device_id));
|
| + &entry_iterator) == kIOReturnSuccess) {
|
| + io_registry_entry_t entry;
|
| + while ((entry = IOIteratorNext(entry_iterator))) {
|
| + content::GPUInfo::GPUDevice gpu;
|
| + if (GetEntryProperty(entry, CFSTR("class-code")) != 0x30000) {
|
| + // 0x30000 : DISPLAY_VGA
|
| + continue;
|
| + }
|
| + gpu.vendor_id = GetEntryProperty(entry, CFSTR("vendor-id"));
|
| + gpu.device_id = GetEntryProperty(entry, CFSTR("device-id"));
|
| + if (gpu.vendor_id && gpu.device_id)
|
| + gpu_list.push_back(gpu);
|
| + }
|
| + IOObjectRelease(entry_iterator);
|
| }
|
| - IOObjectRelease(entry_iterator);
|
|
|
| - const UInt32 kIntelVendorId = 0x8086;
|
| - size_t found = video_card_list.size();
|
| - switch (video_card_list.size()) {
|
| + switch (gpu_list.size()) {
|
| + case 0:
|
| + return false;
|
| case 1:
|
| - found = 0;
|
| + gpu_info->gpu = gpu_list[0];
|
| break;
|
| case 2:
|
| - if (video_card_list[0].vendor_id == kIntelVendorId &&
|
| - video_card_list[1].vendor_id != kIntelVendorId)
|
| - found = 1;
|
| - else if (video_card_list[0].vendor_id != kIntelVendorId &&
|
| - video_card_list[1].vendor_id == kIntelVendorId)
|
| - found = 0;
|
| + {
|
| + int integrated = -1;
|
| + int discrete = -1;
|
| + if (gpu_list[0].vendor_id == kVendorIDIntel)
|
| + integrated = 0;
|
| + else if (gpu_list[1].vendor_id == kVendorIDIntel)
|
| + integrated = 1;
|
| + if (integrated >= 0) {
|
| + switch (gpu_list[1 - integrated].vendor_id) {
|
| + case kVendorIDAMD:
|
| + gpu_info->amd_switchable = true;
|
| + discrete = 1 - integrated;
|
| + break;
|
| + case kVendorIDNVidia:
|
| + gpu_info->optimus = true;
|
| + discrete = 1 - integrated;
|
| + break;
|
| + default:
|
| + break;
|
| + }
|
| + }
|
| + if (integrated >= 0 && discrete >= 0) {
|
| + // We always put discrete GPU as primary for blacklisting purpose.
|
| + gpu_info->gpu = gpu_list[discrete];
|
| + gpu_info->secondary_gpus.push_back(gpu_list[integrated]);
|
| + break;
|
| + }
|
| + // If it's not optimus or amd_switchable, we put the current GPU as
|
| + // primary. Fall through to default.
|
| + }
|
| + default:
|
| + {
|
| + content::GPUInfo::GPUDevice active_gpu = GetActiveGPU();
|
| + size_t current = gpu_list.size();
|
| + if (active_gpu.vendor_id && active_gpu.device_id) {
|
| + for (size_t i = 0; i < gpu_list.size(); ++i) {
|
| + if (gpu_list[i].vendor_id == active_gpu.vendor_id &&
|
| + gpu_list[i].device_id == active_gpu.device_id) {
|
| + current = i;
|
| + break;
|
| + }
|
| + }
|
| + }
|
| + if (current == gpu_list.size()) {
|
| + // If we fail to identify the current GPU, select any one as primary.
|
| + current = 0;
|
| + }
|
| + for (size_t i = 0; i < gpu_list.size(); ++i) {
|
| + if (i == current)
|
| + gpu_info->gpu = gpu_list[i];
|
| + else
|
| + gpu_info->secondary_gpus.push_back(gpu_list[i]);
|
| + }
|
| + }
|
| break;
|
| }
|
| - if (found < video_card_list.size()) {
|
| - gpu_info->gpu.vendor_id = video_card_list[found].vendor_id;
|
| - gpu_info->gpu.device_id = video_card_list[found].device_id;
|
| - return true;
|
| - }
|
| - return false;
|
| + return (gpu_info->gpu.vendor_id && gpu_info->gpu.device_id);
|
| }
|
|
|
| } // namespace anonymous
|
| @@ -134,32 +166,11 @@
|
| bool CollectPreliminaryGraphicsInfo(content::GPUInfo* gpu_info) {
|
| DCHECK(gpu_info);
|
|
|
| - bool rt = true;
|
| - if (!CollectPCIVideoCardInfo(gpu_info) && !CollectVideoCardInfo(gpu_info))
|
| - rt = false;
|
| -
|
| - return rt;
|
| + return CollectPCIVideoCardInfo(gpu_info);
|
| }
|
|
|
| bool CollectVideoCardInfo(content::GPUInfo* gpu_info) {
|
| - DCHECK(gpu_info);
|
| -
|
| - UInt32 vendor_id = 0, device_id = 0;
|
| - io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay);
|
| - CFTypeRef vendor_id_ref = SearchPortForProperty(dsp_port, CFSTR("vendor-id"));
|
| - if (vendor_id_ref) {
|
| - vendor_id = IntValueOfCFData((CFDataRef)vendor_id_ref);
|
| - CFRelease(vendor_id_ref);
|
| - }
|
| - CFTypeRef device_id_ref = SearchPortForProperty(dsp_port, CFSTR("device-id"));
|
| - if (device_id_ref) {
|
| - device_id = IntValueOfCFData((CFDataRef)device_id_ref);
|
| - CFRelease(device_id_ref);
|
| - }
|
| -
|
| - gpu_info->gpu.vendor_id = vendor_id;
|
| - gpu_info->gpu.device_id = device_id;
|
| - return true;
|
| + return CollectPreliminaryGraphicsInfo(gpu_info);
|
| }
|
|
|
| bool CollectDriverInfoGL(content::GPUInfo* gpu_info) {
|
|
|