Home | History | Annotate | Download | only in src
      1 /*
      2     Copyright 2011 Google Inc.
      3 
      4     Licensed under the Apache License, Version 2.0 (the "License");
      5     you may not use this file except in compliance with the License.
      6     You may obtain a copy of the License at
      7 
      8          http://www.apache.org/licenses/LICENSE-2.0
      9 
     10     Unless required by applicable law or agreed to in writing, software
     11     distributed under the License is distributed on an "AS IS" BASIS,
     12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13     See the License for the specific language governing permissions and
     14     limitations under the License.
     15  */
     16 
     17 
     18 #include "GrTypes.h"
     19 #include "GrGLInterface.h"
     20 #include "GrGLDefines.h"
     21 
     22 #include <stdio.h>
     23 
     24 GrGLInterface* gGLInterface = NULL;
     25 
     26 void gl_version_from_string(int* major, int* minor,
     27                             const char* versionString) {
     28     if (NULL == versionString) {
     29         GrAssert(0);
     30         *major = 0;
     31         *minor = 0;
     32         return;
     33     }
     34 
     35     int n = sscanf(versionString, "%d.%d", major, minor);
     36     if (2 == n) {
     37       return;
     38     }
     39 
     40     char profile[2];
     41     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
     42                major, minor);
     43     bool ok = 4 == n;
     44     if (!ok) {
     45         n = sscanf(versionString, "OpenGL ES %d.%d", major, minor);
     46         ok = 2 == n;
     47     }
     48 
     49     if (!ok) {
     50         GrAssert(0);
     51         *major = 0;
     52         *minor = 0;
     53         return;
     54     }
     55 }
     56 
     57 bool has_gl_extension_from_string(const char* ext,
     58                                   const char* extensionString) {
     59     int extLength = strlen(ext);
     60 
     61     while (true) {
     62         int n = strcspn(extensionString, " ");
     63         if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
     64             return true;
     65         }
     66         if (0 == extensionString[n]) {
     67             return false;
     68         }
     69         extensionString += n+1;
     70     }
     71 
     72     return false;
     73 }
     74 
     75 
     76 GR_API void GrGLSetGLInterface(GrGLInterface* gl_interface) {
     77     gGLInterface = gl_interface;
     78 }
     79 
     80 GR_API GrGLInterface* GrGLGetGLInterface() {
     81     return gGLInterface;
     82 }
     83 
     84 bool has_gl_extension(const char* ext) {
     85     const char* glstr = reinterpret_cast<const char*>(
     86                 GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
     87 
     88     return has_gl_extension_from_string(ext, glstr);
     89 }
     90 
     91 void gl_version(int* major, int* minor) {
     92     const char* v = reinterpret_cast<const char*>(
     93                 GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
     94     gl_version_from_string(major, minor, v);
     95 }
     96 
     97 bool GrGLInterface::validateShaderFunctions() const {
     98     // required for GrGpuGLShaders
     99     if (NULL == fAttachShader ||
    100         NULL == fBindAttribLocation ||
    101         NULL == fCompileShader ||
    102         NULL == fCreateProgram ||
    103         NULL == fCreateShader ||
    104         NULL == fDeleteProgram ||
    105         NULL == fDeleteShader ||
    106         NULL == fDisableVertexAttribArray ||
    107         NULL == fEnableVertexAttribArray ||
    108         NULL == fGetProgramInfoLog ||
    109         NULL == fGetProgramiv ||
    110         NULL == fGetShaderInfoLog ||
    111         NULL == fGetShaderiv ||
    112         NULL == fGetUniformLocation ||
    113         NULL == fLinkProgram ||
    114         NULL == fShaderSource ||
    115         NULL == fUniform1f ||
    116         NULL == fUniform1i ||
    117         NULL == fUniform1fv ||
    118         NULL == fUniform1iv ||
    119         NULL == fUniform2f ||
    120         NULL == fUniform2i ||
    121         NULL == fUniform2fv ||
    122         NULL == fUniform2iv ||
    123         NULL == fUniform3f ||
    124         NULL == fUniform3i ||
    125         NULL == fUniform3fv ||
    126         NULL == fUniform3iv ||
    127         NULL == fUniform4f ||
    128         NULL == fUniform4i ||
    129         NULL == fUniform4fv ||
    130         NULL == fUniform4iv ||
    131         NULL == fUniformMatrix2fv ||
    132         NULL == fUniformMatrix3fv ||
    133         NULL == fUniformMatrix4fv ||
    134         NULL == fUseProgram ||
    135         NULL == fVertexAttrib4fv ||
    136         NULL == fVertexAttribPointer) {
    137         return false;
    138     }
    139     return true;
    140 }
    141 
    142 bool GrGLInterface::validateFixedFunctions() const {
    143     if (NULL == fClientActiveTexture ||
    144         NULL == fColor4ub ||
    145         NULL == fColorPointer ||
    146         NULL == fDisableClientState ||
    147         NULL == fEnableClientState ||
    148         NULL == fLoadMatrixf ||
    149         NULL == fMatrixMode ||
    150         NULL == fPointSize ||
    151         NULL == fShadeModel ||
    152         NULL == fTexCoordPointer ||
    153         NULL == fTexEnvi ||
    154         NULL == fVertexPointer) {
    155         return false;
    156     }
    157     return true;
    158 }
    159 
    160 bool GrGLInterface::validate(GrEngine engine) const {
    161 
    162     bool isDesktop = kDesktop_GrGLBinding == fBindingsExported;
    163 
    164     // ES1 and 2 can be supported in the same interface
    165     bool isES = ((kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported &&
    166                  !(~(kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported));
    167 
    168     if (!isDesktop && !isES) {
    169         return false;
    170     }
    171 
    172     // functions that are always required
    173     if (NULL == fActiveTexture ||
    174         NULL == fBindBuffer ||
    175         NULL == fBindTexture ||
    176         NULL == fBlendFunc ||
    177         NULL == fBufferData ||
    178         NULL == fBufferSubData ||
    179         NULL == fClear ||
    180         NULL == fClearColor ||
    181         NULL == fClearStencil ||
    182         NULL == fColorMask ||
    183         NULL == fCullFace ||
    184         NULL == fDeleteBuffers ||
    185         NULL == fDeleteTextures ||
    186         NULL == fDepthMask ||
    187         NULL == fDisable ||
    188         NULL == fDrawArrays ||
    189         NULL == fDrawElements ||
    190         NULL == fEnable ||
    191         NULL == fFrontFace ||
    192         NULL == fGenBuffers ||
    193         NULL == fGenTextures ||
    194         NULL == fGetBufferParameteriv ||
    195         NULL == fGetError ||
    196         NULL == fGetIntegerv ||
    197         NULL == fGetString ||
    198         NULL == fPixelStorei ||
    199         NULL == fReadPixels ||
    200         NULL == fScissor ||
    201         NULL == fStencilFunc ||
    202         NULL == fStencilMask ||
    203         NULL == fStencilOp ||
    204         NULL == fTexImage2D ||
    205         NULL == fTexParameteri ||
    206         NULL == fTexSubImage2D ||
    207         NULL == fViewport ||
    208         NULL == fBindFramebuffer ||
    209         NULL == fBindRenderbuffer ||
    210         NULL == fCheckFramebufferStatus ||
    211         NULL == fDeleteFramebuffers ||
    212         NULL == fDeleteRenderbuffers ||
    213         NULL == fFramebufferRenderbuffer ||
    214         NULL == fFramebufferTexture2D ||
    215         NULL == fGenFramebuffers ||
    216         NULL == fGenRenderbuffers ||
    217         NULL == fRenderbufferStorage) {
    218         return false;
    219     }
    220 
    221     switch (engine) {
    222         case kOpenGL_Shaders_GrEngine:
    223             if (kES1_GrGLBinding == fBindingsExported) {
    224                 return false;
    225             }
    226             if (!this->validateShaderFunctions()) {
    227                 return false;
    228             }
    229             break;
    230         case kOpenGL_Fixed_GrEngine:
    231             if (kES1_GrGLBinding == fBindingsExported) {
    232                 return false;
    233             }
    234             if (!this->validateFixedFunctions()) {
    235                 return false;
    236             }
    237             break;
    238         default:
    239             return false;
    240     }
    241 
    242     int major, minor;
    243     const char* ext;
    244 
    245     gl_version(&major, &minor);
    246     ext = (const char*)fGetString(GR_GL_EXTENSIONS);
    247 
    248     // Now check that baseline ES/Desktop fns not covered above are present
    249     // and that we have fn pointers for any advertised extensions that we will
    250     // try to use.
    251 
    252     // these functions are part of ES2, we assume they are available
    253     // On the desktop we assume they are available if the extension
    254     // is present or GL version is high enough.
    255     if ((kES2_GrGLBinding & fBindingsExported)) {
    256         if (NULL == fBlendColor ||
    257             NULL == fStencilFuncSeparate ||
    258             NULL == fStencilMaskSeparate ||
    259             NULL == fStencilOpSeparate) {
    260             return false;
    261         }
    262     } else if (kDesktop_GrGLBinding == fBindingsExported) {
    263         if (major >= 2) {
    264             if (NULL == fStencilFuncSeparate ||
    265                 NULL == fStencilMaskSeparate ||
    266                 NULL == fStencilOpSeparate) {
    267                 return false;
    268             }
    269         }
    270         if (1 < major || (1 == major && 4 <= minor) ||
    271             has_gl_extension_from_string("GL_EXT_blend_color", ext)) {
    272             if (NULL == fBlendColor) {
    273                 return false;
    274             }
    275         }
    276     }
    277 
    278     // optional function on desktop before 1.3
    279     if (kDesktop_GrGLBinding != fBindingsExported ||
    280         (1 < major || (1 == major && 3 <= minor)) ||
    281         has_gl_extension_from_string("GL_ARB_texture_compression", ext)) {
    282         if (NULL == fCompressedTexImage2D) {
    283             return false;
    284         }
    285     }
    286 
    287     // part of desktop GL
    288     if (kDesktop_GrGLBinding == fBindingsExported &&
    289         NULL == fLineWidth) {
    290         return false;
    291     }
    292     // FBO MSAA
    293     if (kDesktop_GrGLBinding == fBindingsExported) {
    294         // GL 3.0 and the ARB extension have multisample + blit
    295         if ((major >= 3) || has_gl_extension_from_string("GL_ARB_framebuffer_object", ext)) {
    296             if (NULL == fRenderbufferStorageMultisample ||
    297                 NULL == fBlitFramebuffer) {
    298                 return false;
    299             }
    300         } else {
    301             if (has_gl_extension_from_string("GL_EXT_framebuffer_blit", ext) &&
    302                 NULL == fBlitFramebuffer) {
    303                 return false;
    304             }
    305             if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample", ext) &&
    306                 NULL == fRenderbufferStorageMultisample) {
    307                 return false;
    308             }
    309         }
    310     } else {
    311         if (has_gl_extension_from_string("GL_CHROMIUM_framebuffer_multisample", ext)) {
    312             if (NULL == fRenderbufferStorageMultisample ||
    313                 NULL == fBlitFramebuffer) {
    314                 return false;
    315             }
    316         }
    317         if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample", ext)) {
    318             if (NULL == fRenderbufferStorageMultisample ||
    319                 NULL == fResolveMultisampleFramebuffer) {
    320                 return false;
    321             }
    322         }
    323     }
    324 
    325     // On ES buffer mapping is an extension. On Desktop
    326     // buffer mapping was part of original VBO extension
    327     // which we require.
    328     if (kDesktop_GrGLBinding == fBindingsExported  ||
    329         has_gl_extension_from_string("GL_OES_mapbuffer", ext)) {
    330         if (NULL == fMapBuffer ||
    331             NULL == fUnmapBuffer) {
    332             return false;
    333         }
    334     }
    335 
    336     // Dual source blending
    337     if (kDesktop_GrGLBinding == fBindingsExported  &&
    338         (has_gl_extension_from_string("GL_ARB_blend_func_extended", ext) ||
    339          (3 < major) || (3 == major && 3 <= minor))) {
    340         if (NULL == fBindFragDataLocationIndexed) {
    341             return false;
    342         }
    343     }
    344 
    345     return true;
    346 }
    347 
    348