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