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
14void GrGLClearErr(const GrGLInterface* gl) {
15    while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {}
16}
17
18namespace {
19const 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
38void 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
66GrGLStandard 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
96void 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;
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);
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);
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);
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);
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);
172            }
173            return;
174        }
175    }
176
177    if (kIntel_GrGLVendor == vendor) {
178        // We presume we're on the Intel driver since it hasn't identified itself as Mesa.
179        *outDriver = kIntel_GrGLDriver;
180    }
181
182    if (kQualcomm_GrGLVendor == vendor) {
183        *outDriver = kQualcomm_GrGLDriver;
184        int n = sscanf(versionString, "OpenGL ES %d.%d V@%d.%d", &major, &minor, &driverMajor,
185                       &driverMinor);
186        if (4 == n) {
187            *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
188        }
189        return;
190    }
191}
192
193GrGLVersion GrGLGetVersionFromString(const char* versionString) {
194    if (nullptr == versionString) {
195        SkDebugf("nullptr GL version string.");
196        return GR_GL_INVALID_VER;
197    }
198
199    int major, minor;
200
201    // check for mesa
202    int mesaMajor, mesaMinor;
203    int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
204    if (4 == n) {
205        return GR_GL_VER(major, minor);
206    }
207
208    n = sscanf(versionString, "%d.%d", &major, &minor);
209    if (2 == n) {
210        return GR_GL_VER(major, minor);
211    }
212
213    char profile[2];
214    n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
215               &major, &minor);
216    if (4 == n) {
217        return GR_GL_VER(major, minor);
218    }
219
220    n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
221    if (2 == n) {
222        return GR_GL_VER(major, minor);
223    }
224
225    return GR_GL_INVALID_VER;
226}
227
228GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
229    if (nullptr == versionString) {
230        SkDebugf("nullptr GLSL version string.");
231        return GR_GLSL_INVALID_VER;
232    }
233
234    int major, minor;
235
236    int n = sscanf(versionString, "%d.%d", &major, &minor);
237    if (2 == n) {
238        return GR_GLSL_VER(major, minor);
239    }
240
241    n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
242    if (2 == n) {
243        return GR_GLSL_VER(major, minor);
244    }
245
246#ifdef SK_BUILD_FOR_ANDROID
247    // android hack until the gpu vender updates their drivers
248    n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
249    if (2 == n) {
250        return GR_GLSL_VER(major, minor);
251    }
252#endif
253
254    return GR_GLSL_INVALID_VER;
255}
256
257GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
258    if (vendorString) {
259        if (0 == strcmp(vendorString, "ARM")) {
260            return kARM_GrGLVendor;
261        }
262        if (0 == strcmp(vendorString, "Imagination Technologies")) {
263            return kImagination_GrGLVendor;
264        }
265        if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
266            return kIntel_GrGLVendor;
267        }
268        if (0 == strcmp(vendorString, "Qualcomm")) {
269            return kQualcomm_GrGLVendor;
270        }
271        if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
272            return kNVIDIA_GrGLVendor;
273        }
274        if (0 == strcmp(vendorString, "ATI Technologies Inc.")) {
275            return kATI_GrGLVendor;
276        }
277    }
278    return kOther_GrGLVendor;
279}
280
281static bool is_renderer_angle(const char* rendererString) {
282    static constexpr char kHeader[] = "ANGLE ";
283    static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1;
284    return 0 == strncmp(rendererString, kHeader, kHeaderLength);
285}
286
287GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
288    if (rendererString) {
289        if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
290            return kTegra3_GrGLRenderer;
291        } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
292            return kTegra2_GrGLRenderer;
293        }
294        int lastDigit;
295        int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
296        if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
297            return kPowerVR54x_GrGLRenderer;
298        }
299        // certain iOS devices also use PowerVR54x GPUs
300        static const char kAppleA4Str[] = "Apple A4";
301        static const char kAppleA5Str[] = "Apple A5";
302        static const char kAppleA6Str[] = "Apple A6";
303        if (0 == strncmp(rendererString, kAppleA4Str,
304                         SK_ARRAY_COUNT(kAppleA4Str)-1) ||
305            0 == strncmp(rendererString, kAppleA5Str,
306                         SK_ARRAY_COUNT(kAppleA5Str)-1) ||
307            0 == strncmp(rendererString, kAppleA6Str,
308                         SK_ARRAY_COUNT(kAppleA6Str)-1)) {
309            return kPowerVR54x_GrGLRenderer;
310        }
311        static const char kPowerVRRogueStr[] = "PowerVR Rogue";
312        static const char kAppleA7Str[] = "Apple A7";
313        static const char kAppleA8Str[] = "Apple A8";
314        if (0 == strncmp(rendererString, kPowerVRRogueStr,
315                         SK_ARRAY_COUNT(kPowerVRRogueStr)-1) ||
316            0 == strncmp(rendererString, kAppleA7Str,
317                         SK_ARRAY_COUNT(kAppleA7Str)-1) ||
318            0 == strncmp(rendererString, kAppleA8Str,
319                         SK_ARRAY_COUNT(kAppleA8Str)-1)) {
320            return kPowerVRRogue_GrGLRenderer;
321        }
322        int adrenoNumber;
323        n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber);
324        if (1 == n) {
325            if (adrenoNumber >= 300) {
326                if (adrenoNumber < 400) {
327                    return kAdreno3xx_GrGLRenderer;
328                }
329                if (adrenoNumber < 500) {
330                    return kAdreno4xx_GrGLRenderer;
331                }
332                if (adrenoNumber < 600) {
333                    return kAdreno5xx_GrGLRenderer;
334                }
335            }
336        }
337        if (0 == strcmp("Intel Iris Pro OpenGL Engine", rendererString)) {
338            return kIntelIrisPro_GrGLRenderer;
339        }
340
341        int intelNumber;
342        n = sscanf(rendererString, "Intel(R) Iris(TM) Graphics %d", &intelNumber);
343        if (1 != n) {
344            n = sscanf(rendererString, "Intel(R) HD Graphics %d", &intelNumber);
345        }
346        if (1 == n) {
347            if (intelNumber >= 4000 && intelNumber < 5000) {
348                return kIntel4xxx_GrGLRenderer;
349            }
350            if (intelNumber >= 6000 && intelNumber < 7000) {
351                return kIntel6xxx_GrGLRenderer;
352            }
353        }
354
355        // The AMD string can have a somewhat arbitrary preamble (see skbug.com/7195)
356        if (const char* amdString = strstr(rendererString, "Radeon")) {
357            char amdGeneration, amdTier, amdRevision;
358            n = sscanf(amdString, "Radeon (TM) R9 M%c%c%c",
359                                       &amdGeneration, &amdTier, &amdRevision);
360            if (3 == n) {
361                if ('4' == amdGeneration) {
362                    return kAMDRadeonR9M4xx_GrGLRenderer;
363                }
364            }
365
366            char amd0, amd1, amd2;
367            n = sscanf(amdString, "Radeon HD 7%c%c%c Series", &amd0, &amd1, &amd2);
368            if (3 == n) {
369                return kAMDRadeonHD7xxx_GrGLRenderer;
370            }
371        }
372
373        if (0 == strcmp("Mesa Offscreen", rendererString)) {
374            return kOSMesa_GrGLRenderer;
375        }
376        if (strstr(rendererString, "llvmpipe")) {
377            return kGalliumLLVM_GrGLRenderer;
378        }
379        static const char kMaliTStr[] = "Mali-T";
380        if (0 == strncmp(rendererString, kMaliTStr, SK_ARRAY_COUNT(kMaliTStr) - 1)) {
381            return kMaliT_GrGLRenderer;
382        }
383        if (is_renderer_angle(rendererString)) {
384            return kANGLE_GrGLRenderer;
385        }
386    }
387    return kOther_GrGLRenderer;
388}
389
390void GrGLGetANGLEInfoFromString(const char* rendererString, GrGLANGLEBackend* backend,
391                                GrGLANGLEVendor* vendor, GrGLANGLERenderer* renderer) {
392    *backend = GrGLANGLEBackend::kUnknown;
393    *vendor = GrGLANGLEVendor::kUnknown;
394    *renderer = GrGLANGLERenderer::kUnknown;
395    if (!is_renderer_angle(rendererString)) {
396        return;
397    }
398    if (strstr(rendererString, "Intel")) {
399        *vendor = GrGLANGLEVendor::kIntel;
400
401        const char* modelStr;
402        int modelNumber;
403        if ((modelStr = strstr(rendererString, "HD Graphics")) &&
404            (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) ||
405             1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) {
406            switch (modelNumber) {
407                case 4000:
408                case 2500:
409                    *renderer = GrGLANGLERenderer::kIvyBridge;
410                    break;
411                case 510:
412                case 515:
413                case 520:
414                case 530:
415                    *renderer = GrGLANGLERenderer::kSkylake;
416                    break;
417            }
418        } else if ((modelStr = strstr(rendererString, "Iris")) &&
419                   (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) ||
420                    1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) ||
421                    1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) {
422            switch (modelNumber) {
423                case 540:
424                case 550:
425                case 555:
426                case 580:
427                    *renderer = GrGLANGLERenderer::kSkylake;
428                    break;
429            }
430        }
431    }
432    if (strstr(rendererString, "Direct3D11")) {
433        *backend = GrGLANGLEBackend::kD3D11;
434    } else if (strstr(rendererString, "Direct3D9")) {
435        *backend = GrGLANGLEBackend::kD3D9;
436    } else if (strstr(rendererString, "OpenGL")) {
437        *backend = GrGLANGLEBackend::kOpenGL;
438    }
439}
440
441GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
442    const GrGLubyte* v;
443    GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
444    return GrGLGetVersionFromString((const char*) v);
445}
446
447GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
448    const GrGLubyte* v;
449    GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
450    return GrGLGetGLSLVersionFromString((const char*) v);
451}
452
453GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
454    const GrGLubyte* v;
455    GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
456    return GrGLGetVendorFromString((const char*) v);
457}
458
459GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
460    const GrGLubyte* v;
461    GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER));
462    return GrGLGetRendererFromString((const char*) v);
463}
464
465GrGLenum GrToGLStencilFunc(GrStencilTest test) {
466    static const GrGLenum gTable[kGrStencilTestCount] = {
467        GR_GL_ALWAYS,           // kAlways
468        GR_GL_NEVER,            // kNever
469        GR_GL_GREATER,          // kGreater
470        GR_GL_GEQUAL,           // kGEqual
471        GR_GL_LESS,             // kLess
472        GR_GL_LEQUAL,           // kLEqual
473        GR_GL_EQUAL,            // kEqual
474        GR_GL_NOTEQUAL,         // kNotEqual
475    };
476    GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
477    GR_STATIC_ASSERT(1 == (int)GrStencilTest::kNever);
478    GR_STATIC_ASSERT(2 == (int)GrStencilTest::kGreater);
479    GR_STATIC_ASSERT(3 == (int)GrStencilTest::kGEqual);
480    GR_STATIC_ASSERT(4 == (int)GrStencilTest::kLess);
481    GR_STATIC_ASSERT(5 == (int)GrStencilTest::kLEqual);
482    GR_STATIC_ASSERT(6 == (int)GrStencilTest::kEqual);
483    GR_STATIC_ASSERT(7 == (int)GrStencilTest::kNotEqual);
484    SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
485
486    return gTable[(int)test];
487}
488
489GrPixelConfig GrGLSizedFormatToPixelConfig(GrGLenum sizedFormat) {
490    switch (sizedFormat) {
491        case GR_GL_R8:
492            return kAlpha_8_as_Red_GrPixelConfig;
493        case GR_GL_ALPHA8:
494            return kAlpha_8_as_Alpha_GrPixelConfig;
495        case GR_GL_RGBA8:
496            return kRGBA_8888_GrPixelConfig;
497        case GR_GL_BGRA8:
498            return kBGRA_8888_GrPixelConfig;
499        case GR_GL_SRGB8_ALPHA8:
500            return kSRGBA_8888_GrPixelConfig;
501        case GR_GL_RGB565:
502            return kRGB_565_GrPixelConfig;
503        case GR_GL_RGB5:
504            return kRGB_565_GrPixelConfig;
505        case GR_GL_RGBA4:
506            return kRGBA_4444_GrPixelConfig;
507        case GR_GL_RGB10_A2:
508            return kRGBA_1010102_GrPixelConfig;
509        case GR_GL_LUMINANCE8:
510            return kGray_8_GrPixelConfig;
511        case GR_GL_RGBA32F:
512            return kRGBA_float_GrPixelConfig;
513        case GR_GL_RG32F:
514            return kRG_float_GrPixelConfig;
515        case GR_GL_R16F:
516            return kAlpha_half_as_Red_GrPixelConfig;
517        case GR_GL_RGBA16F:
518            return kRGBA_half_GrPixelConfig;
519        default:
520            return kUnknown_GrPixelConfig;
521    }
522}
523
524