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 // This has to be included before windows.h. | 7 // This has to be included before windows.h. |
8 #include "third_party/re2/re2/re2.h" | 8 #include "third_party/re2/re2/re2.h" |
9 | 9 |
10 #include <windows.h> | 10 #include <windows.h> |
11 #include <d3d9.h> | 11 #include <d3d9.h> |
12 #include <d3d11.h> | 12 #include <d3d11.h> |
13 #include <dxgi.h> | 13 #include <dxgi.h> |
14 #include <setupapi.h> | 14 #include <setupapi.h> |
15 | 15 |
16 #include "base/command_line.h" | 16 #include "base/command_line.h" |
17 #include "base/debug/trace_event.h" | 17 #include "base/debug/trace_event.h" |
18 #include "base/file_util.h" | 18 #include "base/file_util.h" |
19 #include "base/files/file_path.h" | 19 #include "base/files/file_path.h" |
20 #include "base/logging.h" | 20 #include "base/logging.h" |
21 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
22 #include "base/metrics/histogram.h" | 22 #include "base/metrics/histogram.h" |
23 #include "base/scoped_native_library.h" | 23 #include "base/scoped_native_library.h" |
24 #include "base/string_number_conversions.h" | 24 #include "base/string_number_conversions.h" |
25 #include "base/string_util.h" | 25 #include "base/string_util.h" |
| 26 #include "base/string16.h" |
26 #include "base/stringprintf.h" | 27 #include "base/stringprintf.h" |
27 #include "base/threading/thread.h" | 28 #include "base/threading/thread.h" |
28 #include "base/threading/worker_pool.h" | 29 #include "base/threading/worker_pool.h" |
29 #include "base/win/registry.h" | 30 #include "base/win/registry.h" |
30 #include "base/win/scoped_com_initializer.h" | 31 #include "base/win/scoped_com_initializer.h" |
31 #include "base/win/scoped_comptr.h" | 32 #include "base/win/scoped_comptr.h" |
32 #include "base/win/windows_version.h" | 33 #include "base/win/windows_version.h" |
33 #include "third_party/libxml/chromium/libxml_utils.h" | 34 #include "third_party/libxml/chromium/libxml_utils.h" |
34 #include "ui/gl/gl_implementation.h" | 35 #include "ui/gl/gl_implementation.h" |
35 #include "ui/gl/gl_surface_egl.h" | 36 #include "ui/gl/gl_surface_egl.h" |
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 } | 197 } |
197 | 198 |
198 if (FAILED(key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY))) | 199 if (FAILED(key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY))) |
199 return false; | 200 return false; |
200 | 201 |
201 if (FAILED(key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY))) | 202 if (FAILED(key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY))) |
202 return false; | 203 return false; |
203 | 204 |
204 return true; | 205 return true; |
205 } | 206 } |
206 } // namespace anonymous | |
207 | 207 |
208 namespace gpu_info_collector { | 208 // Determines whether D3D11 won't work, either because it is not supported on |
| 209 // the machine or because it is known it is likely to crash. |
| 210 bool D3D11ShouldWork(const content::GPUInfo& gpu_info) { |
| 211 // Windows XP never supports D3D11. |
| 212 if (base::win::GetVersion() <= base::win::VERSION_XP) |
| 213 return false; |
209 | 214 |
210 #if !defined(GOOGLE_CHROME_BUILD) | 215 // Intel? |
211 AMDVideoCardType GetAMDVideocardType() { | 216 if (gpu_info.gpu.vendor_id == 0x8086) { |
212 return UNKNOWN; | 217 // 2nd Generation Core Processor Family Integrated Graphics Controller? |
| 218 if (gpu_info.gpu.device_id == 0x0102 || |
| 219 gpu_info.gpu.device_id == 0x0106 || |
| 220 gpu_info.gpu.device_id == 0x0116 || |
| 221 gpu_info.gpu.device_id == 0x0126) { |
| 222 // http://crbug.com/196373. |
| 223 if (base::win::GetVersion() == base::win::VERSION_VISTA) |
| 224 return false; |
| 225 |
| 226 // http://crbug.com/175525. |
| 227 if (gpu_info.display_link_version.IsValid()) |
| 228 return false; |
| 229 } |
| 230 } |
| 231 |
| 232 return true; |
213 } | 233 } |
214 #else | |
215 // This function has a real implementation for official builds that can | |
216 // be found in src/third_party/amd. | |
217 AMDVideoCardType GetAMDVideocardType(); | |
218 #endif | |
219 | 234 |
220 // Collects information about the level of D3D11 support and records it in | 235 // Collects information about the level of D3D11 support and records it in |
221 // the UMA stats. Records no stats when D3D11 in not supported at all. | 236 // the UMA stats. Records no stats when D3D11 in not supported at all. |
222 // | 237 void CollectD3D11SupportOnWorkerThread() { |
223 // http://crbug.com/175525. Using D3D11 seems to crash when dlumd32.dll is | |
224 // loaded. This function is not currently called. | |
225 void CollectD3D11Support(HMODULE d3d11_module) { | |
226 TRACE_EVENT0("gpu", "CollectD3D11Support"); | 238 TRACE_EVENT0("gpu", "CollectD3D11Support"); |
227 | 239 |
228 typedef HRESULT (WINAPI *D3D11CreateDeviceFunc)( | 240 typedef HRESULT (WINAPI *D3D11CreateDeviceFunc)( |
229 IDXGIAdapter* adapter, | 241 IDXGIAdapter* adapter, |
230 D3D_DRIVER_TYPE driver_type, | 242 D3D_DRIVER_TYPE driver_type, |
231 HMODULE software, | 243 HMODULE software, |
232 UINT flags, | 244 UINT flags, |
233 const D3D_FEATURE_LEVEL* feature_levels, | 245 const D3D_FEATURE_LEVEL* feature_levels, |
234 UINT num_feature_levels, | 246 UINT num_feature_levels, |
235 UINT sdk_version, | 247 UINT sdk_version, |
(...skipping 13 matching lines...) Expand all Loading... |
249 FEATURE_LEVEL_9_3, | 261 FEATURE_LEVEL_9_3, |
250 FEATURE_LEVEL_10_0, | 262 FEATURE_LEVEL_10_0, |
251 FEATURE_LEVEL_10_1, | 263 FEATURE_LEVEL_10_1, |
252 FEATURE_LEVEL_11_0, | 264 FEATURE_LEVEL_11_0, |
253 NUM_FEATURE_LEVELS | 265 NUM_FEATURE_LEVELS |
254 }; | 266 }; |
255 | 267 |
256 FeatureLevel feature_level = FEATURE_LEVEL_UNKNOWN; | 268 FeatureLevel feature_level = FEATURE_LEVEL_UNKNOWN; |
257 UINT bgra_support = 0; | 269 UINT bgra_support = 0; |
258 | 270 |
| 271 // This module is leaked in case it is hooked by third party software. |
| 272 base::NativeLibrary d3d11_module = base::LoadNativeLibrary( |
| 273 base::FilePath(L"d3d11.dll"), |
| 274 NULL); |
| 275 |
259 if (!d3d11_module) { | 276 if (!d3d11_module) { |
260 feature_level = FEATURE_LEVEL_NO_D3D11_DLL; | 277 feature_level = FEATURE_LEVEL_NO_D3D11_DLL; |
261 } else { | 278 } else { |
262 D3D11CreateDeviceFunc create_func = | 279 D3D11CreateDeviceFunc create_func = |
263 reinterpret_cast<D3D11CreateDeviceFunc>( | 280 reinterpret_cast<D3D11CreateDeviceFunc>( |
264 GetProcAddress(d3d11_module, "D3D11CreateDevice")); | 281 base::GetFunctionPointerFromNativeLibrary(d3d11_module, |
| 282 "D3D11CreateDevice")); |
265 if (!create_func) { | 283 if (!create_func) { |
266 feature_level = FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT; | 284 feature_level = FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT; |
267 } else { | 285 } else { |
268 static const D3D_FEATURE_LEVEL d3d_feature_levels[] = { | 286 static const D3D_FEATURE_LEVEL d3d_feature_levels[] = { |
269 D3D_FEATURE_LEVEL_11_0, | 287 D3D_FEATURE_LEVEL_11_0, |
270 D3D_FEATURE_LEVEL_10_1, | 288 D3D_FEATURE_LEVEL_10_1, |
271 D3D_FEATURE_LEVEL_10_0, | 289 D3D_FEATURE_LEVEL_10_0, |
272 D3D_FEATURE_LEVEL_9_3, | 290 D3D_FEATURE_LEVEL_9_3, |
273 D3D_FEATURE_LEVEL_9_2, | 291 D3D_FEATURE_LEVEL_9_2, |
274 D3D_FEATURE_LEVEL_9_1 | 292 D3D_FEATURE_LEVEL_9_1 |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 return; | 349 return; |
332 | 350 |
333 UMA_HISTOGRAM_BOOLEAN( | 351 UMA_HISTOGRAM_BOOLEAN( |
334 "GPU.D3D11_B8G8R8A8_Texture2DSupport", | 352 "GPU.D3D11_B8G8R8A8_Texture2DSupport", |
335 (bgra_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); | 353 (bgra_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); |
336 UMA_HISTOGRAM_BOOLEAN( | 354 UMA_HISTOGRAM_BOOLEAN( |
337 "GPU.D3D11_B8G8R8A8_RenderTargetSupport", | 355 "GPU.D3D11_B8G8R8A8_RenderTargetSupport", |
338 (bgra_support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0); | 356 (bgra_support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0); |
339 } | 357 } |
340 | 358 |
341 void CollectD3D11SupportDelayed( | 359 // Collects information about the level of D3D11 support and records it in |
342 const scoped_refptr<base::MessageLoopProxy> main_loop) { | 360 // the UMA stats. Records no stats when D3D11 in not supported at all. |
343 // Windows XP is expected to not support D3D11. | 361 void CollectD3D11Support() { |
344 if (base::win::GetVersion() <= base::win::VERSION_XP) | 362 // D3D11 takes about 50ms to initialize so do this on a worker thread. |
345 return; | 363 base::WorkerPool::PostTask( |
| 364 FROM_HERE, |
| 365 base::Bind(CollectD3D11SupportOnWorkerThread), |
| 366 false); |
| 367 } |
| 368 } // namespace anonymous |
346 | 369 |
347 // This is leaked in case it is hooked by a third party DLL. | 370 namespace gpu_info_collector { |
348 HMODULE d3d11_module = LoadLibrary(L"d3d11.dll"); | |
349 | 371 |
350 // Collect the D3D11 stats after a delay to allow third party DLLs | 372 #if !defined(GOOGLE_CHROME_BUILD) |
351 // to hook D3D11 before we try to use it. Also do it on the main thread | 373 AMDVideoCardType GetAMDVideocardType() { |
352 // in case the third party DLL does this on the main thread. | 374 return UNKNOWN; |
353 main_loop->PostDelayedTask( | |
354 FROM_HERE, | |
355 base::Bind(CollectD3D11Support, d3d11_module), | |
356 base::TimeDelta::FromSeconds(10)); | |
357 } | 375 } |
| 376 #else |
| 377 // This function has a real implementation for official builds that can |
| 378 // be found in src/third_party/amd. |
| 379 AMDVideoCardType GetAMDVideocardType(); |
| 380 #endif |
358 | 381 |
359 bool CollectDriverInfoD3D(const std::wstring& device_id, | 382 bool CollectDriverInfoD3D(const std::wstring& device_id, |
360 content::GPUInfo* gpu_info) { | 383 content::GPUInfo* gpu_info) { |
361 TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); | 384 TRACE_EVENT0("gpu", "CollectDriverInfoD3D"); |
362 | 385 |
363 // create device info for the display device | 386 // create device info for the display device |
364 HDEVINFO device_info = SetupDiGetClassDevsW( | 387 HDEVINFO device_info = SetupDiGetClassDevsW( |
365 NULL, device_id.c_str(), NULL, | 388 NULL, device_id.c_str(), NULL, |
366 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); | 389 DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); |
367 if (device_info == INVALID_HANDLE_VALUE) { | 390 if (device_info == INVALID_HANDLE_VALUE) { |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
555 DISPLAY_DEVICE dd; | 578 DISPLAY_DEVICE dd; |
556 dd.cb = sizeof(DISPLAY_DEVICE); | 579 dd.cb = sizeof(DISPLAY_DEVICE); |
557 std::wstring id; | 580 std::wstring id; |
558 for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) { | 581 for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) { |
559 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { | 582 if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) { |
560 id = dd.DeviceID; | 583 id = dd.DeviceID; |
561 break; | 584 break; |
562 } | 585 } |
563 } | 586 } |
564 | 587 |
565 if (id.length() > 20) { | 588 if (id.length() <= 20) |
566 int vendor_id = 0, device_id = 0; | 589 return false; |
567 std::wstring vendor_id_string = id.substr(8, 4); | 590 |
568 std::wstring device_id_string = id.substr(17, 4); | 591 int vendor_id = 0, device_id = 0; |
569 base::HexStringToInt(WideToASCII(vendor_id_string), &vendor_id); | 592 string16 vendor_id_string = id.substr(8, 4); |
570 base::HexStringToInt(WideToASCII(device_id_string), &device_id); | 593 string16 device_id_string = id.substr(17, 4); |
571 gpu_info->gpu.vendor_id = vendor_id; | 594 base::HexStringToInt(WideToASCII(vendor_id_string), &vendor_id); |
572 gpu_info->gpu.device_id = device_id; | 595 base::HexStringToInt(WideToASCII(device_id_string), &device_id); |
573 // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE. | 596 gpu_info->gpu.vendor_id = vendor_id; |
574 return CollectDriverInfoD3D(id, gpu_info); | 597 gpu_info->gpu.device_id = device_id; |
| 598 // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE. |
| 599 if (!CollectDriverInfoD3D(id, gpu_info)) |
| 600 return false; |
| 601 |
| 602 // Collect basic information about supported D3D11 features. Delay for 45 |
| 603 // seconds so as not to regress performance tests. |
| 604 if (D3D11ShouldWork(*gpu_info)) { |
| 605 MessageLoop::current()->PostDelayedTask( |
| 606 FROM_HERE, |
| 607 base::Bind(&CollectD3D11Support), |
| 608 base::TimeDelta::FromSeconds(45)); |
575 } | 609 } |
576 return false; | 610 |
| 611 return true; |
577 } | 612 } |
578 | 613 |
579 bool CollectDriverInfoGL(content::GPUInfo* gpu_info) { | 614 bool CollectDriverInfoGL(content::GPUInfo* gpu_info) { |
580 TRACE_EVENT0("gpu", "CollectDriverInfoGL"); | 615 TRACE_EVENT0("gpu", "CollectDriverInfoGL"); |
581 | 616 |
582 if (!gpu_info->driver_version.empty()) | 617 if (!gpu_info->driver_version.empty()) |
583 return true; | 618 return true; |
584 | 619 |
585 std::string gl_version_string = gpu_info->gl_version_string; | 620 std::string gl_version_string = gpu_info->gl_version_string; |
586 | 621 |
(...skipping 10 matching lines...) Expand all Loading... |
597 basic_gpu_info->software_rendering = true; | 632 basic_gpu_info->software_rendering = true; |
598 return; | 633 return; |
599 } | 634 } |
600 | 635 |
601 MergeGPUInfoGL(basic_gpu_info, context_gpu_info); | 636 MergeGPUInfoGL(basic_gpu_info, context_gpu_info); |
602 | 637 |
603 basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics; | 638 basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics; |
604 } | 639 } |
605 | 640 |
606 } // namespace gpu_info_collector | 641 } // namespace gpu_info_collector |
OLD | NEW |