diff --git a/include/osg/Array b/include/osg/Array index 8c3b3aa8e..7b1aa1068 100644 --- a/include/osg/Array +++ b/include/osg/Array @@ -77,6 +77,7 @@ class SG_EXPORT Array : public Object GLint getDataSize() const { return _dataSize; } GLenum getDataType() const { return _dataType; } virtual const GLvoid* getDataPointer() const = 0; + virtual unsigned int getTotalDataSize() const = 0; virtual unsigned int getNumElements() const = 0; protected: @@ -122,6 +123,7 @@ class TemplateArray : public Array, public std::vector virtual void accept(unsigned int index,ConstValueVisitor& vv) const { vv.apply( (*this)[index] );} virtual const GLvoid* getDataPointer() const { if (!empty()) return &front(); else return 0; } + virtual unsigned int getTotalDataSize() const { return size()*sizeof(T); } virtual unsigned int getNumElements() const { return size(); } protected: @@ -183,6 +185,7 @@ class TemplateIndexArray : public IndexArray, public std::vector virtual void accept(unsigned int index,ConstValueVisitor& vv) const { vv.apply( (*this)[index] );} virtual const GLvoid* getDataPointer() const { if (!empty()) return &front(); else return 0; } + virtual unsigned int getTotalDataSize() const { return size()*sizeof(T); } virtual unsigned int getNumElements() const { return size(); } virtual unsigned int index(unsigned int pos) const { return (*this)[pos]; } diff --git a/include/osg/Drawable b/include/osg/Drawable index e4e64f3a7..8afeb7ba1 100644 --- a/include/osg/Drawable +++ b/include/osg/Drawable @@ -28,6 +28,55 @@ class Vec4; class UByte4; class Geometry; +#ifndef GL_ARB_vertex_buffer_object + + // for compatibility with gl.h headers that don't support VBO, + #if defined(_WIN64) + typedef __int64 GLintptrARB; + typedef __int64 GLsizeiptrARB; + #elif defined(__ia64__) || defined(__x86_64__) + typedef long int GLintptrARB; + typedef long int GLsizeiptrARB; + #else + typedef int GLintptrARB; + typedef int GLsizeiptrARB; + #endif + + #define GL_ARRAY_BUFFER_ARB 0x8892 + #define GL_ELEMENT_ARRAY_BUFFER_ARB 0x8893 + #define GL_ARRAY_BUFFER_BINDING_ARB 0x8894 + #define GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB 0x8895 + #define GL_VERTEX_ARRAY_BUFFER_BINDING_ARB 0x8896 + #define GL_NORMAL_ARRAY_BUFFER_BINDING_ARB 0x8897 + #define GL_COLOR_ARRAY_BUFFER_BINDING_ARB 0x8898 + #define GL_INDEX_ARRAY_BUFFER_BINDING_ARB 0x8899 + #define GL_TEXTURE_COORD_ARRAY_BUFFER_BINDING_ARB 0x889A + #define GL_EDGE_FLAG_ARRAY_BUFFER_BINDING_ARB 0x889B + #define GL_SECONDARY_COLOR_ARRAY_BUFFER_BINDING_ARB 0x889C + #define GL_FOG_COORDINATE_ARRAY_BUFFER_BINDING_ARB 0x889D + #define GL_WEIGHT_ARRAY_BUFFER_BINDING_ARB 0x889E + #define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB 0x889F + #define GL_STREAM_DRAW_ARB 0x88E0 + #define GL_STREAM_READ_ARB 0x88E1 + #define GL_STREAM_COPY_ARB 0x88E2 + #define GL_STATIC_DRAW_ARB 0x88E4 + #define GL_STATIC_READ_ARB 0x88E5 + #define GL_STATIC_COPY_ARB 0x88E6 + #define GL_DYNAMIC_DRAW_ARB 0x88E8 + #define GL_DYNAMIC_READ_ARB 0x88E9 + #define GL_DYNAMIC_COPY_ARB 0x88EA + #define GL_READ_ONLY_ARB 0x88B8 + #define GL_WRITE_ONLY_ARB 0x88B9 + #define GL_READ_WRITE_ARB 0x88BA + #define GL_BUFFER_SIZE_ARB 0x8764 + #define GL_BUFFER_USAGE_ARB 0x8765 + #define GL_BUFFER_ACCESS_ARB 0x88BB + #define GL_BUFFER_MAPPED_ARB 0x88BC + #define GL_BUFFER_MAP_POINTER_ARB 0x88BD + +#endif + + // this is define to alter the way display lists are compiled inside the // the draw method, it has been found that the NVidia drivers fail completely // to optimize COMPILE_AND_EXECUTE in fact make it go slower than for no display @@ -160,6 +209,14 @@ class SG_EXPORT Drawable : public Object /** Return whether OpenGL display lists are being used for rendering.*/ inline bool getUseDisplayList() const { return _useDisplayList; } + /** When set to true, ignore the setUseDisplayList() settings, and hints to the drawImplemention + method to use OpenGL vertex buffer objects for rendering..*/ + void setUseVertexBufferObjects(bool flag); + + /** Return whether OpenGL vertex buffer objects should be used when supported by OpenGL driver.*/ + inline bool getUseVertexBufferObjects() const { return _useVertexBufferObjects; } + + /** Force a recompile on next draw() of any OpenGL display list associated with this geoset.*/ void dirtyDisplayList(); @@ -249,6 +306,15 @@ class SG_EXPORT Drawable : public Object * in the OpenGL context related to contextID.*/ static void flushDeletedDisplayLists(unsigned int contextID); + /** use deleteVertexBufferObject instead of glDeleteList to allow + * OpenGL buffer objects to cached until they can be deleted + * by the OpenGL context in which they were created, specified + * by contextID.*/ + static void deleteVertexBufferObject(unsigned int contextID,GLuint globj); + + /** flush all the cached vertex buffer objects which need to be deleted + * in the OpenGL context related to contextID.*/ + static void flushDeletedVertexBufferObjects(unsigned int contextID); typedef unsigned int AttributeType; @@ -369,6 +435,125 @@ class SG_EXPORT Drawable : public Object * so one cannot modify it.*/ virtual void accept(PrimitiveFunctor&) const {} + + /** Extensions class which encapsulates the querring of extensions and + * associated function pointers, and provide convinience wrappers to + * check for the extensions or use the associated functions.*/ + class SG_EXPORT Extensions : public osg::Referenced + { + public: + Extensions(); + + Extensions(const Extensions& rhs); + + void lowestCommonDenominator(const Extensions& rhs); + + void setupGLExtenions(); + + void setVertexProgramSupported(bool flag) { _isVertexProgramSupported=flag; } + bool isVertexProgramSupported() const { return _isVertexProgramSupported; } + + void setSecondaryColorSupported(bool flag) { _isSecondaryColorSupported=flag; } + bool isSecondaryColorSupported() const { return _isSecondaryColorSupported; } + + void setFogCoordSupported(bool flag) { _isFogCoordSupported=flag; } + bool isFogCoordSupported() const { return _isFogCoordSupported; } + + void setMultiTexSupported(bool flag) { _isMultiTexSupported=flag; } + bool isMultiTexSupported() const { return _isMultiTexSupported; } + + void glSecondaryColor3ubv(const GLubyte* coord) const; + void glSecondaryColor3fv(const GLfloat* coord) const; + + void glFogCoordfv(const GLfloat* coord) const; + + void glMultiTexCoord1f(GLenum target,GLfloat coord) const; + void glMultiTexCoord2fv(GLenum target,const GLfloat* coord) const; + void glMultiTexCoord3fv(GLenum target,const GLfloat* coord) const; + void glMultiTexCoord4fv(GLenum target,const GLfloat* coord) const; + + void glVertexAttrib1s(unsigned int index, GLshort s) const; + void glVertexAttrib1f(unsigned int index, GLfloat f) const; + void glVertexAttrib2fv(unsigned int index, const GLfloat * v) const; + void glVertexAttrib3fv(unsigned int index, const GLfloat * v) const; + void glVertexAttrib4fv(unsigned int index, const GLfloat * v) const; + void glVertexAttrib4ubv(unsigned int index, const GLubyte * v) const; + void glVertexAttrib4Nubv(unsigned int index, const GLubyte * v) const; + + void glGenBuffers (GLsizei n, GLuint *buffers) const; + void glBindBuffer (GLenum target, GLuint buffer) const; + void glBufferData (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage) const; + void glBufferSubData (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data) const; + void glDeleteBuffers (GLsizei n, const GLuint *buffers) const; + + + protected: + + typedef void (APIENTRY * FogCoordProc) (const GLfloat* coord); + + typedef void (APIENTRY * VertexAttrib1sProc) (unsigned int index, GLshort s); + typedef void (APIENTRY * VertexAttrib1fProc) (unsigned int index, GLfloat f); + typedef void (APIENTRY * VertexAttribfvProc) (unsigned int index, const GLfloat * v); + typedef void (APIENTRY * VertexAttribubvProc) (unsigned int index, const GLubyte * v); + + typedef void (APIENTRY * SecondaryColor3ubvProc) (const GLubyte* coord); + typedef void (APIENTRY * SecondaryColor3fvProc) (const GLfloat* coord); + + typedef void (APIENTRY * MultiTexCoord1fProc) (GLenum target,GLfloat coord); + typedef void (APIENTRY * MultiTexCoordfvProc) (GLenum target,const GLfloat* coord); + + typedef void (APIENTRY * GenBuffersProc) (GLsizei n, GLuint *buffers); + typedef void (APIENTRY * BindBufferProc) (GLenum target, GLuint buffer); + typedef void (APIENTRY * BufferDataProc) (GLenum target, GLsizeiptrARB size, const GLvoid *data, GLenum usage); + typedef void (APIENTRY * BufferSubDataProc) (GLenum target, GLintptrARB offset, GLsizeiptrARB size, const GLvoid *data); + typedef void (APIENTRY * DeleteBuffersProc) (GLsizei n, const GLuint *buffers); + + ~Extensions() {} + + bool _isVertexProgramSupported; + bool _isSecondaryColorSupported; + bool _isFogCoordSupported; + bool _isMultiTexSupported; + + FogCoordProc _glFogCoordfv; + + SecondaryColor3ubvProc _glSecondaryColor3ubv; + SecondaryColor3fvProc _glSecondaryColor3fv; + + VertexAttrib1sProc _glVertexAttrib1s; + VertexAttrib1fProc _glVertexAttrib1f; + VertexAttribfvProc _glVertexAttrib2fv; + VertexAttribfvProc _glVertexAttrib3fv; + VertexAttribfvProc _glVertexAttrib4fv; + VertexAttribubvProc _glVertexAttrib4ubv; + VertexAttribubvProc _glVertexAttrib4Nubv; + + MultiTexCoord1fProc _glMultiTexCoord1f; + MultiTexCoordfvProc _glMultiTexCoord2fv; + MultiTexCoordfvProc _glMultiTexCoord3fv; + MultiTexCoordfvProc _glMultiTexCoord4fv; + + GenBuffersProc _glGenBuffers; + BindBufferProc _glBindBuffer; + BufferDataProc _glBufferData; + BufferSubDataProc _glBufferSubData; + DeleteBuffersProc _glDeleteBuffers; + }; + + /** Function to call to get the extension of a specified context. + * If the Exentsion object for that context has not yet been created then + * and the 'createIfNotInitalized' flag been set to false then returns NULL. + * If 'createIfNotInitalized' is true then the Extensions object is + * automatically created. However, in this case the extension object + * only be created with the graphics context associated with ContextID..*/ + static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); + + /** setExtensions allows users to override the extensions across graphics contexts. + * typically used when you have different extensions supported across graphics pipes + * but need to ensure that they all use the same low common denominator extensions.*/ + static void setExtensions(unsigned int contextID,Extensions* extensions); + + protected: Drawable& operator = (const Drawable&) { return *this;} @@ -398,9 +583,12 @@ class SG_EXPORT Drawable : public Object bool _supportsDisplayList; bool _useDisplayList; + bool _supportsVertexBufferObjects; + bool _useVertexBufferObjects; typedef osg::buffered_value GLObjectList; - mutable GLObjectList _globjList; + mutable GLObjectList _globjList; + mutable GLObjectList _vboList; ref_ptr _updateCallback; ref_ptr _drawCallback; @@ -411,9 +599,8 @@ class SG_EXPORT Drawable : public Object inline void Drawable::draw(State& state) const { - if (_useDisplayList) + if (_useDisplayList && !(_supportsVertexBufferObjects && _useVertexBufferObjects && state.isVertexBufferObjectSupported())) { - // get the contextID (user defined ID of 0 upwards) for the // current OpenGL context. unsigned int contextID = state.getContextID(); @@ -448,16 +635,16 @@ inline void Drawable::draw(State& state) const glEndList(); #endif } + + return; } - else - { - // draw object as nature intended.. - if (_drawCallback.valid()) - _drawCallback->drawImplementation(state,this); - else - drawImplementation(state); - } + + // draw object as nature intended.. + if (_drawCallback.valid()) + _drawCallback->drawImplementation(state,this); + else + drawImplementation(state); }; diff --git a/include/osg/Geometry b/include/osg/Geometry index 1a0e57796..8fcdd0a7b 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -23,7 +23,6 @@ namespace osg { - class SG_EXPORT Geometry : public Drawable { public: @@ -51,52 +50,71 @@ class SG_EXPORT Geometry : public Drawable BIND_PER_VERTEX }; - void setVertexArray(Array* array) { _vertexArray = array; dirtyDisplayList(); dirtyBound(); } + template + struct AttributeData + { + AttributeData(): + _normalize(GL_FALSE), + _binding(BIND_OFF), + _offset(0) {} + + ref_ptr _array; + ref_ptr _indices; + AttributeBinding _binding; + + // only used in vertex attributes + GLboolean _normalize; + + unsigned int _offset; + }; + + + void setVertexArray(Array* array) { _vertexArray = array; dirtyDisplayList(); dirtyBound(); } Array* getVertexArray() { return _vertexArray.get(); } const Array* getVertexArray() const { return _vertexArray.get(); } - void setVertexIndices(IndexArray* array) { _vertexIndices = array; _fastPathComputed=false; dirtyDisplayList(); dirtyBound(); } + void setVertexIndices(IndexArray* array) { _vertexIndices = array; computeFastPathsUsed(); dirtyDisplayList(); dirtyBound(); } IndexArray* getVertexIndices() { return _vertexIndices.get(); } const IndexArray* getVertexIndices() const { return _vertexIndices.get(); } - void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; dirtyDisplayList(); _fastPathComputed=false; } + void setNormalBinding(AttributeBinding ab) { _normalBinding = ab; dirtyDisplayList(); computeFastPathsUsed(); } AttributeBinding getNormalBinding() const { return _normalBinding; } - void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; _fastPathComputed=false; dirtyDisplayList(); } + void setNormalArray(Vec3Array* array) { _normalArray = array; if (!_normalArray.valid()) _normalBinding=BIND_OFF; computeFastPathsUsed(); dirtyDisplayList(); } Vec3Array* getNormalArray() { return _normalArray.get(); } const Vec3Array* getNormalArray() const { return _normalArray.get(); } - void setNormalIndices(IndexArray* array) { _normalIndices = array; _fastPathComputed=false; dirtyDisplayList(); } + void setNormalIndices(IndexArray* array) { _normalIndices = array; computeFastPathsUsed(); dirtyDisplayList(); } IndexArray* getNormalIndices() { return _normalIndices.get(); } const IndexArray* getNormalIndices() const { return _normalIndices.get(); } - void setColorBinding(AttributeBinding ab) { _colorBinding = ab; _fastPathComputed=false;} + void setColorBinding(AttributeBinding ab) { _colorBinding = ab; computeFastPathsUsed();} AttributeBinding getColorBinding() const { return _colorBinding; } - void setColorArray(Array* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; _fastPathComputed=false; dirtyDisplayList(); } + void setColorArray(Array* array) { _colorArray = array; if (!_colorArray.valid()) _colorBinding=BIND_OFF; computeFastPathsUsed(); dirtyDisplayList(); } Array* getColorArray() { return _colorArray.get(); } const Array* getColorArray() const { return _colorArray.get(); } - void setColorIndices(IndexArray* array) { _colorIndices = array; _fastPathComputed=false; dirtyDisplayList(); } + void setColorIndices(IndexArray* array) { _colorIndices = array; computeFastPathsUsed(); dirtyDisplayList(); } IndexArray* getColorIndices() { return _colorIndices.get(); } const IndexArray* getColorIndices() const { return _colorIndices.get(); } - void setSecondaryColorBinding(AttributeBinding ab) { _secondaryColorBinding = ab; _fastPathComputed=false;} + void setSecondaryColorBinding(AttributeBinding ab) { _secondaryColorBinding = ab; computeFastPathsUsed();} AttributeBinding getSecondaryColorBinding() const { return _secondaryColorBinding; } - void setSecondaryColorArray(Array* array) { _secondaryColorArray = array; if (!_secondaryColorArray.valid()) _secondaryColorBinding=BIND_OFF; _fastPathComputed=false; dirtyDisplayList(); } + void setSecondaryColorArray(Array* array) { _secondaryColorArray = array; if (!_secondaryColorArray.valid()) _secondaryColorBinding=BIND_OFF; computeFastPathsUsed(); dirtyDisplayList(); } Array* getSecondaryColorArray() { return _secondaryColorArray.get(); } const Array* getSecondaryColorArray() const { return _secondaryColorArray.get(); } - void setSecondaryColorIndices(IndexArray* array) { _secondaryColorIndices = array; _fastPathComputed=false; dirtyDisplayList(); } + void setSecondaryColorIndices(IndexArray* array) { _secondaryColorIndices = array; computeFastPathsUsed(); dirtyDisplayList(); } IndexArray* getSecondaryColorIndices() { return _secondaryColorIndices.get(); } const IndexArray* getSecondaryColorIndices() const { return _secondaryColorIndices.get(); } - void setFogCoordBinding(AttributeBinding ab) { _fogCoordBinding = ab; _fastPathComputed=false;} + void setFogCoordBinding(AttributeBinding ab) { _fogCoordBinding = ab; computeFastPathsUsed();} AttributeBinding getFogCoordBinding() const { return _fogCoordBinding; } void setFogCoordArray(Array* array) { _fogCoordArray = array; if (!_fogCoordArray.valid()) _fogCoordBinding=BIND_OFF; dirtyDisplayList(); } @@ -109,9 +127,29 @@ class SG_EXPORT Geometry : public Drawable const IndexArray* getFogCoordIndices() const { return _fogCoordIndices.get(); } + struct ArrayPair + { + ArrayPair(): + offset(0) {} + + ArrayPair(const ArrayPair& rhs): + first(rhs.first), + second(rhs.second), + offset(rhs.offset) {} - typedef std::pair< ref_ptr, ref_ptr > TexCoordArrayPair; - typedef std::vector< TexCoordArrayPair > TexCoordArrayList; + ArrayPair& operator = (const ArrayPair& rhs) + { + first = rhs.first; + second = rhs.second; + offset = rhs.offset; + return *this; + } + + ref_ptr first; + ref_ptr second; + mutable unsigned int offset; + }; + typedef std::vector< ArrayPair > TexCoordArrayList; void setTexCoordArray(unsigned int unit,Array*); @@ -143,17 +181,6 @@ class SG_EXPORT Geometry : public Drawable void setBinding(AttributeType type,AttributeBinding binding); AttributeBinding getBinding(AttributeType type) const; - struct AttributeData - { - AttributeData(): - _normalize(GL_FALSE), - _binding(BIND_OFF) {} - - ref_ptr _array; - ref_ptr _indices; - GLboolean _normalize; - AttributeBinding _binding; - }; unsigned int getNumArrays() const { return _attributeList.size(); } @@ -171,8 +198,7 @@ class SG_EXPORT Geometry : public Drawable #endif - typedef std::pair< ref_ptr, ref_ptr > VertexAttribArrayPair; - typedef std::pair< GLboolean, VertexAttribArrayPair > VertexAttribNormArrayPair; + typedef std::pair< GLboolean, ArrayPair > VertexAttribNormArrayPair; typedef std::vector< VertexAttribNormArrayPair > VertexAttribArrayList; typedef std::vector< AttributeBinding > VertexAttribBindingList; @@ -225,7 +251,9 @@ class SG_EXPORT Geometry : public Drawable * Fast paths use vertex arrays, and glDrawArrays/glDrawElements. Slow paths * use glBegin()/glVertex.../glEnd(). Use of per primitive bindings or per vertex indexed * arrays will drop the rendering path off the fast path.*/ - bool areFastPathsUsed() const; + inline bool areFastPathsUsed() const { return _fastPath; } + + bool computeFastPathsUsed(); bool verifyBindings() const; @@ -256,103 +284,6 @@ class SG_EXPORT Geometry : public Drawable /** accept a PrimitiveFunctor and call its methods to tell it about the interal primitives that this Drawable has.*/ virtual void accept(PrimitiveFunctor& pf) const; - /** Extensions class which encapsulates the querring of extensions and - * associated function pointers, and provide convinience wrappers to - * check for the extensions or use the associated functions.*/ - class SG_EXPORT Extensions : public osg::Referenced - { - public: - Extensions(); - - Extensions(const Extensions& rhs); - - void lowestCommonDenominator(const Extensions& rhs); - - void setupGLExtenions(); - - void setVertexProgramSupported(bool flag) { _isVertexProgramSupported=flag; } - bool isVertexProgramSupported() const { return _isVertexProgramSupported; } - - void setSecondaryColorSupported(bool flag) { _isSecondaryColorSupported=flag; } - bool isSecondaryColorSupported() const { return _isSecondaryColorSupported; } - - void setFogCoordSupported(bool flag) { _isFogCoordSupported=flag; } - bool isFogCoordSupported() const { return _isFogCoordSupported; } - - void setMultiTexSupported(bool flag) { _isMultiTexSupported=flag; } - bool isMultiTexSupported() const { return _isMultiTexSupported; } - - void glSecondaryColor3ubv(const GLubyte* coord) const; - void glSecondaryColor3fv(const GLfloat* coord) const; - - void glFogCoordfv(const GLfloat* coord) const; - - void glMultiTexCoord1f(GLenum target,GLfloat coord) const; - void glMultiTexCoord2fv(GLenum target,const GLfloat* coord) const; - void glMultiTexCoord3fv(GLenum target,const GLfloat* coord) const; - void glMultiTexCoord4fv(GLenum target,const GLfloat* coord) const; - - void glVertexAttrib1s(unsigned int index, GLshort s) const; - void glVertexAttrib1f(unsigned int index, GLfloat f) const; - void glVertexAttrib2fv(unsigned int index, const GLfloat * v) const; - void glVertexAttrib3fv(unsigned int index, const GLfloat * v) const; - void glVertexAttrib4fv(unsigned int index, const GLfloat * v) const; - void glVertexAttrib4ubv(unsigned int index, const GLubyte * v) const; - void glVertexAttrib4Nubv(unsigned int index, const GLubyte * v) const; - - protected: - - typedef void (APIENTRY * FogCoordProc) (const GLfloat* coord); - - typedef void (APIENTRY * VertexAttrib1sProc) (unsigned int index, GLshort s); - typedef void (APIENTRY * VertexAttrib1fProc) (unsigned int index, GLfloat f); - typedef void (APIENTRY * VertexAttribfvProc) (unsigned int index, const GLfloat * v); - typedef void (APIENTRY * VertexAttribubvProc) (unsigned int index, const GLubyte * v); - - typedef void (APIENTRY * SecondaryColor3ubvProc) (const GLubyte* coord); - typedef void (APIENTRY * SecondaryColor3fvProc) (const GLfloat* coord); - - typedef void (APIENTRY * MultiTexCoord1fProc) (GLenum target,GLfloat coord); - typedef void (APIENTRY * MultiTexCoordfvProc) (GLenum target,const GLfloat* coord); - - ~Extensions() {} - - bool _isVertexProgramSupported; - bool _isSecondaryColorSupported; - bool _isFogCoordSupported; - bool _isMultiTexSupported; - - FogCoordProc _glFogCoordfv; - - SecondaryColor3ubvProc _glSecondaryColor3ubv; - SecondaryColor3fvProc _glSecondaryColor3fv; - - VertexAttrib1sProc _glVertexAttrib1s; - VertexAttrib1fProc _glVertexAttrib1f; - VertexAttribfvProc _glVertexAttrib2fv; - VertexAttribfvProc _glVertexAttrib3fv; - VertexAttribfvProc _glVertexAttrib4fv; - VertexAttribubvProc _glVertexAttrib4ubv; - VertexAttribubvProc _glVertexAttrib4Nubv; - - MultiTexCoord1fProc _glMultiTexCoord1f; - MultiTexCoordfvProc _glMultiTexCoord2fv; - MultiTexCoordfvProc _glMultiTexCoord3fv; - MultiTexCoordfvProc _glMultiTexCoord4fv; - }; - - /** Function to call to get the extension of a specified context. - * If the Exentsion object for that context has not yet been created then - * and the 'createIfNotInitalized' flag been set to false then returns NULL. - * If 'createIfNotInitalized' is true then the Extensions object is - * automatically created. However, in this case the extension object - * only be created with the graphics context associated with ContextID..*/ - static Extensions* getExtensions(unsigned int contextID,bool createIfNotInitalized); - - /** setExtensions allows users to override the extensions across graphics contexts. - * typically used when you have different extensions supported across graphics pipes - * but need to ensure that they all use the same low common denominator extensions.*/ - static void setExtensions(unsigned int contextID,Extensions* extensions); protected: @@ -368,30 +299,35 @@ class SG_EXPORT Geometry : public Drawable #endif ref_ptr _vertexArray; ref_ptr _vertexIndices; + mutable unsigned int _vertexOffset; mutable AttributeBinding _normalBinding; - ref_ptr _normalArray; + ref_ptr _normalArray; ref_ptr _normalIndices; + mutable unsigned int _normalOffset; mutable AttributeBinding _colorBinding; ref_ptr _colorArray; ref_ptr _colorIndices; + mutable unsigned int _colorOffset; mutable AttributeBinding _secondaryColorBinding; ref_ptr _secondaryColorArray; ref_ptr _secondaryColorIndices; + mutable unsigned int _secondaryColorOffset; mutable AttributeBinding _fogCoordBinding; ref_ptr _fogCoordArray; ref_ptr _fogCoordIndices; + mutable unsigned int _fogCoordOffset; TexCoordArrayList _texCoordList; VertexAttribArrayList _vertexAttribList; mutable VertexAttribBindingList _vertexAttribBindingList; - mutable bool _fastPathComputed; mutable bool _fastPath; + }; /** Convenience function to be used for creating quad geometry with texture coords. diff --git a/include/osg/State b/include/osg/State index 434b9442b..a4088e699 100644 --- a/include/osg/State +++ b/include/osg/State @@ -268,7 +268,7 @@ class SG_EXPORT State : public Referenced _vertexArray._enabled = true; glEnableClientState(GL_VERTEX_ARRAY); } - if (_vertexArray._pointer!=ptr || _vertexArray._dirty) + //if (_vertexArray._pointer!=ptr || _vertexArray._dirty) { _vertexArray._pointer=ptr; glVertexPointer( size, type, stride, ptr ); @@ -304,7 +304,7 @@ class SG_EXPORT State : public Referenced _normalArray._enabled = true; glEnableClientState(GL_NORMAL_ARRAY); } - if (_normalArray._pointer!=ptr || _normalArray._dirty) + //if (_normalArray._pointer!=ptr || _normalArray._dirty) { _normalArray._pointer=ptr; glNormalPointer( type, stride, ptr ); @@ -340,7 +340,7 @@ class SG_EXPORT State : public Referenced _colorArray._enabled = true; glEnableClientState(GL_COLOR_ARRAY); } - if (_colorArray._pointer!=ptr || _colorArray._dirty) + //if (_colorArray._pointer!=ptr || _colorArray._dirty) { _colorArray._pointer=ptr; glColorPointer( size, type, stride, ptr ); @@ -367,7 +367,7 @@ class SG_EXPORT State : public Referenced } - inline bool isSecondaryColorSupported() const { return _isSecondColorSupportResolved?_isSecondColorSupported:computeSecondaryColorSupported(); } + inline bool isSecondaryColorSupported() const { return _isSecondaryColorSupportResolved?_isSecondaryColorSupported:computeSecondaryColorSupported(); } /** wrapper around glEnableClientState(GL_SECONDARY_COLOR_ARRAY);glSecondayColorPointer(..); * note, only updates values that change.*/ @@ -401,7 +401,7 @@ class SG_EXPORT State : public Referenced _indexArray._enabled = true; glEnableClientState(GL_INDEX_ARRAY); } - if (_indexArray._pointer!=ptr || _indexArray._dirty) + //if (_indexArray._pointer!=ptr || _indexArray._dirty) { _indexArray._pointer=ptr; glIndexPointer( type, stride, ptr ); @@ -469,7 +469,7 @@ class SG_EXPORT State : public Referenced eap._enabled = true; glEnableClientState(GL_TEXTURE_COORD_ARRAY); } - if (eap._pointer!=ptr || eap._dirty) + //if (eap._pointer!=ptr || eap._dirty) { glTexCoordPointer( size, type, stride, ptr ); eap._pointer = ptr; @@ -566,6 +566,8 @@ class SG_EXPORT State : public Referenced } } + bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); } + /** Set the current OpenGL context uniqueID. Note, it is the application developers responsibility to @@ -619,6 +621,7 @@ class SG_EXPORT State : public Referenced bool checkGLErrors(const StateAttribute* attribute) const; + protected: virtual ~State(); @@ -800,13 +803,18 @@ class SG_EXPORT State : public Referenced const StateAttribute* getLastAppliedAttribute(const AttributeMap& attributeMap,StateAttribute::Type type) const; - mutable bool _isSecondColorSupportResolved; - mutable bool _isSecondColorSupported; + mutable bool _isSecondaryColorSupportResolved; + mutable bool _isSecondaryColorSupported; bool computeSecondaryColorSupported() const; mutable bool _isFogCoordSupportResolved; mutable bool _isFogCoordSupported; bool computeFogCoordSupported() const; + + mutable bool _isVertexBufferObjectSupportResolved; + mutable bool _isVertexBufferObjectSupported; + bool computeVertexBufferObjectSupported() const; + }; inline void State::pushModeList(ModeMap& modeMap,const StateSet::ModeList& modeList) diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index 16364eefa..f86faf0e9 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,7 @@ using namespace osg; typedef std::vector DisplayListVector; typedef std::map DeletedDisplayListCache; static DeletedDisplayListCache s_deletedDisplayListCache; +static DeletedDisplayListCache s_deletedVertexBufferObjectCache; void Drawable::deleteDisplayList(unsigned int contextID,GLuint globj) { @@ -49,6 +51,7 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID) if (citr!=s_deletedDisplayListCache.end()) { DisplayListVector displayListSet; + displayListSet.reserve(1000); // this swap will transfer the content of and empty citr->second // in one quick pointer change. @@ -63,6 +66,40 @@ void Drawable::flushDeletedDisplayLists(unsigned int contextID) } } +void Drawable::deleteVertexBufferObject(unsigned int contextID,GLuint globj) +{ + if (globj!=0) + { + // insert the globj into the cache for the appropriate context. + s_deletedVertexBufferObjectCache[contextID].push_back(globj); + } +} + +/** flush all the cached display list which need to be deleted + * in the OpenGL context related to contextID.*/ +void Drawable::flushDeletedVertexBufferObjects(unsigned int contextID) +{ + DeletedDisplayListCache::iterator citr = s_deletedVertexBufferObjectCache.find(contextID); + if (citr!=s_deletedVertexBufferObjectCache.end()) + { + const Extensions* extensions = getExtensions(contextID,true); + + DisplayListVector displayListSet; + displayListSet.reserve(1000); + + // this swap will transfer the content of and empty citr->second + // in one quick pointer change. + displayListSet.swap(citr->second); + + for(DisplayListVector::iterator gitr=displayListSet.begin(); + gitr!=displayListSet.end(); + ++gitr) + { + extensions->glDeleteBuffers(1,&(*gitr)); + } + } +} + Drawable::Drawable() { @@ -75,6 +112,9 @@ Drawable::Drawable() // dynamic updating of data. _supportsDisplayList = true; _useDisplayList = true; + + _supportsVertexBufferObjects = false; + _useVertexBufferObjects = true; } Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop): @@ -86,6 +126,8 @@ Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop): _shape(copyop(drawable._shape.get())), _supportsDisplayList(drawable._supportsDisplayList), _useDisplayList(drawable._useDisplayList), + _supportsVertexBufferObjects(drawable._supportsVertexBufferObjects), + _useVertexBufferObjects(drawable._useVertexBufferObjects), _drawCallback(drawable._drawCallback), _cullCallback(drawable._cullCallback) { @@ -229,6 +271,15 @@ void Drawable::dirtyDisplayList() _globjList[i] = 0; } } + + for(unsigned int i=0;i<_vboList.size();++i) + { + if (_vboList[i] != 0) + { + Drawable::deleteVertexBufferObject(i,_vboList[i]); + _vboList[i] = 0; + } + } } @@ -257,14 +308,14 @@ struct ComputeBound : public Drawable::PrimitiveFunctor { ComputeBound():_vertices(0) {} - virtual void setVertexArray(unsigned int count,const Vec2* vertices) + virtual void setVertexArray(unsigned int,const Vec2*) { notify(WARN)<<"ComputeBound does not support Vec2* vertex arrays"< > BufferedExtensions; +static BufferedExtensions s_extensions; + +Drawable::Extensions* Drawable::getExtensions(unsigned int contextID,bool createIfNotInitalized) +{ + if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Drawable::Extensions; + return s_extensions[contextID].get(); +} + +void Drawable::setExtensions(unsigned int contextID,Extensions* extensions) +{ + s_extensions[contextID] = extensions; +} + +Drawable::Extensions::Extensions() +{ + setupGLExtenions(); +} + +Drawable::Extensions::Extensions(const Extensions& rhs): + Referenced() +{ + _isVertexProgramSupported = rhs._isVertexProgramSupported; + _isSecondaryColorSupported = rhs._isSecondaryColorSupported; + _isFogCoordSupported = rhs._isFogCoordSupported; + _isMultiTexSupported = rhs._isMultiTexSupported; + _glFogCoordfv = rhs._glFogCoordfv; + _glSecondaryColor3ubv = rhs._glSecondaryColor3ubv; + _glSecondaryColor3fv = rhs._glSecondaryColor3fv; + _glMultiTexCoord1f = rhs._glMultiTexCoord1f; + _glMultiTexCoord2fv = rhs._glMultiTexCoord2fv; + _glMultiTexCoord3fv = rhs._glMultiTexCoord3fv; + _glMultiTexCoord4fv = rhs._glMultiTexCoord4fv; + _glVertexAttrib1s = rhs._glVertexAttrib1s; + _glVertexAttrib1f = rhs._glVertexAttrib1f; + _glVertexAttrib2fv = rhs._glVertexAttrib2fv; + _glVertexAttrib3fv = rhs._glVertexAttrib3fv; + _glVertexAttrib4fv = rhs._glVertexAttrib4fv; + _glVertexAttrib4ubv = rhs._glVertexAttrib4ubv; + _glVertexAttrib4Nubv = rhs._glVertexAttrib4Nubv; + _glGenBuffers = rhs._glGenBuffers; + _glBindBuffer = rhs._glBindBuffer; + _glBufferData = rhs._glBufferData; + _glBufferSubData = rhs._glBufferSubData; + _glDeleteBuffers = rhs._glDeleteBuffers; +} + + +void Drawable::Extensions::lowestCommonDenominator(const Extensions& rhs) +{ + if (!rhs._isVertexProgramSupported) _isVertexProgramSupported = false; + if (!rhs._isSecondaryColorSupported) _isSecondaryColorSupported = false; + if (!rhs._isFogCoordSupported) _isFogCoordSupported = false; + if (!rhs._isMultiTexSupported) _isMultiTexSupported = false; + + if (!rhs._glFogCoordfv) _glFogCoordfv = 0; + if (!rhs._glSecondaryColor3ubv) _glSecondaryColor3ubv = 0; + if (!rhs._glSecondaryColor3fv) _glSecondaryColor3fv = 0; + if (!rhs._glMultiTexCoord1f) _glMultiTexCoord1f = 0; + if (!rhs._glMultiTexCoord2fv) _glMultiTexCoord2fv = 0; + if (!rhs._glMultiTexCoord3fv) _glMultiTexCoord3fv = 0; + if (!rhs._glMultiTexCoord4fv) _glMultiTexCoord4fv = 0; + + if (!rhs._glVertexAttrib1s) _glVertexAttrib1s = 0; + if (!rhs._glVertexAttrib1f) _glVertexAttrib1f = 0; + if (!rhs._glVertexAttrib2fv) _glVertexAttrib2fv = 0; + if (!rhs._glVertexAttrib3fv) _glVertexAttrib3fv = 0; + if (!rhs._glVertexAttrib4fv) _glVertexAttrib4fv = 0; + if (!rhs._glVertexAttrib4ubv) _glVertexAttrib4ubv = 0; + if (!rhs._glVertexAttrib4Nubv) _glVertexAttrib4Nubv = 0; + + if (!rhs._glGenBuffers) _glGenBuffers = 0; + if (!rhs._glBindBuffer) _glBindBuffer = 0; + if (!rhs._glBufferData) _glBufferData = 0; + if (!rhs._glBufferSubData) _glBufferSubData = 0; + if (!rhs._glDeleteBuffers) _glDeleteBuffers = 0; +} + +void Drawable::Extensions::setupGLExtenions() +{ + _isVertexProgramSupported = isGLExtensionSupported("GL_ARB_vertex_program"); + _isSecondaryColorSupported = isGLExtensionSupported("GL_EXT_secondary_color"); + _isFogCoordSupported = isGLExtensionSupported("GL_EXT_fog_coord"); + _isMultiTexSupported = isGLExtensionSupported("GL_ARB_multitexture"); + + _glFogCoordfv = ((FogCoordProc)osg::getGLExtensionFuncPtr("glFogCoordfv","glFogCoordfvEXT")); + _glSecondaryColor3ubv = ((SecondaryColor3ubvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3ubv","glSecondaryColor3ubvEXT")); + _glSecondaryColor3fv = ((SecondaryColor3fvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3fv","glSecondaryColor3fvEXT")); + _glMultiTexCoord1f = ((MultiTexCoord1fProc)osg::getGLExtensionFuncPtr("glMultiTexCoord1f","glMultiTexCoord1fARB")); + _glMultiTexCoord2fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord2fv","glMultiTexCoord2fvARB")); + _glMultiTexCoord3fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord3fv","glMultiTexCoord3fvARB")); + _glMultiTexCoord4fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord4fv","glMultiTexCoord4fvARB")); + + _glVertexAttrib1s = ((VertexAttrib1sProc)osg::getGLExtensionFuncPtr("glVertexAttrib1s","glVertexAttrib1sARB")); + _glVertexAttrib1f = ((VertexAttrib1fProc)osg::getGLExtensionFuncPtr("glVertexAttrib1f","glVertexAttrib1fARB")); + _glVertexAttrib2fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib2fv","glVertexAttrib2fvARB")); + _glVertexAttrib3fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib3fv","glVertexAttrib3fvARB")); + _glVertexAttrib4fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4fv","glVertexAttrib4fvARB")); + _glVertexAttrib4ubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4ubv","glVertexAttrib4ubvARB")); + _glVertexAttrib4Nubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4Nubv","glVertexAttrib4NubvARB")); + + _glGenBuffers = ((GenBuffersProc)osg::getGLExtensionFuncPtr("glGenBuffers","glGenBuffersARB")); + _glBindBuffer = ((BindBufferProc)osg::getGLExtensionFuncPtr("glBindBuffer","glBindBufferARB")); + _glBufferData = ((BufferDataProc)osg::getGLExtensionFuncPtr("glBufferData","glBufferDataARB")); + _glBufferSubData = ((BufferSubDataProc)osg::getGLExtensionFuncPtr("glBufferSubData","glBufferSubDataARB")); + _glDeleteBuffers = ((DeleteBuffersProc)osg::getGLExtensionFuncPtr("glDeleteBuffers","glDeleteBuffersARB")); + +} +void Drawable::Extensions::glFogCoordfv(const GLfloat* coord) const +{ + if (_glFogCoordfv) + { + _glFogCoordfv(coord); + } + else + { + notify(WARN)<<"Error: glFogCoordfv not supported by OpenGL driver"< #include #include @@ -82,7 +81,7 @@ class DrawVertexAttrib : public osg::Referenced, public osg::ConstValueVisitor { public: - DrawVertexAttrib(const Geometry::Extensions * extensions,unsigned int index,GLboolean normalized,const Array* attribcoords,const IndexArray* indices): + DrawVertexAttrib(const Drawable::Extensions * extensions,unsigned int index,GLboolean normalized,const Array* attribcoords,const IndexArray* indices): _index(index), _normalized(normalized), _extensions(extensions), @@ -129,7 +128,7 @@ public: unsigned int _index; GLboolean _normalized; - const Geometry::Extensions* _extensions; + const Drawable::Extensions* _extensions; const Array* _attribcoords; const IndexArray* _indices; }; @@ -162,7 +161,7 @@ class DrawMultiTexCoord : public osg::Referenced, public osg::ConstValueVisitor public: DrawMultiTexCoord(GLenum target,const Array* texcoords,const IndexArray* indices, - const Geometry::Extensions * extensions): + const Drawable::Extensions * extensions): _target(target), _texcoords(texcoords), _indices(indices), @@ -183,7 +182,7 @@ class DrawMultiTexCoord : public osg::Referenced, public osg::ConstValueVisitor const Array* _texcoords; const IndexArray* _indices; - const Geometry::Extensions * _extensions; + const Drawable::Extensions * _extensions; }; @@ -192,7 +191,7 @@ class DrawSecondaryColor : public osg::ConstValueVisitor public: DrawSecondaryColor(const Array* colors,const IndexArray* indices, - const Geometry::Extensions * extensions): + const Drawable::Extensions * extensions): _colors(colors), _indices(indices), _extensions(extensions) @@ -211,14 +210,14 @@ class DrawSecondaryColor : public osg::ConstValueVisitor const Array* _colors; const IndexArray* _indices; - const Geometry::Extensions * _extensions; + const Drawable::Extensions * _extensions; }; class DrawFogCoord : public osg::ConstValueVisitor { public: - DrawFogCoord(const Array* fogcoords,const IndexArray* indices,const Geometry::Extensions * extensions): + DrawFogCoord(const Array* fogcoords,const IndexArray* indices,const Drawable::Extensions * extensions): _fogcoords(fogcoords), _indices(indices), _extensions(extensions) {} @@ -234,7 +233,7 @@ class DrawFogCoord : public osg::ConstValueVisitor const Array* _fogcoords; const IndexArray* _indices; - const Geometry::Extensions * _extensions; + const Drawable::Extensions * _extensions; }; @@ -245,7 +244,6 @@ Geometry::Geometry() _secondaryColorBinding = BIND_OFF; _fogCoordBinding = BIND_OFF; - _fastPathComputed = false; _fastPath = false; } @@ -263,7 +261,6 @@ Geometry::Geometry(const Geometry& geometry,const CopyOp& copyop): _secondaryColorArray(copyop(geometry._secondaryColorArray.get())), _fogCoordBinding(geometry._fogCoordBinding), _fogCoordArray(dynamic_cast(copyop(geometry._fogCoordArray.get()))), - _fastPathComputed(geometry._fastPathComputed), _fastPath(geometry._fastPath) { for(PrimitiveSetList::const_iterator pitr=geometry._primitives.begin(); @@ -442,7 +439,7 @@ void Geometry::setVertexAttribArray(unsigned int index,bool normalize,Array* arr _vertexAttribBindingList[index] = ab; } - _fastPathComputed = false; + computeFastPathsUsed(); dirtyDisplayList(); } @@ -592,10 +589,10 @@ unsigned int Geometry::getPrimitiveSetIndex(const PrimitiveSet* primitiveset) co return _primitives.size(); // node not found. } -bool Geometry::areFastPathsUsed() const +bool Geometry::computeFastPathsUsed() { - if (_fastPathComputed) return _fastPath; +/* /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // set up normals if required. @@ -665,7 +662,7 @@ bool Geometry::areFastPathsUsed() const _vertexAttribBindingList[va] = BIND_OFF; } } - +*/ /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // check to see if fast path can be used. @@ -706,7 +703,7 @@ bool Geometry::areFastPathsUsed() const // for(unsigned int unit=0;unit!=_texCoordList.size();++unit) { - const TexCoordArrayPair& texcoordPair = _texCoordList[unit]; + const ArrayPair& texcoordPair = _texCoordList[unit]; if (texcoordPair.first.valid() && texcoordPair.first->getNumElements()>0) { if (texcoordPair.second.valid()) @@ -719,8 +716,11 @@ bool Geometry::areFastPathsUsed() const } } } - - _fastPathComputed = true; + + _supportsVertexBufferObjects = _fastPath; + + //_supportsVertexBufferObjects = false; + //_useVertexBufferObjects = false; return _fastPath; } @@ -809,86 +809,283 @@ void Geometry::drawImplementation(State& state) const typedef std::map< Geometry::AttributeBinding, DrawVertexAttribList> DrawVertexAttribMap; DrawVertexAttribMap drawVertexAttribMap; + bool handleVertexAttributes = (!_vertexAttribList.empty() && extensions->isVertexProgramSupported()); + if (areFastPathsUsed()) { /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // fast path. // - - if( _vertexArray.valid() ) - state.setVertexPointer(_vertexArray->getDataSize(),_vertexArray->getDataType(),0,_vertexArray->getDataPointer()); - else - state.disableVertexPointer(); - - if (_normalBinding==BIND_PER_VERTEX) - state.setNormalPointer(GL_FLOAT,0,_normalArray->getDataPointer()); - else - state.disableNormalPointer(); + if (_useVertexBufferObjects && state.isVertexBufferObjectSupported()) + { + // + // Vertex Buffer Object path for defining vertex arrays. + // - if (_colorBinding==BIND_PER_VERTEX) - state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,_colorArray->getDataPointer()); - else - state.disableColorPointer(); - - if (secondaryColorBinding==BIND_PER_VERTEX) - state.setSecondaryColorPointer(_secondaryColorArray->getDataSize(),_secondaryColorArray->getDataType(),0,_secondaryColorArray->getDataPointer()); - else - state.disableSecondaryColorPointer(); - - if (fogCoordBinding==BIND_PER_VERTEX) - state.setFogCoordPointer(GL_FLOAT,0,_fogCoordArray->getDataPointer()); - else - state.disableFogCoordPointer(); - - unsigned int unit; - for(unit=0;unit<_texCoordList.size();++unit) - { - const Array* array = _texCoordList[unit].first.get(); - if (array) - state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,array->getDataPointer()); - else - state.disableTexCoordPointer(unit); - } - state.disableTexCoordPointersAboveAndIncluding(unit); - - if( extensions->isVertexProgramSupported() ) - { - unsigned int index; - for( index = 0; index < _vertexAttribList.size(); ++index ) + GLuint& buffer = _vboList[state.getContextID()]; + if (!buffer) { - const Array* array = _vertexAttribList[index].second.first.get(); - const AttributeBinding ab = _vertexAttribBindingList[index]; - if( ab == BIND_PER_VERTEX && array ) + //std::cout << "creating VertexBuffer "<glGenBuffers(1, &buffer); + extensions->glBindBuffer(GL_ARRAY_BUFFER_ARB,buffer); + + //std::cout << " gen VertexBuffer "<getTotalDataSize(); + + _normalOffset = totalSize; + if (_normalArray.valid()) totalSize += _normalArray->getTotalDataSize(); + + _colorOffset = totalSize; + if (_colorArray.valid()) totalSize += _colorArray->getTotalDataSize(); + + _secondaryColorOffset = totalSize; + if (_secondaryColorArray.valid()) totalSize += _secondaryColorArray->getTotalDataSize(); + + _fogCoordOffset = totalSize; + if (_fogCoordArray.valid()) totalSize += _fogCoordArray->getTotalDataSize(); + + + unsigned int unit; + for(unit=0;unit<_texCoordList.size();++unit) { - state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(), - _vertexAttribList[index].first, 0, array->getDataPointer() ); + _texCoordList[unit].offset = totalSize; + const Array* array = _texCoordList[unit].first.get(); + if (array) + totalSize += array->getTotalDataSize(); + } - else - { - if( array ) - { - const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); - if( indexArray && indexArray->getNumElements() > 0 ) + if( handleVertexAttributes ) + { + unsigned int index; + for( index = 0; index < _vertexAttribList.size(); ++index ) + { + _texCoordList[unit].offset = totalSize; + const Array* array = _vertexAttribList[index].second.first.get(); + const AttributeBinding ab = _vertexAttribBindingList[index]; + if( ab == BIND_PER_VERTEX && array ) { - drawVertexAttribMap[ab].push_back( - new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); - } - else - { - drawVertexAttribMap[ab].push_back( - new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); + totalSize += array->getTotalDataSize(); } } - - state.disableVertexAttribPointer( index ); } - } - state.disableVertexAttribPointersAboveAndIncluding( index ); - } + // allocated the buffer space, but leave the copy to be done per vertex array below + extensions->glBufferData(GL_ARRAY_BUFFER_ARB,totalSize, 0, GL_STATIC_DRAW_ARB); + + //std::cout << " Created VertexBuffer "<getDataSize(),_vertexArray->getDataType(),0,(const GLvoid*)_vertexOffset); + else + state.disableVertexPointer(); + + if (_normalBinding==BIND_PER_VERTEX) + state.setNormalPointer(GL_FLOAT,0,(const GLvoid*)_normalOffset); + else + state.disableNormalPointer(); + + if (_colorBinding==BIND_PER_VERTEX) + state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,(const GLvoid*)_colorOffset); + else + state.disableColorPointer(); + + if (secondaryColorBinding==BIND_PER_VERTEX) + state.setSecondaryColorPointer(_secondaryColorArray->getDataSize(),_secondaryColorArray->getDataType(),0,(const GLvoid*)_secondaryColorOffset); + else + state.disableSecondaryColorPointer(); + + if (fogCoordBinding==BIND_PER_VERTEX) + state.setFogCoordPointer(GL_FLOAT,0,(const GLvoid*)_fogCoordOffset); + else + state.disableFogCoordPointer(); + + unsigned int unit; + for(unit=0;unit<_texCoordList.size();++unit) + { + const Array* array = _texCoordList[unit].first.get(); + if (array) + state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,(const GLvoid*)_texCoordList[unit].offset); + else + state.disableTexCoordPointer(unit); + } + state.disableTexCoordPointersAboveAndIncluding(unit); + + if( handleVertexAttributes ) + { + unsigned int index; + for( index = 0; index < _vertexAttribList.size(); ++index ) + { + const Array* array = _vertexAttribList[index].second.first.get(); + const AttributeBinding ab = _vertexAttribBindingList[index]; + + if( ab == BIND_PER_VERTEX && array ) + { + state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(), + _vertexAttribList[index].first, 0, (const GLvoid*)_vertexAttribList[index].second.offset ); + } + else + { + if( array ) + { + const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); + + if( indexArray && indexArray->getNumElements() > 0 ) + { + drawVertexAttribMap[ab].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); + } + else + { + drawVertexAttribMap[ab].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); + } + } + + state.disableVertexAttribPointer( index ); + } + } + state.disableVertexAttribPointersAboveAndIncluding( index ); + } + + + } + else + { + //std::cout << "none VertexBuffer path"<getDataSize(),_vertexArray->getDataType(),0,_vertexArray->getDataPointer()); + else + state.disableVertexPointer(); + + if (_normalBinding==BIND_PER_VERTEX) + state.setNormalPointer(GL_FLOAT,0,_normalArray->getDataPointer()); + else + state.disableNormalPointer(); + + if (_colorBinding==BIND_PER_VERTEX) + state.setColorPointer(_colorArray->getDataSize(),_colorArray->getDataType(),0,_colorArray->getDataPointer()); + else + state.disableColorPointer(); + + if (secondaryColorBinding==BIND_PER_VERTEX) + state.setSecondaryColorPointer(_secondaryColorArray->getDataSize(),_secondaryColorArray->getDataType(),0,_secondaryColorArray->getDataPointer()); + else + state.disableSecondaryColorPointer(); + + if (fogCoordBinding==BIND_PER_VERTEX) + state.setFogCoordPointer(GL_FLOAT,0,_fogCoordArray->getDataPointer()); + else + state.disableFogCoordPointer(); + + unsigned int unit; + for(unit=0;unit<_texCoordList.size();++unit) + { + const Array* array = _texCoordList[unit].first.get(); + if (array) + state.setTexCoordPointer(unit,array->getDataSize(),array->getDataType(),0,array->getDataPointer()); + else + state.disableTexCoordPointer(unit); + } + state.disableTexCoordPointersAboveAndIncluding(unit); + + if( handleVertexAttributes ) + { + unsigned int index; + for( index = 0; index < _vertexAttribList.size(); ++index ) + { + const Array* array = _vertexAttribList[index].second.first.get(); + const AttributeBinding ab = _vertexAttribBindingList[index]; + + if( ab == BIND_PER_VERTEX && array ) + { + state.setVertexAttribPointer( index, array->getDataSize(), array->getDataType(), + _vertexAttribList[index].first, 0, array->getDataPointer() ); + } + else + { + if( array ) + { + const IndexArray* indexArray = _vertexAttribList[index].second.second.get(); + + if( indexArray && indexArray->getNumElements() > 0 ) + { + drawVertexAttribMap[ab].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,indexArray) ); + } + else + { + drawVertexAttribMap[ab].push_back( + new DrawVertexAttrib(extensions,index,_vertexAttribList[index].first,array,0) ); + } + } + + state.disableVertexAttribPointer( index ); + } + } + state.disableVertexAttribPointersAboveAndIncluding( index ); + } + } + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // pass the overall binding values onto OpenGL. @@ -897,7 +1094,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_OVERALL) drawColor(colorIndex++); if (secondaryColorBinding==BIND_OVERALL) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_OVERALL) drawFogCoord(fogCoordIndex++); - if( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL]; @@ -920,7 +1117,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE_SET) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE_SET) drawFogCoord(fogCoordIndex++); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET]; @@ -934,6 +1131,11 @@ void Geometry::drawImplementation(State& state) const } + if (_useVertexBufferObjects) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB,0); + } + } else { @@ -956,7 +1158,7 @@ void Geometry::drawImplementation(State& state) const // multitexture supported.. for(unsigned int unit=0;unit!=_texCoordList.size();++unit) { - const TexCoordArrayPair& texcoordPair = _texCoordList[unit]; + const ArrayPair& texcoordPair = _texCoordList[unit]; if (texcoordPair.first.valid() && texcoordPair.first->getNumElements()>0) { if (texcoordPair.second.valid()) @@ -980,7 +1182,7 @@ void Geometry::drawImplementation(State& state) const { if (!_texCoordList.empty()) { - const TexCoordArrayPair& texcoordPair = _texCoordList[0]; + const ArrayPair& texcoordPair = _texCoordList[0]; if (texcoordPair.first.valid() && texcoordPair.first->getNumElements()>0) { if (texcoordPair.second.valid()) @@ -999,7 +1201,7 @@ void Geometry::drawImplementation(State& state) const } } - if( extensions->isVertexProgramSupported() ) + if(handleVertexAttributes) { unsigned int index; for( index = 1; index < _vertexAttribList.size(); ++index ) @@ -1037,7 +1239,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_OVERALL) drawColor(colorIndex++); if (secondaryColorBinding==BIND_OVERALL) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_OVERALL) drawFogCoord(fogCoordIndex++); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_OVERALL]; @@ -1074,7 +1276,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE_SET) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE_SET) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE_SET) drawFogCoord(fogCoordIndex++); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE_SET]; @@ -1122,7 +1324,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; @@ -1137,7 +1339,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; @@ -1191,7 +1393,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; @@ -1206,7 +1408,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; @@ -1259,7 +1461,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; @@ -1326,7 +1528,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_PRIMITIVE) drawColor(colorIndex++); if (secondaryColorBinding==BIND_PER_PRIMITIVE) drawSecondaryColor(secondaryColorIndex++); if (fogCoordBinding==BIND_PER_PRIMITIVE) drawFogCoord(fogCoordIndex++); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_PRIMITIVE]; @@ -1343,7 +1545,7 @@ void Geometry::drawImplementation(State& state) const if (_colorBinding==BIND_PER_VERTEX) drawColor(vindex); if (secondaryColorBinding==BIND_PER_VERTEX) drawSecondaryColor(vindex); if (fogCoordBinding==BIND_PER_VERTEX) drawFogCoord(vindex); - if ( extensions->isVertexProgramSupported() ) + if (handleVertexAttributes) { DrawVertexAttribList &list = drawVertexAttribMap[BIND_PER_VERTEX]; @@ -1927,264 +2129,6 @@ void Geometry::computeCorrectBindingsAndArraySizes() } -typedef buffered_value< ref_ptr > BufferedExtensions; -static BufferedExtensions s_extensions; - -Geometry::Extensions* Geometry::getExtensions(unsigned int contextID,bool createIfNotInitalized) -{ - if (!s_extensions[contextID] && createIfNotInitalized) s_extensions[contextID] = new Geometry::Extensions; - return s_extensions[contextID].get(); -} - -void Geometry::setExtensions(unsigned int contextID,Extensions* extensions) -{ - s_extensions[contextID] = extensions; -} - -Geometry::Extensions::Extensions() -{ - setupGLExtenions(); -} - -Geometry::Extensions::Extensions(const Extensions& rhs): - Referenced() -{ - _isVertexProgramSupported = rhs._isVertexProgramSupported; - _isSecondaryColorSupported = rhs._isSecondaryColorSupported; - _isFogCoordSupported = rhs._isFogCoordSupported; - _isMultiTexSupported = rhs._isMultiTexSupported; - _glFogCoordfv = rhs._glFogCoordfv; - _glSecondaryColor3ubv = rhs._glSecondaryColor3ubv; - _glSecondaryColor3fv = rhs._glSecondaryColor3fv; - _glMultiTexCoord1f = rhs._glMultiTexCoord1f; - _glMultiTexCoord2fv = rhs._glMultiTexCoord2fv; - _glMultiTexCoord3fv = rhs._glMultiTexCoord3fv; - _glMultiTexCoord4fv = rhs._glMultiTexCoord4fv; - _glVertexAttrib1s = rhs._glVertexAttrib1s; - _glVertexAttrib1f = rhs._glVertexAttrib1f; - _glVertexAttrib2fv = rhs._glVertexAttrib2fv; - _glVertexAttrib3fv = rhs._glVertexAttrib3fv; - _glVertexAttrib4fv = rhs._glVertexAttrib4fv; - _glVertexAttrib4ubv = rhs._glVertexAttrib4ubv; - _glVertexAttrib4Nubv = rhs._glVertexAttrib4Nubv; -} - - -void Geometry::Extensions::lowestCommonDenominator(const Extensions& rhs) -{ - if (!rhs._isVertexProgramSupported) _isVertexProgramSupported = false; - if (!rhs._isSecondaryColorSupported) _isSecondaryColorSupported = false; - if (!rhs._isFogCoordSupported) _isFogCoordSupported = false; - if (!rhs._isMultiTexSupported) _isMultiTexSupported = false; - - if (!rhs._glFogCoordfv) _glFogCoordfv = 0; - if (!rhs._glSecondaryColor3ubv) _glSecondaryColor3ubv = 0; - if (!rhs._glSecondaryColor3fv) _glSecondaryColor3fv = 0; - if (!rhs._glMultiTexCoord1f) _glMultiTexCoord1f = 0; - if (!rhs._glMultiTexCoord2fv) _glMultiTexCoord2fv = 0; - if (!rhs._glMultiTexCoord3fv) _glMultiTexCoord3fv = 0; - if (!rhs._glMultiTexCoord4fv) _glMultiTexCoord4fv = 0; - - if (!rhs._glVertexAttrib1s) _glVertexAttrib1s = 0; - if (!rhs._glVertexAttrib1f) _glVertexAttrib1f = 0; - if (!rhs._glVertexAttrib2fv) _glVertexAttrib2fv = 0; - if (!rhs._glVertexAttrib3fv) _glVertexAttrib3fv = 0; - if (!rhs._glVertexAttrib4fv) _glVertexAttrib4fv = 0; - if (!rhs._glVertexAttrib4ubv) _glVertexAttrib4ubv = 0; - if (!rhs._glVertexAttrib4Nubv) _glVertexAttrib4Nubv = 0; -} - -void Geometry::Extensions::setupGLExtenions() -{ - _isVertexProgramSupported = isGLExtensionSupported("GL_ARB_vertex_program"); - _isSecondaryColorSupported = isGLExtensionSupported("GL_EXT_secondary_color"); - _isFogCoordSupported = isGLExtensionSupported("GL_EXT_fog_coord"); - _isMultiTexSupported = isGLExtensionSupported("GL_ARB_multitexture"); - - _glFogCoordfv = ((FogCoordProc)osg::getGLExtensionFuncPtr("glFogCoordfv","glFogCoordfvEXT")); - _glSecondaryColor3ubv = ((SecondaryColor3ubvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3ubv","glSecondaryColor3ubvEXT")); - _glSecondaryColor3fv = ((SecondaryColor3fvProc)osg::getGLExtensionFuncPtr("glSecondaryColor3fv","glSecondaryColor3fvEXT")); - _glMultiTexCoord1f = ((MultiTexCoord1fProc)osg::getGLExtensionFuncPtr("glMultiTexCoord1f","glMultiTexCoord1fARB")); - _glMultiTexCoord2fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord2fv","glMultiTexCoord2fvARB")); - _glMultiTexCoord3fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord3fv","glMultiTexCoord3fvARB")); - _glMultiTexCoord4fv = ((MultiTexCoordfvProc)osg::getGLExtensionFuncPtr("glMultiTexCoord4fv","glMultiTexCoord4fvARB")); - - _glVertexAttrib1s = ((VertexAttrib1sProc)osg::getGLExtensionFuncPtr("glVertexAttrib1s","glVertexAttrib1sARB")); - _glVertexAttrib1f = ((VertexAttrib1fProc)osg::getGLExtensionFuncPtr("glVertexAttrib1f","glVertexAttrib1fARB")); - _glVertexAttrib2fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib2fv","glVertexAttrib2fvARB")); - _glVertexAttrib3fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib3fv","glVertexAttrib3fvARB")); - _glVertexAttrib4fv = ((VertexAttribfvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4fv","glVertexAttrib4fvARB")); - _glVertexAttrib4ubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4ubv","glVertexAttrib4ubvARB")); - _glVertexAttrib4Nubv = ((VertexAttribubvProc)osg::getGLExtensionFuncPtr("glVertexAttrib4Nubv","glVertexAttrib4NubvARB")); -} -void Geometry::Extensions::glFogCoordfv(const GLfloat* coord) const -{ - if (_glFogCoordfv) - { - _glFogCoordfv(coord); - } - else - { - notify(WARN)<<"Error: glFogCoordfv not supported by OpenGL driver"<second // in one quick pointer change. textureObjectSet.swap(citr->second); diff --git a/src/osg/VertexProgram.cpp b/src/osg/VertexProgram.cpp index 72da1d9f6..35680cc1a 100644 --- a/src/osg/VertexProgram.cpp +++ b/src/osg/VertexProgram.cpp @@ -45,10 +45,12 @@ void VertexProgram::flushDeletedVertexProgramObjects(unsigned int contextID) if (citr!=s_deletedVertexProgramObjectCache.end()) { VertexProgramObjectVector vpObjectSet; + vpObjectSet.reserve(1000); // this swap will transfer the content of and empty citr->second // in one quick pointer change. vpObjectSet.swap(citr->second); + for(VertexProgramObjectVector::iterator titr=vpObjectSet.begin(); titr!=vpObjectSet.end(); ++titr) diff --git a/src/osgUtil/Optimizer.cpp b/src/osgUtil/Optimizer.cpp index 04e8b3456..54d1fcba0 100644 --- a/src/osgUtil/Optimizer.cpp +++ b/src/osgUtil/Optimizer.cpp @@ -1163,6 +1163,9 @@ bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode) } } + // don't merge geometry if its above a maximum number of vertices. + unsigned int _maximumNumber = 10000; + for(GeometryDuplicateMap::iterator itr=geometryDuplicateMap.begin(); itr!=geometryDuplicateMap.end(); ++itr) @@ -1175,7 +1178,26 @@ bool Optimizer::MergeGeometryVisitor::mergeGeode(osg::Geode& geode) dupItr!=itr->second.end(); ++dupItr) { + osg::Geometry* rhs = *dupItr; + + if (lhs->getVertexArray() && lhs->getVertexArray()->getNumElements()>=_maximumNumber) + { + lhs = rhs; + continue; + } + + if (rhs->getVertexArray() && rhs->getVertexArray()->getNumElements()>=_maximumNumber) + { + continue; + } + + if (lhs->getVertexArray() && rhs->getVertexArray() && + (lhs->getVertexArray()->getNumElements()+rhs->getVertexArray()->getNumElements())>=_maximumNumber) + { + continue; + } + if (mergeGeometry(*lhs,*rhs)) { geode.removeDrawable(rhs); diff --git a/src/osgUtil/SceneView.cpp b/src/osgUtil/SceneView.cpp index b98b6afaf..208122cc7 100644 --- a/src/osgUtil/SceneView.cpp +++ b/src/osgUtil/SceneView.cpp @@ -537,6 +537,7 @@ void SceneView::draw() // context for when the object were originally created. Here we know what // context we are in so can flush the appropriate caches. osg::Drawable::flushDeletedDisplayLists(_state->getContextID()); + osg::Drawable::flushDeletedVertexBufferObjects(_state->getContextID()); osg::Texture::flushDeletedTextureObjects(_state->getContextID()); osg::VertexProgram::flushDeletedVertexProgramObjects(_state->getContextID());