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