summaryrefslogtreecommitdiffstats
path: root/content/gpu
diff options
context:
space:
mode:
authorzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-10 23:02:42 +0000
committerzmo@chromium.org <zmo@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-10 23:02:42 +0000
commita094e2cb67f9c134163a4418315d8d245e406fbe (patch)
tree47f0ee5de8d8216bcb12c2dbd5c65569b13fe200 /content/gpu
parente9165b203749b1b3b37a93d3e640781384191cb9 (diff)
downloadchromium_src-a094e2cb67f9c134163a4418315d8d245e406fbe.zip
chromium_src-a094e2cb67f9c134163a4418315d8d245e406fbe.tar.gz
chromium_src-a094e2cb67f9c134163a4418315d8d245e406fbe.tar.bz2
Change GPUInfo to handle multiple GPUs.
At the moment we always select one GPU as primary and the others as secondary. In preliminary GPU info collection (without creating a GL context and collect GL VENDOR/RENDERER strings), we actually don't know which GPU is in use. The current logic is that if one GPU is Intel, we assume the other is primary. I agree a better logic is needed. However, at the moment, logging/crash reports all requires ONE GPU vendor_id/device_id, so even though we don't know which GPU is active, we still need to randomly select one. This needs more thinking and design, so I think it's reasonable to leave it to a possible future CL. Also, the logic on collecting GPU info through libpci is changed to collect multiple GPUs. If one is Intel and one is NVIDIA, we assume it's optimus and we disable GPU features. This logic is hardwired in Chrome in this CL. The plan is to push the logic to blacklist, but I'll leave it to a seperate CL. BUG=126307,75220 TEST=about:gpu page on a Linux system with optimus GPU R=kbr TBR=jam Review URL: https://chromiumcodereview.appspot.com/10389051 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136429 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/gpu')
-rw-r--r--content/gpu/gpu_info_collector_linux.cc112
-rw-r--r--content/gpu/gpu_info_collector_mac.mm10
-rw-r--r--content/gpu/gpu_info_collector_unittest.cc6
-rw-r--r--content/gpu/gpu_info_collector_win.cc4
-rw-r--r--content/gpu/gpu_main.cc2
5 files changed, 72 insertions, 62 deletions
diff --git a/content/gpu/gpu_info_collector_linux.cc b/content/gpu/gpu_info_collector_linux.cc
index 330f299..0fc224b 100644
--- a/content/gpu/gpu_info_collector_linux.cc
+++ b/content/gpu/gpu_info_collector_linux.cc
@@ -164,6 +164,10 @@ std::string CollectDriverVersionATI() {
return "";
}
+const uint32 kVendorIDIntel = 0x8086;
+const uint32 kVendorIDNVidia = 0x10de;
+const uint32 kVendorIDAMD = 0x1002;
+
} // namespace anonymous
namespace gpu_info_collector {
@@ -192,7 +196,7 @@ bool CollectPreliminaryGraphicsInfo(content::GPUInfo* gpu_info) {
bool rt = CollectVideoCardInfo(gpu_info);
- if (gpu_info->vendor_id == 0x1002) { // ATI
+ if (gpu_info->gpu.vendor_id == kVendorIDAMD) {
std::string ati_driver_version = CollectDriverVersionATI();
if (!ati_driver_version.empty()) {
gpu_info->driver_vendor = "ATI / AMD";
@@ -200,6 +204,12 @@ bool CollectPreliminaryGraphicsInfo(content::GPUInfo* gpu_info) {
}
}
+ // Disable all GPU features for Optimus on Linux.
+ if (gpu_info->optimus) {
+ gpu_info->gpu_accessible = false;
+ gpu_info->finalized = true;
+ }
+
return rt;
}
@@ -224,49 +234,36 @@ bool CollectVideoCardInfo(content::GPUInfo* gpu_info) {
DCHECK(access != NULL);
(interface->pci_init)(access);
(interface->pci_scan_bus)(access);
- std::vector<PciDevice*> gpu_list;
- PciDevice* gpu_active = NULL;
+ bool primary_gpu_identified = false;
for (PciDevice* device = access->device_list;
device != NULL; device = device->next) {
(interface->pci_fill_info)(device, 33); // Fill the IDs and class fields.
// TODO(zmo): there might be other classes that qualify as display devices.
- if (device->device_class == 0x0300) { // Device class is DISPLAY_VGA.
- if (gpu_info->vendor_id == 0 || gpu_info->vendor_id == device->vendor_id)
- gpu_list.push_back(device);
- }
- }
- if (gpu_list.size() == 1) {
- gpu_active = gpu_list[0];
- } else {
- // If more than one graphics card are identified, find the one that matches
- // gl VENDOR and RENDERER info.
- std::string gl_vendor_string = gpu_info->gl_vendor;
- std::string gl_renderer_string = gpu_info->gl_renderer;
+ if (device->device_class != 0x0300) // Device class is DISPLAY_VGA.
+ continue;
+
+ content::GPUInfo::GPUDevice gpu;
+ gpu.vendor_id = device->vendor_id;
+ gpu.device_id = device->device_id;
+
const int buffer_size = 255;
scoped_array<char> buffer(new char[buffer_size]);
- std::vector<PciDevice*> candidates;
- for (size_t i = 0; i < gpu_list.size(); ++i) {
- PciDevice* gpu = gpu_list[i];
- // The current implementation of pci_lookup_name returns the same pointer
- // as the passed in upon success, and a different one (NULL or a pointer
- // to an error message) upon failure.
- if ((interface->pci_lookup_name)(access,
- buffer.get(),
- buffer_size,
- 1,
- gpu->vendor_id) != buffer.get())
- continue;
- std::string vendor_string = buffer.get();
- const bool kCaseSensitive = false;
- if (!StartsWithASCII(gl_vendor_string, vendor_string, kCaseSensitive))
- continue;
- if ((interface->pci_lookup_name)(access,
- buffer.get(),
- buffer_size,
- 2,
- gpu->vendor_id,
- gpu->device_id) != buffer.get())
- continue;
+ // The current implementation of pci_lookup_name returns the same pointer
+ // as the passed in upon success, and a different one (NULL or a pointer
+ // to an error message) upon failure.
+ if ((interface->pci_lookup_name)(access,
+ buffer.get(),
+ buffer_size,
+ 1,
+ device->vendor_id) == buffer.get()) {
+ gpu.vendor_string = buffer.get();
+ }
+ if ((interface->pci_lookup_name)(access,
+ buffer.get(),
+ buffer_size,
+ 2,
+ device->vendor_id,
+ device->device_id) == buffer.get()) {
std::string device_string = buffer.get();
size_t begin = device_string.find_first_of('[');
size_t end = device_string.find_last_of(']');
@@ -274,25 +271,38 @@ bool CollectVideoCardInfo(content::GPUInfo* gpu_info) {
begin < end) {
device_string = device_string.substr(begin + 1, end - begin - 1);
}
- if (StartsWithASCII(gl_renderer_string, device_string, kCaseSensitive)) {
- gpu_active = gpu;
- break;
+ gpu.device_string = device_string;
+ }
+
+ if (!primary_gpu_identified) {
+ primary_gpu_identified = true;
+ gpu_info->gpu = gpu;
+ } else {
+ // TODO(zmo): if there are multiple GPUs, we assume the non Intel
+ // one is primary. Revisit this logic because we actually don't know
+ // which GPU we are using at this point.
+ if (gpu_info->gpu.vendor_id == kVendorIDIntel &&
+ gpu.vendor_id != kVendorIDIntel) {
+ gpu_info->secondary_gpus.push_back(gpu_info->gpu);
+ gpu_info->gpu = gpu;
+ } else {
+ gpu_info->secondary_gpus.push_back(gpu);
}
- // If a device's vendor matches gl VENDOR string, we want to consider the
- // possibility that libpci may not return the exact same name as gl
- // RENDERER string.
- candidates.push_back(gpu);
}
- if (gpu_active == NULL && candidates.size() == 1)
- gpu_active = candidates[0];
}
- if (gpu_active != NULL) {
- gpu_info->vendor_id = gpu_active->vendor_id;
- gpu_info->device_id = gpu_active->device_id;
+
+ // Detect Optimus or AMD Switchable GPU.
+ if (gpu_info->secondary_gpus.size() == 1 &&
+ gpu_info->secondary_gpus[0].vendor_id == kVendorIDIntel) {
+ if (gpu_info->gpu.vendor_id == kVendorIDNVidia)
+ gpu_info->optimus = true;
+ if (gpu_info->gpu.vendor_id == kVendorIDAMD)
+ gpu_info->amd_switchable = true;
}
+
(interface->pci_cleanup)(access);
FinalizeLibPci(&interface);
- return (gpu_active != NULL);
+ return (primary_gpu_identified);
}
bool CollectDriverInfoGL(content::GPUInfo* gpu_info) {
diff --git a/content/gpu/gpu_info_collector_mac.mm b/content/gpu/gpu_info_collector_mac.mm
index ace83a4..bf284f6 100644
--- a/content/gpu/gpu_info_collector_mac.mm
+++ b/content/gpu/gpu_info_collector_mac.mm
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -111,8 +111,8 @@ bool CollectPCIVideoCardInfo(content::GPUInfo* gpu_info) {
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;
+ 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;
@@ -157,8 +157,8 @@ bool CollectVideoCardInfo(content::GPUInfo* gpu_info) {
CFRelease(device_id_ref);
}
- gpu_info->vendor_id = vendor_id;
- gpu_info->device_id = device_id;
+ gpu_info->gpu.vendor_id = vendor_id;
+ gpu_info->gpu.device_id = device_id;
return true;
}
diff --git a/content/gpu/gpu_info_collector_unittest.cc b/content/gpu/gpu_info_collector_unittest.cc
index eaca0f2..0d2b710 100644
--- a/content/gpu/gpu_info_collector_unittest.cc
+++ b/content/gpu/gpu_info_collector_unittest.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -68,8 +68,8 @@ class GPUInfoCollectorTest : public testing::Test {
"GL_OES_packed_depth_stencil GL_EXT_texture_format_BGRA8888 "
"GL_EXT_read_format_bgra";
#endif
- test_values_.vendor_id = vendor_id;
- test_values_.device_id = device_id;
+ test_values_.gpu.vendor_id = vendor_id;
+ test_values_.gpu.device_id = device_id;
test_values_.driver_vendor = driver_vendor;
test_values_.driver_version =driver_version;
test_values_.pixel_shader_version = shader_version;
diff --git a/content/gpu/gpu_info_collector_win.cc b/content/gpu/gpu_info_collector_win.cc
index 1533a48..2ea0915 100644
--- a/content/gpu/gpu_info_collector_win.cc
+++ b/content/gpu/gpu_info_collector_win.cc
@@ -219,8 +219,8 @@ bool CollectVideoCardInfo(content::GPUInfo* gpu_info) {
std::wstring device_id_string = id.substr(17, 4);
base::HexStringToInt(WideToASCII(vendor_id_string), &vendor_id);
base::HexStringToInt(WideToASCII(device_id_string), &device_id);
- gpu_info->vendor_id = vendor_id;
- gpu_info->device_id = device_id;
+ gpu_info->gpu.vendor_id = vendor_id;
+ gpu_info->gpu.device_id = device_id;
// TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
return CollectDriverInfoD3D(id, gpu_info);
}
diff --git a/content/gpu/gpu_main.cc b/content/gpu/gpu_main.cc
index da3a589..2694e76 100644
--- a/content/gpu/gpu_main.cc
+++ b/content/gpu/gpu_main.cc
@@ -81,7 +81,7 @@ int GpuMain(const content::MainFunctionParams& parameters) {
}
#if defined(OS_LINUX)
- if (gpu_info.vendor_id == 0x10de && // NVIDIA
+ if (gpu_info.gpu.vendor_id == 0x10de && // NVIDIA
gpu_info.driver_vendor == "NVIDIA") {
base::ThreadRestrictions::AssertIOAllowed();
if (access("/dev/nvidiactl", R_OK) != 0) {