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> | |
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; |
Zhenyao Mo
2012/10/29 21:39:08
Nit: this can be outside the #if branches.
Paweł Hajdan Jr.
2012/10/29 23:06:44
Done. Note I used scoped_ptr to avoid leaks.
| |
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>( |
113 dlsym(handle, "pci_init")); | 82 dlsym(handle, "pci_init")); |
114 interface->pci_cleanup = reinterpret_cast<FT_pci_cleanup>( | 83 interface->pci_cleanup = reinterpret_cast<FT_pci_cleanup>( |
115 dlsym(handle, "pci_cleanup")); | 84 dlsym(handle, "pci_cleanup")); |
116 interface->pci_scan_bus = reinterpret_cast<FT_pci_scan_bus>( | 85 interface->pci_scan_bus = reinterpret_cast<FT_pci_scan_bus>( |
117 dlsym(handle, "pci_scan_bus")); | 86 dlsym(handle, "pci_scan_bus")); |
118 interface->pci_fill_info = reinterpret_cast<FT_pci_fill_info>( | 87 interface->pci_fill_info = reinterpret_cast<FT_pci_fill_info>( |
119 dlsym(handle, "pci_fill_info")); | 88 dlsym(handle, "pci_fill_info")); |
120 interface->pci_lookup_name = reinterpret_cast<FT_pci_lookup_name>( | 89 interface->pci_lookup_name = reinterpret_cast<FT_pci_lookup_name>( |
121 dlsym(handle, "pci_lookup_name")); | 90 dlsym(handle, "pci_lookup_name")); |
122 if (interface->pci_alloc == NULL || | 91 if (interface->pci_alloc == NULL || |
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 = &pci_alloc; | |
106 interface->pci_init = &pci_init; | |
107 interface->pci_cleanup = &pci_cleanup; | |
108 interface->pci_scan_bus = &pci_scan_bus; | |
109 interface->pci_fill_info = &pci_fill_info; | |
110 interface->pci_lookup_name = &pci_lookup_name; | |
111 #endif // !defined(DLOPEN_LIBPCI) | |
133 return interface; | 112 return interface; |
134 } | 113 } |
135 | 114 |
136 // This close the dynamically opened libpci and delete the interface. | 115 // This close the dynamically opened libpci and delete the interface. |
137 void FinalizeLibPci(PciInterface** interface) { | 116 void FinalizeLibPci(PciInterface** interface) { |
117 #if defined(DLOPEN_LIBPCI) | |
138 DCHECK(interface && *interface && (*interface)->lib_handle); | 118 DCHECK(interface && *interface && (*interface)->lib_handle); |
139 dlclose((*interface)->lib_handle); | 119 dlclose((*interface)->lib_handle); |
120 #endif // defined(DLOPEN_LIBPCI) | |
140 delete (*interface); | 121 delete (*interface); |
141 *interface = NULL; | 122 *interface = NULL; |
142 } | 123 } |
143 | 124 |
144 // Scan /etc/ati/amdpcsdb.default for "ReleaseVersion". | 125 // Scan /etc/ati/amdpcsdb.default for "ReleaseVersion". |
145 // Return empty string on failing. | 126 // Return empty string on failing. |
146 std::string CollectDriverVersionATI() { | 127 std::string CollectDriverVersionATI() { |
147 const FilePath::CharType kATIFileName[] = | 128 const FilePath::CharType kATIFileName[] = |
148 FILE_PATH_LITERAL("/etc/ati/amdpcsdb.default"); | 129 FILE_PATH_LITERAL("/etc/ati/amdpcsdb.default"); |
149 FilePath ati_file_path(kATIFileName); | 130 FilePath ati_file_path(kATIFileName); |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
274 | 255 |
275 // TODO(zmo): be more flexible about library name. | 256 // TODO(zmo): be more flexible about library name. |
276 PciInterface* interface = InitializeLibPci("libpci.so.3"); | 257 PciInterface* interface = InitializeLibPci("libpci.so.3"); |
277 if (interface == NULL) | 258 if (interface == NULL) |
278 interface = InitializeLibPci("libpci.so"); | 259 interface = InitializeLibPci("libpci.so"); |
279 if (interface == NULL) { | 260 if (interface == NULL) { |
280 VLOG(1) << "Failed to locate libpci"; | 261 VLOG(1) << "Failed to locate libpci"; |
281 return false; | 262 return false; |
282 } | 263 } |
283 | 264 |
284 PciAccess* access = (interface->pci_alloc)(); | 265 pci_access* access = (interface->pci_alloc)(); |
285 DCHECK(access != NULL); | 266 DCHECK(access != NULL); |
286 (interface->pci_init)(access); | 267 (interface->pci_init)(access); |
287 (interface->pci_scan_bus)(access); | 268 (interface->pci_scan_bus)(access); |
288 bool primary_gpu_identified = false; | 269 bool primary_gpu_identified = false; |
289 for (PciDevice* device = access->device_list; | 270 for (pci_dev* device = access->devices; |
290 device != NULL; device = device->next) { | 271 device != NULL; device = device->next) { |
291 (interface->pci_fill_info)(device, 33); // Fill the IDs and class fields. | 272 (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. | 273 // TODO(zmo): there might be other classes that qualify as display devices. |
293 if (device->device_class != 0x0300) // Device class is DISPLAY_VGA. | 274 if (device->device_class != 0x0300) // Device class is DISPLAY_VGA. |
294 continue; | 275 continue; |
295 | 276 |
296 content::GPUInfo::GPUDevice gpu; | 277 content::GPUInfo::GPUDevice gpu; |
297 gpu.vendor_id = device->vendor_id; | 278 gpu.vendor_id = device->vendor_id; |
298 gpu.device_id = device->device_id; | 279 gpu.device_id = device->device_id; |
299 | 280 |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
375 return false; | 356 return false; |
376 if (pos != std::string::npos) | 357 if (pos != std::string::npos) |
377 driver_version = driver_version.substr(0, pos); | 358 driver_version = driver_version.substr(0, pos); |
378 | 359 |
379 gpu_info->driver_vendor = pieces[1]; | 360 gpu_info->driver_vendor = pieces[1]; |
380 gpu_info->driver_version = driver_version; | 361 gpu_info->driver_version = driver_version; |
381 return true; | 362 return true; |
382 } | 363 } |
383 | 364 |
384 } // namespace gpu_info_collector | 365 } // namespace gpu_info_collector |
OLD | NEW |