Added releaseGLObjects(State*) support into osg::FrameBufferObject, osg::RenderBin and osg::RenderStage

to ensure proper clean up of FBO's on closing a graphics context.
This commit is contained in:
Robert Osfield 2011-04-20 11:45:01 +00:00
parent f564926570
commit 70aa087f6e
8 changed files with 158 additions and 2 deletions

View File

@ -242,6 +242,14 @@ namespace osg
static int getMaxSamples(unsigned int contextID, const FBOExtensions *ext);
/** Resize any per context GLObject buffers to specified size. */
virtual void resizeGLObjectBuffers(unsigned int maxSize);
/** If State is non-zero, this function releases any associated OpenGL objects for
* the specified graphics context. Otherwise, releases OpenGL objexts
* for all graphics contexts. */
virtual void releaseGLObjects(osg::State* = 0) const;
protected:
virtual ~RenderBuffer();
RenderBuffer &operator=(const RenderBuffer &) { return *this; }
@ -451,6 +459,14 @@ namespace osg
* in the OpenGL context related to contextID.*/
static void discardDeletedFrameBufferObjects(unsigned int contextID);
/** Resize any per context GLObject buffers to specified size. */
virtual void resizeGLObjectBuffers(unsigned int maxSize);
/** If State is non-zero, this function releases any associated OpenGL objects for
* the specified graphics context. Otherwise, releases OpenGL objexts
* for all graphics contexts. */
virtual void releaseGLObjects(osg::State* = 0) const;
protected:
virtual ~FrameBufferObject();
FrameBufferObject& operator = (const FrameBufferObject&) { return *this; }

View File

@ -148,6 +148,11 @@ class OSGUTIL_EXPORT RenderBin : public osg::Object
void copyLeavesFromStateGraphListToRenderLeafList();
/** If State is non-zero, this function releases any associated OpenGL objects for
* the specified graphics context. Otherwise, releases OpenGL objexts
* for all graphics contexts. */
virtual void releaseGLObjects(osg::State* state= 0) const;
protected:
virtual ~RenderBin();

View File

@ -253,6 +253,11 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin
/** clear the references to any dependent cameras.*/
void clearReferencesToDependentCameras();
/** If State is non-zero, this function releases any associated OpenGL objects for
* the specified graphics context. Otherwise, releases OpenGL objexts
* for all graphics contexts. */
virtual void releaseGLObjects(osg::State* state= 0) const;
protected:
virtual ~RenderStage();

View File

@ -284,6 +284,36 @@ GLuint RenderBuffer::getObjectID(unsigned int contextID, const FBOExtensions *ex
return objectID;
}
void RenderBuffer::resizeGLObjectBuffers(unsigned int maxSize)
{
_objectID.resize(maxSize);
_dirty.resize(maxSize);
}
void RenderBuffer::releaseGLObjects(osg::State* state) const
{
if (state)
{
unsigned int contextID = state->getContextID();
if (_objectID[contextID])
{
deleteRenderBuffer(contextID, _objectID[contextID]);
_objectID[contextID] = 0;
}
}
else
{
for(unsigned i=0; i<_objectID.size(); ++i)
{
if (_objectID[i])
{
deleteRenderBuffer(i, _objectID[i]);
_objectID[i] = 0;
}
}
}
}
/**************************************************************************
* FrameBufferAttachment
**************************************************************************/
@ -748,6 +778,37 @@ FrameBufferObject::~FrameBufferObject()
}
}
void FrameBufferObject::resizeGLObjectBuffers(unsigned int maxSize)
{
_fboID.resize(maxSize);
_unsupported.resize(maxSize);
_fboID.resize(maxSize);
}
void FrameBufferObject::releaseGLObjects(osg::State* state) const
{
if (state)
{
unsigned int contextID = state->getContextID();
if (_fboID[contextID])
{
deleteFrameBufferObject(contextID, _fboID[contextID]);
_fboID[contextID] = 0;
}
}
else
{
for(unsigned int i=0; i<_fboID.size(); ++i)
{
if (_fboID[i])
{
deleteFrameBufferObject(i, _fboID[i]);
_fboID[i] = 0;
}
}
}
}
void FrameBufferObject::setAttachment(BufferComponent attachment_point, const FrameBufferAttachment &attachment)
{
_attachments[attachment_point] = attachment;

View File

@ -34,8 +34,8 @@ void osg::flushDeletedGLObjects(unsigned int contextID, double currentTime, doub
osg::GLBufferObject::flushDeletedBufferObjects(contextID,currentTime,availableTime);
osg::FrameBufferObject::flushDeletedFrameBufferObjects(contextID,currentTime,availableTime);
osg::Program::flushDeletedGlPrograms(contextID,currentTime,availableTime);
osg::RenderBuffer::flushDeletedRenderBuffers(contextID,currentTime,availableTime);
osg::Program::flushDeletedGlPrograms(contextID,currentTime,availableTime);
osg::Shader::flushDeletedGlShaders(contextID,currentTime,availableTime);
osg::Texture::flushDeletedTextureObjects(contextID,currentTime,availableTime);
osg::OcclusionQueryNode::flushDeletedQueryObjects(contextID,currentTime,availableTime);

View File

@ -1285,6 +1285,30 @@ class RenderStageCache : public osg::Object
typedef std::map<CullVisitor*, osg::ref_ptr<RenderStage> > RenderStageMap;
/** Resize any per context GLObject buffers to specified size. */
virtual void resizeGLObjectBuffers(unsigned int maxSize)
{
for(RenderStageMap::const_iterator itr = _renderStageMap.begin();
itr != _renderStageMap.end();
++itr)
{
itr->second->resizeGLObjectBuffers(maxSize);
}
}
/** If State is non-zero, this function releases any associated OpenGL objects for
* the specified graphics context. Otherwise, releases OpenGL objexts
* for all graphics contexts. */
virtual void releaseGLObjects(osg::State* state= 0) const
{
for(RenderStageMap::const_iterator itr = _renderStageMap.begin();
itr != _renderStageMap.end();
++itr)
{
itr->second->releaseGLObjects(state);
}
}
OpenThreads::Mutex _mutex;
RenderStageMap _renderStageMap;
};

View File

@ -648,3 +648,16 @@ unsigned int RenderBin::computeNumberOfDynamicRenderLeaves() const
return count;
}
void RenderBin::releaseGLObjects(osg::State* state) const
{
if (_stateset) _stateset->releaseGLObjects(state);
for(RenderBinList::const_iterator itr = _bins.begin();
itr != _bins.end();
++itr)
{
itr->second->releaseGLObjects(state);
}
}

View File

@ -1494,3 +1494,35 @@ void RenderStage::clearReferencesToDependentCameras()
_dependentCameras.clear();
}
void RenderStage::releaseGLObjects(osg::State* state) const
{
RenderBin::releaseGLObjects(state);
for(RenderStageList::const_iterator itr = _preRenderList.begin();
itr != _preRenderList.end();
++itr)
{
itr->second->releaseGLObjects(state);
}
for(RenderStageList::const_iterator itr = _postRenderList.begin();
itr != _postRenderList.end();
++itr)
{
itr->second->releaseGLObjects(state);
}
for(Cameras::const_iterator itr = _dependentCameras.begin();
itr != _dependentCameras.end();
++itr)
{
(*itr)->releaseGLObjects(state);
}
if (_texture.valid()) _texture->releaseGLObjects(state);
if (_fbo.valid()) _fbo->releaseGLObjects(state);
if (_resolveFbo.valid()) _resolveFbo->releaseGLObjects(state);
if (_graphicsContext.valid()) _graphicsContext->releaseGLObjects(state);
}