| OLD | NEW |
| 1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/gpu/gpu_info_collector.h" | 5 #include "chrome/gpu/gpu_info_collector.h" |
| 6 #include "base/logging.h" | 6 #include "base/logging.h" |
| 7 #include "base/scoped_ptr.h" | 7 #include "base/scoped_ptr.h" |
| 8 #include "base/string_piece.h" | 8 #include "base/string_piece.h" |
| 9 #include "base/sys_string_conversions.h" | 9 #include "base/sys_string_conversions.h" |
| 10 #include "app/gfx/gl/gl_bindings.h" | 10 #include "app/gfx/gl/gl_bindings.h" |
| 11 #include "app/gfx/gl/gl_context.h" | 11 #include "app/gfx/gl/gl_context.h" |
| 12 #include "app/gfx/gl/gl_implementation.h" | 12 #include "app/gfx/gl/gl_implementation.h" |
| 13 #include "app/gfx/gl/gl_interface.h" | 13 #include "app/gfx/gl/gl_interface.h" |
| 14 | 14 |
| 15 #import <Cocoa/Cocoa.h> | 15 #import <Cocoa/Cocoa.h> |
| 16 #import <Foundation/Foundation.h> | 16 #import <Foundation/Foundation.h> |
| 17 #import <IOKit/IOKitLib.h> | 17 #import <IOKit/IOKitLib.h> |
| 18 | 18 |
| 19 namespace gpu_info_collector { | 19 namespace { |
| 20 | 20 |
| 21 static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort, | 21 CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort, |
| 22 CFStringRef propertyName) { | 22 CFStringRef propertyName) { |
| 23 return IORegistryEntrySearchCFProperty(dspPort, | 23 return IORegistryEntrySearchCFProperty(dspPort, |
| 24 kIOServicePlane, | 24 kIOServicePlane, |
| 25 propertyName, | 25 propertyName, |
| 26 kCFAllocatorDefault, | 26 kCFAllocatorDefault, |
| 27 kIORegistryIterateRecursively | | 27 kIORegistryIterateRecursively | |
| 28 kIORegistryIterateParents); | 28 kIORegistryIterateParents); |
| 29 } | 29 } |
| 30 | 30 |
| 31 static void CFReleaseIf(CFTypeRef type_ref) { | 31 UInt32 IntValueOfCFData(CFDataRef data_ref) { |
| 32 if (type_ref) | 32 DCHECK(data_ref); |
| 33 CFRelease(type_ref); | |
| 34 } | |
| 35 | 33 |
| 36 static UInt32 IntValueOfCFData(CFDataRef data_ref) { | |
| 37 UInt32 value = 0; | 34 UInt32 value = 0; |
| 38 | 35 const UInt32* value_pointer = |
| 39 if (data_ref) { | 36 reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref)); |
| 40 const UInt32 *value_pointer = | 37 if (value_pointer != NULL) |
| 41 reinterpret_cast<const UInt32*>(CFDataGetBytePtr(data_ref)); | 38 value = *value_pointer; |
| 42 if (value_pointer != NULL) | |
| 43 value = *value_pointer; | |
| 44 } | |
| 45 | |
| 46 return value; | 39 return value; |
| 47 } | 40 } |
| 48 | 41 |
| 49 static void CollectVideoCardInfo(CGDirectDisplayID displayID, | 42 } // namespace anonymous |
| 50 int *vendorID, | |
| 51 int *deviceID) { | |
| 52 io_registry_entry_t dspPort = CGDisplayIOServicePort(displayID); | |
| 53 | 43 |
| 54 CFTypeRef vendorIDRef = SearchPortForProperty(dspPort, CFSTR("vendor-id")); | 44 namespace gpu_info_collector { |
| 55 if (vendorID) *vendorID = IntValueOfCFData((CFDataRef)vendorIDRef); | |
| 56 | 45 |
| 57 CFTypeRef deviceIDRef = SearchPortForProperty(dspPort, CFSTR("device-id")); | 46 bool CollectGraphicsInfo(GPUInfo* gpu_info) { |
| 58 if (deviceID) *deviceID = IntValueOfCFData((CFDataRef)deviceIDRef); | 47 DCHECK(gpu_info); |
| 59 | 48 |
| 60 CFReleaseIf(vendorIDRef); | 49 gpu_info->SetCanLoseContext( |
| 61 CFReleaseIf(deviceIDRef); | 50 gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2); |
| 51 gpu_info->SetProgress(GPUInfo::kComplete); |
| 52 return CollectGraphicsInfoGL(gpu_info); |
| 62 } | 53 } |
| 63 | 54 |
| 64 // Return a pointer to the last character with value c in string s. | 55 bool CollectVideoCardInfo(GPUInfo* gpu_info) { |
| 65 // Returns NULL if c is not found. | 56 DCHECK(gpu_info); |
| 66 static char* FindLastChar(char *s, char c) { | |
| 67 char *s_found = NULL; | |
| 68 | 57 |
| 69 while (*s != '\0') { | 58 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) |
| 70 if (*s == c) | 59 return false; |
| 71 s_found = s; | 60 |
| 72 s++; | 61 UInt32 vendor_id = 0, device_id = 0; |
| 62 io_registry_entry_t dsp_port = CGDisplayIOServicePort(kCGDirectMainDisplay); |
| 63 CFTypeRef vendor_id_ref = SearchPortForProperty(dsp_port, CFSTR("vendor-id")); |
| 64 if (vendor_id_ref) { |
| 65 vendor_id = IntValueOfCFData((CFDataRef)vendor_id_ref); |
| 66 CFRelease(vendor_id_ref); |
| 73 } | 67 } |
| 74 return s_found; | 68 CFTypeRef device_id_ref = SearchPortForProperty(dsp_port, CFSTR("device-id")); |
| 69 if (device_id_ref) { |
| 70 device_id = IntValueOfCFData((CFDataRef)device_id_ref); |
| 71 CFRelease(device_id_ref); |
| 72 } |
| 73 |
| 74 gpu_info->SetVideoCardInfo(vendor_id, device_id); |
| 75 return true; |
| 75 } | 76 } |
| 76 | 77 |
| 77 // Gets the numeric HLSL version. | 78 bool CollectDriverInfo(GPUInfo* gpu_info) { |
| 78 // You pass it the current GL major version, to give it a hint where to look. | 79 DCHECK(gpu_info); |
| 79 static int GetShaderNumericVersion(int gl_major_version) { | |
| 80 int gl_hlsl_major = 0, gl_hlsl_minor = 0; | |
| 81 int shader_version = 0; | |
| 82 | |
| 83 if (gl_major_version == 1) { | |
| 84 const char *gl_extensions_string = (const char*)glGetString(GL_EXTENSIONS); | |
| 85 if (gl_extensions_string && | |
| 86 strstr(gl_extensions_string, "GL_ARB_shading_language_100")) { | |
| 87 gl_hlsl_major = 1; | |
| 88 gl_hlsl_minor = 0; | |
| 89 } | |
| 90 } else if (gl_major_version > 1) { | |
| 91 const char *glsl_version_string = | |
| 92 (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); | |
| 93 if (glsl_version_string) | |
| 94 sscanf(glsl_version_string, "%u.%u", &gl_hlsl_major, &gl_hlsl_minor); | |
| 95 } | |
| 96 | |
| 97 shader_version = (gl_hlsl_major << 8) | (gl_hlsl_minor & 0xFF); | |
| 98 return shader_version; | |
| 99 } | |
| 100 | |
| 101 | |
| 102 static std::wstring CStringToWString(const char *s) { | |
| 103 base::StringPiece sp(s); | |
| 104 return base::SysUTF8ToWide(sp); | |
| 105 } | |
| 106 | |
| 107 | |
| 108 // Returns the driver version string as its value, and also returns the | |
| 109 // gl version and shader language version by setting the arguments pointed to. | |
| 110 static std::wstring CollectGLInfo(int *out_gl_version, | |
| 111 int *out_shader_version) { | |
| 112 int gl_major = 0, gl_minor = 0; | |
| 113 char *gl_version_string = NULL; | |
| 114 std::wstring driver_version; | |
| 115 | |
| 116 gl_version_string = (char*)glGetString(GL_VERSION); | |
| 117 sscanf(gl_version_string, "%u.%u", &gl_major, &gl_minor); | |
| 118 | |
| 119 *out_gl_version = (gl_major << 8) | (gl_minor & 0xFF); | |
| 120 *out_shader_version = GetShaderNumericVersion(gl_major); | |
| 121 | 80 |
| 122 // Extract the OpenGL driver version string from the GL_VERSION string. | 81 // Extract the OpenGL driver version string from the GL_VERSION string. |
| 123 // Mac OpenGL drivers have the driver version | 82 // Mac OpenGL drivers have the driver version |
| 124 // at the end of the gl version string preceded by a dash. | 83 // at the end of the gl version string preceded by a dash. |
| 125 // Use some jiggery-pokery to turn that utf8 string into a std::wstring. | 84 // Use some jiggery-pokery to turn that utf8 string into a std::wstring. |
| 126 char *s = FindLastChar(gl_version_string, '-'); | 85 std::string gl_version_string = gpu_info->gl_version_string(); |
| 127 if (s) | 86 size_t pos = gl_version_string.find_last_of('-'); |
| 128 driver_version = CStringToWString(s + 1); | 87 if (pos == std::string::npos) |
| 129 | |
| 130 return driver_version; | |
| 131 } | |
| 132 | |
| 133 | |
| 134 bool CollectGraphicsInfo(GPUInfo* gpu_info) { | |
| 135 if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL) | |
| 136 return false; | 88 return false; |
| 137 // Video Card data. | 89 gpu_info->SetDriverInfo("", gl_version_string.substr(pos + 1)); |
| 138 int vendor_id = 0, device_id = 0; | |
| 139 // OpenGL data. | |
| 140 std::wstring driver_version = L""; | |
| 141 int gl_version = 0, shader_version = 0; | |
| 142 | |
| 143 CollectVideoCardInfo(kCGDirectMainDisplay, &vendor_id, &device_id); | |
| 144 | |
| 145 // Temporarily make an offscreen GL context so we can gather info from it. | |
| 146 if (gfx::GLContext::InitializeOneOff()) { | |
| 147 scoped_ptr<gfx::GLContext> ctx( | |
| 148 gfx::GLContext::CreateOffscreenGLContext(NULL)); | |
| 149 if (ctx.get()) { | |
| 150 if (ctx->MakeCurrent()) { | |
| 151 driver_version = CollectGLInfo(&gl_version, &shader_version); | |
| 152 } | |
| 153 ctx->Destroy(); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 | |
| 158 // OpenGL doesn't have separate versions for pixel and vertex shader | |
| 159 // languages, so we just pass the shader_version for both. | |
| 160 gpu_info->SetGraphicsInfo(vendor_id, | |
| 161 device_id, | |
| 162 driver_version, | |
| 163 shader_version, | |
| 164 shader_version, | |
| 165 gl_version, | |
| 166 false); | |
| 167 | |
| 168 gpu_info->SetProgress(GPUInfo::kComplete); | |
| 169 | |
| 170 return true; | 90 return true; |
| 171 } | 91 } |
| 172 | 92 |
| 173 } // namespace gpu_info_collector | 93 } // namespace gpu_info_collector |
| OLD | NEW |