• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "GrTypesPriv.h"
11 #include "SkMatrix.h"
12 #include <stdio.h>
13 
GrGLClearErr(const GrGLInterface * gl)14 void GrGLClearErr(const GrGLInterface* gl) {
15     while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {}
16 }
17 
18 namespace {
get_error_string(uint32_t err)19 const char *get_error_string(uint32_t err) {
20     switch (err) {
21     case GR_GL_NO_ERROR:
22         return "";
23     case GR_GL_INVALID_ENUM:
24         return "Invalid Enum";
25     case GR_GL_INVALID_VALUE:
26         return "Invalid Value";
27     case GR_GL_INVALID_OPERATION:
28         return "Invalid Operation";
29     case GR_GL_OUT_OF_MEMORY:
30         return "Out of Memory";
31     case GR_GL_CONTEXT_LOST:
32         return "Context Lost";
33     }
34     return "Unknown";
35 }
36 }
37 
GrGLCheckErr(const GrGLInterface * gl,const char * location,const char * call)38 void GrGLCheckErr(const GrGLInterface* gl,
39                   const char* location,
40                   const char* call) {
41     uint32_t err = GR_GL_GET_ERROR(gl);
42     if (GR_GL_NO_ERROR != err) {
43         SkDebugf("---- glGetError 0x%x(%s)", err, get_error_string(err));
44         if (location) {
45             SkDebugf(" at\n\t%s", location);
46         }
47         if (call) {
48             SkDebugf("\n\t\t%s", call);
49         }
50         SkDebugf("\n");
51     }
52 }
53 
54 ///////////////////////////////////////////////////////////////////////////////
55 
56 #if GR_GL_LOG_CALLS
57     bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
58 #endif
59 
60 #if GR_GL_CHECK_ERROR
61     bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
62 #endif
63 
64 ///////////////////////////////////////////////////////////////////////////////
65 
GrGLGetStandardInUseFromString(const char * versionString)66 GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
67     if (nullptr == versionString) {
68         SkDebugf("nullptr GL version string.");
69         return kNone_GrGLStandard;
70     }
71 
72     int major, minor;
73 
74     // check for desktop
75     int n = sscanf(versionString, "%d.%d", &major, &minor);
76     if (2 == n) {
77         return kGL_GrGLStandard;
78     }
79 
80     // check for ES 1
81     char profile[2];
82     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor);
83     if (4 == n) {
84         // we no longer support ES1.
85         return kNone_GrGLStandard;
86     }
87 
88     // check for ES2
89     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
90     if (2 == n) {
91         return kGLES_GrGLStandard;
92     }
93     return kNone_GrGLStandard;
94 }
95 
GrGLGetDriverInfo(GrGLStandard standard,GrGLVendor vendor,const char * rendererString,const char * versionString,GrGLDriver * outDriver,GrGLDriverVersion * outVersion)96 void GrGLGetDriverInfo(GrGLStandard standard,
97                        GrGLVendor vendor,
98                        const char* rendererString,
99                        const char* versionString,
100                        GrGLDriver* outDriver,
101                        GrGLDriverVersion* outVersion) {
102     int major, minor, rev, driverMajor, driverMinor, driverPoint;
103 
104     *outDriver = kUnknown_GrGLDriver;
105     *outVersion = GR_GL_DRIVER_UNKNOWN_VER;
106     // These null checks are for test GL contexts that return nullptr in their
107     // glGetString implementation.
108     if (!rendererString) {
109         rendererString = "";
110     }
111     if (!versionString) {
112         versionString = "";
113     }
114 
115     static const char kChromium[] = "Chromium";
116     char suffix[SK_ARRAY_COUNT(kChromium)];
117     if (0 == strcmp(rendererString, kChromium) ||
118         (3 == sscanf(versionString, "OpenGL ES %d.%d %8s", &major, &minor, suffix) &&
119          0 == strcmp(kChromium, suffix))) {
120         *outDriver = kChromium_GrGLDriver;
121         return;
122     }
123 
124     if (standard == kGL_GrGLStandard) {
125         if (kNVIDIA_GrGLVendor == vendor) {
126             *outDriver = kNVIDIA_GrGLDriver;
127             int n = sscanf(versionString, "%d.%d.%d NVIDIA %d.%d",
128                            &major, &minor, &rev, &driverMajor, &driverMinor);
129             // Some older NVIDIA drivers don't report the driver version.
130             if (5 == n) {
131                 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
132             }
133             return;
134         }
135         int n = sscanf(versionString, "%d.%d Mesa %d.%d",
136                        &major, &minor, &driverMajor, &driverMinor);
137         if (4 != n) {
138             n = sscanf(versionString, "%d.%d (Core Profile) Mesa %d.%d",
139                        &major, &minor, &driverMajor, &driverMinor);
140         }
141         if (4 == n) {
142             *outDriver = kMesa_GrGLDriver;
143             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
144             return;
145         }
146     }
147     else {
148         if (kNVIDIA_GrGLVendor == vendor) {
149             *outDriver = kNVIDIA_GrGLDriver;
150             int n = sscanf(versionString, "OpenGL ES %d.%d NVIDIA %d.%d",
151                            &major, &minor, &driverMajor, &driverMinor);
152             // Some older NVIDIA drivers don't report the driver version.
153             if (4 == n) {
154                 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
155             }
156             return;
157         }
158 
159         int n = sscanf(versionString, "OpenGL ES %d.%d Mesa %d.%d",
160                        &major, &minor, &driverMajor, &driverMinor);
161         if (4 == n) {
162             *outDriver = kMesa_GrGLDriver;
163             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
164             return;
165         }
166         if (0 == strncmp("ANGLE", rendererString, 5)) {
167             *outDriver = kANGLE_GrGLDriver;
168             n = sscanf(versionString, "OpenGL ES %d.%d (ANGLE %d.%d", &major, &minor, &driverMajor,
169                                                                       &driverMinor);
170             if (4 == n) {
171                 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
172             }
173             return;
174         }
175     }
176 
177     if (kGoogle_GrGLVendor == vendor) {
178         // Swiftshader is the only Google vendor at the moment
179         *outDriver = kSwiftShader_GrGLDriver;
180 
181         // Swiftshader has a strange version string: w.x.y.z  Going to arbitrarily ignore
182         // y and assume w,x and z are major, minor, point.
183         // As of writing, version is 4.0.0.6
184         int n = sscanf(versionString, "OpenGL ES %d.%d SwiftShader %d.%d.0.%d", &major, &minor,
185                        &driverMajor, &driverMinor, &driverPoint);
186         if (5 == n) {
187             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
188         }
189         return;
190     }
191 
192     if (kIntel_GrGLVendor == vendor) {
193         // We presume we're on the Intel driver since it hasn't identified itself as Mesa.
194         *outDriver = kIntel_GrGLDriver;
195 
196         //This is how the macOS version strings are structured. This might be different on different
197         // OSes.
198         int n = sscanf(versionString, "%d.%d INTEL-%d.%d.%d", &major, &minor, &driverMajor,
199                        &driverMinor, &driverPoint);
200         if (5 == n) {
201             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
202         }
203     }
204 
205     if (kQualcomm_GrGLVendor == vendor) {
206         *outDriver = kQualcomm_GrGLDriver;
207         int n = sscanf(versionString, "OpenGL ES %d.%d V@%d.%d", &major, &minor, &driverMajor,
208                        &driverMinor);
209         if (4 == n) {
210             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
211         }
212         return;
213     }
214 }
215 
GrGLGetVersionFromString(const char * versionString)216 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
217     if (nullptr == versionString) {
218         SkDebugf("nullptr GL version string.");
219         return GR_GL_INVALID_VER;
220     }
221 
222     int major, minor;
223 
224     // check for mesa
225     int mesaMajor, mesaMinor;
226     int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
227     if (4 == n) {
228         return GR_GL_VER(major, minor);
229     }
230 
231     n = sscanf(versionString, "%d.%d", &major, &minor);
232     if (2 == n) {
233         return GR_GL_VER(major, minor);
234     }
235 
236     char profile[2];
237     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
238                &major, &minor);
239     if (4 == n) {
240         return GR_GL_VER(major, minor);
241     }
242 
243     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
244     if (2 == n) {
245         return GR_GL_VER(major, minor);
246     }
247 
248     return GR_GL_INVALID_VER;
249 }
250 
GrGLGetGLSLVersionFromString(const char * versionString)251 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
252     if (nullptr == versionString) {
253         SkDebugf("nullptr GLSL version string.");
254         return GR_GLSL_INVALID_VER;
255     }
256 
257     int major, minor;
258 
259     int n = sscanf(versionString, "%d.%d", &major, &minor);
260     if (2 == n) {
261         return GR_GLSL_VER(major, minor);
262     }
263 
264     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
265     if (2 == n) {
266         return GR_GLSL_VER(major, minor);
267     }
268 
269 #ifdef SK_BUILD_FOR_ANDROID
270     // android hack until the gpu vender updates their drivers
271     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
272     if (2 == n) {
273         return GR_GLSL_VER(major, minor);
274     }
275 #endif
276 
277     return GR_GLSL_INVALID_VER;
278 }
279 
GrGLGetVendorFromString(const char * vendorString)280 GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
281     if (vendorString) {
282         if (0 == strcmp(vendorString, "ARM")) {
283             return kARM_GrGLVendor;
284         }
285         if (0 == strcmp(vendorString, "Google Inc.")) {
286             return kGoogle_GrGLVendor;
287         }
288         if (0 == strcmp(vendorString, "Imagination Technologies")) {
289             return kImagination_GrGLVendor;
290         }
291         if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
292             return kIntel_GrGLVendor;
293         }
294         if (0 == strcmp(vendorString, "Qualcomm")) {
295             return kQualcomm_GrGLVendor;
296         }
297         if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
298             return kNVIDIA_GrGLVendor;
299         }
300         if (0 == strcmp(vendorString, "ATI Technologies Inc.")) {
301             return kATI_GrGLVendor;
302         }
303     }
304     return kOther_GrGLVendor;
305 }
306 
is_renderer_angle(const char * rendererString)307 static bool is_renderer_angle(const char* rendererString) {
308     static constexpr char kHeader[] = "ANGLE ";
309     static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1;
310     return rendererString && 0 == strncmp(rendererString, kHeader, kHeaderLength);
311 }
312 
GrGLGetRendererFromStrings(const char * rendererString,const GrGLExtensions & extensions)313 GrGLRenderer GrGLGetRendererFromStrings(const char* rendererString,
314                                         const GrGLExtensions& extensions) {
315     if (rendererString) {
316         static const char kTegraStr[] = "NVIDIA Tegra";
317         if (0 == strncmp(rendererString, kTegraStr, SK_ARRAY_COUNT(kTegraStr) - 1)) {
318             // Tegra strings are not very descriptive. We distinguish between the modern and legacy
319             // architectures by the presence of NV_path_rendering.
320             return extensions.has("GL_NV_path_rendering") ? kTegra_GrGLRenderer
321                                                           : kTegra_PreK1_GrGLRenderer;
322         }
323         int lastDigit;
324         int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
325         if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
326             return kPowerVR54x_GrGLRenderer;
327         }
328         // certain iOS devices also use PowerVR54x GPUs
329         static const char kAppleA4Str[] = "Apple A4";
330         static const char kAppleA5Str[] = "Apple A5";
331         static const char kAppleA6Str[] = "Apple A6";
332         if (0 == strncmp(rendererString, kAppleA4Str,
333                          SK_ARRAY_COUNT(kAppleA4Str)-1) ||
334             0 == strncmp(rendererString, kAppleA5Str,
335                          SK_ARRAY_COUNT(kAppleA5Str)-1) ||
336             0 == strncmp(rendererString, kAppleA6Str,
337                          SK_ARRAY_COUNT(kAppleA6Str)-1)) {
338             return kPowerVR54x_GrGLRenderer;
339         }
340         static const char kPowerVRRogueStr[] = "PowerVR Rogue";
341         static const char kAppleA7Str[] = "Apple A7";
342         static const char kAppleA8Str[] = "Apple A8";
343         if (0 == strncmp(rendererString, kPowerVRRogueStr,
344                          SK_ARRAY_COUNT(kPowerVRRogueStr)-1) ||
345             0 == strncmp(rendererString, kAppleA7Str,
346                          SK_ARRAY_COUNT(kAppleA7Str)-1) ||
347             0 == strncmp(rendererString, kAppleA8Str,
348                          SK_ARRAY_COUNT(kAppleA8Str)-1)) {
349             return kPowerVRRogue_GrGLRenderer;
350         }
351         int adrenoNumber;
352         n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber);
353         if (1 == n) {
354             if (adrenoNumber >= 300) {
355                 if (adrenoNumber < 400) {
356                     return kAdreno3xx_GrGLRenderer;
357                 }
358                 if (adrenoNumber < 500) {
359                     return adrenoNumber >= 430
360                             ? kAdreno430_GrGLRenderer : kAdreno4xx_other_GrGLRenderer;
361                 }
362                 if (adrenoNumber < 600) {
363                     return kAdreno5xx_GrGLRenderer;
364                 }
365             }
366         }
367         if (0 == strcmp("Google SwiftShader", rendererString)) {
368             return kGoogleSwiftShader_GrGLRenderer;
369         }
370 
371         if (const char* intelString = strstr(rendererString, "Intel")) {
372             if (0 == strcmp("Intel Iris Pro OpenGL Engine", intelString)) {
373                 return kIntelIrisPro_GrGLRenderer;
374             }
375             if (strstr(intelString, "Sandybridge")) {
376                 return kIntelSandyBridge_GrGLRenderer;
377             }
378             if (strstr(intelString, "Bay Trail")) {
379                 return kIntelBayTrail_GrGLRenderer;
380             }
381             int intelNumber;
382             if (sscanf(intelString, "Intel(R) Iris(TM) Graphics %d", &intelNumber) ||
383                 sscanf(intelString, "Intel(R) Iris(TM) Pro Graphics %d", &intelNumber) ||
384                 sscanf(intelString, "Intel(R) Iris(TM) Pro Graphics P%d", &intelNumber) ||
385                 sscanf(intelString, "Intel(R) Iris(R) Graphics %d", &intelNumber) ||
386                 sscanf(intelString, "Intel(R) Iris(R) Pro Graphics %d", &intelNumber) ||
387                 sscanf(intelString, "Intel(R) Iris(R) Pro Graphics P%d", &intelNumber) ||
388                 sscanf(intelString, "Intel(R) HD Graphics %d", &intelNumber) ||
389                 sscanf(intelString, "Intel(R) HD Graphics P%d", &intelNumber)) {
390 
391                 if (intelNumber >= 4000 && intelNumber < 5000) {
392                     return kIntel4xxx_GrGLRenderer;
393                 }
394                 if (intelNumber >= 6000 && intelNumber < 7000) {
395                     return kIntel6xxx_GrGLRenderer;
396                 }
397                 if (intelNumber >= 2000 && intelNumber < 4000) {
398                     return kIntelSandyBridge_GrGLRenderer;
399                 }
400                 if (intelNumber >= 500 && intelNumber < 600) {
401                     return kIntelSkylake_GrGLRenderer;
402                 }
403             }
404         }
405 
406         // The AMD string can have a somewhat arbitrary preamble (see skbug.com/7195)
407         if (const char* amdString = strstr(rendererString, "Radeon")) {
408             char amdGeneration, amdTier, amdRevision;
409             n = sscanf(amdString, "Radeon (TM) R9 M%c%c%c",
410                                        &amdGeneration, &amdTier, &amdRevision);
411             if (3 == n) {
412                 if ('4' == amdGeneration) {
413                     return kAMDRadeonR9M4xx_GrGLRenderer;
414                 }
415             }
416 
417             char amd0, amd1, amd2;
418             n = sscanf(amdString, "Radeon HD 7%c%c%c Series", &amd0, &amd1, &amd2);
419             if (3 == n) {
420                 return kAMDRadeonHD7xxx_GrGLRenderer;
421             }
422         }
423 
424         if (0 == strcmp("Mesa Offscreen", rendererString)) {
425             return kOSMesa_GrGLRenderer;
426         }
427         if (strstr(rendererString, "llvmpipe")) {
428             return kGalliumLLVM_GrGLRenderer;
429         }
430         static const char kMaliTStr[] = "Mali-T";
431         if (0 == strncmp(rendererString, kMaliTStr, SK_ARRAY_COUNT(kMaliTStr) - 1)) {
432             return kMaliT_GrGLRenderer;
433         }
434         int mali400Num;
435         if (1 == sscanf(rendererString, "Mali-%d", &mali400Num) && mali400Num >= 400 &&
436             mali400Num < 500) {
437             return kMali4xx_GrGLRenderer;
438         }
439         if (is_renderer_angle(rendererString)) {
440             return kANGLE_GrGLRenderer;
441         }
442     }
443     return kOther_GrGLRenderer;
444 }
445 
GrGLGetANGLEInfoFromString(const char * rendererString,GrGLANGLEBackend * backend,GrGLANGLEVendor * vendor,GrGLANGLERenderer * renderer)446 void GrGLGetANGLEInfoFromString(const char* rendererString, GrGLANGLEBackend* backend,
447                                 GrGLANGLEVendor* vendor, GrGLANGLERenderer* renderer) {
448     *backend = GrGLANGLEBackend::kUnknown;
449     *vendor = GrGLANGLEVendor::kUnknown;
450     *renderer = GrGLANGLERenderer::kUnknown;
451     if (!is_renderer_angle(rendererString)) {
452         return;
453     }
454     if (strstr(rendererString, "Intel")) {
455         *vendor = GrGLANGLEVendor::kIntel;
456 
457         const char* modelStr;
458         int modelNumber;
459         if ((modelStr = strstr(rendererString, "HD Graphics")) &&
460             (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) ||
461              1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) {
462             switch (modelNumber) {
463                 case 2000:
464                 case 3000:
465                     *renderer = GrGLANGLERenderer::kSandyBridge;
466                     break;
467                 case 4000:
468                 case 2500:
469                     *renderer = GrGLANGLERenderer::kIvyBridge;
470                     break;
471                 case 510:
472                 case 515:
473                 case 520:
474                 case 530:
475                     *renderer = GrGLANGLERenderer::kSkylake;
476                     break;
477             }
478         } else if ((modelStr = strstr(rendererString, "Iris")) &&
479                    (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) ||
480                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) ||
481                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) {
482             switch (modelNumber) {
483                 case 540:
484                 case 550:
485                 case 555:
486                 case 580:
487                     *renderer = GrGLANGLERenderer::kSkylake;
488                     break;
489             }
490         }
491     }
492     if (strstr(rendererString, "Direct3D11")) {
493         *backend = GrGLANGLEBackend::kD3D11;
494     } else if (strstr(rendererString, "Direct3D9")) {
495         *backend = GrGLANGLEBackend::kD3D9;
496     } else if (strstr(rendererString, "OpenGL")) {
497         *backend = GrGLANGLEBackend::kOpenGL;
498     }
499 }
500 
GrGLGetVersion(const GrGLInterface * gl)501 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
502     const GrGLubyte* v;
503     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
504     return GrGLGetVersionFromString((const char*) v);
505 }
506 
GrGLGetGLSLVersion(const GrGLInterface * gl)507 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
508     const GrGLubyte* v;
509     GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
510     return GrGLGetGLSLVersionFromString((const char*) v);
511 }
512 
GrGLGetVendor(const GrGLInterface * gl)513 GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
514     const GrGLubyte* v;
515     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
516     return GrGLGetVendorFromString((const char*) v);
517 }
518 
GrGLGetRenderer(const GrGLInterface * gl)519 GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
520     const GrGLubyte* rendererString;
521     GR_GL_CALL_RET(gl, rendererString, GetString(GR_GL_RENDERER));
522 
523     return GrGLGetRendererFromStrings((const char*)rendererString, gl->fExtensions);
524 }
525 
GrToGLStencilFunc(GrStencilTest test)526 GrGLenum GrToGLStencilFunc(GrStencilTest test) {
527     static const GrGLenum gTable[kGrStencilTestCount] = {
528         GR_GL_ALWAYS,           // kAlways
529         GR_GL_NEVER,            // kNever
530         GR_GL_GREATER,          // kGreater
531         GR_GL_GEQUAL,           // kGEqual
532         GR_GL_LESS,             // kLess
533         GR_GL_LEQUAL,           // kLEqual
534         GR_GL_EQUAL,            // kEqual
535         GR_GL_NOTEQUAL,         // kNotEqual
536     };
537     GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
538     GR_STATIC_ASSERT(1 == (int)GrStencilTest::kNever);
539     GR_STATIC_ASSERT(2 == (int)GrStencilTest::kGreater);
540     GR_STATIC_ASSERT(3 == (int)GrStencilTest::kGEqual);
541     GR_STATIC_ASSERT(4 == (int)GrStencilTest::kLess);
542     GR_STATIC_ASSERT(5 == (int)GrStencilTest::kLEqual);
543     GR_STATIC_ASSERT(6 == (int)GrStencilTest::kEqual);
544     GR_STATIC_ASSERT(7 == (int)GrStencilTest::kNotEqual);
545     SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
546 
547     return gTable[(int)test];
548 }
549 
550