OLD | NEW |
---|---|
1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/gpu/gpu_info_collector.h" | 5 #include "chrome/gpu/gpu_info_collector.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "app/gfx/gl/gl_bindings.h" | 10 #include "app/gfx/gl/gl_bindings.h" |
11 #include "app/gfx/gl/gl_context.h" | 11 #include "app/gfx/gl/gl_context.h" |
12 #include "app/gfx/gl/gl_implementation.h" | 12 #include "app/gfx/gl/gl_implementation.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/scoped_ptr.h" | 14 #include "base/scoped_ptr.h" |
15 #include "base/string_piece.h" | |
16 #include "base/string_split.h" | |
15 #include "base/string_util.h" | 17 #include "base/string_util.h" |
16 | 18 |
17 namespace { | 19 namespace { |
18 | 20 |
19 // PciDevice and PciAccess are defined to access libpci functions. Their | 21 // PciDevice and PciAccess are defined to access libpci functions. Their |
20 // members match the corresponding structures defined by libpci in size up to | 22 // members match the corresponding structures defined by libpci in size up to |
21 // fields we may access. For those members we don't use, their names are | 23 // fields we may access. For those members we don't use, their names are |
22 // defined as "fieldX", etc., or, left out if they are declared after the | 24 // defined as "fieldX", etc., or, left out if they are declared after the |
23 // members we care about in libpci. | 25 // members we care about in libpci. |
24 | 26 |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
113 } | 115 } |
114 | 116 |
115 // This close the dynamically opened libpci and delete the interface. | 117 // This close the dynamically opened libpci and delete the interface. |
116 void FinalizeLibPci(PciInterface*& interface) { | 118 void FinalizeLibPci(PciInterface*& interface) { |
117 DCHECK(interface != NULL && interface->lib_handle != NULL); | 119 DCHECK(interface != NULL && interface->lib_handle != NULL); |
118 dlclose(interface->lib_handle); | 120 dlclose(interface->lib_handle); |
119 delete interface; | 121 delete interface; |
120 interface = NULL; | 122 interface = NULL; |
121 } | 123 } |
122 | 124 |
123 // This creates an offscreen GL context for gl queries. Returned GLContext | |
124 // should be deleted in FinalizeGLContext. | |
125 gfx::GLContext* InitializeGLContext() { | |
126 if (!gfx::GLContext::InitializeOneOff()) { | |
127 LOG(ERROR) << "gfx::GLContext::InitializeOneOff() failed"; | |
128 return NULL; | |
129 } | |
130 gfx::GLContext* context = gfx::GLContext::CreateOffscreenGLContext(NULL); | |
131 if (context == NULL) { | |
132 LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLContext(NULL) failed"; | |
133 return NULL; | |
134 } | |
135 if (!context->MakeCurrent()) { | |
136 LOG(ERROR) << "gfx::GLContext::MakeCurrent() failed"; | |
137 context->Destroy(); | |
138 delete context; | |
139 return NULL; | |
140 } | |
141 return context; | |
142 } | |
143 | |
144 // This destroy and delete the GL context. | |
145 void FinalizeGLContext(gfx::GLContext*& context) { | |
146 DCHECK(context != NULL); | |
147 context->Destroy(); | |
148 delete context; | |
149 context = NULL; | |
150 } | |
151 | |
152 } // namespace anonymous | 125 } // namespace anonymous |
153 | 126 |
154 namespace gpu_info_collector { | 127 namespace gpu_info_collector { |
155 | 128 |
156 bool CollectGraphicsInfo(GPUInfo* gpu_info) { | 129 bool CollectGraphicsInfo(GPUInfo* gpu_info) { |
157 gfx::GLContext* context = InitializeGLContext(); | 130 DCHECK(gpu_info); |
158 if (context == NULL) | |
159 return false; | |
160 | 131 |
161 // TODO(zmo): collect driver version, pixel shader version, vertex shader | 132 gpu_info->SetCanLoseContext( |
162 // version, and gl version. | 133 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2); |
Ken Russell (switch to Gerrit)
2011/01/19 22:11:43
What if we're running on desktop GL and the GL_ARB
Zhenyao Mo
2011/01/19 23:36:22
Added a FIXME here for this.
On 2011/01/19 22:11:
| |
163 std::wstring driver_version = L""; | 134 gpu_info->SetProgress(GPUInfo::kComplete); |
164 uint32 pixel_shader_version = 0; | 135 return CollectGraphicsInfoGL(gpu_info); |
165 uint32 vertex_shader_version = 0; | 136 } |
166 uint32 gl_version = 0; | 137 |
167 bool can_lose_context = | 138 bool CollectVideoCardInfo(GPUInfo* gpu_info) { |
168 (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2); | 139 DCHECK(gpu_info); |
169 | 140 |
170 // TODO(zmo): be more flexible about library name. | 141 // TODO(zmo): be more flexible about library name. |
171 PciInterface* interface = InitializeLibPci("libpci.so.3"); | 142 PciInterface* interface = InitializeLibPci("libpci.so.3"); |
172 if (interface == NULL) { | 143 if (interface == NULL) |
173 FinalizeGLContext(context); | |
174 return false; | 144 return false; |
175 } | |
176 | 145 |
177 PciAccess* access = (interface->pci_alloc)(); | 146 PciAccess* access = (interface->pci_alloc)(); |
178 DCHECK(access != NULL); | 147 DCHECK(access != NULL); |
179 (interface->pci_init)(access); | 148 (interface->pci_init)(access); |
180 (interface->pci_scan_bus)(access); | 149 (interface->pci_scan_bus)(access); |
181 std::vector<PciDevice*> gpu_list; | 150 std::vector<PciDevice*> gpu_list; |
182 PciDevice* gpu_active = NULL; | 151 PciDevice* gpu_active = NULL; |
183 for (PciDevice* device = access->device_list; | 152 for (PciDevice* device = access->device_list; |
184 device != NULL; device = device->next) { | 153 device != NULL; device = device->next) { |
185 (interface->pci_fill_info)(device, 33); // Fill the IDs and class fields. | 154 (interface->pci_fill_info)(device, 33); // Fill the IDs and class fields. |
186 if (device->device_class == 0x0300) { // Device class is DISPLAY_VGA. | 155 if (device->device_class == 0x0300) { // Device class is DISPLAY_VGA. |
rpetterson
2011/01/20 00:48:03
0x0300 was the most common in my research, but the
| |
187 gpu_list.push_back(device); | 156 gpu_list.push_back(device); |
188 } | 157 } |
189 } | 158 } |
190 if (gpu_list.size() == 1) { | 159 if (gpu_list.size() == 1) { |
191 gpu_active = gpu_list[0]; | 160 gpu_active = gpu_list[0]; |
192 } else { | 161 } else { |
193 // If more than one graphics card are identified, find the one that matches | 162 // If more than one graphics card are identified, find the one that matches |
194 // gl VENDOR and RENDERER info. | 163 // gl VENDOR and RENDERER info. |
195 std::string gl_vendor_string = | 164 std::string gl_vendor_string = gpu_info->gl_vendor(); |
196 reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | 165 std::string gl_renderer_string = gpu_info->gl_renderer(); |
197 std::string gl_renderer_string = | |
198 reinterpret_cast<const char*>(glGetString(GL_RENDERER)); | |
199 const int buffer_size = 255; | 166 const int buffer_size = 255; |
200 scoped_array<char> buffer(new char[buffer_size]); | 167 scoped_array<char> buffer(new char[buffer_size]); |
201 std::vector<PciDevice*> candidates; | 168 std::vector<PciDevice*> candidates; |
202 for (size_t i = 0; i < gpu_list.size(); ++i) { | 169 for (size_t i = 0; i < gpu_list.size(); ++i) { |
203 PciDevice* gpu = gpu_list[i]; | 170 PciDevice* gpu = gpu_list[i]; |
204 // The current implementation of pci_lookup_name returns the same pointer | 171 // The current implementation of pci_lookup_name returns the same pointer |
205 // as the passed in upon success, and a different one (NULL or a pointer | 172 // as the passed in upon success, and a different one (NULL or a pointer |
206 // to an error message) upon failure. | 173 // to an error message) upon failure. |
207 if ((interface->pci_lookup_name)(access, | 174 if ((interface->pci_lookup_name)(access, |
208 buffer.get(), | 175 buffer.get(), |
(...skipping 24 matching lines...) Expand all Loading... | |
233 break; | 200 break; |
234 } | 201 } |
235 // If a device's vendor matches gl VENDOR string, we want to consider the | 202 // If a device's vendor matches gl VENDOR string, we want to consider the |
236 // possibility that libpci may not return the exact same name as gl | 203 // possibility that libpci may not return the exact same name as gl |
237 // RENDERER string. | 204 // RENDERER string. |
238 candidates.push_back(gpu); | 205 candidates.push_back(gpu); |
239 } | 206 } |
240 if (gpu_active == NULL && candidates.size() == 1) | 207 if (gpu_active == NULL && candidates.size() == 1) |
241 gpu_active = candidates[0]; | 208 gpu_active = candidates[0]; |
242 } | 209 } |
243 if (gpu_active != NULL) { | 210 if (gpu_active != NULL) |
244 gpu_info->SetGraphicsInfo(gpu_active->vendor_id, | 211 gpu_info->SetVideoCardInfo(gpu_active->vendor_id, gpu_active->device_id); |
245 gpu_active->device_id, | |
246 driver_version, | |
247 pixel_shader_version, | |
248 vertex_shader_version, | |
249 gl_version, | |
250 can_lose_context); | |
251 gpu_info->SetProgress(GPUInfo::kComplete); | |
252 } | |
253 (interface->pci_cleanup)(access); | 212 (interface->pci_cleanup)(access); |
254 FinalizeLibPci(interface); | 213 FinalizeLibPci(interface); |
255 FinalizeGLContext(context); | |
256 return (gpu_active != NULL); | 214 return (gpu_active != NULL); |
257 } | 215 } |
258 | 216 |
217 bool CollectDriverInfo(GPUInfo* gpu_info) { | |
218 DCHECK(gpu_info); | |
219 | |
220 std::string gl_version_string = gpu_info->gl_version_string(); | |
221 std::vector<std::string> pieces; | |
222 base::SplitStringAlongWhitespace(gl_version_string, &pieces); | |
223 // In linux, the gl version string might be in the format of | |
224 // GLVersion DriverVendor DriverVersion | |
225 if (pieces.size() < 3) | |
226 return false; | |
227 | |
228 std::string driver_version = pieces[2]; | |
229 size_t pos = driver_version.find_first_not_of("0123456789."); | |
230 if (pos == 0) | |
231 return false; | |
232 if (pos != std::string::npos) | |
233 driver_version = driver_version.substr(0, pos); | |
234 | |
235 gpu_info->SetDriverInfo(pieces[1], driver_version); | |
236 return true; | |
237 } | |
238 | |
259 } // namespace gpu_info_collector | 239 } // namespace gpu_info_collector |
OLD | NEW |