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
16 namespace {
GrGLDefaultInterfaceCallback(const GrGLInterface *)17 void GrGLDefaultInterfaceCallback(const GrGLInterface*) {}
18 }
19 #endif
20 
GrGLInterfaceAddTestDebugMarker(const GrGLInterface * interface,GrGLInsertEventMarkerProc insertEventMarkerFn,GrGLPushGroupMarkerProc pushGroupMarkerFn,GrGLPopGroupMarkerProc popGroupMarkerFn)21 const 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 
GrGLInterfaceRemoveNVPR(const GrGLInterface * interface)38 const 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 
GrGLInterface()69 GrGLInterface::GrGLInterface() {
70     fStandard = kNone_GrGLStandard;
71 
72 #if GR_GL_PER_GL_FUNC_CALLBACK
73     fCallback = GrGLDefaultInterfaceCallback;
74     fCallbackData = 0;
75 #endif
76 }
77 
NewClone(const GrGLInterface * interface)78 GrGLInterface* 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 
validate() const102 bool 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