diff --git a/include/osg/GL2Extensions b/include/osg/GL2Extensions index 73dd8aaf5..3c5999458 100644 --- a/include/osg/GL2Extensions +++ b/include/osg/GL2Extensions @@ -267,6 +267,11 @@ class OSG_EXPORT GL2Extensions : public osg::Referenced bool getProgramInfoLog( GLuint program, std::string& result ) const; bool getShaderInfoLog( GLuint shader, std::string& result ) const; bool getAttribLocation( const char* attribName, GLuint& slot ) const; + bool getFragDataLocation( const char* fragDataName, GLuint& slot) const; + + //EXT_gpu_shader4 to support frag data binding + void glBindFragDataLocation(GLuint program, GLuint colorNumber, const GLchar *name) const; + GLint glGetFragDataLocation(GLuint program, const GLchar *name) const; protected: ~GL2Extensions() {} @@ -377,6 +382,9 @@ class OSG_EXPORT GL2Extensions : public osg::Referenced void* _glGetObjectParameterivARB; void* _glDeleteObjectARB; void* _glGetHandleARB; + + void* _glBindFragDataLocation; + void* _glGetFragDataLocation; }; } diff --git a/include/osg/Program b/include/osg/Program index 75396a457..fcee05d27 100644 --- a/include/osg/Program +++ b/include/osg/Program @@ -2,7 +2,7 @@ * Copyright (C) 2003-2005 3Dlabs Inc. Ltd. * Copyright (C) 2004-2005 Nathan Cournia * - * This application is open source and may be redistributed and/or modified + * 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. * @@ -94,12 +94,20 @@ class OSG_EXPORT Program : public osg::StateAttribute /** Add an attribute location binding. */ void addBindAttribLocation( const std::string& name, GLuint index ); - /** Add an attribute location binding. */ + /** Remove an attribute location binding. */ void removeBindAttribLocation( const std::string& name ); + /** Add an frag data location binding. See EXT_gpu_shader4 for BindFragDataLocationEXT */ + void addBindFragDataLocation( const std::string& name, GLuint index ); + + /** Remove an frag data location binding. */ + void removeBindFragDataLocation( const std::string& name ); + typedef std::map AttribBindingList; + typedef std::map FragDataBindingList; const AttribBindingList& getAttribBindingList() const { return _attribBindingList; } + const FragDataBindingList& getFragDataBindingList() const { return _fragDataBindingList; } /** Return true if this Program represents "fixed-functionality" rendering */ bool isFixedFunction() const; @@ -234,6 +242,7 @@ class OSG_EXPORT Program : public osg::StateAttribute mutable osg::buffered_value< osg::ref_ptr > _pcpList; AttribBindingList _attribBindingList; + FragDataBindingList _fragDataBindingList; typedef std::vector< ref_ptr > ShaderList; ShaderList _shaderList; diff --git a/src/osg/Program.cpp b/src/osg/Program.cpp index 86a3351d7..2050366b6 100644 --- a/src/osg/Program.cpp +++ b/src/osg/Program.cpp @@ -153,6 +153,9 @@ GL2Extensions::GL2Extensions(const GL2Extensions& rhs) : osg::Referenced() _glGetObjectParameterivARB = rhs._glGetObjectParameterivARB; _glDeleteObjectARB = rhs._glDeleteObjectARB; _glGetHandleARB = rhs._glGetHandleARB; + + _glBindFragDataLocation = rhs._glBindFragDataLocation; + _glGetFragDataLocation = rhs._glGetFragDataLocation; } @@ -265,6 +268,9 @@ void GL2Extensions::lowestCommonDenominator(const GL2Extensions& rhs) if (!rhs._glGetObjectParameterivARB) _glGetObjectParameterivARB = 0; if (!rhs._glDeleteObjectARB) _glDeleteObjectARB = 0; if (!rhs._glGetHandleARB) _glGetHandleARB = 0; + + if (!rhs._glBindFragDataLocation) _glBindFragDataLocation = 0; + if (!rhs._glGetFragDataLocation) _glGetFragDataLocation = 0; } @@ -402,6 +408,13 @@ void GL2Extensions::setupGL2Extensions(unsigned int contextID) _glGetObjectParameterivARB = osg::getGLExtensionFuncPtr("glGetObjectParameterivARB"); _glDeleteObjectARB = osg::getGLExtensionFuncPtr("glDeleteObjectARB"); _glGetHandleARB = osg::getGLExtensionFuncPtr("glGetHandleARB"); + + // v2.1 check also for EXT and ARB names, since this extension can became ARB later + _glBindFragDataLocation = osg::getGLExtensionFuncPtr("glBindFragDataLocation", "glBindFragDataLocationARB"); + if (_glBindFragDataLocation == NULL) _glBindFragDataLocation = osg::getGLExtensionFuncPtr("glBindFragDataLocationEXT"); + _glGetFragDataLocation = osg::getGLExtensionFuncPtr("glGetFragDataLocation", "glGetFragDataLocationARB"); + if (_glGetFragDataLocation == NULL) _glGetFragDataLocation = osg::getGLExtensionFuncPtr("glGetFragDataLocationEXT"); + } @@ -1782,6 +1795,32 @@ void GL2Extensions::glVertexAttribPointer(GLuint index, GLint size, GLenum type, } } +void GL2Extensions::glBindFragDataLocation(GLuint program, GLuint colorIndex, const GLchar *name) const +{ + if (_glBindFragDataLocation) + { + typedef void (APIENTRY * BindFragDataLocationProc)(GLuint , GLuint, const GLchar*); + ((BindFragDataLocationProc)_glBindFragDataLocation)(program, colorIndex, name); + } + else + { + NotSupported( "glBindFragDataLocation" ); + } +} + +GLint GL2Extensions::glGetFragDataLocation(GLuint program, const GLchar *name) const +{ + if (_glGetFragDataLocation) + { + typedef GLint (APIENTRY * GetFragDataLocationProc)(GLuint, const GLchar*); + return ((GetFragDataLocationProc)_glGetFragDataLocation)(program, name); + } + else + { + NotSupported( "glGetFragDataLocation" ); + return -1; + } +} /////////////////////////////////////////////////////////////////////////// // C++-friendly convenience methods @@ -1866,6 +1905,28 @@ bool GL2Extensions::getAttribLocation( const char* attribName, GLuint& location } +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; +} + /////////////////////////////////////////////////////////////////////////// // static cache of glPrograms flagged for deletion, which will actually // be deleted in the correct GL context. @@ -2079,6 +2140,17 @@ void Program::removeBindAttribLocation( const std::string& name ) dirtyProgram(); } +void Program::addBindFragDataLocation( const std::string& name, GLuint index ) +{ + _fragDataBindingList[name] = index; + dirtyProgram(); +} + +void Program::removeBindFragDataLocation( const std::string& name ) +{ + _fragDataBindingList.erase(name); + dirtyProgram(); +} void Program::apply( osg::State& state ) const { @@ -2206,6 +2278,14 @@ void Program::PerContextProgram::linkProgram() _extensions->glBindAttribLocation( _glProgramHandle, itr->second, itr->first.c_str() ); } + // set any explicit frag data bindings + const FragDataBindingList& fdbindlist = _program->getFragDataBindingList(); + for( FragDataBindingList::const_iterator itr = fdbindlist.begin(); + itr != fdbindlist.end(); ++itr ) + { + _extensions->glBindFragDataLocation( _glProgramHandle, itr->second, itr->first.c_str() ); + } + // link the glProgram GLint linked = GL_FALSE; _extensions->glLinkProgram( _glProgramHandle );