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 
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 
29 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.fTexParameteri ||
100         !fFunctions.fTexParameteriv ||
101         !fFunctions.fTexSubImage2D ||
102         !fFunctions.fUniform1f ||
103         !fFunctions.fUniform1i ||
104         !fFunctions.fUniform1fv ||
105         !fFunctions.fUniform1iv ||
106         !fFunctions.fUniform2f ||
107         !fFunctions.fUniform2i ||
108         !fFunctions.fUniform2fv ||
109         !fFunctions.fUniform2iv ||
110         !fFunctions.fUniform3f ||
111         !fFunctions.fUniform3i ||
112         !fFunctions.fUniform3fv ||
113         !fFunctions.fUniform3iv ||
114         !fFunctions.fUniform4f ||
115         !fFunctions.fUniform4i ||
116         !fFunctions.fUniform4fv ||
117         !fFunctions.fUniform4iv ||
118         !fFunctions.fUniformMatrix2fv ||
119         !fFunctions.fUniformMatrix3fv ||
120         !fFunctions.fUniformMatrix4fv ||
121         !fFunctions.fUseProgram ||
122         !fFunctions.fVertexAttrib1f ||
123         !fFunctions.fVertexAttrib2fv ||
124         !fFunctions.fVertexAttrib3fv ||
125         !fFunctions.fVertexAttrib4fv ||
126         !fFunctions.fVertexAttribPointer ||
127         !fFunctions.fViewport ||
128         !fFunctions.fBindFramebuffer ||
129         !fFunctions.fBindRenderbuffer ||
130         !fFunctions.fCheckFramebufferStatus ||
131         !fFunctions.fDeleteFramebuffers ||
132         !fFunctions.fDeleteRenderbuffers ||
133         !fFunctions.fFinish ||
134         !fFunctions.fFlush ||
135         !fFunctions.fFramebufferRenderbuffer ||
136         !fFunctions.fFramebufferTexture2D ||
137         !fFunctions.fGetFramebufferAttachmentParameteriv ||
138         !fFunctions.fGetRenderbufferParameteriv ||
139         !fFunctions.fGenFramebuffers ||
140         !fFunctions.fGenRenderbuffers ||
141         !fFunctions.fRenderbufferStorage) {
142         RETURN_FALSE_INTERFACE
143     }
144 
145     GrGLVersion glVer = GrGLGetVersion(this);
146     if (GR_GL_INVALID_VER == glVer) {
147         RETURN_FALSE_INTERFACE
148     }
149 
150     // Now check that baseline ES/Desktop fns not covered above are present
151     // and that we have fn pointers for any advertised fExtensions 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.
157     if (kGL_GrGLStandard == fStandard) {
158         if (glVer >= GR_GL_VER(3,0) && !fFunctions.fBindFragDataLocation) {
159             RETURN_FALSE_INTERFACE
160         }
161 
162         if (glVer >= GR_GL_VER(3,3) ||
163             fExtensions.has("GL_ARB_timer_query") ||
164             fExtensions.has("GL_EXT_timer_query")) {
165             if (!fFunctions.fGetQueryObjecti64v ||
166                 !fFunctions.fGetQueryObjectui64v) {
167                 RETURN_FALSE_INTERFACE
168             }
169         }
170         if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) {
171             if (!fFunctions.fQueryCounter) {
172                 RETURN_FALSE_INTERFACE
173             }
174         }
175     }
176 
177     // part of desktop GL, but not ES
178     if (kGL_GrGLStandard == fStandard &&
179         (!fFunctions.fDrawBuffer ||
180          !fFunctions.fPolygonMode)) {
181         RETURN_FALSE_INTERFACE
182     }
183 
184     // ES 3.0 (or ES 2.0 extended) has glDrawBuffers but not glDrawBuffer
185     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) {
186         if (!fFunctions.fDrawBuffers) {
187             RETURN_FALSE_INTERFACE
188         }
189     }
190 
191     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) {
192         if (!fFunctions.fReadBuffer) {
193             RETURN_FALSE_INTERFACE
194         }
195     }
196 
197     // glGetTexLevelParameteriv was added to ES in 3.1.
198     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,1)) {
199         if (!fFunctions.fGetTexLevelParameteriv) {
200             RETURN_FALSE_INTERFACE
201         }
202     }
203 
204     // GL_EXT_texture_storage is part of desktop 4.2
205     // There is a desktop ARB extension and an ES+desktop EXT extension
206     if (kGL_GrGLStandard == fStandard) {
207         if (glVer >= GR_GL_VER(4,2) ||
208             fExtensions.has("GL_ARB_texture_storage") ||
209             fExtensions.has("GL_EXT_texture_storage")) {
210             if (!fFunctions.fTexStorage2D) {
211                 RETURN_FALSE_INTERFACE
212             }
213         }
214     } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) {
215         if (!fFunctions.fTexStorage2D) {
216             RETURN_FALSE_INTERFACE
217         }
218     }
219 
220     // glTextureBarrier is part of desktop 4.5. There are also ARB and NV extensions.
221     if (kGL_GrGLStandard == fStandard) {
222         if (glVer >= GR_GL_VER(4,5) ||
223             fExtensions.has("GL_ARB_texture_barrier") ||
224             fExtensions.has("GL_NV_texture_barrier")) {
225             if (!fFunctions.fTextureBarrier) {
226                 RETURN_FALSE_INTERFACE
227             }
228         }
229     } else if (fExtensions.has("GL_NV_texture_barrier")) {
230         if (!fFunctions.fTextureBarrier) {
231             RETURN_FALSE_INTERFACE
232         }
233     }
234 
235     if (fExtensions.has("GL_KHR_blend_equation_advanced") ||
236         fExtensions.has("GL_NV_blend_equation_advanced")) {
237         if (!fFunctions.fBlendBarrier) {
238             RETURN_FALSE_INTERFACE
239         }
240     }
241 
242     if (fExtensions.has("GL_EXT_discard_framebuffer")) {
243         if (!fFunctions.fDiscardFramebuffer) {
244             RETURN_FALSE_INTERFACE
245         }
246     }
247 
248     // Required since OpenGL 1.5 and ES 3.0 or with GL_EXT_occlusion_query_boolean
249     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0) ||
250         fExtensions.has("GL_EXT_occlusion_query_boolean")) {
251 #if 0 // Not yet added to chrome's bindings.
252         if (!fFunctions.fGenQueries ||
253             !fFunctions.fDeleteQueries ||
254             !fFunctions.fBeginQuery ||
255             !fFunctions.fEndQuery ||
256             !fFunctions.fGetQueryiv ||
257             !fFunctions.fGetQueryObjectuiv) {
258             RETURN_FALSE_INTERFACE
259         }
260 #endif
261     }
262     // glGetQueryObjectiv doesn't exist in ES.
263     if (kGL_GrGLStandard == fStandard && !fFunctions.fGetQueryObjectiv) {
264         RETURN_FALSE_INTERFACE
265     }
266 
267     // FBO MSAA
268     if (kGL_GrGLStandard == fStandard) {
269         // GL 3.0 and the ARB extension have multisample + blit
270         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) {
271             if (!fFunctions.fRenderbufferStorageMultisample ||
272                 !fFunctions.fBlitFramebuffer) {
273                 RETURN_FALSE_INTERFACE
274             }
275         } else {
276             if (fExtensions.has("GL_EXT_framebuffer_blit") &&
277                 !fFunctions.fBlitFramebuffer) {
278                 RETURN_FALSE_INTERFACE
279             }
280             if (fExtensions.has("GL_EXT_framebuffer_multisample") &&
281                 !fFunctions.fRenderbufferStorageMultisample) {
282                 RETURN_FALSE_INTERFACE
283             }
284         }
285     } else {
286         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) {
287             if (!fFunctions.fRenderbufferStorageMultisample ||
288                 !fFunctions.fBlitFramebuffer) {
289                 RETURN_FALSE_INTERFACE
290             }
291         } else {
292             if (fExtensions.has("GL_ANGLE_framebuffer_multisample") &&
293                 !fFunctions.fRenderbufferStorageMultisample) {
294                 RETURN_FALSE_INTERFACE
295             }
296             if (fExtensions.has("GL_ANGLE_framebuffer_blit") &&
297                 !fFunctions.fBlitFramebuffer) {
298                 RETURN_FALSE_INTERFACE
299             }
300         }
301         if (fExtensions.has("GL_APPLE_framebuffer_multisample")) {
302             if (!fFunctions.fRenderbufferStorageMultisampleES2APPLE ||
303                 !fFunctions.fResolveMultisampleFramebuffer) {
304                 RETURN_FALSE_INTERFACE
305             }
306         }
307         if (fExtensions.has("GL_IMG_multisampled_render_to_texture") ||
308             fExtensions.has("GL_EXT_multisampled_render_to_texture")) {
309             if (!fFunctions.fRenderbufferStorageMultisampleES2EXT ||
310                 !fFunctions.fFramebufferTexture2DMultisample) {
311                 RETURN_FALSE_INTERFACE
312             }
313         }
314     }
315 
316     // On ES buffer mapping is an extension. On Desktop
317     // buffer mapping was part of original VBO extension
318     // which we require.
319     if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) {
320         if (!fFunctions.fMapBuffer ||
321             !fFunctions.fUnmapBuffer) {
322             RETURN_FALSE_INTERFACE
323         }
324     }
325 
326     // Dual source blending
327     if (kGL_GrGLStandard == fStandard) {
328         if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended")) {
329             if (!fFunctions.fBindFragDataLocationIndexed) {
330                 RETURN_FALSE_INTERFACE
331             }
332         }
333     } else {
334         if (glVer >= GR_GL_VER(3,0) && fExtensions.has("GL_EXT_blend_func_extended")) {
335             if (!fFunctions.fBindFragDataLocation ||
336                 !fFunctions.fBindFragDataLocationIndexed) {
337                 RETURN_FALSE_INTERFACE
338             }
339         }
340     }
341 
342 
343     // glGetStringi was added in version 3.0 of both desktop and ES.
344     if (glVer >= GR_GL_VER(3, 0)) {
345         if (!fFunctions.fGetStringi) {
346             RETURN_FALSE_INTERFACE
347         }
348     }
349 
350     // glVertexAttribIPointer was added in version 3.0 of both desktop and ES.
351     if (glVer >= GR_GL_VER(3, 0)) {
352         if (!fFunctions.fVertexAttribIPointer) {
353             RETURN_FALSE_INTERFACE
354         }
355     }
356 
357     if (kGL_GrGLStandard == fStandard) {
358         if (glVer >= GR_GL_VER(3,1)) {
359             if (!fFunctions.fTexBuffer) {
360                 RETURN_FALSE_INTERFACE;
361             }
362         }
363         if (glVer >= GR_GL_VER(4,3)) {
364             if (!fFunctions.fTexBufferRange) {
365                 RETURN_FALSE_INTERFACE;
366             }
367         }
368     } else {
369         if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_OES_texture_buffer") ||
370             fExtensions.has("GL_EXT_texture_buffer")) {
371             if (!fFunctions.fTexBuffer ||
372                 !fFunctions.fTexBufferRange) {
373                 RETURN_FALSE_INTERFACE;
374             }
375         }
376     }
377 
378     if (kGL_GrGLStandard == fStandard) {
379         if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) {
380             if (!fFunctions.fBindVertexArray ||
381                 !fFunctions.fDeleteVertexArrays ||
382                 !fFunctions.fGenVertexArrays) {
383                 RETURN_FALSE_INTERFACE
384             }
385         }
386     } else {
387         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) {
388             if (!fFunctions.fBindVertexArray ||
389                 !fFunctions.fDeleteVertexArrays ||
390                 !fFunctions.fGenVertexArrays) {
391                 RETURN_FALSE_INTERFACE
392             }
393         }
394     }
395 
396     if (fExtensions.has("GL_EXT_debug_marker")) {
397         if (!fFunctions.fInsertEventMarker ||
398             !fFunctions.fPushGroupMarker ||
399             !fFunctions.fPopGroupMarker) {
400             RETURN_FALSE_INTERFACE
401         }
402     }
403 
404     if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
405         fExtensions.has("GL_ARB_invalidate_subdata")) {
406         if (!fFunctions.fInvalidateBufferData ||
407             !fFunctions.fInvalidateBufferSubData ||
408             !fFunctions.fInvalidateFramebuffer ||
409             !fFunctions.fInvalidateSubFramebuffer ||
410             !fFunctions.fInvalidateTexImage ||
411             !fFunctions.fInvalidateTexSubImage) {
412             RETURN_FALSE_INTERFACE;
413         }
414     } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) {
415         // ES 3.0 adds the framebuffer functions but not the others.
416         if (!fFunctions.fInvalidateFramebuffer ||
417             !fFunctions.fInvalidateSubFramebuffer) {
418             RETURN_FALSE_INTERFACE;
419         }
420     }
421 
422     if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_CHROMIUM_map_sub")) {
423         if (!fFunctions.fMapBufferSubData ||
424             !fFunctions.fMapTexSubImage2D ||
425             !fFunctions.fUnmapBufferSubData ||
426             !fFunctions.fUnmapTexSubImage2D) {
427             RETURN_FALSE_INTERFACE;
428         }
429     }
430 
431     // These functions are added to the 3.0 version of both GLES and GL.
432     if (glVer >= GR_GL_VER(3,0) ||
433         (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_map_buffer_range")) ||
434         (kGL_GrGLStandard == fStandard && fExtensions.has("GL_ARB_map_buffer_range"))) {
435         if (!fFunctions.fMapBufferRange ||
436             !fFunctions.fFlushMappedBufferRange) {
437             RETURN_FALSE_INTERFACE;
438         }
439     }
440 
441     if ((kGL_GrGLStandard == fStandard &&
442          (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_texture_multisample"))) ||
443         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
444         if (!fFunctions.fGetMultisamplefv) {
445             RETURN_FALSE_INTERFACE
446         }
447     }
448 
449     if ((kGL_GrGLStandard == fStandard &&
450          (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_program_interface_query"))) ||
451         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
452         if (!fFunctions.fGetProgramResourceLocation) {
453             RETURN_FALSE_INTERFACE
454         }
455     }
456 
457     if (kGLES_GrGLStandard == fStandard || glVer >= GR_GL_VER(4,1) ||
458         fExtensions.has("GL_ARB_ES2_compatibility")) {
459         if (!fFunctions.fGetShaderPrecisionFormat) {
460             RETURN_FALSE_INTERFACE
461         }
462     }
463 
464     if (fExtensions.has("GL_NV_path_rendering") || fExtensions.has("GL_CHROMIUM_path_rendering")) {
465         if (!fFunctions.fMatrixLoadf ||
466             !fFunctions.fMatrixLoadIdentity ||
467             !fFunctions.fPathCommands ||
468             !fFunctions.fPathParameteri ||
469             !fFunctions.fPathParameterf ||
470             !fFunctions.fGenPaths ||
471             !fFunctions.fDeletePaths ||
472             !fFunctions.fIsPath ||
473             !fFunctions.fPathStencilFunc ||
474             !fFunctions.fStencilFillPath ||
475             !fFunctions.fStencilStrokePath ||
476             !fFunctions.fStencilFillPathInstanced ||
477             !fFunctions.fStencilStrokePathInstanced ||
478             !fFunctions.fCoverFillPath ||
479             !fFunctions.fCoverStrokePath ||
480             !fFunctions.fCoverFillPathInstanced ||
481             !fFunctions.fCoverStrokePathInstanced
482 #if 0
483             // List of functions that Skia uses, but which have been added since the initial release
484             // of NV_path_rendering driver. We do not want to fail interface validation due to
485             // missing features, we will just not use the extension.
486             // Update this list -> update GrGLCaps::hasPathRenderingSupport too.
487             || !fFunctions.fStencilThenCoverFillPath ||
488             !fFunctions.fStencilThenCoverStrokePath ||
489             !fFunctions.fStencilThenCoverFillPathInstanced ||
490             !fFunctions.fStencilThenCoverStrokePathInstanced ||
491             !fFunctions.fProgramPathFragmentInputGen
492 #endif
493             ) {
494             RETURN_FALSE_INTERFACE
495         }
496         if (fExtensions.has("GL_CHROMIUM_path_rendering")) {
497             if (!fFunctions.fBindFragmentInputLocation) {
498                 RETURN_FALSE_INTERFACE
499             }
500         }
501     }
502 
503     if (fExtensions.has("GL_EXT_raster_multisample")) {
504         if (!fFunctions.fRasterSamples) {
505             RETURN_FALSE_INTERFACE
506         }
507     }
508 
509     if (fExtensions.has("GL_NV_framebuffer_mixed_samples") ||
510         fExtensions.has("GL_CHROMIUM_framebuffer_mixed_samples")) {
511         if (!fFunctions.fCoverageModulation) {
512             RETURN_FALSE_INTERFACE
513         }
514     }
515 
516     if (kGL_GrGLStandard == fStandard) {
517         if (glVer >= GR_GL_VER(3,1) ||
518             fExtensions.has("GL_EXT_draw_instanced") || fExtensions.has("GL_ARB_draw_instanced")) {
519             if (!fFunctions.fDrawArraysInstanced ||
520                 !fFunctions.fDrawElementsInstanced) {
521                 RETURN_FALSE_INTERFACE
522             }
523         }
524     } else if (kGLES_GrGLStandard == fStandard) {
525         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_draw_instanced")) {
526             if (!fFunctions.fDrawArraysInstanced ||
527                 !fFunctions.fDrawElementsInstanced) {
528                 RETURN_FALSE_INTERFACE
529             }
530         }
531     }
532 
533     if (kGL_GrGLStandard == fStandard) {
534         if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_instanced_arrays")) {
535             if (!fFunctions.fVertexAttribDivisor) {
536                 RETURN_FALSE_INTERFACE
537             }
538         }
539     } else if (kGLES_GrGLStandard == fStandard) {
540         if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_instanced_arrays")) {
541             if (!fFunctions.fVertexAttribDivisor) {
542                 RETURN_FALSE_INTERFACE
543             }
544         }
545     }
546 
547     if ((kGL_GrGLStandard == fStandard &&
548          (glVer >= GR_GL_VER(4,0) || fExtensions.has("GL_ARB_draw_indirect"))) ||
549         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
550         if (!fFunctions.fDrawArraysIndirect ||
551             !fFunctions.fDrawElementsIndirect) {
552             RETURN_FALSE_INTERFACE
553         }
554     }
555 
556     if ((kGL_GrGLStandard == fStandard &&
557          (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_multi_draw_indirect"))) ||
558         (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_multi_draw_indirect"))) {
559         if (!fFunctions.fMultiDrawArraysIndirect ||
560             !fFunctions.fMultiDrawElementsIndirect) {
561             RETURN_FALSE_INTERFACE
562         }
563     }
564 
565     if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
566         fExtensions.has("GL_KHR_debug")) {
567         if (!fFunctions.fDebugMessageControl ||
568             !fFunctions.fDebugMessageInsert ||
569             !fFunctions.fDebugMessageCallback ||
570             !fFunctions.fGetDebugMessageLog ||
571             !fFunctions.fPushDebugGroup ||
572             !fFunctions.fPopDebugGroup ||
573             !fFunctions.fObjectLabel) {
574             RETURN_FALSE_INTERFACE
575         }
576     }
577 
578     if (fExtensions.has("GL_EXT_window_rectangles")) {
579         if (!fFunctions.fWindowRectangles) {
580             RETURN_FALSE_INTERFACE
581         }
582     }
583 
584     if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,0)) ||
585         fExtensions.has("GL_ARB_sample_shading")) {
586         if (!fFunctions.fMinSampleShading) {
587             RETURN_FALSE_INTERFACE
588         }
589     } else if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_OES_sample_shading")) {
590         if (!fFunctions.fMinSampleShading) {
591             RETURN_FALSE_INTERFACE
592         }
593     }
594 
595     if (kGL_GrGLStandard == fStandard) {
596         if (glVer >= GR_GL_VER(3, 2) || fExtensions.has("GL_ARB_sync")) {
597             if (!fFunctions.fFenceSync ||
598                 !fFunctions.fIsSync ||
599                 !fFunctions.fClientWaitSync ||
600                 !fFunctions.fWaitSync ||
601                 !fFunctions.fDeleteSync) {
602                 RETURN_FALSE_INTERFACE
603             }
604         }
605     } else if (kGLES_GrGLStandard == fStandard) {
606         if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_APPLE_sync")) {
607             if (!fFunctions.fFenceSync ||
608                 !fFunctions.fIsSync ||
609                 !fFunctions.fClientWaitSync ||
610                 !fFunctions.fWaitSync ||
611                 !fFunctions.fDeleteSync) {
612                 RETURN_FALSE_INTERFACE
613             }
614         }
615     }
616 
617     if (fExtensions.has("EGL_KHR_image") || fExtensions.has("EGL_KHR_image_base")) {
618         if (!fFunctions.fEGLCreateImage ||
619             !fFunctions.fEGLDestroyImage) {
620             RETURN_FALSE_INTERFACE
621         }
622     }
623 
624     // glDrawRangeElements was added to ES in 3.0.
625     if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) {
626         if (!fFunctions.fDrawRangeElements) {
627             RETURN_FALSE_INTERFACE;
628         }
629     }
630 
631     // getInternalformativ was added in GL 4.2, ES 3.0, and with extension ARB_internalformat_query
632     if ((kGL_GrGLStandard == fStandard &&
633          (glVer >= GR_GL_VER(4,2) || fExtensions.has("GL_ARB_internalformat_query"))) ||
634         (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0))) {
635         if (!fFunctions.fGetInternalformativ) {
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.fGetProgramBinary ||
643             !fFunctions.fProgramBinary ||
644             !fFunctions.fProgramParameteri) {
645             RETURN_FALSE_INTERFACE;
646         }
647     }
648 
649     return true;
650 }
651