blob: 0b433d16f97e513cdfed90c8d547d73154fe6c6d [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"
bsalomon@google.comf987d1b2011-04-04 17:13:52 +000011#include "GrGLInterface.h"
12#include "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.comc82b8892011-09-22 14:10:33 +000022GrGLVersion GrGLGetVersionFromString(const char* versionString) {
23 GrAssert(versionString);
24 int major, minor;
twiz@google.com0f31ca72011-03-18 17:38:11 +000025
bsalomon@google.comc82b8892011-09-22 14:10:33 +000026 int n = sscanf(versionString, "%d.%d", &major, &minor);
twiz@google.com0f31ca72011-03-18 17:38:11 +000027 if (2 == n) {
bsalomon@google.comc82b8892011-09-22 14:10:33 +000028 return GR_GL_VER(major, minor);
twiz@google.com59a190b2011-03-14 21:23:01 +000029 }
twiz@google.com0f31ca72011-03-18 17:38:11 +000030
twiz@google.com59a190b2011-03-14 21:23:01 +000031 char profile[2];
twiz@google.com0f31ca72011-03-18 17:38:11 +000032 n = sscanf(versionString, "OpenGL ES-%c%c %d.%d", profile, profile+1,
bsalomon@google.comc82b8892011-09-22 14:10:33 +000033 &major, &minor);
34 if (4 == n) {
35 return GR_GL_VER(major, minor);
36 }
37
38 n = sscanf(versionString, "OpenGL ES %d.%d", &major, &minor);
39 if (2 == n) {
40 return GR_GL_VER(major, minor);
twiz@google.com59a190b2011-03-14 21:23:01 +000041 }
twiz@google.com0f31ca72011-03-18 17:38:11 +000042
bsalomon@google.comc82b8892011-09-22 14:10:33 +000043 return 0;
twiz@google.com59a190b2011-03-14 21:23:01 +000044}
45
bsalomon@google.comc82b8892011-09-22 14:10:33 +000046bool GrGLHasExtensionFromString(const char* ext, const char* extensionString) {
twiz@google.com59a190b2011-03-14 21:23:01 +000047 int extLength = strlen(ext);
48
49 while (true) {
50 int n = strcspn(extensionString, " ");
51 if (n == extLength && 0 == strncmp(ext, extensionString, n)) {
52 return true;
53 }
54 if (0 == extensionString[n]) {
55 return false;
56 }
57 extensionString += n+1;
58 }
59
60 return false;
61}
62
bsalomon@google.comc82b8892011-09-22 14:10:33 +000063bool GrGLHasExtension(const GrGLInterface* gl, const char* ext) {
bsalomon@google.comdca4aab2011-09-06 19:05:24 +000064 const GrGLubyte* glstr;
65 GR_GL_CALL_RET(gl, glstr, GetString(GR_GL_EXTENSIONS));
bsalomon@google.comc82b8892011-09-22 14:10:33 +000066 return GrGLHasExtensionFromString(ext, (const char*) glstr);
twiz@google.com59a190b2011-03-14 21:23:01 +000067}
68
bsalomon@google.comc82b8892011-09-22 14:10:33 +000069GrGLVersion GrGLGetVersion(const GrGLInterface* gl) {
bsalomon@google.comdca4aab2011-09-06 19:05:24 +000070 const GrGLubyte* v;
71 GR_GL_CALL_RET(gl, v, GetString(GR_GL_VERSION));
bsalomon@google.comc82b8892011-09-22 14:10:33 +000072 return GrGLGetVersionFromString((const char*) v);
bsalomon@google.com2c17fcd2011-07-06 17:47:02 +000073}
74
bsalomon@google.com0b77d682011-08-19 13:28:54 +000075GrGLInterface::GrGLInterface() {
76 fBindingsExported = (GrGLBinding)0;
77 fNPOTRenderTargetSupport = kProbe_GrGLCapability;
78 fMinRenderTargetHeight = kProbe_GrGLCapability;
79 fMinRenderTargetWidth = kProbe_GrGLCapability;
80
81 fActiveTexture = NULL;
82 fAttachShader = NULL;
83 fBindAttribLocation = NULL;
84 fBindBuffer = NULL;
bsalomon@google.combc5cf512011-09-21 16:21:07 +000085 fBindFragDataLocation = NULL;
bsalomon@google.com0b77d682011-08-19 13:28:54 +000086 fBindTexture = NULL;
87 fBlendColor = NULL;
88 fBlendFunc = NULL;
89 fBufferData = NULL;
90 fBufferSubData = NULL;
91 fClear = NULL;
92 fClearColor = NULL;
93 fClearStencil = NULL;
94 fClientActiveTexture = NULL;
95 fColor4ub = NULL;
96 fColorMask = NULL;
97 fColorPointer = NULL;
98 fCompileShader = NULL;
99 fCompressedTexImage2D = NULL;
100 fCreateProgram = NULL;
101 fCreateShader = NULL;
102 fCullFace = NULL;
103 fDeleteBuffers = NULL;
104 fDeleteProgram = NULL;
105 fDeleteShader = NULL;
106 fDeleteTextures = NULL;
107 fDepthMask = NULL;
108 fDisable = NULL;
109 fDisableClientState = NULL;
110 fDisableVertexAttribArray = NULL;
111 fDrawArrays = NULL;
112 fDrawBuffer = NULL;
113 fDrawBuffers = NULL;
114 fDrawElements = NULL;
115 fEnable = NULL;
116 fEnableClientState = NULL;
117 fEnableVertexAttribArray = NULL;
118 fFrontFace = NULL;
119 fGenBuffers = NULL;
120 fGenTextures = NULL;
121 fGetBufferParameteriv = NULL;
122 fGetError = NULL;
123 fGetIntegerv = NULL;
124 fGetProgramInfoLog = NULL;
125 fGetProgramiv = NULL;
126 fGetShaderInfoLog = NULL;
127 fGetShaderiv = NULL;
128 fGetString = NULL;
129 fGetTexLevelParameteriv = NULL;
130 fGetUniformLocation = NULL;
131 fLineWidth = NULL;
132 fLinkProgram = NULL;
133 fLoadMatrixf = NULL;
134 fMatrixMode = NULL;
135 fPixelStorei = NULL;
136 fPointSize = NULL;
137 fReadBuffer = NULL;
138 fReadPixels = NULL;
139 fScissor = NULL;
140 fShadeModel = NULL;
141 fShaderSource = NULL;
142 fStencilFunc = NULL;
143 fStencilFuncSeparate = NULL;
144 fStencilMask = NULL;
145 fStencilMaskSeparate = NULL;
146 fStencilOp = NULL;
147 fStencilOpSeparate = NULL;
148 fTexCoordPointer = NULL;
149 fTexEnvi = NULL;
150 fTexImage2D = NULL;
151 fTexParameteri = NULL;
152 fTexSubImage2D = NULL;
153 fUniform1f = NULL;
154 fUniform1i = NULL;
155 fUniform1fv = NULL;
156 fUniform1iv = NULL;
157 fUniform2f = NULL;
158 fUniform2i = NULL;
159 fUniform2fv = NULL;
160 fUniform2iv = NULL;
161 fUniform3f = NULL;
162 fUniform3i = NULL;
163 fUniform3fv = NULL;
164 fUniform3iv = NULL;
165 fUniform4f = NULL;
166 fUniform4i = NULL;
167 fUniform4fv = NULL;
168 fUniform4iv = NULL;
169 fUniformMatrix2fv = NULL;
170 fUniformMatrix3fv = NULL;
171 fUniformMatrix4fv = NULL;
172 fUseProgram = NULL;
173 fVertexAttrib4fv = NULL;
174 fVertexAttribPointer = NULL;
175 fVertexPointer = NULL;
176 fViewport = NULL;
177 fBindFramebuffer = NULL;
178 fBindRenderbuffer = NULL;
179 fCheckFramebufferStatus = NULL;
180 fDeleteFramebuffers = NULL;
181 fDeleteRenderbuffers = NULL;
182 fFramebufferRenderbuffer = NULL;
183 fFramebufferTexture2D = NULL;
184 fGenFramebuffers = NULL;
185 fGenRenderbuffers = NULL;
186 fGetFramebufferAttachmentParameteriv = NULL;
187 fGetRenderbufferParameteriv = NULL;
188 fRenderbufferStorage = NULL;
189 fRenderbufferStorageMultisample = NULL;
190 fBlitFramebuffer = NULL;
191 fResolveMultisampleFramebuffer = NULL;
192 fMapBuffer = NULL;
193 fUnmapBuffer = NULL;
194 fBindFragDataLocationIndexed = NULL;
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +0000195
196#if GR_GL_PER_GL_FUNC_CALLBACK
197 fCallback = GrGLDefaultInterfaceCallback;
198 fCallbackData = 0;
199#endif
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000200}
201
202
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000203bool GrGLInterface::validateShaderFunctions() const {
204 // required for GrGpuGLShaders
205 if (NULL == fAttachShader ||
206 NULL == fBindAttribLocation ||
207 NULL == fCompileShader ||
208 NULL == fCreateProgram ||
209 NULL == fCreateShader ||
210 NULL == fDeleteProgram ||
211 NULL == fDeleteShader ||
212 NULL == fDisableVertexAttribArray ||
213 NULL == fEnableVertexAttribArray ||
214 NULL == fGetProgramInfoLog ||
215 NULL == fGetProgramiv ||
216 NULL == fGetShaderInfoLog ||
217 NULL == fGetShaderiv ||
218 NULL == fGetUniformLocation ||
219 NULL == fLinkProgram ||
220 NULL == fShaderSource ||
221 NULL == fUniform1f ||
222 NULL == fUniform1i ||
223 NULL == fUniform1fv ||
224 NULL == fUniform1iv ||
225 NULL == fUniform2f ||
226 NULL == fUniform2i ||
227 NULL == fUniform2fv ||
228 NULL == fUniform2iv ||
229 NULL == fUniform3f ||
230 NULL == fUniform3i ||
231 NULL == fUniform3fv ||
232 NULL == fUniform3iv ||
233 NULL == fUniform4f ||
234 NULL == fUniform4i ||
235 NULL == fUniform4fv ||
236 NULL == fUniform4iv ||
237 NULL == fUniformMatrix2fv ||
238 NULL == fUniformMatrix3fv ||
239 NULL == fUniformMatrix4fv ||
240 NULL == fUseProgram ||
241 NULL == fVertexAttrib4fv ||
242 NULL == fVertexAttribPointer) {
243 return false;
244 }
245 return true;
246}
247
248bool GrGLInterface::validateFixedFunctions() const {
249 if (NULL == fClientActiveTexture ||
250 NULL == fColor4ub ||
251 NULL == fColorPointer ||
252 NULL == fDisableClientState ||
253 NULL == fEnableClientState ||
254 NULL == fLoadMatrixf ||
255 NULL == fMatrixMode ||
256 NULL == fPointSize ||
257 NULL == fShadeModel ||
258 NULL == fTexCoordPointer ||
bsalomon@google.com4b9b6a22011-05-04 15:01:16 +0000259 NULL == fTexEnvi ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000260 NULL == fVertexPointer) {
261 return false;
262 }
263 return true;
264}
265
266bool GrGLInterface::validate(GrEngine engine) const {
267
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000268 bool isDesktop = this->supportsDesktop();
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000269
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000270 bool isES = this->supportsES();
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000271
bsalomon@google.com0b77d682011-08-19 13:28:54 +0000272 if (isDesktop == isES) {
273 // must have one, don't support both in same interface
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000274 return false;
275 }
276
277 // functions that are always required
278 if (NULL == fActiveTexture ||
279 NULL == fBindBuffer ||
280 NULL == fBindTexture ||
281 NULL == fBlendFunc ||
282 NULL == fBufferData ||
283 NULL == fBufferSubData ||
284 NULL == fClear ||
285 NULL == fClearColor ||
286 NULL == fClearStencil ||
287 NULL == fColorMask ||
288 NULL == fCullFace ||
289 NULL == fDeleteBuffers ||
290 NULL == fDeleteTextures ||
291 NULL == fDepthMask ||
292 NULL == fDisable ||
293 NULL == fDrawArrays ||
294 NULL == fDrawElements ||
295 NULL == fEnable ||
296 NULL == fFrontFace ||
297 NULL == fGenBuffers ||
298 NULL == fGenTextures ||
299 NULL == fGetBufferParameteriv ||
300 NULL == fGetError ||
301 NULL == fGetIntegerv ||
302 NULL == fGetString ||
303 NULL == fPixelStorei ||
304 NULL == fReadPixels ||
305 NULL == fScissor ||
306 NULL == fStencilFunc ||
307 NULL == fStencilMask ||
308 NULL == fStencilOp ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000309 NULL == fTexImage2D ||
310 NULL == fTexParameteri ||
311 NULL == fTexSubImage2D ||
312 NULL == fViewport ||
313 NULL == fBindFramebuffer ||
314 NULL == fBindRenderbuffer ||
315 NULL == fCheckFramebufferStatus ||
316 NULL == fDeleteFramebuffers ||
317 NULL == fDeleteRenderbuffers ||
318 NULL == fFramebufferRenderbuffer ||
319 NULL == fFramebufferTexture2D ||
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000320 NULL == fGetFramebufferAttachmentParameteriv ||
321 NULL == fGetRenderbufferParameteriv ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000322 NULL == fGenFramebuffers ||
323 NULL == fGenRenderbuffers ||
324 NULL == fRenderbufferStorage) {
325 return false;
326 }
327
328 switch (engine) {
329 case kOpenGL_Shaders_GrEngine:
330 if (kES1_GrGLBinding == fBindingsExported) {
331 return false;
332 }
333 if (!this->validateShaderFunctions()) {
334 return false;
335 }
336 break;
337 case kOpenGL_Fixed_GrEngine:
338 if (kES1_GrGLBinding == fBindingsExported) {
339 return false;
340 }
341 if (!this->validateFixedFunctions()) {
342 return false;
343 }
344 break;
345 default:
346 return false;
347 }
348
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000349 const char* ext;
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000350 GrGLVersion glVer = GrGLGetVersion(this);
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000351 ext = (const char*)fGetString(GR_GL_EXTENSIONS);
352
353 // Now check that baseline ES/Desktop fns not covered above are present
354 // and that we have fn pointers for any advertised extensions that we will
355 // try to use.
356
357 // these functions are part of ES2, we assume they are available
358 // On the desktop we assume they are available if the extension
359 // is present or GL version is high enough.
360 if ((kES2_GrGLBinding & fBindingsExported)) {
361 if (NULL == fBlendColor ||
362 NULL == fStencilFuncSeparate ||
363 NULL == fStencilMaskSeparate ||
364 NULL == fStencilOpSeparate) {
365 return false;
366 }
367 } else if (kDesktop_GrGLBinding == fBindingsExported) {
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000368 if (glVer >= GR_GL_VER(2,0)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000369 if (NULL == fStencilFuncSeparate ||
370 NULL == fStencilMaskSeparate ||
371 NULL == fStencilOpSeparate) {
372 return false;
373 }
374 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000375 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
bsalomon@google.combc5cf512011-09-21 16:21:07 +0000376 return false;
377 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000378 if (glVer >= GR_GL_VER(2,0) ||
379 GrGLHasExtensionFromString("GL_ARB_draw_buffers", ext)) {
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000380 if (NULL == fDrawBuffers) {
381 return false;
382 }
383 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000384 if (glVer >= GR_GL_VER(1,4) ||
385 GrGLHasExtensionFromString("GL_EXT_blend_color", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000386 if (NULL == fBlendColor) {
387 return false;
388 }
389 }
390 }
391
392 // optional function on desktop before 1.3
393 if (kDesktop_GrGLBinding != fBindingsExported ||
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000394 (glVer >= GR_GL_VER(1,3) ||
395 GrGLHasExtensionFromString("GL_ARB_texture_compression", ext))) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000396 if (NULL == fCompressedTexImage2D) {
397 return false;
398 }
399 }
400
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000401 // part of desktop GL, but not ES
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000402 if (kDesktop_GrGLBinding == fBindingsExported &&
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000403 (NULL == fLineWidth ||
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000404 NULL == fGetTexLevelParameteriv ||
bsalomon@google.comc49d66b2011-08-03 14:22:30 +0000405 NULL == fDrawBuffer ||
406 NULL == fReadBuffer)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000407 return false;
408 }
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000409
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000410 // FBO MSAA
411 if (kDesktop_GrGLBinding == fBindingsExported) {
412 // GL 3.0 and the ARB extension have multisample + blit
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000413 if (glVer >= GR_GL_VER(3,0) || GrGLHasExtensionFromString("GL_ARB_framebuffer_object", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000414 if (NULL == fRenderbufferStorageMultisample ||
415 NULL == fBlitFramebuffer) {
416 return false;
417 }
418 } else {
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000419 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_blit", ext) &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000420 NULL == fBlitFramebuffer) {
421 return false;
422 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000423 if (GrGLHasExtensionFromString("GL_EXT_framebuffer_multisample", ext) &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000424 NULL == fRenderbufferStorageMultisample) {
425 return false;
426 }
427 }
428 } else {
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000429 if (GrGLHasExtensionFromString("GL_CHROMIUM_framebuffer_multisample", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000430 if (NULL == fRenderbufferStorageMultisample ||
431 NULL == fBlitFramebuffer) {
432 return false;
433 }
434 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000435 if (GrGLHasExtensionFromString("GL_APPLE_framebuffer_multisample", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000436 if (NULL == fRenderbufferStorageMultisample ||
437 NULL == fResolveMultisampleFramebuffer) {
438 return false;
439 }
440 }
441 }
442
443 // On ES buffer mapping is an extension. On Desktop
444 // buffer mapping was part of original VBO extension
445 // which we require.
446 if (kDesktop_GrGLBinding == fBindingsExported ||
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000447 GrGLHasExtensionFromString("GL_OES_mapbuffer", ext)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000448 if (NULL == fMapBuffer ||
449 NULL == fUnmapBuffer) {
450 return false;
451 }
452 }
453
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000454 // Dual source blending
455 if (kDesktop_GrGLBinding == fBindingsExported &&
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000456 (glVer >= GR_GL_VER(3,3) ||
457 GrGLHasExtensionFromString("GL_ARB_blend_func_extended", ext))) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000458 if (NULL == fBindFragDataLocationIndexed) {
459 return false;
460 }
461 }
462
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000463 return true;
464}
465