root/OpenSceneGraph/trunk/src/osgViewer/Viewer.cpp @ 7017

Revision 7017, 77.4 kB (checked in by robert, 7 years ago)

Added ability to compile OpenGL objects via pbuffers in the DatabasePager/Viewer?

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osg/GLExtensions>
15#include <osg/DeleteHandler>
16#include <osgUtil/Optimizer>
17#include <osgUtil/GLObjectsVisitor>
18#include <osgDB/Registry>
19#include <osgGA/TrackballManipulator>
20#include <osgViewer/Viewer>
21
22#include <osg/io_utils>
23
24#include <sstream>
25
26using namespace osgViewer;
27
28
29class ViewerQuerySupport
30{
31public:
32    ViewerQuerySupport(osg::Timer_t startTick):
33        _startTick(startTick),
34        _initialized(false),
35        _timerQuerySupported(false),
36        _extensions(0),
37        _previousQueryTime(0.0)
38    {
39    }
40       
41    typedef std::pair<GLuint, int> QueryFrameNumberPair;
42    typedef std::list<QueryFrameNumberPair> QueryFrameNumberList;
43    typedef std::vector<GLuint> QueryList;
44
45    inline void checkQuery(osg::Stats* stats)
46    {
47        for(QueryFrameNumberList::iterator itr = _queryFrameNumberList.begin();
48            itr != _queryFrameNumberList.end();
49            )
50        {
51            GLuint query = itr->first;
52            GLint available = 0;
53            _extensions->glGetQueryObjectiv(query, GL_QUERY_RESULT_AVAILABLE, &available);
54            if (available)
55            {
56                GLuint64EXT timeElapsed = 0;
57                _extensions->glGetQueryObjectui64v(query, GL_QUERY_RESULT, &timeElapsed);
58
59                double timeElapsedSeconds = double(timeElapsed)*1e-9;
60                double currentTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
61                double estimatedEndTime = (_previousQueryTime + currentTime) * 0.5;
62                double estimatedBeginTime = estimatedEndTime - timeElapsedSeconds;
63
64                stats->setAttribute(itr->second, "GPU draw begin time", estimatedBeginTime);
65                stats->setAttribute(itr->second, "GPU draw end time", estimatedEndTime);
66                stats->setAttribute(itr->second, "GPU draw time taken", timeElapsedSeconds);
67               
68
69                itr = _queryFrameNumberList.erase(itr);
70                _availableQueryObjects.push_back(query);
71            }
72            else
73            {
74                ++itr;
75            }
76           
77        }
78        _previousQueryTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
79    }
80   
81    inline GLuint createQueryObject()
82    {
83        if (_availableQueryObjects.empty())
84        {
85            GLuint query;
86            _extensions->glGenQueries(1, &query);
87            return query;
88        }
89        else
90        {
91            GLuint query = _availableQueryObjects.back();
92            _availableQueryObjects.pop_back();
93            return query;
94        }
95    }
96   
97    inline void beginQuery(int frameNumber)
98    {
99        GLuint query = createQueryObject();
100        _extensions->glBeginQuery(GL_TIME_ELAPSED, query);
101        _queryFrameNumberList.push_back(QueryFrameNumberPair(query, frameNumber));       
102    }
103   
104    inline void endQuery()
105    {
106        _extensions->glEndQuery(GL_TIME_ELAPSED);
107    }
108   
109    void initialize(osg::State* state)
110    {
111        if (_initialized) return;
112
113        _initialized = true;
114        _extensions = osg::Drawable::getExtensions(state->getContextID(),true);
115        _timerQuerySupported = _extensions && _extensions->isTimerQuerySupported();
116        _previousQueryTime = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
117    }
118   
119    osg::Timer_t                                _startTick;
120    bool                                        _initialized;
121    bool                                        _timerQuerySupported;
122    const osg::Drawable::Extensions*            _extensions;
123    QueryFrameNumberList                        _queryFrameNumberList;
124    QueryList                                   _availableQueryObjects;
125    double                                      _previousQueryTime;
126
127};
128
129
130// Draw operation, that does a draw on the scene graph.
131struct ViewerRenderingOperation : public osg::Operation, public ViewerQuerySupport
132{
133    ViewerRenderingOperation(osgUtil::SceneView* sceneView, osgDB::DatabasePager* databasePager, osg::Timer_t startTick):
134        osg::Operation("Render",true),
135        ViewerQuerySupport(startTick),
136        _sceneView(sceneView),
137        _databasePager(databasePager)
138    {
139        _sceneView->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
140    }
141   
142    osg::Camera* getCamera() { return _sceneView->getCamera(); }
143
144    virtual void operator () (osg::Object*)
145    {
146        if (!_sceneView) return;
147
148        // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
149
150        osg::Stats* stats = _sceneView->getCamera()->getStats();
151        osg::State* state = _sceneView->getState();
152        const osg::FrameStamp* fs = state->getFrameStamp();
153        int frameNumber = fs ? fs->getFrameNumber() : 0;
154
155        if (!_initialized)
156        {
157            initialize(state);
158        }
159       
160        bool aquireGPUStats = stats && _timerQuerySupported && stats->collectStats("gpu");
161
162        if (aquireGPUStats)
163        {
164            checkQuery(stats);
165        }
166       
167        // do cull taversal
168        osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
169       
170        // pass on the fusion distance settings from the View to the SceneView
171        osgViewer::View* view = dynamic_cast<osgViewer::View*>(_sceneView->getCamera()->getView());
172        if (view) _sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
173
174        _sceneView->inheritCullSettings(*(_sceneView->getCamera()));
175       
176        _sceneView->cull();
177       
178       
179        osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
180
181#if 0
182        if (_sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
183        {
184            osg::notify(osg::NOTICE)<<"Completed in ViewerRenderingOperation"<<std::endl;
185            state->getDynamicObjectRenderingCompletedCallback()->completed(state);
186        }
187#endif
188       
189        state->setDynamicObjectCount(_sceneView->getDynamicObjectCount());
190
191        // do draw traveral
192        if (aquireGPUStats)
193        {
194            checkQuery(stats);
195            beginQuery(frameNumber);
196        }
197               
198        _sceneView->draw();
199
200        double availableTime = 0.004; // 4 ms
201        if (_databasePager.valid() && _databasePager->requiresExternalCompileGLObjects(_sceneView->getState()->getContextID()))
202        {
203             _databasePager->compileGLObjects(*(_sceneView->getState()), availableTime);
204        }
205        _sceneView->flushDeletedGLObjects(availableTime);
206
207        if (aquireGPUStats)
208        {
209            endQuery();
210            checkQuery(stats);
211        }
212       
213        osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
214
215        if (stats && stats->collectStats("rendering"))
216        {
217            stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
218            stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
219            stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
220
221            stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
222            stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
223            stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(afterCullTick, afterDrawTick));
224        }
225       
226    }
227   
228    osg::observer_ptr<osgUtil::SceneView>       _sceneView;
229    osg::observer_ptr<osgDB::DatabasePager>     _databasePager;
230
231};
232
233
234// Draw operation, that does a draw on the scene graph.
235struct ViewerDoubleBufferedRenderingOperation : public osg::Operation, public ViewerQuerySupport
236{
237    ViewerDoubleBufferedRenderingOperation(bool graphicsThreadDoesCull, osgUtil::SceneView* sv0, osgUtil::SceneView* sv1, osgDB::DatabasePager* databasePager, osg::Timer_t startTick):
238        osg::Operation("Render",true),
239        ViewerQuerySupport(startTick),
240        _graphicsThreadDoesCull(graphicsThreadDoesCull),
241        _done(false),
242        _databasePager(databasePager)
243    {
244        _lockHeld[0]  = false;
245        _lockHeld[1]  = false;
246
247        _sceneView[0] = sv0;
248        _sceneView[0]->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
249
250        _sceneView[1] = sv1;
251        _sceneView[1]->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get());
252       
253        _currentCull = 0;
254        _currentDraw = 0;
255       
256        // lock the mutex for the current cull SceneView to
257        // prevent the draw traversal from reading from it before the cull traversal has been completed.
258        if (!_graphicsThreadDoesCull)
259        {
260             _mutex[_currentCull].lock();
261             _lockHeld[_currentCull] = true;
262        }
263   
264        // osg::notify(osg::NOTICE)<<"constructed"<<std::endl;
265    }
266   
267    osg::Camera* getCamera() { return _sceneView[0]->getCamera(); }
268
269    void setGraphicsThreadDoesCull(bool flag)
270    {
271        if (_graphicsThreadDoesCull==flag) return;
272       
273        _graphicsThreadDoesCull = flag;
274       
275        _currentCull = 0;
276        _currentDraw = 0;
277
278        if (_graphicsThreadDoesCull)
279        {
280            // need to disable any locks held by the cull
281            if (_lockHeld[0])
282            {
283                _lockHeld[0] = false;
284                _mutex[0].unlock();
285            }
286
287            if (_lockHeld[1])
288            {
289                _lockHeld[1] = false;
290                _mutex[1].unlock();
291            }
292        }
293        else
294        {
295            // need to set a lock for cull
296            _mutex[_currentCull].lock();
297            _lockHeld[_currentCull] = true;
298        }
299    }
300   
301    bool getGraphicsThreadDoesCull() const { return _graphicsThreadDoesCull; }
302
303    void cull()
304    {
305        // osg::notify(osg::NOTICE)<<"cull()"<<std::endl;
306
307        if (_done || _graphicsThreadDoesCull) return;
308
309        // note we assume lock has already been aquired.
310        osgUtil::SceneView* sceneView = _sceneView[_currentCull].get();
311       
312        if (sceneView)
313        {
314            // osg::notify(osg::NOTICE)<<"Culling buffer "<<_currentCull<<std::endl;
315
316            // pass on the fusion distance settings from the View to the SceneView
317            osgViewer::View* view = dynamic_cast<osgViewer::View*>(sceneView->getCamera()->getView());
318            if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
319       
320            osg::Stats* stats = sceneView->getCamera()->getStats();
321            osg::State* state = sceneView->getState();
322            const osg::FrameStamp* fs = state->getFrameStamp();
323            int frameNumber = fs ? fs->getFrameNumber() : 0;
324
325            _frameNumber[_currentCull] = frameNumber;
326
327            // do cull taversal
328            osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
329           
330            sceneView->inheritCullSettings(*(sceneView->getCamera()));
331            sceneView->cull();
332           
333            osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
334
335#if 0
336            if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
337            {
338                // osg::notify(osg::NOTICE)<<"Completed in cull"<<std::endl;
339                state->getDynamicObjectRenderingCompletedCallback()->completed(state);
340            }
341#endif
342            if (stats && stats->collectStats("rendering"))
343            {
344                stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
345                stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
346                stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
347            }
348        }
349
350
351        // relase the mutex associated with this cull traversal, let the draw commence.
352        _lockHeld[_currentCull] = false;
353        _mutex[_currentCull].unlock();
354       
355        // swap which SceneView we need to do cull traversal on next.
356        _currentCull = 1 - _currentCull;
357       
358        // aquire the lock for it for the new cull traversal
359        _mutex[_currentCull].lock();
360        _lockHeld[_currentCull] = true;
361    }
362   
363    void draw()
364    {
365        // osg::notify(osg::NOTICE)<<"draw()"<<std::endl;
366
367        osgUtil::SceneView* sceneView = _sceneView[_currentDraw].get();
368       
369        if (sceneView || _done)
370        {
371            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex[_currentDraw]);
372
373            // osg::notify(osg::NOTICE)<<"Drawing buffer "<<_currentDraw<<std::endl;
374
375            if (_done)
376            {
377                osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::release() causing draw to exit"<<std::endl;
378                return;
379            }
380           
381            if (_graphicsThreadDoesCull)
382            {
383                osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::draw() completing early due to change in _graphicsThreadDoesCull flag."<<std::endl;
384                return;
385            }
386
387            // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
388
389            osg::Stats* stats = sceneView->getCamera()->getStats();
390            osg::State* state = sceneView->getState();
391            int frameNumber = _frameNumber[_currentDraw];
392
393            if (!_initialized)
394            {
395                initialize(state);
396            }
397
398            state->setDynamicObjectCount(sceneView->getDynamicObjectCount());
399
400            if (sceneView->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
401            {
402                // osg::notify(osg::NOTICE)<<"Completed in cull"<<std::endl;
403                state->getDynamicObjectRenderingCompletedCallback()->completed(state);
404            }
405
406            osg::Timer_t beforeDrawTick = osg::Timer::instance()->tick();
407
408            bool aquireGPUStats = stats && _timerQuerySupported && stats->collectStats("gpu");
409
410            if (aquireGPUStats)
411            {
412                checkQuery(stats);
413            }
414
415            // do draw traveral
416            if (aquireGPUStats)
417            {
418                checkQuery(stats);
419                beginQuery(frameNumber);
420            }
421
422            sceneView->draw();
423
424            double availableTime = 0.004; // 4 ms
425            if (_databasePager.valid() && _databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID()))
426            {
427                _databasePager->compileGLObjects(*(sceneView->getState()), availableTime);
428            }
429
430            sceneView->flushDeletedGLObjects(availableTime);
431
432            if (aquireGPUStats)
433            {
434                endQuery();
435                checkQuery(stats);
436            }
437
438            glFlush();
439
440
441            osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
442
443            if (stats && stats->collectStats("rendering"))
444            {
445                stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeDrawTick));
446                stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
447                stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(beforeDrawTick, afterDrawTick));
448            }
449        }
450               
451        _currentDraw = 1-_currentDraw;
452       
453    }
454   
455    void cull_draw()
456    {
457        osgUtil::SceneView* sceneView = _sceneView[_currentDraw].get();
458        if (!sceneView || _done) return;
459
460        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_mutex[_currentDraw]);
461
462        if (_done)
463        {
464            osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::release() causing cull_draw to exit"<<std::endl;
465            return;
466        }
467
468        // osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
469
470        // pass on the fusion distance settings from the View to the SceneView
471        osgViewer::View* view = dynamic_cast<osgViewer::View*>(sceneView->getCamera()->getView());
472        if (view) sceneView->setFusionDistance(view->getFusionDistanceMode(), view->getFusionDistanceValue());
473
474        osg::Stats* stats = sceneView->getCamera()->getStats();
475        osg::State* state = sceneView->getState();
476        const osg::FrameStamp* fs = state->getFrameStamp();
477        int frameNumber = fs ? fs->getFrameNumber() : 0;
478
479        if (!_initialized)
480        {
481            initialize(state);
482        }
483       
484        bool aquireGPUStats = stats && _timerQuerySupported && stats->collectStats("gpu");
485
486        if (aquireGPUStats)
487        {
488            checkQuery(stats);
489        }
490       
491        // do cull taversal
492        osg::Timer_t beforeCullTick = osg::Timer::instance()->tick();
493
494        sceneView->inheritCullSettings(*(sceneView->getCamera()));
495        sceneView->cull();
496
497        osg::Timer_t afterCullTick = osg::Timer::instance()->tick();
498
499        if (state->getDynamicObjectCount()==0 && state->getDynamicObjectRenderingCompletedCallback())
500        {
501            state->getDynamicObjectRenderingCompletedCallback()->completed(state);
502        }
503
504        // do draw traveral
505        if (aquireGPUStats)
506        {
507            checkQuery(stats);
508            beginQuery(frameNumber);
509        }
510               
511        sceneView->draw();
512
513        double availableTime = 0.004; // 4 ms
514        if (_databasePager.valid() && _databasePager->requiresExternalCompileGLObjects(sceneView->getState()->getContextID()))
515        {
516            _databasePager->compileGLObjects(*(sceneView->getState()), availableTime);
517        }
518        sceneView->flushDeletedGLObjects(availableTime);
519
520        if (aquireGPUStats)
521        {
522            endQuery();
523            checkQuery(stats);
524        }
525       
526        osg::Timer_t afterDrawTick = osg::Timer::instance()->tick();
527
528        if (stats && stats->collectStats("rendering"))
529        {
530            stats->setAttribute(frameNumber, "Cull traversal begin time", osg::Timer::instance()->delta_s(_startTick, beforeCullTick));
531            stats->setAttribute(frameNumber, "Cull traversal end time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
532            stats->setAttribute(frameNumber, "Cull traversal time taken", osg::Timer::instance()->delta_s(beforeCullTick, afterCullTick));
533
534            stats->setAttribute(frameNumber, "Draw traversal begin time", osg::Timer::instance()->delta_s(_startTick, afterCullTick));
535            stats->setAttribute(frameNumber, "Draw traversal end time", osg::Timer::instance()->delta_s(_startTick, afterDrawTick));
536            stats->setAttribute(frameNumber, "Draw traversal time taken", osg::Timer::instance()->delta_s(afterCullTick, afterDrawTick));
537        }
538    }
539
540    virtual void operator () (osg::Object* object)
541    {
542        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
543        if (!context)
544        {
545            osg::Camera* camera = dynamic_cast<osg::Camera*>(object);
546            if (camera) cull();
547            return;
548        }
549
550        //osg::notify(osg::NOTICE)<<"GraphicsCall "<<std::endl;
551        // if (_done) return;
552
553        if (_graphicsThreadDoesCull)
554        {
555            cull_draw();
556        }
557        else
558        {
559            draw();
560        }
561    }
562   
563    virtual void release()
564    {
565        osg::notify(osg::INFO)<<"ViewerDoubleBufferedRenderingOperation::release()"<<std::endl;
566        _done = true;
567
568        if (_lockHeld[0])
569        {
570            _lockHeld[0] = false;
571            _mutex[0].unlock();
572        }
573
574        if (_lockHeld[1])
575        {
576            _lockHeld[1] = false;
577            _mutex[1].unlock();
578        }
579    }
580
581    bool                                    _graphicsThreadDoesCull;
582    bool                                    _done;
583    unsigned int                            _currentCull;
584    unsigned int                            _currentDraw;
585   
586    OpenThreads::Mutex                      _mutex[2];
587    bool                                    _lockHeld[2];
588    osg::observer_ptr<osgUtil::SceneView>   _sceneView[2];
589    int                                     _frameNumber[2];
590    osg::observer_ptr<osgDB::DatabasePager> _databasePager;
591
592
593};
594
595
596Viewer::Viewer()
597{
598    constructorInit();
599}
600
601Viewer::Viewer(osg::ArgumentParser& arguments)
602{
603    constructorInit();
604   
605    while (arguments.read("--SingleThreaded")) setThreadingModel(SingleThreaded);
606    while (arguments.read("--CullDrawThreadPerContext")) setThreadingModel(CullDrawThreadPerContext);
607    while (arguments.read("--DrawThreadPerContext")) setThreadingModel(DrawThreadPerContext);
608    while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) setThreadingModel(CullThreadPerCameraDrawThreadPerContext);
609
610    osg::DisplaySettings::instance()->readCommandLine(arguments);
611    osgDB::readCommandLine(arguments);
612
613    std::string colorStr;
614    while (arguments.read("--clear-color",colorStr))
615    {
616        float r, g, b;
617        float a = 1.0f;
618        int cnt = sscanf( colorStr.c_str(), "%f,%f,%f,%f", &r, &g, &b, &a );
619        if( cnt==3 || cnt==4 ) getCamera()->setClearColor( osg::Vec4(r,g,b,a) );
620        else osg::notify(osg::WARN)<<"Invalid clear color \""<<colorStr<<"\""<<std::endl;
621    }
622   
623    int screenNum = -1;
624    while (arguments.read("--screen",screenNum)) {}
625   
626    int x = -1, y = -1, width = -1, height = -1;
627    while (arguments.read("--window",x,y,width,height)) {}
628
629    if (width>0 && height>0)
630    {
631        if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum);
632        else setUpViewInWindow(x,y,width,height);
633       
634    }
635    else if (screenNum>=0)
636    {
637        setUpViewOnSingleScreen(screenNum);
638    }
639
640}
641
642void Viewer::constructorInit()
643{
644    _firstFrame = true;
645    _done = false;
646    _keyEventSetsDone = osgGA::GUIEventAdapter::KEY_Escape;
647    _quitEventSetsDone = true;
648    _threadingModel = AutomaticSelection;
649    _threadsRunning = false;
650    _useMainThreadForRenderingTraversal = true;
651    _endBarrierPosition = AfterSwapBuffers;
652    _numWindowsOpenAtLastSetUpThreading = 0;
653    _startTick = 0;
654
655    _frameStamp = new osg::FrameStamp;
656    _frameStamp->setFrameNumber(0);
657    _frameStamp->setReferenceTime(0);
658    _frameStamp->setSimulationTime(0);
659
660    _eventVisitor = new osgGA::EventVisitor;
661    _eventVisitor->setActionAdapter(this);
662   
663    setStats(new osg::Stats("Viewer"));
664}
665
666Viewer::~Viewer()
667{
668    //osg::notify(osg::NOTICE)<<"Viewer::~Viewer()"<<std::endl;
669
670
671    Threads threads;
672    getAllThreads(threads);
673
674    osg::notify(osg::INFO)<<"Viewer::~Viewer():: start destructor getThreads = "<<threads.size()<<std::endl;
675
676
677    stopThreading();
678   
679    if (_scene.valid() && _scene->getDatabasePager())
680    {
681        _scene->getDatabasePager()->cancel();
682        _scene->setDatabasePager(0);
683    }
684
685    Contexts contexts;
686    getContexts(contexts);
687
688    // clear out all the previously assigned operations
689    for(Contexts::iterator citr = contexts.begin();
690        citr != contexts.end();
691        ++citr)
692    {
693        (*citr)->close();
694    }
695
696    if (osg::Referenced::getDeleteHandler())
697    {
698        osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(0);
699        osg::Referenced::getDeleteHandler()->flushAll();
700    }
701    //osg::notify(osg::NOTICE)<<"finish Viewer::~Viewer()"<<std::endl;
702   
703    getAllThreads(threads);
704
705    osg::notify(osg::INFO)<<"Viewer::~Viewer() end destrcutor getThreads = "<<threads.size()<<std::endl;
706
707}
708
709bool Viewer::isRealized() const
710{
711
712    Contexts contexts;
713    const_cast<Viewer*>(this)->getContexts(contexts);
714
715    unsigned int numRealizedWindows = 0;
716
717    // clear out all the previously assigned operations
718    for(Contexts::iterator citr = contexts.begin();
719        citr != contexts.end();
720        ++citr)
721    {
722        if ((*citr)->isRealized()) ++numRealizedWindows;
723    }
724   
725    return numRealizedWindows > 0;
726}
727
728int Viewer::run()
729{
730    // if we don't have any scene graph assigned then just return
731    if (!getSceneData())
732    {
733        osg::notify(osg::NOTICE)<<"Warning: Viewer::run() called without a scene graph being assigned to the viewer, cannot run."<<std::endl;
734        return 1;
735    }
736
737    if (!getCameraManipulator() && getCamera()->getAllowEventFocus())
738    {
739        setCameraManipulator(new osgGA::TrackballManipulator());
740    }
741
742    if (!isRealized())
743    {
744        realize();
745    }
746
747#if 0
748    while (!done())
749    {
750        frame();
751    }
752#else
753
754    const char* str = getenv("OSG_RUN_FRAME_COUNT");
755    if (str)
756    {
757        int runTillFrameNumber = atoi(str);
758        while (!done() && getFrameStamp()->getFrameNumber()<runTillFrameNumber)
759        {
760            frame();
761        }
762    }
763    else
764    {
765        while (!done())
766        {
767            frame();
768        }
769    }
770
771#endif   
772    return 0;
773}
774
775void Viewer::setStartTick(osg::Timer_t tick)
776{
777    _startTick = tick;
778   
779    Contexts contexts;
780    getContexts(contexts,false);
781
782    getEventQueue()->setStartTick(_startTick);
783    for(Contexts::iterator citr = contexts.begin();
784        citr != contexts.end();
785        ++citr)
786    {
787        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
788        if (gw)
789        {
790            gw->getEventQueue()->setStartTick(_startTick);
791        }
792    }
793}
794
795
796void Viewer::setReferenceTime(double time)
797{
798    osg::Timer_t tick = osg::Timer::instance()->tick();
799    double currentTime = osg::Timer::instance()->delta_s(_startTick, tick);
800    double delta_ticks = (time-currentTime)*(osg::Timer::instance()->getSecondsPerTick());
801    if (delta_ticks>=0) tick += osg::Timer_t(delta_ticks);
802    else tick -= osg::Timer_t(-delta_ticks);
803
804    // assign the new start tick
805    setStartTick(tick);
806}
807
808
809void Viewer::setSceneData(osg::Node* node)
810{
811    _scene = new osgViewer::Scene;
812    _scene->setSceneData(node);
813    _scene->setFrameStamp(_frameStamp.get());
814   
815    computeActiveCoordinateSystemNodePath();
816
817    setReferenceTime(0.0);
818   
819    assignSceneDataToCameras();
820    setUpRenderingSupport();
821}
822
823GraphicsWindowEmbedded* Viewer::setUpViewerAsEmbeddedInWindow(int x, int y, int width, int height)
824{
825    setThreadingModel(SingleThreaded);
826    osgViewer::GraphicsWindowEmbedded* gw = new osgViewer::GraphicsWindowEmbedded(x,y,width,height);
827    getCamera()->setViewport(new osg::Viewport(0,0,width,height));
828    getCamera()->setGraphicsContext(gw);
829    return gw;
830}
831
832void Viewer::setThreadingModel(ThreadingModel threadingModel)
833{
834    if (_threadingModel == threadingModel) return;
835   
836    if (_threadsRunning) stopThreading();
837   
838    _threadingModel = threadingModel;
839
840    if (isRealized() && _threadingModel!=SingleThreaded) startThreading();
841}
842
843void Viewer::setUpThreading()
844{
845    Contexts contexts;
846    getContexts(contexts);
847
848    _numWindowsOpenAtLastSetUpThreading = contexts.size();
849
850    if (_threadingModel==SingleThreaded)
851    {
852        if (_threadsRunning) stopThreading();
853        else
854        {
855            // we'll set processor affinity here to help single threaded apps
856            // with multiple processor cores, and using the database pager.
857            int numProcessors = OpenThreads::GetNumberOfProcessors();
858            bool affinity = numProcessors>1;   
859            if (affinity)
860            {
861                OpenThreads::SetProcessorAffinityOfCurrentThread(0);
862                if (_scene.valid() && _scene->getDatabasePager())
863                {
864                    _scene->getDatabasePager()->setProcessorAffinity(1);
865                }
866            }
867        }
868    }
869    else
870    {
871        if (!_threadsRunning) startThreading();
872    }
873   
874}
875
876
877void Viewer::setUseMainThreadForRenderingTraversals(bool flag)
878{
879    if (_useMainThreadForRenderingTraversal==flag) return;
880
881    if (_threadsRunning) stopThreading();
882   
883    _useMainThreadForRenderingTraversal = flag;
884   
885    if (_threadingModel!=SingleThreaded) startThreading();
886}
887
888void Viewer::setEndBarrierPosition(BarrierPosition bp)
889{
890    if (_endBarrierPosition == bp) return;
891   
892    if (_threadsRunning) stopThreading();
893   
894    _endBarrierPosition = bp;
895
896    if (_threadingModel!=SingleThreaded) startThreading();
897}
898
899void Viewer::stopThreading()
900{
901    if (!_threadsRunning) return;
902
903    osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopping threading"<<std::endl;
904
905    Contexts contexts;
906    getContexts(contexts);
907
908    Cameras cameras;
909    getCameras(cameras);
910
911    Contexts::iterator gcitr;
912    Cameras::iterator citr;
913
914    // reset any double buffer graphics objects
915    for(gcitr = contexts.begin();
916        gcitr != contexts.end();
917        ++gcitr)
918    {
919        osg::GraphicsContext* gc = (*gcitr);
920       
921        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
922        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
923        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
924            oitr != operations.end();
925            ++oitr)
926        {
927            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
928            if (vdbro)
929            {
930                vdbro->release();
931            }
932        }
933
934    }
935
936    // delete all the graphics threads.   
937    for(gcitr = contexts.begin();
938        gcitr != contexts.end();
939        ++gcitr)
940    {
941        (*gcitr)->setGraphicsThread(0);
942    }
943
944    // delete all the camera threads.   
945    for(citr = cameras.begin();
946        citr != cameras.end();
947        ++citr)
948    {
949        (*citr)->setCameraThread(0);
950    }
951
952    // reset any double buffer graphics objects
953    for(gcitr = contexts.begin();
954        gcitr != contexts.end();
955        ++gcitr)
956    {
957        osg::GraphicsContext* gc = (*gcitr);
958       
959        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
960        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
961        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
962            oitr != operations.end();
963            ++oitr)
964        {
965            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
966            if (vdbro)
967            {
968                vdbro->setGraphicsThreadDoesCull( true );
969                vdbro->_done = false;
970            }
971        }
972
973    }
974
975    int numProcessors = OpenThreads::GetNumberOfProcessors();
976    bool affinity = numProcessors>1;   
977    if (affinity)
978    {
979        OpenThreads::SetProcessorAffinityOfCurrentThread(0);
980        if (_scene.valid() && _scene->getDatabasePager())
981        {
982            _scene->getDatabasePager()->setProcessorAffinity(1);
983        }
984    }
985
986    _threadsRunning = false;
987    _startRenderingBarrier = 0;
988    _endRenderingDispatchBarrier = 0;
989    _endDynamicDrawBlock = 0;
990    _numWindowsOpenAtLastSetUpThreading = contexts.size();
991
992    osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading."<<std::endl;
993}
994
995// Compile operation, that compile OpenGL objects.
996struct ViewerCompileOperation : public osg::Operation
997{
998    ViewerCompileOperation(osg::Node* scene):
999        osg::Operation("Compile",false),
1000        _scene(scene)
1001    {
1002    }
1003   
1004    virtual void operator () (osg::Object* object)
1005    {
1006        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1007        if (!context) return;
1008
1009        // OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
1010        // osg::notify(osg::NOTICE)<<"Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
1011
1012        // context->makeCurrent();
1013       
1014        context->getState()->initializeExtensionProcs();
1015
1016        osgUtil::GLObjectsVisitor compileVisitor;
1017        compileVisitor.setState(context->getState());
1018
1019        // do the compile traversal
1020        if (_scene.valid()) _scene->accept(compileVisitor);
1021
1022        // osg::notify(osg::NOTICE)<<"Done Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
1023    }
1024   
1025    osg::ref_ptr<osg::Node> _scene;
1026};
1027
1028
1029// Draw operation, that does a draw on the scene graph.
1030struct ViewerRunOperations : public osg::Operation
1031{
1032    ViewerRunOperations():
1033        osg::Operation("RunOperation",true)
1034    {
1035    }
1036   
1037    virtual void operator () (osg::Object* object)
1038    {
1039        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1040        if (!context) return;
1041
1042        context->runOperations();
1043    }
1044};
1045
1046static 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.");
1047static osg::ApplicationUsageProxy Viewer_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN <value>","Set the default screen that windows should open up on.");
1048static 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.");
1049
1050Viewer::ThreadingModel Viewer::suggestBestThreadingModel()
1051{
1052    const char* str = getenv("OSG_THREADING");
1053    if (str)
1054    {
1055        if (strcmp(str,"SingleThreaded")==0) return SingleThreaded;
1056        else if (strcmp(str,"CullDrawThreadPerContext")==0) return CullDrawThreadPerContext;
1057        else if (strcmp(str,"DrawThreadPerContext")==0) return DrawThreadPerContext;
1058        else if (strcmp(str,"CullThreadPerCameraDrawThreadPerContext")==0) return CullThreadPerCameraDrawThreadPerContext;
1059    }
1060
1061    Contexts contexts;
1062    getContexts(contexts);
1063   
1064    if (contexts.empty()) return SingleThreaded;
1065
1066#if 0
1067#ifdef _WIN32
1068    // temporary hack to disable multi-threading under Windows till we find good solutions for
1069    // crashes that users are seeing.
1070    return SingleThreaded;
1071#endif
1072#endif
1073
1074    Cameras cameras;
1075    getCameras(cameras);
1076
1077    if (cameras.empty()) return SingleThreaded;
1078
1079
1080    int numProcessors = OpenThreads::GetNumberOfProcessors();
1081
1082    if (contexts.size()==1)
1083    {
1084        if (numProcessors==1) return SingleThreaded;
1085        else return DrawThreadPerContext;
1086    }
1087
1088    if (numProcessors >= static_cast<int>(cameras.size()+contexts.size()))
1089    {
1090        return CullThreadPerCameraDrawThreadPerContext;
1091    }
1092
1093#if 1
1094        return DrawThreadPerContext;
1095#else
1096        return CullDrawThreadPerContext;
1097#endif
1098}
1099
1100void Viewer::startThreading()
1101{
1102    if (_threadsRunning) return;
1103   
1104    // osg::notify(osg::NOTICE)<<"Viewer::startThreading() - starting threading"<<std::endl;
1105   
1106    // release any context held by the main thread.
1107    releaseContext();
1108
1109    _threadingModel = _threadingModel==AutomaticSelection ? suggestBestThreadingModel() : _threadingModel;
1110
1111    Contexts contexts;
1112    getContexts(contexts);
1113   
1114    osg::notify(osg::INFO)<<"Viewer::startThreading() - contexts.size()="<<contexts.size()<<std::endl;
1115
1116    Cameras cameras;
1117    getCameras(cameras);
1118   
1119    unsigned int numThreadsOnBarrier = 0;
1120    switch(_threadingModel)
1121    {
1122        case(SingleThreaded):
1123            numThreadsOnBarrier = 1;
1124            return;
1125        case(CullDrawThreadPerContext):
1126            numThreadsOnBarrier = contexts.size()+1;
1127            break;
1128        case(DrawThreadPerContext):
1129            numThreadsOnBarrier = 1;
1130            break;
1131        case(CullThreadPerCameraDrawThreadPerContext):
1132            numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1;
1133            break;
1134        default:
1135            osg::notify(osg::NOTICE)<<"Error: Threading model not selected"<<std::endl;
1136            return;
1137    }
1138
1139    // using multi-threading so make sure that new objects are allocated with thread safe ref/unref
1140    osg::Referenced::setThreadSafeReferenceCounting(true);
1141   
1142    if (getSceneData())
1143    {
1144        osg::notify(osg::INFO)<<"Making scene thread safe"<<std::endl;
1145
1146        // make sure that existing scene graph objects are allocated with thread safe ref/unref
1147        getSceneData()->setThreadSafeRefUnref(true);
1148       
1149        // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it.
1150        getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts());
1151    }
1152   
1153    int numProcessors = OpenThreads::GetNumberOfProcessors();
1154    bool affinity = numProcessors>1;   
1155   
1156    Contexts::iterator citr;
1157
1158    unsigned int numViewerDoubleBufferedRenderingOperation = 0;
1159
1160    bool graphicsThreadsDoesCull = _threadingModel == CullDrawThreadPerContext;
1161
1162    // reset any double buffer graphics objects
1163    for(citr = contexts.begin();
1164        citr != contexts.end();
1165        ++citr)
1166    {
1167        osg::GraphicsContext* gc = (*citr);
1168       
1169        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
1170        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
1171        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
1172            oitr != operations.end();
1173            ++oitr)
1174        {
1175            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
1176            if (vdbro)
1177            {
1178                vdbro->setGraphicsThreadDoesCull( graphicsThreadsDoesCull );
1179                vdbro->_done = false;
1180                ++numViewerDoubleBufferedRenderingOperation;
1181            }
1182        }
1183
1184    }
1185
1186    if (_threadingModel==CullDrawThreadPerContext)
1187    {
1188        _startRenderingBarrier = 0;
1189        _endRenderingDispatchBarrier = 0;
1190        _endDynamicDrawBlock = 0;
1191    }
1192    else if (_threadingModel==DrawThreadPerContext ||
1193             _threadingModel==CullThreadPerCameraDrawThreadPerContext)
1194    {
1195        _startRenderingBarrier = 0;
1196        _endRenderingDispatchBarrier = 0;
1197        _endDynamicDrawBlock = new EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation);
1198       
1199        if (!osg::Referenced::getDeleteHandler()) osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2));
1200        else osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2);
1201       
1202        // now make sure the scene graph is set up with the correct DataVariance to protect the dyamic elements of
1203        // the scene graph from being run in parallel.
1204        osgUtil::Optimizer::StaticObjectDetectionVisitor sodv;
1205        getSceneData()->accept(sodv);
1206    }
1207   
1208    if (numThreadsOnBarrier>1)
1209    {
1210        _startRenderingBarrier = new osg::BarrierOperation(numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
1211        _endRenderingDispatchBarrier = new osg::BarrierOperation(numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
1212    }
1213
1214
1215    osg::ref_ptr<osg::BarrierOperation> swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION);
1216
1217    osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
1218
1219    typedef std::map<OpenThreads::Thread*, int> ThreadAffinityMap;
1220    ThreadAffinityMap threadAffinityMap;
1221
1222    unsigned int processNum = 1;
1223    for(citr = contexts.begin();
1224        citr != contexts.end();
1225        ++citr, ++processNum)
1226    {
1227        osg::GraphicsContext* gc = (*citr);
1228       
1229        gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get());
1230
1231        // create the a graphics thread for this context
1232        gc->createGraphicsThread();
1233
1234        if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
1235        threadAffinityMap[gc->getGraphicsThread()] = processNum % numProcessors;
1236
1237        gc->getGraphicsThread()->add(new ViewerCompileOperation(getSceneData()));
1238
1239        // add the startRenderingBarrier
1240        if (_threadingModel==CullDrawThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get());
1241
1242        // add the rendering operation itself.
1243        gc->getGraphicsThread()->add(new ViewerRunOperations());
1244
1245        if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid())
1246        {
1247            // add the endRenderingDispatchBarrier
1248            gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
1249        }
1250
1251        if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get());
1252
1253        // add the swap buffers
1254        gc->getGraphicsThread()->add(swapOp.get());
1255
1256        if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid())
1257        {
1258            // add the endRenderingDispatchBarrier
1259            gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
1260        }
1261
1262
1263
1264    }
1265
1266   
1267    if (_threadingModel==CullThreadPerCameraDrawThreadPerContext && numThreadsOnBarrier>1)
1268    {
1269        Cameras::iterator camItr = cameras.begin();
1270        if (_useMainThreadForRenderingTraversal) ++camItr;
1271
1272        for(;
1273            camItr != cameras.end();
1274            ++camItr, ++processNum)
1275        {
1276            osg::Camera* camera = *camItr;
1277            camera->createCameraThread();
1278
1279            if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors);
1280            threadAffinityMap[camera->getCameraThread()] = processNum % numProcessors;
1281
1282            osg::GraphicsContext* gc = camera->getGraphicsContext();
1283
1284            // add the startRenderingBarrier
1285            if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get());
1286
1287            OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
1288            osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
1289            for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
1290                oitr != operations.end();
1291                ++oitr)
1292            {
1293                ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
1294                if (vdbro && vdbro->getCamera()==camera)
1295                {
1296                    camera->getCameraThread()->add(vdbro);
1297                }
1298            }
1299           
1300            if (_endRenderingDispatchBarrier.valid())
1301            {
1302                // add the endRenderingDispatchBarrier
1303                gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
1304            }
1305
1306        }
1307
1308        for(camItr = cameras.begin();
1309            camItr != cameras.end();
1310            ++camItr)
1311        {
1312            osg::Camera* camera = *camItr;
1313            if (camera->getCameraThread() && !camera->getCameraThread()->isRunning())
1314            {
1315                osg::notify(osg::INFO)<<"  camera->getCameraThread()-> "<<camera->getCameraThread()<<std::endl;
1316                camera->getCameraThread()->startThread();
1317            }
1318        }
1319    }
1320   
1321    if (affinity)
1322    {
1323        OpenThreads::SetProcessorAffinityOfCurrentThread(0);
1324        if (_scene.valid() && _scene->getDatabasePager())
1325        {
1326#if 0       
1327            //_scene->getDatabasePager()->setProcessorAffinity(1);
1328#else
1329            _scene->getDatabasePager()->setProcessorAffinity(0);
1330#endif
1331        }
1332    }
1333
1334#if 0
1335    if (affinity)
1336    {
1337        for(ThreadAffinityMap::iterator titr = threadAffinityMap.begin();
1338            titr != threadAffinityMap.end();
1339            ++titr)
1340        {
1341            titr->first->setProcessorAffinity(titr->second);
1342        }
1343    }
1344#endif
1345
1346
1347    for(citr = contexts.begin();
1348        citr != contexts.end();
1349        ++citr)
1350    {
1351        osg::GraphicsContext* gc = (*citr);
1352        if (gc->getGraphicsThread() && !gc->getGraphicsThread()->isRunning())
1353        {
1354            osg::notify(osg::INFO)<<"  gc->getGraphicsThread()->startThread() "<<gc->getGraphicsThread()<<std::endl;
1355            gc->getGraphicsThread()->startThread();
1356            // OpenThreads::Thread::YieldCurrentThread();
1357        }
1358    }
1359
1360    _threadsRunning = true;
1361    _numWindowsOpenAtLastSetUpThreading = contexts.size();
1362
1363    osg::notify(osg::INFO)<<"Set up threading"<<std::endl;
1364}
1365
1366void Viewer::checkWindowStatus()
1367{
1368    Contexts contexts;
1369    getContexts(contexts);
1370   
1371    // osg::notify(osg::NOTICE)<<"Viewer::checkWindowStatus() - "<<contexts.size()<<std::endl;
1372   
1373    if (contexts.size()==0)
1374    {
1375        _done = true;
1376        if (areThreadsRunning()) stopThreading();
1377    }
1378}
1379
1380
1381struct LessGraphicsContext
1382{
1383    bool operator () (const osg::GraphicsContext* lhs, const osg::GraphicsContext* rhs) const
1384    {
1385        int screenLeft = lhs->getTraits()? lhs->getTraits()->screenNum : 0;
1386        int screenRight = rhs->getTraits()? rhs->getTraits()->screenNum : 0;
1387        if (screenLeft < screenRight) return true;
1388        if (screenLeft > screenRight) return false;
1389
1390        screenLeft = lhs->getTraits()? lhs->getTraits()->x : 0;
1391        screenRight = rhs->getTraits()? rhs->getTraits()->x : 0;
1392        if (screenLeft < screenRight) return true;
1393        if (screenLeft > screenRight) return false;
1394
1395        screenLeft = lhs->getTraits()? lhs->getTraits()->y : 0;
1396        screenRight = rhs->getTraits()? rhs->getTraits()->y : 0;
1397        if (screenLeft < screenRight) return true;
1398        if (screenLeft > screenRight) return false;
1399       
1400        return lhs < rhs;
1401    }
1402};
1403
1404void Viewer::getContexts(Contexts& contexts, bool onlyValid)
1405{
1406    typedef std::set<osg::GraphicsContext*> ContextSet;
1407    ContextSet contextSet;
1408
1409    if (_camera.valid() &&
1410        _camera->getGraphicsContext() &&
1411        (_camera->getGraphicsContext()->valid() || !onlyValid))
1412    {
1413        contextSet.insert(_camera->getGraphicsContext());
1414    }
1415   
1416    for(unsigned int i=0; i<getNumSlaves(); ++i)
1417    {
1418        Slave& slave = getSlave(i);
1419        if (slave._camera.valid() &&
1420            slave._camera->getGraphicsContext() &&
1421            (slave._camera->getGraphicsContext()->valid() || !onlyValid))
1422        {
1423            contextSet.insert(slave._camera->getGraphicsContext());
1424        }
1425    }
1426
1427    contexts.clear();
1428    contexts.reserve(contextSet.size());
1429
1430    for(ContextSet::iterator itr = contextSet.begin();
1431        itr != contextSet.end();
1432        ++itr)
1433    {
1434        contexts.push_back(const_cast<osg::GraphicsContext*>(*itr));
1435    }
1436
1437    if (contexts.size()>=2)
1438    {
1439        std::sort(contexts.begin(), contexts.end(), LessGraphicsContext());
1440    }
1441}
1442
1443void Viewer::getWindows(Windows& windows, bool onlyValid)
1444{
1445    windows.clear();
1446
1447    Contexts contexts;
1448    getContexts(contexts, onlyValid);
1449   
1450    for(Contexts::iterator itr = contexts.begin();
1451        itr != contexts.end();
1452        ++itr)
1453    {
1454        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*itr);
1455        if (gw) windows.push_back(gw);
1456    }
1457}
1458
1459void Viewer::getCameras(Cameras& cameras, bool onlyActive)
1460{
1461    cameras.clear();
1462   
1463    if (!onlyActive || (_camera->getGraphicsContext() && _camera->getGraphicsContext()->valid()) ) cameras.push_back(_camera.get());
1464
1465    for(Slaves::iterator itr = _slaves.begin();
1466        itr != _slaves.end();
1467        ++itr)
1468    {
1469        if (!onlyActive || (itr->_camera->getGraphicsContext() && itr->_camera->getGraphicsContext()->valid()) ) cameras.push_back(itr->_camera.get());
1470    }
1471       
1472}
1473
1474void Viewer::getAllThreads(Threads& threads, bool onlyActive)
1475{
1476    OperationsThreads operationsThreads;
1477    getOperationsThreads(operationsThreads);
1478   
1479    for(OperationsThreads::iterator itr = operationsThreads.begin();
1480        itr != operationsThreads.end();
1481        ++itr)
1482    {
1483        threads.push_back(*itr);
1484    }
1485   
1486    if (_scene.valid() &&
1487        _scene->getDatabasePager() &&
1488       (!onlyActive || _scene->getDatabasePager()->isRunning()))
1489    {
1490        threads.push_back(_scene->getDatabasePager());
1491    }
1492}
1493
1494
1495void Viewer::getOperationsThreads(OperationsThreads& threads, bool onlyActive)
1496{
1497    threads.clear();
1498   
1499    Contexts contexts;
1500    getContexts(contexts);
1501    for(Contexts::iterator gcitr = contexts.begin();
1502        gcitr != contexts.end();
1503        ++gcitr)
1504    {
1505        osg::GraphicsContext* gc = *gcitr;
1506        if (gc->getGraphicsThread() &&
1507            (!onlyActive || gc->getGraphicsThread()->isRunning()) )
1508        {
1509            threads.push_back(gc->getGraphicsThread());
1510        }
1511    }
1512   
1513    Cameras cameras;
1514    getCameras(cameras);
1515    for(Cameras::iterator citr = cameras.begin();
1516        citr != cameras.end();
1517        ++citr)
1518    {
1519        osg::Camera* camera = *citr;
1520        if (camera->getCameraThread() &&
1521            (!onlyActive || camera->getCameraThread()->isRunning()) )
1522        {
1523            threads.push_back(camera->getCameraThread());
1524        }
1525    }
1526   
1527}
1528
1529void Viewer::setUpRenderingSupport()
1530{
1531    bool threadsRunningBeforeSetUpRenderingSupport = _threadsRunning;
1532    if (_threadsRunning) stopThreading();
1533
1534    _sceneViews.clear();
1535
1536    Contexts contexts;
1537    getContexts(contexts);
1538   
1539    osg::FrameStamp* frameStamp = getFrameStamp();
1540    osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance();
1541    osgDB::DatabasePager* dp = _scene.valid() ? _scene->getDatabasePager() : 0;
1542
1543    bool graphicsThreadDoesCull = _threadingModel!=CullThreadPerCameraDrawThreadPerContext;
1544    unsigned int numViewerDoubleBufferedRenderingOperation = 0;
1545   
1546    Cameras localCameras;
1547    getCameras(localCameras);
1548   
1549    unsigned int sceneViewOptions = osgUtil::SceneView::HEADLIGHT;
1550
1551    if (true)//(_threadingModel==CullThreadPerCameraDrawThreadPerContext)
1552    {
1553        for(Contexts::iterator gcitr = contexts.begin();
1554            gcitr != contexts.end();
1555            ++gcitr)
1556        {
1557            (*gcitr)->removeAllOperations();
1558
1559            osg::GraphicsContext* gc = *gcitr;
1560            osg::GraphicsContext::Cameras& cameras = gc->getCameras();
1561            osg::State* state = gc->getState();
1562           
1563            if (dp) dp->setCompileGLObjectsForContextID(state->getContextID(), true);
1564
1565            for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
1566                citr != cameras.end();
1567                ++citr)
1568            {
1569                osg::Camera* camera = *citr;
1570                if (!camera->getStats()) camera->setStats(new osg::Stats("Camera"));
1571               
1572                bool localCamera = std::find(localCameras.begin(),localCameras.end(),camera) != localCameras.end();
1573                if (localCamera)
1574                {
1575                    osgUtil::SceneView* sceneViewList[2];
1576
1577                    for(int i=0; i<2; ++i)
1578                    {
1579                        osgUtil::SceneView* sceneView = new osgUtil::SceneView;
1580
1581                        _sceneViews.push_back(sceneView);                   
1582                        sceneViewList[i] = sceneView;
1583
1584                        sceneView->setGlobalStateSet(_camera->getStateSet());
1585                        sceneView->setDefaults(sceneViewOptions);
1586                        sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ? camera->getDisplaySettings() : ds);
1587                        sceneView->setCamera(camera);
1588                        sceneView->setState(state);
1589                        sceneView->setFrameStamp(frameStamp);
1590                    }
1591
1592
1593                    // osg::notify(osg::NOTICE)<<"localCamera "<<camera->getName()<<std::endl;
1594                    ViewerDoubleBufferedRenderingOperation* vdbro = new ViewerDoubleBufferedRenderingOperation(graphicsThreadDoesCull, sceneViewList[0], sceneViewList[1], dp, _startTick);
1595                    gc->add(vdbro);
1596                    ++numViewerDoubleBufferedRenderingOperation;
1597                }
1598                else
1599                {
1600                    // osg::notify(osg::NOTICE)<<"non local Camera"<<std::endl;
1601
1602                    osgUtil::SceneView* sceneView = new osgUtil::SceneView;
1603
1604                    _sceneViews.push_back(sceneView);                   
1605
1606                    sceneView->setGlobalStateSet(_camera->getStateSet());
1607                    sceneView->setDefaults(sceneViewOptions);
1608                    sceneView->setDisplaySettings(ds);
1609                    sceneView->setCamera(camera);
1610                    sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ? camera->getDisplaySettings() : ds);
1611                    sceneView->setState(state);
1612                    sceneView->setFrameStamp(frameStamp);
1613
1614                    ViewerRenderingOperation* vro = new ViewerRenderingOperation(sceneView, dp, _startTick);
1615                    gc->add(vro);
1616                }
1617
1618            }
1619        }
1620    }
1621    else
1622    {
1623        for(Contexts::iterator gcitr = contexts.begin();
1624            gcitr != contexts.end();
1625            ++gcitr)
1626        {
1627            (*gcitr)->removeAllOperations();
1628
1629            osg::GraphicsContext* gc = *gcitr;
1630            osg::GraphicsContext::Cameras& cameras = gc->getCameras();
1631            osg::State* state = gc->getState();
1632
1633            for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
1634                citr != cameras.end();
1635                ++citr)
1636            {
1637                osg::Camera* camera = *citr;
1638
1639                if (!camera->getStats()) camera->setStats(new osg::Stats("Camera"));
1640
1641                osgUtil::SceneView* sceneView = new osgUtil::SceneView;
1642                _sceneViews.push_back(sceneView);
1643
1644                sceneView->setGlobalStateSet(_camera->getStateSet());
1645                sceneView->setDefaults(sceneViewOptions);
1646                sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ? camera->getDisplaySettings() : ds);
1647                sceneView->setCamera(camera);
1648                sceneView->setState(state);
1649                sceneView->setFrameStamp(frameStamp);
1650
1651                if (dp) dp->setCompileGLObjectsForContextID(state->getContextID(), true);
1652
1653                gc->add(new ViewerRenderingOperation(sceneView, dp, _startTick));
1654
1655                ++numViewerDoubleBufferedRenderingOperation;
1656            }
1657        }
1658    }
1659
1660    if (_endDynamicDrawBlock.valid())
1661    {
1662        _endDynamicDrawBlock->setNumOfBlocks(numViewerDoubleBufferedRenderingOperation);
1663    }
1664
1665    if (threadsRunningBeforeSetUpRenderingSupport) startThreading();
1666}
1667
1668
1669void Viewer::realize()
1670{
1671    //osg::notify(osg::INFO)<<"Viewer::realize()"<<std::endl;
1672   
1673    setCameraWithFocus(0);
1674
1675    Contexts contexts;
1676    getContexts(contexts);
1677   
1678    if (contexts.empty())
1679    {
1680        osg::notify(osg::INFO)<<"Viewer::realize() - No valid contexts found, setting up view across all screens."<<std::endl;
1681   
1682        // no windows are already set up so set up a default view       
1683       
1684        const char* ptr = 0;
1685        int screenNum = -1;
1686        if ((ptr = getenv("OSG_SCREEN")) != 0)
1687        {
1688            if (strlen(ptr)!=0) screenNum = atoi(ptr);
1689            else screenNum = -1;
1690        }
1691       
1692        int x = -1, y = -1, width = -1, height = -1;
1693        if ((ptr = getenv("OSG_WINDOW")) != 0)
1694        {
1695            std::istringstream iss(ptr);
1696            iss >> x >> y >> width >> height;
1697        }
1698
1699        if (width>0 && height>0)
1700        {
1701            if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum);
1702            else setUpViewInWindow(x,y,width,height);
1703        }
1704        else if (screenNum>=0)
1705        {
1706            setUpViewOnSingleScreen(screenNum);
1707        }
1708        else
1709        {
1710            setUpViewAcrossAllScreens();
1711        }
1712
1713        getContexts(contexts);
1714    }
1715
1716    if (contexts.empty())
1717    {
1718        osg::notify(osg::NOTICE)<<"Viewer::realize() - failed to set up any windows"<<std::endl;
1719        _done = true;
1720        return;
1721    }
1722   
1723    setUpRenderingSupport();
1724   
1725    for(Contexts::iterator citr = contexts.begin();
1726        citr != contexts.end();
1727        ++citr)
1728    {
1729        osg::GraphicsContext* gc = *citr;
1730        gc->realize();
1731       
1732        if (_realizeOperation.valid() && gc->valid())
1733        {
1734            gc->makeCurrent();
1735           
1736            (*_realizeOperation)(gc);
1737           
1738            gc->releaseContext();
1739        }
1740    }
1741   
1742    bool grabFocus = true;
1743    if (grabFocus)
1744    {
1745        for(Contexts::iterator citr = contexts.begin();
1746            citr != contexts.end();
1747            ++citr)
1748        {
1749            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
1750            if (gw)
1751            {
1752                gw->grabFocusIfPointerInWindow();   
1753            }
1754        }
1755    }
1756   
1757    // initialize the global timer to be relative to the current time.
1758    osg::Timer::instance()->setStartTick();
1759
1760    // pass on the start tick to all the associated eventqueues
1761    setStartTick(osg::Timer::instance()->getStartTick());
1762
1763    setUpThreading();
1764}
1765
1766
1767void Viewer::frame(double simulationTime)
1768{
1769    if (_done) return;
1770
1771    // osg::notify(osg::NOTICE)<<std::endl<<"Viewer::frame()"<<std::endl<<std::endl;
1772
1773    if (_firstFrame)
1774    {
1775        init();
1776       
1777        if (!isRealized())
1778        {
1779            realize();
1780        }
1781       
1782        _firstFrame = false;
1783    }
1784    advance(simulationTime);
1785   
1786    eventTraversal();
1787    updateTraversal();
1788    renderingTraversals();
1789}
1790
1791void Viewer::advance(double simulationTime)
1792{
1793    if (_done) return;
1794
1795    double prevousReferenceTime = _frameStamp->getReferenceTime();
1796    int previousFrameNumber = _frameStamp->getFrameNumber();
1797
1798    _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
1799
1800    _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) );
1801
1802    if (simulationTime==USE_REFERENCE_TIME)
1803    {
1804        _frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
1805    }
1806    else
1807    {
1808        _frameStamp->setSimulationTime(simulationTime);
1809    }
1810   
1811    if (getStats() && getStats()->collectStats("frame_rate"))
1812    {
1813        // update previous frame stats
1814        double deltaFrameTime = _frameStamp->getReferenceTime() - prevousReferenceTime;
1815        getStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime);
1816        getStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime);
1817
1818        // update current frames stats
1819        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime());
1820    }
1821
1822    if (osg::Referenced::getDeleteHandler())
1823    {
1824        osg::Referenced::getDeleteHandler()->flush();
1825        osg::Referenced::getDeleteHandler()->setFrameNumber(_frameStamp->getFrameNumber());
1826    }
1827
1828}
1829
1830void Viewer::eventTraversal()
1831{
1832    if (_done) return;
1833
1834    double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1835
1836    // osg::notify(osg::NOTICE)<<"Viewer::frameEventTraversal()."<<std::endl;
1837   
1838    // need to copy events from the GraphicsWindow's into local EventQueue;
1839    osgGA::EventQueue::Events events;
1840
1841    Contexts contexts;
1842    getContexts(contexts);
1843
1844    osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1845    osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
1846    if (getCamera()->getViewport())
1847    {
1848        osg::Viewport* viewport = getCamera()->getViewport();
1849        masterCameraVPW *= viewport->computeWindowMatrix();
1850        eventState->setInputRange( viewport->x(), viewport->y(), viewport->x() + viewport->width(), viewport->y() + viewport->height());
1851    }
1852    else
1853    {
1854        eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
1855    }
1856
1857
1858    for(Contexts::iterator citr = contexts.begin();
1859        citr != contexts.end();
1860        ++citr)
1861    {
1862        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
1863        if (gw)
1864        {
1865            gw->checkEvents();
1866           
1867            osgGA::EventQueue::Events gw_events;
1868            gw->getEventQueue()->takeEvents(gw_events);
1869           
1870            osgGA::EventQueue::Events::iterator itr;
1871            for(itr = gw_events.begin();
1872                itr != gw_events.end();
1873                ++itr)
1874            {
1875                osgGA::GUIEventAdapter* event = itr->get();
1876               
1877                bool pointerEvent = false;
1878
1879                float x = event->getX();
1880                float y = event->getY();
1881               
1882                bool invert_y = event->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
1883                if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
1884               
1885                switch(event->getEventType())
1886                {
1887                    case(osgGA::GUIEventAdapter::PUSH):
1888                    case(osgGA::GUIEventAdapter::RELEASE):
1889                    case(osgGA::GUIEventAdapter::DRAG):
1890                    case(osgGA::GUIEventAdapter::MOVE):
1891                    {
1892                        pointerEvent = true;
1893                       
1894                        if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG || !getCameraWithFocus())
1895                        {
1896                            osg::GraphicsContext::Cameras& cameras = gw->getCameras();
1897                            for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
1898                                citr != cameras.end();
1899                                ++citr)
1900                            {
1901                                osg::Camera* camera = *citr;
1902                                if (camera->getView()==this &&
1903                                    camera->getAllowEventFocus() &&
1904                                    camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
1905                                {
1906                                    osg::Viewport* viewport = camera ? camera->getViewport() : 0;
1907                                    if (viewport &&
1908                                        x >= viewport->x() && y >= viewport->y() &&
1909                                        x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
1910                                    {
1911                                        // osg::notify(osg::NOTICE)<<"setCamera with focus "<<camera->getName()<<" x="<<x<<" y="<<y<<std::endl;
1912                                        setCameraWithFocus(camera);
1913                                    }
1914                                }
1915                            }
1916                        }
1917                       
1918                        break;
1919                    }
1920                    default:
1921                        break;
1922                }
1923               
1924                if (pointerEvent)
1925                {
1926                    if (getCameraWithFocus())
1927                    {
1928                        osg::Viewport* viewport = getCameraWithFocus()->getViewport();
1929                        osg::Matrix localCameraVPW = getCameraWithFocus()->getViewMatrix() * getCameraWithFocus()->getProjectionMatrix();
1930                        if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
1931
1932                        osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
1933
1934                        osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
1935
1936                        x = new_coord.x();
1937                        y = new_coord.y();                               
1938
1939                        // osg::notify(osg::NOTICE)<<"pointer event new_coord.x()="<<new_coord.x()<<" new_coord.y()="<<new_coord.y()<<std::endl;
1940
1941                        event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
1942                        event->setX(x);
1943                        event->setY(y);
1944                        event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
1945
1946                    }
1947                    else
1948                    {
1949                        x = eventState->getXmin() + (x/double(gw->getTraits()->width))*(eventState->getXmax() - eventState->getXmin());
1950                        y = eventState->getYmin() + (y/double(gw->getTraits()->height))*(eventState->getYmax() - eventState->getYmin());
1951                        // osg::notify(osg::NOTICE)<<"new x = "<<x<<" new y = "<<y<<std::endl;
1952
1953                        event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
1954                        event->setX(x);
1955                        event->setY(y);
1956                        event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
1957                    }
1958                   
1959                    // pass along the new pointer events details to the eventState of the viewer
1960                    eventState->setX(x);
1961                    eventState->setY(y);
1962                    eventState->setButtonMask(event->getButtonMask());
1963                    eventState->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
1964
1965                }
1966                else
1967                {
1968                    event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
1969                    event->setX(eventState->getX());
1970                    event->setY(eventState->getY());
1971                    event->setButtonMask(eventState->getButtonMask());
1972                    event->setMouseYOrientation(eventState->getMouseYOrientation());
1973                }
1974                //osg::notify(osg::NOTICE)<<"   mouse x = "<<event->getX()<<" y="<<event->getY()<<std::endl;
1975                // osg::notify(osg::NOTICE)<<"   mouse Xmin = "<<event->getXmin()<<" Ymin="<<event->getYmin()<<" xMax="<<event->getXmax()<<" Ymax="<<event->getYmax()<<std::endl;
1976            }
1977
1978            for(itr = gw_events.begin();
1979                itr != gw_events.end();
1980                ++itr)
1981            {
1982                osgGA::GUIEventAdapter* event = itr->get();
1983                switch(event->getEventType())
1984                {
1985                    case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
1986                    {
1987                        bool wasThreading = areThreadsRunning();
1988                        if (wasThreading) stopThreading();
1989                       
1990                        gw->close();
1991                       
1992                        if (wasThreading) startThreading();
1993                       
1994                        break;
1995                    }
1996                    default:
1997                        break;
1998                }
1999            }
2000
2001            events.insert(events.end(), gw_events.begin(), gw_events.end());
2002
2003        }
2004    }
2005   
2006
2007    // osg::notify(osg::NOTICE)<<"mouseEventState Xmin = "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl;
2008
2009
2010    _eventQueue->frame( getFrameStamp()->getReferenceTime() );
2011    _eventQueue->takeEvents(events);
2012
2013
2014#if 0
2015    // osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
2016    for(osgGA::EventQueue::Events::iterator itr = events.begin();
2017        itr != events.end();
2018        ++itr)
2019    {
2020        osgGA::GUIEventAdapter* event = itr->get();
2021        switch(event->getEventType())
2022        {
2023            case(osgGA::GUIEventAdapter::PUSH):
2024                osg::notify(osg::NOTICE)<<"  PUSH "<<event->getButton()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2025                break;
2026            case(osgGA::GUIEventAdapter::RELEASE):
2027                osg::notify(osg::NOTICE)<<"  RELEASE "<<event->getButton()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2028                break;
2029            case(osgGA::GUIEventAdapter::DRAG):
2030                osg::notify(osg::NOTICE)<<"  DRAG "<<event->getButtonMask()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2031                break;
2032            case(osgGA::GUIEventAdapter::MOVE):
2033                osg::notify(osg::NOTICE)<<"  MOVE "<<event->getButtonMask()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2034                break;
2035            case(osgGA::GUIEventAdapter::SCROLL):
2036                osg::notify(osg::NOTICE)<<"  SCROLL "<<event->getScrollingMotion()<<std::endl;
2037                break;
2038            case(osgGA::GUIEventAdapter::KEYDOWN):
2039                osg::notify(osg::NOTICE)<<"  KEYDOWN '"<<(char)event->getKey()<<"'"<<std::endl;
2040                break;
2041            case(osgGA::GUIEventAdapter::KEYUP):
2042                osg::notify(osg::NOTICE)<<"  KEYUP '"<<(char)event->getKey()<<"'"<<std::endl;
2043                break;
2044            case(osgGA::GUIEventAdapter::RESIZE):
2045                osg::notify(osg::NOTICE)<<"  RESIZE "<<event->getWindowX()<<"/"<<event->getWindowY()<<" x "<<event->getWindowWidth()<<"/"<<event->getWindowHeight() << std::endl;
2046                break;
2047            case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
2048                osg::notify(osg::NOTICE)<<"  QUIT_APPLICATION " << std::endl;
2049                break;
2050            case(osgGA::GUIEventAdapter::FRAME):
2051                // osg::notify(osg::NOTICE)<<"  FRAME "<<std::endl;
2052                break;
2053            default:
2054                // osg::notify(osg::NOTICE)<<"  Event not handled"<<std::endl;
2055                break;
2056        }
2057    }
2058#endif
2059
2060    // osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
2061   
2062    if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
2063    {
2064        for(osgGA::EventQueue::Events::iterator itr = events.begin();
2065            itr != events.end();
2066            ++itr)
2067        {
2068            osgGA::GUIEventAdapter* event = itr->get();
2069            switch(event->getEventType())
2070            {
2071                case(osgGA::GUIEventAdapter::KEYUP):
2072                    if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true;
2073                    break;
2074               
2075                case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
2076                    if (_quitEventSetsDone) _done = true;
2077                    break;
2078                   
2079                default:
2080                    break;
2081            }
2082        }
2083    }
2084       
2085    if (_done) return;
2086
2087    for(osgGA::EventQueue::Events::iterator itr = events.begin();
2088        itr != events.end();
2089        ++itr)
2090    {
2091        osgGA::GUIEventAdapter* event = itr->get();
2092
2093        for(EventHandlers::iterator hitr = _eventHandlers.begin();
2094            hitr != _eventHandlers.end();
2095            ++hitr)
2096        {
2097            if ((*hitr)->handle( *event, *this, 0, 0)) event->setHandled(true);
2098        }
2099
2100        if (_cameraManipulator.valid())
2101        {
2102            if (_cameraManipulator->handle( *event, *this)) event->setHandled(true);
2103        }
2104       
2105    }
2106
2107    if (_eventVisitor.valid() && _scene.valid())
2108    {
2109        _eventVisitor->setFrameStamp(getFrameStamp());
2110        _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
2111
2112        for(osgGA::EventQueue::Events::iterator itr = events.begin();
2113            itr != events.end();
2114            ++itr)
2115        {
2116            osgGA::GUIEventAdapter* event = itr->get();
2117
2118            _eventVisitor->reset();
2119            _eventVisitor->addEvent( event );
2120
2121            getSceneData()->accept(*_eventVisitor);
2122
2123            // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
2124            // leave that to the scene update traversal.
2125            osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode();
2126            _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
2127
2128            if (_camera.valid() && _camera->getEventCallback()) _camera->accept(*_eventVisitor);
2129
2130            for(unsigned int i=0; i<getNumSlaves(); ++i)
2131            {
2132                osg::Camera* camera = getSlave(i)._camera.get();
2133                if (camera && camera->getEventCallback()) camera->accept(*_eventVisitor);
2134            }
2135
2136            _eventVisitor->setTraversalMode(tm);
2137
2138        }
2139    }
2140
2141    if (getStats() && getStats()->collectStats("event"))
2142    {
2143        double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2144
2145        // update current frames stats
2146        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal);
2147        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal);
2148        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal);
2149    }
2150
2151
2152}
2153
2154void Viewer::updateTraversal()
2155{
2156    if (_done) return;
2157
2158    double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2159
2160    // do the update traversal of the scene.
2161    if (_scene.valid()) _scene->updateTraversal();
2162
2163    osgUtil::UpdateVisitor* uv = _scene.valid() ? _scene->getUpdateVisitor() : 0;
2164    if (uv)
2165    {
2166        // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
2167        // leave that to the scene update traversal.
2168        osg::NodeVisitor::TraversalMode tm = uv->getTraversalMode();
2169        uv->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
2170
2171        if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*uv);
2172
2173        for(unsigned int i=0; i<getNumSlaves(); ++i)
2174        {
2175            osg::Camera* camera = getSlave(i)._camera.get();
2176            if (camera && camera->getUpdateCallback()) camera->accept(*uv);
2177        }
2178
2179        uv->setTraversalMode(tm);
2180    }
2181
2182    if (_cameraManipulator.valid())
2183    {
2184        setFusionDistance( getCameraManipulator()->getFusionDistanceMode(),
2185                            getCameraManipulator()->getFusionDistanceValue() );
2186
2187        _camera->setViewMatrix(_cameraManipulator->getInverseMatrix());
2188    }
2189
2190    updateSlaves();
2191
2192    if (getStats() && getStats()->collectStats("update"))
2193    {
2194        double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2195
2196        // update current frames stats
2197        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
2198        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
2199        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
2200    }
2201}
2202
2203void Viewer::renderingTraversals()
2204{
2205    // check to see if windows are still valid
2206    checkWindowStatus();
2207
2208    if (_done) return;
2209
2210    double beginRenderingTraversals = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2211
2212    osgDB::DatabasePager* dp = _scene.valid() ? _scene->getDatabasePager() : 0;
2213    if (dp)
2214    {
2215        dp->signalBeginFrame(getFrameStamp());
2216    }
2217
2218    // osg::notify(osg::NOTICE)<<std::endl<<"Joing _startRenderingBarrier block"<<std::endl;
2219   
2220
2221    Contexts contexts;
2222    getContexts(contexts);
2223   
2224    Contexts::iterator itr;
2225
2226    // dispatch the the rendering threads
2227    if (_startRenderingBarrier.valid()) _startRenderingBarrier->block();
2228
2229    if (_endDynamicDrawBlock.valid())
2230    {
2231        _endDynamicDrawBlock->reset();
2232    }
2233   
2234    // reset any double buffer graphics objects
2235    for(itr = contexts.begin();
2236        itr != contexts.end();
2237        ++itr)
2238    {
2239        osg::GraphicsContext* gc = (*itr);
2240       
2241        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
2242        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
2243        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
2244            oitr != operations.end();
2245            ++oitr)
2246        {
2247            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
2248            if (vdbro)
2249            {
2250                if (!vdbro->getGraphicsThreadDoesCull() && !(vdbro->getCamera()->getCameraThread()))
2251                {
2252                    vdbro->cull();
2253                }
2254            }
2255        }
2256    }
2257
2258    for(itr = contexts.begin();
2259        itr != contexts.end();
2260        ++itr)
2261    {
2262        if (_done) return;
2263        if (!((*itr)->getGraphicsThread()) && (*itr)->valid())
2264        {
2265            makeCurrent(*itr);
2266            (*itr)->runOperations();
2267        }
2268    }
2269
2270    // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<<std::endl;
2271
2272    // wait till the rendering dispatch is done.
2273    if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block();
2274
2275    for(itr = contexts.begin();
2276        itr != contexts.end();
2277        ++itr)
2278    {
2279        if (_done) return;
2280
2281        if (!((*itr)->getGraphicsThread()) && (*itr)->valid())
2282        {
2283            makeCurrent(*itr);
2284            (*itr)->swapBuffers();
2285        }
2286    }
2287
2288    if (dp)
2289    {
2290        dp->signalEndFrame();
2291    }
2292
2293    // wait till the dynamic draw is complete.
2294    if (_endDynamicDrawBlock.valid())
2295    {
2296        // osg::Timer_t startTick = osg::Timer::instance()->tick();
2297        _endDynamicDrawBlock->block();
2298        // osg::notify(osg::NOTICE)<<"Time waiting "<<osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick())<<std::endl;;
2299    }
2300
2301
2302    if (getStats() && getStats()->collectStats("update"))
2303    {
2304        double endRenderingTraversals = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2305
2306        // update current frames stats
2307        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals begin time ", beginRenderingTraversals);
2308        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals);
2309        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals);
2310    }
2311}
2312
2313void Viewer::getUsage(osg::ApplicationUsage& usage) const
2314{
2315    if (_cameraManipulator.valid())
2316    {
2317        _cameraManipulator->getUsage(usage);
2318    }
2319
2320    for(EventHandlers::const_iterator hitr = _eventHandlers.begin();
2321        hitr != _eventHandlers.end();
2322        ++hitr)
2323    {
2324        (*hitr)->getUsage(usage);
2325    }
2326
2327}
Note: See TracBrowser for help on using the browser.