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