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