1 /*
2  * 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.
6  */
7 
8 
9 #include "gl/GrGLInterface.h"
10 #include "gl/GrGLExtensions.h"
11 #include "gl/GrGLUtil.h"
12 
13 #include <stdio.h>
14 
GrGLInterface()15 GrGLInterface::GrGLInterface() {
16     fStandard = kNone_GrGLStandard;
17 }
18 
19 #ifdef SK_DEBUG
20     static int kIsDebug = 1;
21 #else
22     static int kIsDebug = 0;
23 #endif
24 
25 #define RETURN_FALSE_INTERFACE                                                                   \
26     if (kIsDebug) { SkDebugf("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); } \
27     return false
28 
validate() const29 bool GrGLInterface::validate() const {
30 
31     if (kNone_GrGLStandard == fStandard) {
32         RETURN_FALSE_INTERFACE;
33     }
34 
35     if (!fExtensions.isInitialized()) {
36         RETURN_FALSE_INTERFACE;
37     }
38 
39     // functions that are always required
40     if (!fFunctions.fActiveTexture ||
41         !fFunctions.fAttachShader ||
42         !fFunctions.fBindAttribLocation ||
43         !fFunctions.fBindBuffer ||
44         !fFunctions.fBindTexture ||
45         !fFunctions.fBlendColor ||      // -> GL >= 1.4 or extension, ES >= 2.0
46         !fFunctions.fBlendEquation ||   // -> GL >= 1.4 or extension, ES >= 2.0
47         !fFunctions.fBlendFunc ||
48         !fFunctions.fBufferData ||
49         !fFunctions.fBufferSubData ||
50         !fFunctions.fClear ||
51         !fFunctions.fClearColor ||
52         !fFunctions.fClearStencil ||
53         !fFunctions.fColorMask ||
54         !fFunctions.fCompileShader ||
55         !fFunctions.fCompressedTexImage2D ||
56         !fFunctions.fCompressedTexSubImage2D ||
57         !fFunctions.fCopyTexSubImage2D ||
58         !fFunctions.fCreateProgram ||
59         !fFunctions.fCreateShader ||
60         !fFunctions.fCullFace ||
61         !fFunctions.fDeleteBuffers ||
62         !fFunctions.fDeleteProgram ||
63         !fFunctions.fDeleteShader ||
64         !fFunctions.fDeleteTextures ||
65         !fFunctions.fDepthMask ||
66         !fFunctions.fDisable ||
67         !fFunctions.fDisableVertexAttribArray ||
68         !fFunctions.fDrawArrays ||
69         !fFunctions.fDrawElements ||
70         !fFunctions.fEnable ||
71         !fFunctions.fEnableVertexAttribArray ||
72         !fFunctions.fFrontFace ||
73         !fFunctions.fGenBuffers ||
74         !fFunctions.fGenTextures ||
75         !fFunctions.fGetBufferParameteriv ||
76         !fFunctions.fGenerateMipmap ||
77         !fFunctions.fGetError ||
78         !fFunctions.fGetIntegerv ||
79         !fFunctions.fGetProgramInfoLog ||
80         !fFunctions.fGetProgramiv ||
81         !fFunctions.fGetShaderInfoLog ||
82         !fFunctions.fGetShaderiv ||
83         !fFunctions.fGetString ||
84         !fFunctions.fGetUniformLocation ||
85         !fFunctions.fIsTexture ||
86         !fFunctions.fLinkProgram ||
87         !fFunctions.fLineWidth ||
88         !fFunctions.fPixelStorei ||
89         !fFunctions.fReadPixels ||
90         !fFunctions.fScissor ||
91         !fFunctions.fShaderSource ||
92         !fFunctions.fStencilFunc ||
93         !fFunctions.fStencilFuncSeparate ||
94         !fFunctions.fStencilMask ||
95         !fFunctions.fStencilMaskSeparate ||
96         !fFunctions.fStencilOp ||
97         !fFunctions.fStencilOpSeparate ||
98         !fFunctions.fTexImage2D ||
99         !fFunctions.fTexParameterf ||
100         !fFunctions.fTexParameterfv ||
101         !fFunctions.fTexParameteri ||
102         !fFunctions.fTexParameteriv ||
103         !fFunctions.fTexSubImage2D ||
104         !fFunctions.fUniform1f ||
105         !fFunctions.fUniform1i ||
106         !fFunctions.fUniform1fv ||
107         !fFunctions.fUniform1iv ||
108         !fFunctions.fUniform2f ||
109         !fFunctions.fUniform2i ||
110         !fFunctions.fUniform2fv ||
111         !fFunctions.fUniform2iv ||
112         !fFunctions.fUniform3f ||
113         !fFunctions.fUniform3i ||
114         !fFunctions.fUniform3fv ||
115         !fFunctions.fUniform3iv ||
116         !fFunctions.fUniform4f ||
117         !fFunctions.fUniform4i ||
118         !fFunctions.fUniform4fv ||
119         !fFunctions.fUniform4iv ||
120         !fFunctions.fUniformMatrix2fv ||
121         !fFunctions.fUniformMatrix3fv ||
122         !fFunctions.fUniformMatrix4fv ||
123         !fFunctions.fUseProgram ||
124         !fFunctions.fVertexAttrib1f ||
125         !fFunctions.fVertexAttrib2fv ||
126         !fFunctions.fVertexAttrib3fv ||
127         !fFunctions.fVertexAttrib4fv ||
128         !fFunctions.fVertexAttribPointer ||
129         !fFunctions.fViewport ||
130         !fFunctions.fBindFramebuffer ||
131         !fFunctions.fBindRenderbuffer ||
132         !fFunctions.fCheckFramebufferStatus ||
133         !fFunctions.fDeleteFramebuffers ||
134         !fFunctions.fDeleteRenderbuffers ||
135         !fFunctions.fFinish ||
136         !fFunctions.fFlush ||
137         !fFunctions.fFramebufferRenderbuffer ||
138         !fFunctions.fFramebufferTexture2D ||
139         !fFunctions.fGetFramebufferAttachmentParameteriv ||
140         !fFunctions.fGetRenderbufferParameteriv ||
141         !fFunctions.fGenFramebuffers ||
142         !fFunctions.fGenRenderbuffers ||
143         !fFunctions.fRenderbufferStorage) {
144         RETURN_FALSE_INTERFACE;
145     }
146 
147     GrGLVersion glVer = GrGLGetVersion(this);
148     if (GR_GL_INVALID_VER == glVer) {
149         RETURN_FALSE_INTERFACE;
150     }
151 
152     // Now check that baseline ES/Desktop fns not covered above are present
153     // and that we have fn pointers for any advertised fExtensions that we will
154     // try to use.
155 
156     // these functions are part of ES2, we assume they are available
157     // On the desktop we assume they are available if the extension
158     // is present or GL version is high enough.
159     if (kGL_GrGLStandard == fStandard) {
160         if (glVer >= GR_GL_VER(3,0) && !fFunctions.fBindFragDataLocation) {
161             RETURN_FALSE_INTERFACE;
162         }
163 
164         if (glVer >= GR_GL_VER(3,3) ||
165             fExtensions.has("GL_ARB_timer_query") ||
166             fExtensions.has("GL_EXT_timer_query")) {
167             if (!fFunctions.fGetQueryObjecti64v ||
168                 !fFunctions.fGetQueryObjectui64v) {
169                 RETURN_FALSE_INTERFACE;
170             }
171         }
172         if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) {
173             if (!fFunctions.fQueryCounter) {
174                 RETURN_FALSE_INTERFACE;
175             }
176         }
177     }
178 
179     // part of desktop GL, but not ES
180     if (kGL_GrGLStandard == fStandard &&
181         (!fFunctions.fDrawBuffer ||
182          !fFunctions.fPolygonMode)) {
183         RETURN_FALSE_INTERFACE;
184     }
185 
186     // ES 3.0 (or ES 2.0 extended) has glDrawBuffers but not glDrawBuffer
187     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) {
188         if (!fFunctions.fDrawBuffers) {
189             RETURN_FALSE_INTERFACE;
190         }
191     }
192 
193     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) {
194         if (!fFunctions.fReadBuffer) {
195             RETURN_FALSE_INTERFACE;
196         }
197     }
198 
199     // glGetTexLevelParameteriv was added to ES in 3.1.
200     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,1)) {
201         if (!fFunctions.fGetTexLevelParameteriv) {
202             RETURN_FALSE_INTERFACE;
203         }
204     }
205 
206     // GL_EXT_texture_storage is part of desktop 4.2
207     // There is a desktop ARB extension and an ES+desktop EXT extension
208     if (kGL_GrGLStandard == fStandard) {
209         if (glVer >= GR_GL_VER(4,2) ||
210             fExtensions.has("GL_ARB_texture_storage") ||
211             fExtensions.has("GL_EXT_texture_storage")) {
212             if (!fFunctions.fTexStorage2D) {
213                 RETURN_FALSE_INTERFACE;
214             }
215         }
216     } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) {
217         if (!fFunctions.fTexStorage2D) {
218             RETURN_FALSE_INTERFACE;
219         }
220     }
221 
222     // glTextureBarrier is part of desktop 4.5. There are also ARB and NV extensions.
223     if (kGL_GrGLStandard == fStandard) {
224         if (glVer >= GR_GL_VER(4,5) ||
225             fExtensions.has("GL_ARB_texture_barrier") ||
226             fExtensions.has("GL_NV_texture_barrier")) {
227             if (!fFunctions.fTextureBarrier) {
228                 RETURN_FALSE_INTERFACE;
229             }
230         }
231     } else if (fExtensions.has("GL_NV_texture_barrier")) {
232         if (!fFunctions.fTextureBarrier) {
233             RETURN_FALSE_INTERFACE;
234         }
235     }
236 
237     if (fExtensions.has("GL_KHR_blend_equation_advanced") ||
238         fExtensions.has("GL_NV_blend_equation_advanced")) {
239         if (!fFunctions.fBlendBarrier) {
240             RETURN_FALSE_INTERFACE;
241         }
242     }
243 
244     if (fExtensions.has("GL_EXT_discard_framebuffer")) {
245         if (!fFunctions.fDiscardFramebuffer) {
246             RETURN_FALSE_INTERFACE;
247         }
248     }
249 
250     // Required since OpenGL 1.5 and ES 3.0 or with GL_EXT_occlusion_query_boolean
251     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0) ||
252         fExtensions.has("GL_EXT_occlusion_query_boolean")) {
253 #if 0 // Not yet added to chrome's bindings.
254         if (!fFunctions.fGenQueries ||
255             !fFunctions.fDeleteQueries ||
256             !fFunctions.fBeginQuery ||
257             !fFunctions.fEndQuery ||
258             !fFunctions.fGetQueryiv ||
259             !fFunctions.fGetQueryObjectuiv) {
260             RETURN_FALSE_INTERFACE;
261         }
262 #endif
263     }
264     // glGetQueryObjectiv doesn't exist in ES.
265     if (kGL_GrGLStandard == fStandard && !fFunctions.fGetQueryObjectiv) {
266         RETURN_FALSE_INTERFACE;
267     }
268 
269     // FBO MSAA
270     if (kGL_GrGLStandard == fStandard) {
271         // GL 3.0 and the ARB extension have multisample + blit
272         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) {
273             if (!fFunctions.fRenderbufferStorageMultisample ||
274                 !fFunctions.fBlitFramebuffer) {
275                 RETURN_FALSE_INTERFACE;
276             }
277         } else {
278             if (fExtensions.has("GL_EXT_framebuffer_blit") &&
279                 !fFunctions.fBlitFramebuffer) {
280                 RETURN_FALSE_INTERFACE;
281             }
282             if (fExtensions.has("GL_EXT_framebuffer_multisample") &&
283                 !fFunctions.fRenderbufferStorageMultisample) {
284                 RETURN_FALSE_INTERFACE;
285             }
286         }
287     } else {
288         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) {
289             if (!fFunctions.fRenderbufferStorageMultisample ||
290                 !fFunctions.fBlitFramebuffer) {
291                 RETURN_FALSE_INTERFACE;
292             }
293         } else {
294             if (fExtensions.has("GL_ANGLE_framebuffer_multisample") &&
295                 !fFunctions.fRenderbufferStorageMultisample) {
296                 RETURN_FALSE_INTERFACE;
297             }
298             if (fExtensions.has("GL_ANGLE_framebuffer_blit") &&
299                 !fFunctions.fBlitFramebuffer) {
300                 RETURN_FALSE_INTERFACE;
301             }
302         }
303         if (fExtensions.has("GL_APPLE_framebuffer_multisample")) {
304             if (!fFunctions.fRenderbufferStorageMultisampleES2APPLE ||
305                 !fFunctions.fResolveMultisampleFramebuffer) {
306                 RETURN_FALSE_INTERFACE;
307             }
308         }
309         if (fExtensions.has("GL_IMG_multisampled_render_to_texture") ||
310             fExtensions.has("GL_EXT_multisampled_render_to_texture")) {
311             if (!fFunctions.fRenderbufferStorageMultisampleES2EXT ||
312                 !fFunctions.fFramebufferTexture2DMultisample) {
313                 RETURN_FALSE_INTERFACE;
314             }
315         }
316     }
317 
318     // On ES buffer mapping is an extension. On Desktop
319     // buffer mapping was part of original VBO extension
320     // which we require.
321     if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) {
322         if (!fFunctions.fMapBuffer ||
323             !fFunctions.fUnmapBuffer) {
324             RETURN_FALSE_INTERFACE;
325         }
326     }
327 
328     // Dual source blending
329     if (kGL_GrGLStandard == fStandard) {
330         if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended")) {
331             if (!fFunctions.fBindFragDataLocationIndexed) {
332                 RETURN_FALSE_INTERFACE;
333             }
334         }
335     } else {
336         if (glVer >= GR_GL_VER(3,0) && fExtensions.has("GL_EXT_blend_func_extended")) {
337             if (!fFunctions.fBindFragDataLocation ||
338                 !fFunctions.fBindFragDataLocationIndexed) {
339                 RETURN_FALSE_INTERFACE;
340             }
341         }
342     }
343 
344 
345     // glGetStringi was added in version 3.0 of both desktop and ES.
346     if (glVer >= GR_GL_VER(3, 0)) {
347         if (!fFunctions.fGetStringi) {
348             RETURN_FALSE_INTERFACE;
349         }
350     }
351 
352     // glVertexAttribIPointer was added in version 3.0 of both desktop and ES.
353     if (glVer >= GR_GL_VER(3, 0)) {
354         if (!fFunctions.fVertexAttribIPointer) {
355             RETURN_FALSE_INTERFACE;
356         }
357     }
358 
359     if (kGL_GrGLStandard == fStandard) {
360         if (glVer >= GR_GL_VER(3,1)) {
361             if (!fFunctions.fTexBuffer) {
362                 RETURN_FALSE_INTERFACE;
363             }
364         }
365         if (glVer >= GR_GL_VER(4,3)) {
366             if (!fFunctions.fTexBufferRange) {
367                 RETURN_FALSE_INTERFACE;
368             }
369         }
370     } else {
371         if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_OES_texture_buffer") ||
372             fExtensions.has("GL_EXT_texture_buffer")) {
373             if (!fFunctions.fTexBuffer ||
374                 !fFunctions.fTexBufferRange) {
375                 RETURN_FALSE_INTERFACE;
376             }
377         }
378     }
379 
380     if (kGL_GrGLStandard == fStandard) {
381         if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) {
382             if (!fFunctions.fBindVertexArray ||
383                 !fFunctions.fDeleteVertexArrays ||
384                 !fFunctions.fGenVertexArrays) {
385                 RETURN_FALSE_INTERFACE;
386             }
387         }
388     } else {
389         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) {
390             if (!fFunctions.fBindVertexArray ||
391                 !fFunctions.fDeleteVertexArrays ||
392                 !fFunctions.fGenVertexArrays) {
393                 RETURN_FALSE_INTERFACE;
394             }
395         }
396     }
397 
398     if (fExtensions.has("GL_EXT_debug_marker")) {
399         if (!fFunctions.fInsertEventMarker ||
400             !fFunctions.fPushGroupMarker ||
401             !fFunctions.fPopGroupMarker) {
402             RETURN_FALSE_INTERFACE;
403         }
404     }
405 
406     if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
407         fExtensions.has("GL_ARB_invalidate_subdata")) {
408         if (!fFunctions.fInvalidateBufferData ||
409             !fFunctions.fInvalidateBufferSubData ||
410             !fFunctions.fInvalidateFramebuffer ||
411             !fFunctions.fInvalidateSubFramebuffer ||
412             !fFunctions.fInvalidateTexImage ||
413             !fFunctions.fInvalidateTexSubImage) {
414             RETURN_FALSE_INTERFACE;
415         }
416     } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) {
417         // ES 3.0 adds the framebuffer functions but not the others.
418         if (!fFunctions.fInvalidateFramebuffer ||
419             !fFunctions.fInvalidateSubFramebuffer) {
420             RETURN_FALSE_INTERFACE;
421         }
422     }
423 
424     if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_CHROMIUM_map_sub")) {
425         if (!fFunctions.fMapBufferSubData ||
426             !fFunctions.fMapTexSubImage2D ||
427             !fFunctions.fUnmapBufferSubData ||
428             !fFunctions.fUnmapTexSubImage2D) {
429             RETURN_FALSE_INTERFACE;
430         }
431     }
432 
433     // These functions are added to the 3.0 version of both GLES and GL.
434     if (glVer >= GR_GL_VER(3,0) ||
435         (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_map_buffer_range")) ||
436         (kGL_GrGLStandard == fStandard && fExtensions.has("GL_ARB_map_buffer_range"))) {
437         if (!fFunctions.fMapBufferRange ||
438             !fFunctions.fFlushMappedBufferRange) {
439             RETURN_FALSE_INTERFACE;
440         }
441     }
442 
443     if ((kGL_GrGLStandard == fStandard &&
444          (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_texture_multisample"))) ||
445         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
446         if (!fFunctions.fGetMultisamplefv) {
447             RETURN_FALSE_INTERFACE;
448         }
449     }
450 
451     if ((kGL_GrGLStandard == fStandard &&
452          (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_program_interface_query"))) ||
453         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
454         if (!fFunctions.fGetProgramResourceLocation) {
455             RETURN_FALSE_INTERFACE;
456         }
457     }
458 
459     if (kGLES_GrGLStandard == fStandard || glVer >= GR_GL_VER(4,1) ||
460         fExtensions.has("GL_ARB_ES2_compatibility")) {
461         if (!fFunctions.fGetShaderPrecisionFormat) {
462             RETURN_FALSE_INTERFACE;
463         }
464     }
465 
466     if (fExtensions.has("GL_NV_path_rendering") || fExtensions.has("GL_CHROMIUM_path_rendering")) {
467         if (!fFunctions.fMatrixLoadf ||
468             !fFunctions.fMatrixLoadIdentity ||
469             !fFunctions.fPathCommands ||
470             !fFunctions.fPathParameteri ||
471             !fFunctions.fPathParameterf ||
472             !fFunctions.fGenPaths ||
473             !fFunctions.fDeletePaths ||
474             !fFunctions.fIsPath ||
475             !fFunctions.fPathStencilFunc ||
476             !fFunctions.fStencilFillPath ||
477             !fFunctions.fStencilStrokePath ||
478             !fFunctions.fStencilFillPathInstanced ||
479             !fFunctions.fStencilStrokePathInstanced ||
480             !fFunctions.fCoverFillPath ||
481             !fFunctions.fCoverStrokePath ||
482             !fFunctions.fCoverFillPathInstanced ||
483             !fFunctions.fCoverStrokePathInstanced
484 #if 0
485             // List of functions that Skia uses, but which have been added since the initial release
486             // of NV_path_rendering driver. We do not want to fail interface validation due to
487             // missing features, we will just not use the extension.
488             // Update this list -> update GrGLCaps::hasPathRenderingSupport too.
489             || !fFunctions.fStencilThenCoverFillPath ||
490             !fFunctions.fStencilThenCoverStrokePath ||
491             !fFunctions.fStencilThenCoverFillPathInstanced ||
492             !fFunctions.fStencilThenCoverStrokePathInstanced ||
493             !fFunctions.fProgramPathFragmentInputGen
494 #endif
495             ) {
496             RETURN_FALSE_INTERFACE;
497         }
498         if (fExtensions.has("GL_CHROMIUM_path_rendering")) {
499             if (!fFunctions.fBindFragmentInputLocation) {
500                 RETURN_FALSE_INTERFACE;
501             }
502         }
503     }
504 
505     if (fExtensions.has("GL_EXT_raster_multisample")) {
506         if (!fFunctions.fRasterSamples) {
507             RETURN_FALSE_INTERFACE;
508         }
509     }
510 
511     if (fExtensions.has("GL_NV_framebuffer_mixed_samples") ||
512         fExtensions.has("GL_CHROMIUM_framebuffer_mixed_samples")) {
513         if (!fFunctions.fCoverageModulation) {
514             RETURN_FALSE_INTERFACE;
515         }
516     }
517 
518     if (kGL_GrGLStandard == fStandard) {
519         if (glVer >= GR_GL_VER(3,1) ||
520             fExtensions.has("GL_EXT_draw_instanced") || fExtensions.has("GL_ARB_draw_instanced")) {
521             if (!fFunctions.fDrawArraysInstanced ||
522                 !fFunctions.fDrawElementsInstanced) {
523                 RETURN_FALSE_INTERFACE;
524             }
525         }
526     } else if (kGLES_GrGLStandard == fStandard) {
527         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_draw_instanced")) {
528             if (!fFunctions.fDrawArraysInstanced ||
529                 !fFunctions.fDrawElementsInstanced) {
530                 RETURN_FALSE_INTERFACE;
531             }
532         }
533     }
534 
535     if (kGL_GrGLStandard == fStandard) {
536         if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_instanced_arrays")) {
537             if (!fFunctions.fVertexAttribDivisor) {
538                 RETURN_FALSE_INTERFACE;
539             }
540         }
541     } else if (kGLES_GrGLStandard == fStandard) {
542         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_instanced_arrays")) {
543             if (!fFunctions.fVertexAttribDivisor) {
544                 RETURN_FALSE_INTERFACE;
545             }
546         }
547     }
548 
549     if ((kGL_GrGLStandard == fStandard &&
550          (glVer >= GR_GL_VER(4,0) || fExtensions.has("GL_ARB_draw_indirect"))) ||
551         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
552         if (!fFunctions.fDrawArraysIndirect ||
553             !fFunctions.fDrawElementsIndirect) {
554             RETURN_FALSE_INTERFACE;
555         }
556     }
557 
558     if ((kGL_GrGLStandard == fStandard &&
559          (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_multi_draw_indirect"))) ||
560         (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_multi_draw_indirect"))) {
561         if (!fFunctions.fMultiDrawArraysIndirect ||
562             !fFunctions.fMultiDrawElementsIndirect) {
563             RETURN_FALSE_INTERFACE;
564         }
565     }
566 
567     if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
568         fExtensions.has("GL_KHR_debug")) {
569         if (!fFunctions.fDebugMessageControl ||
570             !fFunctions.fDebugMessageInsert ||
571             !fFunctions.fDebugMessageCallback ||
572             !fFunctions.fGetDebugMessageLog ||
573             !fFunctions.fPushDebugGroup ||
574             !fFunctions.fPopDebugGroup ||
575             !fFunctions.fObjectLabel) {
576             RETURN_FALSE_INTERFACE;
577         }
578     }
579 
580     if (fExtensions.has("GL_EXT_window_rectangles")) {
581         if (!fFunctions.fWindowRectangles) {
582             RETURN_FALSE_INTERFACE;
583         }
584     }
585 
586     if (kGL_GrGLStandard == fStandard) {
587         if (glVer >= GR_GL_VER(3, 2) || fExtensions.has("GL_ARB_sync")) {
588             if (!fFunctions.fFenceSync ||
589                 !fFunctions.fIsSync ||
590                 !fFunctions.fClientWaitSync ||
591                 !fFunctions.fWaitSync ||
592                 !fFunctions.fDeleteSync) {
593                 RETURN_FALSE_INTERFACE;
594             }
595         }
596     } else if (kGLES_GrGLStandard == fStandard) {
597         if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_APPLE_sync")) {
598             if (!fFunctions.fFenceSync ||
599                 !fFunctions.fIsSync ||
600                 !fFunctions.fClientWaitSync ||
601                 !fFunctions.fWaitSync ||
602                 !fFunctions.fDeleteSync) {
603                 RETURN_FALSE_INTERFACE;
604             }
605         }
606     }
607 
608     if (fExtensions.has("EGL_KHR_image") || fExtensions.has("EGL_KHR_image_base")) {
609         if (!fFunctions.fEGLCreateImage ||
610             !fFunctions.fEGLDestroyImage) {
611             RETURN_FALSE_INTERFACE;
612         }
613     }
614 
615     // glDrawRangeElements was added to ES in 3.0.
616     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) {
617         if (!fFunctions.fDrawRangeElements) {
618             RETURN_FALSE_INTERFACE;
619         }
620     }
621 
622     // getInternalformativ was added in GL 4.2, ES 3.0, and with extension ARB_internalformat_query
623     if ((kGL_GrGLStandard == fStandard &&
624          (glVer >= GR_GL_VER(4,2) || fExtensions.has("GL_ARB_internalformat_query"))) ||
625         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0))) {
626         if (!fFunctions.fGetInternalformativ) {
627             RETURN_FALSE_INTERFACE;
628         }
629     }
630 
631     if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,1)) ||
632         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0))) {
633         if (!fFunctions.fGetProgramBinary ||
634             !fFunctions.fProgramBinary ||
635             !fFunctions.fProgramParameteri) {
636             RETURN_FALSE_INTERFACE;
637         }
638     }
639 
640     if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,1)) ||
641         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0))) {
642         if (!fFunctions.fBindSampler ||
643             !fFunctions.fDeleteSamplers  ||
644             !fFunctions.fGenSamplers ||
645             !fFunctions.fSamplerParameteri ||
646             !fFunctions.fSamplerParameteriv) {
647             RETURN_FALSE_INTERFACE;
648         }
649     }
650 
651     return true;
652 }
653 
654 #if GR_TEST_UTILS
655 
abandon() const656 void GrGLInterface::abandon() const {
657     const_cast<GrGLInterface*>(this)->fFunctions = GrGLInterface::Functions();
658 }
659 
660 #endif // GR_TEST_UTILS
661 
662