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 
106     if (0 == strcmp(rendererString, "Chromium")) {
107         *outDriver = kChromium_GrGLDriver;
108         return;
109     }
110 
111     if (standard == kGL_GrGLStandard) {
112         if (kNVIDIA_GrGLVendor == vendor) {
113             *outDriver = kNVIDIA_GrGLDriver;
114             int n = sscanf(versionString, "%d.%d.%d NVIDIA %d.%d",
115                            &major, &minor, &rev, &driverMajor, &driverMinor);
116             // Some older NVIDIA drivers don't report the driver version.
117             if (5 == n) {
118                 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
119             }
120             return;
121         }
122 
123         int n = sscanf(versionString, "%d.%d Mesa %d.%d",
124                        &major, &minor, &driverMajor, &driverMinor);
125         if (4 == n) {
126             *outDriver = kMesa_GrGLDriver;
127             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
128             return;
129         }
130     }
131     else {
132         if (kNVIDIA_GrGLVendor == vendor) {
133             *outDriver = kNVIDIA_GrGLDriver;
134             int n = sscanf(versionString, "OpenGL ES %d.%d NVIDIA %d.%d",
135                            &major, &minor, &driverMajor, &driverMinor);
136             // Some older NVIDIA drivers don't report the driver version.
137             if (4 == n) {
138                 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
139             }
140             return;
141         }
142 
143         int n = sscanf(versionString, "OpenGL ES %d.%d Mesa %d.%d",
144                        &major, &minor, &driverMajor, &driverMinor);
145         if (4 == n) {
146             *outDriver = kMesa_GrGLDriver;
147             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
148             return;
149         }
150         if (0 == strncmp("ANGLE", rendererString, 5)) {
151             *outDriver = kANGLE_GrGLDriver;
152             n = sscanf(versionString, "OpenGL ES %d.%d (ANGLE %d.%d", &major, &minor, &driverMajor,
153                                                                       &driverMinor);
154             if (4 == n) {
155                 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
156             }
157             return;
158         }
159     }
160 
161     if (kIntel_GrGLVendor == vendor) {
162         // We presume we're on the Intel driver since it hasn't identified itself as Mesa.
163         *outDriver = kIntel_GrGLDriver;
164     }
165 }
166 
GrGLGetVersionFromString(const char * versionString)167 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
168     if (nullptr == versionString) {
169         SkDebugf("nullptr GL version string.");
170         return GR_GL_INVALID_VER;
171     }
172 
173     int major, minor;
174 
175     // check for mesa
176     int mesaMajor, mesaMinor;
177     int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
178     if (4 == n) {
179         return GR_GL_VER(major, minor);
180     }
181 
182     n = sscanf(versionString, "%d.%d", &major, &minor);
183     if (2 == n) {
184         return GR_GL_VER(major, minor);
185     }
186 
187     char profile[2];
188     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
189                &major, &minor);
190     if (4 == n) {
191         return GR_GL_VER(major, minor);
192     }
193 
194     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
195     if (2 == n) {
196         return GR_GL_VER(major, minor);
197     }
198 
199     return GR_GL_INVALID_VER;
200 }
201 
GrGLGetGLSLVersionFromString(const char * versionString)202 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
203     if (nullptr == versionString) {
204         SkDebugf("nullptr GLSL version string.");
205         return GR_GLSL_INVALID_VER;
206     }
207 
208     int major, minor;
209 
210     int n = sscanf(versionString, "%d.%d", &major, &minor);
211     if (2 == n) {
212         return GR_GLSL_VER(major, minor);
213     }
214 
215     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
216     if (2 == n) {
217         return GR_GLSL_VER(major, minor);
218     }
219 
220 #ifdef SK_BUILD_FOR_ANDROID
221     // android hack until the gpu vender updates their drivers
222     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
223     if (2 == n) {
224         return GR_GLSL_VER(major, minor);
225     }
226 #endif
227 
228     return GR_GLSL_INVALID_VER;
229 }
230 
GrGLGetVendorFromString(const char * vendorString)231 GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
232     if (vendorString) {
233         if (0 == strcmp(vendorString, "ARM")) {
234             return kARM_GrGLVendor;
235         }
236         if (0 == strcmp(vendorString, "Imagination Technologies")) {
237             return kImagination_GrGLVendor;
238         }
239         if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
240             return kIntel_GrGLVendor;
241         }
242         if (0 == strcmp(vendorString, "Qualcomm")) {
243             return kQualcomm_GrGLVendor;
244         }
245         if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
246             return kNVIDIA_GrGLVendor;
247         }
248     }
249     return kOther_GrGLVendor;
250 }
251 
GrGLGetRendererFromString(const char * rendererString)252 GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
253     if (rendererString) {
254         if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
255             return kTegra3_GrGLRenderer;
256         } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
257             return kTegra2_GrGLRenderer;
258         }
259         int lastDigit;
260         int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
261         if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
262             return kPowerVR54x_GrGLRenderer;
263         }
264         // certain iOS devices also use PowerVR54x GPUs
265         static const char kAppleA4Str[] = "Apple A4";
266         static const char kAppleA5Str[] = "Apple A5";
267         static const char kAppleA6Str[] = "Apple A6";
268         if (0 == strncmp(rendererString, kAppleA4Str,
269                          SK_ARRAY_COUNT(kAppleA4Str)-1) ||
270             0 == strncmp(rendererString, kAppleA5Str,
271                          SK_ARRAY_COUNT(kAppleA5Str)-1) ||
272             0 == strncmp(rendererString, kAppleA6Str,
273                          SK_ARRAY_COUNT(kAppleA6Str)-1)) {
274             return kPowerVR54x_GrGLRenderer;
275         }
276         static const char kPowerVRRogueStr[] = "PowerVR Rogue";
277         static const char kAppleA7Str[] = "Apple A7";
278         static const char kAppleA8Str[] = "Apple A8";
279         if (0 == strncmp(rendererString, kPowerVRRogueStr,
280                          SK_ARRAY_COUNT(kPowerVRRogueStr)-1) ||
281             0 == strncmp(rendererString, kAppleA7Str,
282                          SK_ARRAY_COUNT(kAppleA7Str)-1) ||
283             0 == strncmp(rendererString, kAppleA8Str,
284                          SK_ARRAY_COUNT(kAppleA8Str)-1)) {
285             return kPowerVRRogue_GrGLRenderer;
286         }
287         int adrenoNumber;
288         n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber);
289         if (1 == n) {
290             if (adrenoNumber >= 300) {
291                 if (adrenoNumber < 400) {
292                     return kAdreno3xx_GrGLRenderer;
293                 }
294                 if (adrenoNumber < 500) {
295                     return kAdreno4xx_GrGLRenderer;
296                 }
297             }
298         }
299     }
300     return kOther_GrGLRenderer;
301 }
302 
GrGLGetVersion(const GrGLInterface * gl)303 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
304     const GrGLubyte* v;
305     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
306     return GrGLGetVersionFromString((const char*) v);
307 }
308 
GrGLGetGLSLVersion(const GrGLInterface * gl)309 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
310     const GrGLubyte* v;
311     GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
312     return GrGLGetGLSLVersionFromString((const char*) v);
313 }
314 
GrGLGetVendor(const GrGLInterface * gl)315 GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
316     const GrGLubyte* v;
317     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
318     return GrGLGetVendorFromString((const char*) v);
319 }
320 
GrGLGetRenderer(const GrGLInterface * gl)321 GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
322     const GrGLubyte* v;
323     GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER));
324     return GrGLGetRendererFromString((const char*) v);
325 }
326 
GrToGLStencilFunc(GrStencilFunc basicFunc)327 GrGLenum GrToGLStencilFunc(GrStencilFunc basicFunc) {
328     static const GrGLenum gTable[] = {
329         GR_GL_ALWAYS,           // kAlways_StencilFunc
330         GR_GL_NEVER,            // kNever_StencilFunc
331         GR_GL_GREATER,          // kGreater_StencilFunc
332         GR_GL_GEQUAL,           // kGEqual_StencilFunc
333         GR_GL_LESS,             // kLess_StencilFunc
334         GR_GL_LEQUAL,           // kLEqual_StencilFunc,
335         GR_GL_EQUAL,            // kEqual_StencilFunc,
336         GR_GL_NOTEQUAL,         // kNotEqual_StencilFunc,
337     };
338     GR_STATIC_ASSERT(SK_ARRAY_COUNT(gTable) == kBasicStencilFuncCount);
339     GR_STATIC_ASSERT(0 == kAlways_StencilFunc);
340     GR_STATIC_ASSERT(1 == kNever_StencilFunc);
341     GR_STATIC_ASSERT(2 == kGreater_StencilFunc);
342     GR_STATIC_ASSERT(3 == kGEqual_StencilFunc);
343     GR_STATIC_ASSERT(4 == kLess_StencilFunc);
344     GR_STATIC_ASSERT(5 == kLEqual_StencilFunc);
345     GR_STATIC_ASSERT(6 == kEqual_StencilFunc);
346     GR_STATIC_ASSERT(7 == kNotEqual_StencilFunc);
347     SkASSERT((unsigned) basicFunc < kBasicStencilFuncCount);
348 
349     return gTable[basicFunc];
350 }
351