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