[osg-submissions] FW: osgViewer/Viewer causing crash withthreading

Robert Osfield robert.osfield at gmail.com
Mon Aug 6 02:52:59 PDT 2007


Hi Leo,

I've now reviewed your change, but rather than go with the addition of
the getSceneData() in the startThreading() method I've added the
optimizer traversal to the setSceneData() method, this way all new
data will be initialized appropriately.  The orignal code is now
removed so shouldn't required the if (getSceneData()).

Could you test the SVN/2.1.4 dev release of the OSG to see if it works fine.

Cheers,
Robert.

On 7/31/07, Leo <sirmagic at hotmail.com> wrote:
> Try again... sorry
>
> -----Original Message-----
> From: osg-submissions-bounces at lists.openscenegraph.org
> [mailto:osg-submissions-bounces at lists.openscenegraph.org] On Behalf Of
> Robert Osfield
> Sent: July 30, 2007 3:57 PM
> To: osg-submissions at lists.openscenegraph.org
> Subject: Re: [osg-submissions] FW: osgViewer/Viewer causing crash
> withthreading
>
> Dear Sir Magic!,
>
> Alas no magic is available to handle the inline nature of your
> attachment, as your email client hast inlined your submissions
> rendering it useless for mere dwarfs.  Could thoust zip the modified
> and resubmit.
>
> Robert.
>
> On 7/30/07, Sir Magic <sirmagic at hotmail.com> wrote:
> >
> >
> > I am working with OpenSceneGraph version 2.0 but the same problem
> > exists in 2.1.1.
> >
> > Sorry if this is my mistake, but
> >
> > I am realizing a viewer before my scene has been added.
> >
> > In single threaded mode I have no problem.
> >
> > I when I set threading to DrawThreadPerContext I get a crash.
> >
> > I have reviewed the code and the problem occurs in
> > Viewer::startThreading
> >
> > Early on there is a
> >         if (getSceneData())
> > test and special processing for is the scene is present.
> >
> > The next reference to getSceneData - the statement :
> >     getSceneData()->accept(sodv);
> > is unprotected and will crash if scene data has not been loaded.
> >
> > In order to get past this crash I have added a test
> >         if (getSceneData())
> >
> > around the allocation of the StaticObjectDetectionVisitor and the
> > getSceneData()->accept.
> >
> > Leo
> >
> > _________________________________________________________________
> > Windows Live Hotmail is the next generation of MSN Hotmail. It's fast,
> > simple, and safer than ever and best of all - it's still free. Try it
> today!
> > www.newhotmail.ca?icid=WLHMENCA146
> >
> > /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
> > *
> > * This library is open source and may be redistributed and/or modified
> under
> > * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0
> or
> > * (at your option) any later version.  The full license is in LICENSE
> file
> > * included with this distribution, and on the openscenegraph.org
> website.
> > *
> > * This library is distributed in the hope that it will be useful,
> > * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > * OpenSceneGraph Public License for more details.
> > */
> >
> > #include <osg/GLExtensions>
> > #include <osg/DeleteHandler>
> > #include <osgUtil/Optimizer>
> > #include <osgUtil/GLObjectsVisitor>
> > #include <osgDB/Registry>
> > #include <osgGA/TrackballManipulator>
> > #include <osgViewer/Viewer>
> >
> > #include <osg/io_utils>
> >
> > #include <sstream>
> >
> > using namespace osgViewer;
> >
> >
> > class ViewerQuerySupport
> > {
> > public:
> >     ViewerQuerySupport(osg::Timer_t startTick):
> >         _startTick(startTick),
> >         _initialized(false),
> >         _timerQuerySupported(false),
> >         _extensions(0),
> >         _previousQueryTime(0.0)
> >     {
> >     }
> >
> >     typedef std::pair<GLuint, int> QueryFrameNumberPair;
> >     typedef std::list<QueryFrameNumberPair> QueryFrameNumberList;
> >     typedef std::vector<GLuint> QueryList;
> >
> >     inline void checkQuery(osg::Stats* stats)
> >     {
> >         for(QueryFrameNumberList::iterator itr =
> > _queryFrameNumberList.begin();
> >             itr != _queryFrameNumberList.end();
> >             )
> >         {
> >             GLuint query = itr->first;
> >             GLint available = 0;
> >             _extensions->glGetQueryObjectiv(query,
> > GL_QUERY_RESULT_AVAILABLE, &available);
> >             if (available)
> >             {
> >                 GLuint64EXT timeElapsed = 0;
> >                 _extensions->glGetQueryObjectui64v(query,
> GL_QUERY_RESULT,
> > &timeElapsed);
> >
> >                 double timeElapsedSeconds = double(timeElapsed)*1e-9;
> >                 double currentTime =
> > osg::Timer::instance()->delta_s(_startTick,
> osg::Timer::instance()->tick());
> >                 double estimatedEndTime = (_previousQueryTime +
> currentTime)
> > * 0.5;
> >                 double estimatedBeginTime = estimatedEndTime -
> > timeElapsedSeconds;
> >
> >                 stats->setAttribute(itr->second, "GPU draw begin
> time",
> > estimatedBeginTime);
> >                 stats->setAttribute(itr->second, "GPU draw end time",
> > estimatedEndTime);
> >                 stats->setAttribute(itr->second, "GPU draw time
> taken",
> > timeElapsedSeconds);
> >
> >
> >                 itr = _queryFrameNumberList.erase(itr);
> >                 _availableQueryObjects.push_back(query);
> >             }
> >             else
> >             {
> >                 ++itr;
> >             }
> >
> >         }
> >         _previousQueryTime =
> osg::Timer::instance()->delta_s(_startTick,
> > osg::Timer::instance()->tick());
> >     }
> >
> >     inline GLuint createQueryObject()
> >     {
> >         if (_availableQueryObjects.empty())
> >         {
> >             GLuint query;
> >             _extensions->glGenQueries(1, &query);
> >             return query;
> >         }
> >         else
> >         {
> >             GLuint query = _availableQueryObjects.back();
> >             _availableQueryObjects.pop_back();
> >             return query;
> >         }
> >     }
> >
> >     inline void beginQuery(int frameNumber)
> >     {
> >         GLuint query = createQueryObject();
> >         _extensions->glBeginQuery(GL_TIME_ELAPSED, query);
> >         _queryFrameNumberList.push_back(QueryFrameNumberPair(query,
> > frameNumber));
> >     }
> >
> >     inline void endQuery()
> >     {
> >         _extensions->glEndQuery(GL_TIME_ELAPSED);
> >     }
> >
> >     void initialize(osg::State* state)
> >     {
> >         if (_initialized) return;
> >
> >         _initialized = true;
> >         _extensions =
> > osg::Drawable::getExtensions(state->getContextID(),true);
> >         _timerQuerySupported = _extensions &&
> > _extensions->isTimerQuerySupported();
> >         _previousQueryTime =
> osg::Timer::instance()->delta_s(_startTick,
> > osg::Timer::instance()->tick());
> >     }
> >
> >     osg::Timer_t                                _startTick;
> >     bool                                        _initialized;
> >     bool                                        _timerQuerySupported;
> >     const osg::Drawable::Extensions*            _extensions;
> >     QueryFrameNumberList                        _queryFrameNumberList;
> >     QueryList
> _availableQueryObjects;
> >     double                                      _previousQueryTime;
> >
> > };
> >
> >
> > // Draw operation, that does a draw on the scene graph.
> > struct ViewerRenderingOperation : public osg::Operation, public
> > ViewerQuerySupport
> > {
> >     ViewerRenderingOperation(osgUtil::SceneView* sceneView,
> > osgDB::DatabasePager* databasePager, osg::Timer_t startTick):
> >         osg::Operation("Render",true),
> >         ViewerQuerySupport(startTick),
> >         _sceneView(sceneView),
> >         _databasePager(databasePager)
> >     {
> >
> >
> _sceneView->getCullVisitor()->setDatabaseRequestHandler(_databasePager.g
> et());
> >     }
> >
> >     osg::Camera* getCamera() { return _sceneView->getCamera(); }
> >
> >     virtual void operator () (osg::Object*)
> >     {
> >         if (!_sceneView) return;
> >
> >         // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
> >
> >         osg::Stats* stats = _sceneView->getCamera()->getStats();
> >         osg::State* state = _sceneView->getState();
> >         const osg::FrameStamp* fs = state->getFrameStamp();
> >         int frameNumber = fs ? fs->getFrameNumber() : 0;
> >
> >         if (!_initialized)
> >         {
> >             initialize(state);
> >         }
> >
> >         bool aquireGPUStats = stats && _timerQuerySupported &&
> > stats->collectStats("gpu");
> >
> >         if (aquireGPUStats)
> >         {
> >             checkQuery(stats);
> >         }
> >
> >         // do cull taversal
> >         osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
> >
> >         // pass on the fusion distance settings from the View to the
> > SceneView
> >         osgViewer::View* view =
> > dynamic_cast<osgViewer::View*>(_sceneView->getCamera()->getView());
> >         if (view)
> > _sceneView->setFusionDistance(view->getFusionDistanceMode(),
> > view->getFusionDistanceValue());
> >
> >         _sceneView->inheritCullSettings(*(_sceneView->getCamera()));
> >
> >         _sceneView->cull();
> >
> >
> >         osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
> >
> > #if 0
> >         if (_sceneView->getDynamicObjectCount()==0 &&
> > state->getDynamicObjectRenderingCompletedCallback())
> >         {
> >             osg::notify(osg::NOTICE)<<"Completed in
> > ViewerRenderingOperation"<<std::endl;
> >
> > state->getDynamicObjectRenderingCompletedCallback()->completed(state);
> >         }
> > #endif
> >
> >
> state->setDynamicObjectCount(_sceneView->getDynamicObjectCount());
> >
> >         // do draw traveral
> >         if (aquireGPUStats)
> >         {
> >             checkQuery(stats);
> >             beginQuery(frameNumber);
> >         }
> >
> >         _sceneView->draw();
> >
> >         double availableTime = 0.004; // 4 ms
> >         if (_databasePager.valid())
> >         {
> >
> _databasePager->compileGLObjects(*(_sceneView->getState()),
> > availableTime);
> >         }
> >         _sceneView->flushDeletedGLObjects(availableTime);
> >
> >         if (aquireGPUStats)
> >         {
> >             endQuery();
> >             checkQuery(stats);
> >         }
> >
> >         osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
> >
> >         if (stats && stats->collectStats("rendering"))
> >         {
> >             stats->setAttribute(frameNumber, "Cull traversal begin
> time",
> > osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
> >             stats->setAttribute(frameNumber, "Cull traversal end
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterCullTick));
> >             stats->setAttribute(frameNumber, "Cull traversal time
> taken",
> > osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
> >
> >             stats->setAttribute(frameNumber, "Draw traversal begin
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterCullTick));
> >             stats->setAttribute(frameNumber, "Draw traversal end
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
> >             stats->setAttribute(frameNumber, "Draw traversal time
> taken",
> > osg::Timer::instance()->delta_s(afterCullTick, afterDrawTick));
> >         }
> >
> >     }
> >
> >     osg::observer_ptr<osgUtil::SceneView>       _sceneView;
> >     osg::observer_ptr<osgDB::DatabasePager>     _databasePager;
> >
> > };
> >
> >
> > // Draw operation, that does a draw on the scene graph.
> > struct ViewerDoubleBufferedRenderingOperation : public osg::Operation,
> > public ViewerQuerySupport
> > {
> >     ViewerDoubleBufferedRenderingOperation(bool
> graphicsThreadDoesCull,
> > osgUtil::SceneView* sv0, osgUtil::SceneView* sv1,
> osgDB::DatabasePager*
> > databasePager, osg::Timer_t startTick):
> >         osg::Operation("Render",true),
> >         ViewerQuerySupport(startTick),
> >         _graphicsThreadDoesCull(graphicsThreadDoesCull),
> >         _done(false),
> >         _databasePager(databasePager)
> >     {
> >         _lockHeld[0]  = false;
> >         _lockHeld[1]  = false;
> >
> >         _sceneView[0] = sv0;
> >
> >
> _sceneView[0]->getCullVisitor()->setDatabaseRequestHandler(_databasePage
> r.get());
> >
> >         _sceneView[1] = sv1;
> >
> >
> _sceneView[1]->getCullVisitor()->setDatabaseRequestHandler(_databasePage
> r.get());
> >
> >         _currentCull = 0;
> >         _currentDraw = 0;
> >
> >         // lock the mutex for the current cull SceneView to
> >         // prevent the draw traversal from reading from it before the
> cull
> > traversal has been completed.
> >         if (!_graphicsThreadDoesCull)
> >         {
> >              _mutex[_currentCull].lock();
> >              _lockHeld[_currentCull] = true;
> >         }
> >
> >         // osg::notify(osg::NOTICE)<<"constructed"<<std::endl;
> >     }
> >
> >     osg::Camera* getCamera() { return _sceneView[0]->getCamera(); }
> >
> >     void setGraphicsThreadDoesCull(bool flag)
> >     {
> >         if (_graphicsThreadDoesCull==flag) return;
> >
> >         _graphicsThreadDoesCull = flag;
> >
> >         _currentCull = 0;
> >         _currentDraw = 0;
> >
> >         if (_graphicsThreadDoesCull)
> >         {
> >             // need to disable any locks held by the cull
> >             if (_lockHeld[0])
> >             {
> >                 _lockHeld[0] = false;
> >                 _mutex[0].unlock();
> >             }
> >
> >             if (_lockHeld[1])
> >             {
> >                 _lockHeld[1] = false;
> >                 _mutex[1].unlock();
> >             }
> >         }
> >         else
> >         {
> >             // need to set a lock for cull
> >             _mutex[_currentCull].lock();
> >             _lockHeld[_currentCull] = true;
> >         }
> >     }
> >
> >     bool getGraphicsThreadDoesCull() const { return
> _graphicsThreadDoesCull;
> > }
> >
> >     void cull()
> >     {
> >         // osg::notify(osg::NOTICE)<<"cull()"<<std::endl;
> >
> >         if (_done || _graphicsThreadDoesCull) return;
> >
> >         // note we assume lock has already been aquired.
> >         osgUtil::SceneView* sceneView =
> _sceneView[_currentCull].get();
> >
> >         if (sceneView)
> >         {
> >             // osg::notify(osg::NOTICE)<<"Culling buffer
> > "<<_currentCull<<std::endl;
> >
> >             // pass on the fusion distance settings from the View to
> the
> > SceneView
> >             osgViewer::View* view =
> > dynamic_cast<osgViewer::View*>(sceneView->getCamera()->getView());
> >             if (view)
> > sceneView->setFusionDistance(view->getFusionDistanceMode(),
> > view->getFusionDistanceValue());
> >
> >             osg::Stats* stats = sceneView->getCamera()->getStats();
> >             osg::State* state = sceneView->getState();
> >             const osg::FrameStamp* fs = state->getFrameStamp();
> >             int frameNumber = fs ? fs->getFrameNumber() : 0;
> >
> >             _frameNumber[_currentCull] = frameNumber;
> >
> >             // do cull taversal
> >             osg::Timer_t beforeCullTick =
> osg::Timer::instance()->tick();
> >
> >             sceneView->inheritCullSettings(*(sceneView->getCamera()));
> >             sceneView->cull();
> >
> >             osg::Timer_t afterCullTick =
> osg::Timer::instance()->tick();
> >
> > #if 0
> >             if (sceneView->getDynamicObjectCount()==0 &&
> > state->getDynamicObjectRenderingCompletedCallback())
> >             {
> >                 // osg::notify(osg::NOTICE)<<"Completed in
> cull"<<std::endl;
> >
> > state->getDynamicObjectRenderingCompletedCallback()->completed(state);
> >             }
> > #endif
> >             if (stats && stats->collectStats("rendering"))
> >             {
> >                 stats->setAttribute(frameNumber, "Cull traversal begin
> > time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
> >                 stats->setAttribute(frameNumber, "Cull traversal end
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterCullTick));
> >                 stats->setAttribute(frameNumber, "Cull traversal time
> > taken", osg::Timer::instance()->delta_s(beforeCullTick,
> afterCullTick));
> >             }
> >         }
> >
> >
> >         // relase the mutex associated with this cull traversal, let
> the
> > draw commence.
> >         _lockHeld[_currentCull] = false;
> >         _mutex[_currentCull].unlock();
> >
> >         // swap which SceneView we need to do cull traversal on next.
> >         _currentCull = 1 - _currentCull;
> >
> >         // aquire the lock for it for the new cull traversal
> >         _mutex[_currentCull].lock();
> >         _lockHeld[_currentCull] = true;
> >     }
> >
> >     void draw()
> >     {
> >         // osg::notify(osg::NOTICE)<<"draw()"<<std::endl;
> >
> >         osgUtil::SceneView* sceneView =
> _sceneView[_currentDraw].get();
> >
> >         if (sceneView || _done)
> >         {
> >             OpenThreads::ScopedLock<OpenThreads::Mutex>
> > lock(_mutex[_currentDraw]);
> >
> >             // osg::notify(osg::NOTICE)<<"Drawing buffer
> > "<<_currentDraw<<std::endl;
> >
> >             if (_done)
> >             {
> >
> >
> osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::release
> ()
> > causing draw to exit"<<std::endl;
> >                 return;
> >             }
> >
> >             if (_graphicsThreadDoesCull)
> >             {
> >
> >
> osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::draw()
> > completing early due to change in _graphicsThreadDoesCull
> flag."<<std::endl;
> >                 return;
> >             }
> >
> >             //
> osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
> >
> >             osg::Stats* stats = sceneView->getCamera()->getStats();
> >             osg::State* state = sceneView->getState();
> >             int frameNumber = _frameNumber[_currentDraw];
> >
> >             if (!_initialized)
> >             {
> >                 initialize(state);
> >             }
> >
> >
> > state->setDynamicObjectCount(sceneView->getDynamicObjectCount());
> >
> >             if (sceneView->getDynamicObjectCount()==0 &&
> > state->getDynamicObjectRenderingCompletedCallback())
> >             {
> >                 // osg::notify(osg::NOTICE)<<"Completed in
> cull"<<std::endl;
> >
> > state->getDynamicObjectRenderingCompletedCallback()->completed(state);
> >             }
> >
> >             osg::Timer_t beforeDrawTick =
> osg::Timer::instance()->tick();
> >
> >             bool aquireGPUStats = stats && _timerQuerySupported &&
> > stats->collectStats("gpu");
> >
> >             if (aquireGPUStats)
> >             {
> >                 checkQuery(stats);
> >             }
> >
> >             // do draw traveral
> >             if (aquireGPUStats)
> >             {
> >                 checkQuery(stats);
> >                 beginQuery(frameNumber);
> >             }
> >
> >             sceneView->draw();
> >
> >             double availableTime = 0.004; // 4 ms
> >             if (_databasePager.valid())
> >             {
> >
> _databasePager->compileGLObjects(*(sceneView->getState()),
> > availableTime);
> >             }
> >
> >             sceneView->flushDeletedGLObjects(availableTime);
> >
> >             if (aquireGPUStats)
> >             {
> >                 endQuery();
> >                 checkQuery(stats);
> >             }
> >
> >             glFlush();
> >
> >
> >             osg::Timer_t afterDrawTick =
> osg::Timer::instance()->tick();
> >
> >             if (stats && stats->collectStats("rendering"))
> >             {
> >                 stats->setAttribute(frameNumber, "Draw traversal begin
> > time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick));
> >                 stats->setAttribute(frameNumber, "Draw traversal end
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
> >                 stats->setAttribute(frameNumber, "Draw traversal time
> > taken", osg::Timer::instance()->delta_s(beforeDrawTick,
> afterDrawTick));
> >             }
> >         }
> >
> >         _currentDraw = 1-_currentDraw;
> >
> >     }
> >
> >     void cull_draw()
> >     {
> >         osgUtil::SceneView* sceneView =
> _sceneView[_currentDraw].get();
> >         if (!sceneView || _done) return;
> >
> >         OpenThreads::ScopedLock<OpenThreads::Mutex>
> > lock(_mutex[_currentDraw]);
> >
> >         if (_done)
> >         {
> >
> >
> osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::release
> ()
> > causing cull_draw to exit"<<std::endl;
> >             return;
> >         }
> >
> >         // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
> >
> >         // pass on the fusion distance settings from the View to the
> > SceneView
> >         osgViewer::View* view =
> > dynamic_cast<osgViewer::View*>(sceneView->getCamera()->getView());
> >         if (view)
> > sceneView->setFusionDistance(view->getFusionDistanceMode(),
> > view->getFusionDistanceValue());
> >
> >         osg::Stats* stats = sceneView->getCamera()->getStats();
> >         osg::State* state = sceneView->getState();
> >         const osg::FrameStamp* fs = state->getFrameStamp();
> >         int frameNumber = fs ? fs->getFrameNumber() : 0;
> >
> >         if (!_initialized)
> >         {
> >             initialize(state);
> >         }
> >
> >         bool aquireGPUStats = stats && _timerQuerySupported &&
> > stats->collectStats("gpu");
> >
> >         if (aquireGPUStats)
> >         {
> >             checkQuery(stats);
> >         }
> >
> >         // do cull taversal
> >         osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
> >
> >         sceneView->inheritCullSettings(*(sceneView->getCamera()));
> >         sceneView->cull();
> >
> >         osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
> >
> >         if (state->getDynamicObjectCount()==0 &&
> > state->getDynamicObjectRenderingCompletedCallback())
> >         {
> >
> > state->getDynamicObjectRenderingCompletedCallback()->completed(state);
> >         }
> >
> >         // do draw traveral
> >         if (aquireGPUStats)
> >         {
> >             checkQuery(stats);
> >             beginQuery(frameNumber);
> >         }
> >
> >         sceneView->draw();
> >
> >         double availableTime = 0.004; // 4 ms
> >         if (_databasePager.valid())
> >         {
> >             _databasePager->compileGLObjects(*(sceneView->getState()),
> > availableTime);
> >         }
> >         sceneView->flushDeletedGLObjects(availableTime);
> >
> >         if (aquireGPUStats)
> >         {
> >             endQuery();
> >             checkQuery(stats);
> >         }
> >
> >         osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
> >
> >         if (stats && stats->collectStats("rendering"))
> >         {
> >             stats->setAttribute(frameNumber, "Cull traversal begin
> time",
> > osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
> >             stats->setAttribute(frameNumber, "Cull traversal end
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterCullTick));
> >             stats->setAttribute(frameNumber, "Cull traversal time
> taken",
> > osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
> >
> >             stats->setAttribute(frameNumber, "Draw traversal begin
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterCullTick));
> >             stats->setAttribute(frameNumber, "Draw traversal end
> time",
> > osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
> >             stats->setAttribute(frameNumber, "Draw traversal time
> taken",
> > osg::Timer::instance()->delta_s(afterCullTick, afterDrawTick));
> >         }
> >     }
> >
> >     virtual void operator () (osg::Object* object)
> >     {
> >         osg::GraphicsContext* context =
> > dynamic_cast<osg::GraphicsContext*>(object);
> >         if (!context)
> >         {
> >             osg::Camera* camera = dynamic_cast<osg::Camera*>(object);
> >             if (camera) cull();
> >             return;
> >         }
> >
> >         //osg::notify(osg::NOTICE)<<"GraphicsCall "<<std::endl;
> >         // if (_done) return;
> >
> >         if (_graphicsThreadDoesCull)
> >         {
> >             cull_draw();
> >         }
> >         else
> >         {
> >             draw();
> >         }
> >     }
> >
> >     virtual void release()
> >     {
> >
> >
> osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::release
> ()"<<std::endl;
> >         _done = true;
> >
> >         if (_lockHeld[0])
> >         {
> >             _lockHeld[0] = false;
> >             _mutex[0].unlock();
> >         }
> >
> >         if (_lockHeld[1])
> >         {
> >             _lockHeld[1] = false;
> >             _mutex[1].unlock();
> >         }
> >     }
> >
> >     bool                                    _graphicsThreadDoesCull;
> >     bool                                    _done;
> >     unsigned int                            _currentCull;
> >     unsigned int                            _currentDraw;
> >
> >     OpenThreads::Mutex                      _mutex[2];
> >     bool                                    _lockHeld[2];
> >     osg::observer_ptr<osgUtil::SceneView>   _sceneView[2];
> >     int                                     _frameNumber[2];
> >     osg::observer_ptr<osgDB::DatabasePager> _databasePager;
> >
> >
> > };
> >
> >
> > Viewer::Viewer()
> > {
> >     constructorInit();
> > }
> >
> > Viewer::Viewer(osg::ArgumentParser& arguments)
> > {
> >     constructorInit();
> >
> >     while (arguments.read("--SingleThreaded"))
> > setThreadingModel(SingleThreaded);
> >     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);
> >
> >     std::string colorStr;
> >     while (arguments.read("--clear-color",colorStr))
> >     {
> >         float r, g, b;
> >         float a = 1.0f;
> >         int cnt = sscanf( colorStr.c_str(), "%f,%f,%f,%f", &r, &g, &b,
> &a );
> >         if( cnt==3 || cnt==4 ) getCamera()->setClearColor(
> > osg::Vec4(r,g,b,a) );
> >         else osg::notify(osg::WARN)<<"Invalid clear color
> > \""<<colorStr<<"\""<<std::endl;
> >     }
> >
> >     int screenNum = -1;
> >     while (arguments.read("--screen",screenNum)) {}
> >
> >     int x = -1, y = -1, width = -1, height = -1;
> >     while (arguments.read("--window",x,y,width,height)) {}
> >
> >     if (width>0 && height>0)
> >     {
> >         if (screenNum>=0) setUpViewInWindow(x, y, width, height,
> screenNum);
> >         else setUpViewInWindow(x,y,width,height);
> >
> >     }
> >     else if (screenNum>=0)
> >     {
> >         setUpViewOnSingleScreen(screenNum);
> >     }
> >
> > }
> >
> > void Viewer::constructorInit()
> > {
> >     _firstFrame = true;
> >     _done = false;
> >     _keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape;
> >     _quitEventSetsDone = true;
> >     _threadingModel = AutomaticSelection;
> >     _threadsRunning = false;
> >     _useMainThreadForRenderingTraversal = true;
> >     _endBarrierPosition = AfterSwapBuffers;
> >     _numWindowsOpenAtLastSetUpThreading = 0;
> >     _startTick = 0;
> >
> >     _frameStamp = new osg::FrameStamp;
> >     _frameStamp->setFrameNumber(0);
> >     _frameStamp->setReferenceTime(0);
> >     _frameStamp->setSimulationTime(0);
> >
> >     _eventVisitor = new osgGA::EventVisitor;
> >     _eventVisitor->setActionAdapter(this);
> >
> >     setStats(new osg::Stats("Viewer"));
> > }
> >
> > Viewer::~Viewer()
> > {
> >     //osg::notify(osg::NOTICE)<<"Viewer::~Viewer()"<<std::endl;
> >
> >
> >     Threads threads;
> >     getAllThreads(threads);
> >
> >     osg::notify(osg::INFO)<<"Viewer::~Viewer():: start destructor
> getThreads
> > = "<<threads.size()<<std::endl;
> >
> >
> >     stopThreading();
> >
> >     if (_scene.valid() && _scene->getDatabasePager())
> >     {
> >         _scene->getDatabasePager()->cancel();
> >         _scene->setDatabasePager(0);
> >     }
> >
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     // clear out all the previously assigned operations
> >     for(Contexts::iterator citr = contexts.begin();
> >         citr != contexts.end();
> >         ++citr)
> >     {
> >         (*citr)->close();
> >     }
> >
> >     if (osg::Referenced::getDeleteHandler())
> >     {
> >
> osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
> >         osg::Referenced::getDeleteHandler()->flushAll();
> >     }
> >     //osg::notify(osg::NOTICE)<<"finish Viewer::~Viewer()"<<std::endl;
> >
> >     getAllThreads(threads);
> >
> >     osg::notify(osg::INFO)<<"Viewer::~Viewer() end destrcutor
> getThreads =
> > "<<threads.size()<<std::endl;
> >
> > }
> >
> > bool Viewer::isRealized() const
> > {
> >
> >     Contexts contexts;
> >     const_cast<Viewer*>(this)->getContexts(contexts);
> >
> >     unsigned int numRealizedWindows = 0;
> >
> >     // clear out all the previously assigned operations
> >     for(Contexts::iterator citr = contexts.begin();
> >         citr != contexts.end();
> >         ++citr)
> >     {
> >         if ((*citr)->isRealized()) ++numRealizedWindows;
> >     }
> >
> >     return numRealizedWindows > 0;
> > }
> >
> > 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."<<std::endl;
> >         return 1;
> >     }
> >
> >     if (!getCameraManipulator() && getCamera()->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()<runTillFrameNumber)
> >         {
> >             frame();
> >         }
> >     }
> >     else
> >     {
> >         while (!done())
> >         {
> >             frame();
> >         }
> >     }
> >
> > #endif
> >     return 0;
> > }
> >
> > void Viewer::setStartTick(osg::Timer_t tick)
> > {
> >     _startTick = tick;
> >
> >     Contexts contexts;
> >     getContexts(contexts,false);
> >
> >     getEventQueue()->setStartTick(_startTick);
> >     for(Contexts::iterator citr = contexts.begin();
> >         citr != contexts.end();
> >         ++citr)
> >     {
> >         osgViewer::GraphicsWindow* gw =
> > dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
> >         if (gw)
> >         {
> >             gw->getEventQueue()->setStartTick(_startTick);
> >         }
> >     }
> > }
> >
> >
> > void Viewer::setReferenceTime(double time)
> > {
> >     osg::Timer_t tick = osg::Timer::instance()->tick();
> >     double currentTime = osg::Timer::instance()->delta_s(_startTick,
> tick);
> >     double delta_ticks =
> > (time-currentTime)*(osg::Timer::instance()->getSecondsPerTick());
> >     if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks);
> >     else tick -= osg::Timer_t(-delta_ticks);
> >
> >     // assign the new start tick
> >     setStartTick(tick);
> > }
> >
> >
> > void Viewer::setSceneData(osg::Node* node)
> > {
> >     _scene = new osgViewer::Scene;
> >     _scene->setSceneData(node);
> >     _scene->setFrameStamp(_frameStamp.get());
> >
> >     computeActiveCoordinateSystemNodePath();
> >
> >     setReferenceTime(0.0);
> >
> >     assignSceneDataToCameras();
> >     setUpRenderingSupport();
> > }
> >
> > GraphicsWindowEmbedded* Viewer::setUpViewerAsEmbeddedInWindow(int x,
> int y,
> > int width, int height)
> > {
> >     setThreadingModel(SingleThreaded);
> >     osgViewer::GraphicsWindowEmbedded* gw = new
> > osgViewer::GraphicsWindowEmbedded(x,y,width,height);
> >     getCamera()->setViewport(new osg::Viewport(0,0,width,height));
> >     getCamera()->setGraphicsContext(gw);
> >     return gw;
> > }
> >
> > void Viewer::setThreadingModel(ThreadingModel threadingModel)
> > {
> >     if (_threadingModel == threadingModel) return;
> >
> >     if (_threadsRunning) stopThreading();
> >
> >     _threadingModel = threadingModel;
> >
> >     if (isRealized() && _threadingModel!=SingleThreaded)
> startThreading();
> > }
> >
> > void Viewer::setUpThreading()
> > {
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     _numWindowsOpenAtLastSetUpThreading = contexts.size();
> >
> >     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);
> >                 if (_scene.valid() && _scene->getDatabasePager())
> >                 {
> >
> _scene->getDatabasePager()->setProcessorAffinity(1);
> >                 }
> >             }
> >         }
> >     }
> >     else
> >     {
> >         if (!_threadsRunning) startThreading();
> >     }
> >
> > }
> >
> >
> > void Viewer::setUseMainThreadForRenderingTraversals(bool flag)
> > {
> >     if (_useMainThreadForRenderingTraversal==flag) return;
> >
> >     if (_threadsRunning) stopThreading();
> >
> >     _useMainThreadForRenderingTraversal = flag;
> >
> >     if (_threadingModel!=SingleThreaded) 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"<<std::endl;
> >
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     Cameras cameras;
> >     getCameras(cameras);
> >
> >     Contexts::iterator gcitr;
> >     Cameras::iterator citr;
> >
> >     // reset any double buffer graphics objects
> >     for(gcitr = contexts.begin();
> >         gcitr != contexts.end();
> >         ++gcitr)
> >     {
> >         osg::GraphicsContext* gc = (*gcitr);
> >
> >         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(
> > *(gc->getOperationsMutex()) );
> >         osg::GraphicsContext::OperationQueue& operations =
> > gc->getOperationsQueue();
> >         for(osg::GraphicsContext::OperationQueue::iterator oitr =
> > operations.begin();
> >             oitr != operations.end();
> >             ++oitr)
> >         {
> >             ViewerDoubleBufferedRenderingOperation* vdbro =
> > dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
> >             if (vdbro)
> >             {
> >                 vdbro->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);
> >     }
> >
> >     // reset any double buffer graphics objects
> >     for(gcitr = contexts.begin();
> >         gcitr != contexts.end();
> >         ++gcitr)
> >     {
> >         osg::GraphicsContext* gc = (*gcitr);
> >
> >         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(
> > *(gc->getOperationsMutex()) );
> >         osg::GraphicsContext::OperationQueue& operations =
> > gc->getOperationsQueue();
> >         for(osg::GraphicsContext::OperationQueue::iterator oitr =
> > operations.begin();
> >             oitr != operations.end();
> >             ++oitr)
> >         {
> >             ViewerDoubleBufferedRenderingOperation* vdbro =
> > dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
> >             if (vdbro)
> >             {
> >                 vdbro->setGraphicsThreadDoesCull( true );
> >                 vdbro->_done = 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."<<std::endl;
> > }
> >
> > // Compile operation, that compile OpenGL objects.
> > struct ViewerCompileOperation : public osg::Operation
> > {
> >     ViewerCompileOperation(osg::Node* scene):
> >         osg::Operation("Compile",false),
> >         _scene(scene)
> >     {
> >     }
> >
> >     virtual void operator () (osg::Object* object)
> >     {
> >         osg::GraphicsContext* context =
> > dynamic_cast<osg::GraphicsContext*>(object);
> >         if (!context) return;
> >
> >         // OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
> >         // osg::notify(osg::NOTICE)<<"Compile "<<context<<"
> > "<<OpenThreads::Thread::CurrentThread()<<std::endl;
> >
> >         // context->makeCurrent();
> >
> >         context->getState()->initializeExtensionProcs();
> >
> >         osgUtil::GLObjectsVisitor compileVisitor;
> >         compileVisitor.setState(context->getState());
> >
> >         // do the compile traversal
> >         if (_scene.valid()) _scene->accept(compileVisitor);
> >
> >         // osg::notify(osg::NOTICE)<<"Done Compile "<<context<<"
> > "<<OpenThreads::Thread::CurrentThread()<<std::endl;
> >     }
> >
> >     osg::ref_ptr<osg::Node> _scene;
> > };
> >
> >
> > // Draw operation, that does a draw on the scene graph.
> > struct ViewerRunOperations : public osg::Operation
> > {
> >     ViewerRunOperations():
> >         osg::Operation("RunOperation",true)
> >     {
> >     }
> >
> >     virtual void operator () (osg::Object* object)
> >     {
> >         osg::GraphicsContext* context =
> > dynamic_cast<osg::GraphicsContext*>(object);
> >         if (!context) return;
> >
> >         context->runOperations();
> >     }
> > };
> >
> > static osg::ApplicationUsageProxy
> > Viewer_e0(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREADING
> > <value>","Set the threading model using by Viewer, <value> can be
> > SingleThreaded, CullDrawThreadPerContext, DrawThreadPerContext or
> > CullThreadPerCameraDrawThreadPerContext.");
> > static osg::ApplicationUsageProxy
> > Viewer_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN
> > <value>","Set the default screen that windows should open up on.");
> > static osg::ApplicationUsageProxy
> > Viewer_e2(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_WINDOW x
> y
> > width height","Set the default window dimensions that windows should
> open up
> > on.");
> >
> > Viewer::ThreadingModel Viewer::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
> > #ifdef _WIN32
> >     // temporary hack to disable multi-threading under Windows till we
> find
> > good solutions for
> >     // crashes that users are seeing.
> >     return SingleThreaded;
> > #endif
> > #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 (numProcessors >=
> static_cast<int>(cameras.size()+contexts.size()))
> >     {
> >         return CullThreadPerCameraDrawThreadPerContext;
> >     }
> >
> > #if 1
> >         return DrawThreadPerContext;
> > #else
> >         return CullDrawThreadPerContext;
> > #endif
> > }
> >
> > void Viewer::startThreading()
> > {
> >     if (_threadsRunning) return;
> >
> >     // osg::notify(osg::NOTICE)<<"Viewer::startThreading() - starting
> > threading"<<std::endl;
> >
> >     // release any context held by the main thread.
> >     releaseContext();
> >
> >     _threadingModel = _threadingModel==AutomaticSelection ?
> > suggestBestThreadingModel() : _threadingModel;
> >
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     osg::notify(osg::INFO)<<"Viewer::startThreading() -
> > contexts.size()="<<contexts.size()<<std::endl;
> >
> >     Cameras cameras;
> >     getCameras(cameras);
> >
> >     unsigned int numThreadsOnBarrier = 0;
> >     switch(_threadingModel)
> >     {
> >         case(SingleThreaded):
> >             numThreadsOnBarrier = 1;
> >             return;
> >         case(CullDrawThreadPerContext):
> >             numThreadsOnBarrier = contexts.size()+1;
> >             break;
> >         case(DrawThreadPerContext):
> >             numThreadsOnBarrier = 1;
> >             break;
> >         case(CullThreadPerCameraDrawThreadPerContext):
> >             numThreadsOnBarrier = _useMainThreadForRenderingTraversal
> ?
> > cameras.size() : cameras.size()+1;
> >             break;
> >         default:
> >             osg::notify(osg::NOTICE)<<"Error: Threading model not
> > selected"<<std::endl;
> >             return;
> >     }
> >
> >     // using multi-threading so make sure that new objects are
> allocated
> > with thread safe ref/unref
> >     osg::Referenced::setThreadSafeReferenceCounting(true);
> >
> >     if (getSceneData())
> >     {
> >         osg::notify(osg::INFO)<<"Making scene thread safe"<<std::endl;
> >
> >         // make sure that existing scene graph objects are allocated
> with
> > thread safe ref/unref
> >         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.
> >
> >
> 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;
> >
> >     // reset any double buffer graphics objects
> >     for(citr = contexts.begin();
> >         citr != contexts.end();
> >         ++citr)
> >     {
> >         osg::GraphicsContext* gc = (*citr);
> >
> >         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(
> > *(gc->getOperationsMutex()) );
> >         osg::GraphicsContext::OperationQueue& operations =
> > gc->getOperationsQueue();
> >         for(osg::GraphicsContext::OperationQueue::iterator oitr =
> > operations.begin();
> >             oitr != operations.end();
> >             ++oitr)
> >         {
> >             ViewerDoubleBufferedRenderingOperation* vdbro =
> > dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
> >             if (vdbro)
> >             {
> >                 vdbro->setGraphicsThreadDoesCull(
> graphicsThreadsDoesCull );
> >                 vdbro->_done = false;
> >                 ++numViewerDoubleBufferedRenderingOperation;
> >             }
> >         }
> >
> >     }
> >
> >     if (_threadingModel==CullDrawThreadPerContext)
> >     {
> >         _startRenderingBarrier = 0;
> >         _endRenderingDispatchBarrier = 0;
> >         _endDynamicDrawBlock = 0;
> >     }
> >     else if (_threadingModel==DrawThreadPerContext ||
> >              _threadingModel==CullThreadPerCameraDrawThreadPerContext)
> >     {
> >         _startRenderingBarrier = 0;
> >         _endRenderingDispatchBarrier = 0;
> >         _endDynamicDrawBlock = new
> > EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation);
> >
> >         if (!osg::Referenced::getDeleteHandler())
> > osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2));
> >         else
> > osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2);
> >
> >         // now make sure the scene graph is set up with the correct
> > DataVariance to protect the dyamic elements of
> >         // the scene graph from being run in parallel.
> >        if (getSceneData())
> >           {
> >            osgUtil::Optimizer::StaticObjectDetectionVisitor sodv;
> >            getSceneData()->accept(sodv);
> >           }
> >     }
> >
> >     if (numThreadsOnBarrier>1)
> >     {
> >         _startRenderingBarrier = new
> > osg::BarrierOperation(numThreadsOnBarrier,
> > osg::BarrierOperation::NO_OPERATION);
> >         _endRenderingDispatchBarrier = new
> > osg::BarrierOperation(numThreadsOnBarrier,
> > osg::BarrierOperation::NO_OPERATION);
> >     }
> >
> >
> >     osg::ref_ptr<osg::BarrierOperation> swapReadyBarrier =
> contexts.empty()
> > ? 0 : new osg::BarrierOperation(contexts.size(),
> > osg::BarrierOperation::NO_OPERATION);
> >
> >     osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new
> > osg::SwapBuffersOperation();
> >
> >     typedef std::map<OpenThreads::Thread*, int> ThreadAffinityMap;
> >     ThreadAffinityMap threadAffinityMap;
> >
> >     unsigned int processNum = 1;
> >     for(citr = contexts.begin();
> >         citr != contexts.end();
> >         ++citr, ++processNum)
> >     {
> >         osg::GraphicsContext* gc = (*citr);
> >
> >
> >
> gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDr
> awBlock.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
> > ViewerCompileOperation(getSceneData()));
> >
> >         // add the startRenderingBarrier
> >         if (_threadingModel==CullDrawThreadPerContext &&
> > _startRenderingBarrier.valid())
> > gc->getGraphicsThread()->add(_startRenderingBarrier.get());
> >
> >         // add the rendering operation itself.
> >         gc->getGraphicsThread()->add(new ViewerRunOperations());
> >
> >         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 &&
> > numThreadsOnBarrier>1)
> >     {
> >         Cameras::iterator camItr = cameras.begin();
> >         if (_useMainThreadForRenderingTraversal) ++camItr;
> >
> >         for(;
> >             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());
> >
> >             OpenThreads::ScopedLock<OpenThreads::Mutex> lock(
> > *(gc->getOperationsMutex()) );
> >             osg::GraphicsContext::OperationQueue& operations =
> > gc->getOperationsQueue();
> >             for(osg::GraphicsContext::OperationQueue::iterator oitr =
> > operations.begin();
> >                 oitr != operations.end();
> >                 ++oitr)
> >             {
> >                 ViewerDoubleBufferedRenderingOperation* vdbro =
> > dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
> >                 if (vdbro && vdbro->getCamera()==camera)
> >                 {
> >                     camera->getCameraThread()->add(vdbro);
> >                 }
> >             }
> >
> >             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()->
> > "<<camera->getCameraThread()<<std::endl;
> >                 camera->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()
> > "<<gc->getGraphicsThread()<<std::endl;
> >             gc->getGraphicsThread()->startThread();
> >             // OpenThreads::Thread::YieldCurrentThread();
> >         }
> >     }
> >
> >     _threadsRunning = true;
> >     _numWindowsOpenAtLastSetUpThreading = contexts.size();
> >
> >     osg::notify(osg::INFO)<<"Set up threading"<<std::endl;
> > }
> >
> > void Viewer::checkWindowStatus()
> > {
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     // osg::notify(osg::NOTICE)<<"Viewer::checkWindowStatus() -
> > "<<contexts.size()<<std::endl;
> >
> >     if (contexts.size()==0)
> >     {
> >         _done = true;
> >         if (areThreadsRunning()) stopThreading();
> >     }
> > }
> >
> >
> > struct LessGraphicsContext
> > {
> >     bool operator () (const osg::GraphicsContext* lhs, const
> > osg::GraphicsContext* rhs) const
> >     {
> >         int screenLeft = lhs->getTraits()? lhs->getTraits()->screenNum
> : 0;
> >         int screenRight = rhs->getTraits()?
> rhs->getTraits()->screenNum : 0;
> >         if (screenLeft < screenRight) return true;
> >         if (screenLeft > screenRight) return false;
> >
> >         screenLeft = lhs->getTraits()? lhs->getTraits()->x : 0;
> >         screenRight = rhs->getTraits()? rhs->getTraits()->x : 0;
> >         if (screenLeft < screenRight) return true;
> >         if (screenLeft > screenRight) return false;
> >
> >         screenLeft = lhs->getTraits()? lhs->getTraits()->y : 0;
> >         screenRight = rhs->getTraits()? rhs->getTraits()->y : 0;
> >         if (screenLeft < screenRight) return true;
> >         if (screenLeft > screenRight) return false;
> >
> >         return lhs < rhs;
> >     }
> > };
> >
> > void Viewer::getContexts(Contexts& contexts, bool onlyValid)
> > {
> >     typedef std::set<osg::GraphicsContext*> ContextSet;
> >     ContextSet contextSet;
> >
> >     if (_camera.valid() &&
> >         _camera->getGraphicsContext() &&
> >         (_camera->getGraphicsContext()->valid() || !onlyValid))
> >     {
> >         contextSet.insert(_camera->getGraphicsContext());
> >     }
> >
> >     for(unsigned int i=0; i<getNumSlaves(); ++i)
> >     {
> >         Slave& slave = getSlave(i);
> >         if (slave._camera.valid() &&
> >             slave._camera->getGraphicsContext() &&
> >             (slave._camera->getGraphicsContext()->valid() ||
> !onlyValid))
> >         {
> >             contextSet.insert(slave._camera->getGraphicsContext());
> >         }
> >     }
> >
> >     contexts.clear();
> >     contexts.reserve(contextSet.size());
> >
> >     for(ContextSet::iterator itr = contextSet.begin();
> >         itr != contextSet.end();
> >         ++itr)
> >     {
> >         contexts.push_back(const_cast<osg::GraphicsContext*>(*itr));
> >     }
> >
> >     if (contexts.size()>=2)
> >     {
> >         std::sort(contexts.begin(), contexts.end(),
> LessGraphicsContext());
> >     }
> > }
> >
> > 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<osgViewer::GraphicsWindow*>(*itr);
> >         if (gw) windows.push_back(gw);
> >     }
> > }
> >
> > void Viewer::getCameras(Cameras& cameras, bool onlyActive)
> > {
> >     cameras.clear();
> >
> >     if (!onlyActive || (_camera->getGraphicsContext() &&
> > _camera->getGraphicsContext()->valid()) )
> cameras.push_back(_camera.get());
> >
> >     for(Slaves::iterator itr = _slaves.begin();
> >         itr != _slaves.end();
> >         ++itr)
> >     {
> >         if (!onlyActive || (itr->_camera->getGraphicsContext() &&
> > itr->_camera->getGraphicsContext()->valid()) )
> > cameras.push_back(itr->_camera.get());
> >     }
> >
> > }
> >
> > void Viewer::getAllThreads(Threads& threads, bool onlyActive)
> > {
> >     OperationsThreads operationsThreads;
> >     getOperationsThreads(operationsThreads);
> >
> >     for(OperationsThreads::iterator itr = operationsThreads.begin();
> >         itr != operationsThreads.end();
> >         ++itr)
> >     {
> >         threads.push_back(*itr);
> >     }
> >
> >     if (_scene.valid() &&
> >         _scene->getDatabasePager() &&
> >        (!onlyActive || _scene->getDatabasePager()->isRunning()))
> >     {
> >         threads.push_back(_scene->getDatabasePager());
> >     }
> > }
> >
> >
> > void Viewer::getOperationsThreads(OperationsThreads& 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::setUpRenderingSupport()
> > {
> >     bool threadsRunningBeforeSetUpRenderingSupport = _threadsRunning;
> >     if (_threadsRunning) stopThreading();
> >
> >     _sceneViews.clear();
> >
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     osg::FrameStamp* frameStamp = getFrameStamp();
> >     osg::DisplaySettings* ds = _displaySettings.valid() ?
> > _displaySettings.get() : osg::DisplaySettings::instance();
> >     osgDB::DatabasePager* dp = _scene.valid() ?
> _scene->getDatabasePager() :
> > 0;
> >
> >     bool graphicsThreadDoesCull =
> > _threadingModel!=CullThreadPerCameraDrawThreadPerContext;
> >     unsigned int numViewerDoubleBufferedRenderingOperation = 0;
> >
> >     Cameras localCameras;
> >     getCameras(localCameras);
> >
> >     unsigned int sceneViewOptions = osgUtil::SceneView::HEADLIGHT;
> >
> >     if
> (true)//(_threadingModel==CullThreadPerCameraDrawThreadPerContext)
> >     {
> >         for(Contexts::iterator gcitr = contexts.begin();
> >             gcitr != contexts.end();
> >             ++gcitr)
> >         {
> >             (*gcitr)->removeAllOperations();
> >
> >             osg::GraphicsContext* gc = *gcitr;
> >             osg::GraphicsContext::Cameras& cameras = gc->getCameras();
> >             osg::State* state = gc->getState();
> >             if (dp)
> > dp->setCompileGLObjectsForContextID(state->getContextID(), true);
> >
> >             for(osg::GraphicsContext::Cameras::iterator citr =
> > cameras.begin();
> >                 citr != cameras.end();
> >                 ++citr)
> >             {
> >                 osg::Camera* camera = *citr;
> >                 if (!camera->getStats()) camera->setStats(new
> > osg::Stats("Camera"));
> >
> >                 bool localCamera =
> > std::find(localCameras.begin(),localCameras.end(),camera) !=
> > localCameras.end();
> >                 if (localCamera)
> >                 {
> >                     osgUtil::SceneView* sceneViewList[2];
> >
> >                     for(int i=0; i<2; ++i)
> >                     {
> >                         osgUtil::SceneView* sceneView = new
> > osgUtil::SceneView;
> >
> >                         _sceneViews.push_back(sceneView);
> >                         sceneViewList[i] = sceneView;
> >
> >
> > sceneView->setGlobalStateSet(_camera->getStateSet());
> >                         sceneView->setDefaults(sceneViewOptions);
> >
> > sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ?
> > camera->getDisplaySettings() : ds);
> >                         sceneView->setCamera(camera);
> >                         sceneView->setState(state);
> >                         sceneView->setFrameStamp(frameStamp);
> >                     }
> >
> >
> >                     // osg::notify(osg::NOTICE)<<"localCamera
> > "<<camera->getName()<<std::endl;
> >                     ViewerDoubleBufferedRenderingOperation* vdbro =
> new
> > ViewerDoubleBufferedRenderingOperation(graphicsThreadDoesCull,
> > sceneViewList[0], sceneViewList[1], dp, _startTick);
> >                     gc->add(vdbro);
> >                     ++numViewerDoubleBufferedRenderingOperation;
> >                 }
> >                 else
> >                 {
> >                     // osg::notify(osg::NOTICE)<<"non local
> > Camera"<<std::endl;
> >
> >                     osgUtil::SceneView* sceneView = new
> osgUtil::SceneView;
> >
> >                     _sceneViews.push_back(sceneView);
> >
> >
> sceneView->setGlobalStateSet(_camera->getStateSet());
> >                     sceneView->setDefaults(sceneViewOptions);
> >                     sceneView->setDisplaySettings(ds);
> >                     sceneView->setCamera(camera);
> >
> > sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ?
> > camera->getDisplaySettings() : ds);
> >                     sceneView->setState(state);
> >                     sceneView->setFrameStamp(frameStamp);
> >
> >                     ViewerRenderingOperation* vro = new
> > ViewerRenderingOperation(sceneView, dp, _startTick);
> >                     gc->add(vro);
> >                 }
> >
> >             }
> >         }
> >     }
> >     else
> >     {
> >         for(Contexts::iterator gcitr = contexts.begin();
> >             gcitr != contexts.end();
> >             ++gcitr)
> >         {
> >             (*gcitr)->removeAllOperations();
> >
> >             osg::GraphicsContext* gc = *gcitr;
> >             osg::GraphicsContext::Cameras& cameras = gc->getCameras();
> >             osg::State* state = gc->getState();
> >
> >             for(osg::GraphicsContext::Cameras::iterator citr =
> > cameras.begin();
> >                 citr != cameras.end();
> >                 ++citr)
> >             {
> >                 osg::Camera* camera = *citr;
> >
> >                 if (!camera->getStats()) camera->setStats(new
> > osg::Stats("Camera"));
> >
> >                 osgUtil::SceneView* sceneView = new
> osgUtil::SceneView;
> >                 _sceneViews.push_back(sceneView);
> >
> >                 sceneView->setGlobalStateSet(_camera->getStateSet());
> >                 sceneView->setDefaults(sceneViewOptions);
> >
> > sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ?
> > camera->getDisplaySettings() : ds);
> >                 sceneView->setCamera(camera);
> >                 sceneView->setState(state);
> >                 sceneView->setFrameStamp(frameStamp);
> >
> >                 if (dp)
> > dp->setCompileGLObjectsForContextID(state->getContextID(), true);
> >
> >                 gc->add(new ViewerRenderingOperation(sceneView, dp,
> > _startTick));
> >
> >                 ++numViewerDoubleBufferedRenderingOperation;
> >             }
> >         }
> >     }
> >
> >     if (_endDynamicDrawBlock.valid())
> >     {
> >
> >
> _endDynamicDrawBlock->setNumOfBlocks(numViewerDoubleBufferedRenderingOpe
> ration);
> >     }
> >
> >     if (threadsRunningBeforeSetUpRenderingSupport) startThreading();
> > }
> >
> >
> > void Viewer::realize()
> > {
> >     //osg::notify(osg::INFO)<<"Viewer::realize()"<<std::endl;
> >
> >     setCameraWithFocus(0);
> >
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     if (contexts.empty())
> >     {
> >         osg::notify(osg::INFO)<<"Viewer::realize() - No valid contexts
> > found, setting up view across all screens."<<std::endl;
> >
> >         // no windows are already set up so set up a default view
> >
> >         const char* ptr = 0;
> >         int screenNum = -1;
> >         if ((ptr = getenv("OSG_SCREEN")) != 0)
> >         {
> >             if (strlen(ptr)!=0) screenNum = atoi(ptr);
> >             else screenNum = -1;
> >         }
> >
> >         int x = -1, y = -1, width = -1, height = -1;
> >         if ((ptr = getenv("OSG_WINDOW")) != 0)
> >         {
> >             std::istringstream iss(ptr);
> >             iss >> x >> y >> width >> height;
> >         }
> >
> >         if (width>0 && height>0)
> >         {
> >             if (screenNum>=0) setUpViewInWindow(x, y, width, height,
> > screenNum);
> >             else setUpViewInWindow(x,y,width,height);
> >         }
> >         else if (screenNum>=0)
> >         {
> >             setUpViewOnSingleScreen(screenNum);
> >         }
> >         else
> >         {
> >             setUpViewAcrossAllScreens();
> >         }
> >
> >         getContexts(contexts);
> >     }
> >
> >     if (contexts.empty())
> >     {
> >         osg::notify(osg::NOTICE)<<"Viewer::realize() - failed to set
> up any
> > windows"<<std::endl;
> >         _done = true;
> >         return;
> >     }
> >
> >     setUpRenderingSupport();
> >
> >     for(Contexts::iterator citr = contexts.begin();
> >         citr != contexts.end();
> >         ++citr)
> >     {
> >         osg::GraphicsContext* gc = *citr;
> >         gc->realize();
> >
> >         if (_realizeOperation.valid() && gc->valid())
> >         {
> >             gc->makeCurrent();
> >
> >             (*_realizeOperation)(gc);
> >
> >             gc->releaseContext();
> >         }
> >     }
> >
> >     bool grabFocus = true;
> >     if (grabFocus)
> >     {
> >         for(Contexts::iterator citr = contexts.begin();
> >             citr != contexts.end();
> >             ++citr)
> >         {
> >             osgViewer::GraphicsWindow* gw =
> > dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
> >             if (gw)
> >             {
> >                 gw->grabFocusIfPointerInWindow();
> >             }
> >         }
> >     }
> >
> >     // initialize the global timer to be relative to the current time.
> >     osg::Timer::instance()->setStartTick();
> >
> >     // pass on the start tick to all the associated eventqueues
> >     setStartTick(osg::Timer::instance()->getStartTick());
> >
> >     setUpThreading();
> > }
> >
> >
> > void Viewer::frame(double simulationTime)
> > {
> >     if (_done) return;
> >
> >     //
> >
> osg::notify(osg::NOTICE)<<std::endl<<"Viewer::frame()"<<std::endl<<std::
> endl;
> >
> >     if (_firstFrame)
> >     {
> >         init();
> >
> >         if (!isRealized())
> >         {
> >             realize();
> >         }
> >
> >         _firstFrame = false;
> >     }
> >     advance(simulationTime);
> >
> >     eventTraversal();
> >     updateTraversal();
> >     renderingTraversals();
> > }
> >
> > void Viewer::advance(double simulationTime)
> > {
> >     if (_done) return;
> >
> >     double prevousReferenceTime = _frameStamp->getReferenceTime();
> >     int previousFrameNumber = _frameStamp->getFrameNumber();
> >
> >     _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
> >
> >     _frameStamp->setReferenceTime(
> > osg::Timer::instance()->delta_s(_startTick,
> osg::Timer::instance()->tick())
> > );
> >
> >     if (simulationTime==USE_REFERENCE_TIME)
> >     {
> >
> _frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
> >     }
> >     else
> >     {
> >         _frameStamp->setSimulationTime(simulationTime);
> >     }
> >
> >     if (getStats() && getStats()->collectStats("frame_rate"))
> >     {
> >         // update previous frame stats
> >         double deltaFrameTime = _frameStamp->getReferenceTime() -
> > prevousReferenceTime;
> >         getStats()->setAttribute(previousFrameNumber, "Frame
> duration",
> > deltaFrameTime);
> >         getStats()->setAttribute(previousFrameNumber, "Frame rate",
> > 1.0/deltaFrameTime);
> >
> >         // update current frames stats
> >         getStats()->setAttribute(_frameStamp->getFrameNumber(),
> "Reference
> > time", _frameStamp->getReferenceTime());
> >     }
> >
> >     if (osg::Referenced::getDeleteHandler())
> >     {
> >         osg::Referenced::getDeleteHandler()->flush();
> >
> >
> osg::Referenced::getDeleteHandler()->setFrameNumber(_frameStamp->getFram
> eNumber());
> >     }
> >
> > }
> >
> > void Viewer::eventTraversal()
> > {
> >     if (_done) return;
> >
> >     double beginEventTraversal =
> osg::Timer::instance()->delta_s(_startTick,
> > osg::Timer::instance()->tick());
> >
> >     //
> > osg::notify(osg::NOTICE)<<"Viewer::frameEventTraversal()."<<std::endl;
> >
> >     // need to copy events from the GraphicsWindow's into local
> EventQueue;
> >     osgGA::EventQueue::Events events;
> >
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     osgGA::GUIEventAdapter* eventState =
> > getEventQueue()->getCurrentEventState();
> >     osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() *
> > getCamera()->getProjectionMatrix();
> >     if (getCamera()->getViewport())
> >     {
> >         osg::Viewport* viewport = getCamera()->getViewport();
> >         masterCameraVPW *= viewport->computeWindowMatrix();
> >         eventState->setInputRange( viewport->x(), viewport->y(),
> > viewport->x() + viewport->width(), viewport->y() +
> viewport->height());
> >     }
> >     else
> >     {
> >         eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
> >     }
> >
> >
> >     for(Contexts::iterator citr = contexts.begin();
> >         citr != contexts.end();
> >         ++citr)
> >     {
> >         osgViewer::GraphicsWindow* gw =
> > dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
> >         if (gw)
> >         {
> >             gw->checkEvents();
> >
> >             osgGA::EventQueue::Events gw_events;
> >             gw->getEventQueue()->takeEvents(gw_events);
> >
> >             osgGA::EventQueue::Events::iterator itr;
> >             for(itr = gw_events.begin();
> >                 itr != gw_events.end();
> >                 ++itr)
> >             {
> >                 osgGA::GUIEventAdapter* event = itr->get();
> >
> >                 bool pointerEvent = false;
> >
> >                 float x = event->getX();
> >                 float y = event->getY();
> >
> >                 bool invert_y =
> >
> event->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWN
> WARDS;
> >                 if (invert_y && gw->getTraits()) y =
> gw->getTraits()->height
> > - y;
> >
> >                 switch(event->getEventType())
> >                 {
> >                     case(osgGA::GUIEventAdapter::PUSH):
> >                     case(osgGA::GUIEventAdapter::RELEASE):
> >                     case(osgGA::GUIEventAdapter::DRAG):
> >                     case(osgGA::GUIEventAdapter::MOVE):
> >                     {
> >                         pointerEvent = true;
> >
> >                         if
> > (event->getEventType()!=osgGA::GUIEventAdapter::DRAG ||
> > !getCameraWithFocus())
> >                         {
> >                             osg::GraphicsContext::Cameras& cameras =
> > gw->getCameras();
> >
> for(osg::GraphicsContext::Cameras::iterator citr
> > = cameras.begin();
> >                                 citr != cameras.end();
> >                                 ++citr)
> >                             {
> >                                 osg::Camera* camera = *citr;
> >                                 if (camera->getView()==this &&
> >                                     camera->getAllowEventFocus() &&
> >
> > camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
> >                                 {
> >                                     osg::Viewport* viewport = camera ?
> > camera->getViewport() : 0;
> >                                     if (viewport &&
> >                                         x >= viewport->x() && y >=
> > viewport->y() &&
> >                                         x <=
> > (viewport->x()+viewport->width()) && y <=
> (viewport->y()+viewport->height())
> > )
> >                                     {
> >                                         //
> > osg::notify(osg::NOTICE)<<"setCamera with focus
> "<<camera->getName()<<"
> > x="<<x<<" y="<<y<<std::endl;
> >                                         setCameraWithFocus(camera);
> >                                     }
> >                                 }
> >                             }
> >                         }
> >
> >                         break;
> >                     }
> >                     default:
> >                         break;
> >                 }
> >
> >                 if (pointerEvent)
> >                 {
> >                     if (getCameraWithFocus())
> >                     {
> >                         osg::Viewport* viewport =
> > getCameraWithFocus()->getViewport();
> >                         osg::Matrix localCameraVPW =
> > getCameraWithFocus()->getViewMatrix() *
> > getCameraWithFocus()->getProjectionMatrix();
> >                         if (viewport) localCameraVPW *=
> > viewport->computeWindowMatrix();
> >
> >                         osg::Matrix matrix(
> > osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
> >
> >                         osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) *
> matrix;
> >
> >                         x = new_coord.x();
> >                         y = new_coord.y();
> >
> >                         // osg::notify(osg::NOTICE)<<"pointer event
> > new_coord.x()="<<new_coord.x()<<"
> new_coord.y()="<<new_coord.y()<<std::endl;
> >
> >                         event->setInputRange(eventState->getXmin(),
> > eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
> >                         event->setX(x);
> >                         event->setY(y);
> >
> >
> event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS
> );
> >
> >                     }
> >                     else
> >                     {
> >                         x = eventState->getXmin() +
> > (x/double(gw->getTraits()->width))*(eventState->getXmax() -
> > eventState->getXmin());
> >                         y = eventState->getYmin() +
> > (y/double(gw->getTraits()->height))*(eventState->getYmax() -
> > eventState->getYmin());
> >                         // osg::notify(osg::NOTICE)<<"new x = "<<x<<"
> new y
> > = "<<y<<std::endl;
> >
> >                         event->setInputRange(eventState->getXmin(),
> > eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
> >                         event->setX(x);
> >                         event->setY(y);
> >
> >
> event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS
> );
> >                     }
> >
> >                     // pass along the new pointer events details to
> the
> > eventState of the viewer
> >                     eventState->setX(x);
> >                     eventState->setY(y);
> >                     eventState->setButtonMask(event->getButtonMask());
> >
> >
> eventState->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UP
> WARDS);
> >
> >                 }
> >                 else
> >                 {
> >                     event->setInputRange(eventState->getXmin(),
> > eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
> >                     event->setX(eventState->getX());
> >                     event->setY(eventState->getY());
> >                     event->setButtonMask(eventState->getButtonMask());
> >
> > event->setMouseYOrientation(eventState->getMouseYOrientation());
> >                 }
> >                 //osg::notify(osg::NOTICE)<<"   mouse x =
> > "<<event->getX()<<" y="<<event->getY()<<std::endl;
> >                 // osg::notify(osg::NOTICE)<<"   mouse Xmin =
> > "<<event->getXmin()<<" Ymin="<<event->getYmin()<<"
> > xMax="<<event->getXmax()<<" Ymax="<<event->getYmax()<<std::endl;
> >             }
> >
> >             for(itr = gw_events.begin();
> >                 itr != gw_events.end();
> >                 ++itr)
> >             {
> >                 osgGA::GUIEventAdapter* event = itr->get();
> >                 switch(event->getEventType())
> >                 {
> >                     case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
> >                     {
> >                         bool wasThreading = areThreadsRunning();
> >                         if (wasThreading) stopThreading();
> >
> >                         gw->close();
> >
> >                         if (wasThreading) startThreading();
> >
> >                         break;
> >                     }
> >                     default:
> >                         break;
> >                 }
> >             }
> >
> >             events.insert(events.end(), gw_events.begin(),
> gw_events.end());
> >
> >         }
> >     }
> >
> >
> >     // osg::notify(osg::NOTICE)<<"mouseEventState Xmin =
> > "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<"
> > xMax="<<eventState->getXmax()<<"
> Ymax="<<eventState->getYmax()<<std::endl;
> >
> >
> >     _eventQueue->frame( getFrameStamp()->getReferenceTime() );
> >     _eventQueue->takeEvents(events);
> >
> >
> > #if 0
> >     // osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
> >     for(osgGA::EventQueue::Events::iterator itr = events.begin();
> >         itr != events.end();
> >         ++itr)
> >     {
> >         osgGA::GUIEventAdapter* event = itr->get();
> >         switch(event->getEventType())
> >         {
> >             case(osgGA::GUIEventAdapter::PUSH):
> >                 osg::notify(osg::NOTICE)<<"  PUSH
> "<<event->getButton()<<"
> > x="<<event->getX()<<" y="<<event->getY()<<std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::RELEASE):
> >                 osg::notify(osg::NOTICE)<<"  RELEASE
> > "<<event->getButton()<<" x="<<event->getX()<<"
> > y="<<event->getY()<<std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::DRAG):
> >                 osg::notify(osg::NOTICE)<<"  DRAG
> > "<<event->getButtonMask()<<" x="<<event->getX()<<"
> > y="<<event->getY()<<std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::MOVE):
> >                 osg::notify(osg::NOTICE)<<"  MOVE
> > "<<event->getButtonMask()<<" x="<<event->getX()<<"
> > y="<<event->getY()<<std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::SCROLL):
> >                 osg::notify(osg::NOTICE)<<"  SCROLL
> > "<<event->getScrollingMotion()<<std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::KEYDOWN):
> >                 osg::notify(osg::NOTICE)<<"  KEYDOWN
> > '"<<(char)event->getKey()<<"'"<<std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::KEYUP):
> >                 osg::notify(osg::NOTICE)<<"  KEYUP
> > '"<<(char)event->getKey()<<"'"<<std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::RESIZE):
> >                 osg::notify(osg::NOTICE)<<"  RESIZE
> > "<<event->getWindowX()<<"/"<<event->getWindowY()<<" x
> > "<<event->getWindowWidth()<<"/"<<event->getWindowHeight() <<
> std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
> >                 osg::notify(osg::NOTICE)<<"  QUIT_APPLICATION " <<
> > std::endl;
> >                 break;
> >             case(osgGA::GUIEventAdapter::FRAME):
> >                 // osg::notify(osg::NOTICE)<<"  FRAME "<<std::endl;
> >                 break;
> >             default:
> >                 // osg::notify(osg::NOTICE)<<"  Event not
> > handled"<<std::endl;
> >                 break;
> >         }
> >     }
> > #endif
> >
> >     // osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
> >
> >     if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
> >     {
> >         for(osgGA::EventQueue::Events::iterator itr = events.begin();
> >             itr != events.end();
> >             ++itr)
> >         {
> >             osgGA::GUIEventAdapter* event = itr->get();
> >             switch(event->getEventType())
> >             {
> >                 case(osgGA::GUIEventAdapter::KEYUP):
> >                     if (_keyEventSetsDone &&
> > event->getKey()==_keyEventSetsDone) _done = true;
> >                     break;
> >
> >                 case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
> >                     if (_quitEventSetsDone) _done = true;
> >                     break;
> >
> >                 default:
> >                     break;
> >             }
> >         }
> >     }
> >
> >     if (_done) return;
> >
> >     for(osgGA::EventQueue::Events::iterator itr = events.begin();
> >         itr != events.end();
> >         ++itr)
> >     {
> >         osgGA::GUIEventAdapter* event = itr->get();
> >
> >         for(EventHandlers::iterator hitr = _eventHandlers.begin();
> >             hitr != _eventHandlers.end();
> >             ++hitr)
> >         {
> >             if ((*hitr)->handle( *event, *this, 0, 0))
> > event->setHandled(true);
> >         }
> >
> >         if (_cameraManipulator.valid())
> >         {
> >             if (_cameraManipulator->handle( *event, *this))
> > event->setHandled(true);
> >         }
> >
> >     }
> >
> >     if (_eventVisitor.valid() && _scene.valid())
> >     {
> >         _eventVisitor->setFrameStamp(getFrameStamp());
> >
> > _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
> >
> >         for(osgGA::EventQueue::Events::iterator itr = events.begin();
> >             itr != events.end();
> >             ++itr)
> >         {
> >             osgGA::GUIEventAdapter* event = itr->get();
> >
> >             _eventVisitor->reset();
> >             _eventVisitor->addEvent( event );
> >
> >             getSceneData()->accept(*_eventVisitor);
> >
> >             // call any camera update callbacks, but only traverse
> that
> > callback, don't traverse its subgraph
> >             // leave that to the scene update traversal.
> >             osg::NodeVisitor::TraversalMode tm =
> > _eventVisitor->getTraversalMode();
> >
> > _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
> >
> >             if (_camera.valid() && _camera->getEventCallback())
> > _camera->accept(*_eventVisitor);
> >
> >             for(unsigned int i=0; i<getNumSlaves(); ++i)
> >             {
> >                 osg::Camera* camera = getSlave(i)._camera.get();
> >                 if (camera && camera->getEventCallback())
> > camera->accept(*_eventVisitor);
> >             }
> >
> >             _eventVisitor->setTraversalMode(tm);
> >
> >         }
> >     }
> >
> >     if (getStats() && getStats()->collectStats("event"))
> >     {
> >         double endEventTraversal =
> > osg::Timer::instance()->delta_s(_startTick,
> osg::Timer::instance()->tick());
> >
> >         // update current frames stats
> >         getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event
> > traversal begin time", beginEventTraversal);
> >         getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event
> > traversal end time", endEventTraversal);
> >         getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event
> > traversal time taken", endEventTraversal-beginEventTraversal);
> >     }
> >
> >
> > }
> >
> > void Viewer::updateTraversal()
> > {
> >     if (_done) return;
> >
> >     double beginUpdateTraversal =
> > osg::Timer::instance()->delta_s(_startTick,
> osg::Timer::instance()->tick());
> >
> >     // do the update traversal of the scene.
> >     if (_scene.valid()) _scene->updateTraversal();
> >
> >     osgUtil::UpdateVisitor* uv = _scene.valid() ?
> _scene->getUpdateVisitor()
> > : 0;
> >     if (uv)
> >     {
> >         // call any camera update callbacks, but only traverse that
> > callback, don't traverse its subgraph
> >         // leave that to the scene update traversal.
> >         osg::NodeVisitor::TraversalMode tm = uv->getTraversalMode();
> >         uv->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
> >
> >         if (_camera.valid() && _camera->getUpdateCallback())
> > _camera->accept(*uv);
> >
> >         for(unsigned int i=0; i<getNumSlaves(); ++i)
> >         {
> >             osg::Camera* camera = getSlave(i)._camera.get();
> >             if (camera && camera->getUpdateCallback())
> camera->accept(*uv);
> >         }
> >
> >         uv->setTraversalMode(tm);
> >     }
> >
> >     if (_cameraManipulator.valid())
> >     {
> >         setFusionDistance(
> getCameraManipulator()->getFusionDistanceMode(),
> >
> getCameraManipulator()->getFusionDistanceValue()
> > );
> >
> >
> _camera->setViewMatrix(_cameraManipulator->getInverseMatrix());
> >     }
> >
> >     updateSlaves();
> >
> >     if (getStats() && getStats()->collectStats("update"))
> >     {
> >         double endUpdateTraversal =
> > osg::Timer::instance()->delta_s(_startTick,
> osg::Timer::instance()->tick());
> >
> >         // update current frames stats
> >         getStats()->setAttribute(_frameStamp->getFrameNumber(),
> "Update
> > traversal begin time", beginUpdateTraversal);
> >         getStats()->setAttribute(_frameStamp->getFrameNumber(),
> "Update
> > traversal end time", endUpdateTraversal);
> >         getStats()->setAttribute(_frameStamp->getFrameNumber(),
> "Update
> > traversal time taken", endUpdateTraversal-beginUpdateTraversal);
> >     }
> > }
> >
> > void Viewer::renderingTraversals()
> > {
> >     // check to see if windows are still valid
> >     checkWindowStatus();
> >
> >     if (_done) return;
> >
> >     double beginRenderingTraversals =
> > osg::Timer::instance()->delta_s(_startTick,
> osg::Timer::instance()->tick());
> >
> >     osgDB::DatabasePager* dp = _scene.valid() ?
> _scene->getDatabasePager() :
> > 0;
> >     if (dp)
> >     {
> >         dp->signalBeginFrame(getFrameStamp());
> >     }
> >
> >     // osg::notify(osg::NOTICE)<<std::endl<<"Joing
> _startRenderingBarrier
> > block"<<std::endl;
> >
> >
> >     Contexts contexts;
> >     getContexts(contexts);
> >
> >     Contexts::iterator itr;
> >
> >     // dispatch the the rendering threads
> >     if (_startRenderingBarrier.valid())
> _startRenderingBarrier->block();
> >
> >     if (_endDynamicDrawBlock.valid())
> >     {
> >         _endDynamicDrawBlock->reset();
> >     }
> >
> >     // reset any double buffer graphics objects
> >     for(itr = contexts.begin();
> >         itr != contexts.end();
> >         ++itr)
> >     {
> >         osg::GraphicsContext* gc = (*itr);
> >
> >         OpenThreads::ScopedLock<OpenThreads::Mutex> lock(
> > *(gc->getOperationsMutex()) );
> >         osg::GraphicsContext::OperationQueue& operations =
> > gc->getOperationsQueue();
> >         for(osg::GraphicsContext::OperationQueue::iterator oitr =
> > operations.begin();
> >             oitr != operations.end();
> >             ++oitr)
> >         {
> >             ViewerDoubleBufferedRenderingOperation* vdbro =
> > dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
> >             if (vdbro)
> >             {
> >                 if (!vdbro->getGraphicsThreadDoesCull() &&
> > !(vdbro->getCamera()->getCameraThread()))
> >                 {
> >                     vdbro->cull();
> >                 }
> >             }
> >         }
> >     }
> >
> >     for(itr = contexts.begin();
> >         itr != contexts.e