1 /*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8
9 #include "GrGLUtil.h"
10 #include "SkMatrix.h"
11 #include <stdio.h>
12
GrGLClearErr(const GrGLInterface * gl)13 void GrGLClearErr(const GrGLInterface* gl) {
14 while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {}
15 }
16
17 namespace {
get_error_string(uint32_t err)18 const char *get_error_string(uint32_t err) {
19 switch (err) {
20 case GR_GL_NO_ERROR:
21 return "";
22 case GR_GL_INVALID_ENUM:
23 return "Invalid Enum";
24 case GR_GL_INVALID_VALUE:
25 return "Invalid Value";
26 case GR_GL_INVALID_OPERATION:
27 return "Invalid Operation";
28 case GR_GL_OUT_OF_MEMORY:
29 return "Out of Memory";
30 case GR_GL_CONTEXT_LOST:
31 return "Context Lost";
32 }
33 return "Unknown";
34 }
35 }
36
GrGLCheckErr(const GrGLInterface * gl,const char * location,const char * call)37 void GrGLCheckErr(const GrGLInterface* gl,
38 const char* location,
39 const char* call) {
40 uint32_t err = GR_GL_GET_ERROR(gl);
41 if (GR_GL_NO_ERROR != err) {
42 SkDebugf("---- glGetError 0x%x(%s)", err, get_error_string(err));
43 if (location) {
44 SkDebugf(" at\n\t%s", location);
45 }
46 if (call) {
47 SkDebugf("\n\t\t%s", call);
48 }
49 SkDebugf("\n");
50 }
51 }
52
53 ///////////////////////////////////////////////////////////////////////////////
54
55 #if GR_GL_LOG_CALLS
56 bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
57 #endif
58
59 #if GR_GL_CHECK_ERROR
60 bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
61 #endif
62
63 ///////////////////////////////////////////////////////////////////////////////
64
GrGLGetStandardInUseFromString(const char * versionString)65 GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
66 if (nullptr == versionString) {
67 SkDebugf("nullptr GL version string.");
68 return kNone_GrGLStandard;
69 }
70
71 int major, minor;
72
73 // check for desktop
74 int n = sscanf(versionString, "%d.%d", &major, &minor);
75 if (2 == n) {
76 return kGL_GrGLStandard;
77 }
78
79 // check for ES 1
80 char profile[2];
81 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor);
82 if (4 == n) {
83 // we no longer support ES1.
84 return kNone_GrGLStandard;
85 }
86
87 // check for ES2
88 n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
89 if (2 == n) {
90 return kGLES_GrGLStandard;
91 }
92 return kNone_GrGLStandard;
93 }
94
GrGLGetDriverInfo(GrGLStandard standard,GrGLVendor vendor,const char * rendererString,const char * versionString,GrGLDriver * outDriver,GrGLDriverVersion * outVersion)95 void GrGLGetDriverInfo(GrGLStandard standard,
96 GrGLVendor vendor,
97 const char* rendererString,
98 const char* versionString,
99 GrGLDriver* outDriver,
100 GrGLDriverVersion* outVersion) {
101 int major, minor, rev, driverMajor, driverMinor;
102
103 *outDriver = kUnknown_GrGLDriver;
104 *outVersion = GR_GL_DRIVER_UNKNOWN_VER;
105 // These null checks are for test GL contexts that return nullptr in their
106 // glGetString implementation.
107 if (!rendererString) {
108 rendererString = "";
109 }
110 if (!versionString) {
111 versionString = "";
112 }
113
114 static const char kChromium[] = "Chromium";
115 char suffix[SK_ARRAY_COUNT(kChromium)];
116 if (0 == strcmp(rendererString, kChromium) ||
117 (3 == sscanf(versionString, "OpenGL ES %d.%d %8s", &major, &minor, suffix) &&
118 0 == strcmp(kChromium, suffix))) {
119 *outDriver = kChromium_GrGLDriver;
120 return;
121 }
122
123 if (standard == kGL_GrGLStandard) {
124 if (kNVIDIA_GrGLVendor == vendor) {
125 *outDriver = kNVIDIA_GrGLDriver;
126 int n = sscanf(versionString, "%d.%d.%d NVIDIA %d.%d",
127 &major, &minor, &rev, &driverMajor, &driverMinor);
128 // Some older NVIDIA drivers don't report the driver version.
129 if (5 == n) {
130 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
131 }
132 return;
133 }
134 int n = sscanf(versionString, "%d.%d Mesa %d.%d",
135 &major, &minor, &driverMajor, &driverMinor);
136 if (4 == n) {
137 *outDriver = kMesa_GrGLDriver;
138 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
139 return;
140 }
141 }
142 else {
143 if (kNVIDIA_GrGLVendor == vendor) {
144 *outDriver = kNVIDIA_GrGLDriver;
145 int n = sscanf(versionString, "OpenGL ES %d.%d NVIDIA %d.%d",
146 &major, &minor, &driverMajor, &driverMinor);
147 // Some older NVIDIA drivers don't report the driver version.
148 if (4 == n) {
149 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
150 }
151 return;
152 }
153
154 int n = sscanf(versionString, "OpenGL ES %d.%d Mesa %d.%d",
155 &major, &minor, &driverMajor, &driverMinor);
156 if (4 == n) {
157 *outDriver = kMesa_GrGLDriver;
158 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
159 return;
160 }
161 if (0 == strncmp("ANGLE", rendererString, 5)) {
162 *outDriver = kANGLE_GrGLDriver;
163 n = sscanf(versionString, "OpenGL ES %d.%d (ANGLE %d.%d", &major, &minor, &driverMajor,
164 &driverMinor);
165 if (4 == n) {
166 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
167 }
168 return;
169 }
170 }
171
172 if (kIntel_GrGLVendor == vendor) {
173 // We presume we're on the Intel driver since it hasn't identified itself as Mesa.
174 *outDriver = kIntel_GrGLDriver;
175 }
176 }
177
GrGLGetVersionFromString(const char * versionString)178 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
179 if (nullptr == versionString) {
180 SkDebugf("nullptr GL version string.");
181 return GR_GL_INVALID_VER;
182 }
183
184 int major, minor;
185
186 // check for mesa
187 int mesaMajor, mesaMinor;
188 int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
189 if (4 == n) {
190 return GR_GL_VER(major, minor);
191 }
192
193 n = sscanf(versionString, "%d.%d", &major, &minor);
194 if (2 == n) {
195 return GR_GL_VER(major, minor);
196 }
197
198 char profile[2];
199 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
200 &major, &minor);
201 if (4 == n) {
202 return GR_GL_VER(major, minor);
203 }
204
205 n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
206 if (2 == n) {
207 return GR_GL_VER(major, minor);
208 }
209
210 return GR_GL_INVALID_VER;
211 }
212
GrGLGetGLSLVersionFromString(const char * versionString)213 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
214 if (nullptr == versionString) {
215 SkDebugf("nullptr GLSL version string.");
216 return GR_GLSL_INVALID_VER;
217 }
218
219 int major, minor;
220
221 int n = sscanf(versionString, "%d.%d", &major, &minor);
222 if (2 == n) {
223 return GR_GLSL_VER(major, minor);
224 }
225
226 n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
227 if (2 == n) {
228 return GR_GLSL_VER(major, minor);
229 }
230
231 #ifdef SK_BUILD_FOR_ANDROID
232 // android hack until the gpu vender updates their drivers
233 n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
234 if (2 == n) {
235 return GR_GLSL_VER(major, minor);
236 }
237 #endif
238
239 return GR_GLSL_INVALID_VER;
240 }
241
GrGLGetVendorFromString(const char * vendorString)242 GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
243 if (vendorString) {
244 if (0 == strcmp(vendorString, "ARM")) {
245 return kARM_GrGLVendor;
246 }
247 if (0 == strcmp(vendorString, "Imagination Technologies")) {
248 return kImagination_GrGLVendor;
249 }
250 if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
251 return kIntel_GrGLVendor;
252 }
253 if (0 == strcmp(vendorString, "Qualcomm")) {
254 return kQualcomm_GrGLVendor;
255 }
256 if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
257 return kNVIDIA_GrGLVendor;
258 }
259 if (0 == strcmp(vendorString, "ATI Technologies Inc.")) {
260 return kATI_GrGLVendor;
261 }
262 }
263 return kOther_GrGLVendor;
264 }
265
GrGLGetRendererFromString(const char * rendererString)266 GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
267 if (rendererString) {
268 if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
269 return kTegra3_GrGLRenderer;
270 } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
271 return kTegra2_GrGLRenderer;
272 }
273 int lastDigit;
274 int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
275 if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
276 return kPowerVR54x_GrGLRenderer;
277 }
278 // certain iOS devices also use PowerVR54x GPUs
279 static const char kAppleA4Str[] = "Apple A4";
280 static const char kAppleA5Str[] = "Apple A5";
281 static const char kAppleA6Str[] = "Apple A6";
282 if (0 == strncmp(rendererString, kAppleA4Str,
283 SK_ARRAY_COUNT(kAppleA4Str)-1) ||
284 0 == strncmp(rendererString, kAppleA5Str,
285 SK_ARRAY_COUNT(kAppleA5Str)-1) ||
286 0 == strncmp(rendererString, kAppleA6Str,
287 SK_ARRAY_COUNT(kAppleA6Str)-1)) {
288 return kPowerVR54x_GrGLRenderer;
289 }
290 static const char kPowerVRRogueStr[] = "PowerVR Rogue";
291 static const char kAppleA7Str[] = "Apple A7";
292 static const char kAppleA8Str[] = "Apple A8";
293 if (0 == strncmp(rendererString, kPowerVRRogueStr,
294 SK_ARRAY_COUNT(kPowerVRRogueStr)-1) ||
295 0 == strncmp(rendererString, kAppleA7Str,
296 SK_ARRAY_COUNT(kAppleA7Str)-1) ||
297 0 == strncmp(rendererString, kAppleA8Str,
298 SK_ARRAY_COUNT(kAppleA8Str)-1)) {
299 return kPowerVRRogue_GrGLRenderer;
300 }
301 int adrenoNumber;
302 n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber);
303 if (1 == n) {
304 if (adrenoNumber >= 300) {
305 if (adrenoNumber < 400) {
306 return kAdreno3xx_GrGLRenderer;
307 }
308 if (adrenoNumber < 500) {
309 return kAdreno4xx_GrGLRenderer;
310 }
311 if (adrenoNumber < 600) {
312 return kAdreno5xx_GrGLRenderer;
313 }
314 }
315 }
316 if (0 == strcmp("Mesa Offscreen", rendererString)) {
317 return kOSMesa_GrGLRenderer;
318 }
319 }
320 return kOther_GrGLRenderer;
321 }
322
GrGLGetVersion(const GrGLInterface * gl)323 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
324 const GrGLubyte* v;
325 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
326 return GrGLGetVersionFromString((const char*) v);
327 }
328
GrGLGetGLSLVersion(const GrGLInterface * gl)329 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
330 const GrGLubyte* v;
331 GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
332 return GrGLGetGLSLVersionFromString((const char*) v);
333 }
334
GrGLGetVendor(const GrGLInterface * gl)335 GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
336 const GrGLubyte* v;
337 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
338 return GrGLGetVendorFromString((const char*) v);
339 }
340
GrGLGetRenderer(const GrGLInterface * gl)341 GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
342 const GrGLubyte* v;
343 GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER));
344 return GrGLGetRendererFromString((const char*) v);
345 }
346
GrToGLStencilFunc(GrStencilTest test)347 GrGLenum GrToGLStencilFunc(GrStencilTest test) {
348 static const GrGLenum gTable[kGrStencilTestCount] = {
349 GR_GL_ALWAYS, // kAlways
350 GR_GL_NEVER, // kNever
351 GR_GL_GREATER, // kGreater
352 GR_GL_GEQUAL, // kGEqual
353 GR_GL_LESS, // kLess
354 GR_GL_LEQUAL, // kLEqual
355 GR_GL_EQUAL, // kEqual
356 GR_GL_NOTEQUAL, // kNotEqual
357 };
358 GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
359 GR_STATIC_ASSERT(1 == (int)GrStencilTest::kNever);
360 GR_STATIC_ASSERT(2 == (int)GrStencilTest::kGreater);
361 GR_STATIC_ASSERT(3 == (int)GrStencilTest::kGEqual);
362 GR_STATIC_ASSERT(4 == (int)GrStencilTest::kLess);
363 GR_STATIC_ASSERT(5 == (int)GrStencilTest::kLEqual);
364 GR_STATIC_ASSERT(6 == (int)GrStencilTest::kEqual);
365 GR_STATIC_ASSERT(7 == (int)GrStencilTest::kNotEqual);
366 SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
367
368 return gTable[(int)test];
369 }
370