From 5aa47a77c24c8ca7d6dce37bcc97ceff22c425ab Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Wed, 9 Jul 2003 14:55:39 +0000 Subject: [PATCH] Improvements to the DatabasePager and PagedLOD class adding support for deleting expuired children in the database thread. --- include/osg/Group | 7 ++-- include/osg/PagedLOD | 5 ++- include/osgProducer/DatabasePager | 50 ++++++++++++++++++---- include/osgProducer/OsgSceneHandler | 2 +- src/osg/Group.cpp | 8 ++-- src/osg/PagedLOD.cpp | 3 +- src/osgProducer/DatabasePager.cpp | 64 ++++++++++++++++++++++------- src/osgProducer/OsgCameraGroup.cpp | 18 -------- src/osgProducer/Viewer.cpp | 33 +++++++++++++++ 9 files changed, 140 insertions(+), 50 deletions(-) diff --git a/include/osg/Group b/include/osg/Group index 10ff61cf8..9851f6390 100644 --- a/include/osg/Group +++ b/include/osg/Group @@ -19,6 +19,8 @@ namespace osg { +typedef std::vector< ref_ptr > NodeList; + /** General group node which maintains a list of children. Children are reference counted. This allows children to be shared with memory management handled automatically via osg::Referenced. @@ -27,7 +29,6 @@ class SG_EXPORT Group : public Node { public : - typedef std::vector > ChildList; Group(); @@ -89,7 +90,7 @@ class SG_EXPORT Group : public Node inline bool containsNode( const Node* node ) const { - for (ChildList::const_iterator itr=_children.begin(); + for (NodeList::const_iterator itr=_children.begin(); itr!=_children.end(); ++itr) { @@ -116,7 +117,7 @@ class SG_EXPORT Group : public Node virtual bool computeBound() const; - ChildList _children; + NodeList _children; }; diff --git a/include/osg/PagedLOD b/include/osg/PagedLOD index 6f5022265..f6318787e 100644 --- a/include/osg/PagedLOD +++ b/include/osg/PagedLOD @@ -74,7 +74,10 @@ class SG_EXPORT PagedLOD : public LOD /** return the list of time stamps.*/ inline const TimeStampList& getTimeStampList() const { return _timeStampList; } - void removeExpiredChildren(double expiryTime); + /** Remove the children from the PagedLOD which haven't be visited since specified expiry time. + The removed children are added the removeChildren list passed into the method, + this allows the children to be deleted later at the callers discression.*/ + void removeExpiredChildren(double expiryTime,NodeList& removedChildren); protected : diff --git a/include/osgProducer/DatabasePager b/include/osgProducer/DatabasePager index 03c35c1d6..eec0a194a 100644 --- a/include/osgProducer/DatabasePager +++ b/include/osgProducer/DatabasePager @@ -33,19 +33,23 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques DatabasePager(); - /** add a request to load a node file to end the the database request list.*/ + /** Add a request to load a node file to end the the database request list.*/ virtual void requestNodeFile(const std::string& fileName,osg::Group* group); /** run does the database paging.*/ virtual void run(); - /** add the loaded data to the scene graph.*/ + + /** Add the loaded data to the scene graph.*/ void addLoadedDataToSceneGraph(); - /** find all PagedLOD nodes in a subgraph and register them with - * the DatabasePager so it can keep track of expired nodes.*/ + + /** Find all PagedLOD nodes in a subgraph and register them with + * the DatabasePager so it can keep track of expired nodes. + * note, should be only be called from the update thread. */ void registerPagedLODs(osg::Node* subgraph); + /** Set the amount of time that a subgraph will be kept without being visited in the cull traversal * before being removed.*/ void setExpiryDelay(double expiryDelay) { _expiryDelay = expiryDelay; } @@ -54,10 +58,27 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques * before being removed.*/ double getExpiryDelay() const { return _expiryDelay; } - /** iterate through the active PagedLOD nodes children removing - * children which havn't been visited since specified expiryTime.*/ + /** set whether the removed subgraphs should be deleted in the database thread or not.*/ + void setDeleteRemovedSubgraphsInDatabaseThread(bool flag) { _deleteRemovedSubgraphsInDatabaseThread = flag; } + + /** get whether the removed subgraphs should be deleted in the database thread or not.*/ + bool getDeleteRemovedSubgraphsInDatabaseThread() const { return _deleteRemovedSubgraphsInDatabaseThread; } + + /** Iterate through the active PagedLOD nodes children removing + * children which havn't been visited since specified expiryTime. + * note, should be only be called from the update thread. */ void removeExpiredSubgraphs(double currentFrameTime); + + /* Set the maximum amount of time available for compile rendering objects. */ + void setMaximumTimeForCompilingRenderingObjects(double time) { _maximumTimeForCompiling = time; } + + /* Get the maximum amount of time available for compile rendering objects. */ + double getMaximumTimeForCompilingRenderingObjects() const { return _maximumTimeForCompiling; } + + /** Compile the rendering objects (display lists,texture objects, VBO's) on loaded subgraph. + * note, should only be called from the draw thread.*/ + void compileRenderingObjects(osg::State& state); public: @@ -66,6 +87,9 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques protected : virtual ~DatabasePager() {} + + typedef std::vector< osg::ref_ptr > StateSetList; + typedef std::vector< osg::ref_ptr > DrawableList; struct DatabaseRequest : public osg::Referenced { @@ -84,13 +108,23 @@ class OSGPRODUCER_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseReques DatabaseRequestList _fileRequestList; Producer::Mutex _fileRequestListMutex; - DatabaseRequestList _fileLoadedList; - Producer::Mutex _fileLoadedListMutex; + DatabaseRequestList _dataLoadedList; + Producer::Mutex _dataLoadedListMutex; + + bool _deleteRemovedSubgraphsInDatabaseThread; + osg::NodeList _childrenToDeleteList; + Producer::Mutex _childrenToDeleteListMutex; + + DatabaseRequestList _dataToMergeList; + Producer::Mutex _dataToMergeMutex; + PagedLODList _pagedLODList; double _expiryDelay; + double _maximumTimeForCompiling; + }; } diff --git a/include/osgProducer/OsgSceneHandler b/include/osgProducer/OsgSceneHandler index 4d437462a..63e9c0b2f 100644 --- a/include/osgProducer/OsgSceneHandler +++ b/include/osgProducer/OsgSceneHandler @@ -45,7 +45,7 @@ class OSGPRODUCER_EXPORT OsgSceneHandler : public Producer::Camera::SceneHandler { public: virtual ~Callback() {} - virtual void operator()(OsgSceneHandler&, const Producer::Camera &) = 0; + virtual void operator()(OsgSceneHandler&, Producer::Camera &) = 0; }; virtual void clear(Producer::Camera& camera) diff --git a/src/osg/Group.cpp b/src/osg/Group.cpp index 85ebe672d..5305ca106 100644 --- a/src/osg/Group.cpp +++ b/src/osg/Group.cpp @@ -31,7 +31,7 @@ Group::Group() Group::Group(const Group& group,const CopyOp& copyop): Node(group,copyop) { - for(ChildList::const_iterator itr=group._children.begin(); + for(NodeList::const_iterator itr=group._children.begin(); itr!=group._children.end(); ++itr) { @@ -43,7 +43,7 @@ Group::Group(const Group& group,const CopyOp& copyop): Group::~Group() { // remove reference to this from children's parent lists. - for(ChildList::iterator itr=_children.begin(); + for(NodeList::iterator itr=_children.begin(); itr!=_children.end(); ++itr) { @@ -55,7 +55,7 @@ Group::~Group() void Group::traverse(NodeVisitor& nv) { - for(ChildList::iterator itr=_children.begin(); + for(NodeList::iterator itr=_children.begin(); itr!=_children.end(); ++itr) { @@ -298,7 +298,7 @@ bool Group::computeBound() const BoundingBox bb; bb.init(); - ChildList::const_iterator itr; + NodeList::const_iterator itr; for(itr=_children.begin(); itr!=_children.end(); ++itr) diff --git a/src/osg/PagedLOD.cpp b/src/osg/PagedLOD.cpp index eb8beb24b..4219536d6 100644 --- a/src/osg/PagedLOD.cpp +++ b/src/osg/PagedLOD.cpp @@ -129,7 +129,7 @@ void PagedLOD::setTimeStamp(unsigned int childNo, double timeStamp) _timeStampList[childNo] = timeStamp; } -void PagedLOD::removeExpiredChildren(double expiryTime) +void PagedLOD::removeExpiredChildren(double expiryTime,NodeList& removedChildren) { for(unsigned int i=_children.size();i>0;) { @@ -137,6 +137,7 @@ void PagedLOD::removeExpiredChildren(double expiryTime) if (!_fileNameList[i].empty() && _timeStampList[i]_fileName==fileName) @@ -32,7 +37,7 @@ void DatabasePager::requestNodeFile(const std::string& fileName,osg::Group* grou } } - _fileLoadedListMutex.unlock(); + _dataLoadedListMutex.unlock(); if (!foundEntry) { @@ -78,6 +83,23 @@ void DatabasePager::run() while(true) { + // + // delete any children if required. + // + if (_deleteRemovedSubgraphsInDatabaseThread) + { + _childrenToDeleteListMutex.lock(); + if (!_childrenToDeleteList.empty()) + { + std::cout<<"In DatabasePager thread deleting "<<_childrenToDeleteList.size()<<" subgraphs"< databaseRequest; // get the front of the file request list. @@ -97,11 +119,11 @@ void DatabasePager::run() if (databaseRequest->_loadedModel.valid()) { - _fileLoadedListMutex.lock(); + _dataLoadedListMutex.lock(); - _fileLoadedList.push_back(databaseRequest); + _dataLoadedList.push_back(databaseRequest); - _fileLoadedListMutex.unlock(); + _dataLoadedListMutex.unlock(); } } @@ -121,10 +143,10 @@ void DatabasePager::addLoadedDataToSceneGraph() { DatabaseRequestList localFileLoadedList; - // get the dat for the _fileLoadedList, leaving it empty via a std::vector<>.swap. - _fileLoadedListMutex.lock(); - localFileLoadedList.swap(_fileLoadedList); - _fileLoadedListMutex.unlock(); + // get the dat for the _dataLoadedList, leaving it empty via a std::vector<>.swap. + _dataLoadedListMutex.lock(); + localFileLoadedList.swap(_dataLoadedList); + _dataLoadedListMutex.unlock(); // add the loaded data into the scene graph. for(DatabaseRequestList::iterator itr=localFileLoadedList.begin(); @@ -144,13 +166,15 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime) { double expiryTime = currentFrameTime - _expiryDelay; + osg::NodeList childrenRemoved; + //std::cout<<"DatabasePager::removeExpiredSubgraphs("<get(); - plod->removeExpiredChildren(expiryTime); + plod->removeExpiredChildren(expiryTime,childrenRemoved); } for(unsigned int i=_pagedLODList.size(); @@ -171,7 +195,14 @@ void DatabasePager::removeExpiredSubgraphs(double currentFrameTime) } } - + if (_deleteRemovedSubgraphsInDatabaseThread) + { + // 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()); + _childrenToDeleteListMutex.unlock(); + } + // otherwise the childrenRemoved list will automatically unref() and deleting the nodes. } @@ -200,3 +231,8 @@ void DatabasePager::registerPagedLODs(osg::Node* subgraph) if (subgraph) subgraph->accept(fplv); } +void DatabasePager::compileRenderingObjects(osg::State& state) +{ +// std::cout<<"Compiling rendering objects"<registerPagedLODs(getTopMostSceneData()); - - for(SceneHandlerList::iterator p=_shvec.begin(); - p!=_shvec.end(); - ++p) - { - (*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); - } - - } - } diff --git a/src/osgProducer/Viewer.cpp b/src/osgProducer/Viewer.cpp index 20bd68357..2c7a35264 100644 --- a/src/osgProducer/Viewer.cpp +++ b/src/osgProducer/Viewer.cpp @@ -296,11 +296,44 @@ bool Viewer::realize( ThreadingModel thread_model ) return realize(); } +class DatabasePagerCompileCallback : public OsgSceneHandler::Callback +{ +public: + + DatabasePagerCompileCallback(DatabasePager* databasePager): + _databasePager(databasePager) + {} + + virtual void operator()(OsgSceneHandler& sh, Producer::Camera& camera) + { + _databasePager->compileRenderingObjects(*(sh.getSceneView()->getState())); + + sh.drawImplementation(camera); + } + + osg::ref_ptr _databasePager; +}; + bool Viewer::realize() { if (_realized) return _realized; OsgCameraGroup::realize(); + + + // by default set up the DatabasePager. + { + _databasePager = new DatabasePager; + _databasePager->registerPagedLODs(getTopMostSceneData()); + + for(SceneHandlerList::iterator p=_shvec.begin(); + p!=_shvec.end(); + ++p) + { + (*p)->getSceneView()->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); + (*p)->setDrawCallback(new DatabasePagerCompileCallback(_databasePager.get())); + } + } // force a sync before we intialize the keyswitch manipulator to home // so that Producer has a chance to set up the windows before we do