/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "gl/GrGLInterface.h" #include "gl/GrGLExtensions.h" #include "gl/GrGLUtil.h" #include const GrGLInterface* GrGLInterfaceAddTestDebugMarker(const GrGLInterface* interface, GrGLInsertEventMarkerProc insertEventMarkerFn, GrGLPushGroupMarkerProc pushGroupMarkerFn, GrGLPopGroupMarkerProc popGroupMarkerFn) { GrGLInterface* newInterface = GrGLInterface::NewClone(interface); if (!newInterface->fExtensions.has("GL_EXT_debug_marker")) { newInterface->fExtensions.add("GL_EXT_debug_marker"); } newInterface->fFunctions.fInsertEventMarker = insertEventMarkerFn; newInterface->fFunctions.fPushGroupMarker = pushGroupMarkerFn; newInterface->fFunctions.fPopGroupMarker = popGroupMarkerFn; return newInterface; } GrGLInterface::GrGLInterface() { fStandard = kNone_GrGLStandard; } GrGLInterface* GrGLInterface::NewClone(const GrGLInterface* interface) { SkASSERT(interface); GrGLInterface* clone = new GrGLInterface; clone->fStandard = interface->fStandard; clone->fExtensions = interface->fExtensions; clone->fFunctions = interface->fFunctions; return clone; } #ifdef SK_DEBUG static int kIsDebug = 1; #else static int kIsDebug = 0; #endif #define RETURN_FALSE_INTERFACE \ if (kIsDebug) { SkDebugf("%s:%d GrGLInterface::validate() failed.\n", __FILE__, __LINE__); } \ return false; bool GrGLInterface::validate() const { if (kNone_GrGLStandard == fStandard) { RETURN_FALSE_INTERFACE } if (!fExtensions.isInitialized()) { RETURN_FALSE_INTERFACE } // functions that are always required if (!fFunctions.fActiveTexture || !fFunctions.fAttachShader || !fFunctions.fBindAttribLocation || !fFunctions.fBindBuffer || !fFunctions.fBindTexture || !fFunctions.fBlendColor || // -> GL >= 1.4 or extension, ES >= 2.0 !fFunctions.fBlendEquation || // -> GL >= 1.4 or extension, ES >= 2.0 !fFunctions.fBlendFunc || !fFunctions.fBufferData || !fFunctions.fBufferSubData || !fFunctions.fClear || !fFunctions.fClearColor || !fFunctions.fClearStencil || !fFunctions.fColorMask || !fFunctions.fCompileShader || !fFunctions.fCompressedTexImage2D || !fFunctions.fCompressedTexSubImage2D || !fFunctions.fCopyTexSubImage2D || !fFunctions.fCreateProgram || !fFunctions.fCreateShader || !fFunctions.fCullFace || !fFunctions.fDeleteBuffers || !fFunctions.fDeleteProgram || !fFunctions.fDeleteShader || !fFunctions.fDeleteTextures || !fFunctions.fDepthMask || !fFunctions.fDisable || !fFunctions.fDisableVertexAttribArray || !fFunctions.fDrawArrays || !fFunctions.fDrawElements || !fFunctions.fEnable || !fFunctions.fEnableVertexAttribArray || !fFunctions.fFrontFace || !fFunctions.fGenBuffers || !fFunctions.fGenTextures || !fFunctions.fGetBufferParameteriv || !fFunctions.fGenerateMipmap || !fFunctions.fGetError || !fFunctions.fGetIntegerv || !fFunctions.fGetProgramInfoLog || !fFunctions.fGetProgramiv || !fFunctions.fGetShaderInfoLog || !fFunctions.fGetShaderiv || !fFunctions.fGetString || !fFunctions.fGetUniformLocation || !fFunctions.fIsTexture || !fFunctions.fLinkProgram || !fFunctions.fLineWidth || !fFunctions.fPixelStorei || !fFunctions.fReadPixels || !fFunctions.fScissor || !fFunctions.fShaderSource || !fFunctions.fStencilFunc || !fFunctions.fStencilFuncSeparate || !fFunctions.fStencilMask || !fFunctions.fStencilMaskSeparate || !fFunctions.fStencilOp || !fFunctions.fStencilOpSeparate || !fFunctions.fTexImage2D || !fFunctions.fTexParameteri || !fFunctions.fTexParameteriv || !fFunctions.fTexSubImage2D || !fFunctions.fUniform1f || !fFunctions.fUniform1i || !fFunctions.fUniform1fv || !fFunctions.fUniform1iv || !fFunctions.fUniform2f || !fFunctions.fUniform2i || !fFunctions.fUniform2fv || !fFunctions.fUniform2iv || !fFunctions.fUniform3f || !fFunctions.fUniform3i || !fFunctions.fUniform3fv || !fFunctions.fUniform3iv || !fFunctions.fUniform4f || !fFunctions.fUniform4i || !fFunctions.fUniform4fv || !fFunctions.fUniform4iv || !fFunctions.fUniformMatrix2fv || !fFunctions.fUniformMatrix3fv || !fFunctions.fUniformMatrix4fv || !fFunctions.fUseProgram || !fFunctions.fVertexAttrib1f || !fFunctions.fVertexAttrib2fv || !fFunctions.fVertexAttrib3fv || !fFunctions.fVertexAttrib4fv || !fFunctions.fVertexAttribPointer || !fFunctions.fViewport || !fFunctions.fBindFramebuffer || !fFunctions.fBindRenderbuffer || !fFunctions.fCheckFramebufferStatus || !fFunctions.fDeleteFramebuffers || !fFunctions.fDeleteRenderbuffers || !fFunctions.fFinish || !fFunctions.fFlush || !fFunctions.fFramebufferRenderbuffer || !fFunctions.fFramebufferTexture2D || !fFunctions.fGetFramebufferAttachmentParameteriv || !fFunctions.fGetRenderbufferParameteriv || !fFunctions.fGenFramebuffers || !fFunctions.fGenRenderbuffers || !fFunctions.fRenderbufferStorage) { RETURN_FALSE_INTERFACE } GrGLVersion glVer = GrGLGetVersion(this); if (GR_GL_INVALID_VER == glVer) { RETURN_FALSE_INTERFACE } // Now check that baseline ES/Desktop fns not covered above are present // and that we have fn pointers for any advertised fExtensions that we will // try to use. // these functions are part of ES2, we assume they are available // On the desktop we assume they are available if the extension // is present or GL version is high enough. if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3,0) && !fFunctions.fBindFragDataLocation) { RETURN_FALSE_INTERFACE } if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query") || fExtensions.has("GL_EXT_timer_query")) { if (!fFunctions.fGetQueryObjecti64v || !fFunctions.fGetQueryObjectui64v) { RETURN_FALSE_INTERFACE } } if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_timer_query")) { if (!fFunctions.fQueryCounter) { RETURN_FALSE_INTERFACE } } } // part of desktop GL, but not ES if (kGL_GrGLStandard == fStandard && (!fFunctions.fDrawBuffer || !fFunctions.fPolygonMode)) { RETURN_FALSE_INTERFACE } // ES 3.0 (or ES 2.0 extended) has glDrawBuffers but not glDrawBuffer if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) { if (!fFunctions.fDrawBuffers) { RETURN_FALSE_INTERFACE } } if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) { if (!fFunctions.fReadBuffer) { RETURN_FALSE_INTERFACE } } // glGetTexLevelParameteriv was added to ES in 3.1. if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,1)) { if (!fFunctions.fGetTexLevelParameteriv) { RETURN_FALSE_INTERFACE } } // GL_EXT_texture_storage is part of desktop 4.2 // There is a desktop ARB extension and an ES+desktop EXT extension if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(4,2) || fExtensions.has("GL_ARB_texture_storage") || fExtensions.has("GL_EXT_texture_storage")) { if (!fFunctions.fTexStorage2D) { RETURN_FALSE_INTERFACE } } } else if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_texture_storage")) { if (!fFunctions.fTexStorage2D) { RETURN_FALSE_INTERFACE } } // glTextureBarrier is part of desktop 4.5. There are also ARB and NV extensions. if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(4,5) || fExtensions.has("GL_ARB_texture_barrier") || fExtensions.has("GL_NV_texture_barrier")) { if (!fFunctions.fTextureBarrier) { RETURN_FALSE_INTERFACE } } } else if (fExtensions.has("GL_NV_texture_barrier")) { if (!fFunctions.fTextureBarrier) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_KHR_blend_equation_advanced") || fExtensions.has("GL_NV_blend_equation_advanced")) { if (!fFunctions.fBlendBarrier) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_EXT_discard_framebuffer")) { if (!fFunctions.fDiscardFramebuffer) { RETURN_FALSE_INTERFACE } } // Required since OpenGL 1.5 and ES 3.0 or with GL_EXT_occlusion_query_boolean if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_occlusion_query_boolean")) { #if 0 // Not yet added to chrome's bindings. if (!fFunctions.fGenQueries || !fFunctions.fDeleteQueries || !fFunctions.fBeginQuery || !fFunctions.fEndQuery || !fFunctions.fGetQueryiv || !fFunctions.fGetQueryObjectuiv) { RETURN_FALSE_INTERFACE } #endif } // glGetQueryObjectiv doesn't exist in ES. if (kGL_GrGLStandard == fStandard && !fFunctions.fGetQueryObjectiv) { RETURN_FALSE_INTERFACE } // FBO MSAA if (kGL_GrGLStandard == fStandard) { // GL 3.0 and the ARB extension have multisample + blit if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_ARB_framebuffer_object")) { if (!fFunctions.fRenderbufferStorageMultisample || !fFunctions.fBlitFramebuffer) { RETURN_FALSE_INTERFACE } } else { if (fExtensions.has("GL_EXT_framebuffer_blit") && !fFunctions.fBlitFramebuffer) { RETURN_FALSE_INTERFACE } if (fExtensions.has("GL_EXT_framebuffer_multisample") && !fFunctions.fRenderbufferStorageMultisample) { RETURN_FALSE_INTERFACE } } } else { if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_CHROMIUM_framebuffer_multisample")) { if (!fFunctions.fRenderbufferStorageMultisample || !fFunctions.fBlitFramebuffer) { RETURN_FALSE_INTERFACE } } else { if (fExtensions.has("GL_ANGLE_framebuffer_multisample") && !fFunctions.fRenderbufferStorageMultisample) { RETURN_FALSE_INTERFACE } if (fExtensions.has("GL_ANGLE_framebuffer_blit") && !fFunctions.fBlitFramebuffer) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_APPLE_framebuffer_multisample")) { if (!fFunctions.fRenderbufferStorageMultisampleES2APPLE || !fFunctions.fResolveMultisampleFramebuffer) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_IMG_multisampled_render_to_texture") || fExtensions.has("GL_EXT_multisampled_render_to_texture")) { if (!fFunctions.fRenderbufferStorageMultisampleES2EXT || !fFunctions.fFramebufferTexture2DMultisample) { RETURN_FALSE_INTERFACE } } } // On ES buffer mapping is an extension. On Desktop // buffer mapping was part of original VBO extension // which we require. if (kGL_GrGLStandard == fStandard || fExtensions.has("GL_OES_mapbuffer")) { if (!fFunctions.fMapBuffer || !fFunctions.fUnmapBuffer) { RETURN_FALSE_INTERFACE } } // Dual source blending if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3,3) || fExtensions.has("GL_ARB_blend_func_extended")) { if (!fFunctions.fBindFragDataLocationIndexed) { RETURN_FALSE_INTERFACE } } } else { if (glVer >= GR_GL_VER(3,0) && fExtensions.has("GL_EXT_blend_func_extended")) { if (!fFunctions.fBindFragDataLocation || !fFunctions.fBindFragDataLocationIndexed) { RETURN_FALSE_INTERFACE } } } // glGetStringi was added in version 3.0 of both desktop and ES. if (glVer >= GR_GL_VER(3, 0)) { if (!fFunctions.fGetStringi) { RETURN_FALSE_INTERFACE } } // glVertexAttribIPointer was added in version 3.0 of both desktop and ES. if (glVer >= GR_GL_VER(3, 0)) { if (!fFunctions.fVertexAttribIPointer) { RETURN_FALSE_INTERFACE } } if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3,1)) { if (!fFunctions.fTexBuffer) { RETURN_FALSE_INTERFACE; } } if (glVer >= GR_GL_VER(4,3)) { if (!fFunctions.fTexBufferRange) { RETURN_FALSE_INTERFACE; } } } else { if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_OES_texture_buffer") || fExtensions.has("GL_EXT_texture_buffer")) { if (!fFunctions.fTexBuffer || !fFunctions.fTexBufferRange) { RETURN_FALSE_INTERFACE; } } } if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_ARB_vertex_array_object")) { if (!fFunctions.fBindVertexArray || !fFunctions.fDeleteVertexArrays || !fFunctions.fGenVertexArrays) { RETURN_FALSE_INTERFACE } } } else { if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_OES_vertex_array_object")) { if (!fFunctions.fBindVertexArray || !fFunctions.fDeleteVertexArrays || !fFunctions.fGenVertexArrays) { RETURN_FALSE_INTERFACE } } } if (fExtensions.has("GL_EXT_debug_marker")) { if (!fFunctions.fInsertEventMarker || !fFunctions.fPushGroupMarker || !fFunctions.fPopGroupMarker) { RETURN_FALSE_INTERFACE } } if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) || fExtensions.has("GL_ARB_invalidate_subdata")) { if (!fFunctions.fInvalidateBufferData || !fFunctions.fInvalidateBufferSubData || !fFunctions.fInvalidateFramebuffer || !fFunctions.fInvalidateSubFramebuffer || !fFunctions.fInvalidateTexImage || !fFunctions.fInvalidateTexSubImage) { RETURN_FALSE_INTERFACE; } } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0)) { // ES 3.0 adds the framebuffer functions but not the others. if (!fFunctions.fInvalidateFramebuffer || !fFunctions.fInvalidateSubFramebuffer) { RETURN_FALSE_INTERFACE; } } if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_CHROMIUM_map_sub")) { if (!fFunctions.fMapBufferSubData || !fFunctions.fMapTexSubImage2D || !fFunctions.fUnmapBufferSubData || !fFunctions.fUnmapTexSubImage2D) { RETURN_FALSE_INTERFACE; } } // These functions are added to the 3.0 version of both GLES and GL. if (glVer >= GR_GL_VER(3,0) || (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_map_buffer_range")) || (kGL_GrGLStandard == fStandard && fExtensions.has("GL_ARB_map_buffer_range"))) { if (!fFunctions.fMapBufferRange || !fFunctions.fFlushMappedBufferRange) { RETURN_FALSE_INTERFACE; } } if ((kGL_GrGLStandard == fStandard && (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_texture_multisample"))) || (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) { if (!fFunctions.fGetMultisamplefv) { RETURN_FALSE_INTERFACE } } if ((kGL_GrGLStandard == fStandard && (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_program_interface_query"))) || (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) { if (!fFunctions.fGetProgramResourceLocation) { RETURN_FALSE_INTERFACE } } if (kGLES_GrGLStandard == fStandard || glVer >= GR_GL_VER(4,1) || fExtensions.has("GL_ARB_ES2_compatibility")) { if (!fFunctions.fGetShaderPrecisionFormat) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_NV_path_rendering") || fExtensions.has("GL_CHROMIUM_path_rendering")) { if (!fFunctions.fMatrixLoadf || !fFunctions.fMatrixLoadIdentity || !fFunctions.fPathCommands || !fFunctions.fPathParameteri || !fFunctions.fPathParameterf || !fFunctions.fGenPaths || !fFunctions.fDeletePaths || !fFunctions.fIsPath || !fFunctions.fPathStencilFunc || !fFunctions.fStencilFillPath || !fFunctions.fStencilStrokePath || !fFunctions.fStencilFillPathInstanced || !fFunctions.fStencilStrokePathInstanced || !fFunctions.fCoverFillPath || !fFunctions.fCoverStrokePath || !fFunctions.fCoverFillPathInstanced || !fFunctions.fCoverStrokePathInstanced #if 0 // List of functions that Skia uses, but which have been added since the initial release // of NV_path_rendering driver. We do not want to fail interface validation due to // missing features, we will just not use the extension. // Update this list -> update GrGLCaps::hasPathRenderingSupport too. || !fFunctions.fStencilThenCoverFillPath || !fFunctions.fStencilThenCoverStrokePath || !fFunctions.fStencilThenCoverFillPathInstanced || !fFunctions.fStencilThenCoverStrokePathInstanced || !fFunctions.fProgramPathFragmentInputGen #endif ) { RETURN_FALSE_INTERFACE } if (fExtensions.has("GL_CHROMIUM_path_rendering")) { if (!fFunctions.fBindFragmentInputLocation) { RETURN_FALSE_INTERFACE } } } if (fExtensions.has("GL_EXT_raster_multisample")) { if (!fFunctions.fRasterSamples) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_NV_framebuffer_mixed_samples") || fExtensions.has("GL_CHROMIUM_framebuffer_mixed_samples")) { if (!fFunctions.fCoverageModulation) { RETURN_FALSE_INTERFACE } } if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3,1) || fExtensions.has("GL_EXT_draw_instanced") || fExtensions.has("GL_ARB_draw_instanced")) { if (!fFunctions.fDrawArraysInstanced || !fFunctions.fDrawElementsInstanced) { RETURN_FALSE_INTERFACE } } } else if (kGLES_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_draw_instanced")) { if (!fFunctions.fDrawArraysInstanced || !fFunctions.fDrawElementsInstanced) { RETURN_FALSE_INTERFACE } } } if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3,2) || fExtensions.has("GL_ARB_instanced_arrays")) { if (!fFunctions.fVertexAttribDivisor) { RETURN_FALSE_INTERFACE } } } else if (kGLES_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3,0) || fExtensions.has("GL_EXT_instanced_arrays")) { if (!fFunctions.fVertexAttribDivisor) { RETURN_FALSE_INTERFACE } } } if ((kGL_GrGLStandard == fStandard && (glVer >= GR_GL_VER(4,0) || fExtensions.has("GL_ARB_draw_indirect"))) || (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1))) { if (!fFunctions.fDrawArraysIndirect || !fFunctions.fDrawElementsIndirect) { RETURN_FALSE_INTERFACE } } if ((kGL_GrGLStandard == fStandard && (glVer >= GR_GL_VER(4,3) || fExtensions.has("GL_ARB_multi_draw_indirect"))) || (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_EXT_multi_draw_indirect"))) { if (!fFunctions.fMultiDrawArraysIndirect || !fFunctions.fMultiDrawElementsIndirect) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_NV_bindless_texture")) { if (!fFunctions.fGetTextureHandle || !fFunctions.fGetTextureSamplerHandle || !fFunctions.fMakeTextureHandleResident || !fFunctions.fMakeTextureHandleNonResident || !fFunctions.fGetImageHandle || !fFunctions.fMakeImageHandleResident || !fFunctions.fMakeImageHandleNonResident || !fFunctions.fIsTextureHandleResident || !fFunctions.fIsImageHandleResident || !fFunctions.fUniformHandleui64 || !fFunctions.fUniformHandleui64v || !fFunctions.fProgramUniformHandleui64 || !fFunctions.fProgramUniformHandleui64v) { RETURN_FALSE_INTERFACE } } if (kGL_GrGLStandard == fStandard && fExtensions.has("GL_EXT_direct_state_access")) { if (!fFunctions.fTextureParameteri || !fFunctions.fTextureParameteriv || !fFunctions.fTextureParameterf || !fFunctions.fTextureParameterfv || !fFunctions.fTextureImage1D || !fFunctions.fTextureImage2D || !fFunctions.fTextureSubImage1D || !fFunctions.fTextureSubImage2D || !fFunctions.fCopyTextureImage1D || !fFunctions.fCopyTextureImage2D || !fFunctions.fCopyTextureSubImage1D || !fFunctions.fCopyTextureSubImage2D || !fFunctions.fGetNamedBufferParameteriv || !fFunctions.fGetNamedBufferPointerv || !fFunctions.fGetNamedBufferSubData || !fFunctions.fGetTextureImage || !fFunctions.fGetTextureParameterfv || !fFunctions.fGetTextureParameteriv || !fFunctions.fGetTextureLevelParameterfv || !fFunctions.fGetTextureLevelParameteriv || !fFunctions.fMapNamedBuffer || !fFunctions.fNamedBufferData || !fFunctions.fNamedBufferSubData || !fFunctions.fProgramUniform1f || !fFunctions.fProgramUniform2f || !fFunctions.fProgramUniform3f || !fFunctions.fProgramUniform4f || !fFunctions.fProgramUniform1i || !fFunctions.fProgramUniform2i || !fFunctions.fProgramUniform3i || !fFunctions.fProgramUniform4i || !fFunctions.fProgramUniform1fv || !fFunctions.fProgramUniform2fv || !fFunctions.fProgramUniform3fv || !fFunctions.fProgramUniform4fv || !fFunctions.fProgramUniform1iv || !fFunctions.fProgramUniform2iv || !fFunctions.fProgramUniform3iv || !fFunctions.fProgramUniform4iv || !fFunctions.fProgramUniformMatrix2fv || !fFunctions.fProgramUniformMatrix3fv || !fFunctions.fProgramUniformMatrix4fv || !fFunctions.fUnmapNamedBuffer) { RETURN_FALSE_INTERFACE } if (glVer >= GR_GL_VER(1,2)) { if (!fFunctions.fTextureImage3D || !fFunctions.fTextureSubImage3D || !fFunctions.fCopyTextureSubImage3D || !fFunctions.fCompressedTextureImage3D || !fFunctions.fCompressedTextureImage2D || !fFunctions.fCompressedTextureImage1D || !fFunctions.fCompressedTextureSubImage3D || !fFunctions.fCompressedTextureSubImage2D || !fFunctions.fCompressedTextureSubImage1D || !fFunctions.fGetCompressedTextureImage) { RETURN_FALSE_INTERFACE } } if (glVer >= GR_GL_VER(2,1)) { if (!fFunctions.fProgramUniformMatrix2x3fv || !fFunctions.fProgramUniformMatrix3x2fv || !fFunctions.fProgramUniformMatrix2x4fv || !fFunctions.fProgramUniformMatrix4x2fv || !fFunctions.fProgramUniformMatrix3x4fv || !fFunctions.fProgramUniformMatrix4x3fv) { RETURN_FALSE_INTERFACE } } if (glVer >= GR_GL_VER(3,0)) { if (!fFunctions.fNamedRenderbufferStorage || !fFunctions.fGetNamedRenderbufferParameteriv || !fFunctions.fNamedRenderbufferStorageMultisample || !fFunctions.fCheckNamedFramebufferStatus || !fFunctions.fNamedFramebufferTexture1D || !fFunctions.fNamedFramebufferTexture2D || !fFunctions.fNamedFramebufferTexture3D || !fFunctions.fNamedFramebufferRenderbuffer || !fFunctions.fGetNamedFramebufferAttachmentParameteriv || !fFunctions.fGenerateTextureMipmap || !fFunctions.fFramebufferDrawBuffer || !fFunctions.fFramebufferDrawBuffers || !fFunctions.fFramebufferReadBuffer || !fFunctions.fGetFramebufferParameteriv || !fFunctions.fNamedCopyBufferSubData || !fFunctions.fVertexArrayVertexOffset || !fFunctions.fVertexArrayColorOffset || !fFunctions.fVertexArrayEdgeFlagOffset || !fFunctions.fVertexArrayIndexOffset || !fFunctions.fVertexArrayNormalOffset || !fFunctions.fVertexArrayTexCoordOffset || !fFunctions.fVertexArrayMultiTexCoordOffset || !fFunctions.fVertexArrayFogCoordOffset || !fFunctions.fVertexArraySecondaryColorOffset || !fFunctions.fVertexArrayVertexAttribOffset || !fFunctions.fVertexArrayVertexAttribIOffset || !fFunctions.fEnableVertexArray || !fFunctions.fDisableVertexArray || !fFunctions.fEnableVertexArrayAttrib || !fFunctions.fDisableVertexArrayAttrib || !fFunctions.fGetVertexArrayIntegerv || !fFunctions.fGetVertexArrayPointerv || !fFunctions.fGetVertexArrayIntegeri_v || !fFunctions.fGetVertexArrayPointeri_v || !fFunctions.fMapNamedBufferRange || !fFunctions.fFlushMappedNamedBufferRange) { RETURN_FALSE_INTERFACE } } if (glVer >= GR_GL_VER(3,1)) { if (!fFunctions.fTextureBuffer) { RETURN_FALSE_INTERFACE; } } } if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,3)) || fExtensions.has("GL_KHR_debug")) { if (!fFunctions.fDebugMessageControl || !fFunctions.fDebugMessageInsert || !fFunctions.fDebugMessageCallback || !fFunctions.fGetDebugMessageLog || !fFunctions.fPushDebugGroup || !fFunctions.fPopDebugGroup || !fFunctions.fObjectLabel) { RETURN_FALSE_INTERFACE } } if (fExtensions.has("GL_EXT_window_rectangles")) { if (!fFunctions.fWindowRectangles) { RETURN_FALSE_INTERFACE } } if ((kGL_GrGLStandard == fStandard && glVer >= GR_GL_VER(4,0)) || fExtensions.has("GL_ARB_sample_shading")) { if (!fFunctions.fMinSampleShading) { RETURN_FALSE_INTERFACE } } else if (kGLES_GrGLStandard == fStandard && fExtensions.has("GL_OES_sample_shading")) { if (!fFunctions.fMinSampleShading) { RETURN_FALSE_INTERFACE } } if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3, 2) || fExtensions.has("GL_ARB_sync")) { if (!fFunctions.fFenceSync || !fFunctions.fIsSync || !fFunctions.fClientWaitSync || !fFunctions.fWaitSync || !fFunctions.fDeleteSync) { RETURN_FALSE_INTERFACE } } } else if (kGLES_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(3, 0) || fExtensions.has("GL_APPLE_sync")) { if (!fFunctions.fFenceSync || !fFunctions.fIsSync || !fFunctions.fClientWaitSync || !fFunctions.fWaitSync || !fFunctions.fDeleteSync) { RETURN_FALSE_INTERFACE } } } if (fExtensions.has("EGL_KHR_image") || fExtensions.has("EGL_KHR_image_base")) { if (!fFunctions.fEGLCreateImage || !fFunctions.fEGLDestroyImage) { RETURN_FALSE_INTERFACE } } // glDrawRangeElements was added to ES in 3.0. if (kGL_GrGLStandard == fStandard || glVer >= GR_GL_VER(3,0)) { if (!fFunctions.fDrawRangeElements) { RETURN_FALSE_INTERFACE; } } if (kGL_GrGLStandard == fStandard) { if (glVer >= GR_GL_VER(4,2) || fExtensions.has("GL_ARB_shader_image_load_store")) { if (!fFunctions.fBindImageTexture || !fFunctions.fMemoryBarrier) { RETURN_FALSE_INTERFACE; } } if (glVer >= GR_GL_VER(4,5) || fExtensions.has("GL_ARB_ES3_1_compatibility")) { if (!fFunctions.fMemoryBarrierByRegion) { RETURN_FALSE_INTERFACE; } } } else if (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,1)) { if (!fFunctions.fBindImageTexture || !fFunctions.fMemoryBarrier || !fFunctions.fMemoryBarrierByRegion) { RETURN_FALSE_INTERFACE; } } // getInternalformativ was added in GL 4.2, ES 3.0, and with extension ARB_internalformat_query if ((kGL_GrGLStandard == fStandard && (glVer >= GR_GL_VER(4,2) || fExtensions.has("GL_ARB_internalformat_query"))) || (kGLES_GrGLStandard == fStandard && glVer >= GR_GL_VER(3,0))) { if (!fFunctions.fGetInternalformativ) { RETURN_FALSE_INTERFACE; } } return true; }