diff --git a/include/osg/Drawable b/include/osg/Drawable index 25897cb0b..6d1b648cd 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -275,8 +275,6 @@ class OSG_EXPORT Drawable : public Object /** Immediately compile this \c Drawable into an OpenGL Display List. * @note Operation is ignored if \c _useDisplayList is \c false. - * @note This member function is not intended to be overridden in - * subclasses (notice that it is not even \c virtual). */ virtual void compileGLObjects(State& state) const; diff --git a/include/osg/PrimitiveSet b/include/osg/PrimitiveSet index 1729ac0b7..122a26d2b 100644 --- a/include/osg/PrimitiveSet +++ b/include/osg/PrimitiveSet @@ -158,6 +158,11 @@ class PrimitiveSet : public Object /** Get modified count value.*/ inline unsigned int getModifiedCount() const { return _modifiedCount; } + /** If State is non-zero, this function releases OpenGL objects for + * the specified graphics context. Otherwise, releases OpenGL objexts + * for all graphics contexts. */ + virtual void releaseGLObjects(State* /*state*/=0) const {} + protected: virtual ~PrimitiveSet() {} @@ -165,6 +170,30 @@ class PrimitiveSet : public Object Type _primitiveType; GLenum _mode; unsigned int _modifiedCount; + + + struct ObjectIDModifiedCountPair + { + ObjectIDModifiedCountPair(): + _objectID(0), + _modifiedCount(0) {} + + ObjectIDModifiedCountPair(const ObjectIDModifiedCountPair& obj): + _objectID(obj._objectID), + _modifiedCount(obj._modifiedCount) {} + + ObjectIDModifiedCountPair& operator = (const ObjectIDModifiedCountPair& obj) + { + _objectID = obj._objectID; + _modifiedCount = obj._modifiedCount; + return *this; + } + + GLuint _objectID; + unsigned int _modifiedCount; + }; + + typedef osg::buffered_object GLObjectList; }; class OSG_EXPORT DrawArrays : public PrimitiveSet @@ -338,12 +367,14 @@ class OSG_EXPORT DrawElementsUByte : public PrimitiveSet, public std::vector GLObjectList; + virtual ~DrawElementsUByte(); + mutable GLObjectList _vboList; - virtual ~DrawElementsUByte(); }; @@ -392,12 +423,13 @@ class OSG_EXPORT DrawElementsUShort : public PrimitiveSet, public std::vector GLObjectList; - mutable GLObjectList _vboList; - virtual ~DrawElementsUShort(); + + mutable GLObjectList _vboList; }; class OSG_EXPORT DrawElementsUInt : public PrimitiveSet, public std::vector @@ -445,12 +477,13 @@ class OSG_EXPORT DrawElementsUInt : public PrimitiveSet, public std::vector GLObjectList; - mutable GLObjectList _vboList; + + mutable GLObjectList _vboList; }; } diff --git a/src/osg/PrimitiveSet.cpp b/src/osg/PrimitiveSet.cpp index 67e059e1b..d5e3e9f59 100644 --- a/src/osg/PrimitiveSet.cpp +++ b/src/osg/PrimitiveSet.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace osg; @@ -81,12 +82,29 @@ unsigned int DrawArrayLengths::getNumIndices() const DrawElementsUByte::~DrawElementsUByte() { - for(unsigned int i=0;i<_vboList.size();++i) + releaseGLObjects(); +} + +void DrawElementsUByte::releaseGLObjects(State* state) const +{ + if (state) { - if (_vboList[i] != 0) + unsigned int contextID = state->getContextID(); + if (_vboList[contextID]._objectID != 0) { - BufferObject::deleteBufferObject(i,_vboList[i]); - _vboList[i] = 0; + BufferObject::deleteBufferObject(contextID,_vboList[contextID]._objectID); + _vboList[contextID]._objectID = 0; + } + } + else + { + for(unsigned int i=0;i<_vboList.size();++i) + { + if (_vboList[i]._objectID != 0) + { + BufferObject::deleteBufferObject(i,_vboList[i]._objectID); + _vboList[i]._objectID = 0; + } } } } @@ -95,18 +113,28 @@ void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const { if (useVertexBufferObjects) { - const BufferObject::Extensions* extensions = BufferObject::getExtensions(state.getContextID(), true); + unsigned int contextID = state.getContextID(); + const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true); - GLuint& buffer = _vboList[state.getContextID()]; + GLuint& buffer = _vboList[contextID]._objectID; if (!buffer) { extensions->glGenBuffers(1, &buffer); extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * 1, &front(), GL_STATIC_DRAW_ARB); + // osg::notify(osg::NOTICE)<<"Generating ubyte buffer"<glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + + if (_vboList[contextID]._modifiedCount != _modifiedCount) + { + extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * 1, &front(), GL_STATIC_DRAW_ARB); + _vboList[contextID]._modifiedCount = _modifiedCount; + } } glDrawElements(_mode, size(), GL_UNSIGNED_BYTE, 0); @@ -142,12 +170,29 @@ void DrawElementsUByte::offsetIndices(int offset) DrawElementsUShort::~DrawElementsUShort() { - for(unsigned int i=0;i<_vboList.size();++i) + releaseGLObjects(); +} + +void DrawElementsUShort::releaseGLObjects(State* state) const +{ + if (state) { - if (_vboList[i] != 0) + unsigned int contextID = state->getContextID(); + if (_vboList[contextID]._objectID != 0) { - BufferObject::deleteBufferObject(i,_vboList[i]); - _vboList[i] = 0; + BufferObject::deleteBufferObject(contextID,_vboList[contextID]._objectID); + _vboList[contextID]._objectID = 0; + } + } + else + { + for(unsigned int i=0;i<_vboList.size();++i) + { + if (_vboList[i]._objectID != 0) + { + BufferObject::deleteBufferObject(i,_vboList[i]._objectID); + _vboList[i]._objectID = 0; + } } } } @@ -156,18 +201,29 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const { if (useVertexBufferObjects) { - const BufferObject::Extensions* extensions = BufferObject::getExtensions(state.getContextID(), true); + unsigned int contextID = state.getContextID(); + const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true); - GLuint& buffer = _vboList[state.getContextID()]; + GLuint& buffer = _vboList[contextID]._objectID; if (!buffer) { + extensions->glGenBuffers(1, &buffer); extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * 2, &front(), GL_STATIC_DRAW_ARB); + // osg::notify(osg::NOTICE)<<"Generating ushort buffer"<glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + + if (_vboList[contextID]._modifiedCount != _modifiedCount) + { + extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * 2, &front(), GL_STATIC_DRAW_ARB); + _vboList[contextID]._modifiedCount = _modifiedCount; + } } glDrawElements(_mode, size(), GL_UNSIGNED_SHORT, 0); @@ -203,12 +259,29 @@ void DrawElementsUShort::offsetIndices(int offset) DrawElementsUInt::~DrawElementsUInt() { - for(unsigned int i=0;i<_vboList.size();++i) + releaseGLObjects(); +} + +void DrawElementsUInt::releaseGLObjects(State* state) const +{ + if (state) { - if (_vboList[i] != 0) + unsigned int contextID = state->getContextID(); + if (_vboList[contextID]._objectID != 0) { - BufferObject::deleteBufferObject(i,_vboList[i]); - _vboList[i] = 0; + BufferObject::deleteBufferObject(contextID,_vboList[contextID]._objectID); + _vboList[contextID]._objectID = 0; + } + } + else + { + for(unsigned int i=0;i<_vboList.size();++i) + { + if (_vboList[i]._objectID != 0) + { + BufferObject::deleteBufferObject(i,_vboList[i]._objectID); + _vboList[i]._objectID = 0; + } } } } @@ -217,18 +290,29 @@ void DrawElementsUInt::draw(State& state, bool useVertexBufferObjects) const { if (useVertexBufferObjects) { - const BufferObject::Extensions* extensions = BufferObject::getExtensions(state.getContextID(), true); - - GLuint& buffer = _vboList[state.getContextID()]; + unsigned int contextID = state.getContextID(); + const BufferObject::Extensions* extensions = BufferObject::getExtensions(contextID, true); + + GLuint& buffer = _vboList[contextID]._objectID; if (!buffer) { extensions->glGenBuffers(1, &buffer); extensions->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * 4, &front(), GL_STATIC_DRAW_ARB); + // osg::notify(osg::NOTICE)<<"Generating buffer int"<glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB, buffer); + + if (_vboList[contextID]._modifiedCount != _modifiedCount) + { + extensions->glBufferData(GL_ELEMENT_ARRAY_BUFFER_ARB, size() * 4, &front(), GL_STATIC_DRAW_ARB); + _vboList[contextID]._modifiedCount = _modifiedCount; + } } glDrawElements(_mode, size(), GL_UNSIGNED_INT, 0); diff --git a/src/osgWrappers/osg/PrimitiveSet.cpp b/src/osgWrappers/osg/PrimitiveSet.cpp index 0bead28b4..57294495d 100644 --- a/src/osgWrappers/osg/PrimitiveSet.cpp +++ b/src/osgWrappers/osg/PrimitiveSet.cpp @@ -98,6 +98,7 @@ BEGIN_OBJECT_REFLECTOR(osg::DrawElementsUByte) I_Method0(unsigned int, getNumIndices); I_Method1(unsigned int, index, IN, unsigned int, pos); I_Method1(void, offsetIndices, IN, int, offset); + I_MethodWithDefaults1(void, releaseGLObjects, IN, osg::State *, state, 0); I_ReadOnlyProperty(const GLvoid *, DataPointer); I_ReadOnlyProperty(unsigned int, TotalDataSize); END_REFLECTOR @@ -124,6 +125,7 @@ BEGIN_OBJECT_REFLECTOR(osg::DrawElementsUInt) I_Method0(unsigned int, getNumIndices); I_Method1(unsigned int, index, IN, unsigned int, pos); I_Method1(void, offsetIndices, IN, int, offset); + I_MethodWithDefaults1(void, releaseGLObjects, IN, osg::State *, state, 0); I_ReadOnlyProperty(const GLvoid *, DataPointer); I_ReadOnlyProperty(unsigned int, TotalDataSize); END_REFLECTOR @@ -150,6 +152,7 @@ BEGIN_OBJECT_REFLECTOR(osg::DrawElementsUShort) I_Method0(unsigned int, getNumIndices); I_Method1(unsigned int, index, IN, unsigned int, pos); I_Method1(void, offsetIndices, IN, int, offset); + I_MethodWithDefaults1(void, releaseGLObjects, IN, osg::State *, state, 0); I_ReadOnlyProperty(const GLvoid *, DataPointer); I_ReadOnlyProperty(unsigned int, TotalDataSize); END_REFLECTOR @@ -232,6 +235,7 @@ BEGIN_ABSTRACT_OBJECT_REFLECTOR(osg::PrimitiveSet) I_Method0(void, dirty); I_Method1(void, setModifiedCount, IN, unsigned int, value); I_Method0(unsigned int, getModifiedCount); + I_MethodWithDefaults1(void, releaseGLObjects, IN, osg::State *, x, 0); I_ReadOnlyProperty(const GLvoid *, DataPointer); I_Property(GLenum, Mode); I_Property(unsigned int, ModifiedCount);