From 14d1483b0607e13674ca8512a302d82f414d9750 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Fri, 15 Jul 2016 15:41:43 +0100 Subject: [PATCH] Experimental support for OpenGL Vertex Array Object --- examples/osgsharedarray/osgsharedarray.cpp | 4 + include/osg/Array | 5 +- include/osg/DisplaySettings | 13 + include/osg/GLExtensions | 122 ++- include/osg/Geometry | 13 +- include/osg/State | 51 +- include/osg/VertexArrayState | 222 ++++ src/osg/CMakeLists.txt | 2 + src/osg/DisplaySettings.cpp | 25 + src/osg/Drawable.cpp | 7 +- src/osg/GLBeginEndAdapter.cpp | 4 + src/osg/GLExtensions.cpp | 141 ++- src/osg/Geometry.cpp | 151 ++- src/osg/PrimitiveSet.cpp | 25 +- src/osg/State.cpp | 2 + src/osg/VertexArrayState.cpp | 1097 ++++++++++++++++++++ 16 files changed, 1822 insertions(+), 62 deletions(-) create mode 100644 include/osg/VertexArrayState create mode 100644 src/osg/VertexArrayState.cpp diff --git a/examples/osgsharedarray/osgsharedarray.cpp b/examples/osgsharedarray/osgsharedarray.cpp index 643ddbd64..e648b094f 100644 --- a/examples/osgsharedarray/osgsharedarray.cpp +++ b/examples/osgsharedarray/osgsharedarray.cpp @@ -113,6 +113,10 @@ public: return _ptr; } + virtual const GLvoid* getDataPointer(unsigned int index) const { + return &((*_ptr)[index]); + } + /** Returns the number of elements in the array. */ virtual unsigned int getNumElements() const { return _numElements; diff --git a/include/osg/Array b/include/osg/Array index a2f70319d..3a602c000 100644 --- a/include/osg/Array +++ b/include/osg/Array @@ -164,6 +164,7 @@ class OSG_EXPORT Array : public BufferData virtual unsigned int getElementSize() const = 0; virtual const GLvoid* getDataPointer() const = 0; + virtual const GLvoid* getDataPointer(unsigned int index) const = 0; virtual unsigned int getTotalDataSize() const = 0; virtual unsigned int getNumElements() const = 0; virtual void reserveArray(unsigned int num) = 0; @@ -285,8 +286,9 @@ class TemplateArray : public Array, public MixinVector MixinVector( *this ).swap( *this ); } - virtual unsigned int getElementSize() const { return sizeof(ElementDataType); } + virtual unsigned int getElementSize() const { return sizeof(ElementDataType); } virtual const GLvoid* getDataPointer() const { if (!this->empty()) return &this->front(); else return 0; } + virtual const GLvoid* getDataPointer(unsigned int index) const { if (!this->empty()) return &((*this)[index]); else return 0; } virtual unsigned int getTotalDataSize() const { return static_cast(this->size()*sizeof(ElementDataType)); } virtual unsigned int getNumElements() const { return static_cast(this->size()); } virtual void reserveArray(unsigned int num) { this->reserve(num); } @@ -376,6 +378,7 @@ class TemplateIndexArray : public IndexArray, public MixinVector virtual unsigned int getElementSize() const { return sizeof(ElementDataType); } virtual const GLvoid* getDataPointer() const { if (!this->empty()) return &this->front(); else return 0; } + virtual const GLvoid* getDataPointer(unsigned int index) const { if (!this->empty()) return &((*this)[index]); else return 0; } virtual unsigned int getTotalDataSize() const { return static_cast(this->size()*sizeof(T)); } virtual unsigned int getNumElements() const { return static_cast(this->size()); } virtual void reserveArray(unsigned int num) { this->reserve(num); } diff --git a/include/osg/DisplaySettings b/include/osg/DisplaySettings index f06bd8a1c..9645b1670 100644 --- a/include/osg/DisplaySettings +++ b/include/osg/DisplaySettings @@ -299,6 +299,17 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced int getNvOptimusEnablement() const; + enum GeometryImplementation + { + OLD_GEOMETRY_IMPLEMENTATION, + NEW_GEOMETRY_IMPLEMENTATION, + VERTEX_ARRAY_OBJECT + }; + + void setGeometryImplementation(GeometryImplementation gi) { _geometryImplementation = gi; } + GeometryImplementation getGeometryImplementation() const { return _geometryImplementation; } + + void setKeystoneHint(bool enabled) { _keystoneHint = enabled; } bool getKeystoneHint() const { return _keystoneHint; } @@ -388,6 +399,8 @@ class OSG_EXPORT DisplaySettings : public osg::Referenced SwapMethod _swapMethod; unsigned int _syncSwapBuffers; + GeometryImplementation _geometryImplementation; + bool _keystoneHint; FileNames _keystoneFileNames; Objects _keystones; diff --git a/include/osg/GLExtensions b/include/osg/GLExtensions index 721e747a2..258836026 100644 --- a/include/osg/GLExtensions +++ b/include/osg/GLExtensions @@ -20,11 +20,13 @@ #include #include #include +#include +#include namespace osg { -/** Return floating-point OpenGL version number. +/** Return floating-point OpenGL/GLES version number. * Note: Must only be called within a valid OpenGL context, * undefined behavior may occur otherwise. */ @@ -34,19 +36,25 @@ extern OSG_EXPORT float getGLVersionNumber(); */ extern OSG_EXPORT bool isExtensionInExtensionString(const char *extension, const char *extensionString); -/** Return true if OpenGL "extension" is supported. +/** Return true if OpenGL/GLES "extension" is supported. * Note: Must only be called within a valid OpenGL context, * undefined behavior may occur otherwise. */ extern OSG_EXPORT bool isGLExtensionSupported(unsigned int contextID, const char *extension); -/** Return true if OpenGL "extension" or minimum OpenGL version number is supported. +/** Return true if either OpenGL/GLES "extension1" or "extension2" is supported. + * Note: Must only be called within a valid OpenGL context, + * undefined behavior may occur otherwise. +*/ +extern OSG_EXPORT bool isGLExtensionSupported(unsigned int contextID, const char *extension1, const char *extension2); + +/** Return true if OpenGL/GLES "extension" or minimum OpenGL version number is supported. * Note: Must only be called within a valid OpenGL context, * undefined behavior may occur otherwise. */ extern OSG_EXPORT bool isGLExtensionOrVersionSupported(unsigned int contextID, const char *extension, float requiredGlVersion); -/** Return the address of the specified OpenGL function. +/** Return the address of the specified OpenGL/GLES function. * Return NULL if function not supported by OpenGL library. * Note, glGLExtensionFuncPtr is declared inline so that the code * is compiled locally to the calling code. This should get by Windows' @@ -123,11 +131,35 @@ bool setGLExtensionFuncPtr(T& t, const char* str1, const char* str2, const char* return convertPointer(t, validContext ? osg::getGLExtensionFuncPtr(str1, str2, str3) : 0); } +class VertexAttribAlias +{ + public: + VertexAttribAlias(): + _location(0) {} + + VertexAttribAlias(const VertexAttribAlias& rhs): + _location(rhs._location), + _glName(rhs._glName), + _osgName(rhs._osgName), + _declaration(rhs._declaration) {} + + VertexAttribAlias(GLuint location, const std::string glName, const std::string osgName, const std::string& declaration): + _location(location), + _glName(glName), + _osgName(osgName), + _declaration(declaration) {} + + GLuint _location; + std::string _glName; + std::string _osgName; + std::string _declaration; +}; + /** Main GLExtensions class for managing OpenGL extensions per graphics context.*/ class OSG_EXPORT GLExtensions : public osg::Referenced { public: - GLExtensions(unsigned int contextID); + GLExtensions(unsigned int in_contextID); /** Function to call to get the extension of a specified context. * If the Exentsion object for that context has not yet been created then @@ -135,12 +167,12 @@ class OSG_EXPORT GLExtensions : public osg::Referenced * 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 GLExtensions* Get(unsigned int contextID,bool createIfNotInitalized); + static GLExtensions* Get(unsigned int in_contextID,bool createIfNotInitalized); /** 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 Set(unsigned int contextID, GLExtensions* extensions); + static void Set(unsigned int in_contextID, GLExtensions* extensions); // C++-friendly convenience wrapper methods GLuint getCurrentProgram() const; @@ -149,6 +181,7 @@ class OSG_EXPORT GLExtensions : public osg::Referenced bool getAttribLocation( const char* attribName, GLuint& slot ) const; bool getFragDataLocation( const char* fragDataName, GLuint& slot) const; + unsigned int contextID; float glVersion; float glslLanguageVersion; @@ -260,8 +293,11 @@ class OSG_EXPORT GLExtensions : public osg::Referenced void (GL_APIENTRY * glVertexAttrib4ubv)(GLuint index, const GLubyte *v); void (GL_APIENTRY * glVertexAttrib4uiv)(GLuint index, const GLuint *v); void (GL_APIENTRY * glVertexAttrib4usv)(GLuint index, const GLushort *v); - void (GL_APIENTRY * glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + void (GL_APIENTRY * glVertexAttribPointer) (unsigned int, GLint, GLenum, GLboolean normalized, GLsizei stride, const GLvoid *pointer); + void (GL_APIENTRY * glVertexAttribIPointer) (unsigned int, GLint, GLenum, GLsizei stride, const GLvoid *pointer); + void (GL_APIENTRY * glVertexAttribLPointer) (unsigned int, GLint, GLenum, GLsizei stride, const GLvoid *pointer); void (GL_APIENTRY * glVertexAttribDivisor)(GLuint index, GLuint divisor); + void (GL_APIENTRY * glUniformMatrix2x3fv)( GLint location, GLsizei count, GLboolean transpose, const GLfloat* value ); void (GL_APIENTRY * glUniformMatrix3x2fv)( GLint location, GLsizei count, GLboolean transpose, const GLfloat* value ); void (GL_APIENTRY * glUniformMatrix2x4fv)( GLint location, GLsizei count, GLboolean transpose, const GLfloat* value ); @@ -313,8 +349,10 @@ class OSG_EXPORT GLExtensions : public osg::Referenced void (GL_APIENTRY * glGetActiveAtomicCounterBufferiv)( GLuint program, GLuint bufferIndex, GLenum pname, GLint* params ); void (GL_APIENTRY * glDispatchCompute)( GLuint numGroupsX, GLuint numGroupsY, GLuint numGroupsZ ); + // Buffer Object extensions bool isBufferObjectSupported; + bool isVBOSupported; bool isPBOSupported; bool isTBOSupported; bool isVAOSupported; @@ -355,12 +393,19 @@ class OSG_EXPORT GLExtensions : public osg::Referenced bool isTimerQuerySupported; bool isARBTimerQuerySupported; + + + void (GL_APIENTRY * glDrawArraysInstanced)( GLenum mode, GLint first, GLsizei count, GLsizei primcount ); + void (GL_APIENTRY * glDrawElementsInstanced)( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount ); + void (GL_APIENTRY * glSecondaryColor3ubv) (const GLubyte* coord); void (GL_APIENTRY * glSecondaryColor3fv) (const GLfloat* coord); void (GL_APIENTRY * glFogCoordfv) (const GLfloat* coord); void (GL_APIENTRY * glMultiTexCoord1f) (GLenum target,GLfloat coord); + void (GL_APIENTRY * glMultiTexCoord4f) (GLenum target, GLfloat x, GLfloat y, GLfloat z, GLfloat w); + void (GL_APIENTRY * glMultiTexCoord1fv) (GLenum target,const GLfloat* coord); void (GL_APIENTRY * glMultiTexCoord2fv) (GLenum target,const GLfloat* coord); void (GL_APIENTRY * glMultiTexCoord3fv) (GLenum target,const GLfloat* coord); @@ -645,6 +690,67 @@ class OSG_EXPORT GLExtensions : public osg::Referenced void (GL_APIENTRY * glEnableIndexedEXT) (GLenum target, GLuint index); void (GL_APIENTRY * glDisableIndexedEXT) (GLenum target, GLuint index); GLboolean (GL_APIENTRY * glIsEnabledIndexedEXT) (GLenum target, GLuint index); + + void (GL_APIENTRY * glClientActiveTexture) (GLenum texture); + void (GL_APIENTRY * glActiveTexture) (GLenum texture); + void (GL_APIENTRY * glFogCoordPointer) (GLenum type, GLsizei stride, const GLvoid *pointer); + void (GL_APIENTRY * glSecondaryColorPointer) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); + + GLint glMaxTextureCoords; + GLint glMaxTextureUnits; +public: + + + void setUseVertexAttributeAliasing(bool flag) { _useVertexAttributeAliasing = flag; } + bool getUseVertexAttributeAliasing() const { return _useVertexAttributeAliasing ; } + + typedef std::vector VertexAttribAliasList; + typedef std::map AttribBindingList; + + void setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration); + + /** Reset the vertex attribute aliasing to osg's default. This method needs to be called before render anything unless you really know what you're doing !*/ + void resetVertexAttributeAlias(bool compactAliasing=true, unsigned int numTextureUnits=8); + + /** Set the vertex attribute aliasing for "vertex". This method needs to be called before render anything unless you really know what you're doing !*/ + void setVertexAlias(const VertexAttribAlias& alias) { _vertexAlias = alias; } + const VertexAttribAlias& getVertexAlias() { return _vertexAlias; } + + /** Set the vertex attribute aliasing for "normal". This method needs to be called before render anything unless you really know what you're doing !*/ + void setNormalAlias(const VertexAttribAlias& alias) { _normalAlias = alias; } + const VertexAttribAlias& getNormalAlias() { return _normalAlias; } + + /** Set the vertex attribute aliasing for "color". This method needs to be called before render anything unless you really know what you're doing !*/ + void setColorAlias(const VertexAttribAlias& alias) { _colorAlias = alias; } + const VertexAttribAlias& getColorAlias() { return _colorAlias; } + + /** Set the vertex attribute aliasing for "secondary color". This method needs to be called before render anything unless you really know what you're doing !*/ + void setSecondaryColorAlias(const VertexAttribAlias& alias) { _secondaryColorAlias = alias; } + const VertexAttribAlias& getSecondaryColorAlias() { return _secondaryColorAlias; } + + /** Set the vertex attribute aliasing for "fog coord". This method needs to be called before render anything unless you really know what you're doing !*/ + void setFogCoordAlias(const VertexAttribAlias& alias) { _fogCoordAlias = alias; } + const VertexAttribAlias& getFogCoordAlias() { return _fogCoordAlias; } + + /** Set the vertex attribute aliasing list for texture coordinates. This method needs to be called before render anything unless you really know what you're doing !*/ + void setTexCoordAliasList(const VertexAttribAliasList& aliasList) { _texCoordAliasList = aliasList; } + const VertexAttribAliasList& getTexCoordAliasList() { return _texCoordAliasList; } + + /** Set the vertex attribute binding list. This method needs to be called before render anything unless you really know what you're doing !*/ + void setAttributeBindingList(const AttribBindingList& attribBindingList) { _attributeBindingList = attribBindingList; } + const AttribBindingList& getAttributeBindingList() { return _attributeBindingList; } + + + bool _useVertexAttributeAliasing; + VertexAttribAlias _vertexAlias; + VertexAttribAlias _normalAlias; + VertexAttribAlias _colorAlias; + VertexAttribAlias _secondaryColorAlias; + VertexAttribAlias _fogCoordAlias; + VertexAttribAliasList _texCoordAliasList; + + AttribBindingList _attributeBindingList; + }; diff --git a/include/osg/Geometry b/include/osg/Geometry index fc61445fb..3527a608a 100644 --- a/include/osg/Geometry +++ b/include/osg/Geometry @@ -176,11 +176,17 @@ class OSG_EXPORT Geometry : public Drawable */ virtual void drawImplementation(RenderInfo& renderInfo) const; + /** Set up the vertex arrays for the purpose of rendering, called by drawImplemtation() prior to it calling drawPrimitivesImplementation().*/ - void drawVertexArraysImplementation(RenderInfo& renderInfo) const; + void old_drawVertexArraysImplementation(RenderInfo& renderInfo) const; /** dispatch the primitives to OpenGL, called by drawImplemtation() after calling drawVertexArraysImplementation().*/ - void drawPrimitivesImplementation(RenderInfo& renderInfo) const; + void old_drawPrimitivesImplementation(RenderInfo& renderInfo) const; + + + /** Set up the vertex arrays for the purpose of rendering, called by drawImplemtation() prior to it calling drawPrimitivesImplementation().*/ + void new_drawImplementation(RenderInfo& renderInfo) const; + /** Return true, osg::Geometry does support accept(Drawable::AttributeFunctor&). */ virtual bool supports(const Drawable::AttributeFunctor&) const { return true; } @@ -217,6 +223,9 @@ class OSG_EXPORT Geometry : public Drawable void addVertexBufferObjectIfRequired(osg::Array* array); void addElementBufferObjectIfRequired(osg::PrimitiveSet* primitiveSet); + typedef buffered_object< osg::ref_ptr > VertexArrayStateList; + mutable VertexArrayStateList _vertexArrayStateList; + PrimitiveSetList _primitives; osg::ref_ptr _vertexArray; diff --git a/include/osg/State b/include/osg/State index 22e5f71bb..0de2206c5 100644 --- a/include/osg/State +++ b/include/osg/State @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -72,31 +73,20 @@ namespace osg { // forward declare GraphicsContext, View and State class GraphicsContext; -class VertexAttribAlias +struct EnabledArrayPair { - public: - VertexAttribAlias(): - _location(0) {} + EnabledArrayPair():_arrayType(0), _lazy_disable(false),_dirty(true),_enabled(false),_normalized(0),_pointer(0) {} + EnabledArrayPair(const EnabledArrayPair& eap):_arrayType(0), _lazy_disable(eap._lazy_disable),_dirty(eap._dirty), _enabled(eap._enabled),_normalized(eap._normalized),_pointer(eap._pointer) {} + EnabledArrayPair& operator = (const EnabledArrayPair& eap) { _arrayType = eap._arrayType; _lazy_disable = eap._lazy_disable;_dirty=eap._dirty; _enabled=eap._enabled; _normalized=eap._normalized;_pointer=eap._pointer; return *this; } - VertexAttribAlias(const VertexAttribAlias& rhs): - _location(rhs._location), - _glName(rhs._glName), - _osgName(rhs._osgName), - _declaration(rhs._declaration) {} - - VertexAttribAlias(GLuint location, const std::string glName, const std::string osgName, const std::string& declaration): - _location(location), - _glName(glName), - _osgName(osgName), - _declaration(declaration) {} - - GLuint _location; - std::string _glName; - std::string _osgName; - std::string _declaration; + GLenum _arrayType; + bool _lazy_disable; + bool _dirty; + bool _enabled; + GLboolean _normalized; + const GLvoid* _pointer; }; - /** Encapsulates the current applied OpenGL modes, attributes and vertex arrays settings, * implements lazy state updating and provides accessors for querying the current state. * The venerable Red Book says that "OpenGL is a state machine", and this class @@ -500,12 +490,24 @@ class OSG_EXPORT State : public Referenced const StateAttribute* getLastAppliedTextureAttribute(unsigned int unit, StateAttribute::Type type, unsigned int member=0) const; + + + /** Dirty the modes previously applied in osg::State.*/ void dirtyAllModes(); /** Dirty the modes attributes previously applied in osg::State.*/ void dirtyAllAttributes(); + + + /** Set the CurrentVetexArrayState object that take which vertex arrays are bound.*/ + void setCurrentVertexArrayState(VertexArrayState* vas) { _currentVertexArrayState = vas; } + + /** Get the CurrentVetexArrayState object that take which vertex arrays are bound.*/ + VertexArrayState* getCurrentVertexArrayState() const { return _currentVertexArrayState.get(); } + + /** disable the vertex, normal, color, tex coords, secondary color, fog coord and index arrays.*/ void disableAllVertexArrays(); @@ -513,6 +515,8 @@ class OSG_EXPORT State : public Referenced void dirtyAllVertexArrays(); + + void setCurrentVertexBufferObject(osg::GLBufferObject* vbo) { _currentVBO = vbo; } const GLBufferObject* getCurrentVertexBufferObject() { return _currentVBO; } inline void bindVertexBufferObject(osg::GLBufferObject* vbo) @@ -551,7 +555,7 @@ class OSG_EXPORT State : public Referenced inline void unbindElementBufferObject() { - if (!_currentEBO) return; + //if (!_currentEBO) return; _glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0); _currentEBO = 0; } @@ -1667,6 +1671,8 @@ class OSG_EXPORT State : public Referenced GraphicsContext* _graphicsContext; unsigned int _contextID; + osg::ref_ptr _currentVertexArrayState; + bool _shaderCompositionEnabled; bool _shaderCompositionDirty; osg::ref_ptr _shaderComposer; @@ -1706,6 +1712,7 @@ class OSG_EXPORT State : public Referenced Program::AttribBindingList _attributeBindingList; void setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration); + /** Apply an OpenGL mode if required, passing in mode, enable flag and * appropriate mode stack. This is a wrapper around \c glEnable() and * \c glDisable(), that just actually calls these functions if the diff --git a/include/osg/VertexArrayState b/include/osg/VertexArrayState new file mode 100644 index 000000000..a897230fa --- /dev/null +++ b/include/osg/VertexArrayState @@ -0,0 +1,222 @@ +/* -*-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_VertexArrayState +#define OSG_VertexArrayState 1 + +#include +#include +#include +#include + +namespace osg { + + + +class VertexArrayState : public osg::Referenced +{ +public: + + VertexArrayState(osg::GLExtensions* ext); + + struct ArrayDispatch : public osg::Referenced + { + ArrayDispatch(Array* in_array): + array(in_array), + modifiedCount(0xffffffff) {} + + inline void dispatchIfDirty(osg::State& state, unsigned int index=0) + { + if (modifiedCount!=array->getModifiedCount()) dispatch(state, index); + } + + virtual void dispatch(osg::State& state, unsigned int index=0) = 0; + + virtual void dispatchDeprecated(osg::State& state, unsigned int index=0); + + osg::Array* array; + unsigned int modifiedCount; + }; + + typedef std::vector< ref_ptr > ArrayDispatchList; + + ArrayDispatchList& getArrayDispatchList(Array::Binding binding) + { + switch(binding) + { + case(osg::Array::BIND_PER_VERTEX): return _dispatchArrays; + case(osg::Array::BIND_PER_PRIMITIVE_SET): return _dispatchPerPrimitiveSet; + default: return _dispatchOverall; + } + } + + + enum VertexArrayIdentifier + { + VERTEX_ARRAY, + NORMAL_ARRAY, + COLOR_ARRAY, + SECONDARY_COLOR_ARRAY, + FOG_COORD_ARRAY, + TEX_COORD_ARRAY, + VERTEX_ATTRIB_ARRAY=TEX_COORD_ARRAY+32 + }; + + + void assignVertexArray(osg::Array* array); + void assignColorArray(osg::Array* array); + void assignNormalArray(osg::Array* array); + + void assignSecondaryColorArray(osg::Array* array); + void assignFogCoordArray(osg::Array* array); + + void assignTexCoordArray(unsigned int unit, osg::Array* array); + void assignVertexAttribArray(unsigned int unit, osg::Array* array); + + inline void dispatchOverall(osg::State& state) + { + for(ArrayDispatchList::iterator itr = _dispatchOverall.begin(); + itr != _dispatchOverall.end(); + ++itr) + { + (*(*itr)).dispatch(state); + } + } + + void dispatchPerPrimitveSet(osg::State& state, unsigned int index) + { + for(ArrayDispatchList::iterator itr = _dispatchPerPrimitiveSet.begin(); + itr != _dispatchPerPrimitiveSet.end(); + ++itr) + { + (*(*itr)).dispatch(state, index); + } + } + + inline void dispatchArrays(osg::State& state) + { + // need to check previous enabled/disabled mode + + if (_vertexArrayObject) + { + for(ArrayDispatchList::iterator itr = _dispatchArrays.begin(); + itr != _dispatchArrays.end(); + ++itr) + { + (*(*itr)).dispatch(state); + } + } + else + { + for(ArrayDispatchList::iterator itr = _dispatchArrays.begin(); + itr != _dispatchArrays.end(); + ++itr) + { + (*(*itr)).dispatchDeprecated(state); + } + } + } + + inline void dispatchArraysIfDirty(osg::State& state) + { + // need to check previous enabled/disabled mode + + for(ArrayDispatchList::iterator itr = _dispatchArrays.begin(); + itr != _dispatchArrays.end(); + ++itr) + { + (*(*itr)).dispatchIfDirty(state); + } + } + + + + // Verex Array Object methods. + void generateVretexArrayObject(); + + void bindVertexArrayObject() const; + + void unbindVertexArrayObject() const; + + GLint getVertexArrayObject() const { return _vertexArrayObject; } + + void releaseGLObjects(); + + + + void setCurrentVertexBufferObject(osg::GLBufferObject* vbo) { _currentVBO = vbo; } + const GLBufferObject* getCurrentVertexBufferObject() { return _currentVBO; } + inline void bindVertexBufferObject(osg::GLBufferObject* vbo) + { + if (vbo) + { + if (vbo == _currentVBO) return; + if (vbo->isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + _currentVBO = vbo; + } + else unbindVertexBufferObject(); + } + + inline void unbindVertexBufferObject() + { + if (!_currentVBO) return; + _ext->glBindBuffer(GL_ARRAY_BUFFER_ARB,0); + _currentVBO = 0; + } + + + void setCurrentElementBufferObject(osg::GLBufferObject* ebo) { _currentEBO = ebo; } + const GLBufferObject* getCurrentElementBufferObject() { return _currentEBO; } + + inline void bindElementBufferObject(osg::GLBufferObject* ebo) + { + if (ebo) + { + if (ebo == _currentEBO) return; + if (ebo->isDirty()) ebo->compileBuffer(); + else ebo->bindBuffer(); + _currentEBO = ebo; + } + else unbindElementBufferObject(); + } + + inline void unbindElementBufferObject() + { + if (!_currentEBO) return; + _ext->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,0); + _currentEBO = 0; + } + + +public: + + + osg::GLBufferObject* getGLBufferObject(osg::Array* array); + + osg::ref_ptr _ext; + + GLuint _vertexArrayObject; + + GLBufferObject* _currentVBO; + GLBufferObject* _currentEBO; + + ArrayDispatchList _dispatchOverall; + ArrayDispatchList _dispatchPerPrimitiveSet; + ArrayDispatchList _dispatchArrays; +}; + + +} + +#endif diff --git a/src/osg/CMakeLists.txt b/src/osg/CMakeLists.txt index 7df405dfb..6246a232f 100644 --- a/src/osg/CMakeLists.txt +++ b/src/osg/CMakeLists.txt @@ -221,6 +221,7 @@ SET(TARGET_H ${HEADER_PATH}/Vec4ui ${HEADER_PATH}/Vec4us ${HEADER_PATH}/VertexAttribDivisor + ${HEADER_PATH}/VertexArrayState ${HEADER_PATH}/VertexProgram ${HEADER_PATH}/View ${HEADER_PATH}/Viewport @@ -390,6 +391,7 @@ SET(TARGET_SRC ValueStack.cpp Version.cpp VertexAttribDivisor.cpp + VertexArrayState.cpp VertexProgram.cpp View.cpp Viewport.cpp diff --git a/src/osg/DisplaySettings.cpp b/src/osg/DisplaySettings.cpp index d70ed5040..d02bc88af 100644 --- a/src/osg/DisplaySettings.cpp +++ b/src/osg/DisplaySettings.cpp @@ -116,6 +116,8 @@ void DisplaySettings::setDisplaySettings(const DisplaySettings& vs) _glContextProfileMask = vs._glContextProfileMask; _swapMethod = vs._swapMethod; + _geometryImplementation = vs._geometryImplementation; + _keystoneHint = vs._keystoneHint; _keystoneFileNames = vs._keystoneFileNames; _keystones = vs._keystones; @@ -241,6 +243,8 @@ void DisplaySettings::setDefaults() _swapMethod = SWAP_DEFAULT; _syncSwapBuffers = 0; + _geometryImplementation = VERTEX_ARRAY_OBJECT; + _keystoneHint = false; _OSXMenubarBehavior = MENUBAR_AUTO_HIDE; @@ -361,6 +365,9 @@ static ApplicationUsageProxy DisplaySetting_e30(ApplicationUsage::ENVIRONMENTAL_ static ApplicationUsageProxy DisplaySetting_e31(ApplicationUsage::ENVIRONMENTAL_VARIABLE, "OSG_NvOptimusEnablement ", "Set the hint to NvOptimus of whether to enable it or not, set 1 to enable, 0 to disable"); +static ApplicationUsageProxy DisplaySetting_e32(ApplicationUsage::ENVIRONMENTAL_VARIABLE, + "OSG_GEOMETRY_IMPLEMENTATION ", + "Set the hint to what backend osg::Geometry implementation to use. OLD | NEW | VERTEX_ARRAY_OBJECT"); void DisplaySettings::readEnvironmentalVariables() { @@ -671,6 +678,24 @@ void DisplaySettings::readEnvironmentalVariables() } } + + if ((ptr = getenv("OSG_GEOMETRY_IMPLEMENTATION")) != 0) + { + if (strcmp(ptr,"OLD")==0) + { + _geometryImplementation = OLD_GEOMETRY_IMPLEMENTATION; + } + else if (strcmp(ptr,"NEW")==0 ) + { + _geometryImplementation = NEW_GEOMETRY_IMPLEMENTATION; + } + else if (strcmp(ptr,"VERTEX_ARRAY_OBJECT")==0 || strcmp(ptr,"VAO")==0) + { + _geometryImplementation = VERTEX_ARRAY_OBJECT; + } + } + + if( (ptr = getenv("OSG_KEYSTONE")) != 0) { if (strcmp(ptr,"OFF")==0) diff --git a/src/osg/Drawable.cpp b/src/osg/Drawable.cpp index f16231f44..7a859e474 100644 --- a/src/osg/Drawable.cpp +++ b/src/osg/Drawable.cpp @@ -226,9 +226,14 @@ Drawable::Drawable() _useDisplayList = false; #endif +#if 0 _supportsVertexBufferObjects = false; + //_useVertexBufferObjects = false; _useVertexBufferObjects = false; - // _useVertexBufferObjects = true; +#else + _supportsVertexBufferObjects = true; + _useVertexBufferObjects = false; +#endif } Drawable::Drawable(const Drawable& drawable,const CopyOp& copyop): diff --git a/src/osg/GLBeginEndAdapter.cpp b/src/osg/GLBeginEndAdapter.cpp index c95c01d79..0972d17e3 100644 --- a/src/osg/GLBeginEndAdapter.cpp +++ b/src/osg/GLBeginEndAdapter.cpp @@ -246,6 +246,8 @@ void GLBeginEndAdapter::End() } _state->lazyDisablingOfVertexAttributes(); + _state->unbindVertexBufferObject(); + _state->unbindElementBufferObject(); if (_colorAssigned) { @@ -286,6 +288,8 @@ void GLBeginEndAdapter::End() _state->applyDisablingOfVertexAttributes(); + + if (_primitiveMode==GL_QUADS) { _state->drawQuads(0, _vertices->size()); diff --git a/src/osg/GLExtensions.cpp b/src/osg/GLExtensions.cpp index 103d0193a..c05d358a0 100644 --- a/src/osg/GLExtensions.cpp +++ b/src/osg/GLExtensions.cpp @@ -22,8 +22,8 @@ #include #include -#include #include +#include #if defined(WIN32) #ifndef WIN32_LEAN_AND_MEAN @@ -92,6 +92,12 @@ bool osg::isGLExtensionSupported(unsigned int contextID, const char *extension) return osg::isGLExtensionOrVersionSupported(contextID, extension, FLT_MAX); } +bool osg::isGLExtensionSupported(unsigned int contextID, const char *extension1, const char *extension2) +{ + return osg::isGLExtensionOrVersionSupported(contextID, extension1, FLT_MAX) || + osg::isGLExtensionOrVersionSupported(contextID, extension2, FLT_MAX); +} + bool osg::isGLExtensionOrVersionSupported(unsigned int contextID, const char *extension, float requiredGLVersion) { ExtensionSet& extensionSet = s_glExtensionSetList[contextID]; @@ -415,23 +421,24 @@ OSG_INIT_SINGLETON_PROXY(GLExtensionDisableStringInitializationProxy, osg::getGL typedef osg::buffered_object< osg::ref_ptr > BufferedExtensions; static BufferedExtensions s_extensions; -GLExtensions* GLExtensions::Get(unsigned int contextID, bool createIfNotInitalized) +GLExtensions* GLExtensions::Get(unsigned int in_contextID, bool createIfNotInitalized) { - if (!s_extensions[contextID] && createIfNotInitalized) - s_extensions[contextID] = new GLExtensions(contextID); + if (!s_extensions[in_contextID] && createIfNotInitalized) + s_extensions[in_contextID] = new GLExtensions(in_contextID); - return s_extensions[contextID].get(); + return s_extensions[in_contextID].get(); } -void GLExtensions::Set(unsigned int contextID, GLExtensions* extensions) +void GLExtensions::Set(unsigned int in_contextID, GLExtensions* extensions) { - s_extensions[contextID] = extensions; + s_extensions[in_contextID] = extensions; } /////////////////////////////////////////////////////////////////////////// // Extension function pointers for OpenGL v2.x -GLExtensions::GLExtensions(unsigned int contextID) +GLExtensions::GLExtensions(unsigned int in_contextID): + contextID(in_contextID) { const char* versionString = (const char*) glGetString( GL_VERSION ); bool validContext = versionString!=0; @@ -589,7 +596,9 @@ GLExtensions::GLExtensions(unsigned int contextID) setGLExtensionFuncPtr(glVertexAttrib4ubv, "glVertexAttrib4ubv", validContext); setGLExtensionFuncPtr(glVertexAttrib4uiv, "glVertexAttrib4uiv", validContext); setGLExtensionFuncPtr(glVertexAttrib4usv, "glVertexAttrib4usv", validContext); - setGLExtensionFuncPtr(glVertexAttribPointer, "glVertexAttribPointer", validContext); + setGLExtensionFuncPtr(glVertexAttribPointer, "glVertexAttribPointer","glVertexAttribPointerARB", validContext); + setGLExtensionFuncPtr(glVertexAttribIPointer, "glVertexAttribIPointer","glVertexAttribIPointerARB", validContext); + setGLExtensionFuncPtr(glVertexAttribLPointer, "glVertexAttribLPointer","glVertexAttribPointerARB", validContext); setGLExtensionFuncPtr(glVertexAttribDivisor, "glVertexAttribDivisor", validContext); // v1.5-only ARB entry points, in case they're needed for fallback @@ -666,6 +675,7 @@ GLExtensions::GLExtensions(unsigned int contextID) // ARB_compute_shader setGLExtensionFuncPtr(glDispatchCompute, "glDispatchCompute" , validContext); + setGLExtensionFuncPtr(glMemoryBarrier, "glMemoryBarrier", "glMemoryBarrierEXT" , validContext); // BufferObject extensions @@ -685,12 +695,13 @@ GLExtensions::GLExtensions(unsigned int contextID) setGLExtensionFuncPtr(glBindBufferBase, "glBindBufferBase", "glBindBufferBaseEXT", "glBindBufferBaseNV" , validContext); setGLExtensionFuncPtr(glTexBuffer, "glTexBuffer","glTexBufferARB" , validContext); - isPBOSupported = validContext && (OSG_GL3_FEATURES || osg::isGLExtensionSupported(contextID,"GL_ARB_pixel_buffer_object")); + isVBOSupported = validContext && (OSG_GLES2_FEATURES || OSG_GL3_FEATURES || osg::isGLExtensionSupported(contextID,"GL_ARB_vertex_buffer_object")); + isPBOSupported = validContext && (OSG_GLES2_FEATURES || OSG_GL3_FEATURES || osg::isGLExtensionSupported(contextID,"GL_ARB_pixel_buffer_object")); isUniformBufferObjectSupported = validContext && osg::isGLExtensionSupported(contextID, "GL_ARB_uniform_buffer_object"); isTBOSupported = validContext && osg::isGLExtensionSupported(contextID,"GL_ARB_texture_buffer_object"); - isVAOSupported = validContext && osg::isGLExtensionSupported(contextID, "GL_ARB_vertex_array_object"); + isVAOSupported = validContext && (OSG_GL3_FEATURES || osg::isGLExtensionSupported(contextID, "GL_ARB_vertex_array_object", "GL_OES_vertex_array_object")); isTransformFeedbackSupported = validContext && osg::isGLExtensionSupported(contextID, "GL_ARB_transform_feedback2"); - isBufferObjectSupported = isPBOSupported && isVAOSupported; + isBufferObjectSupported = isVBOSupported && isPBOSupported; // BlendFunc extensions @@ -715,14 +726,24 @@ GLExtensions::GLExtensions(unsigned int contextID) isTimerQuerySupported = validContext && osg::isGLExtensionSupported(contextID, "GL_EXT_timer_query"); isARBTimerQuerySupported = validContext && osg::isGLExtensionSupported(contextID, "GL_ARB_timer_query"); + + setGLExtensionFuncPtr(glDrawArraysInstanced, "glDrawArraysInstanced","glDrawArraysInstancedARB","glDrawArraysInstancedEXT", validContext); + setGLExtensionFuncPtr(glDrawElementsInstanced, "glDrawElementsInstanced","glDrawElementsInstancedARB","glDrawElementsInstancedEXT", validContext); + + setGLExtensionFuncPtr(glFogCoordfv, "glFogCoordfv","glFogCoordfvEXT", validContext); setGLExtensionFuncPtr(glSecondaryColor3ubv, "glSecondaryColor3ubv","glSecondaryColor3ubvEXT", validContext); setGLExtensionFuncPtr(glSecondaryColor3fv, "glSecondaryColor3fv","glSecondaryColor3fvEXT", validContext); + setGLExtensionFuncPtr(glMultiTexCoord1f, "glMultiTexCoord1f","glMultiTexCoord1fARB", validContext); + setGLExtensionFuncPtr(glMultiTexCoord4f, "glMultiTexCoord4f","glMultiTexCoord4fARB", validContext); + setGLExtensionFuncPtr(glMultiTexCoord1fv, "glMultiTexCoord1fv","glMultiTexCoord1fvARB", validContext); setGLExtensionFuncPtr(glMultiTexCoord2fv, "glMultiTexCoord2fv","glMultiTexCoord2fvARB", validContext); setGLExtensionFuncPtr(glMultiTexCoord3fv, "glMultiTexCoord3fv","glMultiTexCoord3fvARB", validContext); setGLExtensionFuncPtr(glMultiTexCoord4fv, "glMultiTexCoord4fv","glMultiTexCoord4fvARB", validContext); + + setGLExtensionFuncPtr(glMultiTexCoord1d, "glMultiTexCoord1d","glMultiTexCoorddfARB", validContext); setGLExtensionFuncPtr(glMultiTexCoord1dv, "glMultiTexCoord1dv","glMultiTexCoord1dvARB", validContext); setGLExtensionFuncPtr(glMultiTexCoord2dv, "glMultiTexCoord2dv","glMultiTexCoord2dvARB", validContext); @@ -1122,6 +1143,43 @@ GLExtensions::GLExtensions(unsigned int contextID) osg::setGLExtensionFuncPtr(glDisableIndexedEXT, "glDisableIndexedEXT", validContext); osg::setGLExtensionFuncPtr(glIsEnabledIndexedEXT, "glIsEnabledIndexedEXT", validContext); + setGLExtensionFuncPtr(glClientActiveTexture,"glClientActiveTexture","glClientActiveTextureARB", validContext); + setGLExtensionFuncPtr(glActiveTexture, "glActiveTexture","glActiveTextureARB", validContext); + setGLExtensionFuncPtr(glFogCoordPointer, "glFogCoordPointer","glFogCoordPointerEXT", validContext); + setGLExtensionFuncPtr(glSecondaryColorPointer, "glSecondaryColorPointer","glSecondaryColorPointerEXT", validContext); + + if (validContext) + { + if (osg::getGLVersionNumber() >= 2.0 || osg::isGLExtensionSupported(contextID, "GL_ARB_vertex_shader") || OSG_GLES2_FEATURES || OSG_GL3_FEATURES) + { + glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,&glMaxTextureUnits); + #ifdef OSG_GL_FIXED_FUNCTION_AVAILABLE + glGetIntegerv(GL_MAX_TEXTURE_COORDS, &glMaxTextureCoords); + #else + glMaxTextureCoords = _glMaxTextureUnits; + #endif + } + else if ( osg::getGLVersionNumber() >= 1.3 || + osg::isGLExtensionSupported(contextID,"GL_ARB_multitexture") || + osg::isGLExtensionSupported(contextID,"GL_EXT_multitexture") || + OSG_GLES1_FEATURES) + { + GLint maxTextureUnits = 0; + glGetIntegerv(GL_MAX_TEXTURE_UNITS,&maxTextureUnits); + glMaxTextureUnits = maxTextureUnits; + glMaxTextureCoords = maxTextureUnits; + } + else + { + glMaxTextureUnits = 1; + glMaxTextureCoords = 1; + } + } + else + { + glMaxTextureUnits = 0; + glMaxTextureCoords = 0; + } } @@ -1230,3 +1288,62 @@ bool GLExtensions::getFragDataLocation( const char* fragDataName, GLuint& locati return true; } +////////////////////////////////////////////////////////////////////////////////////////////////// +// +// Vertex Attrib Aliasing +// +void GLExtensions::setUpVertexAttribAlias(VertexAttribAlias& alias, GLuint location, const std::string glName, const std::string osgName, const std::string& declaration) +{ + alias = VertexAttribAlias(location, glName, osgName, declaration); + _attributeBindingList[osgName] = location; + // OSG_NOTICE<<"State::setUpVertexAttribAlias("< #include +#include #include using namespace osg; @@ -603,6 +604,8 @@ void Geometry::resizeGLObjectBuffers(unsigned int maxSize) { Drawable::resizeGLObjectBuffers(maxSize); + _vertexArrayStateList.resize(maxSize); + ArrayList arrays; if (getArrayList(arrays)) { @@ -630,6 +633,9 @@ void Geometry::releaseGLObjects(State* state) const { Drawable::releaseGLObjects(state); + if (state) _vertexArrayStateList[state->getContextID()]; + else _vertexArrayStateList.clear(); + ArrayList arrays; if (getArrayList(arrays)) { @@ -734,28 +740,41 @@ void Geometry::drawImplementation(RenderInfo& renderInfo) const } State& state = *renderInfo.getState(); + const DisplaySettings* ds = state.getDisplaySettings() ? state.getDisplaySettings() : osg::DisplaySettings::instance(); bool checkForGLErrors = state.getCheckForGLErrors()==osg::State::ONCE_PER_ATTRIBUTE; if (checkForGLErrors) state.checkGLErrors("start of Geometry::drawImplementation()"); - drawVertexArraysImplementation(renderInfo); - if (checkForGLErrors) state.checkGLErrors("Geometry::drawImplementation() after vertex arrays setup."); + bool useNewImplementation = (ds->getGeometryImplementation()!=DisplaySettings::OLD_GEOMETRY_IMPLEMENTATION); + if (useNewImplementation) + { + new_drawImplementation(renderInfo); + } + else + { + // OSG_NOTICE<<"Old implementation"<getGeometryImplementation()==DisplaySettings::VERTEX_ARRAY_OBJECT); + bool dispatchIfDirty = useVAO; + + VertexArrayState* vas = _vertexArrayStateList[contextID].get(); + + bool checkForGLErrors = state.getCheckForGLErrors()==osg::State::ONCE_PER_ATTRIBUTE; + + if (checkForGLErrors) state.checkGLErrors("Geometry::new_drawImplementation() before vertex arrays setup."); + + if (!useVAO) + { + state.lazyDisablingOfVertexAttributes(); + } + + if (!vas) + { + OSG_NOTICE<<"Creating new osg::VertexArrayState"<()); + + if (_vertexArray.valid()) vas->assignVertexArray(_vertexArray.get()); + if (_colorArray.valid()) vas->assignColorArray(_colorArray.get()); + if (_normalArray.valid()) vas->assignNormalArray(_normalArray.get()); + if (_secondaryColorArray.valid()) vas->assignSecondaryColorArray(_secondaryColorArray.get()); + if (_fogCoordArray.valid()) vas->assignFogCoordArray(_fogCoordArray.get()); + + for(unsigned int i=0; i<_texCoordList.size(); ++i) + { + if (_texCoordList[i].valid()) vas->assignTexCoordArray(i, _texCoordList[i].get()); + } + + for(unsigned int i=0; i<_vertexAttribList.size(); ++i) + { + if (_vertexAttribList[i].valid()) vas->assignVertexAttribArray(i, _vertexAttribList[i].get()); + } + + if (useVAO) + { + OSG_NOTICE<<" Setup VertexArrayState to use VAO"<generateVretexArrayObject(); + dispatchIfDirty = false; + } + else + { + OSG_NOTICE<<" Setup VertexArrayState to wihtout using VAO"<bindVertexArrayObject(); + } + + osg::ref_ptr previous_vas = state.getCurrentVertexArrayState(); + + state.setCurrentVertexArrayState(vas); + + vas->dispatchOverall(state); + + + if (dispatchIfDirty) + { + vas->dispatchArraysIfDirty(state); + } + else + { + vas->dispatchArrays(state); + } + + if (!useVAO) + { + state.applyDisablingOfVertexAttributes(); + } + + for(unsigned int primitiveSetNum=0; primitiveSetNum<_primitives.size(); ++primitiveSetNum) + { + // dispatch any attributes that are bound per primitive + vas->dispatchPerPrimitveSet(state, primitiveSetNum); + + // disaptch the primitives + _primitives[primitiveSetNum]->draw(state, usingVertexBufferObjects); + } + + state.setCurrentVertexArrayState(previous_vas); + + if (!useVAO && usingVertexBufferObjects) + { + // unbind the VBO's if any are used. + state.unbindVertexBufferObject(); + state.unbindElementBufferObject(); + } + + if (checkForGLErrors) state.checkGLErrors("Geometry::new_drawImplementation() after primitive dispatch."); +} + + void Geometry::accept(AttributeFunctor& af) { AttributeFunctorArrayVisitor afav(af); diff --git a/src/osg/PrimitiveSet.cpp b/src/osg/PrimitiveSet.cpp index 718a76e91..96e4a5998 100644 --- a/src/osg/PrimitiveSet.cpp +++ b/src/osg/PrimitiveSet.cpp @@ -172,6 +172,7 @@ unsigned int DrawArrayLengths::getNumIndices() const return count; } + //////////////////////////////////////////////////////////////////////////////////////////////////////// // // DrawElementsUByte @@ -192,7 +193,10 @@ void DrawElementsUByte::draw(State& state, bool useVertexBufferObjects) const if (useVertexBufferObjects) { GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); - state.bindElementBufferObject(ebo); + + if (state.getCurrentVertexArrayState()) state.getCurrentVertexArrayState()->bindElementBufferObject(ebo); + else state.bindElementBufferObject(ebo); + if (ebo) { if (_numInstances>=1) state.glDrawElementsInstanced(mode, size(), GL_UNSIGNED_BYTE, (const GLvoid *)(ebo->getOffset(getBufferIndex())), _numInstances); @@ -252,7 +256,19 @@ void DrawElementsUShort::draw(State& state, bool useVertexBufferObjects) const if (useVertexBufferObjects) { GLBufferObject* ebo = getOrCreateGLBufferObject(state.getContextID()); - state.bindElementBufferObject(ebo); + + + if (state.getCurrentVertexArrayState()) + { + OSG_NOTICE<<" DrawElementsUShort::draw() size="< +#include + +using namespace osg; + +void VertexArrayState::ArrayDispatch::dispatchDeprecated(osg::State&, unsigned int) +{ + OSG_INFO<isBufferObjectSupported && array->getBufferObject()) + { + return array->getBufferObject()->getOrCreateGLBufferObject(_ext->contextID); + } + else + { + return 0; + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// +// VertexArrayDispatch +// +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE +struct VertexArrayDispatch : public VertexArrayState::ArrayDispatch +{ + VertexArrayDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int) + { + OSG_INFO<<"VertexArrayDispatch::dispatch() "<getNumElements()<<", "<getDataPointer()<getDataSize(), array->getDataType(), 0, array->getDataPointer()); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"VertexArrayDispatch::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } +}; + +struct VertexArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + VertexArrayWithVBODispatch(Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), vbo(in_vbo) {} + + virtual void dispatch(osg::State&, unsigned int) + { + OSG_INFO<<"VertexArrayWithVBODispatch::dispatch()"<isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(array->getDataSize(), array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"VertexArrayDispatchWitVBO::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } + + GLBufferObject* vbo; +}; + +struct VertexVec2fDispatch : public VertexArrayState::ArrayDispatch +{ + VertexVec2fDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + // OSG_INFO<<"VertexVec2fDispatch::dispatch()"<(array->getDataPointer(index))); + } +}; + +struct VertexVec3fDispatch : public VertexArrayState::ArrayDispatch +{ + VertexVec3fDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + // OSG_INFO<<"VertexVec3fDispatch::dispatch()"<(array->getDataPointer(index))); + } +}; + +struct VertexVec4fDispatch : public VertexArrayState::ArrayDispatch +{ + VertexVec4fDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + // OSG_INFO<<"VertexVec4fDispatch::dispatch()"<(array->getDataPointer(index))); + } +}; +#endif + +void VertexArrayState::assignVertexArray(osg::Array* array) +{ +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE + if (!_ext->getUseVertexAttributeAliasing()) + { + if (array->getBinding()==osg::Array::BIND_PER_VERTEX) + { + GLBufferObject* vbo = getGLBufferObject(array); + osg::ref_ptr dispatcher; + if (vbo) dispatcher = new VertexArrayWithVBODispatch(array, vbo); + else dispatcher = new VertexArrayDispatch(array); + _dispatchArrays.push_back(dispatcher.get()); + } + else + { + osg::ref_ptr dispatcher; + switch(array->getType()) + { + case(Array::Vec2ArrayType): dispatcher = new VertexVec2fDispatch(array); break; + case(Array::Vec3ArrayType): dispatcher = new VertexVec3fDispatch(array); break; + case(Array::Vec4ArrayType): dispatcher = new VertexVec4fDispatch(array); break; + default: break; // unsupported type + } + + if (dispatcher) + { + getArrayDispatchList(array->getBinding()).push_back(dispatcher); + } + } + } + else +#endif + { + assignVertexAttribArray(_ext->getVertexAlias()._location, array); + } +} + + +/////////////////////////////////////////////////////////////////////////////////// +// +// ColorArrayDispatch +// +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE +struct ColorArrayDispatch : public VertexArrayState::ArrayDispatch +{ + ColorArrayDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int) + { + OSG_INFO<<"ColorArrayDispatch::dispatch() "<getNumElements()<<", "<getDataPointer()<getDataSize(), array->getDataType(), 0, array->getDataPointer()); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"ColorArrayDispatch::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } +}; + +struct ColorArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + ColorArrayWithVBODispatch(Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), vbo(in_vbo) {} + + virtual void dispatch(osg::State&, unsigned int) + { + // OSG_INFO<<"ColorArrayWithVBODispatch::dispatch()"<isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + glEnableClientState(GL_COLOR_ARRAY); + glColorPointer(array->getDataSize(), array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"ColorArrayDispatchWitVBO::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } + + GLBufferObject* vbo; +}; + +struct ColorVec3fDispatch : public VertexArrayState::ArrayDispatch +{ + ColorVec3fDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + OSG_INFO<<"ColorVec3fDispatch::dispatch()"<(array->getDataPointer(index))); + } +}; + +struct ColorVec4fDispatch : public VertexArrayState::ArrayDispatch +{ + ColorVec4fDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + OSG_INFO<<"ColorVec4fDispatch::dispatch()"<(array->getDataPointer(index))); + } +}; + +struct ColorVec4ubDispatch : public VertexArrayState::ArrayDispatch +{ + ColorVec4ubDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + // OSG_INFO<<"ColorVec4ubDispatch::dispatch()"<(array->getDataPointer(index))); + } +}; +#endif + +void VertexArrayState::assignColorArray(osg::Array* array) +{ +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE + if (!_ext->getUseVertexAttributeAliasing()) + { + if (array->getBinding()==osg::Array::BIND_PER_VERTEX) + { + GLBufferObject* vbo = getGLBufferObject(array); + osg::ref_ptr dispatcher; + if (vbo) dispatcher = new ColorArrayWithVBODispatch(array, vbo); + else dispatcher = new ColorArrayDispatch(array); + _dispatchArrays.push_back(dispatcher.get()); + } + else + { + osg::ref_ptr dispatcher; + switch(array->getType()) + { + case(Array::Vec3ArrayType): dispatcher = new ColorVec3fDispatch(array); break; + case(Array::Vec4ArrayType): dispatcher = new ColorVec4fDispatch(array); break; + case(Array::Vec4ubArrayType): dispatcher = new ColorVec4ubDispatch(array); break; + default: break; // unsupported type + } + + if (dispatcher) + { + getArrayDispatchList(array->getBinding()).push_back(dispatcher); + } + } + } + else +#endif + { + assignVertexAttribArray(_ext->getColorAlias()._location, array); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// +// NormalArrayDispatch +// +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE +struct NormalArrayDispatch : public VertexArrayState::ArrayDispatch +{ + NormalArrayDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int) + { + OSG_INFO<<"NormalArrayDispatch::dispatch() "<getNumElements()<<", "<getDataPointer()<getDataType(), 0, array->getDataPointer()); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"NormalArrayDispatch::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } +}; + +struct NormalArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + NormalArrayWithVBODispatch(Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), vbo(in_vbo) {} + + virtual void dispatch(osg::State&, unsigned int) + { + OSG_INFO<<"NormalArrayWithVBODispatch::dispatch()"<isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + glEnableClientState(GL_NORMAL_ARRAY); + glNormalPointer(array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"NormalArrayDispatchWithVBO::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } + + GLBufferObject* vbo; +}; + +struct NormalVec3fDispatch : public VertexArrayState::ArrayDispatch +{ + NormalVec3fDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + glNormal3fv(static_cast(array->getDataPointer(index))); + } +}; +#endif + +void VertexArrayState::assignNormalArray(osg::Array* array) +{ +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE + if (!_ext->getUseVertexAttributeAliasing()) + { + if (array->getBinding()==osg::Array::BIND_PER_VERTEX) + { + GLBufferObject* vbo = getGLBufferObject(array); + osg::ref_ptr dispatcher; + if (vbo) dispatcher = new NormalArrayWithVBODispatch(array, vbo); + else dispatcher = new NormalArrayDispatch(array); + _dispatchArrays.push_back(dispatcher.get()); + } + else + { + osg::ref_ptr dispatcher; + switch(array->getType()) + { + case(Array::Vec3ArrayType): dispatcher = new NormalVec3fDispatch(array); break; + default: break; // unsupported type + } + + if (dispatcher) + { + getArrayDispatchList(array->getBinding()).push_back(dispatcher); + } + } + } + else +#endif + { + assignVertexAttribArray(_ext->getNormalAlias()._location, array); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// +// SecondaryColorArrayDispatch +// +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE +struct SecondaryColorArrayDispatch : public VertexArrayState::ArrayDispatch +{ + SecondaryColorArrayDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + OSG_INFO<<"SecondaryColorArrayDispatch::dispatch() "<getNumElements()<<", "<getDataPointer()<()->glSecondaryColorPointer(array->getDataSize(), array->getDataType(), 0, (const GLvoid *)(array->getDataPointer())); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"SecondaryColorArrayDispatch::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } +}; + +struct SecondaryColorArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + SecondaryColorArrayWithVBODispatch(Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), vbo(in_vbo) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + OSG_INFO<<"SecondaryColorArrayWithVBODispatch::dispatch()"<isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + glEnableClientState(GL_FOG_COORDINATE_ARRAY); + state.get()->glSecondaryColorPointer(array->getDataSize(), array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"SecondaryColorArrayDispatchWithVBO::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } + + GLBufferObject* vbo; +}; + +struct SecondaryColor3fDispatch : public VertexArrayState::ArrayDispatch +{ + SecondaryColor3fDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glSecondaryColor3fv(static_cast(array->getDataPointer(index))); + } +}; +#endif + +void VertexArrayState::assignSecondaryColorArray(osg::Array* array) +{ + if (!_ext->isSecondaryColorSupported) + { + OSG_WARN<<"VertexArrayState::assignSecondaryColorArray() glSeconaryColor* not support by OpenGL driver."<getUseVertexAttributeAliasing()) + { + if (array->getBinding()==osg::Array::BIND_PER_VERTEX) + { + GLBufferObject* vbo = getGLBufferObject(array); + osg::ref_ptr dispatcher; + if (vbo) dispatcher = new SecondaryColorArrayWithVBODispatch(array, vbo); + else dispatcher = new SecondaryColorArrayDispatch(array); + _dispatchArrays.push_back(dispatcher.get()); + } + else + { + osg::ref_ptr dispatcher; + switch(array->getType()) + { + case(Array::Vec3ArrayType): dispatcher = new SecondaryColor3fDispatch(array); break; + default: break; // unsupported type + } + + if (dispatcher) + { + getArrayDispatchList(array->getBinding()).push_back(dispatcher); + } + } + } + else +#endif + { + assignVertexAttribArray(_ext->getSecondaryColorAlias()._location, array); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// +// FogCoordArrayDispatch +// +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE +struct FogCoordArrayDispatch : public VertexArrayState::ArrayDispatch +{ + FogCoordArrayDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + OSG_INFO<<"FogCoordArrayDispatch::dispatch() "<getNumElements()<<", "<getDataPointer()<()->glFogCoordPointer(array->getDataType(), 0, (const GLvoid *)(array->getDataPointer())); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"FogCoordArrayDispatch::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } +}; + +struct FogCoordArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + FogCoordArrayWithVBODispatch(Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), vbo(in_vbo) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + OSG_INFO<<"FogCoordArrayWithVBODispatch::dispatch()"<isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + glEnableClientState(GL_FOG_COORDINATE_ARRAY); + state.get()->glFogCoordPointer(array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"FogCoordArrayDispatchWithVBO::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } + + GLBufferObject* vbo; +}; + +struct FogCoordfDispatch : public VertexArrayState::ArrayDispatch +{ + FogCoordfDispatch(Array* in_array) : ArrayDispatch(in_array) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glFogCoordfv(static_cast(array->getDataPointer(index))); + } +}; +#endif + +void VertexArrayState::assignFogCoordArray(osg::Array* array) +{ + if (!_ext->isFogCoordSupported) + { + OSG_WARN<<"VertexArrayState::assignFogCoordArray() glFogCoord* not support by OpenGL driver."<getUseVertexAttributeAliasing()) + { + if (array->getBinding()==osg::Array::BIND_PER_VERTEX) + { + GLBufferObject* vbo = getGLBufferObject(array); + osg::ref_ptr dispatcher; + if (vbo) dispatcher = new FogCoordArrayWithVBODispatch(array, vbo); + else dispatcher = new FogCoordArrayDispatch(array); + _dispatchArrays.push_back(dispatcher.get()); + } + else + { + osg::ref_ptr dispatcher; + switch(array->getType()) + { + case(Array::FloatArrayType): dispatcher = new FogCoordfDispatch(array); break; + default: break; // unsupported type + } + + if (dispatcher) + { + getArrayDispatchList(array->getBinding()).push_back(dispatcher); + } + } + } + else +#endif + { + assignVertexAttribArray(_ext->getFogCoordAlias()._location, array); + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// +// TexCoordArrayDispatch +// +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE +struct TexCoordArrayDispatch : public VertexArrayState::ArrayDispatch +{ + TexCoordArrayDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State&, unsigned int) + { + OSG_INFO<<"TexCoordArrayDispatch::dispatch() "<getNumElements()<<", "<getDataPointer()<(GL_TEXTURE0+unit)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(array->getDataSize(), array->getDataType(), 0, array->getDataPointer()); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"TexCoordArrayDispatch::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } + + unsigned int unit; +}; + +struct TexCoordArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + TexCoordArrayWithVBODispatch(unsigned int in_unit, Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), unit(in_unit), vbo(in_vbo) {} + + virtual void dispatch(osg::State&, unsigned int) + { + OSG_INFO<<"TexCoordArrayWithVBODispatch::dispatch()"<isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + glClientActiveTexture(static_cast(GL_TEXTURE0+unit)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glTexCoordPointer(array->getDataSize(), array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + OSG_INFO<<"TexCoordArrayDispatchWithVBO::dispatchDeprecated() "<getNumElements()<<", "<getDataPointer()<getModifiedCount(); + } + + unsigned int unit; + GLBufferObject* vbo; +}; + +struct TexCoordVec2fDispatch : public VertexArrayState::ArrayDispatch +{ + TexCoordVec2fDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + glMultiTexCoord2fv(static_cast(GL_TEXTURE0+unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct TexCoordVec3fDispatch : public VertexArrayState::ArrayDispatch +{ + TexCoordVec3fDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + glMultiTexCoord3fv(static_cast(GL_TEXTURE0+unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct TexCoordVec4fDispatch : public VertexArrayState::ArrayDispatch +{ + TexCoordVec4fDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State&, unsigned int index) + { + glMultiTexCoord4fv(static_cast(GL_TEXTURE0+unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; +#endif + +void VertexArrayState::assignTexCoordArray(unsigned int unit, osg::Array* array) +{ +#ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE + if (!_ext->getUseVertexAttributeAliasing()) + { + if (array->getBinding()==osg::Array::BIND_PER_VERTEX) + { + GLBufferObject* vbo = getGLBufferObject(array); + osg::ref_ptr dispatcher; + if (vbo) dispatcher = new TexCoordArrayWithVBODispatch(unit, array, vbo); + else dispatcher = new TexCoordArrayDispatch(unit, array); + _dispatchArrays.push_back(dispatcher.get()); + } + else + { + osg::ref_ptr dispatcher; + switch(array->getType()) + { + case(Array::Vec2ArrayType): dispatcher = new TexCoordVec2fDispatch(unit, array); break; + case(Array::Vec3ArrayType): dispatcher = new TexCoordVec3fDispatch(unit, array); break; + case(Array::Vec4ArrayType): dispatcher = new TexCoordVec4fDispatch(unit, array); break; + default: break; // unsupported type + } + + if (dispatcher) + { + getArrayDispatchList(array->getBinding()).push_back(dispatcher); + } + } + } + else +#endif + { + if (unit<_ext->getTexCoordAliasList().size()) + { + assignVertexAttribArray(_ext->getTexCoordAliasList()[unit]._location, array); + } + // else no slot assigned... + } +} + +/////////////////////////////////////////////////////////////////////////////////// +// +// VertexAttribArrayDispatch +// + +struct VertexAttribArrayDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribArrayDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + GLExtensions* ext = state.get(); + + ext->glEnableVertexAttribArray( unit ); + ext->glVertexAttribPointer(static_cast(unit), array->getDataSize(), array->getDataType(), array->getNormalize(), 0, array->getDataPointer()); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + state.setVertexAttribPointer(unit, array); + + modifiedCount = array->getModifiedCount(); + } + + unsigned int unit; +}; + +struct VertexAttribArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribArrayWithVBODispatch(unsigned int in_unit, Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), unit(in_unit), vbo(in_vbo) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + if (vbo->isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + GLExtensions* ext = state.get(); + ext->glEnableVertexAttribArray( unit ); + ext->glVertexAttribPointer(static_cast(unit), array->getDataSize(), array->getDataType(), array->getNormalize(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + state.setVertexAttribPointer(unit, array); + + modifiedCount = array->getModifiedCount(); + } + + unsigned int unit; + GLBufferObject* vbo; +}; + +struct VertexAttribLArrayDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribLArrayDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + GLExtensions* ext = state.get(); + + ext->glEnableVertexAttribArray( unit ); + ext->glVertexAttribLPointer(static_cast(unit), array->getDataSize(), array->getDataType(), 0, array->getDataPointer()); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + state.setVertexAttribLPointer(unit, array); + + modifiedCount = array->getModifiedCount(); + } + + unsigned int unit; +}; + +struct VertexAttribLArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribLArrayWithVBODispatch(unsigned int in_unit, Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), unit(in_unit), vbo(in_vbo) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + if (vbo->isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + GLExtensions* ext = state.get(); + ext->glEnableVertexAttribArray( unit ); + ext->glVertexAttribLPointer(static_cast(unit), array->getDataSize(), array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + state.setVertexAttribLPointer(unit, array); + + modifiedCount = array->getModifiedCount(); + } + + unsigned int unit; + GLBufferObject* vbo; +}; + +struct VertexAttribIArrayDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribIArrayDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + GLExtensions* ext = state.get(); + + ext->glEnableVertexAttribArray( unit ); + ext->glVertexAttribIPointer(static_cast(unit), array->getDataSize(), array->getDataType(), 0, array->getDataPointer()); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + state.setVertexAttribIPointer(unit, array); + + modifiedCount = array->getModifiedCount(); + } + + unsigned int unit; +}; + +struct VertexAttribIArrayWithVBODispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribIArrayWithVBODispatch(unsigned int in_unit, Array* in_array, GLBufferObject* in_vbo) : ArrayDispatch(in_array), unit(in_unit), vbo(in_vbo) {} + + virtual void dispatch(osg::State& state, unsigned int) + { + if (vbo->isDirty()) vbo->compileBuffer(); + else vbo->bindBuffer(); + + GLExtensions* ext = state.get(); + ext->glEnableVertexAttribArray( unit ); + ext->glVertexAttribIPointer(static_cast(unit), array->getDataSize(), array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(array->getBufferIndex()))); + + modifiedCount = array->getModifiedCount(); + } + + virtual void dispatchDeprecated(osg::State& state, unsigned int) + { + state.setVertexAttribIPointer(unit, array); + + modifiedCount = array->getModifiedCount(); + } + + unsigned int unit; + GLBufferObject* vbo; +}; + +struct VertexAttribFloatDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribFloatDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib1fv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct VertexAttribVec2fDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribVec2fDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib2fv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct VertexAttribVec3fDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribVec3fDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib3fv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct VertexAttribVec4fDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribVec4fDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib4fv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + + +struct VertexAttribDoubleDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribDoubleDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib1dv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct VertexAttribVec2dDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribVec2dDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib2dv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct VertexAttribVec3dDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribVec3dDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib3dv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + +struct VertexAttribVec4dDispatch : public VertexArrayState::ArrayDispatch +{ + VertexAttribVec4dDispatch(unsigned int in_unit, Array* in_array) : ArrayDispatch(in_array), unit(in_unit) {} + + virtual void dispatch(osg::State& state, unsigned int index) + { + state.get()->glVertexAttrib4dv(static_cast(unit), static_cast(array->getDataPointer(index))); + } + + unsigned int unit; +}; + + +void VertexArrayState::assignVertexAttribArray(unsigned int unit, osg::Array* array) +{ + if (array->getBinding()==osg::Array::BIND_PER_VERTEX) + { + GLBufferObject* vbo = getGLBufferObject(array); + osg::ref_ptr dispatcher; + if (array->getDataType()==GL_FLOAT) + { + if (vbo) dispatcher = new VertexAttribArrayWithVBODispatch(unit, array, vbo); + else dispatcher = new VertexAttribArrayDispatch(unit, array); + } + else if (array->getDataType()==GL_DOUBLE) + { + if (vbo) dispatcher = new VertexAttribLArrayWithVBODispatch(unit, array, vbo); + else dispatcher = new VertexAttribLArrayDispatch(unit, array); + } + else + { + if (vbo) dispatcher = new VertexAttribIArrayWithVBODispatch(unit, array, vbo); + else dispatcher = new VertexAttribIArrayDispatch(unit, array); + } + + _dispatchArrays.push_back(dispatcher.get()); + } + else + { + osg::ref_ptr dispatcher; + switch(array->getType()) + { + case(Array::FloatArrayType): dispatcher = new VertexAttribFloatDispatch(unit, array); break; + case(Array::Vec2ArrayType): dispatcher = new VertexAttribVec2fDispatch(unit, array); break; + case(Array::Vec3ArrayType): dispatcher = new VertexAttribVec3fDispatch(unit, array); break; + case(Array::Vec4ArrayType): dispatcher = new VertexAttribVec4fDispatch(unit, array); break; + case(Array::DoubleArrayType): dispatcher = new VertexAttribFloatDispatch(unit, array); break; + case(Array::Vec2dArrayType): dispatcher = new VertexAttribVec2dDispatch(unit, array); break; + case(Array::Vec3dArrayType): dispatcher = new VertexAttribVec3dDispatch(unit, array); break; + case(Array::Vec4dArrayType): dispatcher = new VertexAttribVec4dDispatch(unit, array); break; + default: break; // unsupported type + } + + if (dispatcher) + { + getArrayDispatchList(array->getBinding()).push_back(dispatcher); + } + } +} + +void VertexArrayState::generateVretexArrayObject() +{ + _ext->glGenVertexArrays(1, &_vertexArrayObject); +} + +void VertexArrayState::bindVertexArrayObject() const +{ + _ext->glBindVertexArray (_vertexArrayObject); +} + +void VertexArrayState::unbindVertexArrayObject() const +{ + _ext->glBindVertexArray (0); +} + +void VertexArrayState::releaseGLObjects() +{ + if (_vertexArrayObject) + { + _ext->glDeleteVertexArrays(1, &_vertexArrayObject); + } +}