From d1fa5203494854d5621958e21e73083e176788a4 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 5 Jul 2007 18:33:20 +0000 Subject: [PATCH] Added support for managing a CompileContext. Rearranged the DeleteHandler::flushAll call. --- applications/osgviewer/osgviewer.cpp | 39 +----- include/osg/DeleteHandler | 2 +- include/osg/GraphicsContext | 27 ++++ src/osg/DeleteHandler.cpp | 36 +++++- src/osg/GraphicsContext.cpp | 186 +++++++++++++++++++++++++-- src/osg/View.cpp | 12 ++ src/osgViewer/GraphicsWindowX11.cpp | 2 +- src/osgViewer/Viewer.cpp | 7 +- 8 files changed, 255 insertions(+), 56 deletions(-) diff --git a/applications/osgviewer/osgviewer.cpp b/applications/osgviewer/osgviewer.cpp index 8021009d6..61a4583de 100644 --- a/applications/osgviewer/osgviewer.cpp +++ b/applications/osgviewer/osgviewer.cpp @@ -150,7 +150,7 @@ int main(int argc, char** argv) viewer.setSceneData( loadedModel.get() ); viewer.realize(); - + if (createBackgroundContextForCompiling) { @@ -158,37 +158,12 @@ int main(int argc, char** argv) int processNum = 0; osgDB::DatabasePager* dp = viewer.getScene()->getDatabasePager(); - typedef std::vector< osg::ref_ptr > CompileContexts; - CompileContexts compileContexts; - osgViewer::Viewer::Windows windows; - viewer.getWindows(windows); - for(osgViewer::Viewer::Windows::iterator itr = windows.begin(); - itr != windows.end(); - ++itr) + for(unsigned int i=0; igetTraits(); + osg::GraphicsContext* gc = osg::GraphicsContext::getOrCreateCompileContext(i); - osg::GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits; - traits->screenNum = src_traits->screenNum; - traits->displayNum = src_traits->displayNum; - traits->hostName = src_traits->hostName; - traits->width = 100; - traits->height = 100; - traits->red = src_traits->red; - traits->green = src_traits->green; - traits->blue = src_traits->blue; - traits->alpha = src_traits->alpha; - traits->depth = src_traits->depth; - traits->sharedContext = (*itr); - traits->pbuffer = true; - - osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits); - - gc->realize(); - - - if (createBackgroundThreadsForCompiling) + if (gc && createBackgroundThreadsForCompiling) { gc->createGraphicsThread(); gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); @@ -198,11 +173,9 @@ int main(int argc, char** argv) } dp->addCompileGraphicsContext(gc); - - compileContexts.push_back(gc); } } - - return viewer.run(); + viewer.run(); + } diff --git a/include/osg/DeleteHandler b/include/osg/DeleteHandler index fee52b475..ea728d537 100644 --- a/include/osg/DeleteHandler +++ b/include/osg/DeleteHandler @@ -37,7 +37,7 @@ class OSG_EXPORT DeleteHandler DeleteHandler(int numberOfFramesToRetainObjects=0); - virtual ~DeleteHandler() { flushAll(); } + virtual ~DeleteHandler(); /** Set the number of frames to retain objects that are have been requested for deletion. * When set to zero objects are deleted immediately, by set to 1 there are kept around for an extra frame etc. diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index 4312c079b..b05f1656d 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -165,12 +165,32 @@ class OSG_EXPORT GraphicsContext : public Object * Automatically increments the usage count of the contextID to 1.*/ static unsigned int createNewContextID(); + /** Get the current max ContextID.*/ + static unsigned int getMaxContextID(); + /** Increment the usage count associate with a contextID. The usage count speficies how many graphics contexts a specific contextID is shared between.*/ static void incrementContextIDUsageCount(unsigned int contextID); /** Decrement the usage count associate with a contextID. Once the contextID goes to 0 the contextID is then free to be reused.*/ static void decrementContextIDUsageCount(unsigned int contextID); + typedef std::vector GraphicsContexts; + + /** Get all the registered graphics contexts.*/ + static GraphicsContexts getAllRegisteredGraphicsContexts(); + + /** Get all the registered graphics contexts associated with a specific contextID.*/ + static GraphicsContexts getRegisteredGraphicsContexts(unsigned int contextID); + + /** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/ + static void setCompileContext(unsigned int contextID, GraphicsContext* gc); + + /** Get existing or create a new GraphicsContext to do background compilation for GraphicsContexts associated with specified contextID.*/ + static GraphicsContext* getOrCreateCompileContext(unsigned int contextID); + + /** Get the GraphicsContext for doing background compilation for GraphicsContexts associated with specified contextID.*/ + static GraphicsContext* getCompileContext(unsigned int contextID); + public: /** Add operation to end of OperationQueue.*/ @@ -376,6 +396,13 @@ class OSG_EXPORT GraphicsContext : public Object virtual Object* cloneType() const { return 0; } virtual Object* clone(const CopyOp&) const { return 0; } + /** Register a GraphicsContext.*/ + static void registerGraphicsContext(GraphicsContext* gc); + + /** Unregister a GraphicsContext.*/ + static void unregisterGraphicsContext(GraphicsContext* gc); + + void addCamera(osg::Camera* camera); void removeCamera(osg::Camera* camera); diff --git a/src/osg/DeleteHandler.cpp b/src/osg/DeleteHandler.cpp index f0df4f036..4ac262b2d 100644 --- a/src/osg/DeleteHandler.cpp +++ b/src/osg/DeleteHandler.cpp @@ -67,6 +67,11 @@ DeleteHandler::DeleteHandler(int numberOfFramesToRetainObjects): { } +DeleteHandler::~DeleteHandler() +{ + // flushAll(); +} + void DeleteHandler::flush() { typedef std::list DeletionList; @@ -105,12 +110,37 @@ void DeleteHandler::flush() void DeleteHandler::flushAll() { - int temp = _numFramesToRetainObjects; + int temp_numFramesToRetainObjects = _numFramesToRetainObjects; _numFramesToRetainObjects = 0; - flush(); + typedef std::list DeletionList; + DeletionList deletionList; - _numFramesToRetainObjects = temp; + { + // gather all the objects to delete whilst holding the mutex to the _objectsToDelete + // list, but delete the objects outside this scoped lock so that if any objects deleted + // unref their children then no deadlock happens. + OpenThreads::ScopedLock lock(_mutex); + ObjectsToDeleteList::iterator itr; + for(itr = _objectsToDelete.begin(); + itr != _objectsToDelete.end(); + ++itr) + { + deletionList.push_back(itr->second); + itr->second = 0; + } + + _objectsToDelete.erase( _objectsToDelete.begin(), _objectsToDelete.end()); + } + + for(DeletionList::iterator ditr = deletionList.begin(); + ditr != deletionList.end(); + ++ditr) + { + doDelete(*ditr); + } + + _numFramesToRetainObjects = temp_numFramesToRetainObjects; } void DeleteHandler::requestDelete(const osg::Referenced* object) diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index be39a602e..135b50f3e 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -22,6 +22,8 @@ #include #include +#include + #include #include @@ -29,6 +31,11 @@ using namespace osg; +///////////////////////////////////////////////////////////////////////////// +// +// GraphicsContext static method implementations +// + static ref_ptr s_WindowingSystemInterface; void GraphicsContext::setWindowingSystemInterface(WindowingSystemInterface* callback) @@ -60,9 +67,41 @@ std::string GraphicsContext::ScreenIdentifier::displayName() const } -typedef std::map ContextIDMap; +class ContextData +{ +public: + + ContextData(): + _numContexts(0) {} + + unsigned int _numContexts; + + void incrementUsageCount() { ++_numContexts; } + + void decrementUsageCount() + { + --_numContexts; + + osg::notify(osg::INFO)<<"decrementUsageCount()"<<_numContexts<referenceCount()< _compileContext; + +}; + + +typedef std::map ContextIDMap; static ContextIDMap s_contextIDMap; -static OpenThreads::Mutex s_contextIDMapMutex; +static OpenThreads::ReentrantMutex s_contextIDMapMutex; +static GraphicsContext::GraphicsContexts s_registeredContexts; unsigned int GraphicsContext::createNewContextID() { @@ -73,11 +112,11 @@ unsigned int GraphicsContext::createNewContextID() itr != s_contextIDMap.end(); ++itr) { - if (itr->second == 0) + if (itr->second._numContexts == 0) { // reuse contextID; - itr->second = 1; + itr->second._numContexts = 1; osg::notify(osg::INFO)<<"GraphicsContext::createNewContextID() reusing contextID="<first< lock(s_contextIDMapMutex); - - if (s_contextIDMap[contextID]!=0) + if (s_contextIDMap[contextID]._numContexts!=0) { - --s_contextIDMap[contextID]; + s_contextIDMap[contextID].decrementUsageCount(); } else { osg::notify(osg::NOTICE)<<"Warning: decrementContextIDUsageCount("< lock(s_contextIDMapMutex); + + GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc); + if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr); + + s_registeredContexts.push_back(gc); +} + +void GraphicsContext::unregisterGraphicsContext(GraphicsContext* gc) +{ + osg::notify(osg::INFO)<<"GraphicsContext::unregisterGraphicsContext "< lock(s_contextIDMapMutex); + + GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc); + if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr); +} + +GraphicsContext::GraphicsContexts GraphicsContext::getAllRegisteredGraphicsContexts() +{ + osg::notify(osg::INFO)<<"GraphicsContext::getAllRegisteredGraphicsContexts s_registeredContexts.size()="< lock(s_contextIDMapMutex); + return s_registeredContexts; +} + +GraphicsContext::GraphicsContexts GraphicsContext::getRegisteredGraphicsContexts(unsigned int contextID) +{ + GraphicsContexts contexts; + + OpenThreads::ScopedLock lock(s_contextIDMapMutex); + for(GraphicsContexts::iterator itr = s_registeredContexts.begin(); + itr != s_registeredContexts.end(); + ++itr) + { + GraphicsContext* gc = *itr; + if (gc->getState() && gc->getState()->getContextID()==contextID) contexts.push_back(gc); + } + + osg::notify(osg::INFO)<<"GraphicsContext::getRegisteredGraphicsContexts "< lock(s_contextIDMapMutex); + if (s_contextIDMap[contextID]._compileContext.valid()) return s_contextIDMap[contextID]._compileContext.get(); + } + + GraphicsContext::GraphicsContexts contexts = GraphicsContext::getRegisteredGraphicsContexts(contextID); + if (contexts.empty()) return 0; + + GraphicsContext* src_gc = contexts.front(); + const osg::GraphicsContext::Traits* src_traits = src_gc->getTraits(); + + osg::GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits; + traits->screenNum = src_traits->screenNum; + traits->displayNum = src_traits->displayNum; + traits->hostName = src_traits->hostName; + traits->width = 100; + traits->height = 100; + traits->red = src_traits->red; + traits->green = src_traits->green; + traits->blue = src_traits->blue; + traits->alpha = src_traits->alpha; + traits->depth = src_traits->depth; + traits->sharedContext = src_gc; + traits->pbuffer = true; + + osg::GraphicsContext* gc = osg::GraphicsContext::createGraphicsContext(traits); + gc->realize(); + + { + OpenThreads::ScopedLock lock(s_contextIDMapMutex); + s_contextIDMap[contextID]._compileContext = gc; + } + + osg::notify(osg::INFO)<<" succeded GraphicsContext::createCompileContext."< lock(s_contextIDMapMutex); + s_contextIDMap[contextID]._compileContext = gc; +} + +GraphicsContext* GraphicsContext::getCompileContext(unsigned int contextID) +{ + osg::notify(osg::NOTICE)<<"GraphicsContext::getCompileContext "< lock(s_contextIDMapMutex); + return s_contextIDMap[contextID]._compileContext.get(); +} + + +///////////////////////////////////////////////////////////////////////////// +// +// GraphicsContext standard method implementations +// GraphicsContext::GraphicsContext(): _clearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)), _clearMask(0), @@ -140,6 +296,8 @@ GraphicsContext::GraphicsContext(): { setThreadSafeRefUnref(true); _operationsBlock = new RefBlock; + + registerGraphicsContext(this); } GraphicsContext::GraphicsContext(const GraphicsContext&, const osg::CopyOp&): @@ -149,11 +307,15 @@ GraphicsContext::GraphicsContext(const GraphicsContext&, const osg::CopyOp&): { setThreadSafeRefUnref(true); _operationsBlock = new RefBlock; + + registerGraphicsContext(this); } GraphicsContext::~GraphicsContext() { close(false); + + unregisterGraphicsContext(this); } void GraphicsContext::clear() @@ -193,7 +355,7 @@ void GraphicsContext::close(bool callCloseImplementation) if (_state.valid()) { OpenThreads::ScopedLock lock(s_contextIDMapMutex); - if (s_contextIDMap[_state->getContextID()]>1) sharedContextExists = true; + if (s_contextIDMap[_state->getContextID()]._numContexts>1) sharedContextExists = true; } // release all the OpenGL objects in the scene graphs associted with this diff --git a/src/osg/View.cpp b/src/osg/View.cpp index 80fde1937..913b79ae5 100644 --- a/src/osg/View.cpp +++ b/src/osg/View.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace osg; @@ -72,6 +73,17 @@ View::~View() cd._camera->setCullCallback(0); } + _camera = 0; + _slaves.clear(); + _light = 0; + + if (osg::Referenced::getDeleteHandler()) + { + // osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); + osg::Referenced::getDeleteHandler()->flushAll(); + } + + osg::notify(osg::INFO)<<"Done destructing osg::View"<close(); } - - if (osg::Referenced::getDeleteHandler()) - { - osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0); - osg::Referenced::getDeleteHandler()->flushAll(); - } + //osg::notify(osg::NOTICE)<<"finish Viewer::~Viewer()"<