diff --git a/examples/osgforest/osgforest.cpp b/examples/osgforest/osgforest.cpp index 5d8433141..6c7ae9a28 100644 --- a/examples/osgforest/osgforest.cpp +++ b/examples/osgforest/osgforest.cpp @@ -476,6 +476,8 @@ osg::Geode* ForestTechniqueManager::createTerrain(const osg::Vec3& origin, const geometry->setVertexArray(&v); geometry->setColorArray(&color, osg::Array::BIND_OVERALL); geometry->setTexCoordArray(0,&t); + geometry->setUseDisplayList(false); + geometry->setUseVertexBufferObjects(true); for(r=0;rbindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER ); - // if you want to see how many primitives were rendered - uncomment code below, but // be warned : it is a serious performance killer ( because of GPU->CPU roundtrip ) @@ -34,106 +30,12 @@ void DrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/ // OSG_WARN<<"DrawArraysIndirect ("<glUnmapBuffer(GL_DRAW_INDIRECT_BUFFER); - DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true ); - ext->glDrawArraysIndirect( _mode, reinterpret_cast(_indirect) ); - _buffer->unbindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER ); + state.get()->glDrawArraysIndirect( _mode, reinterpret_cast(_indirect) ); + } -void MultiDrawArraysIndirect::draw(osg::State& state, bool /*useVertexBufferObjects*/) const +void MultiDrawArraysIndirect::draw(osg::State& state, bool useVertexBufferObjects) const { - if( !_buffer.valid() ) - return; - _buffer->bindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER ); - - DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true ); - ext->glMultiDrawArraysIndirect( _mode, reinterpret_cast(_indirect), _drawcount, _stride ); - _buffer->unbindBufferAs( state.getContextID(), GL_DRAW_INDIRECT_BUFFER ); -} - -DrawIndirectGLExtensions::DrawIndirectGLExtensions( unsigned int contextID ) -{ - setupGLExtensions( contextID ); -} - -DrawIndirectGLExtensions::DrawIndirectGLExtensions( const DrawIndirectGLExtensions &rhs ) - : Referenced() -{ - _glDrawArraysIndirect = rhs._glDrawArraysIndirect; - _glMultiDrawArraysIndirect = rhs._glMultiDrawArraysIndirect; - _glMemoryBarrier = rhs._glMemoryBarrier; -} - - -void DrawIndirectGLExtensions::lowestCommonDenominator( const DrawIndirectGLExtensions &rhs ) -{ - if ( !rhs._glDrawArraysIndirect ) - { - _glDrawArraysIndirect = rhs._glDrawArraysIndirect; - } - if ( !rhs._glMultiDrawArraysIndirect ) - { - _glMultiDrawArraysIndirect = rhs._glMultiDrawArraysIndirect; - } - if ( !rhs._glMemoryBarrier ) - { - _glMemoryBarrier = rhs._glMemoryBarrier; - } -} - -void DrawIndirectGLExtensions::setupGLExtensions( unsigned int /*contextID*/ ) -{ - _glDrawArraysIndirect = 0; - _glMultiDrawArraysIndirect = 0; - osg::setGLExtensionFuncPtr( _glDrawArraysIndirect, "glDrawArraysIndirect" ); - osg::setGLExtensionFuncPtr( _glMultiDrawArraysIndirect, "glMultiDrawArraysIndirect" ); - osg::setGLExtensionFuncPtr( _glMemoryBarrier, "glMemoryBarrier" ); -} - -void DrawIndirectGLExtensions::glDrawArraysIndirect(GLenum mode, const void * indirect) const -{ - if ( _glDrawArraysIndirect ) - { - _glDrawArraysIndirect( mode, indirect ); - } - else - { - OSG_WARN<<"Error: glDrawArraysIndirect not supported by OpenGL driver"< > BufferedDrawIndirectGLExtensions; -static BufferedDrawIndirectGLExtensions bdiExtensions; - -DrawIndirectGLExtensions* DrawIndirectGLExtensions::getExtensions( unsigned int contextID,bool createIfNotInitalized ) -{ - if ( !bdiExtensions[contextID] && createIfNotInitalized ) - { - bdiExtensions[contextID] = new DrawIndirectGLExtensions( contextID ); - } - return bdiExtensions[contextID].get(); + // DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( state.getContextID(),true ); + state.get()->glMultiDrawArraysIndirect( _mode, reinterpret_cast(_indirect), _drawcount, _stride ); } diff --git a/examples/osggpucull/DrawIndirectPrimitiveSet.h b/examples/osggpucull/DrawIndirectPrimitiveSet.h index cc43e89fa..8a6c7b777 100644 --- a/examples/osggpucull/DrawIndirectPrimitiveSet.h +++ b/examples/osggpucull/DrawIndirectPrimitiveSet.h @@ -20,21 +20,12 @@ #include #include -#ifndef GL_ARB_draw_indirect - #define GL_DRAW_INDIRECT_BUFFER 0x8F3F - #define GL_DRAW_INDIRECT_BUFFER_BINDING 0x8F43 -#endif - -#ifndef GL_SHADER_IMAGE_ACCESS_BARRIER_BIT - #define GL_SHADER_IMAGE_ACCESS_BARRIER_BIT 0x00000020 -#endif - class DrawArraysIndirect : public osg::DrawArrays { public: - DrawArraysIndirect(GLenum mode=0, osg::TextureBuffer* buffer=NULL, unsigned int indirect=0) - : osg::DrawArrays(mode), _buffer(buffer), _indirect(indirect) + DrawArraysIndirect(GLenum mode=0, unsigned int indirect=0) + : osg::DrawArrays(mode), _indirect(indirect) { } virtual osg::Object* cloneType() const { return new DrawArraysIndirect(); } @@ -45,15 +36,14 @@ public: virtual void draw(osg::State& state, bool useVertexBufferObjects) const; protected: - osg::ref_ptr _buffer; unsigned int _indirect; }; class MultiDrawArraysIndirect : public osg::DrawArrays { public: - MultiDrawArraysIndirect(GLenum mode=0, osg::TextureBuffer* buffer=NULL, unsigned int indirect=0, GLsizei drawcount=0, GLsizei stride=0) - : osg::DrawArrays(mode), _buffer(buffer), _indirect(indirect), _drawcount(drawcount), _stride(stride) + MultiDrawArraysIndirect(GLenum mode=0, unsigned int indirect=0, GLsizei drawcount=0, GLsizei stride=0) + : osg::DrawArrays(mode), _indirect(indirect), _drawcount(drawcount), _stride(stride) { } virtual osg::Object* cloneType() const { return new MultiDrawArraysIndirect(); } @@ -64,37 +54,10 @@ public: virtual void draw(osg::State& state, bool useVertexBufferObjects) const; protected: - osg::ref_ptr _buffer; unsigned int _indirect; GLsizei _drawcount; GLsizei _stride; }; -class DrawIndirectGLExtensions : public osg::Referenced -{ -public: - DrawIndirectGLExtensions( unsigned int contextID ); - DrawIndirectGLExtensions( const DrawIndirectGLExtensions &rhs ); - void lowestCommonDenominator( const DrawIndirectGLExtensions &rhs ); - void setupGLExtensions( unsigned int contextID ); - - void glDrawArraysIndirect(GLenum mode, const void * indirect) const; - void glMultiDrawArraysIndirect(GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); - void glMemoryBarrier(GLbitfield barriers); - - static DrawIndirectGLExtensions* getExtensions( unsigned int contextID,bool createIfNotInitalized ); -protected: - - typedef void ( GL_APIENTRY *DrawArraysIndirectProc ) (GLenum mode, const void * indirect); - typedef void ( GL_APIENTRY *MultiDrawArraysIndirectProc ) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride); - typedef void ( GL_APIENTRY *MemoryBarrierProc ) (GLbitfield barriers); - - DrawArraysIndirectProc _glDrawArraysIndirect; - MultiDrawArraysIndirectProc _glMultiDrawArraysIndirect; - MemoryBarrierProc _glMemoryBarrier; - -}; - - #endif diff --git a/examples/osggpucull/osggpucull.cpp b/examples/osggpucull/osggpucull.cpp index 413af29a2..f73d3073b 100644 --- a/examples/osggpucull/osggpucull.cpp +++ b/examples/osggpucull/osggpucull.cpp @@ -189,36 +189,55 @@ struct IndirectTarget { osg::Image* indirectCommandImage = new osg::Image; indirectCommandImage->setImage( indirectCommands->getTotalDataSize()/sizeof(unsigned int), 1, 1, GL_R32I, GL_RED, GL_UNSIGNED_INT, (unsigned char*)indirectCommands->getDataPointer(), osg::Image::NO_DELETE ); + + osg::VertexBufferObject * indirectCommandImagebuffer=new osg::VertexBufferObject(); + indirectCommandImagebuffer->setUsage(GL_DYNAMIC_DRAW); + indirectCommandImage->setBufferObject(indirectCommandImagebuffer); + indirectCommandTextureBuffer = new osg::TextureBuffer(indirectCommandImage); indirectCommandTextureBuffer->setInternalFormat( GL_R32I ); - indirectCommandTextureBuffer->setUsageHint(GL_DYNAMIC_DRAW); indirectCommandTextureBuffer->bindToImageUnit(index, osg::Texture::READ_WRITE); indirectCommandTextureBuffer->setUnRefImageDataAfterApply(false); + // add proper primitivesets to geometryAggregators if( !useMultiDrawArraysIndirect ) // use glDrawArraysIndirect() { std::vector newPrimitiveSets; for(unsigned int j=0;jgetData().size(); ++j) - newPrimitiveSets.push_back( new DrawArraysIndirect( GL_TRIANGLES, indirectCommandTextureBuffer.get(), j*sizeof( DrawArraysIndirectCommand ) ) ); + newPrimitiveSets.push_back( new DrawArraysIndirect( GL_TRIANGLES, j*sizeof( DrawArraysIndirectCommand ) ) ); + geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() ); + for(unsigned int j=0;jgetData().size(); ++j) geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( newPrimitiveSets[j] ); + + } else // use glMultiDrawArraysIndirect() { geometryAggregator->getAggregatedGeometry()->removePrimitiveSet(0,geometryAggregator->getAggregatedGeometry()->getNumPrimitiveSets() ); - geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( new MultiDrawArraysIndirect( GL_TRIANGLES, indirectCommandTextureBuffer.get(), 0, indirectCommands->getData().size(), 0 ) ); + geometryAggregator->getAggregatedGeometry()->addPrimitiveSet( new MultiDrawArraysIndirect( GL_TRIANGLES, 0, indirectCommands->getData().size(), 0 ) ); } - geometryAggregator->getAggregatedGeometry()->setUseVertexBufferObjects(true); + + ///attach a DrawIndirect buffer binding to the stateset + osg::ref_ptr bb=new osg::DrawIndirectBufferBinding(); + bb->setBufferObject(indirectCommandImage->getBufferObject()); + geometryAggregator->getAggregatedGeometry()->getOrCreateStateSet()->setAttribute(bb ); geometryAggregator->getAggregatedGeometry()->setUseDisplayList(false); + geometryAggregator->getAggregatedGeometry()->setUseVertexBufferObjects(true); + osg::Image* instanceTargetImage = new osg::Image; instanceTargetImage->allocateImage( maxTargetQuantity*rowsPerInstance, 1, 1, pixelFormat, type ); + + osg::VertexBufferObject * instanceTargetImageBuffer=new osg::VertexBufferObject(); + instanceTargetImageBuffer->setUsage(GL_DYNAMIC_DRAW); + instanceTargetImage->setBufferObject(instanceTargetImageBuffer); + instanceTarget = new osg::TextureBuffer(instanceTargetImage); instanceTarget->setInternalFormat( internalFormat ); - instanceTarget->setUsageHint(GL_DYNAMIC_DRAW); instanceTarget->bindToImageUnit(OSGGPUCULL_MAXIMUM_INDIRECT_TARGET_NUMBER+index, osg::Texture::READ_WRITE); } @@ -228,6 +247,8 @@ struct IndirectTarget osg::Uniform* uniform = new osg::Uniform(uniformName.c_str(), (int)index ); stateset->addUniform( uniform ); stateset->setTextureAttribute( index, indirectCommandTextureBuffer.get() ); + + } void addIndirectTargetData( bool cullPhase, const std::string& uniformNamePrefix, int index, osg::StateSet* stateset ) { @@ -617,6 +638,9 @@ osg::Geometry* buildGPUCullGeometry( const std::vector& instance geom->setInitialBound( bbox ); + geom->setUseDisplayList(false); + geom->setUseVertexBufferObjects(true); + return geom.release(); } @@ -643,6 +667,9 @@ osg::Node* createInstanceGraph(InstanceCell* cell, const osg::BoundingBox& ob bbox.zMax() += objectsBBox.zMax(); geometry->setInitialBound(bbox); geode = new osg::Geode; + geometry->setUseDisplayList(false); + geometry->setUseVertexBufferObjects(true); + geode->addDrawable( geometry ); } @@ -728,8 +755,8 @@ struct InvokeMemoryBarrier : public osg::Drawable::DrawCallback } virtual void drawImplementation(osg::RenderInfo& renderInfo,const osg::Drawable* drawable) const { - DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( renderInfo.getContextID(), true ); - ext->glMemoryBarrier( _barriers ); + //DrawIndirectGLExtensions *ext = DrawIndirectGLExtensions::getExtensions( renderInfo.getContextID(), true ); + renderInfo.getState()->get()->glMemoryBarrier( _barriers ); drawable->drawImplementation(renderInfo); } GLbitfield _barriers; @@ -1333,8 +1360,12 @@ void createDynamicRendering( osg::Group* root, GPUCullData& gpuData, osg::Buffer // all data about instances is stored in texture buffer ( compare it with static rendering ) osg::Image* instancesImage = new osg::Image; instancesImage->setImage( instances->getTotalDataSize() / sizeof(osg::Vec4f), 1, 1, GL_RGBA32F_ARB, GL_RGBA, GL_FLOAT, (unsigned char*)instances->getDataPointer(), osg::Image::NO_DELETE ); + + osg::VertexBufferObject *instancesBuffer =new osg::VertexBufferObject; + instancesBuffer->setUsage(GL_STATIC_DRAW); + instancesImage->setBufferObject(instancesBuffer); + osg::TextureBuffer* instancesTextureBuffer = new osg::TextureBuffer(instancesImage); - instancesTextureBuffer->setUsageHint(GL_STATIC_DRAW); instancesTextureBuffer->setUnRefImageDataAfterApply(false); osg::Uniform* dynamicInstancesDataUniform = new osg::Uniform( "dynamicInstancesData", 8 ); diff --git a/include/osg/BufferIndexBinding b/include/osg/BufferIndexBinding index 51666b77c..a75532db5 100644 --- a/include/osg/BufferIndexBinding +++ b/include/osg/BufferIndexBinding @@ -50,6 +50,7 @@ class OSG_EXPORT BufferIndexBinding : public StateAttribute virtual unsigned getMember() const { return static_cast(_index); } GLenum getTarget() const { return _target; } + /** Get the index target. */ GLuint getIndex() const { return _index; } @@ -58,7 +59,8 @@ class OSG_EXPORT BufferIndexBinding : public StateAttribute void setBufferObject(BufferObject *bo) { _bufferObject = bo; } /** Get the buffer object to be bound. */ - BufferObject* getBufferObject() const { return _bufferObject.get(); } + const BufferObject* getBufferObject() const { return _bufferObject.get(); } + BufferObject* getBufferObject(){ return _bufferObject.get(); } /** Set the starting offset into the buffer object for data for the indexed target. Note: the required alignment on the offset may be quite large (e.g., 256 bytes on NVidia 8600M). This @@ -71,6 +73,7 @@ class OSG_EXPORT BufferIndexBinding : public StateAttribute void setSize(GLsizeiptr size) { _size = size; } GLsizeiptr getSize() const { return _size; } virtual void apply(State& state) const; + protected: virtual ~BufferIndexBinding(); const GLenum _target; @@ -190,7 +193,27 @@ class OSG_EXPORT ShaderStorageBufferBinding : public BufferIndexBinding } }; +class OSG_EXPORT DrawIndirectBufferBinding : public BufferIndexBinding +{ + public: + DrawIndirectBufferBinding(); + /** Create a binding for a uniform buffer index target. + * @param bo associated buffer object + */ + DrawIndirectBufferBinding( BufferObject* bo); + void apply(State& state) const; + DrawIndirectBufferBinding(const DrawIndirectBufferBinding& rhs, const CopyOp& copyop=CopyOp::SHALLOW_COPY); + META_StateAttribute(osg, DrawIndirectBufferBinding, INDIRECTDRAWBUFFERBINDING); + + virtual int compare(const StateAttribute& bb) const + { + COMPARE_StateAttribute_Types(DrawIndirectBufferBinding, bb) + COMPARE_StateAttribute_Parameter(_target) + COMPARE_StateAttribute_Parameter(_bufferObject) + return 0; + } +}; } // namespace osg diff --git a/include/osg/StateAttribute b/include/osg/StateAttribute index ff325f321..8dba14257 100644 --- a/include/osg/StateAttribute +++ b/include/osg/StateAttribute @@ -202,6 +202,8 @@ class OSG_EXPORT StateAttribute : public Object SHADERSTORAGEBUFFERBINDING, + INDIRECTDRAWBUFFERBINDING, + CAPABILITY = 100 }; diff --git a/include/osg/TextureBuffer b/include/osg/TextureBuffer index 36a476ef7..7a5c603c6 100644 --- a/include/osg/TextureBuffer +++ b/include/osg/TextureBuffer @@ -21,7 +21,7 @@ namespace osg { -/** Encapsulates OpenGL texture buffer functionality. +/** Encapsulates OpenGL texture buffer functionality in a Texture delegating its content to attached BufferObject */ class OSG_EXPORT TextureBuffer : public Texture { @@ -30,7 +30,7 @@ class OSG_EXPORT TextureBuffer : public Texture TextureBuffer(); - TextureBuffer(Image* image); + TextureBuffer(BufferData* image); /** Copy constructor using CopyOp to manage deep vs shallow copy. */ TextureBuffer(const TextureBuffer& text,const CopyOp& copyop=CopyOp::SHALLOW_COPY); @@ -46,26 +46,25 @@ class OSG_EXPORT TextureBuffer : public Texture void setImage(Image* image); /** Gets the texture image. */ - Image* getImage() { return _image.get(); } + Image* getImage() { return dynamic_cast(_bufferData.get() ); } /** Gets the const texture image. */ - inline const Image* getImage() const { return _image.get(); } + inline const Image* getImage() const { return dynamic_cast(_bufferData.get() ); } - inline unsigned int& getModifiedCount(unsigned int contextID) const + inline unsigned int & getModifiedCount(unsigned int contextID) const { // get the modified count for the current contextID. return _modifiedCount[contextID]; } - /** Sets the texture image, ignoring face. */ virtual void setImage(unsigned int, Image* image) { setImage(image); } /** Gets the texture image, ignoring face. */ - virtual Image* getImage(unsigned int) { return _image.get(); } + virtual Image* getImage(unsigned int) { return getImage(); } /** Gets the const texture image, ignoring face. */ - virtual const Image* getImage(unsigned int) const { return _image.get(); } + virtual const Image* getImage(unsigned int) const { return getImage(); } /** Gets the number of images that can be assigned to the Texture. */ virtual unsigned int getNumImages() const { return 1; } @@ -80,58 +79,31 @@ class OSG_EXPORT TextureBuffer : public Texture virtual int getTextureHeight() const { return 1; } virtual int getTextureDepth() const { return 1; } - inline void setUsageHint( GLenum usageHint ) { _usageHint=usageHint; } - inline GLenum getUsageHint() const { return _usageHint; } - virtual void allocateMipmap(State& /*state*/) const {}; /** Bind the texture buffer.*/ virtual void apply(State& state) const; - /** Bind buffer to different target. */ - void bindBufferAs(unsigned int contextID, GLenum target); - void unbindBufferAs(unsigned int contextID, GLenum target); + /** Set setBufferData attached */ + void setBufferData(BufferData *bo); + /** Set setBufferData attached */ + const BufferData * getBufferData()const {return _bufferData.get();} protected : virtual ~TextureBuffer(); virtual void computeInternalFormat() const; - ref_ptr _image; + ref_ptr< BufferData > _bufferData; - mutable GLsizei _textureWidth; - GLenum _usageHint; + GLsizei _textureWidth; - typedef buffered_value ImageModifiedCount; - mutable ImageModifiedCount _modifiedCount; + typedef buffered_value< unsigned int > BufferDataModifiedCount; + mutable BufferDataModifiedCount _modifiedCount; - class TextureBufferObject : public osg::Referenced - { - public: - TextureBufferObject(unsigned int contextID, GLenum usageHint) : - _id(0), - _usageHint(usageHint) - { - _extensions = osg::GLExtensions::Get(contextID, true); - } - void bindBuffer(GLenum target); - void unbindBuffer(GLenum target); - - void texBuffer(GLenum internalFormat); - void bufferData( osg::Image* image ); - void bufferSubData( osg::Image* image ); - - public: - GLuint _id; - GLenum _usageHint; - osg::GLExtensions* _extensions; - }; - - typedef osg::buffered_object > TextureBufferObjectList; - mutable TextureBufferObjectList _textureBufferObjects; -}; + }; } diff --git a/src/osg/BufferIndexBinding.cpp b/src/osg/BufferIndexBinding.cpp index 35c030f38..e08f8b787 100644 --- a/src/osg/BufferIndexBinding.cpp +++ b/src/osg/BufferIndexBinding.cpp @@ -18,6 +18,9 @@ #include // for memcpy +#ifndef GL_DRAW_INDIRECT_BUFFER + #define GL_DRAW_INDIRECT_BUFFER 0x8F3F +#endif namespace osg { @@ -164,5 +167,33 @@ ShaderStorageBufferBinding::ShaderStorageBufferBinding(const ShaderStorageBuffer +DrawIndirectBufferBinding::DrawIndirectBufferBinding( ) + : BufferIndexBinding(GL_DRAW_INDIRECT_BUFFER, 0) +{ +} +void DrawIndirectBufferBinding::apply(State& state) const +{ + if (_bufferObject.valid()) + { + GLBufferObject* glObject + = _bufferObject->getOrCreateGLBufferObject(state.getContextID()); + if (!glObject->_extensions->isUniformBufferObjectSupported) + return; + // if (glObject->isDirty()) glObject->compileBuffer(); + glObject->_extensions->glBindBuffer (_target, glObject->getGLObjectID()); + } +} +DrawIndirectBufferBinding::DrawIndirectBufferBinding( BufferObject* bo) + : BufferIndexBinding(GL_DRAW_INDIRECT_BUFFER, 0, bo, 0, 0) +{ + +} + +DrawIndirectBufferBinding::DrawIndirectBufferBinding(const DrawIndirectBufferBinding& rhs, + const CopyOp& copyop) + : BufferIndexBinding(rhs, copyop) +{ +} + } // namespace osg diff --git a/src/osg/TextureBuffer.cpp b/src/osg/TextureBuffer.cpp index 04c319f88..91eea6c51 100644 --- a/src/osg/TextureBuffer.cpp +++ b/src/osg/TextureBuffer.cpp @@ -12,31 +12,65 @@ */ #include #include +#include + +#ifndef GL_TEXTURE_BUFFER + #define GL_TEXTURE_BUFFER 0x8C2A +#endif using namespace osg; TextureBuffer::TextureBuffer(): - _textureWidth(0), _usageHint(GL_STREAM_DRAW) + _textureWidth(0) { } -TextureBuffer::TextureBuffer(osg::Image* image): - _textureWidth(0), _usageHint(GL_STREAM_DRAW) +TextureBuffer::TextureBuffer(osg::BufferData* image): + _textureWidth(0) { - setImage(image); + setBufferData(image); } TextureBuffer::TextureBuffer(const TextureBuffer& text,const CopyOp& copyop): - Texture(text,copyop), - _textureWidth(text._textureWidth), - _usageHint(text._usageHint) + Texture(text,copyop), + _textureWidth(text._textureWidth) { - setImage(copyop(text._image.get())); + setBufferData(osg::clone(text._bufferData.get(), copyop)); } TextureBuffer::~TextureBuffer() { - setImage(NULL); + _bufferData=NULL; +} + +void TextureBuffer::setBufferData(BufferData *bufferdata) +{ + if (_bufferData == bufferdata) return; + + if (_bufferData.valid()) + { + _bufferData->removeClient(this); + } + + + _bufferData=bufferdata; + _modifiedCount.setAllElementsTo(0); + + + if (_bufferData.valid()) + { + _bufferData->addClient(this); + + ///set BufferObject if not setted by user + if(!_bufferData->getBufferObject()) + { + VertexBufferObject* bo=new VertexBufferObject(); + bo->setUsage(GL_STREAM_DRAW_ARB); + bufferdata->setBufferObject(bo); + } + } + + } int TextureBuffer::compare(const StateAttribute& sa) const @@ -45,13 +79,17 @@ int TextureBuffer::compare(const StateAttribute& sa) const // used by the COMPARE_StateAttribute_Parameter macros below. COMPARE_StateAttribute_Types(TextureBuffer,sa) - if (_image!=rhs._image) // smart pointer comparison. + + if (_bufferData!=rhs._bufferData) // smart pointer comparison. { - if (_image.valid()) + if (_bufferData.valid()) { - if (rhs._image.valid()) + if (rhs._bufferData.valid()) { - int result = _image->compare(*rhs._image); + //int result = _bufferData->compare(*rhs._bufferData); + int result=0; + if(_bufferData.get()rhs._bufferData.get())result=-1; if (result!=0) return result; } else @@ -59,13 +97,13 @@ int TextureBuffer::compare(const StateAttribute& sa) const return 1; // valid lhs._image is greater than null. } } - else if (rhs._image.valid()) + else if (rhs._bufferData.valid()) { return -1; // valid rhs._image is greater than null. } } - if (!_image && !rhs._image) + if (!_bufferData && !rhs._bufferData) { int result = compareTextureObjects(rhs); if (result!=0) return result; @@ -76,27 +114,19 @@ int TextureBuffer::compare(const StateAttribute& sa) const // compare each parameter in turn against the rhs. COMPARE_StateAttribute_Parameter(_textureWidth) - COMPARE_StateAttribute_Parameter(_usageHint) + //COMPARE_StateAttribute_Parameter(_usageHint) return 0; + } void TextureBuffer::setImage(Image* image) { - if (_image == image) return; + if (getImage() == image) return; - if (_image.valid()) - { - _image->removeClient(this); - } + setBufferData(image); - _image = image; - _modifiedCount.setAllElementsTo(0); - if (_image.valid()) - { - _image->addClient(this); - } } void TextureBuffer::apply(State& state) const @@ -105,67 +135,93 @@ void TextureBuffer::apply(State& state) const const unsigned int contextID = state.getContextID(); TextureObject* textureObject = getTextureObject(contextID); - TextureBufferObject* textureBufferObject = _textureBufferObjects[contextID].get(); +///This code could be usefull but would require to watch BufferData changes +///perhaps a mutable percontext dirtyflag (all reset to true onTextureObjectChanged) would do the trick +#if 0 + if (textureObject) + { + bool textureObjectInvalidated = false; + if (textureObject->_profile._internalFormat != _internalFormat ) + { + textureObjectInvalidated=true; + } + if (textureObjectInvalidated) + { + //OSG_NOTICE<<"Discarding TextureObject"<release(); + _textureObjectBuffer[contextID] = 0; + textureObject = 0; + } + } +#endif if (textureObject) { - if (_image.valid() && getModifiedCount(contextID) != _image->getModifiedCount()) + const GLExtensions* extensions = state.get(); + if(_bufferData.valid() &&_modifiedCount[contextID]!=_bufferData->getModifiedCount() ) { - computeInternalFormat(); - textureBufferObject->bindBuffer(GL_TEXTURE_BUFFER); - textureBufferObject->bufferSubData(_image.get() ); - textureBufferObject->unbindBuffer(GL_TEXTURE_BUFFER); - _modifiedCount[contextID] = _image->getModifiedCount(); + GLBufferObject* glBufferObject = _bufferData->getBufferObject()->getOrCreateGLBufferObject(contextID); + if (glBufferObject) + { + if( glBufferObject->isDirty() ) + { + //OSG_NOTICE<<"buffer upload"<compileBuffer(); + } + + } + + _modifiedCount[contextID]=_bufferData->getModifiedCount() ; } textureObject->bind(); if( getTextureParameterDirty(contextID) ) { - const GLExtensions* extensions = state.get(); - if (extensions->isBindImageTextureSupported() && _imageAttachment.access!=0) + if( extensions->isBindImageTextureSupported() && _imageAttachment.access!=0 ) { - extensions->glBindImageTexture( - _imageAttachment.unit, textureObject->id(), _imageAttachment.level, - _imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access, - _imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat); - } - getTextureParameterDirty(state.getContextID()) = false; - } - } - else if (_image.valid() && _image->data()) - { - textureObject = generateAndAssignTextureObject(contextID, GL_TEXTURE_BUFFER); - textureObject->bind(); - - textureBufferObject = new TextureBufferObject(contextID,_usageHint); - _textureBufferObjects[contextID] = textureBufferObject; - - const GLExtensions* extensions = state.get(); - if (extensions->isBindImageTextureSupported() && _imageAttachment.access!=0) - { extensions->glBindImageTexture( _imageAttachment.unit, textureObject->id(), _imageAttachment.level, _imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access, _imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat); + } + getTextureParameterDirty(state.getContextID()) = false; } - getTextureParameterDirty(state.getContextID()) = false; - - computeInternalFormat(); - _textureWidth = _image->s(); - textureBufferObject->bindBuffer(GL_TEXTURE_BUFFER); - textureBufferObject->bufferData( _image.get() ); - textureObject->setAllocated(true); - textureBufferObject->unbindBuffer(GL_TEXTURE_BUFFER); - - textureObject->bind(); - textureBufferObject->texBuffer(_internalFormat); - - _modifiedCount[contextID] = _image->getModifiedCount(); } - else + else if (_bufferData.valid() &&_bufferData->getBufferObject() )//&& _bufferObject->getNumBufferData()>0 ) { - glBindTexture(GL_TEXTURE_BUFFER, 0); + /// now compile bufferobject if required + GLBufferObject* glBufferObject = _bufferData->getBufferObject()->getOrCreateGLBufferObject(contextID); + if (glBufferObject ) + { + const GLExtensions* extensions = state.get(); + + textureObject = generateAndAssignTextureObject(contextID, GL_TEXTURE_BUFFER); + textureObject->_profile._internalFormat=_internalFormat; + textureObject->bind(); + + if ( extensions->isBindImageTextureSupported() && _imageAttachment.access!=0 ) + { + extensions->glBindImageTexture( + _imageAttachment.unit, textureObject->id(), _imageAttachment.level, + _imageAttachment.layered, _imageAttachment.layer, _imageAttachment.access, + _imageAttachment.format!=0 ? _imageAttachment.format : _internalFormat); + } + getTextureParameterDirty(state.getContextID()) = false; + + computeInternalFormat(); + + if( glBufferObject->isDirty()) + glBufferObject->compileBuffer(); + + textureObject->setAllocated(true); + extensions->glBindBuffer(_bufferData->getBufferObject()->getTarget(),0); + + textureObject->bind(); + extensions->glTexBuffer(GL_TEXTURE_BUFFER, _internalFormat, glBufferObject->getGLObjectID()); + _modifiedCount[contextID] = _bufferData->getModifiedCount(); + } + } #else @@ -173,49 +229,10 @@ void TextureBuffer::apply(State& state) const #endif } -void TextureBuffer::bindBufferAs( unsigned int contextID, GLuint target ) -{ - TextureBufferObject* textureBufferObject = _textureBufferObjects[contextID].get(); - textureBufferObject->bindBuffer(target); - -} - -void TextureBuffer::unbindBufferAs( unsigned int contextID, GLuint target ) -{ - TextureBufferObject* textureBufferObject = _textureBufferObjects[contextID].get(); - textureBufferObject->unbindBuffer(target); -} - void TextureBuffer::computeInternalFormat() const { - if (_image.valid()) computeInternalFormatWithImage(*_image); + if (getImage() ) computeInternalFormatWithImage(*getImage()); else computeInternalFormatType(); } -void TextureBuffer::TextureBufferObject::bindBuffer(GLenum target) -{ - if (_id == 0) - _extensions->glGenBuffers(1, &_id); - _extensions->glBindBuffer(target, _id); -} - -void TextureBuffer::TextureBufferObject::unbindBuffer(GLenum target) -{ - _extensions->glBindBuffer(target, 0); -} - -void TextureBuffer::TextureBufferObject::texBuffer(GLenum internalFormat) -{ - _extensions->glTexBuffer(GL_TEXTURE_BUFFER, internalFormat, _id); -} - -void TextureBuffer::TextureBufferObject::bufferData( osg::Image* image ) -{ - _extensions->glBufferData(GL_TEXTURE_BUFFER, image->getTotalDataSize(), image->data(), _usageHint); -} - -void TextureBuffer::TextureBufferObject::bufferSubData( osg::Image* image ) -{ - _extensions->glBufferSubData(GL_TEXTURE_BUFFER, 0, image->getTotalDataSize(), image->data()); -}