diff options
author | zmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-21 00:27:53 +0000 |
---|---|---|
committer | zmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-21 00:27:53 +0000 |
commit | 7004d7ebec6cd4de175d8f894c2a0c58fb6f41c8 (patch) | |
tree | 5efa0e86cd64c61420909af28d43211d609ebf0f /chrome/gpu | |
parent | c7a827e9d91099bae12379f92467e29a8d7ffaab (diff) | |
download | chromium_src-7004d7ebec6cd4de175d8f894c2a0c58fb6f41c8.zip chromium_src-7004d7ebec6cd4de175d8f894c2a0c58fb6f41c8.tar.gz chromium_src-7004d7ebec6cd4de175d8f894c2a0c58fb6f41c8.tar.bz2 |
Refactor and improve gpu_info_collector: collect information on linux;
collect extra information (driver_vendor, gl_renderer, etc.) on Mac/linux.
Note that this CL takes some code from rlp's long outstandingCL (with her
permission).
BUG=49579
TEST=unittest
Review URL: http://codereview.chromium.org/6346007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72055 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/gpu')
-rw-r--r-- | chrome/gpu/gpu_info_collector.cc | 119 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector.h | 15 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector_linux.cc | 111 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector_mac.mm | 160 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector_unittest.cc | 155 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_collector_win.cc | 123 | ||||
-rw-r--r-- | chrome/gpu/gpu_info_unittest_win.cc | 4 |
7 files changed, 440 insertions, 247 deletions
diff --git a/chrome/gpu/gpu_info_collector.cc b/chrome/gpu/gpu_info_collector.cc new file mode 100644 index 0000000..bb55eaf --- /dev/null +++ b/chrome/gpu/gpu_info_collector.cc @@ -0,0 +1,119 @@ +// Copyright (c) 2006-2010 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 "chrome/gpu/gpu_info_collector.h" + +#include <string> +#include <vector> + +#include "app/gfx/gl/gl_bindings.h" +#include "app/gfx/gl/gl_context.h" +#include "base/logging.h" +#include "base/string_number_conversions.h" +#include "base/string_piece.h" +#include "base/string_split.h" + +namespace { + +// This creates an offscreen GL context for gl queries. Returned GLContext +// should be deleted in FinalizeGLContext. +gfx::GLContext* InitializeGLContext() { + if (!gfx::GLContext::InitializeOneOff()) { + LOG(ERROR) << "gfx::GLContext::InitializeOneOff() failed"; + return NULL; + } + gfx::GLContext* context = gfx::GLContext::CreateOffscreenGLContext(NULL); + if (context == NULL) { + LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLContext(NULL) failed"; + return NULL; + } + if (!context->MakeCurrent()) { + LOG(ERROR) << "gfx::GLContext::MakeCurrent() failed"; + context->Destroy(); + delete context; + return NULL; + } + return context; +} + +// This destroy and delete the GL context. +void FinalizeGLContext(gfx::GLContext** context) { + DCHECK(context); + if (*context) { + (*context)->Destroy(); + delete *context; + *context = NULL; + } +} + +std::string GetGLString(unsigned int pname) { + const char* gl_string = + reinterpret_cast<const char*>(glGetString(pname)); + if (gl_string) + return std::string(gl_string); + return ""; +} + +uint32 GetVersionNumberFromString(const std::string& version_string) { + int major = 0, minor = 0; + size_t begin = version_string.find_first_of("0123456789"); + if (begin != std::string::npos) { + size_t end = version_string.find_first_not_of("01234567890.", begin); + std::string sub_string; + if (end != std::string::npos) + sub_string = version_string.substr(begin, end - begin); + else + sub_string = version_string.substr(begin); + std::vector<std::string> pieces; + base::SplitString(sub_string, '.', &pieces); + if (pieces.size() >= 2) { + base::StringToInt(pieces[0], &major); + base::StringToInt(pieces[1], &minor); + } + } + return ((major << 8) + minor); +} + +} // namespace anonymous + +namespace gpu_info_collector { + +bool CollectGraphicsInfoGL(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + gfx::GLContext* context = InitializeGLContext(); + if (context == NULL) + return false; + + gpu_info->SetGLRenderer(GetGLString(GL_RENDERER)); + gpu_info->SetGLVendor(GetGLString(GL_VENDOR)); + gpu_info->SetGLVersionString(GetGLString(GL_VERSION)); + + bool validGLVersionInfo = CollectGLVersionInfo(gpu_info); + bool validVideoCardInfo = CollectVideoCardInfo(gpu_info); + bool validDriverInfo = CollectDriverInfo(gpu_info); + + FinalizeGLContext(&context); + + return (validGLVersionInfo && validVideoCardInfo && validDriverInfo); +} + +bool CollectGLVersionInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + std::string gl_version_string = gpu_info->gl_version_string(); + std::string glsl_version_string = + GetGLString(GL_SHADING_LANGUAGE_VERSION); + + uint32 gl_version = GetVersionNumberFromString(gl_version_string); + gpu_info->SetGLVersion(gl_version); + + uint32 glsl_version = GetVersionNumberFromString(glsl_version_string); + gpu_info->SetShaderVersion(glsl_version, glsl_version); + + return true; +} + +} // namespace gpu_info_collector + diff --git a/chrome/gpu/gpu_info_collector.h b/chrome/gpu/gpu_info_collector.h index ea11093..577d197 100644 --- a/chrome/gpu/gpu_info_collector.h +++ b/chrome/gpu/gpu_info_collector.h @@ -27,13 +27,22 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info); // A D3D argument is passed in for testing purposes bool CollectGraphicsInfoD3D(IDirect3D9* d3d, GPUInfo* gpu_info); -// The GL version of collecting information -bool CollectGraphicsInfoGL(GPUInfo* gpu_info); - // Collect the DirectX Disagnostics information about the attached displays. bool GetDxDiagnostics(DxDiagNode* output); #endif +// All platforms have a GL version for collecting information +bool CollectGraphicsInfoGL(GPUInfo* gpu_info); + +// Collect GL and Shading language version information +bool CollectGLVersionInfo(GPUInfo* gpu_info); + +// Platform specific method for collecting vendor and device ids +bool CollectVideoCardInfo(GPUInfo* gpu_info); + +// Each platform stores the driver version on the GL_VERSION string differently +bool CollectDriverInfo(GPUInfo* gpu_info); + } // namespace gpu_info_collector #endif // CHROME_GPU_GPU_INFO_COLLECTOR_H__ diff --git a/chrome/gpu/gpu_info_collector_linux.cc b/chrome/gpu/gpu_info_collector_linux.cc index 90bdc95..617c28b 100644 --- a/chrome/gpu/gpu_info_collector_linux.cc +++ b/chrome/gpu/gpu_info_collector_linux.cc @@ -12,6 +12,8 @@ #include "app/gfx/gl/gl_implementation.h" #include "base/logging.h" #include "base/scoped_ptr.h" +#include "base/string_piece.h" +#include "base/string_split.h" #include "base/string_util.h" namespace { @@ -113,40 +115,11 @@ PciInterface* InitializeLibPci(const char* lib_name) { } // This close the dynamically opened libpci and delete the interface. -void FinalizeLibPci(PciInterface*& interface) { - DCHECK(interface != NULL && interface->lib_handle != NULL); - dlclose(interface->lib_handle); - delete interface; - interface = NULL; -} - -// This creates an offscreen GL context for gl queries. Returned GLContext -// should be deleted in FinalizeGLContext. -gfx::GLContext* InitializeGLContext() { - if (!gfx::GLContext::InitializeOneOff()) { - LOG(ERROR) << "gfx::GLContext::InitializeOneOff() failed"; - return NULL; - } - gfx::GLContext* context = gfx::GLContext::CreateOffscreenGLContext(NULL); - if (context == NULL) { - LOG(ERROR) << "gfx::GLContext::CreateOffscreenGLContext(NULL) failed"; - return NULL; - } - if (!context->MakeCurrent()) { - LOG(ERROR) << "gfx::GLContext::MakeCurrent() failed"; - context->Destroy(); - delete context; - return NULL; - } - return context; -} - -// This destroy and delete the GL context. -void FinalizeGLContext(gfx::GLContext*& context) { - DCHECK(context != NULL); - context->Destroy(); - delete context; - context = NULL; +void FinalizeLibPci(PciInterface** interface) { + DCHECK(interface && *interface && (*interface)->lib_handle); + dlclose((*interface)->lib_handle); + delete (*interface); + *interface = NULL; } } // namespace anonymous @@ -154,25 +127,23 @@ void FinalizeGLContext(gfx::GLContext*& context) { namespace gpu_info_collector { bool CollectGraphicsInfo(GPUInfo* gpu_info) { - gfx::GLContext* context = InitializeGLContext(); - if (context == NULL) - return false; + DCHECK(gpu_info); + + // TODO(zmo): need to consider the case where we are running on top of + // desktop GL and GL_ARB_robustness extension is available. + gpu_info->SetCanLoseContext( + gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2); + gpu_info->SetProgress(GPUInfo::kComplete); + return CollectGraphicsInfoGL(gpu_info); +} - // TODO(zmo): collect driver version, pixel shader version, vertex shader - // version, and gl version. - std::wstring driver_version = L""; - uint32 pixel_shader_version = 0; - uint32 vertex_shader_version = 0; - uint32 gl_version = 0; - bool can_lose_context = - (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2); +bool CollectVideoCardInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); // TODO(zmo): be more flexible about library name. PciInterface* interface = InitializeLibPci("libpci.so.3"); - if (interface == NULL) { - FinalizeGLContext(context); + if (interface == NULL) return false; - } PciAccess* access = (interface->pci_alloc)(); DCHECK(access != NULL); @@ -183,6 +154,7 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) { for (PciDevice* device = access->device_list; device != NULL; device = device->next) { (interface->pci_fill_info)(device, 33); // Fill the IDs and class fields. + // TODO(zmo): there might be other classes that qualify as display devices. if (device->device_class == 0x0300) { // Device class is DISPLAY_VGA. gpu_list.push_back(device); } @@ -192,10 +164,8 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) { } else { // If more than one graphics card are identified, find the one that matches // gl VENDOR and RENDERER info. - std::string gl_vendor_string = - reinterpret_cast<const char*>(glGetString(GL_VENDOR)); - std::string gl_renderer_string = - reinterpret_cast<const char*>(glGetString(GL_RENDERER)); + std::string gl_vendor_string = gpu_info->gl_vendor(); + std::string gl_renderer_string = gpu_info->gl_renderer(); const int buffer_size = 255; scoped_array<char> buffer(new char[buffer_size]); std::vector<PciDevice*> candidates; @@ -240,20 +210,33 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) { if (gpu_active == NULL && candidates.size() == 1) gpu_active = candidates[0]; } - if (gpu_active != NULL) { - gpu_info->SetGraphicsInfo(gpu_active->vendor_id, - gpu_active->device_id, - driver_version, - pixel_shader_version, - vertex_shader_version, - gl_version, - can_lose_context); - gpu_info->SetProgress(GPUInfo::kComplete); - } + if (gpu_active != NULL) + gpu_info->SetVideoCardInfo(gpu_active->vendor_id, gpu_active->device_id); (interface->pci_cleanup)(access); - FinalizeLibPci(interface); - FinalizeGLContext(context); + FinalizeLibPci(&interface); return (gpu_active != NULL); } +bool CollectDriverInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); + + std::string gl_version_string = gpu_info->gl_version_string(); + std::vector<std::string> pieces; + base::SplitStringAlongWhitespace(gl_version_string, &pieces); + // In linux, the gl version string might be in the format of + // GLVersion DriverVendor DriverVersion + if (pieces.size() < 3) + return false; + + std::string driver_version = pieces[2]; + size_t pos = driver_version.find_first_not_of("0123456789."); + if (pos == 0) + return false; + if (pos != std::string::npos) + driver_version = driver_version.substr(0, pos); + + gpu_info->SetDriverInfo(pieces[1], driver_version); + return true; +} + } // namespace gpu_info_collector diff --git a/chrome/gpu/gpu_info_collector_mac.mm b/chrome/gpu/gpu_info_collector_mac.mm index 24c809d..a904164 100644 --- a/chrome/gpu/gpu_info_collector_mac.mm +++ b/chrome/gpu/gpu_info_collector_mac.mm @@ -16,10 +16,10 @@ #import <Foundation/Foundation.h> #import <IOKit/IOKitLib.h> -namespace gpu_info_collector { +namespace { -static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort, - CFStringRef propertyName) { +CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort, + CFStringRef propertyName) { return IORegistryEntrySearchCFProperty(dspPort, kIOServicePlane, propertyName, @@ -28,145 +28,65 @@ static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort, kIORegistryIterateParents); } -static void CFReleaseIf(CFTypeRef type_ref) { - if (type_ref) - CFRelease(type_ref); -} +UInt32 IntValueOfCFData(CFDataRef data_ref) { + DCHECK(data_ref); -static UInt32 IntValueOfCFData(CFDataRef data_ref) { UInt32 value = 0; - - if (data_ref) { - const UInt32 *value_pointer = - reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref)); - if (value_pointer != NULL) - value = *value_pointer; - } - + const UInt32* value_pointer = + reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref)); + if (value_pointer != NULL) + value = *value_pointer; return value; } -static void CollectVideoCardInfo(CGDirectDisplayID displayID, - int *vendorID, - int *deviceID) { - io_registry_entry_t dspPort = CGDisplayIOServicePort(displayID); +} // namespace anonymous - CFTypeRef vendorIDRef = SearchPortForProperty(dspPort, CFSTR("vendor-id")); - if (vendorID) *vendorID = IntValueOfCFData((CFDataRef)vendorIDRef); +namespace gpu_info_collector { - CFTypeRef deviceIDRef = SearchPortForProperty(dspPort, CFSTR("device-id")); - if (deviceID) *deviceID = IntValueOfCFData((CFDataRef)deviceIDRef); +bool CollectGraphicsInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); - CFReleaseIf(vendorIDRef); - CFReleaseIf(deviceIDRef); + gpu_info->SetCanLoseContext( + gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2); + gpu_info->SetProgress(GPUInfo::kComplete); + return CollectGraphicsInfoGL(gpu_info); } -// Return a pointer to the last character with value c in string s. -// Returns NULL if c is not found. -static char* FindLastChar(char *s, char c) { - char *s_found = NULL; +bool CollectVideoCardInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); - while (*s != '\0') { - if (*s == c) - s_found = s; - s++; - } - return s_found; -} + if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) + return false; -// Gets the numeric HLSL version. -// You pass it the current GL major version, to give it a hint where to look. -static int GetShaderNumericVersion(int gl_major_version) { - int gl_hlsl_major = 0, gl_hlsl_minor = 0; - int shader_version = 0; - - if (gl_major_version == 1) { - const char *gl_extensions_string = (const char*)glGetString(GL_EXTENSIONS); - if (gl_extensions_string && - strstr(gl_extensions_string, "GL_ARB_shading_language_100")) { - gl_hlsl_major = 1; - gl_hlsl_minor = 0; - } - } else if (gl_major_version > 1) { - const char *glsl_version_string = - (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); - if (glsl_version_string) - sscanf(glsl_version_string, "%u.%u", &gl_hlsl_major, &gl_hlsl_minor); + UInt32 vendor_id = 0, device_id = 0; + io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay); + CFTypeRef vendor_id_ref = SearchPortForProperty(dsp_port, CFSTR("vendor-id")); + if (vendor_id_ref) { + vendor_id = IntValueOfCFData((CFDataRef)vendor_id_ref); + CFRelease(vendor_id_ref); + } + CFTypeRef device_id_ref = SearchPortForProperty(dsp_port, CFSTR("device-id")); + if (device_id_ref) { + device_id = IntValueOfCFData((CFDataRef)device_id_ref); + CFRelease(device_id_ref); } - shader_version = (gl_hlsl_major << 8) | (gl_hlsl_minor & 0xFF); - return shader_version; -} - - -static std::wstring CStringToWString(const char *s) { - base::StringPiece sp(s); - return base::SysUTF8ToWide(sp); + gpu_info->SetVideoCardInfo(vendor_id, device_id); + return true; } - -// Returns the driver version string as its value, and also returns the -// gl version and shader language version by setting the arguments pointed to. -static std::wstring CollectGLInfo(int *out_gl_version, - int *out_shader_version) { - int gl_major = 0, gl_minor = 0; - char *gl_version_string = NULL; - std::wstring driver_version; - - gl_version_string = (char*)glGetString(GL_VERSION); - sscanf(gl_version_string, "%u.%u", &gl_major, &gl_minor); - - *out_gl_version = (gl_major << 8) | (gl_minor & 0xFF); - *out_shader_version = GetShaderNumericVersion(gl_major); +bool CollectDriverInfo(GPUInfo* gpu_info) { + DCHECK(gpu_info); // Extract the OpenGL driver version string from the GL_VERSION string. // Mac OpenGL drivers have the driver version // at the end of the gl version string preceded by a dash. // Use some jiggery-pokery to turn that utf8 string into a std::wstring. - char *s = FindLastChar(gl_version_string, '-'); - if (s) - driver_version = CStringToWString(s + 1); - - return driver_version; -} - - -bool CollectGraphicsInfo(GPUInfo* gpu_info) { - if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) + std::string gl_version_string = gpu_info->gl_version_string(); + size_t pos = gl_version_string.find_last_of('-'); + if (pos == std::string::npos) return false; - // Video Card data. - int vendor_id = 0, device_id = 0; - // OpenGL data. - std::wstring driver_version = L""; - int gl_version = 0, shader_version = 0; - - CollectVideoCardInfo(kCGDirectMainDisplay, &vendor_id, &device_id); - - // Temporarily make an offscreen GL context so we can gather info from it. - if (gfx::GLContext::InitializeOneOff()) { - scoped_ptr<gfx::GLContext> ctx( - gfx::GLContext::CreateOffscreenGLContext(NULL)); - if (ctx.get()) { - if (ctx->MakeCurrent()) { - driver_version = CollectGLInfo(&gl_version, &shader_version); - } - ctx->Destroy(); - } - } - - - // OpenGL doesn't have separate versions for pixel and vertex shader - // languages, so we just pass the shader_version for both. - gpu_info->SetGraphicsInfo(vendor_id, - device_id, - driver_version, - shader_version, - shader_version, - gl_version, - false); - - gpu_info->SetProgress(GPUInfo::kComplete); - + gpu_info->SetDriverInfo("", gl_version_string.substr(pos + 1)); return true; } diff --git a/chrome/gpu/gpu_info_collector_unittest.cc b/chrome/gpu/gpu_info_collector_unittest.cc new file mode 100644 index 0000000..1d0156f --- /dev/null +++ b/chrome/gpu/gpu_info_collector_unittest.cc @@ -0,0 +1,155 @@ +// 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 "app/gfx/gl/gl_implementation.h" +#include "base/scoped_ptr.h" +#include "chrome/common/gpu_info.h" +#include "chrome/gpu/gpu_info_collector.h" +#include "gpu/command_buffer/common/gl_mock.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::gfx::MockGLInterface; +using ::testing::Return; + +class GPUInfoCollectorTest : public testing::Test { + public: + GPUInfoCollectorTest() {} + virtual ~GPUInfoCollectorTest() { } + + void SetUp() { + gfx::InitializeGLBindings(gfx::kGLImplementationMockGL); + gl_.reset(new ::testing::StrictMock< ::gfx::MockGLInterface>()); + ::gfx::GLInterface::SetGLInterface(gl_.get()); +#if defined(OS_WIN) + const uint32 vendor_id = 0x10de; + const uint32 device_id = 0x0658; + const char* driver_vendor = ""; // not implemented + const char* driver_version = ""; + const uint32 shader_version = 0x00000128; + const uint32 gl_version = 0x00000301; + const char* gl_renderer = "Quadro FX 380/PCI/SSE2"; + const char* gl_vendor = "NVIDIA Corporation"; + const char* gl_version_string = "3.1.0"; + const char* gl_shading_language_version = "1.40 NVIDIA via Cg compiler"; +#elif defined(OS_MACOSX) + const uint32 vendor_id = 0x10de; + const uint32 device_id = 0x0640; + const char* driver_vendor = ""; // not implemented + const char* driver_version = "1.6.18"; + const uint32 shader_version = 0x00000114; + const uint32 gl_version = 0x00000201; + const char* gl_renderer = "NVIDIA GeForce GT 120 OpenGL Engine"; + const char* gl_vendor = "NVIDIA Corporation"; + const char* gl_version_string = "2.1 NVIDIA-1.6.18"; + const char* gl_shading_language_version = "1.20 "; +#else // defined (OS_LINUX) + const uint32 vendor_id = 0x10de; + const uint32 device_id = 0x0658; + const char* driver_vendor = "NVIDIA"; + const char* driver_version = "195.36.24"; + const uint32 shader_version = 0x00000132; + const uint32 gl_version = 0x00000302; + const char* gl_renderer = "Quadro FX 380/PCI/SSE2"; + const char* gl_vendor = "NVIDIA Corporation"; + const char* gl_version_string = "3.2.0 NVIDIA 195.36.24"; + const char* gl_shading_language_version = "1.50 NVIDIA via Cg compiler"; +#endif + test_values_.SetVideoCardInfo(vendor_id, device_id); + test_values_.SetDriverInfo(driver_vendor, driver_version); + test_values_.SetShaderVersion(shader_version, shader_version); + test_values_.SetGLVersion(gl_version); + test_values_.SetGLRenderer(gl_renderer); + test_values_.SetGLVendor(gl_vendor); + test_values_.SetGLVersionString(gl_version_string); + test_values_.SetCanLoseContext(false); + + EXPECT_CALL(*gl_, GetString(GL_EXTENSIONS)) + .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>( + "GL_OES_packed_depth_stencil GL_EXT_texture_format_BGRA8888 " + "GL_EXT_read_format_bgra"))); + EXPECT_CALL(*gl_, GetString(GL_SHADING_LANGUAGE_VERSION)) + .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>( + gl_shading_language_version))); + EXPECT_CALL(*gl_, GetString(GL_VERSION)) + .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>( + gl_version_string))); + EXPECT_CALL(*gl_, GetString(GL_VENDOR)) + .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>( + gl_vendor))); + EXPECT_CALL(*gl_, GetString(GL_RENDERER)) + .WillRepeatedly(Return(reinterpret_cast<const GLubyte*>( + gl_renderer))); + } + + void TearDown() { + ::gfx::GLInterface::SetGLInterface(NULL); + gl_.reset(); + } + + public: + // Use StrictMock to make 100% sure we know how GL will be called. + scoped_ptr< ::testing::StrictMock< ::gfx::MockGLInterface> > gl_; + GPUInfo test_values_; +}; + +// TODO(rlp): Test the vendor and device id collection if deemed necessary as +// it involves several complicated mocks for each platform. + +TEST_F(GPUInfoCollectorTest, DriverVendorGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + std::string driver_vendor = gpu_info.driver_vendor(); + EXPECT_EQ(test_values_.driver_vendor(), driver_vendor); +} + +TEST_F(GPUInfoCollectorTest, DriverVersionGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + std::string driver_version = gpu_info.driver_version(); + EXPECT_EQ(test_values_.driver_version(), driver_version); +} + +TEST_F(GPUInfoCollectorTest, PixelShaderVersionGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + uint32 ps_version = gpu_info.pixel_shader_version(); + EXPECT_EQ(test_values_.pixel_shader_version(), ps_version); +} + +TEST_F(GPUInfoCollectorTest, VertexShaderVersionGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + uint32 vs_version = gpu_info.vertex_shader_version(); + EXPECT_EQ(test_values_.vertex_shader_version(), vs_version); +} + +TEST_F(GPUInfoCollectorTest, GLVersionGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + uint32 gl_version = gpu_info.gl_version(); + EXPECT_EQ(test_values_.gl_version(), gl_version); +} + +TEST_F(GPUInfoCollectorTest, GLVersionStringGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + std::string gl_version_string = gpu_info.gl_version_string(); + EXPECT_EQ(test_values_.gl_version_string(), gl_version_string); +} + +TEST_F(GPUInfoCollectorTest, GLRendererGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + std::string gl_renderer = gpu_info.gl_renderer(); + EXPECT_EQ(test_values_.gl_renderer(), gl_renderer); +} + +TEST_F(GPUInfoCollectorTest, GLVendorGL) { + GPUInfo gpu_info; + gpu_info_collector::CollectGraphicsInfoGL(&gpu_info); + std::string gl_vendor = gpu_info.gl_vendor(); + EXPECT_EQ(test_values_.gl_vendor(), gl_vendor); +} + diff --git a/chrome/gpu/gpu_info_collector_win.cc b/chrome/gpu/gpu_info_collector_win.cc index f1ed1f8..39efdbef 100644 --- a/chrome/gpu/gpu_info_collector_win.cc +++ b/chrome/gpu/gpu_info_collector_win.cc @@ -11,6 +11,7 @@ #include "app/gfx/gl/gl_implementation.h" #include "base/file_path.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. @@ -20,9 +21,15 @@ namespace gpu_info_collector { bool CollectGraphicsInfo(GPUInfo* gpu_info) { - // TODO: collect OpenGL info if not using ANGLE? - if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) - return true; + DCHECK(gpu_info); + + if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { + gpu_info->SetProgress(GPUInfo::kComplete); + return CollectGraphicsInfoGL(gpu_info); + } + + // 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()); @@ -43,7 +50,6 @@ bool CollectGraphicsInfo(GPUInfo* gpu_info) { // DirectX diagnostics are collected asynchronously because it takes a // couple of seconds. Do not mark as complete until that is done. gpu_info->SetProgress(GPUInfo::kPartial); - return true; } @@ -51,35 +57,39 @@ bool CollectGraphicsInfoD3D(IDirect3D9* d3d, GPUInfo* gpu_info) { DCHECK(d3d); DCHECK(gpu_info); - // Get device information + bool succeed = true; + + // Get device/driver information D3DADAPTER_IDENTIFIER9 identifier; - HRESULT hr = d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier); - if (hr != D3D_OK) { - d3d->Release(); - return false; + if (d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &identifier) == D3D_OK) { + gpu_info->SetVideoCardInfo(identifier.VendorId, identifier.DeviceId); + + uint32 driver_major_version_hi = HIWORD(identifier.DriverVersion.HighPart); + uint32 driver_major_version_lo = LOWORD(identifier.DriverVersion.HighPart); + uint32 driver_minor_version_hi = HIWORD(identifier.DriverVersion.LowPart); + uint32 driver_minor_version_lo = LOWORD(identifier.DriverVersion.LowPart); + std::string driver_version = StringPrintf("%d.%d.%d.%d", + driver_major_version_hi, + driver_major_version_lo, + driver_minor_version_hi, + driver_minor_version_lo); + gpu_info->SetDriverInfo("", driver_version); + } else { + succeed = false; } - uint32 vendor_id = identifier.VendorId; - uint32 device_id = identifier.DeviceId; // Get version information D3DCAPS9 d3d_caps; - HRESULT caps_result = d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, - D3DDEVTYPE_HAL, - &d3d_caps); - if (caps_result != D3D_OK) { - d3d->Release(); - return false; + if (d3d->GetDeviceCaps(D3DADAPTER_DEFAULT, + D3DDEVTYPE_HAL, + &d3d_caps) == D3D_OK) { + gpu_info->SetShaderVersion(d3d_caps.PixelShaderVersion, + d3d_caps.VertexShaderVersion); + } else { + succeed = false; } - uint32 driver_major_version_hi = HIWORD(identifier.DriverVersion.HighPart); - uint32 driver_major_version_lo = LOWORD(identifier.DriverVersion.HighPart); - uint32 driver_minor_version_hi = HIWORD(identifier.DriverVersion.LowPart); - uint32 driver_minor_version_lo = LOWORD(identifier.DriverVersion.LowPart); - std::wstring driver_version = StringPrintf(L"%d.%d.%d.%d", - driver_major_version_hi, - driver_major_version_lo, - driver_minor_version_hi, - driver_minor_version_lo); + // Get can_lose_context bool can_lose_context = false; IDirect3D9Ex* d3dex = NULL; if (SUCCEEDED(d3d->QueryInterface(__uuidof(IDirect3D9Ex), @@ -88,24 +98,15 @@ bool CollectGraphicsInfoD3D(IDirect3D9* d3d, GPUInfo* gpu_info) { } else { can_lose_context = true; } + gpu_info->SetCanLoseContext(can_lose_context); d3d->Release(); - - // Get shader versions - uint32 pixel_shader_version = d3d_caps.PixelShaderVersion; - uint32 vertex_shader_version = d3d_caps.VertexShaderVersion; - - gpu_info->SetGraphicsInfo(vendor_id, - device_id, - driver_version, - pixel_shader_version, - vertex_shader_version, - 0, - can_lose_context); return true; } -bool CollectGraphicsInfoGL(GPUInfo* gpu_info) { +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); @@ -117,27 +118,33 @@ bool CollectGraphicsInfoGL(GPUInfo* gpu_info) { break; } } - if (id.empty()) { - return false; + + 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->SetVideoCardInfo(vendor_id, device_id); + return true; } - uint32 vendor_id; - uint32 device_id; - std::wstring vendorid = id.substr(8, 4); - std::wstring deviceid = id.substr(17, 4); - swscanf_s(vendorid.c_str(), L"%x", &vendor_id); - swscanf_s(deviceid.c_str(), L"%x", &device_id); - - std::wstring driver_version = L""; - uint32 pixel_shader_version = 0; - uint32 vertex_shader_version = 0; - gpu_info->SetGraphicsInfo(vendor_id, device_id, driver_version, - pixel_shader_version, - vertex_shader_version, - 0, // GL version of 0 indicates D3D - false); - return true; + return false; +} - // TODO(rlp): Add driver and pixel versions +bool CollectDriverInfo(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->SetDriverInfo("", gl_version_string.substr(pos + 1)); + return true; + } + return false; } } // namespace gpu_info_collector diff --git a/chrome/gpu/gpu_info_unittest_win.cc b/chrome/gpu/gpu_info_unittest_win.cc index 16a00cc..21c9ef4 100644 --- a/chrome/gpu/gpu_info_unittest_win.cc +++ b/chrome/gpu/gpu_info_unittest_win.cc @@ -62,9 +62,9 @@ TEST_F(GPUInfoTest, DeviceIdD3D) { TEST_F(GPUInfoTest, DriverVersionD3D) { GPUInfo gpu_info; ASSERT_TRUE(gpu_info_collector::CollectGraphicsInfoD3D(&d3d_, &gpu_info)); - std::wstring driver_version = gpu_info.driver_version(); + std::string driver_version = gpu_info.driver_version(); EXPECT_FALSE(driver_version.empty()); - EXPECT_EQ(driver_version, L"6.14.11.7715"); + EXPECT_EQ(driver_version, "6.14.11.7715"); } TEST_F(GPUInfoTest, PixelShaderVersionD3D) { |