diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index d0dffaf78..a09025e0b 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -168,22 +168,6 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl * note, should only be called from the draw thread.*/ void compileGLObjects(osg::State& state,double& availableTime); - /** Helper class used internally to force the release of texture objects - * and displace lists.*/ - class OSGDB_EXPORT ReleaseTexturesAndDrawablesVisitor : public osg::NodeVisitor - { - public: - ReleaseTexturesAndDrawablesVisitor(): - osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN) - { - } - - virtual void apply(osg::Node& node); - virtual void apply(osg::Geode& geode); - inline void apply(osg::StateSet* stateset); - inline void apply(osg::Drawable* drawable); - - }; public: @@ -219,6 +203,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl }; typedef std::vector< osg::ref_ptr > DatabaseRequestList; + typedef std::vector< osg::ref_ptr > ObjectList; protected : @@ -238,8 +223,9 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl DatabaseRequestList _dataToCompileList; OpenThreads::Mutex _dataToCompileListMutex; + bool _deleteRemovedSubgraphsInDatabaseThread; - osg::NodeList _childrenToDeleteList; + ObjectList _childrenToDeleteList; OpenThreads::Mutex _childrenToDeleteListMutex; DatabaseRequestList _dataToMergeList; diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index 8038dd755..bfc0b3028 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -27,7 +27,11 @@ DatabasePager::DatabasePager() _threadPriorityDuringFrame = PRIORITY_MIN; _threadPriorityOutwithFrame = PRIORITY_NOMINAL; - _deleteRemovedSubgraphsInDatabaseThread = false;//true; +#if 1 + _deleteRemovedSubgraphsInDatabaseThread = true; +#else + _deleteRemovedSubgraphsInDatabaseThread = false; +#endif _expiryDelay = 1.0; @@ -306,8 +310,9 @@ void DatabasePager::run() _childrenToDeleteListMutex.lock(); if (!_childrenToDeleteList.empty()) { - osg::notify(osg::INFO)<<"In DatabasePager thread deleting "<<_childrenToDeleteList.size()<<" subgraphs"<getTextureAttributeList(); - for(osg::StateSet::TextureAttributeList::iterator itr=tal.begin(); - itr!=tal.end() && !foundTextureState; - ++itr) + for(TextureSet::iterator titr=_textureSet.begin(); + titr!=_textureSet.end(); + ++titr) { - osg::StateSet::AttributeList& al = *itr; - osg::StateSet::AttributeList::iterator alitr = al.find(osg::StateAttribute::TEXTURE); - if (alitr!=al.end()) + if ((*titr)->referenceCount()==1) { - // found texture, so place it in the texture list. - osg::Texture* texture = static_cast(alitr->second.first.get()); + osg::Texture* texture = const_cast(titr->get()); texture->dirtyTextureObject(); + objectsToDelete.push_back(texture); + } + } + + for(DrawableSet::iterator ditr=_drawableSet.begin(); + ditr!=_drawableSet.end(); + ++ditr) + { + if ((*ditr)->referenceCount()==1) + { + osg::Drawable* drawable = const_cast(ditr->get()); + drawable->dirtyDisplayList(); + objectsToDelete.push_back(drawable); } } } -} -void DatabasePager::ReleaseTexturesAndDrawablesVisitor::apply(osg::Drawable* drawable) -{ - apply(drawable->getStateSet()); - - if (drawable->getUseDisplayList() || drawable->getUseVertexBufferObjects()) + inline void apply(osg::StateSet* stateset) { - drawable->dirtyDisplayList(); + if (stateset) + { + // search for the existance of any texture object attributes + bool foundTextureState = false; + osg::StateSet::TextureAttributeList& tal = stateset->getTextureAttributeList(); + for(osg::StateSet::TextureAttributeList::iterator itr=tal.begin(); + itr!=tal.end() && !foundTextureState; + ++itr) + { + osg::StateSet::AttributeList& al = *itr; + osg::StateSet::AttributeList::iterator alitr = al.find(osg::StateAttribute::TEXTURE); + if (alitr!=al.end()) + { + // found texture, so place it in the texture list. + osg::Texture* texture = static_cast(alitr->second.first.get()); + _textureSet.insert(texture); + } + + } + } } -} + + inline void apply(osg::Drawable* drawable) + { + apply(drawable->getStateSet()); + + _drawableSet.insert(drawable); + } + + virtual void apply(osg::Node& node) + { + apply(node.getStateSet()); + + traverse(node); + } + + virtual void apply(osg::Geode& geode) + { + apply(geode.getStateSet()); + + for(unsigned int i=0;i > DrawableSet; + typedef std::set< osg::ref_ptr > TextureSet; + + TextureSet _textureSet; + DrawableSet _drawableSet; + +}; void DatabasePager::removeExpiredSubgraphs(double currentFrameTime) { @@ -533,30 +581,14 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime) plod->removeExpiredChildren(expiryTime,childrenRemoved); } - for(unsigned int i=_pagedLODList.size(); - i>0; - ) - { - --i; - - osg::PagedLOD* plod = _pagedLODList[i].get(); - if (plod->referenceCount()==1) - { - //osg::notify(osg::INFO)<<" PagedLOD "<referenceCount()<getSharedStateManager()) osgDB::Registry::instance()->getSharedStateManager()->prune(); - + if (_deleteRemovedSubgraphsInDatabaseThread) { + // for all the subgraphs to remove find all the textures and drawables and // strip them from the display lists. ReleaseTexturesAndDrawablesVisitor rtadv; @@ -566,14 +598,41 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime) { (*nitr)->accept(rtadv); } + + // unref' the children we need to remove, keeping behind the Texture's and Drawables for later deletion + // inside the database thread. + childrenRemoved.clear(); // transfer the removed children over to the to delete list so the database thread can delete them. _childrenToDeleteListMutex.lock(); - _childrenToDeleteList.insert(_childrenToDeleteList.begin(),childrenRemoved.begin(),childrenRemoved.end()); + + rtadv.releaseGLObjects(_childrenToDeleteList); + _childrenToDeleteListMutex.unlock(); } - // otherwise the childrenRemoved list will automatically unref() and deleting the nodes. + // flush all the references from the child removed list. If _deleteRemovedSubgraphsInDatabaseThread + // is false then this will typically resulting in a delete, otherwise this will be left to the + // clean up of the _childrenToDeleteList from within the database paging thread. + childrenRemoved.clear(); + + for(unsigned int i=_pagedLODList.size(); + i>0; + ) + { + --i; + + osg::PagedLOD* plod = _pagedLODList[i].get(); + if (plod->referenceCount()==1) + { + _pagedLODList.erase(_pagedLODList.begin()+i); + } + else + { + //osg::notify(osg::INFO)<<" PagedLOD "<referenceCount()<updateTimeStampOfObjectsInCacheWithExtenalReferences(currentFrameTime); osgDB::Registry::instance()->removeExpiredObjectsInCache(expiryTime);