• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright 2011 Google Inc.
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 
10 #include "GrTypes.h"
11 #include "gl/GrGLInterface.h"
12 #include "gl/GrGLDefines.h"
13 
14 #include <stdio.h>
15 
16 #if GR_GL_PER_GL_FUNC_CALLBACK
17 namespace {
GrGLDefaultInterfaceCallback(const GrGLInterface *)18 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
19 }
20 #endif
21 
GrGLGetBindingInUseFromString(const char * versionString)22 GrGLBinding GrGLGetBindingInUseFromString(const char* versionString) {
23     if (NULL == versionString) {
24         GrAssert(!"NULL GL version string.");
25         return kNone_GrGLBinding;
26     }
27 
28     int major, minor;
29 
30     // check for desktop
31     int n = sscanf(versionString, "%d.%d", &major, &minor);
32     if (2 == n) {
33         return kDesktop_GrGLBinding;
34     }
35 
36     // check for ES 1
37     char profile[2];
38     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
39                &major, &minor);
40     if (4 == n) {
41         // we no longer support ES1.
42         return kNone_GrGLBinding;
43     }
44 
45     // check for ES2
46     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
47     if (2 == n) {
48         return kES2_GrGLBinding;
49     }
50     return kNone_GrGLBinding;
51 }
52 
GrGLGetVersionFromString(const char * versionString)53 GrGLVersion GrGLGetVersionFromString(const char* versionString) {
54     if (NULL == versionString) {
55         GrAssert(!"NULL GL version string.");
56         return 0;
57     }
58 
59     int major, minor;
60 
61     int n = sscanf(versionString, "%d.%d", &major, &minor);
62     if (2 == n) {
63         return GR_GL_VER(major, minor);
64     }
65 
66     char profile[2];
67     n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
68                &major, &minor);
69     if (4 == n) {
70         return GR_GL_VER(major, minor);
71     }
72 
73     n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
74     if (2 == n) {
75         return GR_GL_VER(major, minor);
76     }
77 
78     return 0;
79 }
80 
GrGLGetGLSLVersionFromString(const char * versionString)81 GrGLSLVersion GrGLGetGLSLVersionFromString(const char* versionString) {
82     if (NULL == versionString) {
83         GrAssert(!"NULL GLSL version string.");
84         return 0;
85     }
86 
87     int major, minor;
88 
89     int n = sscanf(versionString, "%d.%d", &major, &minor);
90     if (2 == n) {
91         return GR_GLSL_VER(major, minor);
92     }
93 
94     n = sscanf(versionString, "OpenGL ES GLSL ES %d.%d", &major, &minor);
95     if (2 == n) {
96         return GR_GLSL_VER(major, minor);
97     }
98 
99     // android hack
100     n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
101     if (2 == n) {
102         return GR_GLSL_VER(major, minor);
103     }
104 
105     return 0;
106 }
107 
GrGLHasExtensionFromString(const char * ext,const char * extensionString)108 bool GrGLHasExtensionFromString(const char* ext, const char* extensionString) {
109     int extLength = strlen(ext);
110 
111     while (true) {
112         int n = strcspn(extensionString, " ");
113         if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
114             return true;
115         }
116         if (0 == extensionString[n]) {
117             return false;
118         }
119         extensionString += n+1;
120     }
121 
122     return false;
123 }
124 
GrGLHasExtension(const GrGLInterface * gl,const char * ext)125 bool GrGLHasExtension(const GrGLInterface* gl, const char* ext) {
126     const GrGLubyte* glstr;
127     GR_GL_CALL_RET(gl, glstr, GetString(GR_GL_EXTENSIONS));
128     return GrGLHasExtensionFromString(ext, (const char*) glstr);
129 }
130 
GrGLGetBindingInUse(const GrGLInterface * gl)131 GrGLBinding GrGLGetBindingInUse(const GrGLInterface* gl) {
132     const GrGLubyte* v;
133     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
134     return GrGLGetBindingInUseFromString((const char*) v);
135 }
136 
GrGLGetVersion(const GrGLInterface * gl)137 GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
138     const GrGLubyte* v;
139     GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
140     return GrGLGetVersionFromString((const char*) v);
141 }
142 
GrGLGetGLSLVersion(const GrGLInterface * gl)143 GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
144     const GrGLubyte* v;
145     GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
146     return GrGLGetGLSLVersionFromString((const char*) v);
147 }
148 
GrGLInterface()149 GrGLInterface::GrGLInterface() {
150     fBindingsExported = kNone_GrGLBinding;
151 
152     fActiveTexture = NULL;
153     fAttachShader = NULL;
154     fBeginQuery = NULL;
155     fBindAttribLocation = NULL;
156     fBindBuffer = NULL;
157     fBindFragDataLocation = NULL;
158     fBindTexture = NULL;
159     fBlendColor = NULL;
160     fBlendFunc = NULL;
161     fBufferData = NULL;
162     fBufferSubData = NULL;
163     fClear = NULL;
164     fClearColor = NULL;
165     fClearStencil = NULL;
166     fColorMask = NULL;
167     fColorPointer = NULL;
168     fCompileShader = NULL;
169     fCompressedTexImage2D = NULL;
170     fCreateProgram = NULL;
171     fCreateShader = NULL;
172     fCullFace = NULL;
173     fDeleteBuffers = NULL;
174     fDeleteProgram = NULL;
175     fDeleteQueries = NULL;
176     fDeleteShader = NULL;
177     fDeleteTextures = NULL;
178     fDepthMask = NULL;
179     fDisable = NULL;
180     fDisableVertexAttribArray = NULL;
181     fDrawArrays = NULL;
182     fDrawBuffer = NULL;
183     fDrawBuffers = NULL;
184     fDrawElements = NULL;
185     fEndQuery = NULL;
186     fFinish = NULL;
187     fFlush = NULL;
188     fEnable = NULL;
189     fEnableVertexAttribArray = NULL;
190     fFrontFace = NULL;
191     fGenBuffers = NULL;
192     fGenQueries = NULL;
193     fGenTextures = NULL;
194     fGetBufferParameteriv = NULL;
195     fGetError = NULL;
196     fGetIntegerv = NULL;
197     fGetQueryiv = NULL;
198     fGetQueryObjecti64v = NULL;
199     fGetQueryObjectiv = NULL;
200     fGetQueryObjectui64v = NULL;
201     fGetQueryObjectuiv = NULL;
202     fGetProgramInfoLog = NULL;
203     fGetProgramiv = NULL;
204     fGetShaderInfoLog = NULL;
205     fGetShaderiv = NULL;
206     fGetString = NULL;
207     fGetTexLevelParameteriv = NULL;
208     fGetUniformLocation = NULL;
209     fLineWidth = NULL;
210     fLinkProgram = NULL;
211     fPixelStorei = NULL;
212     fQueryCounter = NULL;
213     fReadBuffer = NULL;
214     fReadPixels = NULL;
215     fScissor = NULL;
216     fShaderSource = NULL;
217     fStencilFunc = NULL;
218     fStencilFuncSeparate = NULL;
219     fStencilMask = NULL;
220     fStencilMaskSeparate = NULL;
221     fStencilOp = NULL;
222     fStencilOpSeparate = NULL;
223     fTexImage2D = NULL;
224     fTexParameteri = NULL;
225     fTexStorage2D = NULL;
226     fTexSubImage2D = NULL;
227     fUniform1f = NULL;
228     fUniform1i = NULL;
229     fUniform1fv = NULL;
230     fUniform1iv = NULL;
231     fUniform2f = NULL;
232     fUniform2i = NULL;
233     fUniform2fv = NULL;
234     fUniform2iv = NULL;
235     fUniform3f = NULL;
236     fUniform3i = NULL;
237     fUniform3fv = NULL;
238     fUniform3iv = NULL;
239     fUniform4f = NULL;
240     fUniform4i = NULL;
241     fUniform4fv = NULL;
242     fUniform4iv = NULL;
243     fUniformMatrix2fv = NULL;
244     fUniformMatrix3fv = NULL;
245     fUniformMatrix4fv = NULL;
246     fUseProgram = NULL;
247     fVertexAttrib4fv = NULL;
248     fVertexAttribPointer = NULL;
249     fViewport = NULL;
250     fBindFramebuffer = NULL;
251     fBindRenderbuffer = NULL;
252     fCheckFramebufferStatus = NULL;
253     fDeleteFramebuffers = NULL;
254     fDeleteRenderbuffers = NULL;
255     fFramebufferRenderbuffer = NULL;
256     fFramebufferTexture2D = NULL;
257     fGenFramebuffers = NULL;
258     fGenRenderbuffers = NULL;
259     fGetFramebufferAttachmentParameteriv = NULL;
260     fGetRenderbufferParameteriv = NULL;
261     fRenderbufferStorage = NULL;
262     fRenderbufferStorageMultisample = NULL;
263     fBlitFramebuffer = NULL;
264     fResolveMultisampleFramebuffer = NULL;
265     fMapBuffer = NULL;
266     fUnmapBuffer = NULL;
267     fBindFragDataLocationIndexed = NULL;
268 
269 #if GR_GL_PER_GL_FUNC_CALLBACK
270     fCallback = GrGLDefaultInterfaceCallback;
271     fCallbackData = 0;
272 #endif
273 }
274 
validate(GrGLBinding binding) const275 bool GrGLInterface::validate(GrGLBinding binding) const {
276 
277     // kNone must be 0 so that the check we're about to do can never succeed if
278     // binding == kNone.
279     GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
280 
281     if (0 == (binding & fBindingsExported)) {
282         return false;
283     }
284 
285     // functions that are always required
286     if (NULL == fActiveTexture ||
287         NULL == fAttachShader ||
288         NULL == fBindAttribLocation ||
289         NULL == fBindBuffer ||
290         NULL == fBindTexture ||
291         NULL == fBlendFunc ||
292         NULL == fBufferData ||
293         NULL == fBufferSubData ||
294         NULL == fClear ||
295         NULL == fClearColor ||
296         NULL == fClearStencil ||
297         NULL == fColorMask ||
298         NULL == fCompileShader ||
299         NULL == fCreateProgram ||
300         NULL == fCreateShader ||
301         NULL == fCullFace ||
302         NULL == fDeleteBuffers ||
303         NULL == fDeleteProgram ||
304         NULL == fDeleteShader ||
305         NULL == fDeleteTextures ||
306         NULL == fDepthMask ||
307         NULL == fDisable ||
308         NULL == fDisableVertexAttribArray ||
309         NULL == fDrawArrays ||
310         NULL == fDrawElements ||
311         NULL == fEnable ||
312         NULL == fEnableVertexAttribArray ||
313         NULL == fFrontFace ||
314         NULL == fGenBuffers ||
315         NULL == fGenTextures ||
316         NULL == fGetBufferParameteriv ||
317         NULL == fGetError ||
318         NULL == fGetIntegerv ||
319         NULL == fGetProgramInfoLog ||
320         NULL == fGetProgramiv ||
321         NULL == fGetShaderInfoLog ||
322         NULL == fGetShaderiv ||
323         NULL == fGetString ||
324         NULL == fGetUniformLocation ||
325         NULL == fLinkProgram ||
326         NULL == fPixelStorei ||
327         NULL == fReadPixels ||
328         NULL == fScissor ||
329         NULL == fShaderSource ||
330         NULL == fStencilFunc ||
331         NULL == fStencilMask ||
332         NULL == fStencilOp ||
333         NULL == fTexImage2D ||
334         NULL == fTexParameteri ||
335         NULL == fTexSubImage2D ||
336         NULL == fUniform1f ||
337         NULL == fUniform1i ||
338         NULL == fUniform1fv ||
339         NULL == fUniform1iv ||
340         NULL == fUniform2f ||
341         NULL == fUniform2i ||
342         NULL == fUniform2fv ||
343         NULL == fUniform2iv ||
344         NULL == fUniform3f ||
345         NULL == fUniform3i ||
346         NULL == fUniform3fv ||
347         NULL == fUniform3iv ||
348         NULL == fUniform4f ||
349         NULL == fUniform4i ||
350         NULL == fUniform4fv ||
351         NULL == fUniform4iv ||
352         NULL == fUniformMatrix2fv ||
353         NULL == fUniformMatrix3fv ||
354         NULL == fUniformMatrix4fv ||
355         NULL == fUseProgram ||
356         NULL == fVertexAttrib4fv ||
357         NULL == fVertexAttribPointer ||
358         NULL == fViewport ||
359         NULL == fBindFramebuffer ||
360         NULL == fBindRenderbuffer ||
361         NULL == fCheckFramebufferStatus ||
362         NULL == fDeleteFramebuffers ||
363         NULL == fDeleteRenderbuffers ||
364         NULL == fFinish ||
365         NULL == fFlush ||
366         NULL == fFramebufferRenderbuffer ||
367         NULL == fFramebufferTexture2D ||
368         NULL == fGetFramebufferAttachmentParameteriv ||
369         NULL == fGetRenderbufferParameteriv ||
370         NULL == fGenFramebuffers ||
371         NULL == fGenRenderbuffers ||
372         NULL == fRenderbufferStorage) {
373         return false;
374     }
375 
376     const char* ext;
377     GrGLVersion glVer = GrGLGetVersion(this);
378     ext = (const char*)fGetString(GR_GL_EXTENSIONS);
379 
380     // Now check that baseline ES/Desktop fns not covered above are present
381     // and that we have fn pointers for any advertised extensions that we will
382     // try to use.
383 
384     // these functions are part of ES2, we assume they are available
385     // On the desktop we assume they are available if the extension
386     // is present or GL version is high enough.
387     if (kES2_GrGLBinding == binding) {
388         if (NULL == fBlendColor ||
389             NULL == fStencilFuncSeparate ||
390             NULL == fStencilMaskSeparate ||
391             NULL == fStencilOpSeparate) {
392             return false;
393         }
394     } else if (kDesktop_GrGLBinding == binding) {
395         if (glVer >= GR_GL_VER(2,0)) {
396             if (NULL == fStencilFuncSeparate ||
397                 NULL == fStencilMaskSeparate ||
398                 NULL == fStencilOpSeparate) {
399                 return false;
400             }
401         }
402         if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
403             return false;
404         }
405         if (glVer >= GR_GL_VER(2,0) ||
406             GrGLHasExtensionFromString("GL_ARB_draw_buffers", ext)) {
407             if (NULL == fDrawBuffers) {
408                 return false;
409             }
410         }
411         if (glVer >= GR_GL_VER(1,4) ||
412             GrGLHasExtensionFromString("GL_EXT_blend_color", ext)) {
413             if (NULL == fBlendColor) {
414                 return false;
415             }
416         }
417         if (glVer >= GR_GL_VER(1,5) ||
418             GrGLHasExtensionFromString("GL_ARB_occlusion_query", ext)) {
419             if (NULL == fGenQueries ||
420                 NULL == fDeleteQueries ||
421                 NULL == fBeginQuery ||
422                 NULL == fEndQuery ||
423                 NULL == fGetQueryiv ||
424                 NULL == fGetQueryObjectiv ||
425                 NULL == fGetQueryObjectuiv) {
426                 return false;
427             }
428         }
429         if (glVer >= GR_GL_VER(3,3) ||
430             GrGLHasExtensionFromString("GL_ARB_timer_query", ext) ||
431             GrGLHasExtensionFromString("GL_EXT_timer_query", ext)) {
432             if (NULL == fGetQueryObjecti64v ||
433                 NULL == fGetQueryObjectui64v) {
434                 return false;
435             }
436         }
437         if (glVer >= GR_GL_VER(3,3) ||
438             GrGLHasExtensionFromString("GL_ARB_timer_query", ext)) {
439             if (NULL == fQueryCounter) {
440                 return false;
441             }
442         }
443     }
444 
445     // optional function on desktop before 1.3
446     if (kDesktop_GrGLBinding != binding ||
447         (glVer >= GR_GL_VER(1,3) ||
448         GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) {
449         if (NULL == fCompressedTexImage2D) {
450             return false;
451         }
452     }
453 
454     // part of desktop GL, but not ES
455     if (kDesktop_GrGLBinding == binding &&
456         (NULL == fLineWidth ||
457          NULL == fGetTexLevelParameteriv ||
458          NULL == fDrawBuffer ||
459          NULL == fReadBuffer)) {
460         return false;
461     }
462 
463     // GL_EXT_texture_storage is part of desktop 4.2
464     // There is a desktop ARB extension and an ES+desktop EXT extension
465     if (kDesktop_GrGLBinding == binding) {
466         if (glVer >= GR_GL_VER(4,2) ||
467             GrGLHasExtensionFromString("GL_ARB_texture_storage", ext) ||
468             GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
469             if (NULL == fTexStorage2D) {
470                 return false;
471             }
472         }
473     } else if (GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
474         if (NULL == fTexStorage2D) {
475             return false;
476         }
477     }
478 
479     // FBO MSAA
480     if (kDesktop_GrGLBinding == binding) {
481         // GL 3.0 and the ARB extension have multisample + blit
482         if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", ext)) {
483             if (NULL == fRenderbufferStorageMultisample ||
484                 NULL == fBlitFramebuffer) {
485                 return false;
486             }
487         } else {
488             if (GrGLHasExtensionFromString("GL_EXT_framebuffer_blit", ext) &&
489                 NULL == fBlitFramebuffer) {
490                 return false;
491             }
492             if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", ext) &&
493                 NULL == fRenderbufferStorageMultisample) {
494                 return false;
495             }
496         }
497     } else {
498         if (GrGLHasExtensionFromString("GL_CHROMIUM_framebuffer_multisample", ext)) {
499             if (NULL == fRenderbufferStorageMultisample ||
500                 NULL == fBlitFramebuffer) {
501                 return false;
502             }
503         }
504         if (GrGLHasExtensionFromString("GL_APPLE_framebuffer_multisample", ext)) {
505             if (NULL == fRenderbufferStorageMultisample ||
506                 NULL == fResolveMultisampleFramebuffer) {
507                 return false;
508             }
509         }
510     }
511 
512     // On ES buffer mapping is an extension. On Desktop
513     // buffer mapping was part of original VBO extension
514     // which we require.
515     if (kDesktop_GrGLBinding == binding ||
516         GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) {
517         if (NULL == fMapBuffer ||
518             NULL == fUnmapBuffer) {
519             return false;
520         }
521     }
522 
523     // Dual source blending
524     if (kDesktop_GrGLBinding == binding &&
525         (glVer >= GR_GL_VER(3,3) ||
526          GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) {
527         if (NULL == fBindFragDataLocationIndexed) {
528             return false;
529         }
530     }
531 
532     return true;
533 }
534 
535