summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authorzmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-20 00:46:46 +0000
committerzmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-20 00:46:46 +0000
commit511d63b8fec989b046c1a5f7c5216c3a166fcf74 (patch)
tree967d28c01d58e658fbc6d05f8a6906d9b7f73bd4 /content
parentc070108aaa0a5cce0bd0452ad197c9dab0ddac92 (diff)
downloadchromium_src-511d63b8fec989b046c1a5f7c5216c3a166fcf74.zip
chromium_src-511d63b8fec989b046c1a5f7c5216c3a166fcf74.tar.gz
chromium_src-511d63b8fec989b046c1a5f7c5216c3a166fcf74.tar.bz2
Collect GPU info on Mac through IO registry for dual GPU systems.
Go through IO Registry to locate PCI based video cards on Mac. If there are two video cards and one of them is Intel, we assume Intel GPU is the integrated one and the other is the discrete one. Chromium GPU process should always use the discrete one (if Mac is handling automatic card switching), and we identify the discrete card in preliminary GPU info collection so we could run through GPU software rendering list and set up the renderer process with approriate GPU feature capabilities. Note that if the IO registry method fails, we fallback to the original "GPU locating through current display" method, so this CL should be pretty safe. BUG=75208,75220 TEST=gpu acceleration is enabled on Mac with Intel/ATI dual GPU. Review URL: http://codereview.chromium.org/6879023 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82202 0039d316-1c4b-4281-b951-d872f2087c98
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;