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
15const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface* interface,
16                                                     GrGLInsertEventMarkerProc insertEventMarkerFn,
17                                                     GrGLPushGroupMarkerProc pushGroupMarkerFn,
18                                                     GrGLPopGroupMarkerProc popGroupMarkerFn) {
19    GrGLInterface* newInterface = GrGLInterface::NewClone(interface);
20
21    if (!newInterface->fExtensions.has("GL_EXT_debug_marker")) {
22        newInterface->fExtensions.add("GL_EXT_debug_marker");
23    }
24
25    newInterface->fFunctions.fInsertEventMarker = insertEventMarkerFn;
26    newInterface->fFunctions.fPushGroupMarker = pushGroupMarkerFn;
27    newInterface->fFunctions.fPopGroupMarker = popGroupMarkerFn;
28
29    return newInterface;
30}
31
32GrGLInterface::GrGLInterface() {
33    fStandard = kNone_GrGLStandard;
34}
35
36GrGLInterface* GrGLInterface::NewClone(const GrGLInterface* interface) {
37    SkASSERT(interface);
38
39    GrGLInterface* clone = new GrGLInterface;
40    clone->fStandard = interface->fStandard;
41    clone->fExtensions = interface->fExtensions;
42    clone->fFunctions = interface->fFunctions;
43    return clone;
44}
45
46#ifdef SK_DEBUG
47    static int kIsDebug = 1;
48#else
49    static int kIsDebug = 0;
50#endif
51
52#define RETURN_FALSE_INTERFACE                                                                   \
53    if (kIsDebug) { SkDebugf("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); } \
54    return false;
55
56bool GrGLInterface::validate() const {
57
58    if (kNone_GrGLStandard == fStandard) {
59        RETURN_FALSE_INTERFACE
60    }
61
62    if (!fExtensions.isInitialized()) {
63        RETURN_FALSE_INTERFACE
64    }
65
66    // functions that are always required
67    if (nullptr == fFunctions.fActiveTexture ||
68        nullptr == fFunctions.fAttachShader ||
69        nullptr == fFunctions.fBindAttribLocation ||
70        nullptr == fFunctions.fBindBuffer ||
71        nullptr == fFunctions.fBindTexture ||
72        nullptr == fFunctions.fBlendColor ||      // -> GL >= 1.4 or extension, ES >= 2.0
73        nullptr == fFunctions.fBlendEquation ||   // -> GL >= 1.4 or extension, ES >= 2.0
74        nullptr == fFunctions.fBlendFunc ||
75        nullptr == fFunctions.fBufferData ||
76        nullptr == fFunctions.fBufferSubData ||
77        nullptr == fFunctions.fClear ||
78        nullptr == fFunctions.fClearColor ||
79        nullptr == fFunctions.fClearStencil ||
80        nullptr == fFunctions.fColorMask ||
81        nullptr == fFunctions.fCompileShader ||
82        nullptr == fFunctions.fCopyTexSubImage2D ||
83        nullptr == fFunctions.fCreateProgram ||
84        nullptr == fFunctions.fCreateShader ||
85        nullptr == fFunctions.fCullFace ||
86        nullptr == fFunctions.fDeleteBuffers ||
87        nullptr == fFunctions.fDeleteProgram ||
88        nullptr == fFunctions.fDeleteShader ||
89        nullptr == fFunctions.fDeleteTextures ||
90        nullptr == fFunctions.fDepthMask ||
91        nullptr == fFunctions.fDisable ||
92        nullptr == fFunctions.fDisableVertexAttribArray ||
93        nullptr == fFunctions.fDrawArrays ||
94        nullptr == fFunctions.fDrawElements ||
95        nullptr == fFunctions.fEnable ||
96        nullptr == fFunctions.fEnableVertexAttribArray ||
97        nullptr == fFunctions.fFrontFace ||
98        nullptr == fFunctions.fGenBuffers ||
99        nullptr == fFunctions.fGenTextures ||
100        nullptr == fFunctions.fGetBufferParameteriv ||
101        nullptr == fFunctions.fGenerateMipmap ||
102        nullptr == fFunctions.fGetError ||
103        nullptr == fFunctions.fGetIntegerv ||
104        nullptr == fFunctions.fGetProgramInfoLog ||
105        nullptr == fFunctions.fGetProgramiv ||
106        nullptr == fFunctions.fGetShaderInfoLog ||
107        nullptr == fFunctions.fGetShaderiv ||
108        nullptr == fFunctions.fGetString ||
109        nullptr == fFunctions.fGetUniformLocation ||
110#if 0 //  Not included in Chrome yet
111        nullptr == fFunctions.fIsTexture ||
112#endif
113        nullptr == fFunctions.fLinkProgram ||
114        nullptr == fFunctions.fLineWidth ||
115        nullptr == fFunctions.fPixelStorei ||
116        nullptr == fFunctions.fReadPixels ||
117        nullptr == fFunctions.fScissor ||
118        nullptr == fFunctions.fShaderSource ||
119        nullptr == fFunctions.fStencilFunc ||
120        nullptr == fFunctions.fStencilMask ||
121        nullptr == fFunctions.fStencilOp ||
122        nullptr == fFunctions.fTexImage2D ||
123        nullptr == fFunctions.fTexParameteri ||
124        nullptr == fFunctions.fTexParameteriv ||
125        nullptr == fFunctions.fTexSubImage2D ||
126        nullptr == fFunctions.fUniform1f ||
127        nullptr == fFunctions.fUniform1i ||
128        nullptr == fFunctions.fUniform1fv ||
129        nullptr == fFunctions.fUniform1iv ||
130        nullptr == fFunctions.fUniform2f ||
131        nullptr == fFunctions.fUniform2i ||
132        nullptr == fFunctions.fUniform2fv ||
133        nullptr == fFunctions.fUniform2iv ||
134        nullptr == fFunctions.fUniform3f ||
135        nullptr == fFunctions.fUniform3i ||
136        nullptr == fFunctions.fUniform3fv ||
137        nullptr == fFunctions.fUniform3iv ||
138        nullptr == fFunctions.fUniform4f ||
139        nullptr == fFunctions.fUniform4i ||
140        nullptr == fFunctions.fUniform4fv ||
141        nullptr == fFunctions.fUniform4iv ||
142        nullptr == fFunctions.fUniformMatrix2fv ||
143        nullptr == fFunctions.fUniformMatrix3fv ||
144        nullptr == fFunctions.fUniformMatrix4fv ||
145        nullptr == fFunctions.fUseProgram ||
146        nullptr == fFunctions.fVertexAttrib1f ||
147        nullptr == fFunctions.fVertexAttrib2fv ||
148        nullptr == fFunctions.fVertexAttrib3fv ||
149        nullptr == fFunctions.fVertexAttrib4fv ||
150        nullptr == fFunctions.fVertexAttribPointer ||
151        nullptr == fFunctions.fViewport ||
152        nullptr == fFunctions.fBindFramebuffer ||
153        nullptr == fFunctions.fBindRenderbuffer ||
154        nullptr == fFunctions.fCheckFramebufferStatus ||
155        nullptr == fFunctions.fDeleteFramebuffers ||
156        nullptr == fFunctions.fDeleteRenderbuffers ||
157        nullptr == fFunctions.fFinish ||
158        nullptr == fFunctions.fFlush ||
159        nullptr == fFunctions.fFramebufferRenderbuffer ||
160        nullptr == fFunctions.fFramebufferTexture2D ||
161        nullptr == fFunctions.fGetFramebufferAttachmentParameteriv ||
162        nullptr == fFunctions.fGetRenderbufferParameteriv ||
163        nullptr == fFunctions.fGenFramebuffers ||
164        nullptr == fFunctions.fGenRenderbuffers ||
165        nullptr == fFunctions.fRenderbufferStorage) {
166        RETURN_FALSE_INTERFACE
167    }
168
169    GrGLVersion glVer = GrGLGetVersion(this);
170    if (GR_GL_INVALID_VER == glVer) {
171        RETURN_FALSE_INTERFACE
172    }
173
174    // Now check that baseline ES/Desktop fns not covered above are present
175    // and that we have fn pointers for any advertised fExtensions that we will
176    // try to use.
177
178    // these functions are part of ES2, we assume they are available
179    // On the desktop we assume they are available if the extension
180    // is present or GL version is high enough.
181    if (kGLES_GrGLStandard == fStandard) {
182        if (nullptr == fFunctions.fStencilFuncSeparate ||
183            nullptr == fFunctions.fStencilMaskSeparate ||
184            nullptr == fFunctions.fStencilOpSeparate) {
185            RETURN_FALSE_INTERFACE
186        }
187    } else if (kGL_GrGLStandard == fStandard) {
188
189        if (glVer >= GR_GL_VER(2,0)) {
190            if (nullptr == fFunctions.fStencilFuncSeparate ||
191                nullptr == fFunctions.fStencilMaskSeparate ||
192                nullptr == fFunctions.fStencilOpSeparate) {
193                RETURN_FALSE_INTERFACE
194            }
195        }
196        if (glVer >= GR_GL_VER(3,0) && nullptr == fFunctions.fBindFragDataLocation) {
197            RETURN_FALSE_INTERFACE
198        }
199        if (glVer >= GR_GL_VER(2,0) || fExtensions.has("GL_ARB_draw_buffers")) {
200            if (nullptr == fFunctions.fDrawBuffers) {
201                RETURN_FALSE_INTERFACE
202            }
203        }
204
205        if (glVer >= GR_GL_VER(1,5) || fExtensions.has("GL_ARB_occlusion_query")) {
206            if (nullptr == fFunctions.fGenQueries ||
207                nullptr == fFunctions.fDeleteQueries ||
208                nullptr == fFunctions.fBeginQuery ||
209                nullptr == fFunctions.fEndQuery ||
210                nullptr == fFunctions.fGetQueryiv ||
211                nullptr == fFunctions.fGetQueryObjectiv ||
212                nullptr == fFunctions.fGetQueryObjectuiv) {
213                RETURN_FALSE_INTERFACE
214            }
215        }
216        if (glVer >= GR_GL_VER(3,3) ||
217            fExtensions.has("GL_ARB_timer_query") ||
218            fExtensions.has("GL_EXT_timer_query")) {
219            if (nullptr == fFunctions.fGetQueryObjecti64v ||
220                nullptr == fFunctions.fGetQueryObjectui64v) {
221                RETURN_FALSE_INTERFACE
222            }
223        }
224        if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) {
225            if (nullptr == fFunctions.fQueryCounter) {
226                RETURN_FALSE_INTERFACE
227            }
228        }
229    }
230
231    // optional function on desktop before 1.3
232    if (kGL_GrGLStandard != fStandard ||
233        (glVer >= GR_GL_VER(1,3)) ||
234        fExtensions.has("GL_ARB_texture_compression")) {
235        if (nullptr == fFunctions.fCompressedTexImage2D
236#if 0
237            || nullptr == fFunctions.fCompressedTexSubImage2D
238#endif
239            ) {
240            RETURN_FALSE_INTERFACE
241        }
242    }
243
244    // part of desktop GL, but not ES
245    if (kGL_GrGLStandard == fStandard &&
246        (nullptr == fFunctions.fGetTexLevelParameteriv ||
247         nullptr == fFunctions.fDrawBuffer ||
248         nullptr == fFunctions.fReadBuffer)) {
249        RETURN_FALSE_INTERFACE
250    }
251
252    // GL_EXT_texture_storage is part of desktop 4.2
253    // There is a desktop ARB extension and an ES+desktop EXT extension
254    if (kGL_GrGLStandard == fStandard) {
255        if (glVer >= GR_GL_VER(4,2) ||
256            fExtensions.has("GL_ARB_texture_storage") ||
257            fExtensions.has("GL_EXT_texture_storage")) {
258            if (nullptr == fFunctions.fTexStorage2D) {
259                RETURN_FALSE_INTERFACE
260            }
261        }
262    } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) {
263        if (nullptr == fFunctions.fTexStorage2D) {
264            RETURN_FALSE_INTERFACE
265        }
266    }
267
268    // glTextureBarrier is part of desktop 4.5. There are also ARB and NV extensions.
269    if (kGL_GrGLStandard == fStandard) {
270        if (glVer >= GR_GL_VER(4,5) ||
271            fExtensions.has("GL_ARB_texture_barrier") ||
272            fExtensions.has("GL_NV_texture_barrier")) {
273            if (nullptr == fFunctions.fTextureBarrier) {
274                RETURN_FALSE_INTERFACE
275            }
276        }
277    } else if (fExtensions.has("GL_NV_texture_barrier")) {
278        if (nullptr == fFunctions.fTextureBarrier) {
279            RETURN_FALSE_INTERFACE
280        }
281    }
282
283    if (fExtensions.has("GL_KHR_blend_equation_advanced") ||
284        fExtensions.has("GL_NV_blend_equation_advanced")) {
285        if (nullptr == fFunctions.fBlendBarrier) {
286            RETURN_FALSE_INTERFACE
287        }
288    }
289
290    if (fExtensions.has("GL_EXT_discard_framebuffer")) {
291        if (nullptr == fFunctions.fDiscardFramebuffer) {
292            RETURN_FALSE_INTERFACE
293        }
294    }
295
296    // FBO MSAA
297    if (kGL_GrGLStandard == fStandard) {
298        // GL 3.0 and the ARB extension have multisample + blit
299        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) {
300            if (nullptr == fFunctions.fRenderbufferStorageMultisample ||
301                nullptr == fFunctions.fBlitFramebuffer) {
302                RETURN_FALSE_INTERFACE
303            }
304        } else {
305            if (fExtensions.has("GL_EXT_framebuffer_blit") &&
306                nullptr == fFunctions.fBlitFramebuffer) {
307                RETURN_FALSE_INTERFACE
308            }
309            if (fExtensions.has("GL_EXT_framebuffer_multisample") &&
310                nullptr == fFunctions.fRenderbufferStorageMultisample) {
311                RETURN_FALSE_INTERFACE
312            }
313        }
314    } else {
315        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) {
316            if (nullptr == fFunctions.fRenderbufferStorageMultisample ||
317                nullptr == fFunctions.fBlitFramebuffer) {
318                RETURN_FALSE_INTERFACE
319            }
320        } else {
321            if (fExtensions.has("GL_ANGLE_framebuffer_multisample") &&
322                nullptr == fFunctions.fRenderbufferStorageMultisample) {
323                RETURN_FALSE_INTERFACE
324            }
325            if (fExtensions.has("GL_ANGLE_framebuffer_blit") &&
326                nullptr == fFunctions.fBlitFramebuffer) {
327                RETURN_FALSE_INTERFACE
328            }
329        }
330        if (fExtensions.has("GL_APPLE_framebuffer_multisample")) {
331            if (nullptr == fFunctions.fRenderbufferStorageMultisampleES2APPLE ||
332                nullptr == fFunctions.fResolveMultisampleFramebuffer) {
333                RETURN_FALSE_INTERFACE
334            }
335        }
336        if (fExtensions.has("GL_IMG_multisampled_render_to_texture") ||
337            fExtensions.has("GL_EXT_multisampled_render_to_texture")) {
338            if (nullptr == fFunctions.fRenderbufferStorageMultisampleES2EXT ||
339                nullptr == fFunctions.fFramebufferTexture2DMultisample) {
340                RETURN_FALSE_INTERFACE
341            }
342        }
343    }
344
345    // On ES buffer mapping is an extension. On Desktop
346    // buffer mapping was part of original VBO extension
347    // which we require.
348    if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) {
349        if (nullptr == fFunctions.fMapBuffer ||
350            nullptr == fFunctions.fUnmapBuffer) {
351            RETURN_FALSE_INTERFACE
352        }
353    }
354
355    // Dual source blending
356    if (kGL_GrGLStandard == fStandard) {
357        if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended")) {
358            if (nullptr == fFunctions.fBindFragDataLocationIndexed) {
359                RETURN_FALSE_INTERFACE
360            }
361        }
362    } else {
363        if (glVer >= GR_GL_VER(3,0) && fExtensions.has("GL_EXT_blend_func_extended")) {
364            if (nullptr == fFunctions.fBindFragDataLocation ||
365                nullptr == fFunctions.fBindFragDataLocationIndexed) {
366                RETURN_FALSE_INTERFACE
367            }
368        }
369    }
370
371
372    // glGetStringi was added in version 3.0 of both desktop and ES.
373    if (glVer >= GR_GL_VER(3, 0)) {
374        if (nullptr == fFunctions.fGetStringi) {
375            RETURN_FALSE_INTERFACE
376        }
377    }
378
379    // glVertexAttribIPointer was added in version 3.0 of both desktop and ES.
380    if (glVer >= GR_GL_VER(3, 0)) {
381        if (NULL == fFunctions.fVertexAttribIPointer) {
382            RETURN_FALSE_INTERFACE
383        }
384    }
385
386    if (kGL_GrGLStandard == fStandard) {
387        if (glVer >= GR_GL_VER(3,1)) {
388            if (nullptr == fFunctions.fTexBuffer) {
389                RETURN_FALSE_INTERFACE;
390            }
391        }
392        if (glVer >= GR_GL_VER(4,3)) {
393            if (nullptr == fFunctions.fTexBufferRange) {
394                RETURN_FALSE_INTERFACE;
395            }
396        }
397    } else {
398        if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_OES_texture_buffer") ||
399            fExtensions.has("GL_EXT_texture_buffer")) {
400            if (nullptr == fFunctions.fTexBuffer ||
401                nullptr == fFunctions.fTexBufferRange) {
402                RETURN_FALSE_INTERFACE;
403            }
404        }
405    }
406
407    if (kGL_GrGLStandard == fStandard) {
408        if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) {
409            if (nullptr == fFunctions.fBindVertexArray ||
410                nullptr == fFunctions.fDeleteVertexArrays ||
411                nullptr == fFunctions.fGenVertexArrays) {
412                RETURN_FALSE_INTERFACE
413            }
414        }
415    } else {
416        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) {
417            if (nullptr == fFunctions.fBindVertexArray ||
418                nullptr == fFunctions.fDeleteVertexArrays ||
419                nullptr == fFunctions.fGenVertexArrays) {
420                RETURN_FALSE_INTERFACE
421            }
422        }
423    }
424
425    if (fExtensions.has("GL_EXT_debug_marker")) {
426        if (nullptr == fFunctions.fInsertEventMarker ||
427            nullptr == fFunctions.fPushGroupMarker ||
428            nullptr == fFunctions.fPopGroupMarker) {
429            RETURN_FALSE_INTERFACE
430        }
431    }
432
433    if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
434        fExtensions.has("GL_ARB_invalidate_subdata")) {
435        if (nullptr == fFunctions.fInvalidateBufferData ||
436            nullptr == fFunctions.fInvalidateBufferSubData ||
437            nullptr == fFunctions.fInvalidateFramebuffer ||
438            nullptr == fFunctions.fInvalidateSubFramebuffer ||
439            nullptr == fFunctions.fInvalidateTexImage ||
440            nullptr == fFunctions.fInvalidateTexSubImage) {
441            RETURN_FALSE_INTERFACE;
442        }
443    } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) {
444        // ES 3.0 adds the framebuffer functions but not the others.
445        if (nullptr == fFunctions.fInvalidateFramebuffer ||
446            nullptr == fFunctions.fInvalidateSubFramebuffer) {
447            RETURN_FALSE_INTERFACE;
448        }
449    }
450
451    if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_CHROMIUM_map_sub")) {
452        if (nullptr == fFunctions.fMapBufferSubData ||
453            nullptr == fFunctions.fMapTexSubImage2D ||
454            nullptr == fFunctions.fUnmapBufferSubData ||
455            nullptr == fFunctions.fUnmapTexSubImage2D) {
456            RETURN_FALSE_INTERFACE;
457        }
458    }
459
460    // These functions are added to the 3.0 version of both GLES and GL.
461    if (glVer >= GR_GL_VER(3,0) ||
462        (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_map_buffer_range")) ||
463        (kGL_GrGLStandard == fStandard && fExtensions.has("GL_ARB_map_buffer_range"))) {
464        if (nullptr == fFunctions.fMapBufferRange ||
465            nullptr == fFunctions.fFlushMappedBufferRange) {
466            RETURN_FALSE_INTERFACE;
467        }
468    }
469
470    if ((kGL_GrGLStandard == fStandard &&
471         (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_texture_multisample"))) ||
472        (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
473        if (NULL == fFunctions.fGetMultisamplefv) {
474            RETURN_FALSE_INTERFACE
475        }
476    }
477
478    if ((kGL_GrGLStandard == fStandard &&
479         (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_program_interface_query"))) ||
480        (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
481        if (nullptr == fFunctions.fGetProgramResourceLocation) {
482            RETURN_FALSE_INTERFACE
483        }
484    }
485
486    if (kGLES_GrGLStandard == fStandard || glVer >= GR_GL_VER(4,1) ||
487        fExtensions.has("GL_ARB_ES2_compatibility")) {
488        if (nullptr == fFunctions.fGetShaderPrecisionFormat) {
489            RETURN_FALSE_INTERFACE
490        }
491    }
492
493    if (fExtensions.has("GL_NV_path_rendering") || fExtensions.has("GL_CHROMIUM_path_rendering")) {
494        if (nullptr == fFunctions.fMatrixLoadf ||
495            nullptr == fFunctions.fMatrixLoadIdentity ||
496            nullptr == fFunctions.fPathCommands ||
497            nullptr == fFunctions.fPathParameteri ||
498            nullptr == fFunctions.fPathParameterf ||
499            nullptr == fFunctions.fGenPaths ||
500            nullptr == fFunctions.fDeletePaths ||
501            nullptr == fFunctions.fIsPath ||
502            nullptr == fFunctions.fPathStencilFunc ||
503            nullptr == fFunctions.fStencilFillPath ||
504            nullptr == fFunctions.fStencilStrokePath ||
505            nullptr == fFunctions.fStencilFillPathInstanced ||
506            nullptr == fFunctions.fStencilStrokePathInstanced ||
507            nullptr == fFunctions.fCoverFillPath ||
508            nullptr == fFunctions.fCoverStrokePath ||
509            nullptr == fFunctions.fCoverFillPathInstanced ||
510            nullptr == fFunctions.fCoverStrokePathInstanced
511#if 0
512            // List of functions that Skia uses, but which have been added since the initial release
513            // of NV_path_rendering driver. We do not want to fail interface validation due to
514            // missing features, we will just not use the extension.
515            // Update this list -> update GrGLCaps::hasPathRenderingSupport too.
516            || nullptr == fFunctions.fStencilThenCoverFillPath ||
517            nullptr == fFunctions.fStencilThenCoverStrokePath ||
518            nullptr == fFunctions.fStencilThenCoverFillPathInstanced ||
519            nullptr == fFunctions.fStencilThenCoverStrokePathInstanced ||
520            nullptr == fFunctions.fProgramPathFragmentInputGen
521#endif
522            ) {
523            RETURN_FALSE_INTERFACE
524        }
525        if (fExtensions.has("GL_CHROMIUM_path_rendering")) {
526            if (nullptr == fFunctions.fBindFragmentInputLocation) {
527                RETURN_FALSE_INTERFACE
528            }
529        }
530    }
531
532    if (fExtensions.has("GL_EXT_raster_multisample")) {
533        if (nullptr == fFunctions.fRasterSamples) {
534            RETURN_FALSE_INTERFACE
535        }
536    }
537
538    if (fExtensions.has("GL_NV_framebuffer_mixed_samples") ||
539        fExtensions.has("GL_CHROMIUM_framebuffer_mixed_samples")) {
540        if (nullptr == fFunctions.fCoverageModulation) {
541            RETURN_FALSE_INTERFACE
542        }
543    }
544
545    if (kGL_GrGLStandard == fStandard) {
546        if (glVer >= GR_GL_VER(3,1) ||
547            fExtensions.has("GL_EXT_draw_instanced") || fExtensions.has("GL_ARB_draw_instanced")) {
548            if (nullptr == fFunctions.fDrawArraysInstanced ||
549                nullptr == fFunctions.fDrawElementsInstanced) {
550                RETURN_FALSE_INTERFACE
551            }
552        }
553    } else if (kGLES_GrGLStandard == fStandard) {
554        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_draw_instanced")) {
555            if (nullptr == fFunctions.fDrawArraysInstanced ||
556                nullptr == fFunctions.fDrawElementsInstanced) {
557                RETURN_FALSE_INTERFACE
558            }
559        }
560    }
561
562    if (kGL_GrGLStandard == fStandard) {
563        if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_instanced_arrays")) {
564            if (nullptr == fFunctions.fVertexAttribDivisor) {
565                RETURN_FALSE_INTERFACE
566            }
567        }
568    } else if (kGLES_GrGLStandard == fStandard) {
569        if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_instanced_arrays")) {
570            if (nullptr == fFunctions.fVertexAttribDivisor) {
571                RETURN_FALSE_INTERFACE
572            }
573        }
574    }
575
576    if ((kGL_GrGLStandard == fStandard &&
577         (glVer >= GR_GL_VER(4,0) || fExtensions.has("GL_ARB_draw_indirect"))) ||
578        (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) {
579        if (NULL == fFunctions.fDrawArraysIndirect ||
580            NULL == fFunctions.fDrawElementsIndirect) {
581            RETURN_FALSE_INTERFACE
582        }
583    }
584
585    if ((kGL_GrGLStandard == fStandard &&
586         (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_multi_draw_indirect"))) ||
587        (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_multi_draw_indirect"))) {
588        if (NULL == fFunctions.fMultiDrawArraysIndirect ||
589            NULL == fFunctions.fMultiDrawElementsIndirect) {
590            RETURN_FALSE_INTERFACE
591        }
592    }
593
594    if (fExtensions.has("GL_NV_bindless_texture")) {
595        if (nullptr == fFunctions.fGetTextureHandle ||
596            nullptr == fFunctions.fGetTextureSamplerHandle ||
597            nullptr == fFunctions.fMakeTextureHandleResident ||
598            nullptr == fFunctions.fMakeTextureHandleNonResident ||
599            nullptr == fFunctions.fGetImageHandle ||
600            nullptr == fFunctions.fMakeImageHandleResident ||
601            nullptr == fFunctions.fMakeImageHandleNonResident ||
602            nullptr == fFunctions.fIsTextureHandleResident ||
603            nullptr == fFunctions.fIsImageHandleResident ||
604            nullptr == fFunctions.fUniformHandleui64 ||
605            nullptr == fFunctions.fUniformHandleui64v ||
606            nullptr == fFunctions.fProgramUniformHandleui64 ||
607            nullptr == fFunctions.fProgramUniformHandleui64v) {
608            RETURN_FALSE_INTERFACE
609        }
610    }
611
612    if (kGL_GrGLStandard == fStandard && fExtensions.has("GL_EXT_direct_state_access")) {
613        if (nullptr == fFunctions.fTextureParameteri ||
614            nullptr == fFunctions.fTextureParameteriv ||
615            nullptr == fFunctions.fTextureParameterf ||
616            nullptr == fFunctions.fTextureParameterfv ||
617            nullptr == fFunctions.fTextureImage1D ||
618            nullptr == fFunctions.fTextureImage2D ||
619            nullptr == fFunctions.fTextureSubImage1D ||
620            nullptr == fFunctions.fTextureSubImage2D ||
621            nullptr == fFunctions.fCopyTextureImage1D ||
622            nullptr == fFunctions.fCopyTextureImage2D ||
623            nullptr == fFunctions.fCopyTextureSubImage1D ||
624            nullptr == fFunctions.fCopyTextureSubImage2D ||
625            nullptr == fFunctions.fGetTextureImage ||
626            nullptr == fFunctions.fGetTextureParameterfv ||
627            nullptr == fFunctions.fGetTextureParameteriv ||
628            nullptr == fFunctions.fGetTextureLevelParameterfv ||
629            nullptr == fFunctions.fGetTextureLevelParameteriv) {
630            RETURN_FALSE_INTERFACE
631        }
632        if (glVer >= GR_GL_VER(1,2)) {
633            if (nullptr == fFunctions.fTextureImage3D ||
634                nullptr == fFunctions.fTextureSubImage3D ||
635                nullptr == fFunctions.fCopyTextureSubImage3D ||
636                nullptr == fFunctions.fCompressedTextureImage3D ||
637                nullptr == fFunctions.fCompressedTextureImage2D ||
638                nullptr == fFunctions.fCompressedTextureImage1D ||
639                nullptr == fFunctions.fCompressedTextureSubImage3D ||
640                nullptr == fFunctions.fCompressedTextureSubImage2D ||
641                nullptr == fFunctions.fCompressedTextureSubImage1D ||
642                nullptr == fFunctions.fGetCompressedTextureImage) {
643                RETURN_FALSE_INTERFACE
644            }
645        }
646        if (glVer >= GR_GL_VER(1,5)) {
647            if (nullptr == fFunctions.fNamedBufferData ||
648                nullptr == fFunctions.fNamedBufferSubData ||
649                nullptr == fFunctions.fMapNamedBuffer ||
650                nullptr == fFunctions.fUnmapNamedBuffer ||
651                nullptr == fFunctions.fGetNamedBufferParameteriv ||
652                nullptr == fFunctions.fGetNamedBufferPointerv ||
653                nullptr == fFunctions.fGetNamedBufferSubData) {
654                RETURN_FALSE_INTERFACE
655            }
656        }
657        if (glVer >= GR_GL_VER(2,0)) {
658            if (nullptr == fFunctions.fProgramUniform1f ||
659                nullptr == fFunctions.fProgramUniform2f ||
660                nullptr == fFunctions.fProgramUniform3f ||
661                nullptr == fFunctions.fProgramUniform4f ||
662                nullptr == fFunctions.fProgramUniform1i ||
663                nullptr == fFunctions.fProgramUniform2i ||
664                nullptr == fFunctions.fProgramUniform3i ||
665                nullptr == fFunctions.fProgramUniform4i ||
666                nullptr == fFunctions.fProgramUniform1fv ||
667                nullptr == fFunctions.fProgramUniform2fv ||
668                nullptr == fFunctions.fProgramUniform3fv ||
669                nullptr == fFunctions.fProgramUniform4fv ||
670                nullptr == fFunctions.fProgramUniform1iv ||
671                nullptr == fFunctions.fProgramUniform2iv ||
672                nullptr == fFunctions.fProgramUniform3iv ||
673                nullptr == fFunctions.fProgramUniform4iv ||
674                nullptr == fFunctions.fProgramUniformMatrix2fv ||
675                nullptr == fFunctions.fProgramUniformMatrix3fv ||
676                nullptr == fFunctions.fProgramUniformMatrix4fv) {
677                RETURN_FALSE_INTERFACE
678            }
679        }
680        if (glVer >= GR_GL_VER(2,1)) {
681            if (nullptr == fFunctions.fProgramUniformMatrix2x3fv ||
682                nullptr == fFunctions.fProgramUniformMatrix3x2fv ||
683                nullptr == fFunctions.fProgramUniformMatrix2x4fv ||
684                nullptr == fFunctions.fProgramUniformMatrix4x2fv ||
685                nullptr == fFunctions.fProgramUniformMatrix3x4fv ||
686                nullptr == fFunctions.fProgramUniformMatrix4x3fv) {
687                RETURN_FALSE_INTERFACE
688            }
689        }
690        if (glVer >= GR_GL_VER(3,0)) {
691            if (nullptr == fFunctions.fNamedRenderbufferStorage ||
692                nullptr == fFunctions.fGetNamedRenderbufferParameteriv ||
693                nullptr == fFunctions.fNamedRenderbufferStorageMultisample ||
694                nullptr == fFunctions.fCheckNamedFramebufferStatus ||
695                nullptr == fFunctions.fNamedFramebufferTexture1D ||
696                nullptr == fFunctions.fNamedFramebufferTexture2D ||
697                nullptr == fFunctions.fNamedFramebufferTexture3D ||
698                nullptr == fFunctions.fNamedFramebufferRenderbuffer ||
699                nullptr == fFunctions.fGetNamedFramebufferAttachmentParameteriv ||
700                nullptr == fFunctions.fGenerateTextureMipmap ||
701                nullptr == fFunctions.fFramebufferDrawBuffer ||
702                nullptr == fFunctions.fFramebufferDrawBuffers ||
703                nullptr == fFunctions.fFramebufferReadBuffer ||
704                nullptr == fFunctions.fGetFramebufferParameteriv ||
705                nullptr == fFunctions.fNamedCopyBufferSubData ||
706                nullptr == fFunctions.fVertexArrayVertexOffset ||
707                nullptr == fFunctions.fVertexArrayColorOffset ||
708                nullptr == fFunctions.fVertexArrayEdgeFlagOffset ||
709                nullptr == fFunctions.fVertexArrayIndexOffset ||
710                nullptr == fFunctions.fVertexArrayNormalOffset ||
711                nullptr == fFunctions.fVertexArrayTexCoordOffset ||
712                nullptr == fFunctions.fVertexArrayMultiTexCoordOffset ||
713                nullptr == fFunctions.fVertexArrayFogCoordOffset ||
714                nullptr == fFunctions.fVertexArraySecondaryColorOffset ||
715                nullptr == fFunctions.fVertexArrayVertexAttribOffset ||
716                nullptr == fFunctions.fVertexArrayVertexAttribIOffset ||
717                nullptr == fFunctions.fEnableVertexArray ||
718                nullptr == fFunctions.fDisableVertexArray ||
719                nullptr == fFunctions.fEnableVertexArrayAttrib ||
720                nullptr == fFunctions.fDisableVertexArrayAttrib ||
721                nullptr == fFunctions.fGetVertexArrayIntegerv ||
722                nullptr == fFunctions.fGetVertexArrayPointerv ||
723                nullptr == fFunctions.fGetVertexArrayIntegeri_v ||
724                nullptr == fFunctions.fGetVertexArrayPointeri_v ||
725                nullptr == fFunctions.fMapNamedBufferRange ||
726                nullptr == fFunctions.fFlushMappedNamedBufferRange) {
727                RETURN_FALSE_INTERFACE
728            }
729        }
730        if (glVer >= GR_GL_VER(3,1)) {
731            if (nullptr == fFunctions.fTextureBuffer) {
732                RETURN_FALSE_INTERFACE;
733            }
734        }
735    }
736
737    if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) ||
738        fExtensions.has("GL_KHR_debug")) {
739        if (nullptr == fFunctions.fDebugMessageControl ||
740            nullptr == fFunctions.fDebugMessageInsert ||
741            nullptr == fFunctions.fDebugMessageCallback ||
742            nullptr == fFunctions.fGetDebugMessageLog ||
743            nullptr == fFunctions.fPushDebugGroup ||
744            nullptr == fFunctions.fPopDebugGroup ||
745            nullptr == fFunctions.fObjectLabel) {
746            RETURN_FALSE_INTERFACE
747        }
748    }
749
750    if (fExtensions.has("GL_EXT_window_rectangles")) {
751        if (nullptr == fFunctions.fWindowRectangles) {
752            RETURN_FALSE_INTERFACE
753        }
754    }
755
756    if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,0)) ||
757        fExtensions.has("GL_ARB_sample_shading")) {
758        if (nullptr == fFunctions.fMinSampleShading) {
759            RETURN_FALSE_INTERFACE
760        }
761    } else if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_OES_sample_shading")) {
762        if (nullptr == fFunctions.fMinSampleShading) {
763            RETURN_FALSE_INTERFACE
764        }
765    }
766
767    if (kGL_GrGLStandard == fStandard) {
768        if (glVer >= GR_GL_VER(3, 2) || fExtensions.has("GL_ARB_sync")) {
769            if (nullptr == fFunctions.fFenceSync ||
770                nullptr == fFunctions.fClientWaitSync ||
771                nullptr == fFunctions.fWaitSync ||
772                nullptr == fFunctions.fDeleteSync) {
773                RETURN_FALSE_INTERFACE
774            }
775        }
776    } else if (kGLES_GrGLStandard == fStandard) {
777        if (glVer >= GR_GL_VER(3, 0)) {
778            if (nullptr == fFunctions.fFenceSync ||
779                nullptr == fFunctions.fClientWaitSync ||
780                nullptr == fFunctions.fWaitSync ||
781                nullptr == fFunctions.fDeleteSync) {
782                RETURN_FALSE_INTERFACE
783            }
784        }
785    }
786
787    if (fExtensions.has("EGL_KHR_image") || fExtensions.has("EGL_KHR_image_base")) {
788        if (nullptr == fFunctions.fEGLCreateImage ||
789            nullptr == fFunctions.fEGLDestroyImage) {
790            RETURN_FALSE_INTERFACE
791        }
792    }
793
794    if (kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(2,0)) {
795        if (nullptr == fFunctions.fDrawRangeElements) {
796            RETURN_FALSE_INTERFACE;
797        }
798    } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) {
799        if (nullptr == fFunctions.fDrawRangeElements) {
800            RETURN_FALSE_INTERFACE;
801        }
802    }
803
804    if (kGL_GrGLStandard == fStandard) {
805        if (glVer >= GR_GL_VER(4,2) || fExtensions.has("GL_ARB_shader_image_load_store")) {
806            if (nullptr == fFunctions.fBindImageTexture ||
807                nullptr == fFunctions.fMemoryBarrier) {
808                RETURN_FALSE_INTERFACE;
809            }
810        }
811        if (glVer >= GR_GL_VER(4,5) || fExtensions.has("GL_ARB_ES3_1_compatibility")) {
812            if (nullptr == fFunctions.fMemoryBarrierByRegion) {
813                RETURN_FALSE_INTERFACE;
814            }
815        }
816    } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1)) {
817        if (nullptr == fFunctions.fBindImageTexture ||
818            nullptr == fFunctions.fMemoryBarrier ||
819            nullptr == fFunctions.fMemoryBarrierByRegion) {
820            RETURN_FALSE_INTERFACE;
821        }
822    }
823
824    return true;
825}
826