• 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/GrTypesPriv.h"
11 #include "src/gpu/GrDataUtils.h"
12 #include "src/gpu/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, SK_ARRAY_COUNT(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, SK_ARRAY_COUNT(kAppleA4Str) - 1) ||
182         0 == strncmp(rendererString, kAppleA5Str, SK_ARRAY_COUNT(kAppleA5Str) - 1) ||
183         0 == strncmp(rendererString, kAppleA6Str, SK_ARRAY_COUNT(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, SK_ARRAY_COUNT(kPowerVRRogueStr) - 1) ||
190         0 == strncmp(rendererString, kAppleA7Str, SK_ARRAY_COUNT(kAppleA7Str) - 1) ||
191         0 == strncmp(rendererString, kAppleA8Str, SK_ARRAY_COUNT(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 == 615) {
214                 return GrGLRenderer::kAdreno615;
215             }
216             if (adrenoNumber == 620) {
217                 return GrGLRenderer::kAdreno620;
218             }
219             if (adrenoNumber == 630) {
220                 return GrGLRenderer::kAdreno630;
221             }
222             if (adrenoNumber == 640) {
223                 return GrGLRenderer::kAdreno640;
224             }
225         }
226     }
227     if (0 == strcmp("Google SwiftShader", rendererString)) {
228         return GrGLRenderer::kGoogleSwiftShader;
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         // There are many possible intervening strings here:
244         // 'Intel(R)' is a common prefix
245         // 'Iris' may appear, followed by '(R)' or '(TM)'
246         // 'Iris' can then be followed by 'Graphics', 'Pro Graphics', or 'Plus Graphics'
247         // If 'Iris' isn't there, we might have 'HD Graphics' or 'UHD Graphics'
248         //
249         // In all cases, though, we end with 'Graphics ', an optional 'P', and a number,
250         // so just skip to that and handle two cases:
251         if (const char* intelGfxString = strstr(intelString, "Graphics")) {
252             int intelNumber;
253             if (sscanf(intelGfxString, "Graphics %d", &intelNumber) ||
254                 sscanf(intelGfxString, "Graphics P%d", &intelNumber)) {
255                 if (intelNumber == 2000 || intelNumber == 3000) {
256                     return GrGLRenderer::kIntelSandyBridge;
257                 }
258                 if (intelNumber == 2500 || intelNumber == 4000) {
259                     return GrGLRenderer::kIntelIvyBridge;
260                 }
261                 if (intelNumber >= 4200 && intelNumber <= 5200) {
262                     return GrGLRenderer::kIntelHaswell;
263                 }
264                 if (intelNumber >= 400 && intelNumber <= 405) {
265                     return GrGLRenderer::kIntelCherryView;
266                 }
267                 if (intelNumber >= 5300 && intelNumber <= 6300) {
268                     return GrGLRenderer::kIntelBroadwell;
269                 }
270                 if (intelNumber >= 500 && intelNumber <= 505) {
271                     return GrGLRenderer::kIntelApolloLake;
272                 }
273                 if (intelNumber >= 510 && intelNumber <= 580) {
274                     return GrGLRenderer::kIntelSkyLake;
275                 }
276                 if (intelNumber >= 600 && intelNumber <= 605) {
277                     return GrGLRenderer::kIntelGeminiLake;
278                 }
279                 // 610 and 630 are reused from KabyLake to CoffeeLake. The CoffeeLake variants
280                 // are "UHD Graphics", while the KabyLake ones are "HD Graphics"
281                 if (intelNumber == 610 || intelNumber == 630) {
282                     return strstr(intelString, "UHD") ? GrGLRenderer::kIntelCoffeeLake
283                                                       : GrGLRenderer::kIntelKabyLake;
284                 }
285                 if (intelNumber >= 610 && intelNumber <= 650) {
286                     return GrGLRenderer::kIntelKabyLake;
287                 }
288                 if (intelNumber == 655) {
289                     return GrGLRenderer::kIntelCoffeeLake;
290                 }
291                 if (intelNumber >= 910 && intelNumber <= 950) {
292                     return GrGLRenderer::kIntelIceLake;
293                 }
294             }
295         }
296     }
297 
298     // The AMD string can have a somewhat arbitrary preamble (see skbug.com/7195)
299     static constexpr char kRadeonStr[] = "Radeon ";
300     if (const char* amdString = strstr(rendererString, kRadeonStr)) {
301         amdString += strlen(kRadeonStr);
302         // Sometimes there is a (TM) and sometimes not.
303         static constexpr char kTMStr[] = "(TM) ";
304         if (!strncmp(amdString, kTMStr, strlen(kTMStr))) {
305             amdString += strlen(kTMStr);
306         }
307 
308         char amd0, amd1, amd2;
309         int amdModel;
310         n = sscanf(amdString, "R9 M3%c%c", &amd0, &amd1);
311         if (2 == n && isdigit(amd0) && isdigit(amd1)) {
312             return GrGLRenderer::kAMDRadeonR9M3xx;
313         }
314 
315         n = sscanf(amdString, "R9 M4%c%c", &amd0, &amd1);
316         if (2 == n && isdigit(amd0) && isdigit(amd1)) {
317             return GrGLRenderer::kAMDRadeonR9M4xx;
318         }
319 
320         n = sscanf(amdString, "HD 7%c%c%c Series", &amd0, &amd1, &amd2);
321         if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) {
322             return GrGLRenderer::kAMDRadeonHD7xxx;
323         }
324 
325         n = sscanf(amdString, "Pro 5%c%c%c", &amd0, &amd1, &amd2);
326         if (3 == n && isdigit(amd0) && isdigit(amd1) && isdigit(amd2)) {
327             return GrGLRenderer::kAMDRadeonPro5xxx;
328         }
329 
330         n = sscanf(amdString, "Pro Vega %i", &amdModel);
331         if (1 == n) {
332             return GrGLRenderer::kAMDRadeonProVegaxx;
333         }
334     }
335 
336     if (strstr(rendererString, "llvmpipe")) {
337         return GrGLRenderer::kGalliumLLVM;
338     }
339     static const char kMaliGStr[] = "Mali-G";
340     if (0 == strncmp(rendererString, kMaliGStr, SK_ARRAY_COUNT(kMaliGStr) - 1)) {
341         return GrGLRenderer::kMaliG;
342     }
343     static const char kMaliTStr[] = "Mali-T";
344     if (0 == strncmp(rendererString, kMaliTStr, SK_ARRAY_COUNT(kMaliTStr) - 1)) {
345         return GrGLRenderer::kMaliT;
346     }
347     int mali400Num;
348     if (1 == sscanf(rendererString, "Mali-%d", &mali400Num) && mali400Num >= 400 &&
349         mali400Num < 500) {
350         return GrGLRenderer::kMali4xx;
351     }
352     return GrGLRenderer::kOther;
353 }
354 
get_driver_and_version(GrGLStandard standard,GrGLVendor vendor,const char * rendererString,const char * versionString)355 std::tuple<GrGLDriver, GrGLDriverVersion> get_driver_and_version(GrGLStandard standard,
356                                                                  GrGLVendor vendor,
357                                                                  const char* rendererString,
358                                                                  const char* versionString) {
359     SkASSERT(rendererString);
360     SkASSERT(versionString);
361 
362     GrGLDriver driver               = GrGLDriver::kUnknown;
363     GrGLDriverVersion driverVersion = GR_GL_DRIVER_UNKNOWN_VER;
364 
365     int major, minor, rev, driverMajor, driverMinor, driverPoint;
366     static const char kChromium[] = "Chromium";
367     char suffix[SK_ARRAY_COUNT(kChromium)] = {0};
368     if (0 == strcmp(rendererString, kChromium) ||
369         (3 == sscanf(versionString, "OpenGL ES %d.%d %8s", &major, &minor, suffix) &&
370          0 == strcmp(kChromium, suffix))) {
371         driver = GrGLDriver::kChromium;
372     } else if (GR_IS_GR_GL(standard)) {
373         if (vendor == GrGLVendor::kNVIDIA) {
374             driver = GrGLDriver::kNVIDIA;
375             int n = sscanf(versionString,
376                            "%d.%d.%d NVIDIA %d.%d",
377                            &major,
378                            &minor,
379                            &rev,
380                            &driverMajor,
381                            &driverMinor);
382             // Some older NVIDIA drivers don't report the driver version.
383             if (n == 5) {
384                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
385             }
386         } else {
387             int n = sscanf(versionString,
388                            "%d.%d Mesa %d.%d",
389                            &major,
390                            &minor,
391                            &driverMajor,
392                            &driverMinor);
393             if (n != 4) {
394                 n = sscanf(versionString,
395                            "%d.%d (Core Profile) Mesa %d.%d",
396                            &major,
397                            &minor,
398                            &driverMajor,
399                            &driverMinor);
400             }
401             if (n == 4) {
402                 driver = GrGLDriver::kMesa;
403                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
404             }
405         }
406     } else if (standard) {
407         if (vendor == GrGLVendor::kNVIDIA) {
408             driver = GrGLDriver::kNVIDIA;
409             int n = sscanf(versionString,
410                            "OpenGL ES %d.%d NVIDIA %d.%d",
411                            &major,
412                            &minor,
413                            &driverMajor,
414                            &driverMinor);
415             // Some older NVIDIA drivers don't report the driver version.
416             if (n == 4) {
417                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
418             }
419         } else {
420             int n = sscanf(versionString,
421                            "OpenGL ES %d.%d Mesa %d.%d",
422                            &major,
423                            &minor,
424                            &driverMajor,
425                            &driverMinor);
426             if (n == 4) {
427                 driver = GrGLDriver::kMesa;
428                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
429             }
430         }
431     }
432 
433     if (driver == GrGLDriver::kUnknown) {
434         if (vendor == GrGLVendor::kGoogle) {
435             // Swiftshader is the only Google vendor at the moment
436             driver = GrGLDriver::kSwiftShader;
437 
438             // Swiftshader has a strange version string: w.x.y.z  Going to arbitrarily ignore
439             // y and assume w,x and z are major, minor, point.
440             // As of writing, version is 4.0.0.6
441             int n = sscanf(versionString,
442                            "OpenGL ES %d.%d SwiftShader %d.%d.0.%d",
443                            &major,
444                            &minor,
445                            &driverMajor,
446                            &driverMinor,
447                            &driverPoint);
448             if (n == 5) {
449                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
450             }
451         } else if (vendor == GrGLVendor::kIntel) {
452             // We presume we're on the Intel driver since it hasn't identified itself as Mesa.
453             driver = GrGLDriver::kIntel;
454 
455             // This is how the macOS version strings are structured. This might be different on
456             // different
457             //  OSes.
458             int n = sscanf(versionString,
459                            "%d.%d INTEL-%d.%d.%d",
460                            &major,
461                            &minor,
462                            &driverMajor,
463                            &driverMinor,
464                            &driverPoint);
465             if (n == 5) {
466                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint);
467             }
468         } else if (vendor == GrGLVendor::kQualcomm) {
469             driver = GrGLDriver::kQualcomm;
470             int n = sscanf(versionString,
471                            "OpenGL ES %d.%d V@%d.%d",
472                            &major,
473                            &minor,
474                            &driverMajor,
475                            &driverMinor);
476             if (n == 4) {
477                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
478             }
479         } else if (vendor == GrGLVendor::kImagination) {
480             int revision;
481             int n = sscanf(versionString,
482                            "OpenGL ES %d.%d build %d.%d@%d",
483                            &major,
484                            &minor,
485                            &driverMajor,
486                            &driverMinor,
487                            &revision);
488             if (n == 5) {
489                 // Revision is a large number (looks like a source control revision number) that
490                 // doesn't fit into the 'patch' bits, so omit it until we need it.
491                 driverVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0);
492             }
493         } else {
494             static constexpr char kEmulatorPrefix[] = "Android Emulator OpenGL ES Translator";
495             if (0 == strncmp(kEmulatorPrefix, rendererString, strlen(kEmulatorPrefix))) {
496                 driver = GrGLDriver::kAndroidEmulator;
497             }
498         }
499     }
500     return {driver, driverVersion};
501 }
502 
503 // If this is detected as ANGLE then the ANGLE backend is returned along with rendererString
504 // stripped of "ANGLE(" and ")" at the start and end, respectively.
get_angle_backend(const char * rendererString)505 static std::tuple<GrGLANGLEBackend, SkString> get_angle_backend(const char* rendererString) {
506     // crbug.com/1203705 ANGLE renderer will be "ANGLE (<gl-vendor>, <gl-renderer>, <gl-version>)"
507     // on ANGLE's GL backend with related substitutions for the inner strings on other backends.
508     static constexpr char kHeader[] = "ANGLE (";
509     static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1;
510     int rendererLength = strlen(rendererString);
511     if (!strncmp(rendererString, kHeader, kHeaderLength) &&
512         rendererString[rendererLength - 1] == ')') {
513         SkString innerString;
514         innerString.set(rendererString + kHeaderLength, rendererLength - kHeaderLength - 1);
515         if (strstr(rendererString, "Direct3D11")) {
516             return {GrGLANGLEBackend::kD3D11, std::move(innerString)};
517         } else if (strstr(rendererString, "Direct3D9")) {
518             return {GrGLANGLEBackend::kD3D9, std::move(innerString)};
519         } else if (strstr(rendererString, "OpenGL")) {
520             return {GrGLANGLEBackend::kOpenGL, std::move(innerString)};
521         }
522     }
523     return {GrGLANGLEBackend::kUnknown, {}};
524 }
525 
526 std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion>
get_angle_gl_vendor_and_renderer(const char * innerString,const GrGLExtensions & extensions)527 get_angle_gl_vendor_and_renderer(
528         const char* innerString,
529         const GrGLExtensions& extensions) {
530     SkTArray<SkString> parts;
531     SkStrSplit(innerString, ",", &parts);
532     // This would need some fixing if we have substrings that contain commas.
533     if (parts.size() != 3) {
534         return {GrGLVendor::kOther,
535                 GrGLRenderer::kOther,
536                 GrGLDriver::kUnknown,
537                 GR_GL_DRIVER_UNKNOWN_VER};
538     }
539 
540     const char* angleVendorString   = parts[0].c_str();
541     const char* angleRendererString = parts[1].c_str() + 1; // skip initial space
542     const char* angleVersionString  = parts[2].c_str() + 1; // skip initial space
543 
544     GrGLVendor angleVendor = get_vendor(angleVendorString);
545 
546     auto [angleDriver, angleDriverVersion] = get_driver_and_version(kGLES_GrGLStandard,
547                                                                     angleVendor,
548                                                                     angleRendererString,
549                                                                     angleVersionString);
550 
551     auto angleRenderer = get_renderer(angleRendererString, extensions);
552 
553     return {angleVendor, angleRenderer, angleDriver, angleDriverVersion};
554 }
555 
556 std::tuple<GrGLVendor, GrGLRenderer, GrGLDriver, GrGLDriverVersion>
get_angle_d3d_vendor_and_renderer(const char * innerString)557 get_angle_d3d_vendor_and_renderer(const char* innerString) {
558     auto vendor   = GrGLVendor::kOther;
559     auto renderer = GrGLRenderer::kOther;
560 
561     if (strstr(innerString, "Intel")) {
562         vendor = GrGLVendor::kIntel;
563 
564         const char* modelStr;
565         int modelNumber;
566         if ((modelStr = strstr(innerString, "HD Graphics")) &&
567             (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) ||
568              1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) {
569             switch (modelNumber) {
570                 case 2000:
571                 case 3000:
572                     renderer = GrGLRenderer::kIntelSandyBridge;
573                     break;
574                 case 4000:
575                 case 2500:
576                     renderer = GrGLRenderer::kIntelSandyBridge;
577                     break;
578                 case 510:
579                 case 515:
580                 case 520:
581                 case 530:
582                     renderer = GrGLRenderer::kIntelSkyLake;
583                     break;
584             }
585         } else if ((modelStr = strstr(innerString, "Iris")) &&
586                    (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) ||
587                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) ||
588                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) {
589             switch (modelNumber) {
590                 case 540:
591                 case 550:
592                 case 555:
593                 case 580:
594                     renderer = GrGLRenderer::kIntelSkyLake;
595                     break;
596             }
597         }
598     } else if (strstr(innerString, "NVIDIA")) {
599         vendor = GrGLVendor::kNVIDIA;
600     } else if (strstr(innerString, "Radeon")) {
601         vendor = GrGLVendor::kATI;
602     }
603     // We haven't had a need yet to parse the D3D driver string.
604     return {vendor, renderer, GrGLDriver::kUnknown, GR_GL_DRIVER_UNKNOWN_VER};
605 }
606 
GrGLGetDriverInfo(const GrGLInterface * interface)607 GrGLDriverInfo GrGLGetDriverInfo(const GrGLInterface* interface) {
608     if (!interface) {
609         return {};
610     }
611     SkASSERT(interface->fStandard != kNone_GrGLStandard);
612     GrGLDriverInfo info;
613     info.fStandard = interface->fStandard;
614 
615     auto getString = [&](GrGLenum s) {
616         const GrGLubyte* bytes = interface->fFunctions.fGetString(s);
617         if (!bytes) {
618             return "";
619         }
620         return reinterpret_cast<const char*>(bytes);
621     };
622 
623     const char* const version    = getString(GR_GL_VERSION);
624     const char* const slversion  = getString(GR_GL_SHADING_LANGUAGE_VERSION);
625     const char* const renderer   = getString(GR_GL_RENDERER);
626     const char* const vendor     = getString(GR_GL_VENDOR);
627 
628     info.fVersion     = GrGLGetVersionFromString(version);
629     info.fGLSLVersion = get_glsl_version(slversion);
630     info.fVendor      = get_vendor(vendor);
631     info.fRenderer    = get_renderer(renderer, interface->fExtensions);
632 
633     std::tie(info.fDriver, info.fDriverVersion) = get_driver_and_version(interface->fStandard,
634                                                                          info.fVendor,
635                                                                          renderer,
636                                                                          version);
637 
638     SkString innerAngleRendererString;
639     std::tie(info.fANGLEBackend, innerAngleRendererString) = get_angle_backend(renderer);
640 
641     if (info.fANGLEBackend == GrGLANGLEBackend::kD3D9 ||
642         info.fANGLEBackend == GrGLANGLEBackend::kD3D11) {
643         std::tie(info.fANGLEVendor,
644                  info.fANGLERenderer,
645                  info.fANGLEDriver,
646                  info.fANGLEDriverVersion) =
647                 get_angle_d3d_vendor_and_renderer(innerAngleRendererString.c_str());
648     } else if (info.fANGLEBackend == GrGLANGLEBackend::kOpenGL) {
649         std::tie(info.fANGLEVendor,
650                  info.fANGLERenderer,
651                  info.fANGLEDriver,
652                  info.fANGLEDriverVersion) =
653                 get_angle_gl_vendor_and_renderer(innerAngleRendererString.c_str(),
654                                                  interface->fExtensions);
655     }
656 
657     return info;
658 }
659 
GrToGLStencilFunc(GrStencilTest test)660 GrGLenum GrToGLStencilFunc(GrStencilTest test) {
661     static const GrGLenum gTable[kGrStencilTestCount] = {
662         GR_GL_ALWAYS,           // kAlways
663         GR_GL_NEVER,            // kNever
664         GR_GL_GREATER,          // kGreater
665         GR_GL_GEQUAL,           // kGEqual
666         GR_GL_LESS,             // kLess
667         GR_GL_LEQUAL,           // kLEqual
668         GR_GL_EQUAL,            // kEqual
669         GR_GL_NOTEQUAL,         // kNotEqual
670     };
671     static_assert(0 == (int)GrStencilTest::kAlways);
672     static_assert(1 == (int)GrStencilTest::kNever);
673     static_assert(2 == (int)GrStencilTest::kGreater);
674     static_assert(3 == (int)GrStencilTest::kGEqual);
675     static_assert(4 == (int)GrStencilTest::kLess);
676     static_assert(5 == (int)GrStencilTest::kLEqual);
677     static_assert(6 == (int)GrStencilTest::kEqual);
678     static_assert(7 == (int)GrStencilTest::kNotEqual);
679     SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
680 
681     return gTable[(int)test];
682 }
683 
GrGLFormatIsCompressed(GrGLFormat format)684 bool GrGLFormatIsCompressed(GrGLFormat format) {
685     switch (format) {
686         case GrGLFormat::kCOMPRESSED_ETC1_RGB8:
687         case GrGLFormat::kCOMPRESSED_RGB8_ETC2:
688         case GrGLFormat::kCOMPRESSED_RGB8_BC1:
689         case GrGLFormat::kCOMPRESSED_RGBA8_BC1:
690             return true;
691 
692         case GrGLFormat::kRGBA8:
693         case GrGLFormat::kR8:
694         case GrGLFormat::kALPHA8:
695         case GrGLFormat::kLUMINANCE8:
696         case GrGLFormat::kLUMINANCE8_ALPHA8:
697         case GrGLFormat::kBGRA8:
698         case GrGLFormat::kRGB565:
699         case GrGLFormat::kRGBA16F:
700         case GrGLFormat::kR16F:
701         case GrGLFormat::kLUMINANCE16F:
702         case GrGLFormat::kRGB8:
703         case GrGLFormat::kRG8:
704         case GrGLFormat::kRGB10_A2:
705         case GrGLFormat::kRGBA4:
706         case GrGLFormat::kSRGB8_ALPHA8:
707         case GrGLFormat::kR16:
708         case GrGLFormat::kRG16:
709         case GrGLFormat::kRGBA16:
710         case GrGLFormat::kRG16F:
711         case GrGLFormat::kSTENCIL_INDEX8:
712         case GrGLFormat::kSTENCIL_INDEX16:
713         case GrGLFormat::kDEPTH24_STENCIL8:
714         case GrGLFormat::kUnknown:
715             return false;
716     }
717     SkUNREACHABLE;
718 }
719 
720