blob: 57de3e03fc05ef6172191ac1660a89b03f8a5503 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
twiz@google.com59a190b2011-03-14 21:23:01 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * 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.
twiz@google.com59a190b2011-03-14 21:23:01 +00007 */
8
9
twiz@google.com59a190b2011-03-14 21:23:01 +000010#include "GrTypes.h"
tomhudson@google.com6bf38b52012-02-14 15:11:59 +000011#include "gl/GrGLInterface.h"
12#include "gl/GrGLDefines.h"
twiz@google.com59a190b2011-03-14 21:23:01 +000013
14#include <stdio.h>
15
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +000016#if GR_GL_PER_GL_FUNC_CALLBACK
17namespace {
18void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
19}
20#endif
21
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000022GrGLBinding 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
bsalomon@google.comc82b8892011-09-22 14:10:33 +000053GrGLVersion GrGLGetVersionFromString(const char* versionString) {
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +000054 if (NULL == versionString) {
55 GrAssert(!"NULL GL version string.");
56 return 0;
57 }
58
bsalomon@google.comc82b8892011-09-22 14:10:33 +000059 int major, minor;
twiz@google.com0f31ca72011-03-18 17:38:11 +000060
bsalomon@google.comc82b8892011-09-22 14:10:33 +000061 int n = sscanf(versionString, "%d.%d", &major, &minor);
twiz@google.com0f31ca72011-03-18 17:38:11 +000062 if (2 == n) {
bsalomon@google.comc82b8892011-09-22 14:10:33 +000063 return GR_GL_VER(major, minor);
twiz@google.com59a190b2011-03-14 21:23:01 +000064 }
twiz@google.com0f31ca72011-03-18 17:38:11 +000065
twiz@google.com59a190b2011-03-14 21:23:01 +000066 char profile[2];
twiz@google.com0f31ca72011-03-18 17:38:11 +000067 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
bsalomon@google.comc82b8892011-09-22 14:10:33 +000068 &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);
twiz@google.com59a190b2011-03-14 21:23:01 +000076 }
twiz@google.com0f31ca72011-03-18 17:38:11 +000077
bsalomon@google.comc82b8892011-09-22 14:10:33 +000078 return 0;
twiz@google.com59a190b2011-03-14 21:23:01 +000079}
80
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +000081GrGLSLVersion 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 }
djsollen@google.com55e713c2012-03-20 15:28:14 +000098
99#ifdef SK_BUILD_FOR_ANDROID
100 // android hack until the gpu vender updates their drivers
101 n = sscanf(versionString, "OpenGL ES GLSL %d.%d", &major, &minor);
102 if (2 == n) {
103 return GR_GLSL_VER(major, minor);
104 }
105#endif
106
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +0000107 return 0;
108}
109
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000110bool GrGLHasExtensionFromString(const char* ext, const char* extensionString) {
twiz@google.com59a190b2011-03-14 21:23:01 +0000111 int extLength = strlen(ext);
112
113 while (true) {
114 int n = strcspn(extensionString, " ");
115 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
116 return true;
117 }
118 if (0 == extensionString[n]) {
119 return false;
120 }
121 extensionString += n+1;
122 }
123
124 return false;
125}
126
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000127bool GrGLHasExtension(const GrGLInterface* gl, const char* ext) {
bsalomon@google.comdca4aab2011-09-06 19:05:24 +0000128 const GrGLubyte* glstr;
129 GR_GL_CALL_RET(gl, glstr, GetString(GR_GL_EXTENSIONS));
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000130 return GrGLHasExtensionFromString(ext, (const char*) glstr);
twiz@google.com59a190b2011-03-14 21:23:01 +0000131}
132
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000133GrGLBinding GrGLGetBindingInUse(const GrGLInterface* gl) {
134 const GrGLubyte* v;
135 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
136 return GrGLGetBindingInUseFromString((const char*) v);
137}
138
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000139GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
bsalomon@google.comdca4aab2011-09-06 19:05:24 +0000140 const GrGLubyte* v;
141 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000142 return GrGLGetVersionFromString((const char*) v);
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +0000143}
144
bsalomon@google.comedfe1aa2011-09-29 14:40:26 +0000145GrGLSLVersion GrGLGetGLSLVersion(const GrGLInterface* gl) {
146 const GrGLubyte* v;
147 GR_GL_CALL_RET(gl, v, GetString(GR_GL_SHADING_LANGUAGE_VERSION));
148 return GrGLGetGLSLVersionFromString((const char*) v);
149}
150
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000151GrGLInterface::GrGLInterface() {
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000152 fBindingsExported = kNone_GrGLBinding;
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000153
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +0000154#if GR_GL_PER_GL_FUNC_CALLBACK
155 fCallback = GrGLDefaultInterfaceCallback;
156 fCallbackData = 0;
157#endif
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000158}
159
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000160bool GrGLInterface::validate(GrGLBinding binding) const {
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000161
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000162 // kNone must be 0 so that the check we're about to do can never succeed if
163 // binding == kNone.
164 GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000165
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000166 if (0 == (binding & fBindingsExported)) {
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000167 return false;
168 }
169
170 // functions that are always required
171 if (NULL == fActiveTexture ||
172 NULL == fAttachShader ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000173 NULL == fBindAttribLocation ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000174 NULL == fBindBuffer ||
175 NULL == fBindTexture ||
176 NULL == fBlendFunc ||
robertphillips@google.come7884302012-04-18 14:39:58 +0000177 NULL == fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension
178 NULL == fBlendEquation || // -> GL >= 1.4, ES >= 2.0 or extension
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000179 NULL == fBufferData ||
180 NULL == fBufferSubData ||
181 NULL == fClear ||
182 NULL == fClearColor ||
183 NULL == fClearStencil ||
184 NULL == fColorMask ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000185 NULL == fCompileShader ||
186 NULL == fCreateProgram ||
187 NULL == fCreateShader ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000188 NULL == fCullFace ||
189 NULL == fDeleteBuffers ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000190 NULL == fDeleteProgram ||
191 NULL == fDeleteShader ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000192 NULL == fDeleteTextures ||
193 NULL == fDepthMask ||
194 NULL == fDisable ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000195 NULL == fDisableVertexAttribArray ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000196 NULL == fDrawArrays ||
197 NULL == fDrawElements ||
198 NULL == fEnable ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000199 NULL == fEnableVertexAttribArray ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000200 NULL == fFrontFace ||
201 NULL == fGenBuffers ||
202 NULL == fGenTextures ||
203 NULL == fGetBufferParameteriv ||
204 NULL == fGetError ||
205 NULL == fGetIntegerv ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000206 NULL == fGetProgramInfoLog ||
207 NULL == fGetProgramiv ||
208 NULL == fGetShaderInfoLog ||
209 NULL == fGetShaderiv ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000210 NULL == fGetString ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000211 NULL == fGetUniformLocation ||
212 NULL == fLinkProgram ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000213 NULL == fPixelStorei ||
214 NULL == fReadPixels ||
215 NULL == fScissor ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000216 NULL == fShaderSource ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000217 NULL == fStencilFunc ||
218 NULL == fStencilMask ||
219 NULL == fStencilOp ||
220 NULL == fTexImage2D ||
221 NULL == fTexParameteri ||
222 NULL == fTexSubImage2D ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000223 NULL == fUniform1f ||
224 NULL == fUniform1i ||
225 NULL == fUniform1fv ||
226 NULL == fUniform1iv ||
227 NULL == fUniform2f ||
228 NULL == fUniform2i ||
229 NULL == fUniform2fv ||
230 NULL == fUniform2iv ||
231 NULL == fUniform3f ||
232 NULL == fUniform3i ||
233 NULL == fUniform3fv ||
234 NULL == fUniform3iv ||
235 NULL == fUniform4f ||
236 NULL == fUniform4i ||
237 NULL == fUniform4fv ||
238 NULL == fUniform4iv ||
239 NULL == fUniformMatrix2fv ||
240 NULL == fUniformMatrix3fv ||
241 NULL == fUniformMatrix4fv ||
242 NULL == fUseProgram ||
243 NULL == fVertexAttrib4fv ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000244 NULL == fVertexAttribPointer ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000245 NULL == fViewport ||
246 NULL == fBindFramebuffer ||
247 NULL == fBindRenderbuffer ||
248 NULL == fCheckFramebufferStatus ||
249 NULL == fDeleteFramebuffers ||
250 NULL == fDeleteRenderbuffers ||
bsalomon@google.com373a6632011-10-19 20:43:20 +0000251 NULL == fFinish ||
252 NULL == fFlush ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000253 NULL == fFramebufferRenderbuffer ||
254 NULL == fFramebufferTexture2D ||
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000255 NULL == fGetFramebufferAttachmentParameteriv ||
256 NULL == fGetRenderbufferParameteriv ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000257 NULL == fGenFramebuffers ||
258 NULL == fGenRenderbuffers ||
259 NULL == fRenderbufferStorage) {
260 return false;
261 }
262
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000263 const char* ext;
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000264 GrGLVersion glVer = GrGLGetVersion(this);
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000265 ext = (const char*)fGetString(GR_GL_EXTENSIONS);
266
267 // Now check that baseline ES/Desktop fns not covered above are present
268 // and that we have fn pointers for any advertised extensions that we will
269 // try to use.
270
271 // these functions are part of ES2, we assume they are available
272 // On the desktop we assume they are available if the extension
273 // is present or GL version is high enough.
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000274 if (kES2_GrGLBinding == binding) {
robertphillips@google.come7884302012-04-18 14:39:58 +0000275 if (NULL == fStencilFuncSeparate ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000276 NULL == fStencilMaskSeparate ||
277 NULL == fStencilOpSeparate) {
278 return false;
279 }
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000280 } else if (kDesktop_GrGLBinding == binding) {
robertphillips@google.come7884302012-04-18 14:39:58 +0000281
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000282 if (glVer >= GR_GL_VER(2,0)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000283 if (NULL == fStencilFuncSeparate ||
284 NULL == fStencilMaskSeparate ||
285 NULL == fStencilOpSeparate) {
286 return false;
287 }
288 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000289 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
bsalomon@google.combc5cf512011-09-21 16:21:07 +0000290 return false;
291 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000292 if (glVer >= GR_GL_VER(2,0) ||
293 GrGLHasExtensionFromString("GL_ARB_draw_buffers", ext)) {
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000294 if (NULL == fDrawBuffers) {
295 return false;
296 }
297 }
robertphillips@google.come7884302012-04-18 14:39:58 +0000298
bsalomon@google.com373a6632011-10-19 20:43:20 +0000299 if (glVer >= GR_GL_VER(1,5) ||
300 GrGLHasExtensionFromString("GL_ARB_occlusion_query", ext)) {
301 if (NULL == fGenQueries ||
302 NULL == fDeleteQueries ||
303 NULL == fBeginQuery ||
304 NULL == fEndQuery ||
305 NULL == fGetQueryiv ||
306 NULL == fGetQueryObjectiv ||
307 NULL == fGetQueryObjectuiv) {
308 return false;
309 }
310 }
311 if (glVer >= GR_GL_VER(3,3) ||
312 GrGLHasExtensionFromString("GL_ARB_timer_query", ext) ||
313 GrGLHasExtensionFromString("GL_EXT_timer_query", ext)) {
314 if (NULL == fGetQueryObjecti64v ||
315 NULL == fGetQueryObjectui64v) {
316 return false;
317 }
318 }
319 if (glVer >= GR_GL_VER(3,3) ||
320 GrGLHasExtensionFromString("GL_ARB_timer_query", ext)) {
321 if (NULL == fQueryCounter) {
322 return false;
323 }
324 }
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000325 }
326
327 // optional function on desktop before 1.3
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000328 if (kDesktop_GrGLBinding != binding ||
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000329 (glVer >= GR_GL_VER(1,3) ||
330 GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000331 if (NULL == fCompressedTexImage2D) {
332 return false;
333 }
334 }
335
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000336 // part of desktop GL, but not ES
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000337 if (kDesktop_GrGLBinding == binding &&
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000338 (NULL == fLineWidth ||
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000339 NULL == fGetTexLevelParameteriv ||
bsalomon@google.comc49d66b2011-08-03 14:22:30 +0000340 NULL == fDrawBuffer ||
341 NULL == fReadBuffer)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000342 return false;
343 }
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000344
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000345 // GL_EXT_texture_storage is part of desktop 4.2
346 // There is a desktop ARB extension and an ES+desktop EXT extension
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000347 if (kDesktop_GrGLBinding == binding) {
bsalomon@google.combaa9ea12012-01-06 19:05:43 +0000348 if (glVer >= GR_GL_VER(4,2) ||
349 GrGLHasExtensionFromString("GL_ARB_texture_storage", ext) ||
350 GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
351 if (NULL == fTexStorage2D) {
352 return false;
353 }
354 }
355 } else if (GrGLHasExtensionFromString("GL_EXT_texture_storage", ext)) {
356 if (NULL == fTexStorage2D) {
357 return false;
358 }
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000359 }
360
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000361 // FBO MSAA
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000362 if (kDesktop_GrGLBinding == binding) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000363 // GL 3.0 and the ARB extension have multisample + blit
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000364 if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000365 if (NULL == fRenderbufferStorageMultisample ||
366 NULL == fBlitFramebuffer) {
367 return false;
368 }
369 } else {
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000370 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_blit", ext) &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000371 NULL == fBlitFramebuffer) {
372 return false;
373 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000374 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", ext) &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000375 NULL == fRenderbufferStorageMultisample) {
376 return false;
377 }
378 }
379 } else {
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000380 if (GrGLHasExtensionFromString("GL_CHROMIUM_framebuffer_multisample", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000381 if (NULL == fRenderbufferStorageMultisample ||
382 NULL == fBlitFramebuffer) {
383 return false;
384 }
385 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000386 if (GrGLHasExtensionFromString("GL_APPLE_framebuffer_multisample", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000387 if (NULL == fRenderbufferStorageMultisample ||
388 NULL == fResolveMultisampleFramebuffer) {
389 return false;
390 }
391 }
392 }
393
394 // On ES buffer mapping is an extension. On Desktop
395 // buffer mapping was part of original VBO extension
396 // which we require.
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000397 if (kDesktop_GrGLBinding == binding ||
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000398 GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000399 if (NULL == fMapBuffer ||
400 NULL == fUnmapBuffer) {
401 return false;
402 }
403 }
404
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000405 // Dual source blending
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000406 if (kDesktop_GrGLBinding == binding &&
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000407 (glVer >= GR_GL_VER(3,3) ||
408 GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000409 if (NULL == fBindFragDataLocationIndexed) {
410 return false;
411 }
412 }
413
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000414 return true;
415}
416