summaryrefslogtreecommitdiffstats
path: root/chrome/gpu
diff options
context:
space:
mode:
authorzmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-21 00:27:53 +0000
committerzmo@google.com <zmo@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-01-21 00:27:53 +0000
commit7004d7ebec6cd4de175d8f894c2a0c58fb6f41c8 (patch)
tree5efa0e86cd64c61420909af28d43211d609ebf0f /chrome/gpu
parentc7a827e9d91099bae12379f92467e29a8d7ffaab (diff)
downloadchromium_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.cc119
-rw-r--r--chrome/gpu/gpu_info_collector.h15
-rw-r--r--chrome/gpu/gpu_info_collector_linux.cc111
-rw-r--r--chrome/gpu/gpu_info_collector_mac.mm160
-rw-r--r--chrome/gpu/gpu_info_collector_unittest.cc155
-rw-r--r--chrome/gpu/gpu_info_collector_win.cc123
-rw-r--r--chrome/gpu/gpu_info_unittest_win.cc4
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) {