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