diff options
author | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-12 01:00:41 +0000 |
---|---|---|
committer | jam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-12 01:00:41 +0000 |
commit | 623c0bd198a26b6609c7545a0cce0578dbad5316 (patch) | |
tree | e5cfac9d974797d95a8b4ee0aa0e4204826f089c /content/gpu/gpu_info_collector_win.cc | |
parent | 23716fb643383cb737e564d55234a7c2d58eba00 (diff) | |
download | chromium_src-623c0bd198a26b6609c7545a0cce0578dbad5316.zip chromium_src-623c0bd198a26b6609c7545a0cce0578dbad5316.tar.gz chromium_src-623c0bd198a26b6609c7545a0cce0578dbad5316.tar.bz2 |
Move chrome\gpu to content\gpu.
TBR=avi
Review URL: http://codereview.chromium.org/6684015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@77903 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/gpu/gpu_info_collector_win.cc')
-rw-r--r-- | content/gpu/gpu_info_collector_win.cc | 264 |
1 files changed, 264 insertions, 0 deletions
diff --git a/content/gpu/gpu_info_collector_win.cc b/content/gpu/gpu_info_collector_win.cc new file mode 100644 index 0000000..35ab7c0 --- /dev/null +++ b/content/gpu/gpu_info_collector_win.cc @@ -0,0 +1,264 @@ +// Copyright (c) 2011 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" + +#include <d3d9.h> +#include <setupapi.h> +#include <windows.h> + +#include "app/gfx/gl/gl_context_egl.h" +#include "app/gfx/gl/gl_implementation.h" +#include "base/file_path.h" +#include "base/logging.h" +#include "base/scoped_native_library.h" +#include "base/string_number_conversions.h" +#include "base/string_util.h" + +// ANGLE seems to require that main.h be included before any other ANGLE header. +#include "libEGL/main.h" +#include "libEGL/Display.h" + +// Setup API functions +typedef HDEVINFO (WINAPI*SetupDiGetClassDevsWFunc)( + CONST GUID *ClassGuid, + PCWSTR Enumerator, + HWND hwndParent, + DWORD Flags +); +typedef BOOL (WINAPI*SetupDiEnumDeviceInfoFunc)( + HDEVINFO DeviceInfoSet, + DWORD MemberIndex, + PSP_DEVINFO_DATA DeviceInfoData +); +typedef BOOL (WINAPI*SetupDiGetDeviceRegistryPropertyWFunc)( + HDEVINFO DeviceInfoSet, + PSP_DEVINFO_DATA DeviceInfoData, + DWORD Property, + PDWORD PropertyRegDataType, + PBYTE PropertyBuffer, + DWORD PropertyBufferSize, + PDWORD RequiredSize +); +typedef BOOL (WINAPI*SetupDiDestroyDeviceInfoListFunc)( + HDEVINFO DeviceInfoSet +); + +namespace gpu_info_collector { + +bool CollectGraphicsInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { + gpu_info->level = GPUInfo::kComplete; + return CollectGraphicsInfoGL(gpu_info); + } + + // Set to partial now in case this function returns false below. + gpu_info->level = GPUInfo::kPartial; + + // TODO(zmo): the following code only works if running on top of ANGLE. + // Need to handle the case when running on top of real EGL/GLES2 drivers. + + egl::Display* display = static_cast<egl::Display*>( + gfx::BaseEGLContext::GetDisplay()); + if (!display) { + LOG(ERROR) << "gfx::BaseEGLContext::GetDisplay() failed"; + return false; + } + + IDirect3DDevice9* device = display->getDevice(); + if (!device) { + LOG(ERROR) << "display->getDevice() failed"; + return false; + } + + IDirect3D9* d3d = NULL; + if (FAILED(device->GetDirect3D(&d3d))) { + LOG(ERROR) << "device->GetDirect3D(&d3d) failed"; + return false; + } + + if (!CollectGraphicsInfoD3D(d3d, gpu_info)) + return false; + + // DirectX diagnostics are collected asynchronously because it takes a + // couple of seconds. Do not mark gpu_info as complete until that is done. + return true; +} + +bool CollectPreliminaryGraphicsInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + gpu_info->level = GPUInfo::kPreliminary; + + bool rt = true; + if (!CollectVideoCardInfo(gpu_info)) + rt = false; + + return rt; +} + +bool CollectGraphicsInfoD3D(IDirect3D9* d3d, GPUInfo* gpu_info) { + DCHECK(d3d); + DCHECK(gpu_info); + + bool succeed = CollectVideoCardInfo(gpu_info); + + // Get version information + D3DCAPS9 d3d_caps; + if (d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + &d3d_caps) == D3D_OK) { + gpu_info->pixel_shader_version = d3d_caps.PixelShaderVersion; + gpu_info->vertex_shader_version = d3d_caps.VertexShaderVersion; + } else { + LOG(ERROR) << "d3d->GetDeviceCaps() failed"; + succeed = false; + } + + // Get can_lose_context + bool can_lose_context = false; + IDirect3D9Ex* d3dex = NULL; + if (SUCCEEDED(d3d->QueryInterface(__uuidof(IDirect3D9Ex), + reinterpret_cast<void**>(&d3dex)))) { + d3dex->Release(); + } else { + can_lose_context = true; + } + gpu_info->can_lose_context = can_lose_context; + + d3d->Release(); + return true; +} + +bool CollectVideoCardInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + // Taken from http://developer.nvidia.com/object/device_ids.html + DISPLAY_DEVICE dd; + dd.cb = sizeof(DISPLAY_DEVICE); + int i = 0; + 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_id = 0, device_id = 0; + std::wstring vendor_id_string = id.substr(8, 4); + std::wstring 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->vendor_id = vendor_id; + gpu_info->device_id = device_id; + // TODO(zmo): we only need to call CollectDriverInfoD3D() if we use ANGLE. + return CollectDriverInfoD3D(id, gpu_info); + } + return false; +} + +bool CollectDriverInfoD3D(const std::wstring& device_id, GPUInfo* gpu_info) { + HMODULE lib_setupapi = LoadLibraryW(L"setupapi.dll"); + if (!lib_setupapi) { + LOG(ERROR) << "Open setupapi.dll failed"; + return false; + } + SetupDiGetClassDevsWFunc fp_get_class_devs = + reinterpret_cast<SetupDiGetClassDevsWFunc>( + GetProcAddress(lib_setupapi, "SetupDiGetClassDevsW")); + SetupDiEnumDeviceInfoFunc fp_enum_device_info = + reinterpret_cast<SetupDiEnumDeviceInfoFunc>( + GetProcAddress(lib_setupapi, "SetupDiEnumDeviceInfo")); + SetupDiGetDeviceRegistryPropertyWFunc fp_get_device_registry_property = + reinterpret_cast<SetupDiGetDeviceRegistryPropertyWFunc>( + GetProcAddress(lib_setupapi, "SetupDiGetDeviceRegistryPropertyW")); + SetupDiDestroyDeviceInfoListFunc fp_destroy_device_info_list = + reinterpret_cast<SetupDiDestroyDeviceInfoListFunc>( + GetProcAddress(lib_setupapi, "SetupDiDestroyDeviceInfoList")); + if (!fp_get_class_devs || !fp_enum_device_info || + !fp_get_device_registry_property || !fp_destroy_device_info_list) { + FreeLibrary(lib_setupapi); + LOG(ERROR) << "Retrieve setupapi.dll functions failed"; + return false; + } + + // create device info for the display device + HDEVINFO device_info = fp_get_class_devs( + NULL, device_id.c_str(), NULL, + DIGCF_PRESENT | DIGCF_PROFILE | DIGCF_ALLCLASSES); + if (device_info == INVALID_HANDLE_VALUE) { + FreeLibrary(lib_setupapi); + 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 (fp_enum_device_info(device_info, index++, &device_info_data)) { + WCHAR value[255]; + if (fp_get_device_registry_property(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)); + + gpu_info->driver_version = driver_version; + gpu_info->driver_date = driver_date; + found = true; + RegCloseKey(key); + break; + } + } + } + fp_destroy_device_info_list(device_info); + FreeLibrary(lib_setupapi); + return found; +} + +bool CollectDriverInfoGL(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + std::string gl_version_string = gpu_info->gl_version_string; + + // TODO(zmo): We assume the driver version is in the end of GL_VERSION + // string. Need to verify if it is true for majority drivers. + + size_t pos = gl_version_string.find_last_not_of("0123456789."); + if (pos != std::string::npos && pos < gl_version_string.length() - 1) { + gpu_info->driver_version = gl_version_string.substr(pos + 1); + return true; + } + return false; +} + +} // namespace gpu_info_collector |