xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gl/GrGLUtil.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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 #include "src/gpu/ganesh/gl/GrGLUtil.h"
8 
9 #include "include/core/SkString.h"
10 #include "include/gpu/ganesh/gl/GrGLExtensions.h"
11 #include "include/gpu/ganesh/gl/GrGLFunctions.h"
12 #include "include/private/base/SkTArray.h"
13 #include "src/core/SkStringUtils.h"
14 #include "src/gpu/ganesh/GrStencilSettings.h"
15 
16 #include <ctype.h>
17 #include <array>
18 #include <cstdio>
19 #include <cstring>
20 #include <tuple>
21 #include <utility>
22 
23 using namespace skia_private;
24 
25 ///////////////////////////////////////////////////////////////////////////////
26 
27 #if GR_GL_LOG_CALLS
28     bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
29 #endif
30 
31 #if GR_GL_CHECK_ERROR
32     bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
33 #endif
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 
GrGLGetStandardInUseFromString(const char * versionString)37 GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) {
38     if (!versionString) {
39         SkDebugf("nullptr GL version string.");
40         return kNone_GrGLStandard;
41     }
42 
43     int major, minor;
44 
45     // check for desktop
46     int n = sscanf(versionString, "%d.%d", &major, &minor);
47     if (2 == n) {
48         return kGL_GrGLStandard;
49     }
50 
51     // WebGL might look like "OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium))"
52     int esMajor, esMinor;
53     n = sscanf(versionString, "OpenGL ES %d.%d (WebGL %d.%d", &esMajor, &esMinor, &major, &minor);
54     if (4 == n) {
55         return kWebGL_GrGLStandard;
56     }
57 
58     // check for ES 1
59     char profile[2];
60     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor);
61     if (4 == n) {
62         // we no longer support ES1.
63         return kNone_GrGLStandard;
64     }
65 
66     // check for ES2
67     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
68     if (2 == n) {
69         return kGLES_GrGLStandard;
70     }
71     return kNone_GrGLStandard;
72 }
73 
GrGLGetVersionFromString(const char * versionString)74 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
75     if (!versionString) {
76         SkDebugf("nullptr GL version string.");
77         return GR_GL_INVALID_VER;
78     }
79 
80     int major, minor;
81 
82     // check for mesa
83     int mesaMajor, mesaMinor;
84     int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
85     if (4 == n) {
86         return GR_GL_VER(major, minor);
87     }
88 
89     n = sscanf(versionString, "%d.%d", &major, &minor);
90     if (2 == n) {
91         return GR_GL_VER(major, minor);
92     }
93 
94     // WebGL might look like "OpenGL ES 2.0 (WebGL 1.0 (OpenGL ES 2.0 Chromium))"
95     int esMajor, esMinor;
96     n = sscanf(versionString, "OpenGL ES %d.%d (WebGL %d.%d", &esMajor, &esMinor, &major, &minor);
97     if (4 == n) {
98         return GR_GL_VER(major, minor);
99     }
100 
101     char profile[2];
102     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile + 1, &major, &minor);
103     if (4 == n) {
104         return GR_GL_VER(major, minor);
105     }
106 
107     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
108     if (2 == n) {
109         return GR_GL_VER(major, minor);
110     }
111 
112     return GR_GL_INVALID_VER;
113 }
114 
GrGLGetVersion(const GrGLInterface * gl)115 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
116     SkASSERT(gl);
117     const GrGLubyte* v;
118     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
119     return GrGLGetVersionFromString((const char*)v);
120 }
121 
get_glsl_version(const char * versionString)122 static GrGLSLVersion get_glsl_version(const char* versionString) {
123     SkASSERT(versionString);
124     int major, minor;
125 
126     int n = sscanf(versionString, "%d.%d", &major, &minor);
127     if (2 == n) {
128         return GR_GLSL_VER(major, minor);
129     }
130 
131     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
132     if (2 == n) {
133         return GR_GLSL_VER(major, minor);
134     }
135 
136 #ifdef SK_BUILD_FOR_ANDROID
137     // android hack until the gpu vender updates their drivers
138     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
139     if (2 == n) {
140         return GR_GLSL_VER(major, minor);
141     }
142 #endif
143 
144     return GR_GLSL_INVALID_VER;
145 }
146 
get_vendor(const char * vendorString)147 static GrGLVendor get_vendor(const char* vendorString) {
148     SkASSERT(vendorString);
149     if (0 == strcmp(vendorString, "ARM")) {
150         return GrGLVendor::kARM;
151     }
152     if (0 == strcmp(vendorString, "Google Inc.")) {
153         return GrGLVendor::kGoogle;
154     }
155     if (0 == strcmp(vendorString, "Imagination Technologies")) {
156         return GrGLVendor::kImagination;
157     }
158     if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
159         return GrGLVendor::kIntel;
160     }
161     if (0 == strcmp(vendorString, "Qualcomm") || 0 == strcmp(vendorString, "freedreno")) {
162         return GrGLVendor::kQualcomm;
163     }
164     if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
165         return GrGLVendor::kNVIDIA;
166     }
167     if (0 == strcmp(vendorString, "ATI Technologies Inc.")) {
168         return GrGLVendor::kATI;
169     }
170     if (0 == strcmp(vendorString, "Apple")) {
171         return GrGLVendor::kApple;
172     }
173     return GrGLVendor::kOther;
174 }
175 
get_renderer(const char * rendererString,const GrGLExtensions & extensions)176 static GrGLRenderer get_renderer(const char* rendererString, const GrGLExtensions& extensions) {
177     SkASSERT(rendererString);
178     static const char kTegraStr[] = "NVIDIA Tegra";
179     if (0 == strncmp(rendererString, kTegraStr, std::size(kTegraStr) - 1)) {
180         // Tegra strings are not very descriptive. We distinguish between the modern and legacy
181         // architectures by the presence of NV_path_rendering.
182         return extensions.has("GL_NV_path_rendering") ? GrGLRenderer::kTegra
183                                                       : GrGLRenderer::kTegra_PreK1;
184     }
185     int lastDigit;
186     int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
187     if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
188         return GrGLRenderer::kPowerVR54x;
189     }
190     if (strstr(rendererString, "PowerVR B-Series")) {
191         return GrGLRenderer::kPowerVRBSeries;
192     }
193     // certain iOS devices also use PowerVR54x GPUs
194     static const char kAppleA4Str[] = "Apple A4";
195     static const char kAppleA5Str[] = "Apple A5";
196     static const char kAppleA6Str[] = "Apple A6";
197     if (0 == strncmp(rendererString, kAppleA4Str, std::size(kAppleA4Str) - 1) ||
198         0 == strncmp(rendererString, kAppleA5Str, std::size(kAppleA5Str) - 1) ||
199         0 == strncmp(rendererString, kAppleA6Str, std::size(kAppleA6Str) - 1)) {
200         return GrGLRenderer::kPowerVR54x;
201     }
202     static const char kPowerVRRogueStr[] = "PowerVR Rogue";
203     static const char kAppleA7Str[] = "Apple A7";
204     static const char kAppleA8Str[] = "Apple A8";
205     if (0 == strncmp(rendererString, kPowerVRRogueStr, std::size(kPowerVRRogueStr) - 1) ||
206         0 == strncmp(rendererString, kAppleA7Str, std::size(kAppleA7Str) - 1) ||
207         0 == strncmp(rendererString, kAppleA8Str, std::size(kAppleA8Str) - 1)) {
208         return GrGLRenderer::kPowerVRRogue;
209     }
210     int adrenoNumber;
211     n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber);
212     if (n < 1) {
213         // retry with freedreno driver
214         n = sscanf(rendererString, "FD%d", &adrenoNumber);
215     }
216     if (1 == n) {
217         if (adrenoNumber >= 300) {
218             if (adrenoNumber < 400) {
219                 return GrGLRenderer::kAdreno3xx;
220             }
221             if (adrenoNumber < 500) {
222                 return adrenoNumber >= 430 ? GrGLRenderer::kAdreno430
223                                            : GrGLRenderer::kAdreno4xx_other;
224             }
225             if (adrenoNumber < 600) {
226                 return adrenoNumber == 530 ? GrGLRenderer::kAdreno530
227                                            : GrGLRenderer::kAdreno5xx_other;
228             }
229             if (adrenoNumber < 700) {
230                 if (adrenoNumber == 615) {
231                     return GrGLRenderer::kAdreno615;
232                 }
233                 if (adrenoNumber == 620) {
234                     return GrGLRenderer::kAdreno620;
235                 }
236                 if (adrenoNumber == 630) {
237                     return GrGLRenderer::kAdreno630;
238                 }
239                 if (adrenoNumber == 640) {
240                     return GrGLRenderer::kAdreno640;
241                 }
242                 return GrGLRenderer::kAdreno6xx_other;
243             }
244         }
245     }
246 
247     if (const char* intelString = strstr(rendererString, "Intel")) {
248         // These generic strings seem to always come from Haswell: Iris 5100 or Iris Pro 5200
249         if (0 == strcmp("Intel Iris OpenGL Engine", intelString) ||
250             0 == strcmp("Intel Iris Pro OpenGL Engine", intelString)) {
251             return GrGLRenderer::kIntelHaswell;
252         }
253         if (strstr(intelString, "Sandybridge")) {
254             return GrGLRenderer::kIntelSandyBridge;
255         }
256         if (strstr(intelString, "Bay Trail")) {
257             return GrGLRenderer::kIntelValleyView;
258         }
259         // In Mesa, 'RKL' can be followed by 'Graphics', same for 'TGL' and 'ADL'.
260         // Referenced from the following Mesa source code:
261         // https://github.com/mesa3d/mesa/blob/master/include/pci_ids/iris_pci_ids.h
262         if (strstr(intelString, "RKL")) {
263             return GrGLRenderer::kIntelRocketLake;
264         }
265         if (strstr(intelString, "TGL")) {
266             return GrGLRenderer::kIntelTigerLake;
267         }
268         // For Windows on ADL-S devices, 'AlderLake-S' might be followed by 'Intel(R)'.
269         if (strstr(intelString, "ADL") || strstr(intelString, "AlderLake")) {
270             return GrGLRenderer::kIntelAlderLake;
271         }
272         // For Windows on TGL or other ADL devices, we might only get 'Xe' from the string.
273         // Since they are both 12th gen, we could temporarily use 'kIntelTigerLake' to cover
274         // both TGL and ADL.
275         if (strstr(intelString, "Xe")) {
276             return GrGLRenderer::kIntelTigerLake;
277         }
278         // There are many possible intervening strings here:
279         // 'Intel(R)' is a common prefix
280         // 'Iris' may appear, followed by '(R)' or '(TM)'
281         // 'Iris' can then be followed by 'Graphics', 'Pro Graphics', or 'Plus Graphics'
282         // If 'Iris' isn't there, we might have 'HD Graphics' or 'UHD Graphics'
283         //
284         // In all cases, though, we end with 'Graphics ', an optional 'P', and a number,
285         // so just skip to that and handle two cases:
286         if (const char* intelGfxString = strstr(intelString, "Graphics")) {
287             int intelNumber;
288             if (sscanf(intelGfxString, "Graphics %d", &intelNumber) ||
289                 sscanf(intelGfxString, "Graphics P%d", &intelNumber)) {
290                 if (intelNumber == 2000 || intelNumber == 3000) {
291                     return GrGLRenderer::kIntelSandyBridge;
292                 }
293                 if (intelNumber == 2500 || intelNumber == 4000) {
294                     return GrGLRenderer::kIntelIvyBridge;
295                 }
296                 if (intelNumber >= 4200 && intelNumber <= 5200) {
297                     return GrGLRenderer::kIntelHaswell;
298                 }
299                 if (intelNumber >= 400 && intelNumber <= 405) {
300                     return GrGLRenderer::kIntelCherryView;
301                 }
302                 if (intelNumber >= 5300 && intelNumber <= 6300) {
303                     return GrGLRenderer::kIntelBroadwell;
304                 }
305                 if (intelNumber >= 500 && intelNumber <= 505) {
306                     return GrGLRenderer::kIntelApolloLake;
307                 }
308                 if (intelNumber >= 510 && intelNumber <= 580) {
309                     return GrGLRenderer::kIntelSkyLake;
310                 }
311                 if (intelNumber >= 600 && intelNumber <= 605) {
312                     return GrGLRenderer::kIntelGeminiLake;
313                 }
314                 // 610 and 630 are reused from KabyLake to CoffeeLake. The CoffeeLake variants
315                 // are "UHD Graphics", while the KabyLake ones are "HD Graphics"
316                 if (intelNumber == 610 || intelNumber == 630) {
317                     return strstr(intelString, "UHD") ? GrGLRenderer::kIntelCoffeeLake
318                                                       : GrGLRenderer::kIntelKabyLake;
319                 }
320                 if (intelNumber >= 610 && intelNumber <= 650) {
321                     return GrGLRenderer::kIntelKabyLake;
322                 }
323                 if (intelNumber == 655) {
324                     return GrGLRenderer::kIntelCoffeeLake;
325                 }
326                 // 710/730/750/770 are all 12th gen UHD Graphics, but it's hard to distinguish
327                 // among RKL, TGL and ADL. We might temporarily use 'kIntelTigerLake' to cover all.
328                 if (intelNumber >= 710 && intelNumber <= 770) {
329                     return GrGLRenderer::kIntelTigerLake;
330                 }
331                 if (intelNumber >= 910 && intelNumber <= 950) {
332                     return GrGLRenderer::kIntelIceLake;
333                 }
334             }
335         }
336     }
337 
338     // The AMD string can have a somewhat arbitrary preamble (see skbug.com/7195)
339     static constexpr char kRadeonStr[] = "Radeon ";
340     if (const char* amdString = strstr(rendererString, kRadeonStr)) {
341         amdString += strlen(kRadeonStr);
342         // Sometimes there is a (TM) and sometimes not.
343         static constexpr char kTMStr[] = "(TM) ";
344         if (!strncmp(amdString, kTMStr, strlen(kTMStr))) {
345             amdString += strlen(kTMStr);
346         }
347 
348         char amd0, amd1, amd2;
349         int amdModel;
350         n = sscanf(amdString, "R9 M3%c%c", &amd0, &amd1);
351         if (2 == n && isdigit(amd0) && isdigit(amd1)) {
352             return GrGLRenderer::kAMDRadeonR9M3xx;
353         }
354 
355         n = sscanf(amdString, "R9 M4%c%c", &amd0, &amd1);
356         if (2 == n && isdigit(amd0) && isdigit(amd1)) {
357             return GrGLRenderer::kAMDRadeonR9M4xx;
358         }
359 
360         n = sscanf(amdString, "HD 7%c%c%c Series", &amd0, &amd1, &amd2);
361         if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) {
362             return GrGLRenderer::kAMDRadeonHD7xxx;
363         }
364 
365         n = sscanf(amdString, "Pro 5%c%c%c", &amd0, &amd1, &amd2);
366         if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) {
367             return GrGLRenderer::kAMDRadeonPro5xxx;
368         }
369 
370         n = sscanf(amdString, "Pro Vega %i", &amdModel);
371         if (1 == n) {
372             return GrGLRenderer::kAMDRadeonProVegaxx;
373         }
374     }
375 
376     if (strstr(rendererString, "llvmpipe")) {
377         return GrGLRenderer::kGalliumLLVM;
378     }
379     static const char kMaliGStr[] = "Mali-G";
380     if (0 == strncmp(rendererString, kMaliGStr, std::size(kMaliGStr) - 1)) {
381         return GrGLRenderer::kMaliG;
382     }
383     static const char kMaliTStr[] = "Mali-T";
384     if (0 == strncmp(rendererString, kMaliTStr, std::size(kMaliTStr) - 1)) {
385         return GrGLRenderer::kMaliT;
386     }
387     int mali400Num;
388     if (1 == sscanf(rendererString, "Mali-%d", &mali400Num) && mali400Num >= 400 &&
389         mali400Num < 500) {
390         return GrGLRenderer::kMali4xx;
391     }
392 
393     static const char kAppleStr[] = "Apple";
394     if (0 == strncmp(rendererString, kAppleStr, std::size(kAppleStr) - 1)) {
395         return GrGLRenderer::kApple;
396     }
397 
398     if (strstr(rendererString, "WebGL")) {
399         return GrGLRenderer::kWebGL;
400     }
401 
402     return GrGLRenderer::kOther;
403 }
404 
is_commamd_buffer(const char * rendererString,const char * versionString)405 static bool is_commamd_buffer(const char* rendererString, const char* versionString) {
406     SkASSERT(rendererString);
407     SkASSERT(versionString);
408 
409     int major, minor;
410     static const char kChromium[] = "Chromium";
411     char suffix[std::size(kChromium)] = {0};
412     return (0 == strcmp(rendererString, kChromium) ||
413            (3 == sscanf(versionString, "OpenGL ES %d.%d %8s", &major, &minor, suffix) &&
414             0 == strcmp(kChromium, suffix)));
415 }
416 
is_virgl(const char * rendererString)417 static bool is_virgl(const char* rendererString) {
418     return !!strstr(rendererString, "virgl");
419 }
420 
get_driver_and_version(GrGLStandard standard,GrGLVendor vendor,const char * vendorString,const char * rendererString,const char * versionString)421 static std::tuple<GrGLDriver, GrGLDriverVersion> get_driver_and_version(GrGLStandard standard,
422                                                                         GrGLVendor vendor,
423                                                                         const char* vendorString,
424                                                                         const char* rendererString,
425                                                                         const char* versionString) {
426     SkASSERT(rendererString);
427     SkASSERT(versionString);
428 
429     GrGLDriver driver               = GrGLDriver::kUnknown;
430     GrGLDriverVersion driverVersion = GR_GL_DRIVER_UNKNOWN_VER;
431 
432     int major, minor, rev, driverMajor, driverMinor, driverPoint;
433     // This is the same on ES and regular GL.
434     if (!strcmp(vendorString, "freedreno")) {
435         driver = GrGLDriver::kFreedreno;
436     } else if (GR_IS_GR_GL(standard)) {
437         if (vendor == GrGLVendor::kNVIDIA) {
438             driver = GrGLDriver::kNVIDIA;
439             int n = sscanf(versionString,
440                            "%d.%d.%d NVIDIA %d.%d",
441                            &major,
442                            &minor,
443                            &rev,
444                            &driverMajor,
445                            &driverMinor);
446             // Some older NVIDIA drivers don't report the driver version.
447             if (n == 5) {
448                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
449             }
450         } else {
451             int n = sscanf(versionString,
452                            "%d.%d Mesa %d.%d",
453                            &major,
454                            &minor,
455                            &driverMajor,
456                            &driverMinor);
457             if (n != 4) {
458                 n = sscanf(versionString,
459                            "%d.%d (Core Profile) Mesa %d.%d",
460                            &major,
461                            &minor,
462                            &driverMajor,
463                            &driverMinor);
464             }
465             if (n == 4) {
466                 driver = GrGLDriver::kMesa;
467                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
468             }
469         }
470     } else if (standard == kGLES_GrGLStandard) {
471         if (vendor == GrGLVendor::kNVIDIA) {
472             driver = GrGLDriver::kNVIDIA;
473             int n = sscanf(versionString,
474                            "OpenGL ES %d.%d NVIDIA %d.%d",
475                            &major,
476                            &minor,
477                            &driverMajor,
478                            &driverMinor);
479             // Some older NVIDIA drivers don't report the driver version.
480             if (n == 4) {
481                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
482             }
483         } else if (vendor == GrGLVendor::kImagination) {
484             int revision;
485             int n = sscanf(versionString,
486                            "OpenGL ES %d.%d build %d.%d@%d",
487                            &major,
488                            &minor,
489                            &driverMajor,
490                            &driverMinor,
491                            &revision);
492             if (n == 5) {
493                 driver = GrGLDriver::kImagination;
494                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
495             }
496         } else {
497             int n = sscanf(versionString,
498                            "OpenGL ES %d.%d Mesa %d.%d",
499                            &major,
500                            &minor,
501                            &driverMajor,
502                            &driverMinor);
503             if (n == 4) {
504                 driver = GrGLDriver::kMesa;
505                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
506             }
507         }
508     }
509 
510     if (driver == GrGLDriver::kUnknown) {
511         if (vendor == GrGLVendor::kIntel) {
512             // We presume we're on the Intel driver since it hasn't identified itself as Mesa.
513             driver = GrGLDriver::kIntel;
514 
515             // This is how the macOS version strings are structured. This might be different on
516             // different
517             //  OSes.
518             int n = sscanf(versionString,
519                            "%d.%d INTEL-%d.%d.%d",
520                            &major,
521                            &minor,
522                            &driverMajor,
523                            &driverMinor,
524                            &driverPoint);
525             if (n == 5) {
526                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
527             }
528         } else if (vendor == GrGLVendor::kQualcomm) {
529             driver = GrGLDriver::kQualcomm;
530             int n = sscanf(versionString,
531                            "OpenGL ES %d.%d V@%d.%d",
532                            &major,
533                            &minor,
534                            &driverMajor,
535                            &driverMinor);
536             if (n == 4) {
537                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
538             }
539         } else if (vendor == GrGLVendor::kImagination) {
540             int revision;
541             int n = sscanf(versionString,
542                            "OpenGL ES %d.%d build %d.%d@%d",
543                            &major,
544                            &minor,
545                            &driverMajor,
546                            &driverMinor,
547                            &revision);
548             if (n == 5) {
549                 // Revision is a large number (looks like a source control revision number) that
550                 // doesn't fit into the 'patch' bits, so omit it until we need it.
551                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
552             }
553         } else if (vendor == GrGLVendor::kARM) {
554             // Example:
555             // OpenGL ES 3.2 v1.r26p0-01rel0.217d2597f6bd19b169343737782e56e3
556             // It's unclear how to interpret what comes between "p" and "rel". Every string we've
557             // seen so far has "0-01" there. We ignore it for now.
558             int ignored0;
559             int ignored1;
560             int n = sscanf(versionString,
561                            "OpenGL ES %d.%d v%d.r%dp%d-%drel",
562                            &major,
563                            &minor,
564                            &driverMajor,
565                            &driverMinor,
566                            &ignored0,
567                            &ignored1);
568             if (n == 6) {
569                 driver = GrGLDriver::kARM;
570                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
571             }
572         } else if (vendor == GrGLVendor::kApple) {
573             // There doesn't appear to be a minor version
574             int n = sscanf(versionString,
575                            "%d.%d Metal - %d",
576                            &major,
577                            &minor,
578                            &driverMajor);
579             if (n == 3) {
580                 driver = GrGLDriver::kApple;
581                 driverVersion = GR_GL_DRIVER_VER(driverMajor, 0, 0);
582             }
583         } else {
584             static constexpr char kEmulatorPrefix[] = "Android Emulator OpenGL ES Translator";
585             if (0 == strncmp(kEmulatorPrefix, rendererString, strlen(kEmulatorPrefix))) {
586                 driver = GrGLDriver::kAndroidEmulator;
587             }
588         }
589     }
590     return {driver, driverVersion};
591 }
592 
593 // If this is detected as ANGLE then the ANGLE backend is returned along with rendererString
594 // stripped of "ANGLE(" and ")" at the start and end, respectively.
get_angle_backend(const char * rendererString)595 static std::tuple<GrGLANGLEBackend, SkString> get_angle_backend(const char* rendererString) {
596     // crbug.com/1203705 ANGLE renderer will be "ANGLE (<gl-vendor>, <gl-renderer>, <gl-version>)"
597     // on ANGLE's GL backend with related substitutions for the inner strings on other backends.
598     static constexpr char kHeader[] = "ANGLE (";
599     static constexpr size_t kHeaderLength = std::size(kHeader) - 1;
600     int rendererLength = strlen(rendererString);
601     if (!strncmp(rendererString, kHeader, kHeaderLength) &&
602         rendererString[rendererLength - 1] == ')') {
603         SkString innerString;
604         innerString.set(rendererString + kHeaderLength, rendererLength - kHeaderLength - 1);
605         if (strstr(rendererString, "Direct3D11")) {
606             return {GrGLANGLEBackend::kD3D11, std::move(innerString)};
607         } else if (strstr(rendererString, "Direct3D9")) {
608             return {GrGLANGLEBackend::kD3D9, std::move(innerString)};
609         } else if (strstr(rendererString, "Metal")) {
610             return {GrGLANGLEBackend::kMetal, std::move(innerString)};
611         } else if (strstr(rendererString, "OpenGL")) {
612             return {GrGLANGLEBackend::kOpenGL, std::move(innerString)};
613         } else if (strstr(rendererString, "Vulkan")) {
614             return {GrGLANGLEBackend::kVulkan, std::move(innerString)};
615         }
616     }
617     return {GrGLANGLEBackend::kUnknown, {}};
618 }
619 
620 static std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion>
get_angle_gl_vendor_and_renderer(const char * innerString,const GrGLExtensions & extensions)621 get_angle_gl_vendor_and_renderer(
622         const char* innerString,
623         const GrGLExtensions& extensions) {
624     TArray<SkString> parts;
625     SkStrSplit(innerString, ",", &parts);
626     // This would need some fixing if we have substrings that contain commas.
627     if (parts.size() != 3) {
628         return {GrGLVendor::kOther,
629                 GrGLRenderer::kOther,
630                 GrGLDriver::kUnknown,
631                 GR_GL_DRIVER_UNKNOWN_VER};
632     }
633 
634     const char* angleVendorString   = parts[0].c_str();
635     const char* angleRendererString = parts[1].c_str() + 1; // skip initial space
636     const char* angleVersionString  = parts[2].c_str() + 1; // skip initial space
637 
638     GrGLVendor angleVendor = get_vendor(angleVendorString);
639 
640     auto [angleDriver, angleDriverVersion] = get_driver_and_version(kGLES_GrGLStandard,
641                                                                     angleVendor,
642                                                                     angleVendorString,
643                                                                     angleRendererString,
644                                                                     angleVersionString);
645 
646     auto angleRenderer = get_renderer(angleRendererString, extensions);
647 
648     return {angleVendor, angleRenderer, angleDriver, angleDriverVersion};
649 }
650 
get_angle_metal_vendor(const char * innerString)651 static GrGLVendor get_angle_metal_vendor(const char* innerString) {
652     if (strstr(innerString, "Intel")) {
653         return GrGLVendor::kIntel;
654     }
655 
656     return GrGLVendor::kOther;
657 }
658 
get_angle_vulkan_vendor(const char * innerString)659 static GrGLVendor get_angle_vulkan_vendor(const char* innerString) {
660     if (strstr(innerString, "ARM")) {
661         return GrGLVendor::kARM;
662     }
663 
664     return GrGLVendor::kOther;
665 }
666 
667 static std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion>
get_angle_d3d_vendor_and_renderer(const char * innerString)668 get_angle_d3d_vendor_and_renderer(const char* innerString) {
669     auto vendor   = GrGLVendor::kOther;
670     auto renderer = GrGLRenderer::kOther;
671 
672     if (strstr(innerString, "Intel")) {
673         vendor = GrGLVendor::kIntel;
674 
675         const char* modelStr;
676         int modelNumber;
677         if ((modelStr = strstr(innerString, "HD Graphics")) &&
678             (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) ||
679              1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) {
680             switch (modelNumber) {
681                 case 2000:
682                 case 3000:
683                     renderer = GrGLRenderer::kIntelSandyBridge;
684                     break;
685                 case 4000:
686                 case 2500:
687                     renderer = GrGLRenderer::kIntelSandyBridge;
688                     break;
689                 case 510:
690                 case 515:
691                 case 520:
692                 case 530:
693                     renderer = GrGLRenderer::kIntelSkyLake;
694                     break;
695             }
696         } else if ((modelStr = strstr(innerString, "Iris")) &&
697                    (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) ||
698                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) ||
699                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) {
700             switch (modelNumber) {
701                 case 540:
702                 case 550:
703                 case 555:
704                 case 580:
705                     renderer = GrGLRenderer::kIntelSkyLake;
706                     break;
707             }
708         }
709     } else if (strstr(innerString, "NVIDIA")) {
710         vendor = GrGLVendor::kNVIDIA;
711     } else if (strstr(innerString, "Radeon")) {
712         vendor = GrGLVendor::kATI;
713     }
714     // We haven't had a need yet to parse the D3D driver string.
715     return {vendor, renderer, GrGLDriver::kUnknown, GR_GL_DRIVER_UNKNOWN_VER};
716 }
717 
718 static std::tuple<GrGLVendor, GrGLRenderer>
get_webgl_vendor_and_renderer(const GrGLInterface * interface)719 get_webgl_vendor_and_renderer(
720         const GrGLInterface* interface) {
721     if (!interface->fExtensions.has("WEBGL_debug_renderer_info")) {
722         return {GrGLVendor::kOther,
723                 GrGLRenderer::kOther};
724     }
725 
726     auto getString = [&](GrGLenum s) {
727         const GrGLubyte* bytes = interface->fFunctions.fGetString(s);
728         if (!bytes) {
729             return "";
730         }
731         return reinterpret_cast<const char*>(bytes);
732     };
733 
734     const char* webglVendorString = getString(GR_UNMASKED_VENDOR_WEBGL);
735     const char* webglRendererString = getString(GR_UNMASKED_RENDERER_WEBGL);
736 
737     GrGLVendor webglVendor = get_vendor(webglVendorString);
738     GrGLRenderer webglRenderer = get_renderer(webglRendererString, interface->fExtensions);
739 
740     if (webglVendor == GrGLVendor::kOther && strstr(webglRendererString, "Intel")) {
741         webglVendor = GrGLVendor::kIntel;
742     }
743 
744     return {webglVendor, webglRenderer};
745 }
746 
GrGLGetDriverInfo(const GrGLInterface * interface)747 GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
748     if (!interface) {
749         return {};
750     }
751     SkASSERT(interface->fStandard != kNone_GrGLStandard);
752     GrGLDriverInfo info;
753     info.fStandard = interface->fStandard;
754 
755     auto getString = [&](GrGLenum s) {
756         const GrGLubyte* bytes = interface->fFunctions.fGetString(s);
757         if (!bytes) {
758             return "";
759         }
760         return reinterpret_cast<const char*>(bytes);
761     };
762 
763     const char* const version   = getString(GR_GL_VERSION);
764     const char* const slversion = getString(GR_GL_SHADING_LANGUAGE_VERSION);
765     const char* const renderer  = getString(GR_GL_RENDERER);
766     const char* const vendor    = getString(GR_GL_VENDOR);
767 
768     info.fVersion     = GrGLGetVersionFromString(version);
769     info.fGLSLVersion = get_glsl_version(slversion);
770     info.fVendor      = get_vendor(vendor);
771     info.fRenderer    = get_renderer(renderer, interface->fExtensions);
772 
773     std::tie(info.fDriver, info.fDriverVersion) = get_driver_and_version(interface->fStandard,
774                                                                          info.fVendor,
775                                                                          vendor,
776                                                                          renderer,
777                                                                          version);
778 
779     SkString innerAngleRendererString;
780     std::tie(info.fANGLEBackend, innerAngleRendererString) = get_angle_backend(renderer);
781 
782     if (info.fANGLEBackend == GrGLANGLEBackend::kD3D9 ||
783         info.fANGLEBackend == GrGLANGLEBackend::kD3D11) {
784         std::tie(info.fANGLEVendor,
785                  info.fANGLERenderer,
786                  info.fANGLEDriver,
787                  info.fANGLEDriverVersion) =
788                 get_angle_d3d_vendor_and_renderer(innerAngleRendererString.c_str());
789     } else if (info.fANGLEBackend == GrGLANGLEBackend::kOpenGL) {
790         std::tie(info.fANGLEVendor,
791                  info.fANGLERenderer,
792                  info.fANGLEDriver,
793                  info.fANGLEDriverVersion) =
794                 get_angle_gl_vendor_and_renderer(innerAngleRendererString.c_str(),
795                                                  interface->fExtensions);
796     } else if (info.fANGLEBackend == GrGLANGLEBackend::kMetal) {
797         info.fANGLEVendor = get_angle_metal_vendor(innerAngleRendererString.c_str());
798     } else if (info.fANGLEBackend == GrGLANGLEBackend::kVulkan) {
799         info.fANGLEVendor = get_angle_vulkan_vendor(innerAngleRendererString.c_str());
800     }
801 
802     if (info.fRenderer == GrGLRenderer::kWebGL) {
803         std::tie(info.fWebGLVendor,
804                  info.fWebGLRenderer) =
805                 get_webgl_vendor_and_renderer(interface);
806 
807     }
808 
809     info.fIsOverCommandBuffer = is_commamd_buffer(renderer, version);
810 
811     info.fIsRunningOverVirgl = is_virgl(renderer);
812 
813     return info;
814 }
815 
GrToGLStencilFunc(GrStencilTest test)816 GrGLenum GrToGLStencilFunc(GrStencilTest test) {
817     static const GrGLenum gTable[kGrStencilTestCount] = {
818         GR_GL_ALWAYS,           // kAlways
819         GR_GL_NEVER,            // kNever
820         GR_GL_GREATER,          // kGreater
821         GR_GL_GEQUAL,           // kGEqual
822         GR_GL_LESS,             // kLess
823         GR_GL_LEQUAL,           // kLEqual
824         GR_GL_EQUAL,            // kEqual
825         GR_GL_NOTEQUAL,         // kNotEqual
826     };
827     static_assert(0 == (int)GrStencilTest::kAlways);
828     static_assert(1 == (int)GrStencilTest::kNever);
829     static_assert(2 == (int)GrStencilTest::kGreater);
830     static_assert(3 == (int)GrStencilTest::kGEqual);
831     static_assert(4 == (int)GrStencilTest::kLess);
832     static_assert(5 == (int)GrStencilTest::kLEqual);
833     static_assert(6 == (int)GrStencilTest::kEqual);
834     static_assert(7 == (int)GrStencilTest::kNotEqual);
835     SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
836 
837     return gTable[(int)test];
838 }
839 
GrGLFormatIsCompressed(GrGLFormat format)840 bool GrGLFormatIsCompressed(GrGLFormat format) {
841     switch (format) {
842         case GrGLFormat::kCOMPRESSED_ETC1_RGB8:
843         case GrGLFormat::kCOMPRESSED_RGB8_ETC2:
844         case GrGLFormat::kCOMPRESSED_RGB8_BC1:
845         case GrGLFormat::kCOMPRESSED_RGBA8_BC1:
846             return true;
847 
848         case GrGLFormat::kRGBA8:
849         case GrGLFormat::kR8:
850         case GrGLFormat::kALPHA8:
851         case GrGLFormat::kLUMINANCE8:
852         case GrGLFormat::kLUMINANCE8_ALPHA8:
853         case GrGLFormat::kBGRA8:
854         case GrGLFormat::kRGB565:
855         case GrGLFormat::kRGBA16F:
856         case GrGLFormat::kR16F:
857         case GrGLFormat::kLUMINANCE16F:
858         case GrGLFormat::kRGB8:
859         case GrGLFormat::kRGBX8:
860         case GrGLFormat::kRG8:
861         case GrGLFormat::kRGB10_A2:
862         case GrGLFormat::kRGBA4:
863         case GrGLFormat::kSRGB8_ALPHA8:
864         case GrGLFormat::kR16:
865         case GrGLFormat::kRG16:
866         case GrGLFormat::kRGBA16:
867         case GrGLFormat::kRG16F:
868         case GrGLFormat::kSTENCIL_INDEX8:
869         case GrGLFormat::kSTENCIL_INDEX16:
870         case GrGLFormat::kDEPTH24_STENCIL8:
871         case GrGLFormat::kUnknown:
872             return false;
873     }
874     SkUNREACHABLE;
875 }
876