summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
Diffstat (limited to 'content')
-rw-r--r--content/gpu/gpu_info_collector_mac.mm80
1 files changed, 79 insertions, 1 deletions
diff --git a/content/gpu/gpu_info_collector_mac.mm b/content/gpu/gpu_info_collector_mac.mm
index dd9b663..be6deb5 100644
--- a/content/gpu/gpu_info_collector_mac.mm
+++ b/content/gpu/gpu_info_collector_mac.mm
@@ -4,7 +4,10 @@
#include "content/gpu/gpu_info_collector.h"
+#include <vector>
+
#include "base/logging.h"
+#include "base/mac/scoped_cftyperef.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_piece.h"
#include "base/sys_string_conversions.h"
@@ -19,6 +22,16 @@
namespace {
+struct VideoCardInfo {
+ UInt32 vendor_id;
+ UInt32 device_id;
+
+ VideoCardInfo(UInt32 vendor, UInt32 device) {
+ vendor_id = vendor;
+ device_id = device;
+ }
+};
+
CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort,
CFStringRef propertyName) {
return IORegistryEntrySearchCFProperty(dspPort,
@@ -40,6 +53,71 @@ UInt32 IntValueOfCFData(CFDataRef data_ref) {
return value;
}
+// 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(GPUInfo* gpu_info) {
+ DCHECK(gpu_info);
+
+ // match_dictionary will be consumed by IOServiceGetMatchingServices, no need
+ // to release it.
+ CFMutableDictionaryRef match_dictionary = IOServiceMatching("IOPCIDevice");
+ io_iterator_t entry_iterator;
+ 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));
+ }
+ IOObjectRelease(entry_iterator);
+
+ const UInt32 kIntelVendorId = 0x8086;
+ size_t found = video_card_list.size();
+ switch (video_card_list.size()) {
+ case 1:
+ found = 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;
+ break;
+ }
+ if (found < video_card_list.size()) {
+ gpu_info->vendor_id = video_card_list[found].vendor_id;
+ gpu_info->device_id = video_card_list[found].device_id;
+ return true;
+ }
+ return false;
+}
+
} // namespace anonymous
namespace gpu_info_collector {
@@ -57,7 +135,7 @@ bool CollectPreliminaryGraphicsInfo(GPUInfo* gpu_info) {
DCHECK(gpu_info);
bool rt = true;
- if (!CollectVideoCardInfo(gpu_info))
+ if (!CollectPCIVideoCardInfo(gpu_info) && !CollectVideoCardInfo(gpu_info))
rt = false;
return rt;