/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #include #include #include using namespace osg; #if 1 #define VAS_NOTICE OSG_INFO #else #define VAS_NOTICE OSG_NOTICE #endif class VertexArrayStateManager : public GraphicsObjectManager { public: VertexArrayStateManager(unsigned int contextID): GraphicsObjectManager("VertexArrayStateManager", contextID) { } virtual void flushDeletedGLObjects(double, double& availableTime) { // if no time available don't try to flush objects. if (availableTime<=0.0) return; VAS_NOTICE<<"VertexArrayStateManager::flushDeletedGLObjects()"< lock(_mutex_vertexArrayStateList); // trim from front VertexArrayStateList::iterator ditr=_vertexArrayStateList.begin(); for(; ditr!=_vertexArrayStateList.end() && elapsedTimeget(); vas->deleteVertexArrayObject(); elapsedTime = timer.delta_s(start_tick,timer.tick()); } if (ditr!=_vertexArrayStateList.begin()) _vertexArrayStateList.erase(_vertexArrayStateList.begin(),ditr); } elapsedTime = timer.delta_s(start_tick,timer.tick()); availableTime -= elapsedTime; } virtual void flushAllDeletedGLObjects() { VAS_NOTICE<<"VertexArrayStateManager::flushAllDeletedGLObjects()"< lock(_mutex_vertexArrayStateList); for(VertexArrayStateList::iterator itr = _vertexArrayStateList.begin(); itr != _vertexArrayStateList.end(); ++itr) { VertexArrayState* vas = itr->get(); vas->deleteVertexArrayObject(); } _vertexArrayStateList.clear(); } virtual void deleteAllGLObjects() { OSG_INFO<<"VertexArrayStateManager::deleteAllGLObjects() Not currently implementated"< lock(_mutex_vertexArrayStateList); _vertexArrayStateList.clear(); } void release(VertexArrayState* vas) { VAS_NOTICE<<"VertexArrayStateManager::release("< lock(_mutex_vertexArrayStateList); _vertexArrayStateList.push_back(vas); } protected: typedef std::list< osg::ref_ptr > VertexArrayStateList; OpenThreads::Mutex _mutex_vertexArrayStateList; VertexArrayStateList _vertexArrayStateList; }; #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE /////////////////////////////////////////////////////////////////////////////////// // // VertexArrayDispatch // struct VertexArrayDispatch : public VertexArrayState::ArrayDispatch { VertexArrayDispatch() {} virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array) { VAS_NOTICE<<" VertexArrayDispatch::enable_and_dispatch("<getNumElements()<<")"<getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" VertexArrayDispatch::enable_and_dispatch("<getNumElements()<<", vbo="<getDataSize(), new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void enable_and_dispatch(osg::State& /*state*/, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean /*normalized*/) { glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer(size, type, stride, ptr); } virtual void dispatch(osg::State& state, const osg::Array* new_array) { VAS_NOTICE<<" VertexArrayDispatch::dispatch("<getNumElements()<<")"<getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" VertexArrayDispatch::dispatch("<getNumElements()<<", vbo"<getDataSize(), new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void dispatch(osg::State& /*state*/, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean /*normalized*/) { glVertexPointer(size, type, stride, ptr); } virtual void disable(osg::State& state) { VAS_NOTICE<<" VertexArrayDispatch::disable()"<getNumElements()<<")"<getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void enable_and_dispatch(osg::State& /*state*/, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean /*normalized*/) { glEnableClientState(GL_COLOR_ARRAY); glColorPointer(size, type, stride, ptr); } virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" ColorArrayDispatch::enable_and_dispatch("<getNumElements()<<", vbo="<getDataSize(), new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void dispatch(osg::State& state, const osg::Array* new_array) { VAS_NOTICE<<" ColorArrayDispatch::dispatch("<getNumElements()<<")"<getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" ColorArrayDispatch::dispatch("<getNumElements()<<", vbo="<getDataSize(), new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void dispatch(osg::State& /*state*/, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean /*normalized*/) { glColorPointer(size, type, stride, ptr); } virtual void disable(osg::State& state) { VAS_NOTICE<<" ColorArrayDispatch::disable()"<getNumElements()<<")"<getDataType(), 0, new_array->getDataPointer()); } virtual void enable_and_dispatch(osg::State&, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" NormalArrayDispatch::enable_and_dispatch("<getNumElements()<<", vbo="<getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void enable_and_dispatch(osg::State& /*state*/, GLint /*size*/, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean /*normalized*/) { glEnableClientState(GL_NORMAL_ARRAY); glNormalPointer(type, stride, ptr); } virtual void dispatch(osg::State& state, const osg::Array* new_array) { VAS_NOTICE<<" NormalArrayDispatch::dispatch("<getNumElements()<<")"<getDataType(), 0, new_array->getDataPointer()); } virtual void dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" NormalArrayDispatch::dispatch("<getNumElements()<<", vbo="<getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void dispatch(osg::State& /*state*/, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean /*normalized*/) { glNormalPointer(type, stride, ptr); } virtual void disable(osg::State& state) { VAS_NOTICE<<" NormalArrayDispatch::disable()"<()->glSecondaryColorPointer(new_array->getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { glEnableClientState(GL_SECONDARY_COLOR_ARRAY); state.get()->glSecondaryColorPointer(new_array->getDataSize(), new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void dispatch(osg::State& state, const osg::Array* new_array) { state.get()->glSecondaryColorPointer(new_array->getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { state.get()->glSecondaryColorPointer(new_array->getDataSize(), new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void disable(osg::State& state) { glDisableClientState(GL_SECONDARY_COLOR_ARRAY); } }; /////////////////////////////////////////////////////////////////////////////////// // // FogCoordArrayDispatch // struct FogCoordArrayDispatch : public VertexArrayState::ArrayDispatch { FogCoordArrayDispatch() {} virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array) { glEnableClientState(GL_FOG_COORD_ARRAY); state.get()->glFogCoordPointer(new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { glEnableClientState(GL_FOG_COORD_ARRAY); state.get()->glFogCoordPointer(new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void dispatch(osg::State& state, const osg::Array* new_array) { state.get()->glFogCoordPointer(new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { state.get()->glFogCoordPointer(new_array->getDataType(), 0, (const GLvoid *)(vbo->getOffset(new_array->getBufferIndex()))); } virtual void disable(osg::State& state) { glDisableClientState(GL_FOG_COORD_ARRAY); } }; /////////////////////////////////////////////////////////////////////////////////// // // TexCoordArrayDispatch // struct TexCoordArrayDispatch : public VertexArrayState::ArrayDispatch { TexCoordArrayDispatch(unsigned int in_unit) : unit(in_unit) {} virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array) { VAS_NOTICE<<" TexCoordArrayDispatch::enable_and_dispatch("<getNumElements()<<") unit="<getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void enable_and_dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" TexCoordArrayDispatch::enable_and_dispatch("<getNumElements()<<", vbo="<getNumElements()<<") unit="<getDataSize(), new_array->getDataType(), 0, new_array->getDataPointer()); } virtual void dispatch(osg::State& state, const osg::Array* new_array, const osg::GLBufferObject* vbo) { VAS_NOTICE<<" TexCoordArrayDispatch::dispatch("<getNumElements()<<", vbo="<glDeleteVertexArrays(1, &_vertexArrayObject); _vertexArrayObject = 0; } } void VertexArrayState::assignVertexArrayDispatcher() { #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE if (!_state->getUseVertexAttributeAliasing()) { _vertexArray = new VertexArrayDispatch(); } else #endif { VAS_NOTICE<<"VertexArrayState::assignNormalArrayDispatcher() _state->getVertexAlias()._location="<<_state->getVertexAlias()._location<getVertexAlias()._location); } } void VertexArrayState::assignNormalArrayDispatcher() { #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE if (!_state->getUseVertexAttributeAliasing()) { _normalArray = new NormalArrayDispatch(); } else #endif { VAS_NOTICE<<"VertexArrayState::assignNormalArrayDispatcher() _state->getNormalAlias()._location="<<_state->getNormalAlias()._location<getNormalAlias()._location); } } void VertexArrayState::assignColorArrayDispatcher() { #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE if (!_state->getUseVertexAttributeAliasing()) { _colorArray = new ColorArrayDispatch(); } else #endif { VAS_NOTICE<<"VertexArrayState::assignColorArrayDispatcher() _state->getColorAlias()._location="<<_state->getColorAlias()._location<getColorAlias()._location); } } void VertexArrayState::assignSecondaryColorArrayDispatcher() { #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE if (!_state->getUseVertexAttributeAliasing()) { _secondaryColorArray = new SecondaryColorArrayDispatch(); } else #endif { _secondaryColorArray = new VertexAttribArrayDispatch(_state->getSecondaryColorAlias()._location); } } void VertexArrayState::assignFogCoordArrayDispatcher() { #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE if (!_state->getUseVertexAttributeAliasing()) { _fogCoordArray = new FogCoordArrayDispatch(); } else #endif { _fogCoordArray = new VertexAttribArrayDispatch(_state->getFogCoordAlias()._location); } } void VertexArrayState::assignTexCoordArrayDispatcher(unsigned int numUnits) { #ifdef OSG_GL_VERTEX_ARRAY_FUNCS_AVAILABLE if (!_state->getUseVertexAttributeAliasing()) { _texCoordArrays.clear(); for(unsigned int i=0; igetTexCoordAliasList()[i]._location="<<_state->getTexCoordAliasList()[i]._location<getTexCoordAliasList()[i]._location) ); } } } void VertexArrayState::assignVertexAttribArrayDispatcher(unsigned int numUnits) { _vertexAttribArrays.clear(); for(unsigned int i=0; i(_ext->contextID)->release(this); } void VertexArrayState::setArray(ArrayDispatch* vad, osg::State& state, const osg::Array* new_array) { if (new_array) { if (!vad->active) { vad->active = true; _activeDispatchers.push_back(vad); } if (vad->array==0) { GLBufferObject* vbo = isVertexBufferObjectSupported() ? new_array->getOrCreateGLBufferObject(state.getContextID()) : 0; if (vbo) { bindVertexBufferObject(vbo); vad->enable_and_dispatch(state, new_array, vbo); } else { unbindVertexBufferObject(); vad->enable_and_dispatch(state, new_array); } } else if (new_array!=vad->array || new_array->getModifiedCount()!=vad->modifiedCount) { GLBufferObject* vbo = isVertexBufferObjectSupported() ? new_array->getOrCreateGLBufferObject(state.getContextID()) : 0; if (vbo) { bindVertexBufferObject(vbo); vad->dispatch(state, new_array, vbo); } else { unbindVertexBufferObject(); vad->dispatch(state, new_array); } } vad->array = new_array; vad->modifiedCount = new_array->getModifiedCount(); } else if (vad->array) { disable(vad, state); } } void VertexArrayState::setArray(ArrayDispatch* vad, osg::State& state, GLint size, GLenum type, GLsizei stride, const GLvoid *ptr, GLboolean normalized) { if (ptr) { if (!vad->active) { vad->active = true; _activeDispatchers.push_back(vad); } if (vad->array==0) { unbindVertexBufferObject(); vad->enable_and_dispatch(state, size, type, stride, ptr, normalized); } else { unbindVertexBufferObject(); vad->dispatch(state, size, type, stride, ptr, normalized); } vad->array = 0; vad->modifiedCount = 0xffffffff; } else if (vad->array) { disable(vad, state); } } void VertexArrayState::setInterleavedArrays( osg::State& state, GLenum format, GLsizei stride, const GLvoid* pointer) { OSG_NOTICE<<"Warning: VertexArrayState::setInterleavedArrays() NOT IMPLEMENTATED YET"<