Home | History | Annotate | Download | only in gl
      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;
    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);
    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);
    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);
    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);
    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);
    172             }
    173             return;
    174         }
    175     }
    176 
    177     if (kIntel_GrGLVendor == vendor) {
    178         // We presume we're on the Intel driver since it hasn't identified itself as Mesa.
    179         *outDriver = kIntel_GrGLDriver;
    180     }
    181 
    182     if (kQualcomm_GrGLVendor == vendor) {
    183         *outDriver = kQualcomm_GrGLDriver;
    184         int n = sscanf(versionString, "OpenGL ES %d.%d V@%d.%d", &major, &minor, &driverMajor,
    185                        &driverMinor);
    186         if (4 == n) {
    187             *outVersion = GR_GL_DRIVER_VER(driverMajor, driverMinor);
    188         }
    189         return;
    190     }
    191 }
    192 
    193 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
    194     if (nullptr == versionString) {
    195         SkDebugf("nullptr GL version string.");
    196         return GR_GL_INVALID_VER;
    197     }
    198 
    199     int major, minor;
    200 
    201     // check for mesa
    202     int mesaMajor, mesaMinor;
    203     int n = sscanf(versionString, "%d.%d Mesa %d.%d", &major, &minor, &mesaMajor, &mesaMinor);
    204     if (4 == n) {
    205         return GR_GL_VER(major, minor);
    206     }
    207 
    208     n = sscanf(versionString, "%d.%d", &major, &minor);
    209     if (2 == n) {
    210         return GR_GL_VER(major, minor);
    211     }
    212 
    213     char profile[2];
    214     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
    215                &major, &minor);
    216     if (4 == n) {
    217         return GR_GL_VER(major, minor);
    218     }
    219 
    220     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
    221     if (2 == n) {
    222         return GR_GL_VER(major, minor);
    223     }
    224 
    225     return GR_GL_INVALID_VER;
    226 }
    227 
    228 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
    229     if (nullptr == versionString) {
    230         SkDebugf("nullptr GLSL version string.");
    231         return GR_GLSL_INVALID_VER;
    232     }
    233 
    234     int major, minor;
    235 
    236     int n = sscanf(versionString, "%d.%d", &major, &minor);
    237     if (2 == n) {
    238         return GR_GLSL_VER(major, minor);
    239     }
    240 
    241     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
    242     if (2 == n) {
    243         return GR_GLSL_VER(major, minor);
    244     }
    245 
    246 #ifdef SK_BUILD_FOR_ANDROID
    247     // android hack until the gpu vender updates their drivers
    248     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
    249     if (2 == n) {
    250         return GR_GLSL_VER(major, minor);
    251     }
    252 #endif
    253 
    254     return GR_GLSL_INVALID_VER;
    255 }
    256 
    257 GrGLVendor GrGLGetVendorFromString(const char* vendorString) {
    258     if (vendorString) {
    259         if (0 == strcmp(vendorString, "ARM")) {
    260             return kARM_GrGLVendor;
    261         }
    262         if (0 == strcmp(vendorString, "Imagination Technologies")) {
    263             return kImagination_GrGLVendor;
    264         }
    265         if (0 == strncmp(vendorString, "Intel ", 6) || 0 == strcmp(vendorString, "Intel")) {
    266             return kIntel_GrGLVendor;
    267         }
    268         if (0 == strcmp(vendorString, "Qualcomm")) {
    269             return kQualcomm_GrGLVendor;
    270         }
    271         if (0 == strcmp(vendorString, "NVIDIA Corporation")) {
    272             return kNVIDIA_GrGLVendor;
    273         }
    274         if (0 == strcmp(vendorString, "ATI Technologies Inc.")) {
    275             return kATI_GrGLVendor;
    276         }
    277     }
    278     return kOther_GrGLVendor;
    279 }
    280 
    281 static bool is_renderer_angle(const char* rendererString) {
    282     static constexpr char kHeader[] = "ANGLE ";
    283     static constexpr size_t kHeaderLength = SK_ARRAY_COUNT(kHeader) - 1;
    284     return 0 == strncmp(rendererString, kHeader, kHeaderLength);
    285 }
    286 
    287 GrGLRenderer GrGLGetRendererFromString(const char* rendererString) {
    288     if (rendererString) {
    289         if (0 == strcmp(rendererString, "NVIDIA Tegra 3")) {
    290             return kTegra3_GrGLRenderer;
    291         } else if (0 == strcmp(rendererString, "NVIDIA Tegra")) {
    292             return kTegra2_GrGLRenderer;
    293         }
    294         int lastDigit;
    295         int n = sscanf(rendererString, "PowerVR SGX 54%d", &lastDigit);
    296         if (1 == n && lastDigit >= 0 && lastDigit <= 9) {
    297             return kPowerVR54x_GrGLRenderer;
    298         }
    299         // certain iOS devices also use PowerVR54x GPUs
    300         static const char kAppleA4Str[] = "Apple A4";
    301         static const char kAppleA5Str[] = "Apple A5";
    302         static const char kAppleA6Str[] = "Apple A6";
    303         if (0 == strncmp(rendererString, kAppleA4Str,
    304                          SK_ARRAY_COUNT(kAppleA4Str)-1) ||
    305             0 == strncmp(rendererString, kAppleA5Str,
    306                          SK_ARRAY_COUNT(kAppleA5Str)-1) ||
    307             0 == strncmp(rendererString, kAppleA6Str,
    308                          SK_ARRAY_COUNT(kAppleA6Str)-1)) {
    309             return kPowerVR54x_GrGLRenderer;
    310         }
    311         static const char kPowerVRRogueStr[] = "PowerVR Rogue";
    312         static const char kAppleA7Str[] = "Apple A7";
    313         static const char kAppleA8Str[] = "Apple A8";
    314         if (0 == strncmp(rendererString, kPowerVRRogueStr,
    315                          SK_ARRAY_COUNT(kPowerVRRogueStr)-1) ||
    316             0 == strncmp(rendererString, kAppleA7Str,
    317                          SK_ARRAY_COUNT(kAppleA7Str)-1) ||
    318             0 == strncmp(rendererString, kAppleA8Str,
    319                          SK_ARRAY_COUNT(kAppleA8Str)-1)) {
    320             return kPowerVRRogue_GrGLRenderer;
    321         }
    322         int adrenoNumber;
    323         n = sscanf(rendererString, "Adreno (TM) %d", &adrenoNumber);
    324         if (1 == n) {
    325             if (adrenoNumber >= 300) {
    326                 if (adrenoNumber < 400) {
    327                     return kAdreno3xx_GrGLRenderer;
    328                 }
    329                 if (adrenoNumber < 500) {
    330                     return kAdreno4xx_GrGLRenderer;
    331                 }
    332                 if (adrenoNumber < 600) {
    333                     return kAdreno5xx_GrGLRenderer;
    334                 }
    335             }
    336         }
    337         if (0 == strcmp("Intel Iris Pro OpenGL Engine", rendererString)) {
    338             return kIntelIrisPro_GrGLRenderer;
    339         }
    340 
    341         int intelNumber;
    342         n = sscanf(rendererString, "Intel(R) Iris(TM) Graphics %d", &intelNumber);
    343         if (1 != n) {
    344             n = sscanf(rendererString, "Intel(R) HD Graphics %d", &intelNumber);
    345         }
    346         if (1 == n) {
    347             if (intelNumber >= 4000 && intelNumber < 5000) {
    348                 return kIntel4xxx_GrGLRenderer;
    349             }
    350             if (intelNumber >= 6000 && intelNumber < 7000) {
    351                 return kIntel6xxx_GrGLRenderer;
    352             }
    353         }
    354 
    355         // The AMD string can have a somewhat arbitrary preamble (see skbug.com/7195)
    356         if (const char* amdString = strstr(rendererString, "Radeon")) {
    357             char amdGeneration, amdTier, amdRevision;
    358             n = sscanf(amdString, "Radeon (TM) R9 M%c%c%c",
    359                                        &amdGeneration, &amdTier, &amdRevision);
    360             if (3 == n) {
    361                 if ('4' == amdGeneration) {
    362                     return kAMDRadeonR9M4xx_GrGLRenderer;
    363                 }
    364             }
    365 
    366             char amd0, amd1, amd2;
    367             n = sscanf(amdString, "Radeon HD 7%c%c%c Series", &amd0, &amd1, &amd2);
    368             if (3 == n) {
    369                 return kAMDRadeonHD7xxx_GrGLRenderer;
    370             }
    371         }
    372 
    373         if (0 == strcmp("Mesa Offscreen", rendererString)) {
    374             return kOSMesa_GrGLRenderer;
    375         }
    376         if (strstr(rendererString, "llvmpipe")) {
    377             return kGalliumLLVM_GrGLRenderer;
    378         }
    379         static const char kMaliTStr[] = "Mali-T";
    380         if (0 == strncmp(rendererString, kMaliTStr, SK_ARRAY_COUNT(kMaliTStr) - 1)) {
    381             return kMaliT_GrGLRenderer;
    382         }
    383         if (is_renderer_angle(rendererString)) {
    384             return kANGLE_GrGLRenderer;
    385         }
    386     }
    387     return kOther_GrGLRenderer;
    388 }
    389 
    390 void GrGLGetANGLEInfoFromString(const char* rendererString, GrGLANGLEBackend* backend,
    391                                 GrGLANGLEVendor* vendor, GrGLANGLERenderer* renderer) {
    392     *backend = GrGLANGLEBackend::kUnknown;
    393     *vendor = GrGLANGLEVendor::kUnknown;
    394     *renderer = GrGLANGLERenderer::kUnknown;
    395     if (!is_renderer_angle(rendererString)) {
    396         return;
    397     }
    398     if (strstr(rendererString, "Intel")) {
    399         *vendor = GrGLANGLEVendor::kIntel;
    400 
    401         const char* modelStr;
    402         int modelNumber;
    403         if ((modelStr = strstr(rendererString, "HD Graphics")) &&
    404             (1 == sscanf(modelStr, "HD Graphics %i", &modelNumber) ||
    405              1 == sscanf(modelStr, "HD Graphics P%i", &modelNumber))) {
    406             switch (modelNumber) {
    407                 case 4000:
    408                 case 2500:
    409                     *renderer = GrGLANGLERenderer::kIvyBridge;
    410                     break;
    411                 case 510:
    412                 case 515:
    413                 case 520:
    414                 case 530:
    415                     *renderer = GrGLANGLERenderer::kSkylake;
    416                     break;
    417             }
    418         } else if ((modelStr = strstr(rendererString, "Iris")) &&
    419                    (1 == sscanf(modelStr, "Iris(TM) Graphics %i", &modelNumber) ||
    420                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics %i", &modelNumber) ||
    421                     1 == sscanf(modelStr, "Iris(TM) Pro Graphics P%i", &modelNumber))) {
    422             switch (modelNumber) {
    423                 case 540:
    424                 case 550:
    425                 case 555:
    426                 case 580:
    427                     *renderer = GrGLANGLERenderer::kSkylake;
    428                     break;
    429             }
    430         }
    431     }
    432     if (strstr(rendererString, "Direct3D11")) {
    433         *backend = GrGLANGLEBackend::kD3D11;
    434     } else if (strstr(rendererString, "Direct3D9")) {
    435         *backend = GrGLANGLEBackend::kD3D9;
    436     } else if (strstr(rendererString, "OpenGL")) {
    437         *backend = GrGLANGLEBackend::kOpenGL;
    438     }
    439 }
    440 
    441 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
    442     const GrGLubyte* v;
    443     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
    444     return GrGLGetVersionFromString((const char*) v);
    445 }
    446 
    447 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
    448     const GrGLubyte* v;
    449     GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
    450     return GrGLGetGLSLVersionFromString((const char*) v);
    451 }
    452 
    453 GrGLVendor GrGLGetVendor(const GrGLInterface* gl) {
    454     const GrGLubyte* v;
    455     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VENDOR));
    456     return GrGLGetVendorFromString((const char*) v);
    457 }
    458 
    459 GrGLRenderer GrGLGetRenderer(const GrGLInterface* gl) {
    460     const GrGLubyte* v;
    461     GR_GL_CALL_RET(gl, v, GetString(GR_GL_RENDERER));
    462     return GrGLGetRendererFromString((const char*) v);
    463 }
    464 
    465 GrGLenum GrToGLStencilFunc(GrStencilTest test) {
    466     static const GrGLenum gTable[kGrStencilTestCount] = {
    467         GR_GL_ALWAYS,           // kAlways
    468         GR_GL_NEVER,            // kNever
    469         GR_GL_GREATER,          // kGreater
    470         GR_GL_GEQUAL,           // kGEqual
    471         GR_GL_LESS,             // kLess
    472         GR_GL_LEQUAL,           // kLEqual
    473         GR_GL_EQUAL,            // kEqual
    474         GR_GL_NOTEQUAL,         // kNotEqual
    475     };
    476     GR_STATIC_ASSERT(0 == (int)GrStencilTest::kAlways);
    477     GR_STATIC_ASSERT(1 == (int)GrStencilTest::kNever);
    478     GR_STATIC_ASSERT(2 == (int)GrStencilTest::kGreater);
    479     GR_STATIC_ASSERT(3 == (int)GrStencilTest::kGEqual);
    480     GR_STATIC_ASSERT(4 == (int)GrStencilTest::kLess);
    481     GR_STATIC_ASSERT(5 == (int)GrStencilTest::kLEqual);
    482     GR_STATIC_ASSERT(6 == (int)GrStencilTest::kEqual);
    483     GR_STATIC_ASSERT(7 == (int)GrStencilTest::kNotEqual);
    484     SkASSERT(test < (GrStencilTest)kGrStencilTestCount);
    485 
    486     return gTable[(int)test];
    487 }
    488 
    489 GrPixelConfig GrGLSizedFormatToPixelConfig(GrGLenum sizedFormat) {
    490     switch (sizedFormat) {
    491         case GR_GL_R8:
    492             return kAlpha_8_as_Red_GrPixelConfig;
    493         case GR_GL_ALPHA8:
    494             return kAlpha_8_as_Alpha_GrPixelConfig;
    495         case GR_GL_RGBA8:
    496             return kRGBA_8888_GrPixelConfig;
    497         case GR_GL_BGRA8:
    498             return kBGRA_8888_GrPixelConfig;
    499         case GR_GL_SRGB8_ALPHA8:
    500             return kSRGBA_8888_GrPixelConfig;
    501         case GR_GL_RGB565:
    502             return kRGB_565_GrPixelConfig;
    503         case GR_GL_RGB5:
    504             return kRGB_565_GrPixelConfig;
    505         case GR_GL_RGBA4:
    506             return kRGBA_4444_GrPixelConfig;
    507         case GR_GL_RGB10_A2:
    508             return kRGBA_1010102_GrPixelConfig;
    509         case GR_GL_LUMINANCE8:
    510             return kGray_8_GrPixelConfig;
    511         case GR_GL_RGBA32F:
    512             return kRGBA_float_GrPixelConfig;
    513         case GR_GL_RG32F:
    514             return kRG_float_GrPixelConfig;
    515         case GR_GL_R16F:
    516             return kAlpha_half_as_Red_GrPixelConfig;
    517         case GR_GL_RGBA16F:
    518             return kRGBA_half_GrPixelConfig;
    519         default:
    520             return kUnknown_GrPixelConfig;
    521     }
    522 }
    523 
    524