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