From caeed02f524ffbc89e0a4cdb844245c87de399cd Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 2 Oct 2007 21:23:58 +0000 Subject: [PATCH] Merged the threading set up and rendering code from Viewer and CompositeViewer into ViewerBase to allow CompositeViewer to inherit the same theading models previously just supported by osgViewer::Viewer --- include/osgViewer/CompositeViewer | 54 +-- include/osgViewer/Viewer | 73 +-- include/osgViewer/ViewerBase | 99 +++- src/osgViewer/CompositeViewer.cpp | 352 +------------- src/osgViewer/Viewer.cpp | 775 +++--------------------------- src/osgViewer/ViewerBase.cpp | 647 ++++++++++++++++++++++++- 6 files changed, 820 insertions(+), 1180 deletions(-) diff --git a/include/osgViewer/CompositeViewer b/include/osgViewer/CompositeViewer index 5f5d00ddc..a2532c673 100644 --- a/include/osgViewer/CompositeViewer +++ b/include/osgViewer/CompositeViewer @@ -61,33 +61,15 @@ class OSGVIEWER_EXPORT CompositeViewer : public ViewerBase, public virtual osg:: osg::FrameStamp* getFrameStamp() { return _frameStamp.get(); } const osg::FrameStamp* getFrameStamp() const { return _frameStamp.get(); } - /** Set the threading model the rendering traversals will use.*/ - virtual void setThreadingModel(ThreadingModel threadingModel); + virtual double elapsedTime(); + + virtual osg::FrameStamp* getViewerFrameStamp() { return getFrameStamp(); } + void setEventQueue(osgGA::EventQueue* eventQueue) { _eventQueue = eventQueue; } osgGA::EventQueue* getEventQueue() { return _eventQueue.get(); } const osgGA::EventQueue* getEventQueue() const { return _eventQueue.get(); } - - enum BarrierPosition - { - BeforeSwapBuffers, - AfterSwapBuffers - }; - - /** Set the position of the end barrier. - * AfterSwapBuffers will may result is slightly higher framerates, by may - * lead to inconcistent swapping between different windows. - * BeforeSwapBuffers may lead to slightly lower framerate, but improve consistency in timing of swap buffers, - * especially important if you are likely to consistently break frame.*/ - void setEndBarrierPosition(BarrierPosition bp); - - /** Get the end barrier position.*/ - BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; } - - - - /** Execute a main frame loop. * Equivialant to while (!viewer.done()) viewer.frame(); * Also calls realize() if the viewer is not already realized, @@ -95,18 +77,12 @@ class OSGVIEWER_EXPORT CompositeViewer : public ViewerBase, public virtual osg:: */ virtual int run(); - /** Render a complete new frame. - * Calls advance(), eventTraversal(), updateTraversal(), renderingTraversals(). */ - virtual void frame(double simulationTime=USE_REFERENCE_TIME); - virtual void advance(double simulationTime=USE_REFERENCE_TIME); virtual void eventTraversal(); virtual void updateTraversal(); - virtual void renderingTraversals(); - void setCameraWithFocus(osg::Camera* camera); osg::Camera* getCameraWithFocus() { return _cameraWithFocus.get(); } @@ -130,15 +106,6 @@ class OSGVIEWER_EXPORT CompositeViewer : public ViewerBase, public virtual osg:: virtual void getViews(Views& views, bool onlyValid=true); - /** Set up the threading and processor affinity as per the viewers threading model.*/ - virtual void setUpThreading(); - - /** Stop any threads begin run by viewer.*/ - virtual void stopThreading(); - - /** Start any threads required by the viewer, as per viewers ThreadingModel.*/ - virtual void startThreading(); - /** Get the keyboard and mouse usage of this viewer.*/ virtual void getUsage(osg::ApplicationUsage& usage) const; @@ -146,24 +113,13 @@ class OSGVIEWER_EXPORT CompositeViewer : public ViewerBase, public virtual osg:: void constructorInit(); - void init(); - - void checkWindowStatus(); + virtual void viewerInit(); typedef std::vector< osg::ref_ptr > RefViews; RefViews _views; bool _firstFrame; - BarrierPosition _endBarrierPosition; - - osg::ref_ptr _startRenderingBarrier; - osg::ref_ptr _endRenderingDispatchBarrier; - - unsigned int computeNumberOfThreadsIncludingMainRequired(); - - unsigned int _numThreadsOnBarrier; - osg::Timer_t _startTick; osg::ref_ptr _frameStamp; diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index 3e29985c3..ea785d800 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -61,28 +61,10 @@ class OSGVIEWER_EXPORT Viewer : public ViewerBase, public osgViewer::View * Returns the GraphicsWindowEmbedded that can be used by applications to pass in events to the viewer. */ virtual GraphicsWindowEmbedded* setUpViewerAsEmbeddedInWindow(int x, int y, int width, int height); - /** Set the threading model the rendering traversals will use.*/ - virtual void setThreadingModel(ThreadingModel threadingModel); + + virtual double elapsedTime(); - - /** Let the viewer suggest the best threading model for the viewers camera/window setup and the hardware available.*/ - ThreadingModel suggestBestThreadingModel(); - - enum BarrierPosition - { - BeforeSwapBuffers, - AfterSwapBuffers - }; - - /** Set the position of the end barrier. - * AfterSwapBuffers will may result is slightly higher framerates, by may - * lead to inconcistent swapping between different windows. - * BeforeSwapBuffers may lead to slightly lower framerate, but improve consistency in timing of swap buffers, - * especially important if you are likely to consistently break frame.*/ - void setEndBarrierPosition(BarrierPosition bp); - - /** Get the end barrier position.*/ - BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; } + virtual osg::FrameStamp* getViewerFrameStamp() { return getFrameStamp(); } /** Execute a main frame loop. @@ -92,18 +74,12 @@ class OSGVIEWER_EXPORT Viewer : public ViewerBase, public osgViewer::View */ virtual int run(); - /** Render a complete new frame. - * Calls advance(), eventTraversal(), updateTraversal(), renderingTraversals(). */ - virtual void frame(double simulationTime=USE_REFERENCE_TIME); - virtual void advance(double simulationTime=USE_REFERENCE_TIME); virtual void eventTraversal(); virtual void updateTraversal(); - virtual void renderingTraversals(); - void setCameraWithFocus(osg::Camera* camera) { _cameraWithFocus = camera; } osg::Camera* getCameraWithFocus() { return _cameraWithFocus.get(); } const osg::Camera* getCameraWithFocus() const { return _cameraWithFocus.get(); } @@ -122,60 +98,19 @@ class OSGVIEWER_EXPORT Viewer : public ViewerBase, public osgViewer::View virtual void getViews(Views& views, bool onlyValid=true); - - /** Set up the threading and processor affinity as per the viewers threading model.*/ - virtual void setUpThreading(); - - /** Stop any threads begin run by viewer.*/ - virtual void stopThreading(); - - /** Start any threads required by the viewer.*/ - virtual void startThreading(); - /** Get the keyboard and mouse usage of this viewer.*/ virtual void getUsage(osg::ApplicationUsage& usage) const; - protected: void constructorInit(); - - void checkWindowStatus(); - inline void makeCurrent(osg::GraphicsContext* gc) - { - if (_currentContext==gc) return; - - releaseContext(); - - if (gc && gc->valid() && gc->makeCurrent()) _currentContext = gc; - } - - inline void releaseContext() - { - if (_currentContext.valid() && _currentContext->valid()) - { - _currentContext->releaseContext(); - } - _currentContext = 0; - } - - - bool _firstFrame; - - BarrierPosition _endBarrierPosition; + virtual void viewerInit() { init(); } - osg::ref_ptr _startRenderingBarrier; - osg::ref_ptr _endRenderingDispatchBarrier; - osg::ref_ptr _endDynamicDrawBlock; - - unsigned int _numWindowsOpenAtLastSetUpThreading; - osg::observer_ptr _cameraWithFocus; - osg::observer_ptr _currentContext; }; diff --git a/include/osgViewer/ViewerBase b/include/osgViewer/ViewerBase index 9fab60897..8684f6bbe 100644 --- a/include/osgViewer/ViewerBase +++ b/include/osgViewer/ViewerBase @@ -71,11 +71,43 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object }; /** Set the threading model the rendering traversals will use.*/ - virtual void setThreadingModel(ThreadingModel threadingModel) = 0; + virtual void setThreadingModel(ThreadingModel threadingModel); /** Get the threading model the rendering traversals will use.*/ ThreadingModel getThreadingModel() const { return _threadingModel; } + + /** Let the viewer suggest the best threading model for the viewers camera/window setup and the hardware available.*/ + virtual ThreadingModel suggestBestThreadingModel(); + + /** Set up the threading and processor affinity as per the viewers threading model.*/ + virtual void setUpThreading(); + + /** Return true if viewer threads are running. */ + bool areThreadsRunning() const { return _threadsRunning; } + + /** Stop any threads begin run by viewer.*/ + virtual void stopThreading(); + + /** Start any threads required by the viewer.*/ + virtual void startThreading(); + + enum BarrierPosition + { + BeforeSwapBuffers, + AfterSwapBuffers + }; + /** Set the position of the end barrier. + * AfterSwapBuffers will may result is slightly higher framerates, by may + * lead to inconcistent swapping between different windows. + * BeforeSwapBuffers may lead to slightly lower framerate, but improve consistency in timing of swap buffers, + * especially important if you are likely to consistently break frame.*/ + void setEndBarrierPosition(BarrierPosition bp); + + /** Get the end barrier position.*/ + BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; } + + /** Set the done flag to singnal the viewer's work is done and should exit the frame loop.*/ void setDone(bool done) { _done = done; } @@ -135,6 +167,18 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object void removeUpdateOperation(osg::Operation* operation); + /** Set the graphics operation to call on realization of the viewers graphics windows.*/ + void setRealizeOperation(osg::Operation* op) { _realizeOperation = op; } + + /** Get the graphics operation to call on realization of the viewers graphics windows.*/ + osg::Operation* getRealizeOperation() { return _realizeOperation.get(); } + + + /** Check to see if windows are still open, if not set viewer done to true. */ + void checkWindowStatus(); + + + /** Execute a main frame loop. * Equivialant to while (!viewer.done()) viewer.frame(); * Also calls realize() if the viewer is not already realized, @@ -144,7 +188,7 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object /** Render a complete new frame. * Calls advance(), eventTraversal(), updateTraversal(), renderingTraversals(). */ - virtual void frame(double simulationTime=USE_REFERENCE_TIME) = 0; + virtual void frame(double simulationTime=USE_REFERENCE_TIME); virtual void advance(double simulationTime=USE_REFERENCE_TIME) = 0; @@ -152,7 +196,7 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object virtual void updateTraversal() = 0; - virtual void renderingTraversals() = 0; + virtual void renderingTraversals(); typedef std::vector Cameras; virtual void getCameras(Cameras& cameras, bool onlyActive=true) = 0; @@ -175,38 +219,51 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object typedef std::vector Views; virtual void getViews(Views& views, bool onlyValid=true) = 0; + virtual double elapsedTime() = 0; - /** Set the graphics operation to call on realization of the viewers graphics windows.*/ - void setRealizeOperation(osg::Operation* op) { _realizeOperation = op; } - - /** Get the graphics operation to call on realization of the viewers graphics windows.*/ - osg::Operation* getRealizeOperation() { return _realizeOperation.get(); } - - /** Set up the threading and processor affinity as per the viewers threading model.*/ - virtual void setUpThreading() = 0; - - /** Return true if viewer threads are running. */ - bool areThreadsRunning() const { return _threadsRunning; } - - /** Stop any threads begin run by viewer.*/ - virtual void stopThreading() = 0; - - /** Start any threads required by the viewer.*/ - virtual void startThreading() = 0; + virtual osg::FrameStamp* getViewerFrameStamp() = 0; /** Get the keyboard and mouse usage of this viewer.*/ virtual void getUsage(osg::ApplicationUsage& usage) const = 0; protected: + inline void makeCurrent(osg::GraphicsContext* gc) + { + if (_currentContext==gc) return; + + releaseContext(); + + if (gc && gc->valid() && gc->makeCurrent()) _currentContext = gc; + } + + inline void releaseContext() + { + if (_currentContext.valid() && _currentContext->valid()) + { + _currentContext->releaseContext(); + } + _currentContext = 0; + } + + virtual void viewerInit() = 0; + + osg::ref_ptr _stats; + bool _firstFrame; bool _done; int _keyEventSetsDone; bool _quitEventSetsDone; ThreadingModel _threadingModel; bool _threadsRunning; + + BarrierPosition _endBarrierPosition; + + osg::ref_ptr _startRenderingBarrier; + osg::ref_ptr _endRenderingDispatchBarrier; + osg::ref_ptr _endDynamicDrawBlock; osg::ref_ptr _eventVisitor; @@ -215,7 +272,9 @@ class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object osg::ref_ptr _realizeOperation; + osg::observer_ptr _currentContext; }; + } #endif diff --git a/src/osgViewer/CompositeViewer.cpp b/src/osgViewer/CompositeViewer.cpp index df6f499de..ba0e62355 100644 --- a/src/osgViewer/CompositeViewer.cpp +++ b/src/osgViewer/CompositeViewer.cpp @@ -45,7 +45,9 @@ CompositeViewer::CompositeViewer(osg::ArgumentParser& arguments) } while (arguments.read("--SingleThreaded")) setThreadingModel(SingleThreaded); - while (arguments.read("--ThreadPerContext")) setThreadingModel(ThreadPerContext); + while (arguments.read("--CullDrawThreadPerContext")) setThreadingModel(CullDrawThreadPerContext); + while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext); + while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext); osg::DisplaySettings::instance()->readCommandLine(arguments); osgDB::readCommandLine(arguments); @@ -54,7 +56,6 @@ CompositeViewer::CompositeViewer(osg::ArgumentParser& arguments) void CompositeViewer::constructorInit() { _endBarrierPosition = AfterSwapBuffers; - _numThreadsOnBarrier = 0; _startTick = 0; // make sure View is safe to reference multi-threaded. @@ -183,17 +184,7 @@ int CompositeViewer::run() } } - if (!isRealized()) - { - realize(); - } - - while (!done()) - { - frame(); - } - - return 0; + return ViewerBase::run(); } void CompositeViewer::setStartTick(osg::Timer_t tick) @@ -236,228 +227,8 @@ void CompositeViewer::setReferenceTime(double time) } -void CompositeViewer::setThreadingModel(ThreadingModel threadingModel) -{ - if (_threadingModel == threadingModel) return; - - if (_threadingModel!=SingleThreaded) stopThreading(); - - _threadingModel = threadingModel; - if (isRealized() && _threadingModel!=SingleThreaded) startThreading(); -} - - -void CompositeViewer::setEndBarrierPosition(BarrierPosition bp) -{ - if (_endBarrierPosition == bp) return; - - if (_threadingModel!=SingleThreaded) stopThreading(); - - _endBarrierPosition = bp; - - if (_threadingModel!=SingleThreaded) startThreading(); -} - -void CompositeViewer::stopThreading() -{ - if (!_threadsRunning) return; - - if (_numThreadsOnBarrier==0) return; - - osg::notify(osg::INFO)<<"CompositeViewer::stopThreading() - stopping threading"<setGraphicsThread(0); - } - - _startRenderingBarrier = 0; - _endRenderingDispatchBarrier = 0; - _numThreadsOnBarrier = 0; -} - - -unsigned int CompositeViewer::computeNumberOfThreadsIncludingMainRequired() -{ - Contexts contexts; - getContexts(contexts); - - if (contexts.empty()) return 0; - - if (contexts.size()==1 || _threadingModel==SingleThreaded) - { - return 1; - } - - bool firstContextAsMainThread = _threadingModel == ThreadPerContext; - - return firstContextAsMainThread ? contexts.size() : contexts.size()+1; -} - -void CompositeViewer::setUpThreading() -{ - Contexts contexts; - getContexts(contexts); - - if (_threadingModel==SingleThreaded) - { - if (_threadsRunning) stopThreading(); - } - else - { - if (!_threadsRunning) startThreading(); - } - -} - -void CompositeViewer::startThreading() -{ - if (_threadsRunning) return; - - unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired(); - - // return if we don't need multiple threads. - if (numThreadsIncludingMainThread <= 1) return; - - // return if threading is already up and running - if (numThreadsIncludingMainThread == _numThreadsOnBarrier) return; - - if (_numThreadsOnBarrier!=0) - { - // we already have threads running but not the right number, so stop them and then create new threads. - stopThreading(); - } - - osg::notify(osg::INFO)<<"CompositeViewer::startThreading() - starting threading"<getSceneData(); - if (sceneData) - { - osg::notify(osg::INFO)<<"Making scene thread safe"<setThreadSafeRefUnref(true); - - // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it. - sceneData->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); - } - } - - Contexts contexts; - getContexts(contexts); - - int numProcessors = OpenThreads::GetNumberOfProcessors(); - bool affinity = false; - - bool firstContextAsMainThread = numThreadsIncludingMainThread==contexts.size(); - - // osg::notify(osg::NOTICE)<<"numThreadsIncludingMainThread=="< swapOp = new osg::SwapBuffersOperation(); - - Contexts::iterator citr = contexts.begin(); - unsigned int processNum = 0; - - if (firstContextAsMainThread) - { - ++processNum; - ++citr; - } - - for(; - citr != contexts.end(); - ++citr, - ++processNum) - { - osg::GraphicsContext* gc = (*citr); - - // create the a graphics thread for this context - gc->createGraphicsThread(); - - if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); - - gc->getGraphicsThread()->add(new osgUtil::GLObjectsOperation()); - - // add the startRenderingBarrier - gc->getGraphicsThread()->add(_startRenderingBarrier.get()); - - // add the rendering operation itself. - gc->getGraphicsThread()->add(new osg::RunOperations()); - - if (_endBarrierPosition==BeforeSwapBuffers) - { - // add the endRenderingDispatchBarrier - gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); - } - - // add the swap buffers - gc->getGraphicsThread()->add(swapOp.get()); - - if (_endBarrierPosition==AfterSwapBuffers) - { - // add the endRenderingDispatchBarrier - gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); - } - - } - - if (firstContextAsMainThread) - { - if (affinity) OpenThreads::SetProcessorAffinityOfCurrentThread(0); - } - - for(citr = contexts.begin(); - citr != contexts.end(); - ++citr) - { - osg::GraphicsContext* gc = (*citr); - if (gc->getGraphicsThread() && !gc->getGraphicsThread()->isRunning()) - { - //osg::notify(osg::NOTICE)<<" gc->getGraphicsThread()->startThread() "<getGraphicsThread()<getGraphicsThread()->startThread(); - // OpenThreads::Thread::YieldCurrentThread(); - } - } - - _threadsRunning = true; -} - -void CompositeViewer::checkWindowStatus() -{ - Contexts contexts; - getContexts(contexts); - - // osg::notify(osg::INFO)<<"Viewer::checkWindowStatus() - "<delta_s(_startTick, osg::Timer::instance()->tick()); - - Scenes scenes; - getScenes(scenes); - - for(Scenes::iterator sitr = scenes.begin(); - sitr != scenes.end(); - ++sitr) - { - Scene* scene = *sitr; - osgDB::DatabasePager* dp = scene ? scene->getDatabasePager() : 0; - if (dp) - { - dp->signalBeginFrame(getFrameStamp()); - } - } - - // osg::notify(osg::NOTICE)<block(); - - Contexts::iterator itr; - for(itr = contexts.begin(); - itr != contexts.end(); - ++itr) - { - if (_done) return; - if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) - { - (*itr)->makeCurrent(); - (*itr)->runOperations(); - (*itr)->releaseContext(); - } - } - - // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<block(); - - for(itr = contexts.begin(); - itr != contexts.end(); - ++itr) - { - if (_done) return; - - if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) - { - (*itr)->makeCurrent(); - (*itr)->swapBuffers(); - (*itr)->releaseContext(); - } - } - - for(Scenes::iterator sitr = scenes.begin(); - sitr != scenes.end(); - ++sitr) - { - Scene* scene = *sitr; - osgDB::DatabasePager* dp = scene ? scene->getDatabasePager() : 0; - if (dp) - { - dp->signalEndFrame(); - } - } - - if (getStats() && getStats()->collectStats("update")) - { - double endRenderingTraversals = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); - - // update current frames stats - getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals begin time ", beginRenderingTraversals); - getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals); - getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals); - } + return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); } void CompositeViewer::getUsage(osg::ApplicationUsage& usage) const diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index b849a8a4f..d73c7d693 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -30,11 +30,6 @@ using namespace osgViewer; -static osg::ApplicationUsageProxy Viewer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_CONFIG_FILE ","Specify a viewer configuration file to load by default."); -static osg::ApplicationUsageProxy Viewer_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREADING ","Set the threading model using by Viewer, can be SingleThreaded, CullDrawThreadPerContext, DrawThreadPerContext or CullThreadPerCameraDrawThreadPerContext."); -static osg::ApplicationUsageProxy Viewer_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN ","Set the default screen that windows should open up on."); -static osg::ApplicationUsageProxy Viewer_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WINDOW x y width height","Set the default window dimensions that windows should open up on."); - Viewer::Viewer() { @@ -128,10 +123,6 @@ Viewer::Viewer(const osgViewer::Viewer& viewer, const osg::CopyOp& copyop): void Viewer::constructorInit() { - _firstFrame = true; - _endBarrierPosition = AfterSwapBuffers; - _numWindowsOpenAtLastSetUpThreading = 0; - _eventVisitor = new osgGA::EventVisitor; _eventVisitor->setActionAdapter(this); _eventVisitor->setFrameStamp(_frameStamp.get()); @@ -189,7 +180,6 @@ void Viewer::take(View& rhs) if (rhs_viewer) { // variables left to take. - _firstFrame = rhs_viewer->_firstFrame; _done = rhs_viewer->_done; _keyEventSetsDone = rhs_viewer->_keyEventSetsDone; _quitEventSetsDone = rhs_viewer->_quitEventSetsDone; @@ -199,7 +189,6 @@ void Viewer::take(View& rhs) _startRenderingBarrier = rhs_viewer->_startRenderingBarrier; _endRenderingDispatchBarrier = rhs_viewer->_endRenderingDispatchBarrier; _endDynamicDrawBlock = rhs_viewer->_endDynamicDrawBlock; - _numWindowsOpenAtLastSetUpThreading = rhs_viewer->_numWindowsOpenAtLastSetUpThreading; _cameraWithFocus = rhs_viewer->_cameraWithFocus; _eventVisitor = rhs_viewer->_eventVisitor; _updateOperations = rhs_viewer->_updateOperations; @@ -213,7 +202,6 @@ void Viewer::take(View& rhs) rhs_viewer->_startRenderingBarrier = 0; rhs_viewer->_endRenderingDispatchBarrier = 0; rhs_viewer->_endDynamicDrawBlock = 0; - rhs_viewer->_numWindowsOpenAtLastSetUpThreading = 0; rhs_viewer->_cameraWithFocus = 0; rhs_viewer->_eventVisitor = 0; rhs_viewer->_updateOperations = 0; @@ -278,49 +266,12 @@ bool Viewer::isRealized() const int Viewer::run() { - // if we don't have any scene graph assigned then just return - if (!getSceneData()) - { - osg::notify(osg::NOTICE)<<"Warning: Viewer::run() called without a scene graph being assigned to the viewer, cannot run."<getAllowEventFocus()) { setCameraManipulator(new osgGA::TrackballManipulator()); } - - if (!isRealized()) - { - realize(); - } - -#if 0 - while (!done()) - { - frame(); - } -#else - - const char* str = getenv("OSG_RUN_FRAME_COUNT"); - if (str) - { - int runTillFrameNumber = atoi(str); - while (!done() && getFrameStamp()->getFrameNumber()1; - if (affinity) - { - OpenThreads::SetProcessorAffinityOfCurrentThread(0); - if (_scene.valid() && _scene->getDatabasePager()) - { - _scene->getDatabasePager()->setProcessorAffinity(1); - } - } - } - } - else - { - if (!_threadsRunning) startThreading(); - } - -} - - -void Viewer::setEndBarrierPosition(BarrierPosition bp) -{ - if (_endBarrierPosition == bp) return; - - if (_threadsRunning) stopThreading(); - - _endBarrierPosition = bp; - - if (_threadingModel!=SingleThreaded) startThreading(); -} - -void Viewer::stopThreading() -{ - if (!_threadsRunning) return; - - osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopping threading"<(camera->getRenderer()); - if (renderer) renderer->release(); - } - - // delete all the graphics threads. - for(gcitr = contexts.begin(); - gcitr != contexts.end(); - ++gcitr) - { - (*gcitr)->setGraphicsThread(0); - } - - // delete all the camera threads. - for(citr = cameras.begin(); - citr != cameras.end(); - ++citr) - { - (*citr)->setCameraThread(0); - } - - for(Cameras::iterator camItr = cameras.begin(); - camItr != cameras.end(); - ++camItr) - { - osg::Camera* camera = *camItr; - Renderer* renderer = dynamic_cast(camera->getRenderer()); - if (renderer) - { - renderer->setGraphicsThreadDoesCull( true ); - renderer->setDone(false); - } - } - - - int numProcessors = OpenThreads::GetNumberOfProcessors(); - bool affinity = numProcessors>1; - if (affinity) - { - OpenThreads::SetProcessorAffinityOfCurrentThread(0); - if (_scene.valid() && _scene->getDatabasePager()) - { - _scene->getDatabasePager()->setProcessorAffinity(1); - } - } - - _threadsRunning = false; - _startRenderingBarrier = 0; - _endRenderingDispatchBarrier = 0; - _endDynamicDrawBlock = 0; - _numWindowsOpenAtLastSetUpThreading = contexts.size(); - - osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading."<= static_cast(cameras.size()+contexts.size())) - { - return CullThreadPerCameraDrawThreadPerContext; - } -#endif - - return DrawThreadPerContext; -} - -void Viewer::startThreading() -{ - if (_threadsRunning) return; - - osg::notify(osg::INFO)<<"Viewer::startThreading() - starting threading"<setThreadSafeRefUnref(true); - - // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it. - getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); - } - - int numProcessors = OpenThreads::GetNumberOfProcessors(); - bool affinity = numProcessors>1; - - Contexts::iterator citr; - - unsigned int numViewerDoubleBufferedRenderingOperation = 0; - - bool graphicsThreadsDoesCull = _threadingModel == CullDrawThreadPerContext || _threadingModel==SingleThreaded; - - for(Cameras::iterator camItr = cameras.begin(); - camItr != cameras.end(); - ++camItr) - { - osg::Camera* camera = *camItr; - Renderer* renderer = dynamic_cast(camera->getRenderer()); - if (renderer) - { - renderer->setGraphicsThreadDoesCull(graphicsThreadsDoesCull); - renderer->setDone(false); - ++numViewerDoubleBufferedRenderingOperation; - } - } - - if (_threadingModel==CullDrawThreadPerContext) - { - _startRenderingBarrier = 0; - _endRenderingDispatchBarrier = 0; - _endDynamicDrawBlock = 0; - } - else if (_threadingModel==DrawThreadPerContext || - _threadingModel==CullThreadPerCameraDrawThreadPerContext) - { - _startRenderingBarrier = 0; - _endRenderingDispatchBarrier = 0; - _endDynamicDrawBlock = new osg::EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation); - -#ifndef OSGUTIL_RENDERBACKEND_USE_REF_PTR - if (!osg::Referenced::getDeleteHandler()) osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2)); - else osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2); -#endif - } - - if (numThreadsOnStartBarrier>1) - { - _startRenderingBarrier = new osg::BarrierOperation(numThreadsOnStartBarrier, osg::BarrierOperation::NO_OPERATION); - } - - if (numThreadsOnEndBarrier>1) - { - _endRenderingDispatchBarrier = new osg::BarrierOperation(numThreadsOnEndBarrier, osg::BarrierOperation::NO_OPERATION); - } - - - osg::ref_ptr swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION); - - osg::ref_ptr swapOp = new osg::SwapBuffersOperation(); - - typedef std::map ThreadAffinityMap; - ThreadAffinityMap threadAffinityMap; - - unsigned int processNum = 1; - for(citr = contexts.begin(); - citr != contexts.end(); - ++citr, ++processNum) - { - osg::GraphicsContext* gc = (*citr); - - gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get()); - - // create the a graphics thread for this context - gc->createGraphicsThread(); - - if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); - threadAffinityMap[gc->getGraphicsThread()] = processNum % numProcessors; - - gc->getGraphicsThread()->add(new osgUtil::GLObjectsOperation()); - - // add the startRenderingBarrier - if (_threadingModel==CullDrawThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); - - // add the rendering operation itself. - gc->getGraphicsThread()->add(new osg::RunOperations()); - - if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) - { - // add the endRenderingDispatchBarrier - gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); - } - - if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get()); - - // add the swap buffers - gc->getGraphicsThread()->add(swapOp.get()); - - if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) - { - // add the endRenderingDispatchBarrier - gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); - } - - } - - if (_threadingModel==CullThreadPerCameraDrawThreadPerContext && numThreadsOnStartBarrier>1) - { - Cameras::iterator camItr; - - for(camItr = cameras.begin(); - camItr != cameras.end(); - ++camItr, ++processNum) - { - osg::Camera* camera = *camItr; - camera->createCameraThread(); - - if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors); - threadAffinityMap[camera->getCameraThread()] = processNum % numProcessors; - - osg::GraphicsContext* gc = camera->getGraphicsContext(); - - // add the startRenderingBarrier - if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get()); - - Renderer* renderer = dynamic_cast(camera->getRenderer()); - renderer->setGraphicsThreadDoesCull(false); - camera->getCameraThread()->add(renderer); - - if (_endRenderingDispatchBarrier.valid()) - { - // add the endRenderingDispatchBarrier - gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); - } - - } - - for(camItr = cameras.begin(); - camItr != cameras.end(); - ++camItr) - { - osg::Camera* camera = *camItr; - if (camera->getCameraThread() && !camera->getCameraThread()->isRunning()) - { - osg::notify(osg::INFO)<<" camera->getCameraThread()-> "<getCameraThread()<getCameraThread()->startThread(); - } - } - } - - if (affinity) - { - OpenThreads::SetProcessorAffinityOfCurrentThread(0); - if (_scene.valid() && _scene->getDatabasePager()) - { -#if 0 - _scene->getDatabasePager()->setProcessorAffinity(1); -#else - _scene->getDatabasePager()->setProcessorAffinity(0); -#endif - } - } - -#if 0 - if (affinity) - { - for(ThreadAffinityMap::iterator titr = threadAffinityMap.begin(); - titr != threadAffinityMap.end(); - ++titr) - { - titr->first->setProcessorAffinity(titr->second); - } - } -#endif - - - for(citr = contexts.begin(); - citr != contexts.end(); - ++citr) - { - osg::GraphicsContext* gc = (*citr); - if (gc->getGraphicsThread() && !gc->getGraphicsThread()->isRunning()) - { - osg::notify(osg::INFO)<<" gc->getGraphicsThread()->startThread() "<getGraphicsThread()<getGraphicsThread()->startThread(); - // OpenThreads::Thread::YieldCurrentThread(); - } - } - - _threadsRunning = true; - _numWindowsOpenAtLastSetUpThreading = contexts.size(); - - osg::notify(osg::INFO)<<"Set up threading"<(*itr); - if (gw) windows.push_back(gw); - } -} - - -void Viewer::getAllThreads(Threads& threads, bool onlyActive) -{ - OperationThreads operationThreads; - getOperationThreads(operationThreads); - - for(OperationThreads::iterator itr = operationThreads.begin(); - itr != operationThreads.end(); - ++itr) - { - threads.push_back(*itr); - } - - if (_scene.valid() && - _scene->getDatabasePager() && - (!onlyActive || _scene->getDatabasePager()->isRunning())) - { - threads.push_back(_scene->getDatabasePager()); - } -} - - -void Viewer::getOperationThreads(OperationThreads& threads, bool onlyActive) -{ - threads.clear(); - - Contexts contexts; - getContexts(contexts); - for(Contexts::iterator gcitr = contexts.begin(); - gcitr != contexts.end(); - ++gcitr) - { - osg::GraphicsContext* gc = *gcitr; - if (gc->getGraphicsThread() && - (!onlyActive || gc->getGraphicsThread()->isRunning()) ) - { - threads.push_back(gc->getGraphicsThread()); - } - } - - Cameras cameras; - getCameras(cameras); - for(Cameras::iterator citr = cameras.begin(); - citr != cameras.end(); - ++citr) - { - osg::Camera* camera = *citr; - if (camera->getCameraThread() && - (!onlyActive || camera->getCameraThread()->isRunning()) ) - { - threads.push_back(camera->getCameraThread()); - } - } - -} - - void Viewer::realize() { //osg::notify(osg::INFO)<<"Viewer::realize()"<delta_s(_startTick, osg::Timer::instance()->tick()); - - osgDB::DatabasePager* dp = _scene.valid() ? _scene->getDatabasePager() : 0; - if (dp) - { - dp->signalBeginFrame(getFrameStamp()); - } - - // osg::notify(osg::NOTICE)<block(); - - if (_endDynamicDrawBlock.valid()) - { - _endDynamicDrawBlock->reset(); - } - - // reset any double buffer graphics objects - for(Cameras::iterator camItr = cameras.begin(); - camItr != cameras.end(); - ++camItr) - { - osg::Camera* camera = *camItr; - Renderer* renderer = dynamic_cast(camera->getRenderer()); - if (renderer) - { - if (!renderer->getGraphicsThreadDoesCull() && !(camera->getCameraThread())) - { - renderer->cull(); - } - } - } - - for(itr = contexts.begin(); - itr != contexts.end(); - ++itr) - { - if (_done) return; - if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) - { - makeCurrent(*itr); - (*itr)->runOperations(); - } - } - - // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block "<<_endRenderingDispatchBarrier.get()<block(); - - for(itr = contexts.begin(); - itr != contexts.end(); - ++itr) - { - if (_done) return; - - if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) - { - makeCurrent(*itr); - (*itr)->swapBuffers(); - } - } - - if (dp) - { - dp->signalEndFrame(); - } - - // wait till the dynamic draw is complete. - if (_endDynamicDrawBlock.valid()) - { - // osg::Timer_t startTick = osg::Timer::instance()->tick(); - _endDynamicDrawBlock->block(); - // osg::notify(osg::NOTICE)<<"Time waiting "<delta_m(startTick, osg::Timer::instance()->tick())<collectStats("update")) - { - double endRenderingTraversals = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); - - // update current frames stats - getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals begin time ", beginRenderingTraversals); - getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals); - getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals); - } -} - void Viewer::getScenes(Scenes& scenes, bool onlyValid) { scenes.push_back(_scene.get()); @@ -1589,6 +896,78 @@ void Viewer::getViews(Views& views, bool onlyValid) views.push_back(this); } +void Viewer::getWindows(Windows& windows, bool onlyValid) +{ + windows.clear(); + + Contexts contexts; + getContexts(contexts, onlyValid); + + for(Contexts::iterator itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + osgViewer::GraphicsWindow* gw = dynamic_cast(*itr); + if (gw) windows.push_back(gw); + } +} + + +void Viewer::getAllThreads(Threads& threads, bool onlyActive) +{ + OperationThreads operationThreads; + getOperationThreads(operationThreads); + + for(OperationThreads::iterator itr = operationThreads.begin(); + itr != operationThreads.end(); + ++itr) + { + threads.push_back(*itr); + } + + if (_scene.valid() && + _scene->getDatabasePager() && + (!onlyActive || _scene->getDatabasePager()->isRunning())) + { + threads.push_back(_scene->getDatabasePager()); + } +} + + +void Viewer::getOperationThreads(OperationThreads& threads, bool onlyActive) +{ + threads.clear(); + + Contexts contexts; + getContexts(contexts); + for(Contexts::iterator gcitr = contexts.begin(); + gcitr != contexts.end(); + ++gcitr) + { + osg::GraphicsContext* gc = *gcitr; + if (gc->getGraphicsThread() && + (!onlyActive || gc->getGraphicsThread()->isRunning()) ) + { + threads.push_back(gc->getGraphicsThread()); + } + } + + Cameras cameras; + getCameras(cameras); + for(Cameras::iterator citr = cameras.begin(); + citr != cameras.end(); + ++citr) + { + osg::Camera* camera = *citr; + if (camera->getCameraThread() && + (!onlyActive || camera->getCameraThread()->isRunning()) ) + { + threads.push_back(camera->getCameraThread()); + } + } + +} + struct LessGraphicsContext { bool operator () (const osg::GraphicsContext* lhs, const osg::GraphicsContext* rhs) const @@ -1670,6 +1049,11 @@ void Viewer::getCameras(Cameras& cameras, bool onlyActive) } +double Viewer::elapsedTime() +{ + return osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()); +} + void Viewer::getUsage(osg::ApplicationUsage& usage) const { @@ -1686,4 +1070,3 @@ void Viewer::getUsage(osg::ApplicationUsage& usage) const } } - diff --git a/src/osgViewer/ViewerBase.cpp b/src/osgViewer/ViewerBase.cpp index 6605cf12d..61aa53841 100644 --- a/src/osgViewer/ViewerBase.cpp +++ b/src/osgViewer/ViewerBase.cpp @@ -12,6 +12,7 @@ */ #include +#include #include @@ -21,23 +22,483 @@ #include #include +#include + +static osg::ApplicationUsageProxy ViewerBase_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_CONFIG_FILE ","Specify a viewer configuration file to load by default."); +static osg::ApplicationUsageProxy ViewerBase_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREADING ","Set the threading model using by Viewer, can be SingleThreaded, CullDrawThreadPerContext, DrawThreadPerContext or CullThreadPerCameraDrawThreadPerContext."); +static osg::ApplicationUsageProxy ViewerBase_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN ","Set the default screen that windows should open up on."); +static osg::ApplicationUsageProxy ViewerBase_e3(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WINDOW x y width height","Set the default window dimensions that windows should open up on."); + using namespace osgViewer; ViewerBase::ViewerBase(): osg::Object(true) { + _firstFrame = true; _done = false; _keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape; _quitEventSetsDone = true; _threadingModel = AutomaticSelection; _threadsRunning = false; - + _endBarrierPosition = AfterSwapBuffers; } ViewerBase::ViewerBase(const ViewerBase& base): osg::Object(true) { + _firstFrame = true; + _done = false; + _keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape; + _quitEventSetsDone = true; + _threadingModel = AutomaticSelection; + _threadsRunning = false; + _endBarrierPosition = AfterSwapBuffers; +} + +void ViewerBase::setThreadingModel(ThreadingModel threadingModel) +{ + if (_threadingModel == threadingModel) return; + + if (_threadsRunning) stopThreading(); + + _threadingModel = threadingModel; + + if (isRealized() && _threadingModel!=SingleThreaded) startThreading(); +} + +ViewerBase::ThreadingModel ViewerBase::suggestBestThreadingModel() +{ + const char* str = getenv("OSG_THREADING"); + if (str) + { + if (strcmp(str,"SingleThreaded")==0) return SingleThreaded; + else if (strcmp(str,"CullDrawThreadPerContext")==0) return CullDrawThreadPerContext; + else if (strcmp(str,"DrawThreadPerContext")==0) return DrawThreadPerContext; + else if (strcmp(str,"CullThreadPerCameraDrawThreadPerContext")==0) return CullThreadPerCameraDrawThreadPerContext; + } + + Contexts contexts; + getContexts(contexts); + + if (contexts.empty()) return SingleThreaded; + +#if 0 + // temporary hack to disable multi-threading under Windows till we find good solutions for + // crashes that users are seeing. + return SingleThreaded; +#endif + + Cameras cameras; + getCameras(cameras); + + if (cameras.empty()) return SingleThreaded; + + + int numProcessors = OpenThreads::GetNumberOfProcessors(); + + if (contexts.size()==1) + { + if (numProcessors==1) return SingleThreaded; + else return DrawThreadPerContext; + } + +#if 1 + if (numProcessors >= static_cast(cameras.size()+contexts.size())) + { + return CullThreadPerCameraDrawThreadPerContext; + } +#endif + + return DrawThreadPerContext; +} + +void ViewerBase::setUpThreading() +{ + Contexts contexts; + getContexts(contexts); + + if (_threadingModel==SingleThreaded) + { + if (_threadsRunning) stopThreading(); + else + { + // we'll set processor affinity here to help single threaded apps + // with multiple processor cores, and using the database pager. + int numProcessors = OpenThreads::GetNumberOfProcessors(); + bool affinity = numProcessors>1; + if (affinity) + { + OpenThreads::SetProcessorAffinityOfCurrentThread(0); + + Scenes scenes; + getScenes(scenes); + + for(Scenes::iterator itr = scenes.begin(); + itr != scenes.end(); + ++itr) + { + Scene* scene = *itr; + if (scene && scene->getDatabasePager()) + { + scene->getDatabasePager()->setProcessorAffinity(1); + } + } + + } + } + } + else + { + if (!_threadsRunning) startThreading(); + } + +} + +void ViewerBase::setEndBarrierPosition(BarrierPosition bp) +{ + if (_endBarrierPosition == bp) return; + + if (_threadsRunning) stopThreading(); + + _endBarrierPosition = bp; + + if (_threadingModel!=SingleThreaded) startThreading(); +} + + +void ViewerBase::stopThreading() +{ + if (!_threadsRunning) return; + + osg::notify(osg::INFO)<<"ViewerBase::stopThreading() - stopping threading"<(camera->getRenderer()); + if (renderer) renderer->release(); + } + + // delete all the graphics threads. + for(gcitr = contexts.begin(); + gcitr != contexts.end(); + ++gcitr) + { + (*gcitr)->setGraphicsThread(0); + } + + // delete all the camera threads. + for(citr = cameras.begin(); + citr != cameras.end(); + ++citr) + { + (*citr)->setCameraThread(0); + } + + for(Cameras::iterator camItr = cameras.begin(); + camItr != cameras.end(); + ++camItr) + { + osg::Camera* camera = *camItr; + Renderer* renderer = dynamic_cast(camera->getRenderer()); + if (renderer) + { + renderer->setGraphicsThreadDoesCull( true ); + renderer->setDone(false); + } + } + + + _threadsRunning = false; + _startRenderingBarrier = 0; + _endRenderingDispatchBarrier = 0; + _endDynamicDrawBlock = 0; + + osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading."<getSceneData()) + { + osg::notify(osg::INFO)<<"Making scene thread safe"<getSceneData()->setThreadSafeRefUnref(true); + + // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it. + (*scitr)->getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts()); + } + } + + int numProcessors = OpenThreads::GetNumberOfProcessors(); + bool affinity = numProcessors>1; + + Contexts::iterator citr; + + unsigned int numViewerDoubleBufferedRenderingOperation = 0; + + bool graphicsThreadsDoesCull = _threadingModel == CullDrawThreadPerContext || _threadingModel==SingleThreaded; + + for(Cameras::iterator camItr = cameras.begin(); + camItr != cameras.end(); + ++camItr) + { + osg::Camera* camera = *camItr; + Renderer* renderer = dynamic_cast(camera->getRenderer()); + if (renderer) + { + renderer->setGraphicsThreadDoesCull(graphicsThreadsDoesCull); + renderer->setDone(false); + ++numViewerDoubleBufferedRenderingOperation; + } + } + + if (_threadingModel==CullDrawThreadPerContext) + { + _startRenderingBarrier = 0; + _endRenderingDispatchBarrier = 0; + _endDynamicDrawBlock = 0; + } + else if (_threadingModel==DrawThreadPerContext || + _threadingModel==CullThreadPerCameraDrawThreadPerContext) + { + _startRenderingBarrier = 0; + _endRenderingDispatchBarrier = 0; + _endDynamicDrawBlock = new osg::EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation); + +#ifndef OSGUTIL_RENDERBACKEND_USE_REF_PTR + if (!osg::Referenced::getDeleteHandler()) osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2)); + else osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2); +#endif + } + + if (numThreadsOnStartBarrier>1) + { + _startRenderingBarrier = new osg::BarrierOperation(numThreadsOnStartBarrier, osg::BarrierOperation::NO_OPERATION); + } + + if (numThreadsOnEndBarrier>1) + { + _endRenderingDispatchBarrier = new osg::BarrierOperation(numThreadsOnEndBarrier, osg::BarrierOperation::NO_OPERATION); + } + + + osg::ref_ptr swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION); + + osg::ref_ptr swapOp = new osg::SwapBuffersOperation(); + + typedef std::map ThreadAffinityMap; + ThreadAffinityMap threadAffinityMap; + + unsigned int processNum = 1; + for(citr = contexts.begin(); + citr != contexts.end(); + ++citr, ++processNum) + { + osg::GraphicsContext* gc = (*citr); + + gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get()); + + // create the a graphics thread for this context + gc->createGraphicsThread(); + + if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors); + threadAffinityMap[gc->getGraphicsThread()] = processNum % numProcessors; + + gc->getGraphicsThread()->add(new osgUtil::GLObjectsOperation()); + + // add the startRenderingBarrier + if (_threadingModel==CullDrawThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get()); + + // add the rendering operation itself. + gc->getGraphicsThread()->add(new osg::RunOperations()); + + if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid()) + { + // add the endRenderingDispatchBarrier + gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + } + + if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get()); + + // add the swap buffers + gc->getGraphicsThread()->add(swapOp.get()); + + if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid()) + { + // add the endRenderingDispatchBarrier + gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + } + + } + + if (_threadingModel==CullThreadPerCameraDrawThreadPerContext && numThreadsOnStartBarrier>1) + { + Cameras::iterator camItr; + + for(camItr = cameras.begin(); + camItr != cameras.end(); + ++camItr, ++processNum) + { + osg::Camera* camera = *camItr; + camera->createCameraThread(); + + if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors); + threadAffinityMap[camera->getCameraThread()] = processNum % numProcessors; + + osg::GraphicsContext* gc = camera->getGraphicsContext(); + + // add the startRenderingBarrier + if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get()); + + Renderer* renderer = dynamic_cast(camera->getRenderer()); + renderer->setGraphicsThreadDoesCull(false); + camera->getCameraThread()->add(renderer); + + if (_endRenderingDispatchBarrier.valid()) + { + // add the endRenderingDispatchBarrier + gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + } + + } + + for(camItr = cameras.begin(); + camItr != cameras.end(); + ++camItr) + { + osg::Camera* camera = *camItr; + if (camera->getCameraThread() && !camera->getCameraThread()->isRunning()) + { + osg::notify(osg::INFO)<<" camera->getCameraThread()-> "<getCameraThread()<getCameraThread()->startThread(); + } + } + } + +#if 0 + if (affinity) + { + OpenThreads::SetProcessorAffinityOfCurrentThread(0); + if (_scene.valid() && _scene->getDatabasePager()) + { +#if 0 + _scene->getDatabasePager()->setProcessorAffinity(1); +#else + _scene->getDatabasePager()->setProcessorAffinity(0); +#endif + } + } +#endif + +#if 0 + if (affinity) + { + for(ThreadAffinityMap::iterator titr = threadAffinityMap.begin(); + titr != threadAffinityMap.end(); + ++titr) + { + titr->first->setProcessorAffinity(titr->second); + } + } +#endif + + + for(citr = contexts.begin(); + citr != contexts.end(); + ++citr) + { + osg::GraphicsContext* gc = (*citr); + if (gc->getGraphicsThread() && !gc->getGraphicsThread()->isRunning()) + { + osg::notify(osg::INFO)<<" gc->getGraphicsThread()->startThread() "<getGraphicsThread()<getGraphicsThread()->startThread(); + // OpenThreads::Thread::YieldCurrentThread(); + } + } + + _threadsRunning = true; + + osg::notify(osg::INFO)<<"Set up threading"<remove(operation); } } + +int ViewerBase::run() +{ + if (!isRealized()) + { + realize(); + } + +#if 0 + while (!done()) + { + frame(); + } +#else + + const char* str = getenv("OSG_RUN_FRAME_COUNT"); + if (str) + { + int runTillFrameNumber = atoi(str); + while (!done() && getViewerFrameStamp()->getFrameNumber()getDatabasePager() : 0; + if (dp) + { + dp->signalBeginFrame(frameStamp); + } + } + + // osg::notify(osg::NOTICE)<block(); + + if (_endDynamicDrawBlock.valid()) + { + _endDynamicDrawBlock->reset(); + } + + // reset any double buffer graphics objects + for(Cameras::iterator camItr = cameras.begin(); + camItr != cameras.end(); + ++camItr) + { + osg::Camera* camera = *camItr; + Renderer* renderer = dynamic_cast(camera->getRenderer()); + if (renderer) + { + if (!renderer->getGraphicsThreadDoesCull() && !(camera->getCameraThread())) + { + renderer->cull(); + } + } + } + + for(itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + if (_done) return; + if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) + { + makeCurrent(*itr); + (*itr)->runOperations(); + } + } + + // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block "<<_endRenderingDispatchBarrier.get()<block(); + + for(itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + if (_done) return; + + if (!((*itr)->getGraphicsThread()) && (*itr)->valid()) + { + makeCurrent(*itr); + (*itr)->swapBuffers(); + } + } + + for(Scenes::iterator sitr = scenes.begin(); + sitr != scenes.end(); + ++sitr) + { + Scene* scene = *sitr; + osgDB::DatabasePager* dp = scene ? scene->getDatabasePager() : 0; + if (dp) + { + dp->signalEndFrame(); + } + } + + // wait till the dynamic draw is complete. + if (_endDynamicDrawBlock.valid()) + { + // osg::Timer_t startTick = osg::Timer::instance()->tick(); + _endDynamicDrawBlock->block(); + // osg::notify(osg::NOTICE)<<"Time waiting "<delta_m(startTick, osg::Timer::instance()->tick())<collectStats("update")) + { + double endRenderingTraversals = elapsedTime(); + + // update current frames stats + getStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals begin time ", beginRenderingTraversals); + getStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals); + getStats()->setAttribute(frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals); + } +} +