/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * Copyright (C) 2003-2005 3Dlabs Inc. Ltd. * Copyright (C) 2004-2005 Nathan Cournia * Copyright (C) 2008 Zebra Imaging * * This application is open source and may be redistributed and/or modified * freely and without restriction, both in commericial and non commericial * applications, as long as this copyright notice is maintained. * * This application is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * */ /* file: src/osg/GL2Extensions.cpp * author: Mike Weiblen 2008-01-19 */ #include #include #include #include #include #include using namespace osg; /////////////////////////////////////////////////////////////////////////// // Extension function pointers for OpenGL v2.x GL2Extensions::GL2Extensions(unsigned int contextID) { setupGL2Extensions(contextID); } GL2Extensions::GL2Extensions(const GL2Extensions& rhs) : osg::Referenced() { _glVersion = rhs._glVersion; _glslLanguageVersion = rhs._glslLanguageVersion; _isShaderObjectsSupported = rhs._isShaderObjectsSupported; _isVertexShaderSupported = rhs._isVertexShaderSupported; _isFragmentShaderSupported = rhs._isFragmentShaderSupported; _isLanguage100Supported = rhs._isLanguage100Supported; _isGeometryShader4Supported = rhs._isGeometryShader4Supported; _isGpuShader4Supported = rhs._isGpuShader4Supported; _glBlendEquationSeparate = rhs._glBlendEquationSeparate; _glDrawBuffers = rhs._glDrawBuffers; _glStencilOpSeparate = rhs._glStencilOpSeparate; _glStencilFuncSeparate = rhs._glStencilFuncSeparate; _glStencilMaskSeparate = rhs._glStencilMaskSeparate; _glAttachShader = rhs._glAttachShader; _glBindAttribLocation = rhs._glBindAttribLocation; _glCompileShader = rhs._glCompileShader; _glCreateProgram = rhs._glCreateProgram; _glCreateShader = rhs._glCreateShader; _glDeleteProgram = rhs._glDeleteProgram; _glDeleteShader = rhs._glDeleteShader; _glDetachShader = rhs._glDetachShader; _glDisableVertexAttribArray = rhs._glDisableVertexAttribArray; _glEnableVertexAttribArray = rhs._glEnableVertexAttribArray; _glGetActiveAttrib = rhs._glGetActiveAttrib; _glGetActiveUniform = rhs._glGetActiveUniform; _glGetAttachedShaders = rhs._glGetAttachedShaders; _glGetAttribLocation = rhs._glGetAttribLocation; _glGetProgramiv = rhs._glGetProgramiv; _glGetProgramInfoLog = rhs._glGetProgramInfoLog; _glGetShaderiv = rhs._glGetShaderiv; _glGetShaderInfoLog = rhs._glGetShaderInfoLog; _glGetShaderSource = rhs._glGetShaderSource; _glGetUniformLocation = rhs._glGetUniformLocation; _glGetUniformfv = rhs._glGetUniformfv; _glGetUniformiv = rhs._glGetUniformiv; _glGetVertexAttribdv = rhs._glGetVertexAttribdv; _glGetVertexAttribfv = rhs._glGetVertexAttribfv; _glGetVertexAttribiv = rhs._glGetVertexAttribiv; _glGetVertexAttribPointerv = rhs._glGetVertexAttribPointerv; _glIsProgram = rhs._glIsProgram; _glIsShader = rhs._glIsShader; _glLinkProgram = rhs._glLinkProgram; _glShaderSource = rhs._glShaderSource; _glUseProgram = rhs._glUseProgram; _glUniform1f = rhs._glUniform1f; _glUniform2f = rhs._glUniform2f; _glUniform3f = rhs._glUniform3f; _glUniform4f = rhs._glUniform4f; _glUniform1i = rhs._glUniform1i; _glUniform2i = rhs._glUniform2i; _glUniform3i = rhs._glUniform3i; _glUniform4i = rhs._glUniform4i; _glUniform1fv = rhs._glUniform1fv; _glUniform2fv = rhs._glUniform2fv; _glUniform3fv = rhs._glUniform3fv; _glUniform4fv = rhs._glUniform4fv; _glUniform1iv = rhs._glUniform1iv; _glUniform2iv = rhs._glUniform2iv; _glUniform3iv = rhs._glUniform3iv; _glUniform4iv = rhs._glUniform4iv; _glUniformMatrix2fv = rhs._glUniformMatrix2fv; _glUniformMatrix3fv = rhs._glUniformMatrix3fv; _glUniformMatrix4fv = rhs._glUniformMatrix4fv; _glValidateProgram = rhs._glValidateProgram; _glVertexAttrib1d = rhs._glVertexAttrib1d; _glVertexAttrib1dv = rhs._glVertexAttrib1dv; _glVertexAttrib1f = rhs._glVertexAttrib1f; _glVertexAttrib1fv = rhs._glVertexAttrib1fv; _glVertexAttrib1s = rhs._glVertexAttrib1s; _glVertexAttrib1sv = rhs._glVertexAttrib1sv; _glVertexAttrib2d = rhs._glVertexAttrib2d; _glVertexAttrib2dv = rhs._glVertexAttrib2dv; _glVertexAttrib2f = rhs._glVertexAttrib2f; _glVertexAttrib2fv = rhs._glVertexAttrib2fv; _glVertexAttrib2s = rhs._glVertexAttrib2s; _glVertexAttrib2sv = rhs._glVertexAttrib2sv; _glVertexAttrib3d = rhs._glVertexAttrib3d; _glVertexAttrib3dv = rhs._glVertexAttrib3dv; _glVertexAttrib3f = rhs._glVertexAttrib3f; _glVertexAttrib3fv = rhs._glVertexAttrib3fv; _glVertexAttrib3s = rhs._glVertexAttrib3s; _glVertexAttrib3sv = rhs._glVertexAttrib3sv; _glVertexAttrib4Nbv = rhs._glVertexAttrib4Nbv; _glVertexAttrib4Niv = rhs._glVertexAttrib4Niv; _glVertexAttrib4Nsv = rhs._glVertexAttrib4Nsv; _glVertexAttrib4Nub = rhs._glVertexAttrib4Nub; _glVertexAttrib4Nubv = rhs._glVertexAttrib4Nubv; _glVertexAttrib4Nuiv = rhs._glVertexAttrib4Nuiv; _glVertexAttrib4Nusv = rhs._glVertexAttrib4Nusv; _glVertexAttrib4bv = rhs._glVertexAttrib4bv; _glVertexAttrib4d = rhs._glVertexAttrib4d; _glVertexAttrib4dv = rhs._glVertexAttrib4dv; _glVertexAttrib4f = rhs._glVertexAttrib4f; _glVertexAttrib4fv = rhs._glVertexAttrib4fv; _glVertexAttrib4iv = rhs._glVertexAttrib4iv; _glVertexAttrib4s = rhs._glVertexAttrib4s; _glVertexAttrib4sv = rhs._glVertexAttrib4sv; _glVertexAttrib4ubv = rhs._glVertexAttrib4ubv; _glVertexAttrib4uiv = rhs._glVertexAttrib4uiv; _glVertexAttrib4usv = rhs._glVertexAttrib4usv; _glVertexAttribPointer = rhs._glVertexAttribPointer; _glGetInfoLogARB = rhs._glGetInfoLogARB; _glGetObjectParameterivARB = rhs._glGetObjectParameterivARB; _glDeleteObjectARB = rhs._glDeleteObjectARB; _glGetHandleARB = rhs._glGetHandleARB; // GL 2.1 _glUniformMatrix2x3fv = rhs._glUniformMatrix2x3fv; _glUniformMatrix3x2fv = rhs._glUniformMatrix3x2fv; _glUniformMatrix2x4fv = rhs._glUniformMatrix2x4fv; _glUniformMatrix4x2fv = rhs._glUniformMatrix4x2fv; _glUniformMatrix3x4fv = rhs._glUniformMatrix3x4fv; _glUniformMatrix4x3fv = rhs._glUniformMatrix4x3fv; // EXT_geometry_shader4 _glProgramParameteri = rhs._glProgramParameteri; _glFramebufferTexture = rhs._glFramebufferTexture; _glFramebufferTextureLayer = rhs._glFramebufferTextureLayer; _glFramebufferTextureFace = rhs._glFramebufferTextureFace; // EXT_gpu_shader4 _glGetUniformuiv = rhs._glGetUniformuiv; _glBindFragDataLocation = rhs._glBindFragDataLocation; _glGetFragDataLocation = rhs._glGetFragDataLocation; _glUniform1ui = rhs._glUniform1ui; _glUniform2ui = rhs._glUniform2ui; _glUniform3ui = rhs._glUniform3ui; _glUniform4ui = rhs._glUniform4ui; _glUniform1uiv = rhs._glUniform1uiv; _glUniform2uiv = rhs._glUniform2uiv; _glUniform3uiv = rhs._glUniform3uiv; _glUniform4uiv = rhs._glUniform4uiv; } void GL2Extensions::lowestCommonDenominator(const GL2Extensions& rhs) { if (rhs._glVersion < _glVersion) _glVersion = rhs._glVersion; if (rhs._glslLanguageVersion < _glslLanguageVersion) _glslLanguageVersion = rhs._glslLanguageVersion; if (!rhs._isShaderObjectsSupported) _isShaderObjectsSupported = false; if (!rhs._isVertexShaderSupported) _isVertexShaderSupported = false; if (!rhs._isFragmentShaderSupported) _isFragmentShaderSupported = false; if (!rhs._isLanguage100Supported) _isLanguage100Supported = false; if (!rhs._isGeometryShader4Supported) _isGeometryShader4Supported = false; if (!rhs._isGpuShader4Supported) _isGpuShader4Supported = false; if (!rhs._glBlendEquationSeparate) _glBlendEquationSeparate = 0; if (!rhs._glDrawBuffers) _glDrawBuffers = 0; if (!rhs._glStencilOpSeparate) _glStencilOpSeparate = 0; if (!rhs._glStencilFuncSeparate) _glStencilFuncSeparate = 0; if (!rhs._glStencilMaskSeparate) _glStencilMaskSeparate = 0; if (!rhs._glAttachShader) _glAttachShader = 0; if (!rhs._glBindAttribLocation) _glBindAttribLocation = 0; if (!rhs._glCompileShader) _glCompileShader = 0; if (!rhs._glCreateProgram) _glCreateProgram = 0; if (!rhs._glCreateShader) _glCreateShader = 0; if (!rhs._glDeleteProgram) _glDeleteProgram = 0; if (!rhs._glDeleteShader) _glDeleteShader = 0; if (!rhs._glDetachShader) _glDetachShader = 0; if (!rhs._glDisableVertexAttribArray) _glDisableVertexAttribArray = 0; if (!rhs._glEnableVertexAttribArray) _glEnableVertexAttribArray = 0; if (!rhs._glGetActiveAttrib) _glGetActiveAttrib = 0; if (!rhs._glGetActiveUniform) _glGetActiveUniform = 0; if (!rhs._glGetAttachedShaders) _glGetAttachedShaders = 0; if (!rhs._glGetAttribLocation) _glGetAttribLocation = 0; if (!rhs._glGetProgramiv) _glGetProgramiv = 0; if (!rhs._glGetProgramInfoLog) _glGetProgramInfoLog = 0; if (!rhs._glGetShaderiv) _glGetShaderiv = 0; if (!rhs._glGetShaderInfoLog) _glGetShaderInfoLog = 0; if (!rhs._glGetShaderSource) _glGetShaderSource = 0; if (!rhs._glGetUniformLocation) _glGetUniformLocation = 0; if (!rhs._glGetUniformfv) _glGetUniformfv = 0; if (!rhs._glGetUniformiv) _glGetUniformiv = 0; if (!rhs._glGetVertexAttribdv) _glGetVertexAttribdv = 0; if (!rhs._glGetVertexAttribfv) _glGetVertexAttribfv = 0; if (!rhs._glGetVertexAttribiv) _glGetVertexAttribiv = 0; if (!rhs._glGetVertexAttribPointerv) _glGetVertexAttribPointerv = 0; if (!rhs._glIsProgram) _glIsProgram = 0; if (!rhs._glIsShader) _glIsShader = 0; if (!rhs._glLinkProgram) _glLinkProgram = 0; if (!rhs._glShaderSource) _glShaderSource = 0; if (!rhs._glUseProgram) _glUseProgram = 0; if (!rhs._glUniform1f) _glUniform1f = 0; if (!rhs._glUniform2f) _glUniform2f = 0; if (!rhs._glUniform3f) _glUniform3f = 0; if (!rhs._glUniform4f) _glUniform4f = 0; if (!rhs._glUniform1i) _glUniform1i = 0; if (!rhs._glUniform2i) _glUniform2i = 0; if (!rhs._glUniform3i) _glUniform3i = 0; if (!rhs._glUniform4i) _glUniform4i = 0; if (!rhs._glUniform1fv) _glUniform1fv = 0; if (!rhs._glUniform2fv) _glUniform2fv = 0; if (!rhs._glUniform3fv) _glUniform3fv = 0; if (!rhs._glUniform4fv) _glUniform4fv = 0; if (!rhs._glUniform1iv) _glUniform1iv = 0; if (!rhs._glUniform2iv) _glUniform2iv = 0; if (!rhs._glUniform3iv) _glUniform3iv = 0; if (!rhs._glUniform4iv) _glUniform4iv = 0; if (!rhs._glUniformMatrix2fv) _glUniformMatrix2fv = 0; if (!rhs._glUniformMatrix3fv) _glUniformMatrix3fv = 0; if (!rhs._glUniformMatrix4fv) _glUniformMatrix4fv = 0; if (!rhs._glValidateProgram) _glValidateProgram = 0; if (!rhs._glVertexAttrib1d) _glVertexAttrib1d = 0; if (!rhs._glVertexAttrib1dv) _glVertexAttrib1dv = 0; if (!rhs._glVertexAttrib1f) _glVertexAttrib1f = 0; if (!rhs._glVertexAttrib1fv) _glVertexAttrib1fv = 0; if (!rhs._glVertexAttrib1s) _glVertexAttrib1s = 0; if (!rhs._glVertexAttrib1sv) _glVertexAttrib1sv = 0; if (!rhs._glVertexAttrib2d) _glVertexAttrib2d = 0; if (!rhs._glVertexAttrib2dv) _glVertexAttrib2dv = 0; if (!rhs._glVertexAttrib2f) _glVertexAttrib2f = 0; if (!rhs._glVertexAttrib2fv) _glVertexAttrib2fv = 0; if (!rhs._glVertexAttrib2s) _glVertexAttrib2s = 0; if (!rhs._glVertexAttrib2sv) _glVertexAttrib2sv = 0; if (!rhs._glVertexAttrib3d) _glVertexAttrib3d = 0; if (!rhs._glVertexAttrib3dv) _glVertexAttrib3dv = 0; if (!rhs._glVertexAttrib3f) _glVertexAttrib3f = 0; if (!rhs._glVertexAttrib3fv) _glVertexAttrib3fv = 0; if (!rhs._glVertexAttrib3s) _glVertexAttrib3s = 0; if (!rhs._glVertexAttrib3sv) _glVertexAttrib3sv = 0; if (!rhs._glVertexAttrib4Nbv) _glVertexAttrib4Nbv = 0; if (!rhs._glVertexAttrib4Niv) _glVertexAttrib4Niv = 0; if (!rhs._glVertexAttrib4Nsv) _glVertexAttrib4Nsv = 0; if (!rhs._glVertexAttrib4Nub) _glVertexAttrib4Nub = 0; if (!rhs._glVertexAttrib4Nubv) _glVertexAttrib4Nubv = 0; if (!rhs._glVertexAttrib4Nuiv) _glVertexAttrib4Nuiv = 0; if (!rhs._glVertexAttrib4Nusv) _glVertexAttrib4Nusv = 0; if (!rhs._glVertexAttrib4bv) _glVertexAttrib4bv = 0; if (!rhs._glVertexAttrib4d) _glVertexAttrib4d = 0; if (!rhs._glVertexAttrib4dv) _glVertexAttrib4dv = 0; if (!rhs._glVertexAttrib4f) _glVertexAttrib4f = 0; if (!rhs._glVertexAttrib4fv) _glVertexAttrib4fv = 0; if (!rhs._glVertexAttrib4iv) _glVertexAttrib4iv = 0; if (!rhs._glVertexAttrib4s) _glVertexAttrib4s = 0; if (!rhs._glVertexAttrib4sv) _glVertexAttrib4sv = 0; if (!rhs._glVertexAttrib4ubv) _glVertexAttrib4ubv = 0; if (!rhs._glVertexAttrib4uiv) _glVertexAttrib4uiv = 0; if (!rhs._glVertexAttrib4usv) _glVertexAttrib4usv = 0; if (!rhs._glVertexAttribPointer) _glVertexAttribPointer = 0; if (!rhs._glGetInfoLogARB) _glGetInfoLogARB = 0; if (!rhs._glGetObjectParameterivARB) _glGetObjectParameterivARB = 0; if (!rhs._glDeleteObjectARB) _glDeleteObjectARB = 0; if (!rhs._glGetHandleARB) _glGetHandleARB = 0; // GL 2.1 if (!rhs._glUniformMatrix2x3fv) _glUniformMatrix2x3fv = 0; if (!rhs._glUniformMatrix3x2fv) _glUniformMatrix3x2fv = 0; if (!rhs._glUniformMatrix2x4fv) _glUniformMatrix2x4fv = 0; if (!rhs._glUniformMatrix4x2fv) _glUniformMatrix4x2fv = 0; if (!rhs._glUniformMatrix3x4fv) _glUniformMatrix3x4fv = 0; if (!rhs._glUniformMatrix4x3fv) _glUniformMatrix4x3fv = 0; // EXT_geometry_shader4 if (!rhs._glProgramParameteri) _glProgramParameteri = 0; if (!rhs._glFramebufferTexture) _glFramebufferTexture = 0; if (!rhs._glFramebufferTextureLayer) _glFramebufferTextureLayer = 0; if (!rhs._glFramebufferTextureFace) _glFramebufferTextureFace = 0; // EXT_gpu_shader4 if (!rhs._glGetUniformuiv) _glGetUniformuiv = 0; if (!rhs._glBindFragDataLocation) _glBindFragDataLocation = 0; if (!rhs._glGetFragDataLocation) _glGetFragDataLocation = 0; if (!rhs._glUniform1ui) _glUniform1ui = 0; if (!rhs._glUniform2ui) _glUniform2ui = 0; if (!rhs._glUniform3ui) _glUniform3ui = 0; if (!rhs._glUniform4ui) _glUniform4ui = 0; if (!rhs._glUniform1uiv) _glUniform1uiv = 0; if (!rhs._glUniform2uiv) _glUniform2uiv = 0; if (!rhs._glUniform3uiv) _glUniform3uiv = 0; if (!rhs._glUniform4uiv) _glUniform4uiv = 0; } void GL2Extensions::setupGL2Extensions(unsigned int contextID) { const char* version = (const char*) glGetString( GL_VERSION ); if (!version) { osg::notify(osg::FATAL)<<"Error: OpenGL version test failed, requires valid graphics context."<= 2.0f ) || ( _isShaderObjectsSupported && _isVertexShaderSupported && _isFragmentShaderSupported && _isLanguage100Supported ); } /////////////////////////////////////////////////////////////////////////// // Static array of per-context osg::GL2Extensions instances typedef osg::buffered_object< osg::ref_ptr > BufferedExtensions; static BufferedExtensions s_extensions; GL2Extensions* GL2Extensions::Get(unsigned int contextID, bool createIfNotInitalized) { if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new GL2Extensions(contextID); return s_extensions[contextID].get(); } void GL2Extensions::Set(unsigned int contextID, GL2Extensions* extensions) { s_extensions[contextID] = extensions; } /////////////////////////////////////////////////////////////////////////// static void NotSupported( const char* funcName ) { osg::notify(osg::WARN) <<"Error: "<= 2.0f ) { // GLSL as GL v2.0 core functionality GLint result = 0; glGetIntegerv( GL_CURRENT_PROGRAM, &result ); return static_cast(result); } else if (_glGetHandleARB) { // fallback for GLSL as GL v1.5 ARB extension #ifndef GL_PROGRAM_OBJECT_ARB #define GL_PROGRAM_OBJECT_ARB 0x8B40 #endif return _glGetHandleARB( GL_PROGRAM_OBJECT_ARB ); } else { NotSupported( "getCurrentProgram" ); return 0; } } bool GL2Extensions::getProgramInfoLog( GLuint program, std::string& result ) const { GLsizei bufLen = 0; // length of buffer to allocate GLsizei strLen = 0; // strlen GL actually wrote to buffer glGetProgramiv( program, GL_INFO_LOG_LENGTH, &bufLen ); if( bufLen > 1 ) { GLchar* infoLog = new GLchar[bufLen]; glGetProgramInfoLog( program, bufLen, &strLen, infoLog ); if( strLen > 0 ) result = infoLog; delete [] infoLog; } return (strLen > 0); } bool GL2Extensions::getShaderInfoLog( GLuint shader, std::string& result ) const { GLsizei bufLen = 0; // length of buffer to allocate GLsizei strLen = 0; // strlen GL actually wrote to buffer glGetShaderiv( shader, GL_INFO_LOG_LENGTH, &bufLen ); if( bufLen > 1 ) { GLchar* infoLog = new GLchar[bufLen]; glGetShaderInfoLog( shader, bufLen, &strLen, infoLog ); if( strLen > 0 ) result = infoLog; delete [] infoLog; } return (strLen > 0); } bool GL2Extensions::getAttribLocation( const char* attribName, GLuint& location ) const { // is there an active GLSL program? GLuint program = getCurrentProgram(); if( glIsProgram(program) == GL_FALSE ) return false; // has that program been successfully linked? GLint linked = GL_FALSE; glGetProgramiv( program, GL_LINK_STATUS, &linked ); if( linked == GL_FALSE ) return false; // is there such a named attribute? GLint loc = glGetAttribLocation( program, attribName ); if( loc < 0 ) return false; location = loc; return true; } bool GL2Extensions::getFragDataLocation( const char* fragDataName, GLuint& location ) const { // is there an active GLSL program? GLuint program = getCurrentProgram(); if( glIsProgram(program) == GL_FALSE ) return false; // has that program been successfully linked? GLint linked = GL_FALSE; glGetProgramiv( program, GL_LINK_STATUS, &linked ); if( linked == GL_FALSE ) return false; // check if supported if (_glGetFragDataLocation == NULL) return false; // is there such a named attribute? GLint loc = glGetFragDataLocation( program, fragDataName ); if( loc < 0 ) return false; location = loc; return true; }