| Index: content/gpu/gpu_info_collector_win.cc
|
| ===================================================================
|
| --- content/gpu/gpu_info_collector_win.cc (revision 201645)
|
| +++ content/gpu/gpu_info_collector_win.cc (working copy)
|
| @@ -1,643 +0,0 @@
|
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include "content/gpu/gpu_info_collector.h"
|
| -
|
| -// This has to be included before windows.h.
|
| -#include "third_party/re2/re2/re2.h"
|
| -
|
| -#include <windows.h>
|
| -#include <d3d9.h>
|
| -#include <d3d11.h>
|
| -#include <dxgi.h>
|
| -#include <setupapi.h>
|
| -
|
| -#include "base/command_line.h"
|
| -#include "base/debug/trace_event.h"
|
| -#include "base/file_util.h"
|
| -#include "base/files/file_path.h"
|
| -#include "base/logging.h"
|
| -#include "base/message_loop.h"
|
| -#include "base/metrics/histogram.h"
|
| -#include "base/scoped_native_library.h"
|
| -#include "base/string_number_conversions.h"
|
| -#include "base/string_util.h"
|
| -#include "base/string16.h"
|
| -#include "base/stringprintf.h"
|
| -#include "base/threading/thread.h"
|
| -#include "base/threading/worker_pool.h"
|
| -#include "base/win/registry.h"
|
| -#include "base/win/scoped_com_initializer.h"
|
| -#include "base/win/scoped_comptr.h"
|
| -#include "base/win/windows_version.h"
|
| -#include "third_party/libxml/chromium/libxml_utils.h"
|
| -#include "ui/gl/gl_implementation.h"
|
| -#include "ui/gl/gl_surface_egl.h"
|
| -
|
| -namespace {
|
| -
|
| -// This must be kept in sync with histograms.xml.
|
| -enum DisplayLinkInstallationStatus {
|
| - DISPLAY_LINK_NOT_INSTALLED,
|
| - DISPLAY_LINK_7_1_OR_EARLIER,
|
| - DISPLAY_LINK_7_2_OR_LATER,
|
| - DISPLAY_LINK_INSTALLATION_STATUS_MAX
|
| -};
|
| -
|
| -float ReadXMLFloatValue(XmlReader* reader) {
|
| - std::string score_string;
|
| - if (!reader->ReadElementContent(&score_string))
|
| - return 0.0;
|
| -
|
| - double score;
|
| - if (!base::StringToDouble(score_string, &score))
|
| - return 0.0;
|
| -
|
| - return static_cast<float>(score);
|
| -}
|
| -
|
| -content::GpuPerformanceStats RetrieveGpuPerformanceStats() {
|
| - TRACE_EVENT0("gpu", "RetrieveGpuPerformanceStats");
|
| -
|
| - // If the user re-runs the assessment without restarting, the COM API
|
| - // returns WINSAT_ASSESSMENT_STATE_NOT_AVAILABLE. Because of that and
|
| - // http://crbug.com/124325, read the assessment result files directly.
|
| - content::GpuPerformanceStats stats;
|
| -
|
| - // Get path to WinSAT results files.
|
| - wchar_t winsat_results_path[MAX_PATH];
|
| - DWORD size = ExpandEnvironmentStrings(
|
| - L"%WinDir%\\Performance\\WinSAT\\DataStore\\",
|
| - winsat_results_path, MAX_PATH);
|
| - if (size == 0 || size > MAX_PATH) {
|
| - LOG(ERROR) << "The path to the WinSAT results is too long: "
|
| - << size << " chars.";
|
| - return stats;
|
| - }
|
| -
|
| - // Find most recent formal assessment results.
|
| - file_util::FileEnumerator file_enumerator(
|
| - base::FilePath(winsat_results_path),
|
| - false, // not recursive
|
| - file_util::FileEnumerator::FILES,
|
| - FILE_PATH_LITERAL("* * Formal.Assessment (*).WinSAT.xml"));
|
| -
|
| - base::FilePath current_results;
|
| - for (base::FilePath results = file_enumerator.Next(); !results.empty();
|
| - results = file_enumerator.Next()) {
|
| - // The filenames start with the date and time as yyyy-mm-dd hh.mm.ss.xxx,
|
| - // so the greatest file lexicographically is also the most recent file.
|
| - if (base::FilePath::CompareLessIgnoreCase(current_results.value(),
|
| - results.value()))
|
| - current_results = results;
|
| - }
|
| -
|
| - std::string current_results_string = current_results.MaybeAsASCII();
|
| - if (current_results_string.empty()) {
|
| - LOG(ERROR) << "Can't retrieve a valid WinSAT assessment.";
|
| - return stats;
|
| - }
|
| -
|
| - // Get relevant scores from results file. XML schema at:
|
| - // http://msdn.microsoft.com/en-us/library/windows/desktop/aa969210.aspx
|
| - XmlReader reader;
|
| - if (!reader.LoadFile(current_results_string)) {
|
| - LOG(ERROR) << "Could not open WinSAT results file.";
|
| - return stats;
|
| - }
|
| - // Descend into <WinSAT> root element.
|
| - if (!reader.SkipToElement() || !reader.Read()) {
|
| - LOG(ERROR) << "Could not read WinSAT results file.";
|
| - return stats;
|
| - }
|
| -
|
| - // Search for <WinSPR> element containing the results.
|
| - do {
|
| - if (reader.NodeName() == "WinSPR")
|
| - break;
|
| - } while (reader.Next());
|
| - // Descend into <WinSPR> element.
|
| - if (!reader.Read()) {
|
| - LOG(ERROR) << "Could not find WinSPR element in results file.";
|
| - return stats;
|
| - }
|
| -
|
| - // Read scores.
|
| - for (int depth = reader.Depth(); reader.Depth() == depth; reader.Next()) {
|
| - std::string node_name = reader.NodeName();
|
| - if (node_name == "SystemScore")
|
| - stats.overall = ReadXMLFloatValue(&reader);
|
| - else if (node_name == "GraphicsScore")
|
| - stats.graphics = ReadXMLFloatValue(&reader);
|
| - else if (node_name == "GamingScore")
|
| - stats.gaming = ReadXMLFloatValue(&reader);
|
| - }
|
| -
|
| - if (stats.overall == 0.0)
|
| - LOG(ERROR) << "Could not read overall score from assessment results.";
|
| - if (stats.graphics == 0.0)
|
| - LOG(ERROR) << "Could not read graphics score from assessment results.";
|
| - if (stats.gaming == 0.0)
|
| - LOG(ERROR) << "Could not read gaming score from assessment results.";
|
| -
|
| - return stats;
|
| -}
|
| -
|
| -content::GpuPerformanceStats RetrieveGpuPerformanceStatsWithHistograms() {
|
| - base::TimeTicks start_time = base::TimeTicks::Now();
|
| -
|
| - content::GpuPerformanceStats stats = RetrieveGpuPerformanceStats();
|
| -
|
| - UMA_HISTOGRAM_TIMES("GPU.WinSAT.ReadResultsFileTime",
|
| - base::TimeTicks::Now() - start_time);
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.OverallScore2",
|
| - stats.overall * 10, 10, 200, 50);
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GraphicsScore2",
|
| - stats.graphics * 10, 10, 200, 50);
|
| - UMA_HISTOGRAM_CUSTOM_COUNTS("GPU.WinSAT.GamingScore2",
|
| - stats.gaming * 10, 10, 200, 50);
|
| - UMA_HISTOGRAM_BOOLEAN(
|
| - "GPU.WinSAT.HasResults",
|
| - stats.overall != 0.0 && stats.graphics != 0.0 && stats.gaming != 0.0);
|
| -
|
| - return stats;
|
| -}
|
| -
|
| -// Returns the display link driver version or an invalid version if it is
|
| -// not installed.
|
| -Version DisplayLinkVersion() {
|
| - base::win::RegKey key;
|
| -
|
| - if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
|
| - return Version();
|
| -
|
| - if (key.OpenKey(L"DisplayLink", KEY_READ | KEY_WOW64_64KEY))
|
| - return Version();
|
| -
|
| - if (key.OpenKey(L"Core", KEY_READ | KEY_WOW64_64KEY))
|
| - return Version();
|
| -
|
| - string16 version;
|
| - if (key.ReadValue(L"Version", &version))
|
| - return Version();
|
| -
|
| - return Version(WideToASCII(version));
|
| -}
|
| -
|
| -// Returns whether Lenovo dCute is installed.
|
| -bool IsLenovoDCuteInstalled() {
|
| - base::win::RegKey key;
|
| -
|
| - if (key.Open(HKEY_LOCAL_MACHINE, L"SOFTWARE", KEY_READ | KEY_WOW64_64KEY))
|
| - return false;
|
| -
|
| - if (key.OpenKey(L"Lenovo", KEY_READ | KEY_WOW64_64KEY))
|
| - return false;
|
| -
|
| - if (key.OpenKey(L"Lenovo dCute", KEY_READ | KEY_WOW64_64KEY))
|
| - return false;
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// Determines whether D3D11 won't work, either because it is not supported on
|
| -// the machine or because it is known it is likely to crash.
|
| -bool D3D11ShouldWork(const content::GPUInfo& gpu_info) {
|
| - // Windows XP never supports D3D11.
|
| - if (base::win::GetVersion() <= base::win::VERSION_XP)
|
| - return false;
|
| -
|
| - // Intel?
|
| - if (gpu_info.gpu.vendor_id == 0x8086) {
|
| - // 2nd Generation Core Processor Family Integrated Graphics Controller
|
| - // or Intel Ivy Bridge?
|
| - if (gpu_info.gpu.device_id == 0x0102 ||
|
| - gpu_info.gpu.device_id == 0x0106 ||
|
| - gpu_info.gpu.device_id == 0x0116 ||
|
| - gpu_info.gpu.device_id == 0x0126 ||
|
| - gpu_info.gpu.device_id == 0x0152 ||
|
| - gpu_info.gpu.device_id == 0x0156 ||
|
| - gpu_info.gpu.device_id == 0x015a ||
|
| - gpu_info.gpu.device_id == 0x0162 ||
|
| - gpu_info.gpu.device_id == 0x0166) {
|
| - // http://crbug.com/196373.
|
| - if (base::win::GetVersion() == base::win::VERSION_VISTA)
|
| - return false;
|
| -
|
| - // http://crbug.com/175525.
|
| - if (gpu_info.display_link_version.IsValid())
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -// Collects information about the level of D3D11 support and records it in
|
| -// the UMA stats. Records no stats when D3D11 in not supported at all.
|
| -void CollectD3D11SupportOnWorkerThread() {
|
| - TRACE_EVENT0("gpu", "CollectD3D11Support");
|
| -
|
| - typedef HRESULT (WINAPI *D3D11CreateDeviceFunc)(
|
| - IDXGIAdapter* adapter,
|
| - D3D_DRIVER_TYPE driver_type,
|
| - HMODULE software,
|
| - UINT flags,
|
| - const D3D_FEATURE_LEVEL* feature_levels,
|
| - UINT num_feature_levels,
|
| - UINT sdk_version,
|
| - ID3D11Device** device,
|
| - D3D_FEATURE_LEVEL* feature_level,
|
| - ID3D11DeviceContext** immediate_context);
|
| -
|
| - // This enumeration must be kept in sync with histograms.xml. Do not reorder
|
| - // the members; always add to the end.
|
| - enum FeatureLevel {
|
| - FEATURE_LEVEL_UNKNOWN,
|
| - FEATURE_LEVEL_NO_D3D11_DLL,
|
| - FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT,
|
| - FEATURE_LEVEL_DEVICE_CREATION_FAILED,
|
| - FEATURE_LEVEL_9_1,
|
| - FEATURE_LEVEL_9_2,
|
| - FEATURE_LEVEL_9_3,
|
| - FEATURE_LEVEL_10_0,
|
| - FEATURE_LEVEL_10_1,
|
| - FEATURE_LEVEL_11_0,
|
| - NUM_FEATURE_LEVELS
|
| - };
|
| -
|
| - FeatureLevel feature_level = FEATURE_LEVEL_UNKNOWN;
|
| - UINT bgra_support = 0;
|
| -
|
| - // This module is leaked in case it is hooked by third party software.
|
| - base::NativeLibrary d3d11_module = base::LoadNativeLibrary(
|
| - base::FilePath(L"d3d11.dll"),
|
| - NULL);
|
| -
|
| - if (!d3d11_module) {
|
| - feature_level = FEATURE_LEVEL_NO_D3D11_DLL;
|
| - } else {
|
| - D3D11CreateDeviceFunc create_func =
|
| - reinterpret_cast<D3D11CreateDeviceFunc>(
|
| - base::GetFunctionPointerFromNativeLibrary(d3d11_module,
|
| - "D3D11CreateDevice"));
|
| - if (!create_func) {
|
| - feature_level = FEATURE_LEVEL_NO_CREATE_DEVICE_ENTRY_POINT;
|
| - } else {
|
| - static const D3D_FEATURE_LEVEL d3d_feature_levels[] = {
|
| - D3D_FEATURE_LEVEL_11_0,
|
| - D3D_FEATURE_LEVEL_10_1,
|
| - D3D_FEATURE_LEVEL_10_0,
|
| - D3D_FEATURE_LEVEL_9_3,
|
| - D3D_FEATURE_LEVEL_9_2,
|
| - D3D_FEATURE_LEVEL_9_1
|
| - };
|
| -
|
| - base::win::ScopedComPtr<ID3D11Device> device;
|
| - D3D_FEATURE_LEVEL d3d_feature_level;
|
| - base::win::ScopedComPtr<ID3D11DeviceContext> device_context;
|
| - HRESULT hr = create_func(NULL,
|
| - D3D_DRIVER_TYPE_HARDWARE,
|
| - NULL,
|
| - 0,
|
| - d3d_feature_levels,
|
| - arraysize(d3d_feature_levels),
|
| - D3D11_SDK_VERSION,
|
| - device.Receive(),
|
| - &d3d_feature_level,
|
| - device_context.Receive());
|
| - if (FAILED(hr)) {
|
| - feature_level = FEATURE_LEVEL_DEVICE_CREATION_FAILED;
|
| - } else {
|
| - switch (d3d_feature_level) {
|
| - case D3D_FEATURE_LEVEL_11_0:
|
| - feature_level = FEATURE_LEVEL_11_0;
|
| - break;
|
| - case D3D_FEATURE_LEVEL_10_1:
|
| - feature_level = FEATURE_LEVEL_10_1;
|
| - break;
|
| - case D3D_FEATURE_LEVEL_10_0:
|
| - feature_level = FEATURE_LEVEL_10_0;
|
| - break;
|
| - case D3D_FEATURE_LEVEL_9_3:
|
| - feature_level = FEATURE_LEVEL_9_3;
|
| - break;
|
| - case D3D_FEATURE_LEVEL_9_2:
|
| - feature_level = FEATURE_LEVEL_9_2;
|
| - break;
|
| - case D3D_FEATURE_LEVEL_9_1:
|
| - feature_level = FEATURE_LEVEL_9_1;
|
| - break;
|
| - default:
|
| - NOTREACHED();
|
| - break;
|
| - }
|
| -
|
| - hr = device->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM,
|
| - &bgra_support);
|
| - DCHECK(SUCCEEDED(hr));
|
| - }
|
| - }
|
| - }
|
| -
|
| - UMA_HISTOGRAM_ENUMERATION("GPU.D3D11_FeatureLevel",
|
| - feature_level,
|
| - NUM_FEATURE_LEVELS);
|
| -
|
| - // ANGLE requires at least feature level 10.0. Do not record any further
|
| - // stats if ANGLE would not work anyway.
|
| - if (feature_level < FEATURE_LEVEL_10_0)
|
| - return;
|
| -
|
| - UMA_HISTOGRAM_BOOLEAN(
|
| - "GPU.D3D11_B8G8R8A8_Texture2DSupport",
|
| - (bgra_support & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
|
| - UMA_HISTOGRAM_BOOLEAN(
|
| - "GPU.D3D11_B8G8R8A8_RenderTargetSupport",
|
| - (bgra_support & D3D11_FORMAT_SUPPORT_RENDER_TARGET) != 0);
|
| -}
|
| -
|
| -// Collects information about the level of D3D11 support and records it in
|
| -// the UMA stats. Records no stats when D3D11 in not supported at all.
|
| -void CollectD3D11Support() {
|
| - // D3D11 takes about 50ms to initialize so do this on a worker thread.
|
| - base::WorkerPool::PostTask(
|
| - FROM_HERE,
|
| - base::Bind(CollectD3D11SupportOnWorkerThread),
|
| - false);
|
| -}
|
| -} // namespace anonymous
|
| -
|
| -namespace gpu_info_collector {
|
| -
|
| -#if !defined(GOOGLE_CHROME_BUILD)
|
| -AMDVideoCardType GetAMDVideocardType() {
|
| - return STANDALONE;
|
| -}
|
| -#else
|
| -// This function has a real implementation for official builds that can
|
| -// be found in src/third_party/amd.
|
| -AMDVideoCardType GetAMDVideocardType();
|
| -#endif
|
| -
|
| -bool CollectDriverInfoD3D(const std::wstring& device_id,
|
| - content::GPUInfo* gpu_info) {
|
| - TRACE_EVENT0("gpu", "CollectDriverInfoD3D");
|
| -
|
| - // create device info for the display device
|
| - HDEVINFO device_info = SetupDiGetClassDevsW(
|
| - NULL, device_id.c_str(), NULL,
|
| - DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES);
|
| - if (device_info == INVALID_HANDLE_VALUE) {
|
| - LOG(ERROR) << "Creating device info failed";
|
| - return false;
|
| - }
|
| -
|
| - DWORD index = 0;
|
| - bool found = false;
|
| - SP_DEVINFO_DATA device_info_data;
|
| - device_info_data.cbSize = sizeof(device_info_data);
|
| - while (SetupDiEnumDeviceInfo(device_info, index++, &device_info_data)) {
|
| - WCHAR value[255];
|
| - if (SetupDiGetDeviceRegistryPropertyW(device_info,
|
| - &device_info_data,
|
| - SPDRP_DRIVER,
|
| - NULL,
|
| - reinterpret_cast<PBYTE>(value),
|
| - sizeof(value),
|
| - NULL)) {
|
| - HKEY key;
|
| - std::wstring driver_key = L"System\\CurrentControlSet\\Control\\Class\\";
|
| - driver_key += value;
|
| - LONG result = RegOpenKeyExW(
|
| - HKEY_LOCAL_MACHINE, driver_key.c_str(), 0, KEY_QUERY_VALUE, &key);
|
| - if (result == ERROR_SUCCESS) {
|
| - DWORD dwcb_data = sizeof(value);
|
| - std::string driver_version;
|
| - result = RegQueryValueExW(
|
| - key, L"DriverVersion", NULL, NULL,
|
| - reinterpret_cast<LPBYTE>(value), &dwcb_data);
|
| - if (result == ERROR_SUCCESS)
|
| - driver_version = WideToASCII(std::wstring(value));
|
| -
|
| - std::string driver_date;
|
| - dwcb_data = sizeof(value);
|
| - result = RegQueryValueExW(
|
| - key, L"DriverDate", NULL, NULL,
|
| - reinterpret_cast<LPBYTE>(value), &dwcb_data);
|
| - if (result == ERROR_SUCCESS)
|
| - driver_date = WideToASCII(std::wstring(value));
|
| -
|
| - std::string driver_vendor;
|
| - dwcb_data = sizeof(value);
|
| - result = RegQueryValueExW(
|
| - key, L"ProviderName", NULL, NULL,
|
| - reinterpret_cast<LPBYTE>(value), &dwcb_data);
|
| - if (result == ERROR_SUCCESS) {
|
| - driver_vendor = WideToASCII(std::wstring(value));
|
| - if (driver_vendor == "Advanced Micro Devices, Inc." ||
|
| - driver_vendor == "ATI Technologies Inc.") {
|
| - // We are conservative and assume that in the absence of a clear
|
| - // signal the videocard is assumed to be switchable. Additionally,
|
| - // some switchable systems with Intel GPUs aren't correctly
|
| - // detected, so always count them.
|
| - AMDVideoCardType amd_card_type = GetAMDVideocardType();
|
| - gpu_info->amd_switchable = (gpu_info->gpu.vendor_id == 0x8086) ||
|
| - (amd_card_type != STANDALONE);
|
| - }
|
| - }
|
| -
|
| - gpu_info->driver_vendor = driver_vendor;
|
| - gpu_info->driver_version = driver_version;
|
| - gpu_info->driver_date = driver_date;
|
| - found = true;
|
| - RegCloseKey(key);
|
| - break;
|
| - }
|
| - }
|
| - }
|
| - SetupDiDestroyDeviceInfoList(device_info);
|
| - return found;
|
| -}
|
| -
|
| -bool CollectContextGraphicsInfo(content::GPUInfo* gpu_info) {
|
| - TRACE_EVENT0("gpu", "CollectGraphicsInfo");
|
| -
|
| - DCHECK(gpu_info);
|
| -
|
| - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) {
|
| - std::string requested_implementation_name =
|
| - CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
|
| - if (requested_implementation_name == "swiftshader") {
|
| - gpu_info->software_rendering = true;
|
| - return false;
|
| - }
|
| - }
|
| -
|
| - if (!CollectGraphicsInfoGL(gpu_info))
|
| - return false;
|
| -
|
| - // ANGLE's renderer strings are of the form:
|
| - // ANGLE (<adapter_identifier> Direct3D<version> vs_x_x ps_x_x)
|
| - std::string direct3d_version;
|
| - int vertex_shader_major_version = 0;
|
| - int vertex_shader_minor_version = 0;
|
| - int pixel_shader_major_version = 0;
|
| - int pixel_shader_minor_version = 0;
|
| - if (RE2::FullMatch(gpu_info->gl_renderer,
|
| - "ANGLE \\(.*\\)") &&
|
| - RE2::PartialMatch(gpu_info->gl_renderer,
|
| - " Direct3D(\\w+)",
|
| - &direct3d_version) &&
|
| - RE2::PartialMatch(gpu_info->gl_renderer,
|
| - " vs_(\\d+)_(\\d+)",
|
| - &vertex_shader_major_version,
|
| - &vertex_shader_minor_version) &&
|
| - RE2::PartialMatch(gpu_info->gl_renderer,
|
| - " ps_(\\d+)_(\\d+)",
|
| - &pixel_shader_major_version,
|
| - &pixel_shader_minor_version)) {
|
| - gpu_info->can_lose_context = direct3d_version == "9";
|
| - gpu_info->vertex_shader_version =
|
| - base::StringPrintf("%d.%d",
|
| - vertex_shader_major_version,
|
| - vertex_shader_minor_version);
|
| - gpu_info->pixel_shader_version =
|
| - base::StringPrintf("%d.%d",
|
| - pixel_shader_major_version,
|
| - pixel_shader_minor_version);
|
| -
|
| - // DirectX diagnostics are collected asynchronously because it takes a
|
| - // couple of seconds. Do not mark gpu_info as complete until that is done.
|
| - gpu_info->finalized = false;
|
| - } else {
|
| - gpu_info->finalized = true;
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -GpuIDResult CollectGpuID(uint32* vendor_id, uint32* device_id) {
|
| - DCHECK(vendor_id && device_id);
|
| - *vendor_id = 0;
|
| - *device_id = 0;
|
| -
|
| - // Taken from http://developer.nvidia.com/object/device_ids.html
|
| - DISPLAY_DEVICE dd;
|
| - dd.cb = sizeof(DISPLAY_DEVICE);
|
| - std::wstring id;
|
| - for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
|
| - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
|
| - id = dd.DeviceID;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (id.length() > 20) {
|
| - int vendor = 0, device = 0;
|
| - std::wstring vendor_string = id.substr(8, 4);
|
| - std::wstring device_string = id.substr(17, 4);
|
| - base::HexStringToInt(WideToASCII(vendor_string), &vendor);
|
| - base::HexStringToInt(WideToASCII(device_string), &device);
|
| - *vendor_id = vendor;
|
| - *device_id = device;
|
| - return kGpuIDSuccess;
|
| - }
|
| - return kGpuIDFailure;
|
| -}
|
| -
|
| -bool CollectBasicGraphicsInfo(content::GPUInfo* gpu_info) {
|
| - TRACE_EVENT0("gpu", "CollectPreliminaryGraphicsInfo");
|
| -
|
| - DCHECK(gpu_info);
|
| -
|
| - gpu_info->performance_stats = RetrieveGpuPerformanceStatsWithHistograms();
|
| -
|
| - // nvd3d9wrap.dll is loaded into all processes when Optimus is enabled.
|
| - HMODULE nvd3d9wrap = GetModuleHandleW(L"nvd3d9wrap.dll");
|
| - gpu_info->optimus = nvd3d9wrap != NULL;
|
| -
|
| - gpu_info->lenovo_dcute = IsLenovoDCuteInstalled();
|
| -
|
| - gpu_info->display_link_version = DisplayLinkVersion();
|
| -
|
| - if (!gpu_info->display_link_version .IsValid()) {
|
| - UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
|
| - DISPLAY_LINK_NOT_INSTALLED,
|
| - DISPLAY_LINK_INSTALLATION_STATUS_MAX);
|
| - } else if (gpu_info->display_link_version.IsOlderThan("7.2")) {
|
| - UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
|
| - DISPLAY_LINK_7_1_OR_EARLIER,
|
| - DISPLAY_LINK_INSTALLATION_STATUS_MAX);
|
| - } else {
|
| - UMA_HISTOGRAM_ENUMERATION("GPU.DisplayLinkInstallationStatus",
|
| - DISPLAY_LINK_7_2_OR_LATER,
|
| - DISPLAY_LINK_INSTALLATION_STATUS_MAX);
|
| - }
|
| -
|
| - // Taken from http://developer.nvidia.com/object/device_ids.html
|
| - DISPLAY_DEVICE dd;
|
| - dd.cb = sizeof(DISPLAY_DEVICE);
|
| - std::wstring id;
|
| - for (int i = 0; EnumDisplayDevices(NULL, i, &dd, 0); ++i) {
|
| - if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE) {
|
| - id = dd.DeviceID;
|
| - break;
|
| - }
|
| - }
|
| -
|
| - if (id.length() <= 20)
|
| - return false;
|
| -
|
| - int vendor_id = 0, device_id = 0;
|
| - string16 vendor_id_string = id.substr(8, 4);
|
| - string16 device_id_string = id.substr(17, 4);
|
| - base::HexStringToInt(WideToASCII(vendor_id_string), &vendor_id);
|
| - base::HexStringToInt(WideToASCII(device_id_string), &device_id);
|
| - gpu_info->gpu.vendor_id = vendor_id;
|
| - gpu_info->gpu.device_id = device_id;
|
| - // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE.
|
| - if (!CollectDriverInfoD3D(id, gpu_info))
|
| - return false;
|
| -
|
| - // Collect basic information about supported D3D11 features. Delay for 45
|
| - // seconds so as not to regress performance tests.
|
| - if (D3D11ShouldWork(*gpu_info)) {
|
| - base::MessageLoop::current()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&CollectD3D11Support),
|
| - base::TimeDelta::FromSeconds(45));
|
| - }
|
| -
|
| - return true;
|
| -}
|
| -
|
| -bool CollectDriverInfoGL(content::GPUInfo* gpu_info) {
|
| - TRACE_EVENT0("gpu", "CollectDriverInfoGL");
|
| -
|
| - if (!gpu_info->driver_version.empty())
|
| - return true;
|
| -
|
| - std::string gl_version_string = gpu_info->gl_version_string;
|
| -
|
| - return RE2::PartialMatch(gl_version_string,
|
| - "([\\d\\.]+)$",
|
| - &gpu_info->driver_version);
|
| -}
|
| -
|
| -void MergeGPUInfo(content::GPUInfo* basic_gpu_info,
|
| - const content::GPUInfo& context_gpu_info) {
|
| - DCHECK(basic_gpu_info);
|
| -
|
| - if (context_gpu_info.software_rendering) {
|
| - basic_gpu_info->software_rendering = true;
|
| - return;
|
| - }
|
| -
|
| - MergeGPUInfoGL(basic_gpu_info, context_gpu_info);
|
| -
|
| - basic_gpu_info->dx_diagnostics = context_gpu_info.dx_diagnostics;
|
| -}
|
| -
|
| -} // namespace gpu_info_collector
|
|
|