GrGLInterface.cpp revision cee661af926cc977addc6e039b7022975a448ace
159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com/*
259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    Copyright 2011 Google Inc.
359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
459a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    Licensed under the Apache License, Version 2.0 (the "License");
559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    you may not use this file except in compliance with the License.
659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    You may obtain a copy of the License at
759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
859a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com         http://www.apache.org/licenses/LICENSE-2.0
959a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
1059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    Unless required by applicable law or agreed to in writing, software
1159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    distributed under the License is distributed on an "AS IS" BASIS,
1259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    See the License for the specific language governing permissions and
1459a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    limitations under the License.
1559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com */
1659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
1759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
1859a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com#include "GrTypes.h"
19f987d1b2348258970cae675135b6dedda079de48bsalomon@google.com#include "GrGLInterface.h"
20f987d1b2348258970cae675135b6dedda079de48bsalomon@google.com#include "GrGLDefines.h"
2159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
2259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com#include <stdio.h>
2359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
24f987d1b2348258970cae675135b6dedda079de48bsalomon@google.comGrGLInterface* gGLInterface = NULL;
2559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
2659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.comvoid gl_version_from_string(int* major, int* minor,
2759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com                            const char* versionString) {
2859a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    if (NULL == versionString) {
2959a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        GrAssert(0);
3059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        *major = 0;
3159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        *minor = 0;
3259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        return;
3359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    }
340f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com
3559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    int n = sscanf(versionString, "%d.%d", major, minor);
360f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com    if (2 == n) {
370f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com      return;
3859a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    }
390f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com
4059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    char profile[2];
410f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com    n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
420f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com               major, minor);
4359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    bool ok = 4 == n;
4459a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    if (!ok) {
450f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com        n = sscanf(versionString, "OpenGL ES %d.%d", major, minor);
4659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        ok = 2 == n;
4759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    }
480f31ca79bde088e6caac219734c35c1ae3e9e8b9twiz@google.com
4959a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    if (!ok) {
5059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        GrAssert(0);
5159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        *major = 0;
5259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        *minor = 0;
5359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        return;
5459a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    }
5559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com}
5659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
572c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.comfloat gl_version_as_float_from_string(const char* versionString) {
582c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    int major, minor;
592c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    gl_version_from_string(&major, &minor, versionString);
602c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    GrAssert(minor >= 0);
612c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    // AFAIK there are only single digit minor numbers
622c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    if (minor < 10) {
632c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com        return major + minor / 10.f;
642c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    } else if (minor < 100) {
652c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com        return major + minor / 100.f;
662c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    } else if (minor < 1000) {
672c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com        return major + minor / 1000.f;
682c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    } else {
692c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com        GrAssert(!"Why so many digits in minor revision number?");
702c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com        char temp[32];
712c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com        sprintf(temp, "%d.%d", major, minor);
722c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com        return (float) atof(temp);
732c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    }
742c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com}
752c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com
7659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.combool has_gl_extension_from_string(const char* ext,
7759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com                                  const char* extensionString) {
7859a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    int extLength = strlen(ext);
7959a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
8059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    while (true) {
8159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        int n = strcspn(extensionString, " ");
8259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
8359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com            return true;
8459a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        }
8559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        if (0 == extensionString[n]) {
8659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com            return false;
8759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        }
8859a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com        extensionString += n+1;
8959a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    }
9059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
9159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    return false;
9259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com}
9359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
94918261018f7a7754a5e7f0fbb6ec96f9b269fd26bsalomon@google.comGR_API void GrGLSetGLInterface(GrGLInterface* gl_interface) {
9559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    gGLInterface = gl_interface;
9659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com}
9759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
98918261018f7a7754a5e7f0fbb6ec96f9b269fd26bsalomon@google.comGR_API GrGLInterface* GrGLGetGLInterface() {
9959a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    return gGLInterface;
10059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com}
10159a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
10259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.combool has_gl_extension(const char* ext) {
10359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    const char* glstr = reinterpret_cast<const char*>(
104f987d1b2348258970cae675135b6dedda079de48bsalomon@google.com                GrGLGetGLInterface()->fGetString(GR_GL_EXTENSIONS));
10559a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
10659a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    return has_gl_extension_from_string(ext, glstr);
10759a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com}
10859a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com
10959a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.comvoid gl_version(int* major, int* minor) {
11059a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    const char* v = reinterpret_cast<const char*>(
111f987d1b2348258970cae675135b6dedda079de48bsalomon@google.com                GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
11259a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com    gl_version_from_string(major, minor, v);
11359a190bcab5d4b2bf03f8f10cb6a581d19fed403twiz@google.com}
114bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
1152c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.comfloat gl_version_as_float() {
1162c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    const char* v = reinterpret_cast<const char*>(
1172c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com                GrGLGetGLInterface()->fGetString(GR_GL_VERSION));
1182c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com    return gl_version_as_float_from_string(v);
1192c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com}
1202c17fcdc45f9fa9a2dc785786347040fbe30928bbsalomon@google.com
121bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.combool GrGLInterface::validateShaderFunctions() const {
122bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // required for GrGpuGLShaders
123bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (NULL == fAttachShader ||
124bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBindAttribLocation ||
125bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fCompileShader ||
126bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fCreateProgram ||
127bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fCreateShader ||
128bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDeleteProgram ||
129bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDeleteShader ||
130bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDisableVertexAttribArray ||
131bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fEnableVertexAttribArray ||
132bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetProgramInfoLog ||
133bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetProgramiv ||
134bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetShaderInfoLog ||
135bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetShaderiv ||
136bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetUniformLocation ||
137bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fLinkProgram ||
138bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fShaderSource ||
139bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform1f ||
140bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform1i ||
141bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform1fv ||
142bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform1iv ||
143bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform2f ||
144bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform2i ||
145bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform2fv ||
146bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform2iv ||
147bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform3f ||
148bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform3i ||
149bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform3fv ||
150bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform3iv ||
151bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform4f ||
152bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform4i ||
153bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform4fv ||
154bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniform4iv ||
155bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniformMatrix2fv ||
156bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniformMatrix3fv ||
157bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUniformMatrix4fv ||
158bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fUseProgram ||
159bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fVertexAttrib4fv ||
160bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fVertexAttribPointer) {
161bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        return false;
162bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
163bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    return true;
164bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com}
165bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
166bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.combool GrGLInterface::validateFixedFunctions() const {
167bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (NULL == fClientActiveTexture ||
168bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fColor4ub ||
169bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fColorPointer ||
170bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDisableClientState ||
171bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fEnableClientState ||
172bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fLoadMatrixf ||
173bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fMatrixMode ||
174bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fPointSize ||
175bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fShadeModel ||
176bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fTexCoordPointer ||
1774b9b6a20d4bc3147c7ab8b755264f3ddda0e0e04bsalomon@google.com        NULL == fTexEnvi ||
178bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fVertexPointer) {
179bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        return false;
180bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
181bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    return true;
182bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com}
183bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
184bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.combool GrGLInterface::validate(GrEngine engine) const {
185bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
186bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    bool isDesktop = kDesktop_GrGLBinding == fBindingsExported;
187bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
188bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // ES1 and 2 can be supported in the same interface
189bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    bool isES = ((kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported &&
190bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                 !(~(kES1_GrGLBinding | kES2_GrGLBinding) & fBindingsExported));
191bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
192bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (!isDesktop && !isES) {
193bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        return false;
194bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
195bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
196bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // functions that are always required
197bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (NULL == fActiveTexture ||
198bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBindBuffer ||
199bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBindTexture ||
200bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBlendFunc ||
201bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBufferData ||
202bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBufferSubData ||
203bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fClear ||
204bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fClearColor ||
205bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fClearStencil ||
206bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fColorMask ||
207bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fCullFace ||
208bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDeleteBuffers ||
209bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDeleteTextures ||
210bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDepthMask ||
211bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDisable ||
212bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDrawArrays ||
213bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDrawElements ||
214bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fEnable ||
215bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fFrontFace ||
216bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGenBuffers ||
217bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGenTextures ||
218bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetBufferParameteriv ||
219bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetError ||
220bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetIntegerv ||
221bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGetString ||
222bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fPixelStorei ||
223bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fReadPixels ||
224bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fScissor ||
225bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fStencilFunc ||
226bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fStencilMask ||
227bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fStencilOp ||
228bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fTexImage2D ||
229bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fTexParameteri ||
230bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fTexSubImage2D ||
231bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fViewport ||
232bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBindFramebuffer ||
233bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fBindRenderbuffer ||
234bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fCheckFramebufferStatus ||
235bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDeleteFramebuffers ||
236bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fDeleteRenderbuffers ||
237bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fFramebufferRenderbuffer ||
238bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fFramebufferTexture2D ||
239cee661af926cc977addc6e039b7022975a448acebsalomon@google.com        NULL == fGetFramebufferAttachmentParameteriv ||
240cee661af926cc977addc6e039b7022975a448acebsalomon@google.com        NULL == fGetRenderbufferParameteriv ||
241bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGenFramebuffers ||
242bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fGenRenderbuffers ||
243bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        NULL == fRenderbufferStorage) {
244bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        return false;
245bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
246bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
247bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    switch (engine) {
248bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        case kOpenGL_Shaders_GrEngine:
249bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (kES1_GrGLBinding == fBindingsExported) {
250bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
251bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
252bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (!this->validateShaderFunctions()) {
253bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
254bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
255bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            break;
256bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        case kOpenGL_Fixed_GrEngine:
257bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (kES1_GrGLBinding == fBindingsExported) {
258bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
259bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
260bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (!this->validateFixedFunctions()) {
261bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
262bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
263bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            break;
264bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        default:
265bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            return false;
266bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
267bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
268bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    int major, minor;
269bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    const char* ext;
270bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
271bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    gl_version(&major, &minor);
272bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    ext = (const char*)fGetString(GR_GL_EXTENSIONS);
273bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
274bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // Now check that baseline ES/Desktop fns not covered above are present
275bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // and that we have fn pointers for any advertised extensions that we will
276bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // try to use.
277bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
278bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // these functions are part of ES2, we assume they are available
279bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // On the desktop we assume they are available if the extension
280bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // is present or GL version is high enough.
281bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if ((kES2_GrGLBinding & fBindingsExported)) {
282bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if (NULL == fBlendColor ||
283bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            NULL == fStencilFuncSeparate ||
284bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            NULL == fStencilMaskSeparate ||
285bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            NULL == fStencilOpSeparate) {
286bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            return false;
287bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
288bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    } else if (kDesktop_GrGLBinding == fBindingsExported) {
289bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if (major >= 2) {
290bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (NULL == fStencilFuncSeparate ||
291bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                NULL == fStencilMaskSeparate ||
292bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                NULL == fStencilOpSeparate) {
293bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
294bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
295bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
296bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if (1 < major || (1 == major && 4 <= minor) ||
297bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            has_gl_extension_from_string("GL_EXT_blend_color", ext)) {
298bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (NULL == fBlendColor) {
299bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
300bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
301bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
302bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
303bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
304bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // optional function on desktop before 1.3
305bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (kDesktop_GrGLBinding != fBindingsExported ||
306bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        (1 < major || (1 == major && 3 <= minor)) ||
307bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        has_gl_extension_from_string("GL_ARB_texture_compression", ext)) {
308bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if (NULL == fCompressedTexImage2D) {
309bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            return false;
310bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
311bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
312bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
313bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // part of desktop GL
314bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (kDesktop_GrGLBinding == fBindingsExported &&
315cee661af926cc977addc6e039b7022975a448acebsalomon@google.com        (NULL == fLineWidth ||
316cee661af926cc977addc6e039b7022975a448acebsalomon@google.com         NULL == fGetTexLevelParameteriv)) {
317bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        return false;
318bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
319cee661af926cc977addc6e039b7022975a448acebsalomon@google.com
320bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // FBO MSAA
321bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (kDesktop_GrGLBinding == fBindingsExported) {
322bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        // GL 3.0 and the ARB extension have multisample + blit
323bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if ((major >= 3) || has_gl_extension_from_string("GL_ARB_framebuffer_object", ext)) {
324bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (NULL == fRenderbufferStorageMultisample ||
325bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                NULL == fBlitFramebuffer) {
326bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
327bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
328bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        } else {
329bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (has_gl_extension_from_string("GL_EXT_framebuffer_blit", ext) &&
330bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                NULL == fBlitFramebuffer) {
331bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
332bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
333bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (has_gl_extension_from_string("GL_EXT_framebuffer_multisample", ext) &&
334bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                NULL == fRenderbufferStorageMultisample) {
335bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
336bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
337bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
338bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    } else {
339bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if (has_gl_extension_from_string("GL_CHROMIUM_framebuffer_multisample", ext)) {
340bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (NULL == fRenderbufferStorageMultisample ||
341bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                NULL == fBlitFramebuffer) {
342bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
343bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
344bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
345bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if (has_gl_extension_from_string("GL_APPLE_framebuffer_multisample", ext)) {
346bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            if (NULL == fRenderbufferStorageMultisample ||
347bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                NULL == fResolveMultisampleFramebuffer) {
348bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com                return false;
349bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            }
350bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
351bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
352bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
353bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // On ES buffer mapping is an extension. On Desktop
354bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // buffer mapping was part of original VBO extension
355bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    // which we require.
356bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    if (kDesktop_GrGLBinding == fBindingsExported  ||
357bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        has_gl_extension_from_string("GL_OES_mapbuffer", ext)) {
358bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        if (NULL == fMapBuffer ||
359bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            NULL == fUnmapBuffer) {
360bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com            return false;
361bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com        }
362bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    }
363bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
364271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com    // Dual source blending
365271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com    if (kDesktop_GrGLBinding == fBindingsExported  &&
366271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com        (has_gl_extension_from_string("GL_ARB_blend_func_extended", ext) ||
367271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com         (3 < major) || (3 == major && 3 <= minor))) {
368271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com        if (NULL == fBindFragDataLocationIndexed) {
369271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com            return false;
370271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com        }
371271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com    }
372271cffc77bd2fcb3458559e509634442517ca1e9bsalomon@google.com
373bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com    return true;
374bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com}
375bf2a46941e8fdebfcd24ea8f7184779021898225bsalomon@google.com
376