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 "GrGLUtil.h" 10 #include "GrTypesPriv.h" 11 #include "SkMatrix.h" 12 #include <stdio.h> 13 14 void GrGLClearErr(const GrGLInterface* gl) { 15 while (GR_GL_NO_ERROR != gl->fFunctions.fGetError()) {} 16 } 17 18 namespace { 19 const char *get_error_string(uint32_t err) { 20 switch (err) { 21 case GR_GL_NO_ERROR: 22 return ""; 23 case GR_GL_INVALID_ENUM: 24 return "Invalid Enum"; 25 case GR_GL_INVALID_VALUE: 26 return "Invalid Value"; 27 case GR_GL_INVALID_OPERATION: 28 return "Invalid Operation"; 29 case GR_GL_OUT_OF_MEMORY: 30 return "Out of Memory"; 31 case GR_GL_CONTEXT_LOST: 32 return "Context Lost"; 33 } 34 return "Unknown"; 35 } 36 } 37 38 void GrGLCheckErr(const GrGLInterface* gl, 39 const char* location, 40 const char* call) { 41 uint32_t err = GR_GL_GET_ERROR(gl); 42 if (GR_GL_NO_ERROR != err) { 43 SkDebugf("---- glGetError 0x%x(%s)", err, get_error_string(err)); 44 if (location) { 45 SkDebugf(" at\n\t%s", location); 46 } 47 if (call) { 48 SkDebugf("\n\t\t%s", call); 49 } 50 SkDebugf("\n"); 51 } 52 } 53 54 /////////////////////////////////////////////////////////////////////////////// 55 56 #if GR_GL_LOG_CALLS 57 bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START); 58 #endif 59 60 #if GR_GL_CHECK_ERROR 61 bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START); 62 #endif 63 64 /////////////////////////////////////////////////////////////////////////////// 65 66 GrGLStandard GrGLGetStandardInUseFromString(const char* versionString) { 67 if (nullptr == versionString) { 68 SkDebugf("nullptr GL version string."); 69 return kNone_GrGLStandard; 70 } 71 72 int major, minor; 73 74 // check for desktop 75 int n = sscanf(versionString, "%d.%d", &major, &minor); 76 if (2 == n) { 77 return kGL_GrGLStandard; 78 } 79 80 // check for ES 1 81 char profile[2]; 82 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, &major, &minor); 83 if (4 == n) { 84 // we no longer support ES1. 85 return kNone_GrGLStandard; 86 } 87 88 // check for ES2 89 n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor); 90 if (2 == n) { 91 return kGLES_GrGLStandard; 92 } 93 return kNone_GrGLStandard; 94 } 95 96 void GrGLGetDriverInfo(GrGLStandard standard, 97 GrGLVendor vendor, 98 const char* rendererString, 99 const char* versionString, 100 GrGLDriver* outDriver, 101 GrGLDriverVersion* outVersion) { 102 int major, minor, rev, driverMajor, driverMinor, driverPoint; 103 104 *outDriver = kUnknown_GrGLDriver; 105 *outVersion = GR_GL_DRIVER_UNKNOWN_VER; 106 // These null checks are for test GL contexts that return nullptr in their 107 // glGetString implementation. 108 if (!rendererString) { 109 rendererString = ""; 110 } 111 if (!versionString) { 112 versionString = ""; 113 } 114 115 static const char kChromium[] = "Chromium"; 116 char suffix[SK_ARRAY_COUNT(kChromium)]; 117 if (0 == strcmp(rendererString, kChromium) || 118 (3 == sscanf(versionString, "OpenGL ES %d.%d %8s", &major, &minor, suffix) && 119 0 == strcmp(kChromium, suffix))) { 120 *outDriver = kChromium_GrGLDriver; 121 return; 122 } 123 124 if (standard == kGL_GrGLStandard) { 125 if (kNVIDIA_GrGLVendor == vendor) { 126 *outDriver = kNVIDIA_GrGLDriver; 127 int n = sscanf(versionString, "%d.%d.%d NVIDIA %d.%d", 128 &major, &minor, &rev, &driverMajor, &driverMinor); 129 // Some older NVIDIA drivers don't report the driver version. 130 if (5 == n) { 131 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); 132 } 133 return; 134 } 135 int n = sscanf(versionString, "%d.%d Mesa %d.%d", 136 &major, &minor, &driverMajor, &driverMinor); 137 if (4 != n) { 138 n = sscanf(versionString, "%d.%d (Core Profile) Mesa %d.%d", 139 &major, &minor, &driverMajor, &driverMinor); 140 } 141 if (4 == n) { 142 *outDriver = kMesa_GrGLDriver; 143 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); 144 return; 145 } 146 } 147 else { 148 if (kNVIDIA_GrGLVendor == vendor) { 149 *outDriver = kNVIDIA_GrGLDriver; 150 int n = sscanf(versionString, "OpenGL ES %d.%d NVIDIA %d.%d", 151 &major, &minor, &driverMajor, &driverMinor); 152 // Some older NVIDIA drivers don't report the driver version. 153 if (4 == n) { 154 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); 155 } 156 return; 157 } 158 159 int n = sscanf(versionString, "OpenGL ES %d.%d Mesa %d.%d", 160 &major, &minor, &driverMajor, &driverMinor); 161 if (4 == n) { 162 *outDriver = kMesa_GrGLDriver; 163 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); 164 return; 165 } 166 if (0 == strncmp("ANGLE", rendererString, 5)) { 167 *outDriver = kANGLE_GrGLDriver; 168 n = sscanf(versionString, "OpenGL ES %d.%d (ANGLE %d.%d", &major, &minor, &driverMajor, 169 &driverMinor); 170 if (4 == n) { 171 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); 172 } 173 return; 174 } 175 } 176 177 if (kGoogle_GrGLVendor == vendor) { 178 // Swiftshader is the only Google vendor at the moment 179 *outDriver = kSwiftShader_GrGLDriver; 180 181 // Swiftshader has a strange version string: w.x.y.z Going to arbitrarily ignore 182 // y and assume w,x and z are major, minor, point. 183 // As of writing, version is 4.0.0.6 184 int n = sscanf(versionString, "OpenGL ES %d.%d SwiftShader %d.%d.0.%d", &major, &minor, 185 &driverMajor, &driverMinor, &driverPoint); 186 if (5 == n) { 187 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint); 188 } 189 return; 190 } 191 192 if (kIntel_GrGLVendor == vendor) { 193 // We presume we're on the Intel driver since it hasn't identified itself as Mesa. 194 *outDriver = kIntel_GrGLDriver; 195 196 //This is how the macOS version strings are structured. This might be different on different 197 // OSes. 198 int n = sscanf(versionString, "%d.%d INTEL-%d.%d.%d", &major, &minor, &driverMajor, 199 &driverMinor, &driverPoint); 200 if (5 == n) { 201 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, driverPoint); 202 } 203 } 204 205 if (kQualcomm_GrGLVendor == vendor) { 206 *outDriver = kQualcomm_GrGLDriver; 207 int n = sscanf(versionString, "OpenGL ES %d.%d V@%d.%d", &major, &minor, &driverMajor, 208 &driverMinor); 209 if (4 == n) { 210 *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor, 0); 211 } 212 return; 213 } 214 } 215 216 GrGLVersion GrGLGetVersionFromString(const char* versionString) { 217 if (nullptr == versionString) { 218 SkDebugf("nullptr GL version string."); 219 return GR_GL_INVALID_VER; 220 } 221 222 int major, minor; 223 224 // check for mesa 225 int mesaMajor, mesaMinor; 226 int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor); 227 if (4 == n) { 228 return GR_GL_VER(major, minor); 229 } 230 231 n = sscanf(versionString, "%d.%d", &major, &minor); 232 if (2 == n) { 233 return GR_GL_VER(major, minor); 234 } 235 236 char profile[2]; 237 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1, 238 &major, &minor); 239 if (4 == n) { 240 return GR_GL_VER(major, minor); 241 } 242 243 n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor); 244 if (2 == n) { 245 return GR_GL_VER(major, minor); 246 } 247 248 return GR_GL_INVALID_VER; 249 } 250 251 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) { 252 if (nullptr == versionString) { 253 SkDebugf("nullptr GLSL version string."); 254 return GR_GLSL_INVALID_VER; 255 } 256 257 int major, minor; 258 259 int n = sscanf(versionString, "%d.%d", &major, &minor); 260 if (2 == n) { 261 return GR_GLSL_VER(major, minor); 262 } 263 264 n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor); 265 if (2 == n) { 266 return GR_GLSL_VER(major, minor); 267 } 268 269 #ifdef SK_BUILD_FOR_ANDROID 270 // android hack until the gpu vender updates their drivers 271 n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor); 272 if (2 == n) { 273 return GR_GLSL_VER(major, minor); 274 } 275 #endif 276 277 return GR_GLSL_INVALID_VER; 278 } 279 280 GrGLVendor GrGLGetVendorFromString(const char* vendorString) { 281 if (vendorString) { 282 if (0 == strcmp(vendorString, "ARM")) { 283 return kARM_GrGLVendor; 284 } 285 if (0 == strcmp(vendorString, "Google Inc.")) { 286 return kGoogle_GrGLVendor; 287 } 288 if (0 == strcmp(vendorString, "Imagination Technologies")) { 289 return kImagination_GrGLVendor; 290 } 291 if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) { 292 return kIntel_GrGLVendor; 293 } 294 if (0 == strcmp(vendorString, "Qualcomm")) { 295 return kQualcomm_GrGLVendor; 296 } 297 if (0 == strcmp(vendorString, "NVIDIA Corporation")) { 298 return kNVIDIA_GrGLVendor; 299 } 300 if (0 == strcmp(vendorString, "ATI Technologies Inc.")) { 301 return kATI_GrGLVendor; 302 } 303 } 304 return kOther_GrGLVendor; 305 } 306 307 static bool is_renderer_angle(const char* rendererString) { 308 static constexpr char kHeader[] = "ANGLE "; 309 static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1; 310 return rendererString && 0 == strncmp(rendererString, kHeader, kHeaderLength); 311 } 312 313 GrGLRenderer GrGLGetRendererFromStrings(const char* rendererString, 314 const GrGLExtensions& extensions) { 315 if (rendererString) { 316 static const char kTegraStr[] = "NVIDIA Tegra"; 317 if (0 == strncmp(rendererString, kTegraStr, SK_ARRAY_COUNT(kTegraStr) - 1)) { 318 // Tegra strings are not very descriptive. We distinguish between the modern and legacy 319 // architectures by the presence of NV_path_rendering. 320 return extensions.has("GL_NV_path_rendering") ? kTegra_GrGLRenderer 321 : kTegra_PreK1_GrGLRenderer; 322 } 323 int lastDigit; 324 int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit); 325 if (1 == n && lastDigit >= 0 && lastDigit <= 9) { 326 return kPowerVR54x_GrGLRenderer; 327 } 328 // certain iOS devices also use PowerVR54x GPUs 329 static const char kAppleA4Str[] = "Apple A4"; 330 static const char kAppleA5Str[] = "Apple A5"; 331 static const char kAppleA6Str[] = "Apple A6"; 332 if (0 == strncmp(rendererString, kAppleA4Str, 333 SK_ARRAY_COUNT(kAppleA4Str)-1) || 334 0 == strncmp(rendererString, kAppleA5Str, 335 SK_ARRAY_COUNT(kAppleA5Str)-1) || 336 0 == strncmp(rendererString, kAppleA6Str, 337 SK_ARRAY_COUNT(kAppleA6Str)-1)) { 338 return kPowerVR54x_GrGLRenderer; 339 } 340 static const char kPowerVRRogueStr[] = "PowerVR Rogue"; 341 static const char kAppleA7Str[] = "Apple A7"; 342 static const char kAppleA8Str[] = "Apple A8"; 343 if (0 == strncmp(rendererString, kPowerVRRogueStr, 344 SK_ARRAY_COUNT(kPowerVRRogueStr)-1) || 345 0 == strncmp(rendererString, kAppleA7Str, 346 SK_ARRAY_COUNT(kAppleA7Str)-1) || 347 0 == strncmp(rendererString, kAppleA8Str, 348 SK_ARRAY_COUNT(kAppleA8Str)-1)) { 349 return kPowerVRRogue_GrGLRenderer; 350 } 351 int adrenoNumber; 352 n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber); 353 if (1 == n) { 354 if (adrenoNumber >= 300) { 355 if (adrenoNumber < 400) { 356 return kAdreno3xx_GrGLRenderer; 357 } 358 if (adrenoNumber < 500) { 359 return adrenoNumber >= 430 360 ? kAdreno430_GrGLRenderer : kAdreno4xx_other_GrGLRenderer; 361 } 362 if (adrenoNumber < 600) { 363 return kAdreno5xx_GrGLRenderer; 364 } 365 } 366 } 367 if (0 == strcmp("Google SwiftShader", rendererString)) { 368 return kGoogleSwiftShader_GrGLRenderer; 369 } 370 371 if (const char* intelString = strstr(rendererString, "Intel")) { 372 if (0 == strcmp("Intel Iris Pro OpenGL Engine", intelString)) { 373 return kIntelIrisPro_GrGLRenderer; 374 } 375 if (strstr(intelString, "Sandybridge")) { 376 return kIntelSandyBridge_GrGLRenderer; 377 } 378 if (strstr(intelString, "Bay Trail")) { 379 return kIntelBayTrail_GrGLRenderer; 380 } 381 int intelNumber; 382 if (sscanf(intelString, "Intel(R) Iris(TM) Graphics %d", &intelNumber) || 383 sscanf(intelString, "Intel(R) Iris(TM) Pro Graphics %d", &intelNumber) || 384 sscanf(intelString, "Intel(R) Iris(TM) Pro Graphics P%d", &intelNumber) || 385 sscanf(intelString, "Intel(R) Iris(R) Graphics %d", &intelNumber) || 386 sscanf(intelString, "Intel(R) Iris(R) Pro Graphics %d", &intelNumber) || 387 sscanf(intelString, "Intel(R) Iris(R) Pro Graphics P%d", &intelNumber) || 388 sscanf(intelString, "Intel(R) HD Graphics %d", &intelNumber) || 389 sscanf(intelString, "Intel(R) HD Graphics P%d", &intelNumber)) { 390 391 if (intelNumber >= 4000 && intelNumber < 5000) { 392 return kIntel4xxx_GrGLRenderer; 393 } 394 if (intelNumber >= 6000 && intelNumber < 7000) { 395 return kIntel6xxx_GrGLRenderer; 396 } 397 if (intelNumber >= 2000 && intelNumber < 4000) { 398 return kIntelSandyBridge_GrGLRenderer; 399 } 400 if (intelNumber >= 500 && intelNumber < 600) { 401 return kIntelSkylake_GrGLRenderer; 402 } 403 } 404 } 405 406 // The AMD string can have a somewhat arbitrary preamble (see skbug.com/7195) 407 if (const char* amdString = strstr(rendererString, "Radeon")) { 408 char amdGeneration, amdTier, amdRevision; 409 n = sscanf(amdString, "Radeon (TM) R9 M%c%c%c", 410 &amdGeneration, &amdTier, &amdRevision); 411 if (3 == n) { 412 if ('4' == amdGeneration) { 413 return kAMDRadeonR9M4xx_GrGLRenderer; 414 } 415 } 416 417 char amd0, amd1, amd2; 418 n = sscanf(amdString, "Radeon HD 7%c%c%c Series", &amd0, &amd1, &amd2); 419 if (3 == n) { 420 return kAMDRadeonHD7xxx_GrGLRenderer; 421 } 422 } 423 424 if (0 == strcmp("Mesa Offscreen", rendererString)) { 425 return kOSMesa_GrGLRenderer; 426 } 427 if (strstr(rendererString, "llvmpipe")) { 428 return kGalliumLLVM_GrGLRenderer; 429 } 430 static const char kMaliTStr[] = "Mali-T"; 431 if (0 == strncmp(rendererString, kMaliTStr, SK_ARRAY_COUNT(kMaliTStr) - 1)) { 432 return kMaliT_GrGLRenderer; 433 } 434 int mali400Num; 435 if (1 == sscanf(rendererString, "Mali-%d", &mali400Num) && mali400Num >= 400 && 436 mali400Num < 500) { 437 return kMali4xx_GrGLRenderer; 438 } 439 if (is_renderer_angle(rendererString)) { 440 return kANGLE_GrGLRenderer; 441 } 442 } 443 return kOther_GrGLRenderer; 444 } 445 446 void GrGLGetANGLEInfoFromString(const char* rendererString, GrGLANGLEBackend* backend, 447 GrGLANGLEVendor* vendor, GrGLANGLERenderer* renderer) { 448 *backend = GrGLANGLEBackend::kUnknown; 449 *vendor = GrGLANGLEVendor::kUnknown; 450 *renderer = GrGLANGLERenderer::kUnknown; 451 if (!is_renderer_angle(rendererString)) { 452 return; 453 } 454 if (strstr(rendererString, "Intel")) { 455 *vendor = GrGLANGLEVendor::kIntel; 456 457 const char* modelStr; 458 int modelNumber; 459 if ((modelStr = strstr(rendererString, "HD Graphics")) && 460 (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) || 461 1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) { 462 switch (modelNumber) { 463 case 2000: 464 case 3000: 465 *renderer = GrGLANGLERenderer::kSandyBridge; 466 break; 467 case 4000: 468 case 2500: 469 *renderer = GrGLANGLERenderer::kIvyBridge; 470 break; 471 case 510: 472 case 515: 473 case 520: 474 case 530: 475 *renderer = GrGLANGLERenderer::kSkylake; 476 break; 477 } 478 } else if ((modelStr = strstr(rendererString, "Iris")) && 479 (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) || 480 1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) || 481 1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) { 482 switch (modelNumber) { 483 case 540: 484 case 550: 485 case 555: 486 case 580: 487 *renderer = GrGLANGLERenderer::kSkylake; 488 break; 489 } 490 } 491 } 492 if (strstr(rendererString, "Direct3D11")) { 493 *backend = GrGLANGLEBackend::kD3D11; 494 } else if (strstr(rendererString, "Direct3D9")) { 495 *backend = GrGLANGLEBackend::kD3D9; 496 } else if (strstr(rendererString, "OpenGL")) { 497 *backend = GrGLANGLEBackend::kOpenGL; 498 } 499 } 500 501 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) { 502 const GrGLubyte* v; 503 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION)); 504 return GrGLGetVersionFromString((const char*) v); 505 } 506 507 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) { 508 const GrGLubyte* v; 509 GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION)); 510 return GrGLGetGLSLVersionFromString((const char*) v); 511 } 512 513 GrGLVendor GrGLGetVendor(const GrGLInterface* gl) { 514 const GrGLubyte* v; 515 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR)); 516 return GrGLGetVendorFromString((const char*) v); 517 } 518 519 GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) { 520 const GrGLubyte* rendererString; 521 GR_GL_CALL_RET(gl, rendererString, GetString(GR_GL_RENDERER)); 522 523 return GrGLGetRendererFromStrings((const char*)rendererString, gl->fExtensions); 524 } 525 526 GrGLenum GrToGLStencilFunc(GrStencilTest test) { 527 static const GrGLenum gTable[kGrStencilTestCount] = { 528 GR_GL_ALWAYS, // kAlways 529 GR_GL_NEVER, // kNever 530 GR_GL_GREATER, // kGreater 531 GR_GL_GEQUAL, // kGEqual 532 GR_GL_LESS, // kLess 533 GR_GL_LEQUAL, // kLEqual 534 GR_GL_EQUAL, // kEqual 535 GR_GL_NOTEQUAL, // kNotEqual 536 }; 537 GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways); 538 GR_STATIC_ASSERT(1 == (int)GrStencilTest::kNever); 539 GR_STATIC_ASSERT(2 == (int)GrStencilTest::kGreater); 540 GR_STATIC_ASSERT(3 == (int)GrStencilTest::kGEqual); 541 GR_STATIC_ASSERT(4 == (int)GrStencilTest::kLess); 542 GR_STATIC_ASSERT(5 == (int)GrStencilTest::kLEqual); 543 GR_STATIC_ASSERT(6 == (int)GrStencilTest::kEqual); 544 GR_STATIC_ASSERT(7 == (int)GrStencilTest::kNotEqual); 545 SkASSERT(test < (GrStencilTest)kGrStencilTestCount); 546 547 return gTable[(int)test]; 548 } 549 550