Home | History | Annotate | Download | only in gl
      1 
      2 /*
      3  * Copyright 2011 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #include "GrTypes.h"
     11 #include "gl/GrGLInterface.h"
     12 #include "gl/GrGLDefines.h"
     13 
     14 #include <stdio.h>
     15 
     16 #if GR_GL_PER_GL_FUNC_CALLBACK
     17 namespace {
     18 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
     19 }
     20 #endif
     21 
     22 GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) {
     23     if (NULL == versionString) {
     24         GrAssert(!"NULL GL version string.");
     25         return kNone_GrGLBinding;
     26     }
     27 
     28     int major, minor;
     29 
     30     // check for desktop
     31     int n = sscanf(versionString, "%d.%d", &major, &minor);
     32     if (2 == n) {
     33         return kDesktop_GrGLBinding;
     34     }
     35 
     36     // check for ES 1
     37     char profile[2];
     38     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
     39                &major, &minor);
     40     if (4 == n) {
     41         // we no longer support ES1.
     42         return kNone_GrGLBinding;
     43     }
     44 
     45     // check for ES2
     46     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
     47     if (2 == n) {
     48         return kES2_GrGLBinding;
     49     }
     50     return kNone_GrGLBinding;
     51 }
     52 
     53 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
     54     if (NULL == versionString) {
     55         GrAssert(!"NULL GL version string.");
     56         return 0;
     57     }
     58 
     59     int major, minor;
     60 
     61     int n = sscanf(versionString, "%d.%d", &major, &minor);
     62     if (2 == n) {
     63         return GR_GL_VER(major, minor);
     64     }
     65 
     66     char profile[2];
     67     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
     68                &major, &minor);
     69     if (4 == n) {
     70         return GR_GL_VER(major, minor);
     71     }
     72 
     73     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
     74     if (2 == n) {
     75         return GR_GL_VER(major, minor);
     76     }
     77 
     78     return 0;
     79 }
     80 
     81 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
     82     if (NULL == versionString) {
     83         GrAssert(!"NULL GLSL version string.");
     84         return 0;
     85     }
     86 
     87     int major, minor;
     88 
     89     int n = sscanf(versionString, "%d.%d", &major, &minor);
     90     if (2 == n) {
     91         return GR_GLSL_VER(major, minor);
     92     }
     93 
     94     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
     95     if (2 == n) {
     96         return GR_GLSL_VER(major, minor);
     97     }
     98 
     99     // android hack
    100     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
    101     if (2 == n) {
    102         return GR_GLSL_VER(major, minor);
    103     }
    104 
    105     return 0;
    106 }
    107 
    108 bool GrGLHasExtensionFromString(const char* ext, const char* extensionString) {
    109     int extLength = strlen(ext);
    110 
    111     while (true) {
    112         int n = strcspn(extensionString, " ");
    113         if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
    114             return true;
    115         }
    116         if (0 == extensionString[n]) {
    117             return false;
    118         }
    119         extensionString += n+1;
    120     }
    121 
    122     return false;
    123 }
    124 
    125 bool GrGLHasExtension(const GrGLInterface* gl, const char* ext) {
    126     const GrGLubyte* glstr;
    127     GR_GL_CALL_RET(gl, glstr, GetString(GR_GL_EXTENSIONS));
    128     return GrGLHasExtensionFromString(ext, (const char*) glstr);
    129 }
    130 
    131 GrGLBinding GrGLGetBindingInUse(const GrGLInterface* gl) {
    132     const GrGLubyte* v;
    133     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
    134     return GrGLGetBindingInUseFromString((const char*) v);
    135 }
    136 
    137 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
    138     const GrGLubyte* v;
    139     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
    140     return GrGLGetVersionFromString((const char*) v);
    141 }
    142 
    143 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
    144     const GrGLubyte* v;
    145     GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
    146     return GrGLGetGLSLVersionFromString((const char*) v);
    147 }
    148 
    149 GrGLInterface::GrGLInterface() {
    150     fBindingsExported = kNone_GrGLBinding;
    151 
    152     fActiveTexture = NULL;
    153     fAttachShader = NULL;
    154     fBeginQuery = NULL;
    155     fBindAttribLocation = NULL;
    156     fBindBuffer = NULL;
    157     fBindFragDataLocation = NULL;
    158     fBindTexture = NULL;
    159     fBlendColor = NULL;
    160     fBlendFunc = NULL;
    161     fBufferData = NULL;
    162     fBufferSubData = NULL;
    163     fClear = NULL;
    164     fClearColor = NULL;
    165     fClearStencil = NULL;
    166     fColorMask = NULL;
    167     fColorPointer = NULL;
    168     fCompileShader = NULL;
    169     fCompressedTexImage2D = NULL;
    170     fCreateProgram = NULL;
    171     fCreateShader = NULL;
    172     fCullFace = NULL;
    173     fDeleteBuffers = NULL;
    174     fDeleteProgram = NULL;
    175     fDeleteQueries = NULL;
    176     fDeleteShader = NULL;
    177     fDeleteTextures = NULL;
    178     fDepthMask = NULL;
    179     fDisable = NULL;
    180     fDisableVertexAttribArray = NULL;
    181     fDrawArrays = NULL;
    182     fDrawBuffer = NULL;
    183     fDrawBuffers = NULL;
    184     fDrawElements = NULL;
    185     fEndQuery = NULL;
    186     fFinish = NULL;
    187     fFlush = NULL;
    188     fEnable = NULL;
    189     fEnableVertexAttribArray = NULL;
    190     fFrontFace = NULL;
    191     fGenBuffers = NULL;
    192     fGenQueries = NULL;
    193     fGenTextures = NULL;
    194     fGetBufferParameteriv = NULL;
    195     fGetError = NULL;
    196     fGetIntegerv = NULL;
    197     fGetQueryiv = NULL;
    198     fGetQueryObjecti64v = NULL;
    199     fGetQueryObjectiv = NULL;
    200     fGetQueryObjectui64v = NULL;
    201     fGetQueryObjectuiv = NULL;
    202     fGetProgramInfoLog = NULL;
    203     fGetProgramiv = NULL;
    204     fGetShaderInfoLog = NULL;
    205     fGetShaderiv = NULL;
    206     fGetString = NULL;
    207     fGetTexLevelParameteriv = NULL;
    208     fGetUniformLocation = NULL;
    209     fLineWidth = NULL;
    210     fLinkProgram = NULL;
    211     fPixelStorei = NULL;
    212     fQueryCounter = NULL;
    213     fReadBuffer = NULL;
    214     fReadPixels = NULL;
    215     fScissor = NULL;
    216     fShaderSource = NULL;
    217     fStencilFunc = NULL;
    218     fStencilFuncSeparate = NULL;
    219     fStencilMask = NULL;
    220     fStencilMaskSeparate = NULL;
    221     fStencilOp = NULL;
    222     fStencilOpSeparate = NULL;
    223     fTexImage2D = NULL;
    224     fTexParameteri = NULL;
    225     fTexStorage2D = NULL;
    226     fTexSubImage2D = NULL;
    227     fUniform1f = NULL;
    228     fUniform1i = NULL;
    229     fUniform1fv = NULL;
    230     fUniform1iv = NULL;
    231     fUniform2f = NULL;
    232     fUniform2i = NULL;
    233     fUniform2fv = NULL;
    234     fUniform2iv = NULL;
    235     fUniform3f = NULL;
    236     fUniform3i = NULL;
    237     fUniform3fv = NULL;
    238     fUniform3iv = NULL;
    239     fUniform4f = NULL;
    240     fUniform4i = NULL;
    241     fUniform4fv = NULL;
    242     fUniform4iv = NULL;
    243     fUniformMatrix2fv = NULL;
    244     fUniformMatrix3fv = NULL;
    245     fUniformMatrix4fv = NULL;
    246     fUseProgram = NULL;
    247     fVertexAttrib4fv = NULL;
    248     fVertexAttribPointer = NULL;
    249     fViewport = NULL;
    250     fBindFramebuffer = NULL;
    251     fBindRenderbuffer = NULL;
    252     fCheckFramebufferStatus = NULL;
    253     fDeleteFramebuffers = NULL;
    254     fDeleteRenderbuffers = NULL;
    255     fFramebufferRenderbuffer = NULL;
    256     fFramebufferTexture2D = NULL;
    257     fGenFramebuffers = NULL;
    258     fGenRenderbuffers = NULL;
    259     fGetFramebufferAttachmentParameteriv = NULL;
    260     fGetRenderbufferParameteriv = NULL;
    261     fRenderbufferStorage = NULL;
    262     fRenderbufferStorageMultisample = NULL;
    263     fBlitFramebuffer = NULL;
    264     fResolveMultisampleFramebuffer = NULL;
    265     fMapBuffer = NULL;
    266     fUnmapBuffer = NULL;
    267     fBindFragDataLocationIndexed = NULL;
    268 
    269 #if GR_GL_PER_GL_FUNC_CALLBACK
    270     fCallback = GrGLDefaultInterfaceCallback;
    271     fCallbackData = 0;
    272 #endif
    273 }
    274 
    275 bool GrGLInterface::validate(GrGLBinding binding) const {
    276 
    277     // kNone must be 0 so that the check we're about to do can never succeed if
    278     // binding == kNone.
    279     GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
    280 
    281     if (0 == (binding & fBindingsExported)) {
    282         return false;
    283     }
    284 
    285     // functions that are always required
    286     if (NULL == fActiveTexture ||
    287         NULL == fAttachShader ||
    288         NULL == fBindAttribLocation ||
    289         NULL == fBindBuffer ||
    290         NULL == fBindTexture ||
    291         NULL == fBlendFunc ||
    292         NULL == fBufferData ||
    293         NULL == fBufferSubData ||
    294         NULL == fClear ||
    295         NULL == fClearColor ||
    296         NULL == fClearStencil ||
    297         NULL == fColorMask ||
    298         NULL == fCompileShader ||
    299         NULL == fCreateProgram ||
    300         NULL == fCreateShader ||
    301         NULL == fCullFace ||
    302         NULL == fDeleteBuffers ||
    303         NULL == fDeleteProgram ||
    304         NULL == fDeleteShader ||
    305         NULL == fDeleteTextures ||
    306         NULL == fDepthMask ||
    307         NULL == fDisable ||
    308         NULL == fDisableVertexAttribArray ||
    309         NULL == fDrawArrays ||
    310         NULL == fDrawElements ||
    311         NULL == fEnable ||
    312         NULL == fEnableVertexAttribArray ||
    313         NULL == fFrontFace ||
    314         NULL == fGenBuffers ||
    315         NULL == fGenTextures ||
    316         NULL == fGetBufferParameteriv ||
    317         NULL == fGetError ||
    318         NULL == fGetIntegerv ||
    319         NULL == fGetProgramInfoLog ||
    320         NULL == fGetProgramiv ||
    321         NULL == fGetShaderInfoLog ||
    322         NULL == fGetShaderiv ||
    323         NULL == fGetString ||
    324         NULL == fGetUniformLocation ||
    325         NULL == fLinkProgram ||
    326         NULL == fPixelStorei ||
    327         NULL == fReadPixels ||
    328         NULL == fScissor ||
    329         NULL == fShaderSource ||
    330         NULL == fStencilFunc ||
    331         NULL == fStencilMask ||
    332         NULL == fStencilOp ||
    333         NULL == fTexImage2D ||
    334         NULL == fTexParameteri ||
    335         NULL == fTexSubImage2D ||
    336         NULL == fUniform1f ||
    337         NULL == fUniform1i ||
    338         NULL == fUniform1fv ||
    339         NULL == fUniform1iv ||
    340         NULL == fUniform2f ||
    341         NULL == fUniform2i ||
    342         NULL == fUniform2fv ||
    343         NULL == fUniform2iv ||
    344         NULL == fUniform3f ||
    345         NULL == fUniform3i ||
    346         NULL == fUniform3fv ||
    347         NULL == fUniform3iv ||
    348         NULL == fUniform4f ||
    349         NULL == fUniform4i ||
    350         NULL == fUniform4fv ||
    351         NULL == fUniform4iv ||
    352         NULL == fUniformMatrix2fv ||
    353         NULL == fUniformMatrix3fv ||
    354         NULL == fUniformMatrix4fv ||
    355         NULL == fUseProgram ||
    356         NULL == fVertexAttrib4fv ||
    357         NULL == fVertexAttribPointer ||
    358         NULL == fViewport ||
    359         NULL == fBindFramebuffer ||
    360         NULL == fBindRenderbuffer ||
    361         NULL == fCheckFramebufferStatus ||
    362         NULL == fDeleteFramebuffers ||
    363         NULL == fDeleteRenderbuffers ||
    364         NULL == fFinish ||
    365         NULL == fFlush ||
    366         NULL == fFramebufferRenderbuffer ||
    367         NULL == fFramebufferTexture2D ||
    368         NULL == fGetFramebufferAttachmentParameteriv ||
    369         NULL == fGetRenderbufferParameteriv ||
    370         NULL == fGenFramebuffers ||
    371         NULL == fGenRenderbuffers ||
    372         NULL == fRenderbufferStorage) {
    373         return false;
    374     }
    375 
    376     const char* ext;
    377     GrGLVersion glVer = GrGLGetVersion(this);
    378     ext = (const char*)fGetString(GR_GL_EXTENSIONS);
    379 
    380     // Now check that baseline ES/Desktop fns not covered above are present
    381     // and that we have fn pointers for any advertised extensions that we will
    382     // try to use.
    383 
    384     // these functions are part of ES2, we assume they are available
    385     // On the desktop we assume they are available if the extension
    386     // is present or GL version is high enough.
    387     if (kES2_GrGLBinding == binding) {
    388         if (NULL == fBlendColor ||
    389             NULL == fStencilFuncSeparate ||
    390             NULL == fStencilMaskSeparate ||
    391             NULL == fStencilOpSeparate) {
    392             return false;
    393         }
    394     } else if (kDesktop_GrGLBinding == binding) {
    395         if (glVer >= GR_GL_VER(2,0)) {
    396             if (NULL == fStencilFuncSeparate ||
    397                 NULL == fStencilMaskSeparate ||
    398                 NULL == fStencilOpSeparate) {
    399                 return false;
    400             }
    401         }
    402         if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
    403             return false;
    404         }
    405         if (glVer >= GR_GL_VER(2,0) ||
    406             GrGLHasExtensionFromString("GL_ARB_draw_buffers", ext)) {
    407             if (NULL == fDrawBuffers) {
    408                 return false;
    409             }
    410         }
    411         if (glVer >= GR_GL_VER(1,4) ||
    412             GrGLHasExtensionFromString("GL_EXT_blend_color", ext)) {
    413             if (NULL == fBlendColor) {
    414                 return false;
    415             }
    416         }
    417         if (glVer >= GR_GL_VER(1,5) ||
    418             GrGLHasExtensionFromString("GL_ARB_occlusion_query", ext)) {
    419             if (NULL == fGenQueries ||
    420                 NULL == fDeleteQueries ||
    421                 NULL == fBeginQuery ||
    422                 NULL == fEndQuery ||
    423                 NULL == fGetQueryiv ||
    424                 NULL == fGetQueryObjectiv ||
    425                 NULL == fGetQueryObjectuiv) {
    426                 return false;
    427             }
    428         }
    429         if (glVer >= GR_GL_VER(3,3) ||
    430             GrGLHasExtensionFromString("GL_ARB_timer_query", ext) ||
    431             GrGLHasExtensionFromString("GL_EXT_timer_query", ext)) {
    432             if (NULL == fGetQueryObjecti64v ||
    433                 NULL == fGetQueryObjectui64v) {
    434                 return false;
    435             }
    436         }
    437         if (glVer >= GR_GL_VER(3,3) ||
    438             GrGLHasExtensionFromString("GL_ARB_timer_query", ext)) {
    439             if (NULL == fQueryCounter) {
    440                 return false;
    441             }
    442         }
    443     }
    444 
    445     // optional function on desktop before 1.3
    446     if (kDesktop_GrGLBinding != binding ||
    447         (glVer >= GR_GL_VER(1,3) ||
    448         GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) {
    449         if (NULL == fCompressedTexImage2D) {
    450             return false;
    451         }
    452     }
    453 
    454     // part of desktop GL, but not ES
    455     if (kDesktop_GrGLBinding == binding &&
    456         (NULL == fLineWidth ||
    457          NULL == fGetTexLevelParameteriv ||
    458          NULL == fDrawBuffer ||
    459          NULL == fReadBuffer)) {
    460         return false;
    461     }
    462 
    463     // GL_EXT_texture_storage is part of desktop 4.2
    464     // There is a desktop ARB extension and an ES+desktop EXT extension
    465     if (kDesktop_GrGLBinding == binding) {
    466         if (glVer >= GR_GL_VER(4,2) ||
    467             GrGLHasExtensionFromString("GL_ARB_texture_storage", ext) ||
    468             GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
    469             if (NULL == fTexStorage2D) {
    470                 return false;
    471             }
    472         }
    473     } else if (GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
    474         if (NULL == fTexStorage2D) {
    475             return false;
    476         }
    477     }
    478 
    479     // FBO MSAA
    480     if (kDesktop_GrGLBinding == binding) {
    481         // GL 3.0 and the ARB extension have multisample + blit
    482         if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", ext)) {
    483             if (NULL == fRenderbufferStorageMultisample ||
    484                 NULL == fBlitFramebuffer) {
    485                 return false;
    486             }
    487         } else {
    488             if (GrGLHasExtensionFromString("GL_EXT_framebuffer_blit", ext) &&
    489                 NULL == fBlitFramebuffer) {
    490                 return false;
    491             }
    492             if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", ext) &&
    493                 NULL == fRenderbufferStorageMultisample) {
    494                 return false;
    495             }
    496         }
    497     } else {
    498         if (GrGLHasExtensionFromString("GL_CHROMIUM_framebuffer_multisample", ext)) {
    499             if (NULL == fRenderbufferStorageMultisample ||
    500                 NULL == fBlitFramebuffer) {
    501                 return false;
    502             }
    503         }
    504         if (GrGLHasExtensionFromString("GL_APPLE_framebuffer_multisample", ext)) {
    505             if (NULL == fRenderbufferStorageMultisample ||
    506                 NULL == fResolveMultisampleFramebuffer) {
    507                 return false;
    508             }
    509         }
    510     }
    511 
    512     // On ES buffer mapping is an extension. On Desktop
    513     // buffer mapping was part of original VBO extension
    514     // which we require.
    515     if (kDesktop_GrGLBinding == binding ||
    516         GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) {
    517         if (NULL == fMapBuffer ||
    518             NULL == fUnmapBuffer) {
    519             return false;
    520         }
    521     }
    522 
    523     // Dual source blending
    524     if (kDesktop_GrGLBinding == binding &&
    525         (glVer >= GR_GL_VER(3,3) ||
    526          GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) {
    527         if (NULL == fBindFragDataLocationIndexed) {
    528             return false;
    529         }
    530     }
    531 
    532     return true;
    533 }
    534 
    535