1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
// 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 "base/logging.h"
#include "base/scoped_ptr.h"
#include "base/string_piece.h"
#include "base/sys_string_conversions.h"
#include "app/gfx/gl/gl_context.h"
#import <Cocoa/Cocoa.h>
#import <Foundation/Foundation.h>
#import <IOKit/IOKitLib.h>
#import <OpenGL/gl.h>
namespace gpu_info_collector {
static CFTypeRef SearchPortForProperty(io_registry_entry_t dspPort,
CFStringRef propertyName) {
return IORegistryEntrySearchCFProperty(dspPort,
kIOServicePlane,
propertyName,
kCFAllocatorDefault,
kIORegistryIterateRecursively |
kIORegistryIterateParents);
}
static void CFReleaseIf(CFTypeRef type_ref) {
if (type_ref)
CFRelease(type_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;
}
return value;
}
static void CollectVideoCardInfo(CGDirectDisplayID displayID,
int *vendorID,
int *deviceID) {
io_registry_entry_t dspPort = CGDisplayIOServicePort(displayID);
CFTypeRef vendorIDRef = SearchPortForProperty(dspPort, CFSTR("vendor-id"));
if (vendorID) *vendorID = IntValueOfCFData((CFDataRef)vendorIDRef);
CFTypeRef deviceIDRef = SearchPortForProperty(dspPort, CFSTR("device-id"));
if (deviceID) *deviceID = IntValueOfCFData((CFDataRef)deviceIDRef);
CFReleaseIf(vendorIDRef);
CFReleaseIf(deviceIDRef);
}
// 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;
while (*s != '\0') {
if (*s == c)
s_found = s;
s++;
}
return s_found;
}
// 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) {
char *gl_extensions_string = (char*)glGetString(GL_EXTENSIONS);
if (strstr(gl_extensions_string, "GL_ARB_shading_language_100")) {
gl_hlsl_major = 1;
gl_hlsl_minor = 0;
}
} else if (gl_major_version > 1) {
char *glsl_version_string = (char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
if (glsl_version_string)
sscanf(glsl_version_string, "%u.%u", &gl_hlsl_major, &gl_hlsl_minor);
}
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);
}
// 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);
// 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) {
// 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);
return true;
}
} // namespace gpu_info_collector
|