diff --git a/include/osg/PrimitiveRestartIndex b/include/osg/PrimitiveRestartIndex new file mode 100644 index 000000000..5872311ba --- /dev/null +++ b/include/osg/PrimitiveRestartIndex @@ -0,0 +1,93 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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. See the + * OpenSceneGraph Public License for more details. +*/ + +#ifndef OSG_PRIMITIVERESTARTINDEX +#define OSG_PRIMITIVERESTARTINDEX 1 + +#include + +namespace osg { + +/** + * osg::PrimitiveRestartIndex does nothing if OpenGL 3.1 is not available. +*/ +class OSG_EXPORT PrimitiveRestartIndex : public StateAttribute +{ + public : + + PrimitiveRestartIndex(); + PrimitiveRestartIndex(unsigned int restartIndex); + + /** Copy constructor using CopyOp to manage deep vs shallow copy.*/ + PrimitiveRestartIndex(const PrimitiveRestartIndex& primitiveRestartIndex,const CopyOp& copyop=CopyOp::SHALLOW_COPY); + + META_StateAttribute(osg, PrimitiveRestartIndex, PRIMITIVERESTARTINDEX) + + /** return -1 if *this < *rhs, 0 if *this==*rhs, 1 if *this>*rhs.*/ + virtual int compare(const StateAttribute& sa) const; + + inline void setRestartIndex(unsigned int restartIndex ) { _restartIndex = restartIndex; } + + inline unsigned int getRestartIndex() const { return _restartIndex; } + + virtual void apply(State& state) const; + + public: + + /** Extensions class which encapsulates the querying of extensions and + * associated function pointers, and provide convenience wrappers to + * check for the extensions or use the associated functions. + */ + class OSG_EXPORT Extensions : public osg::Referenced + { + public: + Extensions(unsigned int contextID); + + Extensions(const Extensions& rhs); + + void lowestCommonDenominator(const Extensions& rhs); + + void setupGLExtensions(unsigned int contextID); + + bool isOpenGL31Supported() const { return _isOpenGL31Supported; } + bool isPrimitiveRestartIndexNVSupported() const { return _isPrimitiveRestartIndexNVSupported; } + + void glPrimitiveRestartIndex( GLuint index ) const; + + protected: + + ~Extensions() {} + + bool _isOpenGL31Supported; + bool _isPrimitiveRestartIndexNVSupported; + + typedef void (GL_APIENTRY * PrimitiveRestartIndex)( GLuint index ); + + PrimitiveRestartIndex _glPrimitiveRestartIndex; + }; + + static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); + + static void setExtensions(unsigned int contextID,Extensions* extensions); + + + protected: + + virtual ~PrimitiveRestartIndex(); + + unsigned int _restartIndex; +}; + +} + +#endif diff --git a/include/osg/StateAttribute b/include/osg/StateAttribute index 977561f4c..7c95997c1 100644 --- a/include/osg/StateAttribute +++ b/include/osg/StateAttribute @@ -165,6 +165,7 @@ class OSG_EXPORT StateAttribute : public Object CLAMPCOLOR, HINT, SAMPLEMASKI, + PRIMITIVERESTARTINDEX, /// osgFX namespace VALIDATOR, diff --git a/src/osg/CMakeLists.txt b/src/osg/CMakeLists.txt index 7b991505e..7d180be10 100644 --- a/src/osg/CMakeLists.txt +++ b/src/osg/CMakeLists.txt @@ -128,6 +128,7 @@ SET(TARGET_H ${HEADER_PATH}/Polytope ${HEADER_PATH}/PositionAttitudeTransform ${HEADER_PATH}/PrimitiveSet + ${HEADER_PATH}/PrimitiveRestartIndex ${HEADER_PATH}/Program ${HEADER_PATH}/Projection ${HEADER_PATH}/ProxyNode @@ -315,6 +316,7 @@ SET(TARGET_SRC PolygonStipple.cpp PositionAttitudeTransform.cpp PrimitiveSet.cpp + PrimitiveRestartIndex.cpp Program.cpp Projection.cpp ProxyNode.cpp diff --git a/src/osg/PrimitiveRestartIndex.cpp b/src/osg/PrimitiveRestartIndex.cpp new file mode 100644 index 000000000..6607c40c7 --- /dev/null +++ b/src/osg/PrimitiveRestartIndex.cpp @@ -0,0 +1,141 @@ +/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield + * + * This library is open source and may be redistributed and/or modified under + * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or + * (at your option) any later version. The full license is in LICENSE file + * included with this distribution, and on the openscenegraph.org website. + * + * This library 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. See the + * OpenSceneGraph Public License for more details. +*/ + +#include +#include +#include +#include + +using namespace osg; + +PrimitiveRestartIndex::PrimitiveRestartIndex() +{ + _restartIndex = 0; +} + +PrimitiveRestartIndex::PrimitiveRestartIndex(unsigned int restartIndex) +{ + _restartIndex = restartIndex; +} + +PrimitiveRestartIndex::PrimitiveRestartIndex(const PrimitiveRestartIndex& primitiveRestartIndex,const CopyOp& copyop): + StateAttribute(primitiveRestartIndex,copyop) +{ + _restartIndex = primitiveRestartIndex._restartIndex; +} + +PrimitiveRestartIndex::~PrimitiveRestartIndex() +{ +} + +int PrimitiveRestartIndex::compare(const StateAttribute& sa) const +{ + // check the types are equal and then create the rhs variable + // used by the COMPARE_StateAttribute_Parameter macros below. + COMPARE_StateAttribute_Types(PrimitiveRestartIndex,sa) + + COMPARE_StateAttribute_Parameter(_restartIndex) + + return 0; // passed all the above comparison macros, must be equal. +} + +void PrimitiveRestartIndex::apply(State& state) const +{ + // get "per-context" extensions + const unsigned int contextID = state.getContextID(); + const Extensions* extensions = getExtensions(contextID,true); + + if ( (extensions->isOpenGL31Supported()) || (extensions->isPrimitiveRestartIndexNVSupported()) ) + { + extensions->glPrimitiveRestartIndex( _restartIndex ); + return; + } + + OSG_WARN << "PrimitiveRestartIndex failed as the required graphics capabilities were\n" + " not found (contextID " << contextID << "). OpenGL 3.1 or \n" + " GL_NV_primitive_restart extension is required." << std::endl; +} + + +typedef buffered_value< ref_ptr > BufferedExtensions; +static BufferedExtensions s_extensions; + +PrimitiveRestartIndex::Extensions* PrimitiveRestartIndex::getExtensions(unsigned int contextID,bool createIfNotInitalized) +{ + if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Extensions(contextID); + return s_extensions[contextID].get(); +} + +void PrimitiveRestartIndex::setExtensions(unsigned int contextID,Extensions* extensions) +{ + s_extensions[contextID] = extensions; +} + +PrimitiveRestartIndex::Extensions::Extensions(unsigned int contextID) +{ + setupGLExtensions(contextID); +} + +PrimitiveRestartIndex::Extensions::Extensions(const Extensions& rhs): + Referenced() +{ + _isOpenGL31Supported = rhs._isOpenGL31Supported; + _isPrimitiveRestartIndexNVSupported = rhs._isPrimitiveRestartIndexNVSupported; + _glPrimitiveRestartIndex = rhs._glPrimitiveRestartIndex; +} + +void PrimitiveRestartIndex::Extensions::lowestCommonDenominator(const Extensions& rhs) +{ + if (!rhs._isOpenGL31Supported) _isOpenGL31Supported = false; + if (!rhs._isPrimitiveRestartIndexNVSupported) _isPrimitiveRestartIndexNVSupported = false; + if (!rhs._glPrimitiveRestartIndex) _glPrimitiveRestartIndex = NULL; +} + +void PrimitiveRestartIndex::Extensions::setupGLExtensions(unsigned int contextID) +{ + // extension support + _isPrimitiveRestartIndexNVSupported = isGLExtensionSupported(contextID, "GL_NV_primitive_restart"); + _isOpenGL31Supported = getGLVersionNumber() >= 3.1; + _glPrimitiveRestartIndex = NULL; + + // function pointers + if (_isOpenGL31Supported) + setGLExtensionFuncPtr(_glPrimitiveRestartIndex, "glPrimitiveRestartIndex"); + else if (_isPrimitiveRestartIndexNVSupported) + setGLExtensionFuncPtr(_glPrimitiveRestartIndex, "glPrimitiveRestartIndexNV"); + + // protect against buggy drivers (maybe not necessary) + if (!_glPrimitiveRestartIndex) _isPrimitiveRestartIndexNVSupported = false; + + // notify + if( _isOpenGL31Supported ) + { + OSG_INFO << "PrimitiveRestartIndex is going to use OpenGL 3.1 API (contextID " << contextID << ")." << std::endl; + } + else if( _isPrimitiveRestartIndexNVSupported ) + { + OSG_INFO << "PrimitiveRestartIndex is going to use GL_NV_primitive_restart extension (contextID " << contextID << ")." << std::endl; + } + else + { + OSG_INFO << "PrimitiveRestartIndex did not found required graphics capabilities\n" + " (contextID " << contextID << "). OpenGL 3.1 or \n" + " GL_NV_primitive_restart extension is required." << std::endl; + } +} + +void PrimitiveRestartIndex::Extensions::glPrimitiveRestartIndex( GLuint index ) const +{ + _glPrimitiveRestartIndex( index ); +} + diff --git a/src/osgWrappers/serializers/osg/PrimitiveRestartIndex.cpp b/src/osgWrappers/serializers/osg/PrimitiveRestartIndex.cpp new file mode 100644 index 000000000..220cdccc7 --- /dev/null +++ b/src/osgWrappers/serializers/osg/PrimitiveRestartIndex.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include + +static bool checkRestartIndex( const osg::PrimitiveRestartIndex& ) +{ + return true; +} + +static bool readRestartIndex( osgDB::InputStream& is, osg::PrimitiveRestartIndex& attr ) +{ + if ( is.getFileVersion() > 97 ) + { + unsigned int restartIndex; + is >> restartIndex; + attr.setRestartIndex( restartIndex ); + } + return true; +} + +static bool writeRestartIndex( osgDB::OutputStream& os, const osg::PrimitiveRestartIndex& attr ) +{ + os << attr.getRestartIndex() << std::endl; + return true; +} + +REGISTER_OBJECT_WRAPPER( PrimitiveRestartIndex, + new osg::PrimitiveRestartIndex, + osg::PrimitiveRestartIndex, + "osg::Object osg::StateAttribute osg::PrimitiveRestartIndex" ) +{ + ADD_USER_SERIALIZER( RestartIndex ); +}