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

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

Issue 6684015: Move chrome\gpu to content\gpu. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 9 months 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 | « chrome/gpu/gpu_info_collector.cc ('k') | chrome/gpu/gpu_info_collector_mac.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/gpu/gpu_info_collector.h"
6
7 #include <dlfcn.h>
8 #include <vector>
9
10 #include "app/gfx/gl/gl_bindings.h"
11 #include "app/gfx/gl/gl_context.h"
12 #include "app/gfx/gl/gl_implementation.h"
13 #include "base/file_util.h"
14 #include "base/logging.h"
15 #include "base/scoped_ptr.h"
16 #include "base/string_piece.h"
17 #include "base/string_split.h"
18 #include "base/string_util.h"
19
20 namespace {
21
22 // PciDevice and PciAccess are defined to access libpci functions. Their
23 // members match the corresponding structures defined by libpci in size up to
24 // fields we may access. For those members we don't use, their names are
25 // defined as "fieldX", etc., or, left out if they are declared after the
26 // members we care about in libpci.
27
28 struct PciDevice {
29 PciDevice* next;
30
31 uint16 field0;
32 uint8 field1;
33 uint8 field2;
34 uint8 field3;
35 int field4;
36
37 uint16 vendor_id;
38 uint16 device_id;
39 uint16 device_class;
40 };
41
42 struct PciAccess {
43 unsigned int field0;
44 int field1;
45 int field2;
46 char* field3;
47 int field4;
48 int field5;
49 unsigned int field6;
50 int field7;
51
52 void (*function0)();
53 void (*function1)();
54 void (*function2)();
55
56 PciDevice* device_list;
57 };
58
59 // Define function types.
60 typedef PciAccess* (*FT_pci_alloc)();
61 typedef void (*FT_pci_init)(PciAccess*);
62 typedef void (*FT_pci_cleanup)(PciAccess*);
63 typedef void (*FT_pci_scan_bus)(PciAccess*);
64 typedef void (*FT_pci_scan_bus)(PciAccess*);
65 typedef int (*FT_pci_fill_info)(PciDevice*, int);
66 typedef char* (*FT_pci_lookup_name)(PciAccess*, char*, int, int, ...);
67
68 // This includes dynamically linked library handle and functions pointers from
69 // libpci.
70 struct PciInterface {
71 void* lib_handle;
72
73 FT_pci_alloc pci_alloc;
74 FT_pci_init pci_init;
75 FT_pci_cleanup pci_cleanup;
76 FT_pci_scan_bus pci_scan_bus;
77 FT_pci_fill_info pci_fill_info;
78 FT_pci_lookup_name pci_lookup_name;
79 };
80
81 // This checks if a system supports PCI bus.
82 // We check the existence of /sys/bus/pci or /sys/bug/pci_express.
83 bool IsPciSupported() {
84 const FilePath pci_path("/sys/bus/pci/");
85 const FilePath pcie_path("/sys/bus/pci_express/");
86 return (file_util::PathExists(pci_path) ||
87 file_util::PathExists(pcie_path));
88 }
89
90 // This dynamically opens libpci and get function pointers we need. Return
91 // NULL if library fails to open or any functions can not be located.
92 // Returned interface (if not NULL) should be deleted in FinalizeLibPci.
93 PciInterface* InitializeLibPci(const char* lib_name) {
94 void* handle = dlopen(lib_name, RTLD_LAZY);
95 if (handle == NULL) {
96 LOG(INFO) << "Failed to dlopen " << lib_name;
97 return NULL;
98 }
99 PciInterface* interface = new struct PciInterface;
100 interface->lib_handle = handle;
101 interface->pci_alloc = reinterpret_cast<FT_pci_alloc>(
102 dlsym(handle, "pci_alloc"));
103 interface->pci_init = reinterpret_cast<FT_pci_init>(
104 dlsym(handle, "pci_init"));
105 interface->pci_cleanup = reinterpret_cast<FT_pci_cleanup>(
106 dlsym(handle, "pci_cleanup"));
107 interface->pci_scan_bus = reinterpret_cast<FT_pci_scan_bus>(
108 dlsym(handle, "pci_scan_bus"));
109 interface->pci_fill_info = reinterpret_cast<FT_pci_fill_info>(
110 dlsym(handle, "pci_fill_info"));
111 interface->pci_lookup_name = reinterpret_cast<FT_pci_lookup_name>(
112 dlsym(handle, "pci_lookup_name"));
113 if (interface->pci_alloc == NULL ||
114 interface->pci_init == NULL ||
115 interface->pci_cleanup == NULL ||
116 interface->pci_scan_bus == NULL ||
117 interface->pci_fill_info == NULL ||
118 interface->pci_lookup_name == NULL) {
119 LOG(ERROR) << "Missing required function(s) from " << lib_name;
120 dlclose(handle);
121 delete interface;
122 return NULL;
123 }
124 return interface;
125 }
126
127 // This close the dynamically opened libpci and delete the interface.
128 void FinalizeLibPci(PciInterface** interface) {
129 DCHECK(interface && *interface && (*interface)->lib_handle);
130 dlclose((*interface)->lib_handle);
131 delete (*interface);
132 *interface = NULL;
133 }
134
135 } // namespace anonymous
136
137 namespace gpu_info_collector {
138
139 bool CollectGraphicsInfo(GPUInfo* gpu_info) {
140 DCHECK(gpu_info);
141
142 // TODO(zmo): need to consider the case where we are running on top of
143 // desktop GL and GL_ARB_robustness extension is available.
144 gpu_info->can_lose_context =
145 (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2);
146 gpu_info->level = GPUInfo::kComplete;
147 return CollectGraphicsInfoGL(gpu_info);
148 }
149
150 bool CollectPreliminaryGraphicsInfo(GPUInfo* gpu_info) {
151 DCHECK(gpu_info);
152
153 gpu_info->level = GPUInfo::kPartial;
154
155 bool rt = true;
156 if (!CollectVideoCardInfo(gpu_info))
157 rt = false;
158
159 // TODO(zmo): if vendor is ATI, consider passing /etc/ati/amdpcsdb.default
160 // for driver information.
161
162 return rt;
163 }
164
165 bool CollectVideoCardInfo(GPUInfo* gpu_info) {
166 DCHECK(gpu_info);
167
168 if (IsPciSupported() == false) {
169 LOG(INFO) << "PCI bus scanning is not supported";
170 return false;
171 }
172
173 // TODO(zmo): be more flexible about library name.
174 PciInterface* interface = InitializeLibPci("libpci.so.3");
175 if (interface == NULL)
176 interface = InitializeLibPci("libpci.so");
177 if (interface == NULL) {
178 LOG(ERROR) << "Failed to locate libpci";
179 return false;
180 }
181
182 PciAccess* access = (interface->pci_alloc)();
183 DCHECK(access != NULL);
184 (interface->pci_init)(access);
185 (interface->pci_scan_bus)(access);
186 std::vector<PciDevice*> gpu_list;
187 PciDevice* gpu_active = NULL;
188 for (PciDevice* device = access->device_list;
189 device != NULL; device = device->next) {
190 (interface->pci_fill_info)(device, 33); // Fill the IDs and class fields.
191 // TODO(zmo): there might be other classes that qualify as display devices.
192 if (device->device_class == 0x0300) { // Device class is DISPLAY_VGA.
193 gpu_list.push_back(device);
194 }
195 }
196 if (gpu_list.size() == 1) {
197 gpu_active = gpu_list[0];
198 } else {
199 // If more than one graphics card are identified, find the one that matches
200 // gl VENDOR and RENDERER info.
201 std::string gl_vendor_string = gpu_info->gl_vendor;
202 std::string gl_renderer_string = gpu_info->gl_renderer;
203 const int buffer_size = 255;
204 scoped_array<char> buffer(new char[buffer_size]);
205 std::vector<PciDevice*> candidates;
206 for (size_t i = 0; i < gpu_list.size(); ++i) {
207 PciDevice* gpu = gpu_list[i];
208 // The current implementation of pci_lookup_name returns the same pointer
209 // as the passed in upon success, and a different one (NULL or a pointer
210 // to an error message) upon failure.
211 if ((interface->pci_lookup_name)(access,
212 buffer.get(),
213 buffer_size,
214 1,
215 gpu->vendor_id) != buffer.get())
216 continue;
217 std::string vendor_string = buffer.get();
218 const bool kCaseSensitive = false;
219 if (!StartsWithASCII(gl_vendor_string, vendor_string, kCaseSensitive))
220 continue;
221 if ((interface->pci_lookup_name)(access,
222 buffer.get(),
223 buffer_size,
224 2,
225 gpu->vendor_id,
226 gpu->device_id) != buffer.get())
227 continue;
228 std::string device_string = buffer.get();
229 size_t begin = device_string.find_first_of('[');
230 size_t end = device_string.find_last_of(']');
231 if (begin != std::string::npos && end != std::string::npos &&
232 begin < end) {
233 device_string = device_string.substr(begin + 1, end - begin - 1);
234 }
235 if (StartsWithASCII(gl_renderer_string, device_string, kCaseSensitive)) {
236 gpu_active = gpu;
237 break;
238 }
239 // If a device's vendor matches gl VENDOR string, we want to consider the
240 // possibility that libpci may not return the exact same name as gl
241 // RENDERER string.
242 candidates.push_back(gpu);
243 }
244 if (gpu_active == NULL && candidates.size() == 1)
245 gpu_active = candidates[0];
246 }
247 if (gpu_active != NULL) {
248 gpu_info->vendor_id = gpu_active->vendor_id;
249 gpu_info->device_id = gpu_active->device_id;
250 }
251 (interface->pci_cleanup)(access);
252 FinalizeLibPci(&interface);
253 return (gpu_active != NULL);
254 }
255
256 bool CollectDriverInfoGL(GPUInfo* gpu_info) {
257 DCHECK(gpu_info);
258
259 std::string gl_version_string = gpu_info->gl_version_string;
260 std::vector<std::string> pieces;
261 base::SplitStringAlongWhitespace(gl_version_string, &pieces);
262 // In linux, the gl version string might be in the format of
263 // GLVersion DriverVendor DriverVersion
264 if (pieces.size() < 3)
265 return false;
266
267 std::string driver_version = pieces[2];
268 size_t pos = driver_version.find_first_not_of("0123456789.");
269 if (pos == 0)
270 return false;
271 if (pos != std::string::npos)
272 driver_version = driver_version.substr(0, pos);
273
274 gpu_info->driver_vendor = pieces[1];
275 gpu_info->driver_version = driver_version;
276 return true;
277 }
278
279 } // namespace gpu_info_collector
OLDNEW
« no previous file with comments | « chrome/gpu/gpu_info_collector.cc ('k') | chrome/gpu/gpu_info_collector_mac.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698