Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(189)

Side by Side Diff: content/gpu/gpu_info_collector_linux.cc

Issue 11343015: Linux: add option to link libpci directly instead of using dlopen. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/content_gpu.gypi ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « content/content_gpu.gypi ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698