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 |