blob: e1c69e18a439269e8765162d563d81c8c45e65a8 [file] [log] [blame]
twiz@google.com59a190b2011-03-14 21:23:01 +00001/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00002 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
twiz@google.com59a190b2011-03-14 21:23:01 +00006 */
7
8
tomhudson@google.com6bf38b52012-02-14 15:11:59 +00009#include "gl/GrGLInterface.h"
bsalomon@google.com1744f972013-02-26 21:46:32 +000010#include "gl/GrGLExtensions.h"
11#include "gl/GrGLUtil.h"
twiz@google.com59a190b2011-03-14 21:23:01 +000012
13#include <stdio.h>
14
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +000015#if GR_GL_PER_GL_FUNC_CALLBACK
16namespace {
17void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
18}
19#endif
20
bsalomon@google.com0b77d682011-08-19 13:28:54 +000021GrGLInterface::GrGLInterface() {
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000022 fBindingsExported = kNone_GrGLBinding;
bsalomon@google.com0b77d682011-08-19 13:28:54 +000023
bsalomon@google.com56bfc5a2011-09-01 13:28:16 +000024#if GR_GL_PER_GL_FUNC_CALLBACK
25 fCallback = GrGLDefaultInterfaceCallback;
26 fCallbackData = 0;
27#endif
bsalomon@google.com0b77d682011-08-19 13:28:54 +000028}
29
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000030bool GrGLInterface::validate(GrGLBinding binding) const {
bsalomon@google.com0b77d682011-08-19 13:28:54 +000031
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000032 // kNone must be 0 so that the check we're about to do can never succeed if
33 // binding == kNone.
34 GR_STATIC_ASSERT(kNone_GrGLBinding == 0);
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000035
bsalomon@google.com89ec61e2012-02-10 20:05:18 +000036 if (0 == (binding & fBindingsExported)) {
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000037 return false;
38 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +000039
bsalomon@google.com1744f972013-02-26 21:46:32 +000040 GrGLExtensions extensions;
41 if (!extensions.init(binding, this)) {
42 return false;
43 }
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000044
45 // functions that are always required
46 if (NULL == fActiveTexture ||
47 NULL == fAttachShader ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000048 NULL == fBindAttribLocation ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000049 NULL == fBindBuffer ||
50 NULL == fBindTexture ||
51 NULL == fBlendFunc ||
robertphillips@google.come7884302012-04-18 14:39:58 +000052 NULL == fBlendColor || // -> GL >= 1.4, ES >= 2.0 or extension
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000053 NULL == fBufferData ||
54 NULL == fBufferSubData ||
55 NULL == fClear ||
56 NULL == fClearColor ||
57 NULL == fClearStencil ||
58 NULL == fColorMask ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000059 NULL == fCompileShader ||
commit-bot@chromium.org98168bb2013-04-11 22:00:34 +000060 NULL == fCopyTexSubImage2D ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000061 NULL == fCreateProgram ||
62 NULL == fCreateShader ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000063 NULL == fCullFace ||
64 NULL == fDeleteBuffers ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000065 NULL == fDeleteProgram ||
66 NULL == fDeleteShader ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000067 NULL == fDeleteTextures ||
68 NULL == fDepthMask ||
69 NULL == fDisable ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000070 NULL == fDisableVertexAttribArray ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000071 NULL == fDrawArrays ||
72 NULL == fDrawElements ||
73 NULL == fEnable ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000074 NULL == fEnableVertexAttribArray ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000075 NULL == fFrontFace ||
76 NULL == fGenBuffers ||
77 NULL == fGenTextures ||
78 NULL == fGetBufferParameteriv ||
commit-bot@chromium.orgcffff792013-07-26 16:36:04 +000079 NULL == fGenerateMipmap ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000080 NULL == fGetError ||
81 NULL == fGetIntegerv ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000082 NULL == fGetProgramInfoLog ||
83 NULL == fGetProgramiv ||
84 NULL == fGetShaderInfoLog ||
85 NULL == fGetShaderiv ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000086 NULL == fGetString ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000087 NULL == fGetUniformLocation ||
88 NULL == fLinkProgram ||
commit-bot@chromium.org941df4f2013-08-20 20:54:08 +000089 NULL == fLineWidth ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000090 NULL == fPixelStorei ||
91 NULL == fReadPixels ||
92 NULL == fScissor ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +000093 NULL == fShaderSource ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +000094 NULL == fStencilFunc ||
95 NULL == fStencilMask ||
96 NULL == fStencilOp ||
97 NULL == fTexImage2D ||
98 NULL == fTexParameteri ||
bsalomon@google.com4d063de2012-05-31 17:59:23 +000099 NULL == fTexParameteriv ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000100 NULL == fTexSubImage2D ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000101 NULL == fUniform1f ||
102 NULL == fUniform1i ||
103 NULL == fUniform1fv ||
104 NULL == fUniform1iv ||
105 NULL == fUniform2f ||
106 NULL == fUniform2i ||
107 NULL == fUniform2fv ||
108 NULL == fUniform2iv ||
109 NULL == fUniform3f ||
110 NULL == fUniform3i ||
111 NULL == fUniform3fv ||
112 NULL == fUniform3iv ||
113 NULL == fUniform4f ||
114 NULL == fUniform4i ||
115 NULL == fUniform4fv ||
116 NULL == fUniform4iv ||
117 NULL == fUniformMatrix2fv ||
118 NULL == fUniformMatrix3fv ||
119 NULL == fUniformMatrix4fv ||
120 NULL == fUseProgram ||
121 NULL == fVertexAttrib4fv ||
bsalomon@google.com1dcf5062011-11-14 19:29:53 +0000122 NULL == fVertexAttribPointer ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000123 NULL == fViewport ||
124 NULL == fBindFramebuffer ||
125 NULL == fBindRenderbuffer ||
126 NULL == fCheckFramebufferStatus ||
127 NULL == fDeleteFramebuffers ||
128 NULL == fDeleteRenderbuffers ||
bsalomon@google.com373a6632011-10-19 20:43:20 +0000129 NULL == fFinish ||
130 NULL == fFlush ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000131 NULL == fFramebufferRenderbuffer ||
132 NULL == fFramebufferTexture2D ||
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000133 NULL == fGetFramebufferAttachmentParameteriv ||
134 NULL == fGetRenderbufferParameteriv ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000135 NULL == fGenFramebuffers ||
136 NULL == fGenRenderbuffers ||
137 NULL == fRenderbufferStorage) {
138 return false;
139 }
140
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000141 GrGLVersion glVer = GrGLGetVersion(this);
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000142
bsalomon@google.comf714d512013-08-30 18:25:21 +0000143 bool isCoreProfile = false;
144 if (kDesktop_GrGLBinding == binding && glVer >= GR_GL_VER(3,2)) {
145 GrGLint profileMask;
146 GR_GL_GetIntegerv(this, GR_GL_CONTEXT_PROFILE_MASK, &profileMask);
147 isCoreProfile = SkToBool(profileMask & GR_GL_CONTEXT_CORE_PROFILE_BIT);
148 }
149
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000150 // Now check that baseline ES/Desktop fns not covered above are present
151 // and that we have fn pointers for any advertised extensions that we will
152 // try to use.
153
154 // these functions are part of ES2, we assume they are available
155 // On the desktop we assume they are available if the extension
156 // is present or GL version is high enough.
bsalomon@google.com791816a2013-08-15 18:54:39 +0000157 if (kES_GrGLBinding == binding) {
robertphillips@google.come7884302012-04-18 14:39:58 +0000158 if (NULL == fStencilFuncSeparate ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000159 NULL == fStencilMaskSeparate ||
160 NULL == fStencilOpSeparate) {
161 return false;
162 }
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000163 } else if (kDesktop_GrGLBinding == binding) {
robertphillips@google.come7884302012-04-18 14:39:58 +0000164
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000165 if (glVer >= GR_GL_VER(2,0)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000166 if (NULL == fStencilFuncSeparate ||
167 NULL == fStencilMaskSeparate ||
168 NULL == fStencilOpSeparate) {
169 return false;
170 }
171 }
bsalomon@google.comc82b8892011-09-22 14:10:33 +0000172 if (glVer >= GR_GL_VER(3,0) && NULL == fBindFragDataLocation) {
bsalomon@google.combc5cf512011-09-21 16:21:07 +0000173 return false;
174 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000175 if (glVer >= GR_GL_VER(2,0) || extensions.has("GL_ARB_draw_buffers")) {
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000176 if (NULL == fDrawBuffers) {
177 return false;
178 }
179 }
robertphillips@google.come7884302012-04-18 14:39:58 +0000180
bsalomon@google.com1744f972013-02-26 21:46:32 +0000181 if (glVer >= GR_GL_VER(1,5) || extensions.has("GL_ARB_occlusion_query")) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000182 if (NULL == fGenQueries ||
183 NULL == fDeleteQueries ||
184 NULL == fBeginQuery ||
185 NULL == fEndQuery ||
186 NULL == fGetQueryiv ||
187 NULL == fGetQueryObjectiv ||
188 NULL == fGetQueryObjectuiv) {
189 return false;
190 }
191 }
192 if (glVer >= GR_GL_VER(3,3) ||
bsalomon@google.com1744f972013-02-26 21:46:32 +0000193 extensions.has("GL_ARB_timer_query") ||
194 extensions.has("GL_EXT_timer_query")) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000195 if (NULL == fGetQueryObjecti64v ||
196 NULL == fGetQueryObjectui64v) {
197 return false;
198 }
199 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000200 if (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_timer_query")) {
bsalomon@google.com373a6632011-10-19 20:43:20 +0000201 if (NULL == fQueryCounter) {
202 return false;
203 }
204 }
commit-bot@chromium.org46fbfe02013-08-30 15:52:12 +0000205 if (!isCoreProfile) {
206 if (NULL == fClientActiveTexture ||
207 NULL == fDisableClientState ||
208 NULL == fEnableClientState ||
209 NULL == fLoadIdentity ||
210 NULL == fLoadMatrixf ||
211 NULL == fMatrixMode ||
212 NULL == fTexGenf ||
213 NULL == fTexGenfv ||
214 NULL == fTexGeni ||
215 NULL == fVertexPointer) {
216 return false;
217 }
bsalomon@google.comfe11cb62012-06-06 15:17:54 +0000218 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000219 if (false && extensions.has("GL_NV_path_rendering")) {
bsalomon@google.comfe11cb62012-06-06 15:17:54 +0000220 if (NULL == fPathCommands ||
221 NULL == fPathCoords ||
222 NULL == fPathSubCommands ||
223 NULL == fPathSubCoords ||
224 NULL == fPathString ||
225 NULL == fPathGlyphs ||
226 NULL == fPathGlyphRange ||
227 NULL == fWeightPaths ||
228 NULL == fCopyPath ||
229 NULL == fInterpolatePaths ||
230 NULL == fTransformPath ||
231 NULL == fPathParameteriv ||
232 NULL == fPathParameteri ||
233 NULL == fPathParameterfv ||
234 NULL == fPathParameterf ||
235 NULL == fPathDashArray ||
236 NULL == fGenPaths ||
237 NULL == fDeletePaths ||
238 NULL == fIsPath ||
239 NULL == fPathStencilFunc ||
240 NULL == fPathStencilDepthOffset ||
241 NULL == fStencilFillPath ||
242 NULL == fStencilStrokePath ||
243 NULL == fStencilFillPathInstanced ||
244 NULL == fStencilStrokePathInstanced ||
245 NULL == fPathCoverDepthFunc ||
246 NULL == fPathColorGen ||
247 NULL == fPathTexGen ||
248 NULL == fPathFogGen ||
249 NULL == fCoverFillPath ||
250 NULL == fCoverStrokePath ||
251 NULL == fCoverFillPathInstanced ||
252 NULL == fCoverStrokePathInstanced ||
253 NULL == fGetPathParameteriv ||
254 NULL == fGetPathParameterfv ||
255 NULL == fGetPathCommands ||
256 NULL == fGetPathCoords ||
257 NULL == fGetPathDashArray ||
258 NULL == fGetPathMetrics ||
259 NULL == fGetPathMetricRange ||
260 NULL == fGetPathSpacing ||
261 NULL == fGetPathColorGeniv ||
262 NULL == fGetPathColorGenfv ||
263 NULL == fGetPathTexGeniv ||
264 NULL == fGetPathTexGenfv ||
265 NULL == fIsPointInFillPath ||
266 NULL == fIsPointInStrokePath ||
267 NULL == fGetPathLength ||
268 NULL == fPointAlongPath) {
269 return false;
270 }
271 }
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000272 }
273
274 // optional function on desktop before 1.3
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000275 if (kDesktop_GrGLBinding != binding ||
bsalomon@google.com1744f972013-02-26 21:46:32 +0000276 (glVer >= GR_GL_VER(1,3)) ||
277 extensions.has("GL_ARB_texture_compression")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000278 if (NULL == fCompressedTexImage2D) {
279 return false;
280 }
281 }
282
bsalomon@google.comd32c5f52011-08-02 19:29:03 +0000283 // part of desktop GL, but not ES
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000284 if (kDesktop_GrGLBinding == binding &&
commit-bot@chromium.org941df4f2013-08-20 20:54:08 +0000285 (NULL == fGetTexLevelParameteriv ||
bsalomon@google.comc49d66b2011-08-03 14:22:30 +0000286 NULL == fDrawBuffer ||
287 NULL == fReadBuffer)) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000288 return false;
289 }
bsalomon@google.comcee661a2011-07-26 12:32:36 +0000290
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000291 // GL_EXT_texture_storage is part of desktop 4.2
292 // There is a desktop ARB extension and an ES+desktop EXT extension
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000293 if (kDesktop_GrGLBinding == binding) {
bsalomon@google.combaa9ea12012-01-06 19:05:43 +0000294 if (glVer >= GR_GL_VER(4,2) ||
bsalomon@google.com1744f972013-02-26 21:46:32 +0000295 extensions.has("GL_ARB_texture_storage") ||
296 extensions.has("GL_EXT_texture_storage")) {
bsalomon@google.combaa9ea12012-01-06 19:05:43 +0000297 if (NULL == fTexStorage2D) {
298 return false;
299 }
300 }
commit-bot@chromium.org7a434a22013-08-21 14:01:56 +0000301 } else if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_EXT_texture_storage")) {
bsalomon@google.combaa9ea12012-01-06 19:05:43 +0000302 if (NULL == fTexStorage2D) {
303 return false;
304 }
bsalomon@google.com280e99f2012-01-05 16:17:38 +0000305 }
306
robertphillips@google.coma6ffb582013-04-29 16:50:17 +0000307 if (extensions.has("GL_EXT_discard_framebuffer")) {
308// FIXME: Remove this once Chromium is updated to provide this function
309#if 0
310 if (NULL == fDiscardFramebuffer) {
311 return false;
312 }
313#endif
314 }
315
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000316 // FBO MSAA
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000317 if (kDesktop_GrGLBinding == binding) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000318 // GL 3.0 and the ARB extension have multisample + blit
bsalomon@google.com1744f972013-02-26 21:46:32 +0000319 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_ARB_framebuffer_object")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000320 if (NULL == fRenderbufferStorageMultisample ||
321 NULL == fBlitFramebuffer) {
322 return false;
323 }
324 } else {
bsalomon@google.com1744f972013-02-26 21:46:32 +0000325 if (extensions.has("GL_EXT_framebuffer_blit") &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000326 NULL == fBlitFramebuffer) {
327 return false;
328 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000329 if (extensions.has("GL_EXT_framebuffer_multisample") &&
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000330 NULL == fRenderbufferStorageMultisample) {
331 return false;
332 }
333 }
334 } else {
commit-bot@chromium.orga8e5a062013-09-05 23:44:09 +0000335#if GR_GL_IGNORE_ES3_MSAA
bsalomon@google.com1744f972013-02-26 21:46:32 +0000336 if (extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000337 if (NULL == fRenderbufferStorageMultisample ||
338 NULL == fBlitFramebuffer) {
339 return false;
340 }
commit-bot@chromium.orga8e5a062013-09-05 23:44:09 +0000341 } else if (extensions.has("GL_APPLE_framebuffer_multisample")) {
342 if (NULL == fRenderbufferStorageMultisample ||
343 NULL == fResolveMultisampleFramebuffer) {
344 return false;
345 }
346 } else if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
347 extensions.has("GL_EXT_multisampled_render_to_texture")) {
348 if (NULL == fRenderbufferStorageMultisample ||
349 NULL == fFramebufferTexture2DMultisample) {
350 return false;
351 }
352 }
353#else
354 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_CHROMIUM_framebuffer_multisample")) {
355 if (NULL == fRenderbufferStorageMultisample ||
356 NULL == fBlitFramebuffer) {
357 return false;
358 }
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000359 }
bsalomon@google.com1744f972013-02-26 21:46:32 +0000360 if (extensions.has("GL_APPLE_framebuffer_multisample")) {
commit-bot@chromium.orga8e5a062013-09-05 23:44:09 +0000361 if (NULL == fRenderbufferStorageMultisampleES2APPLE ||
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000362 NULL == fResolveMultisampleFramebuffer) {
363 return false;
364 }
365 }
bsalomon@google.com347c3822013-05-01 20:10:01 +0000366 if (extensions.has("GL_IMG_multisampled_render_to_texture") ||
367 extensions.has("GL_EXT_multisampled_render_to_texture")) {
commit-bot@chromium.orga8e5a062013-09-05 23:44:09 +0000368 if (NULL == fRenderbufferStorageMultisampleES2EXT ||
bsalomon@google.comf3a60c02013-03-19 19:06:09 +0000369 NULL == fFramebufferTexture2DMultisample) {
370 return false;
371 }
372 }
commit-bot@chromium.orga8e5a062013-09-05 23:44:09 +0000373#endif
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000374 }
375
376 // On ES buffer mapping is an extension. On Desktop
377 // buffer mapping was part of original VBO extension
378 // which we require.
bsalomon@google.com1744f972013-02-26 21:46:32 +0000379 if (kDesktop_GrGLBinding == binding || extensions.has("GL_OES_mapbuffer")) {
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000380 if (NULL == fMapBuffer ||
381 NULL == fUnmapBuffer) {
382 return false;
383 }
384 }
385
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000386 // Dual source blending
bsalomon@google.com89ec61e2012-02-10 20:05:18 +0000387 if (kDesktop_GrGLBinding == binding &&
bsalomon@google.com1744f972013-02-26 21:46:32 +0000388 (glVer >= GR_GL_VER(3,3) || extensions.has("GL_ARB_blend_func_extended"))) {
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000389 if (NULL == fBindFragDataLocationIndexed) {
390 return false;
391 }
392 }
skia.committer@gmail.com12eea2b2013-02-27 07:10:10 +0000393
commit-bot@chromium.org726e6212013-08-23 20:55:46 +0000394 // glGetStringi was added in version 3.0 of both desktop and ES.
395 if (glVer >= GR_GL_VER(3, 0)) {
bsalomon@google.com1744f972013-02-26 21:46:32 +0000396 if (NULL == fGetStringi) {
397 return false;
398 }
399 }
bsalomon@google.com271cffc2011-05-20 14:13:56 +0000400
bsalomon@google.comecd84842013-03-01 15:36:02 +0000401 if (kDesktop_GrGLBinding == binding) {
402 if (glVer >= GR_GL_VER(3, 0) || extensions.has("GL_ARB_vertex_array_object")) {
403 if (NULL == fBindVertexArray ||
404 NULL == fDeleteVertexArrays ||
405 NULL == fGenVertexArrays) {
406 return false;
407 }
408 }
409 } else {
commit-bot@chromium.org2276c012013-08-16 15:53:33 +0000410 if (glVer >= GR_GL_VER(3,0) || extensions.has("GL_OES_vertex_array_object")) {
bsalomon@google.comecd84842013-03-01 15:36:02 +0000411 if (NULL == fBindVertexArray ||
412 NULL == fDeleteVertexArrays ||
413 NULL == fGenVertexArrays) {
414 return false;
415 }
416 }
bsalomon@google.comecd84842013-03-01 15:36:02 +0000417 }
418
bsalomon@google.combf2a4692011-05-04 12:35:39 +0000419 return true;
420}