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 "gl/GrGLInterface.h"
     10 #include "gl/GrGLExtensions.h"
     11 #include "gl/GrGLUtil.h"
     12 
     13 #include <stdio.h>
     14 
     15 #if GR_GL_PER_GL_FUNC_CALLBACK
     16 namespace {
     17 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
     18 }
     19 #endif
     20 
     21 GrGLInterface::GrGLInterface() {
     22     fBindingsExported = kNone_GrGLBinding;
     23 
     24 #if GR_GL_PER_GL_FUNC_CALLBACK
     25     fCallback = GrGLDefaultInterfaceCallback;
     26     fCallbackData = 0;
     27 #endif
     28 }
     29 
     30 bool GrGLInterface::validate(GrGLBinding binding) const {
     31 
     32     // kNone must be 0 so that the check we're about to do can never succeed if
     33     // binding == kNone.
     34     GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
     35 
     36     if (0 == (binding & fBindingsExported)) {
     37         return false;
     38     }
     39 
     40     GrGLExtensions extensions;
     41     if (!extensions.init(binding, this)) {
     42         return false;
     43     }
     44 
     45     // functions that are always required
     46     if (NULL == fActiveTexture ||
     47         NULL == fAttachShader ||
     48         NULL == fBindAttribLocation ||
     49         NULL == fBindBuffer ||
     50         NULL == fBindTexture ||
     51         NULL == fBlendFunc ||
     52         NULL == fBlendColor ||      // -> GL >= 1.4, ES >= 2.0 or extension
     53         NULL == fBufferData ||
     54         NULL == fBufferSubData ||
     55         NULL == fClear ||
     56         NULL == fClearColor ||
     57         NULL == fClearStencil ||
     58         NULL == fColorMask ||
     59         NULL == fCompileShader ||
     60         NULL == fCopyTexSubImage2D ||
     61         NULL == fCreateProgram ||
     62         NULL == fCreateShader ||
     63         NULL == fCullFace ||
     64         NULL == fDeleteBuffers ||
     65         NULL == fDeleteProgram ||
     66         NULL == fDeleteShader ||
     67         NULL == fDeleteTextures ||
     68         NULL == fDepthMask ||
     69         NULL == fDisable ||
     70         NULL == fDisableVertexAttribArray ||
     71         NULL == fDrawArrays ||
     72         NULL == fDrawElements ||
     73         NULL == fEnable ||
     74         NULL == fEnableVertexAttribArray ||
     75         NULL == fFrontFace ||
     76         NULL == fGenBuffers ||
     77         NULL == fGenTextures ||
     78         NULL == fGetBufferParameteriv ||
     79         NULL == fGenerateMipmap ||
     80         NULL == fGetError ||
     81         NULL == fGetIntegerv ||
     82         NULL == fGetProgramInfoLog ||
     83         NULL == fGetProgramiv ||
     84         NULL == fGetShaderInfoLog ||
     85         NULL == fGetShaderiv ||
     86         NULL == fGetString ||
     87         NULL == fGetUniformLocation ||
     88         NULL == fLinkProgram ||
     89         NULL == fLineWidth ||
     90         NULL == fPixelStorei ||
     91         NULL == fReadPixels ||
     92         NULL == fScissor ||
     93         NULL == fShaderSource ||
     94         NULL == fStencilFunc ||
     95         NULL == fStencilMask ||
     96         NULL == fStencilOp ||
     97         NULL == fTexImage2D ||
     98         NULL == fTexParameteri ||
     99         NULL == fTexParameteriv ||
    100         NULL == fTexSubImage2D ||
    101         NULL == fUniform1f ||
    102         NULL == fUniform1i ||
    103         NULL == fUniform1fv ||
    104         NULL == fUniform1iv ||
    105         NULL == fUniform2f ||
    106         NULL == fUniform2i ||
    107         NULL == fUniform2fv ||
    108         NULL == fUniform2iv ||
    109         NULL == fUniform3f ||
    110         NULL == fUniform3i ||
    111         NULL == fUniform3fv ||
    112         NULL == fUniform3iv ||
    113         NULL == fUniform4f ||
    114         NULL == fUniform4i ||
    115         NULL == fUniform4fv ||
    116         NULL == fUniform4iv ||
    117         NULL == fUniformMatrix2fv ||
    118         NULL == fUniformMatrix3fv ||
    119         NULL == fUniformMatrix4fv ||
    120         NULL == fUseProgram ||
    121         NULL == fVertexAttrib4fv ||
    122         NULL == fVertexAttribPointer ||
    123         NULL == fViewport ||
    124         NULL == fBindFramebuffer ||
    125         NULL == fBindRenderbuffer ||
    126         NULL == fCheckFramebufferStatus ||
    127         NULL == fDeleteFramebuffers ||
    128         NULL == fDeleteRenderbuffers ||
    129         NULL == fFinish ||
    130         NULL == fFlush ||
    131         NULL == fFramebufferRenderbuffer ||
    132         NULL == fFramebufferTexture2D ||
    133         NULL == fGetFramebufferAttachmentParameteriv ||
    134         NULL == fGetRenderbufferParameteriv ||
    135         NULL == fGenFramebuffers ||
    136         NULL == fGenRenderbuffers ||
    137         NULL == fRenderbufferStorage) {
    138         return false;
    139     }
    140 
    141     GrGLVersion glVer = GrGLGetVersion(this);
    142 
    143     bool isCoreProfile = false;
    144     if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3,2)) {
    145         GrGLint profileMask;
    146         GR_GL_GetIntegerv(this, GR_GL_CONTEXT_PROFILE_MASK, &profileMask);
    147         isCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT);
    148     }
    149 
    150     // Now check that baseline ES/Desktop fns not covered above are present
    151     // and that we have fn pointers for any advertised extensions that we will
    152     // try to use.
    153 
    154     // these functions are part of ES2, we assume they are available
    155     // On the desktop we assume they are available if the extension
    156     // is present or GL version is high enough.
    157     if (kES_GrGLBinding == binding) {
    158         if (NULL == fStencilFuncSeparate ||
    159             NULL == fStencilMaskSeparate ||
    160             NULL == fStencilOpSeparate) {
    161             return false;
    162         }
    163     } else if (kDesktop_GrGLBinding == binding) {
    164 
    165         if (glVer >= GR_GL_VER(2,0)) {
    166             if (NULL == fStencilFuncSeparate ||
    167                 NULL == fStencilMaskSeparate ||
    168                 NULL == fStencilOpSeparate) {
    169                 return false;
    170             }
    171         }
    172         if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
    173             return false;
    174         }
    175         if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
    176             if (NULL == fDrawBuffers) {
    177                 return false;
    178             }
    179         }
    180 
    181         if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
    182             if (NULL == fGenQueries ||
    183                 NULL == fDeleteQueries ||
    184                 NULL == fBeginQuery ||
    185                 NULL == fEndQuery ||
    186                 NULL == fGetQueryiv ||
    187                 NULL == fGetQueryObjectiv ||
    188                 NULL == fGetQueryObjectuiv) {
    189                 return false;
    190             }
    191         }
    192         if (glVer >= GR_GL_VER(3,3) ||
    193             extensions.has("GL_ARB_timer_query") ||
    194             extensions.has("GL_EXT_timer_query")) {
    195             if (NULL == fGetQueryObjecti64v ||
    196                 NULL == fGetQueryObjectui64v) {
    197                 return false;
    198             }
    199         }
    200         if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
    201             if (NULL == fQueryCounter) {
    202                 return false;
    203             }
    204         }
    205         if (!isCoreProfile) {
    206             if (NULL == fClientActiveTexture ||
    207                 NULL == fDisableClientState ||
    208                 NULL == fEnableClientState ||
    209                 NULL == fLoadIdentity ||
    210                 NULL == fLoadMatrixf ||
    211                 NULL == fMatrixMode ||
    212                 NULL == fTexGenf ||
    213                 NULL == fTexGenfv ||
    214                 NULL == fTexGeni ||
    215                 NULL == fVertexPointer) {
    216                 return false;
    217             }
    218         }
    219         if (false && extensions.has("GL_NV_path_rendering")) {
    220             if (NULL == fPathCommands ||
    221                 NULL == fPathCoords ||
    222                 NULL == fPathSubCommands ||
    223                 NULL == fPathSubCoords ||
    224                 NULL == fPathString ||
    225                 NULL == fPathGlyphs ||
    226                 NULL == fPathGlyphRange ||
    227                 NULL == fWeightPaths ||
    228                 NULL == fCopyPath ||
    229                 NULL == fInterpolatePaths ||
    230                 NULL == fTransformPath ||
    231                 NULL == fPathParameteriv ||
    232                 NULL == fPathParameteri ||
    233                 NULL == fPathParameterfv ||
    234                 NULL == fPathParameterf ||
    235                 NULL == fPathDashArray ||
    236                 NULL == fGenPaths ||
    237                 NULL == fDeletePaths ||
    238                 NULL == fIsPath ||
    239                 NULL == fPathStencilFunc ||
    240                 NULL == fPathStencilDepthOffset ||
    241                 NULL == fStencilFillPath ||
    242                 NULL == fStencilStrokePath ||
    243                 NULL == fStencilFillPathInstanced ||
    244                 NULL == fStencilStrokePathInstanced ||
    245                 NULL == fPathCoverDepthFunc ||
    246                 NULL == fPathColorGen ||
    247                 NULL == fPathTexGen ||
    248                 NULL == fPathFogGen ||
    249                 NULL == fCoverFillPath ||
    250                 NULL == fCoverStrokePath ||
    251                 NULL == fCoverFillPathInstanced ||
    252                 NULL == fCoverStrokePathInstanced ||
    253                 NULL == fGetPathParameteriv ||
    254                 NULL == fGetPathParameterfv ||
    255                 NULL == fGetPathCommands ||
    256                 NULL == fGetPathCoords ||
    257                 NULL == fGetPathDashArray ||
    258                 NULL == fGetPathMetrics ||
    259                 NULL == fGetPathMetricRange ||
    260                 NULL == fGetPathSpacing ||
    261                 NULL == fGetPathColorGeniv ||
    262                 NULL == fGetPathColorGenfv ||
    263                 NULL == fGetPathTexGeniv ||
    264                 NULL == fGetPathTexGenfv ||
    265                 NULL == fIsPointInFillPath ||
    266                 NULL == fIsPointInStrokePath ||
    267                 NULL == fGetPathLength ||
    268                 NULL == fPointAlongPath) {
    269                 return false;
    270             }
    271         }
    272     }
    273 
    274     // optional function on desktop before 1.3
    275     if (kDesktop_GrGLBinding != binding ||
    276         (glVer >= GR_GL_VER(1,3)) ||
    277         extensions.has("GL_ARB_texture_compression")) {
    278         if (NULL == fCompressedTexImage2D) {
    279             return false;
    280         }
    281     }
    282 
    283     // part of desktop GL, but not ES
    284     if (kDesktop_GrGLBinding == binding &&
    285         (NULL == fGetTexLevelParameteriv ||
    286          NULL == fDrawBuffer ||
    287          NULL == fReadBuffer)) {
    288         return false;
    289     }
    290 
    291     // GL_EXT_texture_storage is part of desktop 4.2
    292     // There is a desktop ARB extension and an ES+desktop EXT extension
    293     if (kDesktop_GrGLBinding == binding) {
    294         if (glVer >= GR_GL_VER(4,2) ||
    295             extensions.has("GL_ARB_texture_storage") ||
    296             extensions.has("GL_EXT_texture_storage")) {
    297             if (NULL == fTexStorage2D) {
    298                 return false;
    299             }
    300         }
    301     } else if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_EXT_texture_storage")) {
    302         if (NULL == fTexStorage2D) {
    303             return false;
    304         }
    305     }
    306 
    307     if (extensions.has("GL_EXT_discard_framebuffer")) {
    308 // FIXME: Remove this once Chromium is updated to provide this function
    309 #if 0
    310         if (NULL == fDiscardFramebuffer) {
    311             return false;
    312         }
    313 #endif
    314     }
    315 
    316     // FBO MSAA
    317     if (kDesktop_GrGLBinding == binding) {
    318         // GL 3.0 and the ARB extension have multisample + blit
    319         if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
    320             if (NULL == fRenderbufferStorageMultisample ||
    321                 NULL == fBlitFramebuffer) {
    322                 return false;
    323             }
    324         } else {
    325             if (extensions.has("GL_EXT_framebuffer_blit") &&
    326                 NULL == fBlitFramebuffer) {
    327                 return false;
    328             }
    329             if (extensions.has("GL_EXT_framebuffer_multisample") &&
    330                 NULL == fRenderbufferStorageMultisample) {
    331                 return false;
    332             }
    333         }
    334     } else {
    335 #if GR_GL_IGNORE_ES3_MSAA
    336         if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
    337             if (NULL == fRenderbufferStorageMultisample ||
    338                 NULL == fBlitFramebuffer) {
    339                 return false;
    340             }
    341         } else if (extensions.has("GL_APPLE_framebuffer_multisample")) {
    342             if (NULL == fRenderbufferStorageMultisample ||
    343                 NULL == fResolveMultisampleFramebuffer) {
    344                 return false;
    345             }
    346         } else if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
    347                    extensions.has("GL_EXT_multisampled_render_to_texture")) {
    348             if (NULL == fRenderbufferStorageMultisample ||
    349                 NULL == fFramebufferTexture2DMultisample) {
    350                 return false;
    351             }
    352         }
    353 #else
    354         if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
    355             if (NULL == fRenderbufferStorageMultisample ||
    356                 NULL == fBlitFramebuffer) {
    357                 return false;
    358             }
    359         }
    360         if (extensions.has("GL_APPLE_framebuffer_multisample")) {
    361             if (NULL == fRenderbufferStorageMultisampleES2APPLE ||
    362                 NULL == fResolveMultisampleFramebuffer) {
    363                 return false;
    364             }
    365         }
    366         if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
    367             extensions.has("GL_EXT_multisampled_render_to_texture")) {
    368             if (NULL == fRenderbufferStorageMultisampleES2EXT ||
    369                 NULL == fFramebufferTexture2DMultisample) {
    370                 return false;
    371             }
    372         }
    373 #endif
    374     }
    375 
    376     // On ES buffer mapping is an extension. On Desktop
    377     // buffer mapping was part of original VBO extension
    378     // which we require.
    379     if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) {
    380         if (NULL == fMapBuffer ||
    381             NULL == fUnmapBuffer) {
    382             return false;
    383         }
    384     }
    385 
    386     // Dual source blending
    387     if (kDesktop_GrGLBinding == binding &&
    388         (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
    389         if (NULL == fBindFragDataLocationIndexed) {
    390             return false;
    391         }
    392     }
    393 
    394     // glGetStringi was added in version 3.0 of both desktop and ES.
    395     if (glVer >= GR_GL_VER(3, 0)) {
    396         if (NULL == fGetStringi) {
    397             return false;
    398         }
    399     }
    400 
    401     if (kDesktop_GrGLBinding == binding) {
    402         if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) {
    403             if (NULL == fBindVertexArray ||
    404                 NULL == fDeleteVertexArrays ||
    405                 NULL == fGenVertexArrays) {
    406                 return false;
    407             }
    408         }
    409     } else {
    410         if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_OES_vertex_array_object")) {
    411             if (NULL == fBindVertexArray ||
    412                 NULL == fDeleteVertexArrays ||
    413                 NULL == fGenVertexArrays) {
    414                 return false;
    415             }
    416         }
    417     }
    418 
    419     return true;
    420 }
    421