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