Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/gpu/gpu_info_collector.h" | 5 #include "content/gpu/gpu_info_collector.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <X11/Xlib.h> | 8 #include <X11/Xlib.h> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| 11 // TODO(phajdan.jr): Report problem upstream and make pci.h handle this. | |
| 12 extern "C" { | |
| 13 #include <pci/pci.h> | |
|
piman
2012/10/29 17:24:24
This won't work correctly if you didn't have the p
| |
| 14 } | |
| 15 | |
| 11 #include "base/command_line.h" | 16 #include "base/command_line.h" |
| 12 #include "base/debug/trace_event.h" | 17 #include "base/debug/trace_event.h" |
| 13 #include "base/file_util.h" | 18 #include "base/file_util.h" |
| 14 #include "base/logging.h" | 19 #include "base/logging.h" |
| 15 #include "base/memory/scoped_ptr.h" | 20 #include "base/memory/scoped_ptr.h" |
| 16 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
| 17 #include "base/string_piece.h" | 22 #include "base/string_piece.h" |
| 18 #include "base/string_split.h" | 23 #include "base/string_split.h" |
| 19 #include "base/string_tokenizer.h" | 24 #include "base/string_tokenizer.h" |
| 20 #include "base/string_util.h" | 25 #include "base/string_util.h" |
| 21 #include "third_party/libXNVCtrl/NVCtrl.h" | 26 #include "third_party/libXNVCtrl/NVCtrl.h" |
| 22 #include "third_party/libXNVCtrl/NVCtrlLib.h" | 27 #include "third_party/libXNVCtrl/NVCtrlLib.h" |
| 23 #include "ui/gl/gl_bindings.h" | 28 #include "ui/gl/gl_bindings.h" |
| 24 #include "ui/gl/gl_context.h" | 29 #include "ui/gl/gl_context.h" |
| 25 #include "ui/gl/gl_implementation.h" | 30 #include "ui/gl/gl_implementation.h" |
| 26 #include "ui/gl/gl_surface.h" | 31 #include "ui/gl/gl_surface.h" |
| 27 #include "ui/gl/gl_switches.h" | 32 #include "ui/gl/gl_switches.h" |
| 28 | 33 |
| 29 namespace { | 34 namespace { |
| 30 | 35 |
| 31 // PciDevice and PciAccess are defined to access libpci functions. Their | |
| 32 // members match the corresponding structures defined by libpci in size up to | |
| 33 // fields we may access. For those members we don't use, their names are | |
| 34 // defined as "fieldX", etc., or, left out if they are declared after the | |
| 35 // members we care about in libpci. | |
| 36 | |
| 37 struct PciDevice { | |
| 38 PciDevice* next; | |
| 39 | |
| 40 uint16 field0; | |
| 41 uint8 field1; | |
| 42 uint8 field2; | |
| 43 uint8 field3; | |
| 44 int field4; | |
| 45 | |
| 46 uint16 vendor_id; | |
| 47 uint16 device_id; | |
| 48 uint16 device_class; | |
| 49 }; | |
| 50 | |
| 51 struct PciAccess { | |
| 52 unsigned int field0; | |
| 53 int field1; | |
| 54 int field2; | |
| 55 char* field3; | |
| 56 int field4; | |
| 57 int field5; | |
| 58 unsigned int field6; | |
| 59 int field7; | |
| 60 | |
| 61 void (*function0)(); | |
| 62 void (*function1)(); | |
| 63 void (*function2)(); | |
| 64 | |
| 65 PciDevice* device_list; | |
| 66 }; | |
| 67 | |
| 68 // Define function types. | 36 // Define function types. |
| 69 typedef PciAccess* (*FT_pci_alloc)(); | 37 typedef pci_access* (*FT_pci_alloc)(); |
| 70 typedef void (*FT_pci_init)(PciAccess*); | 38 typedef void (*FT_pci_init)(pci_access*); |
| 71 typedef void (*FT_pci_cleanup)(PciAccess*); | 39 typedef void (*FT_pci_cleanup)(pci_access*); |
| 72 typedef void (*FT_pci_scan_bus)(PciAccess*); | 40 typedef void (*FT_pci_scan_bus)(pci_access*); |
| 73 typedef void (*FT_pci_scan_bus)(PciAccess*); | 41 typedef void (*FT_pci_scan_bus)(pci_access*); |
| 74 typedef int (*FT_pci_fill_info)(PciDevice*, int); | 42 typedef int (*FT_pci_fill_info)(pci_dev*, int); |
| 75 typedef char* (*FT_pci_lookup_name)(PciAccess*, char*, int, int, ...); | 43 typedef char* (*FT_pci_lookup_name)(pci_access*, char*, int, int, ...); |
| 76 | 44 |
| 77 // This includes dynamically linked library handle and functions pointers from | 45 // This includes dynamically linked library handle and functions pointers from |
| 78 // libpci. | 46 // libpci. |
| 79 struct PciInterface { | 47 struct PciInterface { |
| 80 void* lib_handle; | 48 void* lib_handle; |
| 81 | 49 |
| 82 FT_pci_alloc pci_alloc; | 50 FT_pci_alloc pci_alloc; |
| 83 FT_pci_init pci_init; | 51 FT_pci_init pci_init; |
| 84 FT_pci_cleanup pci_cleanup; | 52 FT_pci_cleanup pci_cleanup; |
| 85 FT_pci_scan_bus pci_scan_bus; | 53 FT_pci_scan_bus pci_scan_bus; |
| 86 FT_pci_fill_info pci_fill_info; | 54 FT_pci_fill_info pci_fill_info; |
| 87 FT_pci_lookup_name pci_lookup_name; | 55 FT_pci_lookup_name pci_lookup_name; |
| 88 }; | 56 }; |
| 89 | 57 |
| 90 // This checks if a system supports PCI bus. | 58 // This checks if a system supports PCI bus. |
| 91 // We check the existence of /sys/bus/pci or /sys/bug/pci_express. | 59 // We check the existence of /sys/bus/pci or /sys/bug/pci_express. |
| 92 bool IsPciSupported() { | 60 bool IsPciSupported() { |
| 93 const FilePath pci_path("/sys/bus/pci/"); | 61 const FilePath pci_path("/sys/bus/pci/"); |
| 94 const FilePath pcie_path("/sys/bus/pci_express/"); | 62 const FilePath pcie_path("/sys/bus/pci_express/"); |
| 95 return (file_util::PathExists(pci_path) || | 63 return (file_util::PathExists(pci_path) || |
| 96 file_util::PathExists(pcie_path)); | 64 file_util::PathExists(pcie_path)); |
| 97 } | 65 } |
| 98 | 66 |
| 99 // This dynamically opens libpci and get function pointers we need. Return | 67 // This dynamically opens libpci and get function pointers we need. Return |
| 100 // NULL if library fails to open or any functions can not be located. | 68 // NULL if library fails to open or any functions can not be located. |
| 101 // Returned interface (if not NULL) should be deleted in FinalizeLibPci. | 69 // Returned interface (if not NULL) should be deleted in FinalizeLibPci. |
| 102 PciInterface* InitializeLibPci(const char* lib_name) { | 70 PciInterface* InitializeLibPci(const char* lib_name) { |
| 71 #if defined(DLOPEN_LIBPCI) | |
| 103 void* handle = dlopen(lib_name, RTLD_LAZY); | 72 void* handle = dlopen(lib_name, RTLD_LAZY); |
| 104 if (handle == NULL) { | 73 if (handle == NULL) { |
| 105 VLOG(1) << "Failed to dlopen " << lib_name; | 74 VLOG(1) << "Failed to dlopen " << lib_name; |
| 106 return NULL; | 75 return NULL; |
| 107 } | 76 } |
| 108 PciInterface* interface = new struct PciInterface; | 77 PciInterface* interface = new struct PciInterface; |
| 109 interface->lib_handle = handle; | 78 interface->lib_handle = handle; |
| 110 interface->pci_alloc = reinterpret_cast<FT_pci_alloc>( | 79 interface->pci_alloc = reinterpret_cast<FT_pci_alloc>( |
| 111 dlsym(handle, "pci_alloc")); | 80 dlsym(handle, "pci_alloc")); |
| 112 interface->pci_init = reinterpret_cast<FT_pci_init>( | 81 interface->pci_init = reinterpret_cast<FT_pci_init>( |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 123 interface->pci_init == NULL || | 92 interface->pci_init == NULL || |
| 124 interface->pci_cleanup == NULL || | 93 interface->pci_cleanup == NULL || |
| 125 interface->pci_scan_bus == NULL || | 94 interface->pci_scan_bus == NULL || |
| 126 interface->pci_fill_info == NULL || | 95 interface->pci_fill_info == NULL || |
| 127 interface->pci_lookup_name == NULL) { | 96 interface->pci_lookup_name == NULL) { |
| 128 VLOG(1) << "Missing required function(s) from " << lib_name; | 97 VLOG(1) << "Missing required function(s) from " << lib_name; |
| 129 dlclose(handle); | 98 dlclose(handle); |
| 130 delete interface; | 99 delete interface; |
| 131 return NULL; | 100 return NULL; |
| 132 } | 101 } |
| 102 #else // !defined(DLOPEN_LIBPCI) | |
| 103 PciInterface* interface = new struct PciInterface; | |
| 104 interface->lib_handle = NULL; | |
| 105 interface->pci_alloc = reinterpret_cast<FT_pci_alloc>( | |
|
piman
2012/10/29 17:24:24
Why do we need reinterpret_cast here?
| |
| 106 &pci_alloc); | |
| 107 interface->pci_init = reinterpret_cast<FT_pci_init>( | |
| 108 &pci_init); | |
| 109 interface->pci_cleanup = reinterpret_cast<FT_pci_cleanup>( | |
| 110 &pci_cleanup); | |
| 111 interface->pci_scan_bus = reinterpret_cast<FT_pci_scan_bus>( | |
| 112 &pci_scan_bus); | |
| 113 interface->pci_fill_info = reinterpret_cast<FT_pci_fill_info>( | |
| 114 &pci_fill_info); | |
| 115 interface->pci_lookup_name = reinterpret_cast<FT_pci_lookup_name>( | |
| 116 &pci_lookup_name); | |
| 117 #endif // !defined(DLOPEN_LIBPCI) | |
| 133 return interface; | 118 return interface; |
| 134 } | 119 } |
| 135 | 120 |
| 136 // This close the dynamically opened libpci and delete the interface. | 121 // This close the dynamically opened libpci and delete the interface. |
| 137 void FinalizeLibPci(PciInterface** interface) { | 122 void FinalizeLibPci(PciInterface** interface) { |
| 123 #if defined(DLOPEN_LIBPCI) | |
| 138 DCHECK(interface && *interface && (*interface)->lib_handle); | 124 DCHECK(interface && *interface && (*interface)->lib_handle); |
| 139 dlclose((*interface)->lib_handle); | 125 dlclose((*interface)->lib_handle); |
| 126 #endif // defined(DLOPEN_LIBPCI) | |
| 140 delete (*interface); | 127 delete (*interface); |
| 141 *interface = NULL; | 128 *interface = NULL; |
| 142 } | 129 } |
| 143 | 130 |
| 144 // Scan /etc/ati/amdpcsdb.default for "ReleaseVersion". | 131 // Scan /etc/ati/amdpcsdb.default for "ReleaseVersion". |
| 145 // Return empty string on failing. | 132 // Return empty string on failing. |
| 146 std::string CollectDriverVersionATI() { | 133 std::string CollectDriverVersionATI() { |
| 147 const FilePath::CharType kATIFileName[] = | 134 const FilePath::CharType kATIFileName[] = |
| 148 FILE_PATH_LITERAL("/etc/ati/amdpcsdb.default"); | 135 FILE_PATH_LITERAL("/etc/ati/amdpcsdb.default"); |
| 149 FilePath ati_file_path(kATIFileName); | 136 FilePath ati_file_path(kATIFileName); |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 274 | 261 |
| 275 // TODO(zmo): be more flexible about library name. | 262 // TODO(zmo): be more flexible about library name. |
| 276 PciInterface* interface = InitializeLibPci("libpci.so.3"); | 263 PciInterface* interface = InitializeLibPci("libpci.so.3"); |
| 277 if (interface == NULL) | 264 if (interface == NULL) |
| 278 interface = InitializeLibPci("libpci.so"); | 265 interface = InitializeLibPci("libpci.so"); |
| 279 if (interface == NULL) { | 266 if (interface == NULL) { |
| 280 VLOG(1) << "Failed to locate libpci"; | 267 VLOG(1) << "Failed to locate libpci"; |
| 281 return false; | 268 return false; |
| 282 } | 269 } |
| 283 | 270 |
| 284 PciAccess* access = (interface->pci_alloc)(); | 271 pci_access* access = (interface->pci_alloc)(); |
| 285 DCHECK(access != NULL); | 272 DCHECK(access != NULL); |
| 286 (interface->pci_init)(access); | 273 (interface->pci_init)(access); |
| 287 (interface->pci_scan_bus)(access); | 274 (interface->pci_scan_bus)(access); |
| 288 bool primary_gpu_identified = false; | 275 bool primary_gpu_identified = false; |
| 289 for (PciDevice* device = access->device_list; | 276 for (pci_dev* device = access->devices; |
| 290 device != NULL; device = device->next) { | 277 device != NULL; device = device->next) { |
| 291 (interface->pci_fill_info)(device, 33); // Fill the IDs and class fields. | 278 (interface->pci_fill_info)(device, 33); // Fill the IDs and class fields. |
| 292 // TODO(zmo): there might be other classes that qualify as display devices. | 279 // TODO(zmo): there might be other classes that qualify as display devices. |
| 293 if (device->device_class != 0x0300) // Device class is DISPLAY_VGA. | 280 if (device->device_class != 0x0300) // Device class is DISPLAY_VGA. |
| 294 continue; | 281 continue; |
| 295 | 282 |
| 296 content::GPUInfo::GPUDevice gpu; | 283 content::GPUInfo::GPUDevice gpu; |
| 297 gpu.vendor_id = device->vendor_id; | 284 gpu.vendor_id = device->vendor_id; |
| 298 gpu.device_id = device->device_id; | 285 gpu.device_id = device->device_id; |
| 299 | 286 |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 375 return false; | 362 return false; |
| 376 if (pos != std::string::npos) | 363 if (pos != std::string::npos) |
| 377 driver_version = driver_version.substr(0, pos); | 364 driver_version = driver_version.substr(0, pos); |
| 378 | 365 |
| 379 gpu_info->driver_vendor = pieces[1]; | 366 gpu_info->driver_vendor = pieces[1]; |
| 380 gpu_info->driver_version = driver_version; | 367 gpu_info->driver_version = driver_version; |
| 381 return true; | 368 return true; |
| 382 } | 369 } |
| 383 | 370 |
| 384 } // namespace gpu_info_collector | 371 } // namespace gpu_info_collector |
| OLD | NEW |