180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/*
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2011 Google Inc.
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file.
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "gl/GrGLInterface.h"
10096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "gl/GrGLExtensions.h"
11096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger#include "gl/GrGLUtil.h"
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include <stdio.h>
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_GL_PER_GL_FUNC_CALLBACK
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querunamespace {
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruvoid GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste QueruGrGLInterface::GrGLInterface() {
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fBindingsExported = kNone_GrGLBinding;
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#if GR_GL_PER_GL_FUNC_CALLBACK
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCallback = GrGLDefaultInterfaceCallback;
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    fCallbackData = 0;
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querubool GrGLInterface::validate(GrGLBinding binding) const {
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // kNone must be 0 so that the check we're about to do can never succeed if
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // binding == kNone.
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (0 == (binding & fBindingsExported)) {
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
40096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    GrGLExtensions extensions;
41096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (!extensions.init(binding, this)) {
42096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        return false;
43096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
44096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // functions that are always required
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (NULL == fActiveTexture ||
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fAttachShader ||
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBindAttribLocation ||
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBindBuffer ||
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBindTexture ||
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBlendFunc ||
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBlendColor ||      // -> GL >= 1.4, ES >= 2.0 or extension
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBufferData ||
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBufferSubData ||
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fClear ||
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fClearColor ||
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fClearStencil ||
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fColorMask ||
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fCompileShader ||
607839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        NULL == fCopyTexSubImage2D ||
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fCreateProgram ||
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fCreateShader ||
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fCullFace ||
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDeleteBuffers ||
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDeleteProgram ||
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDeleteShader ||
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDeleteTextures ||
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDepthMask ||
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDisable ||
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDisableVertexAttribArray ||
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDrawArrays ||
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDrawElements ||
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fEnable ||
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fEnableVertexAttribArray ||
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fFrontFace ||
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGenBuffers ||
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGenTextures ||
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetBufferParameteriv ||
79e27eefc4844477cee5d32f51ab45ff62020cdb36Derek Sollenberger        NULL == fGenerateMipmap ||
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetError ||
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetIntegerv ||
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetProgramInfoLog ||
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetProgramiv ||
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetShaderInfoLog ||
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetShaderiv ||
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetString ||
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetUniformLocation ||
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fLinkProgram ||
890a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        NULL == fLineWidth ||
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fPixelStorei ||
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fReadPixels ||
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fScissor ||
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fShaderSource ||
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fStencilFunc ||
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fStencilMask ||
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fStencilOp ||
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fTexImage2D ||
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fTexParameteri ||
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fTexParameteriv ||
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fTexSubImage2D ||
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform1f ||
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform1i ||
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform1fv ||
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform1iv ||
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform2f ||
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform2i ||
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform2fv ||
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform2iv ||
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform3f ||
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform3i ||
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform3fv ||
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform3iv ||
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform4f ||
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform4i ||
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform4fv ||
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniform4iv ||
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniformMatrix2fv ||
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniformMatrix3fv ||
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUniformMatrix4fv ||
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fUseProgram ||
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fVertexAttrib4fv ||
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fVertexAttribPointer ||
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fViewport ||
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBindFramebuffer ||
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fBindRenderbuffer ||
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fCheckFramebufferStatus ||
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDeleteFramebuffers ||
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fDeleteRenderbuffers ||
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fFinish ||
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fFlush ||
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fFramebufferRenderbuffer ||
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fFramebufferTexture2D ||
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetFramebufferAttachmentParameteriv ||
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGetRenderbufferParameteriv ||
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGenFramebuffers ||
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fGenRenderbuffers ||
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        NULL == fRenderbufferStorage) {
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    GrGLVersion glVer = GrGLGetVersion(this);
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
1430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    bool isCoreProfile = false;
1440a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3,2)) {
1450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        GrGLint profileMask;
1460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        GR_GL_GetIntegerv(this, GR_GL_CONTEXT_PROFILE_MASK, &profileMask);
1470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        isCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT);
1480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    }
1490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Now check that baseline ES/Desktop fns not covered above are present
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // and that we have fn pointers for any advertised extensions that we will
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // try to use.
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // these functions are part of ES2, we assume they are available
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // On the desktop we assume they are available if the extension
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // is present or GL version is high enough.
1570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (kES_GrGLBinding == binding) {
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == fStencilFuncSeparate ||
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            NULL == fStencilMaskSeparate ||
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            NULL == fStencilOpSeparate) {
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else if (kDesktop_GrGLBinding == binding) {
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (glVer >= GR_GL_VER(2,0)) {
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fStencilFuncSeparate ||
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fStencilMaskSeparate ||
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fStencilOpSeparate) {
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
175096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fDrawBuffers) {
17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
181096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fGenQueries ||
18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fDeleteQueries ||
18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fBeginQuery ||
18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fEndQuery ||
18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetQueryiv ||
18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetQueryObjectiv ||
18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetQueryObjectuiv) {
18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (glVer >= GR_GL_VER(3,3) ||
193096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            extensions.has("GL_ARB_timer_query") ||
194096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            extensions.has("GL_EXT_timer_query")) {
19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fGetQueryObjecti64v ||
19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetQueryObjectui64v) {
19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
200096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fQueryCounter) {
20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
2050a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (!isCoreProfile) {
2060a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            if (NULL == fClientActiveTexture ||
2070a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fDisableClientState ||
2080a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fEnableClientState ||
2090a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fLoadIdentity ||
2100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fLoadMatrixf ||
2110a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fMatrixMode ||
2120a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fTexGenf ||
2130a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fTexGenfv ||
2140a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fTexGeni ||
2150a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fVertexPointer) {
2160a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                return false;
2170a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            }
21880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
219096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (false && extensions.has("GL_NV_path_rendering")) {
22080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fPathCommands ||
22180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathCoords ||
22280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathSubCommands ||
22380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathSubCoords ||
22480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathString ||
22580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathGlyphs ||
22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathGlyphRange ||
22780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fWeightPaths ||
22880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fCopyPath ||
22980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fInterpolatePaths ||
23080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fTransformPath ||
23180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathParameteriv ||
23280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathParameteri ||
23380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathParameterfv ||
23480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathParameterf ||
23580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathDashArray ||
23680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGenPaths ||
23780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fDeletePaths ||
23880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fIsPath ||
23980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathStencilFunc ||
24080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathStencilDepthOffset ||
24180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fStencilFillPath ||
24280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fStencilStrokePath ||
24380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fStencilFillPathInstanced ||
24480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fStencilStrokePathInstanced ||
24580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathCoverDepthFunc ||
24680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathColorGen ||
24780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathTexGen ||
24880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPathFogGen ||
24980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fCoverFillPath ||
25080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fCoverStrokePath ||
25180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fCoverFillPathInstanced ||
25280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fCoverStrokePathInstanced ||
25380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathParameteriv ||
25480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathParameterfv ||
25580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathCommands ||
25680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathCoords ||
25780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathDashArray ||
25880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathMetrics ||
25980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathMetricRange ||
26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathSpacing ||
26180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathColorGeniv ||
26280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathColorGenfv ||
26380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathTexGeniv ||
26480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathTexGenfv ||
26580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fIsPointInFillPath ||
26680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fIsPointInStrokePath ||
26780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fGetPathLength ||
26880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fPointAlongPath) {
26980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
27080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
27180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
27280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
27380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
27480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // optional function on desktop before 1.3
27580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kDesktop_GrGLBinding != binding ||
276096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        (glVer >= GR_GL_VER(1,3)) ||
277096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        extensions.has("GL_ARB_texture_compression")) {
27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == fCompressedTexImage2D) {
27980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
28080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
28180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // part of desktop GL, but not ES
28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kDesktop_GrGLBinding == binding &&
2850a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        (NULL == fGetTexLevelParameteriv ||
28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         NULL == fDrawBuffer ||
28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru         NULL == fReadBuffer)) {
28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        return false;
28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // GL_EXT_texture_storage is part of desktop 4.2
29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // There is a desktop ARB extension and an ES+desktop EXT extension
29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kDesktop_GrGLBinding == binding) {
29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (glVer >= GR_GL_VER(4,2) ||
295096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            extensions.has("GL_ARB_texture_storage") ||
296096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            extensions.has("GL_EXT_texture_storage")) {
29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fTexStorage2D) {
29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
3010a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    } else if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_EXT_texture_storage")) {
30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == fTexStorage2D) {
30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
30480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
30580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
30680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3077839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    if (extensions.has("GL_EXT_discard_framebuffer")) {
3087839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger// FIXME: Remove this once Chromium is updated to provide this function
3097839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#if 0
3107839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (NULL == fDiscardFramebuffer) {
3117839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            return false;
3127839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        }
3137839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger#endif
3147839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger    }
3157839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger
31680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // FBO MSAA
31780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kDesktop_GrGLBinding == binding) {
31880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        // GL 3.0 and the ARB extension have multisample + blit
319096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
32080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fRenderbufferStorageMultisample ||
32180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fBlitFramebuffer) {
32280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
32380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
32480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        } else {
325096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            if (extensions.has("GL_EXT_framebuffer_blit") &&
32680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fBlitFramebuffer) {
32780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
32880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
329096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            if (extensions.has("GL_EXT_framebuffer_multisample") &&
33080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fRenderbufferStorageMultisample) {
33180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
33280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
33380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
33480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    } else {
3350a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#if GR_GL_IGNORE_ES3_MSAA
336096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
33780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fRenderbufferStorageMultisample ||
33880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fBlitFramebuffer) {
33980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
34080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
3410a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        } else if (extensions.has("GL_APPLE_framebuffer_multisample")) {
3420a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            if (NULL == fRenderbufferStorageMultisample ||
3430a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fResolveMultisampleFramebuffer) {
3440a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                return false;
3450a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            }
3460a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        } else if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
3470a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                   extensions.has("GL_EXT_multisampled_render_to_texture")) {
3480a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            if (NULL == fRenderbufferStorageMultisample ||
3490a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fFramebufferTexture2DMultisample) {
3500a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                return false;
3510a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            }
35280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
3530a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#else
3540a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
35580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            if (NULL == fRenderbufferStorageMultisample ||
3560a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                NULL == fBlitFramebuffer) {
3570a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger                return false;
3580a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            }
3590a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        }
3600a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (extensions.has("GL_APPLE_framebuffer_multisample")) {
3610a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            if (NULL == fRenderbufferStorageMultisampleES2APPLE ||
36280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                NULL == fResolveMultisampleFramebuffer) {
36380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                return false;
36480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            }
36580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
3667839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger        if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
3677839ce1af63bf12fe7b3caa866970bbbb3afb13dDerek Sollenberger            extensions.has("GL_EXT_multisampled_render_to_texture")) {
3680a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger            if (NULL == fRenderbufferStorageMultisampleES2EXT ||
369096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                NULL == fFramebufferTexture2DMultisample) {
370096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                return false;
371096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
372096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
3730a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger#endif
37480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
37580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
37680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // On ES buffer mapping is an extension. On Desktop
37780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // buffer mapping was part of original VBO extension
37880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // which we require.
379096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) {
38080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == fMapBuffer ||
38180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            NULL == fUnmapBuffer) {
38280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
38380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
38480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
38580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
38680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    // Dual source blending
38780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    if (kDesktop_GrGLBinding == binding &&
388096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
38980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        if (NULL == fBindFragDataLocationIndexed) {
39080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru            return false;
39180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru        }
39280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    }
39380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3940a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    // glGetStringi was added in version 3.0 of both desktop and ES.
3950a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger    if (glVer >= GR_GL_VER(3, 0)) {
396096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (NULL == fGetStringi) {
397096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            return false;
398096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
399096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
400096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
401096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    if (kDesktop_GrGLBinding == binding) {
402096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) {
403096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            if (NULL == fBindVertexArray ||
404096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                NULL == fDeleteVertexArrays ||
405096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                NULL == fGenVertexArrays) {
406096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                return false;
407096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
408096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
409096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    } else {
4100a657bbc2c6fc9daf699942e023050536d5ec95fDerek Sollenberger        if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_OES_vertex_array_object")) {
411096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            if (NULL == fBindVertexArray ||
412096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                NULL == fDeleteVertexArrays ||
413096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                NULL == fGenVertexArrays) {
414096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger                return false;
415096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger            }
416096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger        }
417096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger    }
418096defe64d408e54474fe19f418c95bf1a554fc7Derek Sollenberger
41980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru    return true;
42080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}
421