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

Revision 7019, 77.5 kB (checked in by robert, 7 years ago)

Added setting of the Camera's projection matrix to fit the windowing aspect ratio.

  • 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()->setProjectionMatrixAsPerspective(30.0f, static_cast<double>(width)/static_cast<double>(height), 1.0f, 10000.0f);
829    getCamera()->setGraphicsContext(gw);
830    return gw;
831}
832
833void Viewer::setThreadingModel(ThreadingModel threadingModel)
834{
835    if (_threadingModel == threadingModel) return;
836   
837    if (_threadsRunning) stopThreading();
838   
839    _threadingModel = threadingModel;
840
841    if (isRealized() && _threadingModel!=SingleThreaded) startThreading();
842}
843
844void Viewer::setUpThreading()
845{
846    Contexts contexts;
847    getContexts(contexts);
848
849    _numWindowsOpenAtLastSetUpThreading = contexts.size();
850
851    if (_threadingModel==SingleThreaded)
852    {
853        if (_threadsRunning) stopThreading();
854        else
855        {
856            // we'll set processor affinity here to help single threaded apps
857            // with multiple processor cores, and using the database pager.
858            int numProcessors = OpenThreads::GetNumberOfProcessors();
859            bool affinity = numProcessors>1;   
860            if (affinity)
861            {
862                OpenThreads::SetProcessorAffinityOfCurrentThread(0);
863                if (_scene.valid() && _scene->getDatabasePager())
864                {
865                    _scene->getDatabasePager()->setProcessorAffinity(1);
866                }
867            }
868        }
869    }
870    else
871    {
872        if (!_threadsRunning) startThreading();
873    }
874   
875}
876
877
878void Viewer::setUseMainThreadForRenderingTraversals(bool flag)
879{
880    if (_useMainThreadForRenderingTraversal==flag) return;
881
882    if (_threadsRunning) stopThreading();
883   
884    _useMainThreadForRenderingTraversal = flag;
885   
886    if (_threadingModel!=SingleThreaded) startThreading();
887}
888
889void Viewer::setEndBarrierPosition(BarrierPosition bp)
890{
891    if (_endBarrierPosition == bp) return;
892   
893    if (_threadsRunning) stopThreading();
894   
895    _endBarrierPosition = bp;
896
897    if (_threadingModel!=SingleThreaded) startThreading();
898}
899
900void Viewer::stopThreading()
901{
902    if (!_threadsRunning) return;
903
904    osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopping threading"<<std::endl;
905
906    Contexts contexts;
907    getContexts(contexts);
908
909    Cameras cameras;
910    getCameras(cameras);
911
912    Contexts::iterator gcitr;
913    Cameras::iterator citr;
914
915    // reset any double buffer graphics objects
916    for(gcitr = contexts.begin();
917        gcitr != contexts.end();
918        ++gcitr)
919    {
920        osg::GraphicsContext* gc = (*gcitr);
921       
922        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
923        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
924        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
925            oitr != operations.end();
926            ++oitr)
927        {
928            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
929            if (vdbro)
930            {
931                vdbro->release();
932            }
933        }
934
935    }
936
937    // delete all the graphics threads.   
938    for(gcitr = contexts.begin();
939        gcitr != contexts.end();
940        ++gcitr)
941    {
942        (*gcitr)->setGraphicsThread(0);
943    }
944
945    // delete all the camera threads.   
946    for(citr = cameras.begin();
947        citr != cameras.end();
948        ++citr)
949    {
950        (*citr)->setCameraThread(0);
951    }
952
953    // reset any double buffer graphics objects
954    for(gcitr = contexts.begin();
955        gcitr != contexts.end();
956        ++gcitr)
957    {
958        osg::GraphicsContext* gc = (*gcitr);
959       
960        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
961        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
962        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
963            oitr != operations.end();
964            ++oitr)
965        {
966            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
967            if (vdbro)
968            {
969                vdbro->setGraphicsThreadDoesCull( true );
970                vdbro->_done = false;
971            }
972        }
973
974    }
975
976    int numProcessors = OpenThreads::GetNumberOfProcessors();
977    bool affinity = numProcessors>1;   
978    if (affinity)
979    {
980        OpenThreads::SetProcessorAffinityOfCurrentThread(0);
981        if (_scene.valid() && _scene->getDatabasePager())
982        {
983            _scene->getDatabasePager()->setProcessorAffinity(1);
984        }
985    }
986
987    _threadsRunning = false;
988    _startRenderingBarrier = 0;
989    _endRenderingDispatchBarrier = 0;
990    _endDynamicDrawBlock = 0;
991    _numWindowsOpenAtLastSetUpThreading = contexts.size();
992
993    osg::notify(osg::INFO)<<"Viewer::stopThreading() - stopped threading."<<std::endl;
994}
995
996// Compile operation, that compile OpenGL objects.
997struct ViewerCompileOperation : public osg::Operation
998{
999    ViewerCompileOperation(osg::Node* scene):
1000        osg::Operation("Compile",false),
1001        _scene(scene)
1002    {
1003    }
1004   
1005    virtual void operator () (osg::Object* object)
1006    {
1007        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1008        if (!context) return;
1009
1010        // OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
1011        // osg::notify(osg::NOTICE)<<"Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
1012
1013        // context->makeCurrent();
1014       
1015        context->getState()->initializeExtensionProcs();
1016
1017        osgUtil::GLObjectsVisitor compileVisitor;
1018        compileVisitor.setState(context->getState());
1019
1020        // do the compile traversal
1021        if (_scene.valid()) _scene->accept(compileVisitor);
1022
1023        // osg::notify(osg::NOTICE)<<"Done Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
1024    }
1025   
1026    osg::ref_ptr<osg::Node> _scene;
1027};
1028
1029
1030// Draw operation, that does a draw on the scene graph.
1031struct ViewerRunOperations : public osg::Operation
1032{
1033    ViewerRunOperations():
1034        osg::Operation("RunOperation",true)
1035    {
1036    }
1037   
1038    virtual void operator () (osg::Object* object)
1039    {
1040        osg::GraphicsContext* context = dynamic_cast<osg::GraphicsContext*>(object);
1041        if (!context) return;
1042
1043        context->runOperations();
1044    }
1045};
1046
1047static 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.");
1048static osg::ApplicationUsageProxy Viewer_e1(osg::ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_SCREEN <value>","Set the default screen that windows should open up on.");
1049static 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.");
1050
1051Viewer::ThreadingModel Viewer::suggestBestThreadingModel()
1052{
1053    const char* str = getenv("OSG_THREADING");
1054    if (str)
1055    {
1056        if (strcmp(str,"SingleThreaded")==0) return SingleThreaded;
1057        else if (strcmp(str,"CullDrawThreadPerContext")==0) return CullDrawThreadPerContext;
1058        else if (strcmp(str,"DrawThreadPerContext")==0) return DrawThreadPerContext;
1059        else if (strcmp(str,"CullThreadPerCameraDrawThreadPerContext")==0) return CullThreadPerCameraDrawThreadPerContext;
1060    }
1061
1062    Contexts contexts;
1063    getContexts(contexts);
1064   
1065    if (contexts.empty()) return SingleThreaded;
1066
1067#if 0
1068#ifdef _WIN32
1069    // temporary hack to disable multi-threading under Windows till we find good solutions for
1070    // crashes that users are seeing.
1071    return SingleThreaded;
1072#endif
1073#endif
1074
1075    Cameras cameras;
1076    getCameras(cameras);
1077
1078    if (cameras.empty()) return SingleThreaded;
1079
1080
1081    int numProcessors = OpenThreads::GetNumberOfProcessors();
1082
1083    if (contexts.size()==1)
1084    {
1085        if (numProcessors==1) return SingleThreaded;
1086        else return DrawThreadPerContext;
1087    }
1088
1089    if (numProcessors >= static_cast<int>(cameras.size()+contexts.size()))
1090    {
1091        return CullThreadPerCameraDrawThreadPerContext;
1092    }
1093
1094#if 1
1095        return DrawThreadPerContext;
1096#else
1097        return CullDrawThreadPerContext;
1098#endif
1099}
1100
1101void Viewer::startThreading()
1102{
1103    if (_threadsRunning) return;
1104   
1105    // osg::notify(osg::NOTICE)<<"Viewer::startThreading() - starting threading"<<std::endl;
1106   
1107    // release any context held by the main thread.
1108    releaseContext();
1109
1110    _threadingModel = _threadingModel==AutomaticSelection ? suggestBestThreadingModel() : _threadingModel;
1111
1112    Contexts contexts;
1113    getContexts(contexts);
1114   
1115    osg::notify(osg::INFO)<<"Viewer::startThreading() - contexts.size()="<<contexts.size()<<std::endl;
1116
1117    Cameras cameras;
1118    getCameras(cameras);
1119   
1120    unsigned int numThreadsOnBarrier = 0;
1121    switch(_threadingModel)
1122    {
1123        case(SingleThreaded):
1124            numThreadsOnBarrier = 1;
1125            return;
1126        case(CullDrawThreadPerContext):
1127            numThreadsOnBarrier = contexts.size()+1;
1128            break;
1129        case(DrawThreadPerContext):
1130            numThreadsOnBarrier = 1;
1131            break;
1132        case(CullThreadPerCameraDrawThreadPerContext):
1133            numThreadsOnBarrier = _useMainThreadForRenderingTraversal ? cameras.size() : cameras.size()+1;
1134            break;
1135        default:
1136            osg::notify(osg::NOTICE)<<"Error: Threading model not selected"<<std::endl;
1137            return;
1138    }
1139
1140    // using multi-threading so make sure that new objects are allocated with thread safe ref/unref
1141    osg::Referenced::setThreadSafeReferenceCounting(true);
1142   
1143    if (getSceneData())
1144    {
1145        osg::notify(osg::INFO)<<"Making scene thread safe"<<std::endl;
1146
1147        // make sure that existing scene graph objects are allocated with thread safe ref/unref
1148        getSceneData()->setThreadSafeRefUnref(true);
1149       
1150        // update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it.
1151        getSceneData()->resizeGLObjectBuffers(osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts());
1152    }
1153   
1154    int numProcessors = OpenThreads::GetNumberOfProcessors();
1155    bool affinity = numProcessors>1;   
1156   
1157    Contexts::iterator citr;
1158
1159    unsigned int numViewerDoubleBufferedRenderingOperation = 0;
1160
1161    bool graphicsThreadsDoesCull = _threadingModel == CullDrawThreadPerContext;
1162
1163    // reset any double buffer graphics objects
1164    for(citr = contexts.begin();
1165        citr != contexts.end();
1166        ++citr)
1167    {
1168        osg::GraphicsContext* gc = (*citr);
1169       
1170        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
1171        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
1172        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
1173            oitr != operations.end();
1174            ++oitr)
1175        {
1176            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
1177            if (vdbro)
1178            {
1179                vdbro->setGraphicsThreadDoesCull( graphicsThreadsDoesCull );
1180                vdbro->_done = false;
1181                ++numViewerDoubleBufferedRenderingOperation;
1182            }
1183        }
1184
1185    }
1186
1187    if (_threadingModel==CullDrawThreadPerContext)
1188    {
1189        _startRenderingBarrier = 0;
1190        _endRenderingDispatchBarrier = 0;
1191        _endDynamicDrawBlock = 0;
1192    }
1193    else if (_threadingModel==DrawThreadPerContext ||
1194             _threadingModel==CullThreadPerCameraDrawThreadPerContext)
1195    {
1196        _startRenderingBarrier = 0;
1197        _endRenderingDispatchBarrier = 0;
1198        _endDynamicDrawBlock = new EndOfDynamicDrawBlock(numViewerDoubleBufferedRenderingOperation);
1199       
1200        if (!osg::Referenced::getDeleteHandler()) osg::Referenced::setDeleteHandler(new osg::DeleteHandler(2));
1201        else osg::Referenced::getDeleteHandler()->setNumFramesToRetainObjects(2);
1202       
1203        // now make sure the scene graph is set up with the correct DataVariance to protect the dyamic elements of
1204        // the scene graph from being run in parallel.
1205        osgUtil::Optimizer::StaticObjectDetectionVisitor sodv;
1206        getSceneData()->accept(sodv);
1207    }
1208   
1209    if (numThreadsOnBarrier>1)
1210    {
1211        _startRenderingBarrier = new osg::BarrierOperation(numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
1212        _endRenderingDispatchBarrier = new osg::BarrierOperation(numThreadsOnBarrier, osg::BarrierOperation::NO_OPERATION);
1213    }
1214
1215
1216    osg::ref_ptr<osg::BarrierOperation> swapReadyBarrier = contexts.empty() ? 0 : new osg::BarrierOperation(contexts.size(), osg::BarrierOperation::NO_OPERATION);
1217
1218    osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
1219
1220    typedef std::map<OpenThreads::Thread*, int> ThreadAffinityMap;
1221    ThreadAffinityMap threadAffinityMap;
1222
1223    unsigned int processNum = 1;
1224    for(citr = contexts.begin();
1225        citr != contexts.end();
1226        ++citr, ++processNum)
1227    {
1228        osg::GraphicsContext* gc = (*citr);
1229       
1230        gc->getState()->setDynamicObjectRenderingCompletedCallback(_endDynamicDrawBlock.get());
1231
1232        // create the a graphics thread for this context
1233        gc->createGraphicsThread();
1234
1235        if (affinity) gc->getGraphicsThread()->setProcessorAffinity(processNum % numProcessors);
1236        threadAffinityMap[gc->getGraphicsThread()] = processNum % numProcessors;
1237
1238        gc->getGraphicsThread()->add(new ViewerCompileOperation(getSceneData()));
1239
1240        // add the startRenderingBarrier
1241        if (_threadingModel==CullDrawThreadPerContext && _startRenderingBarrier.valid()) gc->getGraphicsThread()->add(_startRenderingBarrier.get());
1242
1243        // add the rendering operation itself.
1244        gc->getGraphicsThread()->add(new ViewerRunOperations());
1245
1246        if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==BeforeSwapBuffers && _endRenderingDispatchBarrier.valid())
1247        {
1248            // add the endRenderingDispatchBarrier
1249            gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
1250        }
1251
1252        if (swapReadyBarrier.valid()) gc->getGraphicsThread()->add(swapReadyBarrier.get());
1253
1254        // add the swap buffers
1255        gc->getGraphicsThread()->add(swapOp.get());
1256
1257        if (_threadingModel==CullDrawThreadPerContext && _endBarrierPosition==AfterSwapBuffers && _endRenderingDispatchBarrier.valid())
1258        {
1259            // add the endRenderingDispatchBarrier
1260            gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
1261        }
1262
1263
1264
1265    }
1266
1267   
1268    if (_threadingModel==CullThreadPerCameraDrawThreadPerContext && numThreadsOnBarrier>1)
1269    {
1270        Cameras::iterator camItr = cameras.begin();
1271        if (_useMainThreadForRenderingTraversal) ++camItr;
1272
1273        for(;
1274            camItr != cameras.end();
1275            ++camItr, ++processNum)
1276        {
1277            osg::Camera* camera = *camItr;
1278            camera->createCameraThread();
1279
1280            if (affinity) camera->getCameraThread()->setProcessorAffinity(processNum % numProcessors);
1281            threadAffinityMap[camera->getCameraThread()] = processNum % numProcessors;
1282
1283            osg::GraphicsContext* gc = camera->getGraphicsContext();
1284
1285            // add the startRenderingBarrier
1286            if (_startRenderingBarrier.valid()) camera->getCameraThread()->add(_startRenderingBarrier.get());
1287
1288            OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
1289            osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
1290            for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
1291                oitr != operations.end();
1292                ++oitr)
1293            {
1294                ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
1295                if (vdbro && vdbro->getCamera()==camera)
1296                {
1297                    camera->getCameraThread()->add(vdbro);
1298                }
1299            }
1300           
1301            if (_endRenderingDispatchBarrier.valid())
1302            {
1303                // add the endRenderingDispatchBarrier
1304                gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get());
1305            }
1306
1307        }
1308
1309        for(camItr = cameras.begin();
1310            camItr != cameras.end();
1311            ++camItr)
1312        {
1313            osg::Camera* camera = *camItr;
1314            if (camera->getCameraThread() && !camera->getCameraThread()->isRunning())
1315            {
1316                osg::notify(osg::INFO)<<"  camera->getCameraThread()-> "<<camera->getCameraThread()<<std::endl;
1317                camera->getCameraThread()->startThread();
1318            }
1319        }
1320    }
1321   
1322    if (affinity)
1323    {
1324        OpenThreads::SetProcessorAffinityOfCurrentThread(0);
1325        if (_scene.valid() && _scene->getDatabasePager())
1326        {
1327#if 0       
1328            //_scene->getDatabasePager()->setProcessorAffinity(1);
1329#else
1330            _scene->getDatabasePager()->setProcessorAffinity(0);
1331#endif
1332        }
1333    }
1334
1335#if 0
1336    if (affinity)
1337    {
1338        for(ThreadAffinityMap::iterator titr = threadAffinityMap.begin();
1339            titr != threadAffinityMap.end();
1340            ++titr)
1341        {
1342            titr->first->setProcessorAffinity(titr->second);
1343        }
1344    }
1345#endif
1346
1347
1348    for(citr = contexts.begin();
1349        citr != contexts.end();
1350        ++citr)
1351    {
1352        osg::GraphicsContext* gc = (*citr);
1353        if (gc->getGraphicsThread() && !gc->getGraphicsThread()->isRunning())
1354        {
1355            osg::notify(osg::INFO)<<"  gc->getGraphicsThread()->startThread() "<<gc->getGraphicsThread()<<std::endl;
1356            gc->getGraphicsThread()->startThread();
1357            // OpenThreads::Thread::YieldCurrentThread();
1358        }
1359    }
1360
1361    _threadsRunning = true;
1362    _numWindowsOpenAtLastSetUpThreading = contexts.size();
1363
1364    osg::notify(osg::INFO)<<"Set up threading"<<std::endl;
1365}
1366
1367void Viewer::checkWindowStatus()
1368{
1369    Contexts contexts;
1370    getContexts(contexts);
1371   
1372    // osg::notify(osg::NOTICE)<<"Viewer::checkWindowStatus() - "<<contexts.size()<<std::endl;
1373   
1374    if (contexts.size()==0)
1375    {
1376        _done = true;
1377        if (areThreadsRunning()) stopThreading();
1378    }
1379}
1380
1381
1382struct LessGraphicsContext
1383{
1384    bool operator () (const osg::GraphicsContext* lhs, const osg::GraphicsContext* rhs) const
1385    {
1386        int screenLeft = lhs->getTraits()? lhs->getTraits()->screenNum : 0;
1387        int screenRight = rhs->getTraits()? rhs->getTraits()->screenNum : 0;
1388        if (screenLeft < screenRight) return true;
1389        if (screenLeft > screenRight) return false;
1390
1391        screenLeft = lhs->getTraits()? lhs->getTraits()->x : 0;
1392        screenRight = rhs->getTraits()? rhs->getTraits()->x : 0;
1393        if (screenLeft < screenRight) return true;
1394        if (screenLeft > screenRight) return false;
1395
1396        screenLeft = lhs->getTraits()? lhs->getTraits()->y : 0;
1397        screenRight = rhs->getTraits()? rhs->getTraits()->y : 0;
1398        if (screenLeft < screenRight) return true;
1399        if (screenLeft > screenRight) return false;
1400       
1401        return lhs < rhs;
1402    }
1403};
1404
1405void Viewer::getContexts(Contexts& contexts, bool onlyValid)
1406{
1407    typedef std::set<osg::GraphicsContext*> ContextSet;
1408    ContextSet contextSet;
1409
1410    if (_camera.valid() &&
1411        _camera->getGraphicsContext() &&
1412        (_camera->getGraphicsContext()->valid() || !onlyValid))
1413    {
1414        contextSet.insert(_camera->getGraphicsContext());
1415    }
1416   
1417    for(unsigned int i=0; i<getNumSlaves(); ++i)
1418    {
1419        Slave& slave = getSlave(i);
1420        if (slave._camera.valid() &&
1421            slave._camera->getGraphicsContext() &&
1422            (slave._camera->getGraphicsContext()->valid() || !onlyValid))
1423        {
1424            contextSet.insert(slave._camera->getGraphicsContext());
1425        }
1426    }
1427
1428    contexts.clear();
1429    contexts.reserve(contextSet.size());
1430
1431    for(ContextSet::iterator itr = contextSet.begin();
1432        itr != contextSet.end();
1433        ++itr)
1434    {
1435        contexts.push_back(const_cast<osg::GraphicsContext*>(*itr));
1436    }
1437
1438    if (contexts.size()>=2)
1439    {
1440        std::sort(contexts.begin(), contexts.end(), LessGraphicsContext());
1441    }
1442}
1443
1444void Viewer::getWindows(Windows& windows, bool onlyValid)
1445{
1446    windows.clear();
1447
1448    Contexts contexts;
1449    getContexts(contexts, onlyValid);
1450   
1451    for(Contexts::iterator itr = contexts.begin();
1452        itr != contexts.end();
1453        ++itr)
1454    {
1455        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*itr);
1456        if (gw) windows.push_back(gw);
1457    }
1458}
1459
1460void Viewer::getCameras(Cameras& cameras, bool onlyActive)
1461{
1462    cameras.clear();
1463   
1464    if (!onlyActive || (_camera->getGraphicsContext() && _camera->getGraphicsContext()->valid()) ) cameras.push_back(_camera.get());
1465
1466    for(Slaves::iterator itr = _slaves.begin();
1467        itr != _slaves.end();
1468        ++itr)
1469    {
1470        if (!onlyActive || (itr->_camera->getGraphicsContext() && itr->_camera->getGraphicsContext()->valid()) ) cameras.push_back(itr->_camera.get());
1471    }
1472       
1473}
1474
1475void Viewer::getAllThreads(Threads& threads, bool onlyActive)
1476{
1477    OperationsThreads operationsThreads;
1478    getOperationsThreads(operationsThreads);
1479   
1480    for(OperationsThreads::iterator itr = operationsThreads.begin();
1481        itr != operationsThreads.end();
1482        ++itr)
1483    {
1484        threads.push_back(*itr);
1485    }
1486   
1487    if (_scene.valid() &&
1488        _scene->getDatabasePager() &&
1489       (!onlyActive || _scene->getDatabasePager()->isRunning()))
1490    {
1491        threads.push_back(_scene->getDatabasePager());
1492    }
1493}
1494
1495
1496void Viewer::getOperationsThreads(OperationsThreads& threads, bool onlyActive)
1497{
1498    threads.clear();
1499   
1500    Contexts contexts;
1501    getContexts(contexts);
1502    for(Contexts::iterator gcitr = contexts.begin();
1503        gcitr != contexts.end();
1504        ++gcitr)
1505    {
1506        osg::GraphicsContext* gc = *gcitr;
1507        if (gc->getGraphicsThread() &&
1508            (!onlyActive || gc->getGraphicsThread()->isRunning()) )
1509        {
1510            threads.push_back(gc->getGraphicsThread());
1511        }
1512    }
1513   
1514    Cameras cameras;
1515    getCameras(cameras);
1516    for(Cameras::iterator citr = cameras.begin();
1517        citr != cameras.end();
1518        ++citr)
1519    {
1520        osg::Camera* camera = *citr;
1521        if (camera->getCameraThread() &&
1522            (!onlyActive || camera->getCameraThread()->isRunning()) )
1523        {
1524            threads.push_back(camera->getCameraThread());
1525        }
1526    }
1527   
1528}
1529
1530void Viewer::setUpRenderingSupport()
1531{
1532    bool threadsRunningBeforeSetUpRenderingSupport = _threadsRunning;
1533    if (_threadsRunning) stopThreading();
1534
1535    _sceneViews.clear();
1536
1537    Contexts contexts;
1538    getContexts(contexts);
1539   
1540    osg::FrameStamp* frameStamp = getFrameStamp();
1541    osg::DisplaySettings* ds = _displaySettings.valid() ? _displaySettings.get() : osg::DisplaySettings::instance();
1542    osgDB::DatabasePager* dp = _scene.valid() ? _scene->getDatabasePager() : 0;
1543
1544    bool graphicsThreadDoesCull = _threadingModel!=CullThreadPerCameraDrawThreadPerContext;
1545    unsigned int numViewerDoubleBufferedRenderingOperation = 0;
1546   
1547    Cameras localCameras;
1548    getCameras(localCameras);
1549   
1550    unsigned int sceneViewOptions = osgUtil::SceneView::HEADLIGHT;
1551
1552    if (true)//(_threadingModel==CullThreadPerCameraDrawThreadPerContext)
1553    {
1554        for(Contexts::iterator gcitr = contexts.begin();
1555            gcitr != contexts.end();
1556            ++gcitr)
1557        {
1558            (*gcitr)->removeAllOperations();
1559
1560            osg::GraphicsContext* gc = *gcitr;
1561            osg::GraphicsContext::Cameras& cameras = gc->getCameras();
1562            osg::State* state = gc->getState();
1563           
1564            if (dp) dp->setCompileGLObjectsForContextID(state->getContextID(), true);
1565
1566            for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
1567                citr != cameras.end();
1568                ++citr)
1569            {
1570                osg::Camera* camera = *citr;
1571                if (!camera->getStats()) camera->setStats(new osg::Stats("Camera"));
1572               
1573                bool localCamera = std::find(localCameras.begin(),localCameras.end(),camera) != localCameras.end();
1574                if (localCamera)
1575                {
1576                    osgUtil::SceneView* sceneViewList[2];
1577
1578                    for(int i=0; i<2; ++i)
1579                    {
1580                        osgUtil::SceneView* sceneView = new osgUtil::SceneView;
1581
1582                        _sceneViews.push_back(sceneView);                   
1583                        sceneViewList[i] = sceneView;
1584
1585                        sceneView->setGlobalStateSet(_camera->getStateSet());
1586                        sceneView->setDefaults(sceneViewOptions);
1587                        sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ? camera->getDisplaySettings() : ds);
1588                        sceneView->setCamera(camera);
1589                        sceneView->setState(state);
1590                        sceneView->setFrameStamp(frameStamp);
1591                    }
1592
1593
1594                    // osg::notify(osg::NOTICE)<<"localCamera "<<camera->getName()<<std::endl;
1595                    ViewerDoubleBufferedRenderingOperation* vdbro = new ViewerDoubleBufferedRenderingOperation(graphicsThreadDoesCull, sceneViewList[0], sceneViewList[1], dp, _startTick);
1596                    gc->add(vdbro);
1597                    ++numViewerDoubleBufferedRenderingOperation;
1598                }
1599                else
1600                {
1601                    // osg::notify(osg::NOTICE)<<"non local Camera"<<std::endl;
1602
1603                    osgUtil::SceneView* sceneView = new osgUtil::SceneView;
1604
1605                    _sceneViews.push_back(sceneView);                   
1606
1607                    sceneView->setGlobalStateSet(_camera->getStateSet());
1608                    sceneView->setDefaults(sceneViewOptions);
1609                    sceneView->setDisplaySettings(ds);
1610                    sceneView->setCamera(camera);
1611                    sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ? camera->getDisplaySettings() : ds);
1612                    sceneView->setState(state);
1613                    sceneView->setFrameStamp(frameStamp);
1614
1615                    ViewerRenderingOperation* vro = new ViewerRenderingOperation(sceneView, dp, _startTick);
1616                    gc->add(vro);
1617                }
1618
1619            }
1620        }
1621    }
1622    else
1623    {
1624        for(Contexts::iterator gcitr = contexts.begin();
1625            gcitr != contexts.end();
1626            ++gcitr)
1627        {
1628            (*gcitr)->removeAllOperations();
1629
1630            osg::GraphicsContext* gc = *gcitr;
1631            osg::GraphicsContext::Cameras& cameras = gc->getCameras();
1632            osg::State* state = gc->getState();
1633
1634            for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
1635                citr != cameras.end();
1636                ++citr)
1637            {
1638                osg::Camera* camera = *citr;
1639
1640                if (!camera->getStats()) camera->setStats(new osg::Stats("Camera"));
1641
1642                osgUtil::SceneView* sceneView = new osgUtil::SceneView;
1643                _sceneViews.push_back(sceneView);
1644
1645                sceneView->setGlobalStateSet(_camera->getStateSet());
1646                sceneView->setDefaults(sceneViewOptions);
1647                sceneView->setDisplaySettings(camera->getDisplaySettings()!=0 ? camera->getDisplaySettings() : ds);
1648                sceneView->setCamera(camera);
1649                sceneView->setState(state);
1650                sceneView->setFrameStamp(frameStamp);
1651
1652                if (dp) dp->setCompileGLObjectsForContextID(state->getContextID(), true);
1653
1654                gc->add(new ViewerRenderingOperation(sceneView, dp, _startTick));
1655
1656                ++numViewerDoubleBufferedRenderingOperation;
1657            }
1658        }
1659    }
1660
1661    if (_endDynamicDrawBlock.valid())
1662    {
1663        _endDynamicDrawBlock->setNumOfBlocks(numViewerDoubleBufferedRenderingOperation);
1664    }
1665
1666    if (threadsRunningBeforeSetUpRenderingSupport) startThreading();
1667}
1668
1669
1670void Viewer::realize()
1671{
1672    //osg::notify(osg::INFO)<<"Viewer::realize()"<<std::endl;
1673   
1674    setCameraWithFocus(0);
1675
1676    Contexts contexts;
1677    getContexts(contexts);
1678   
1679    if (contexts.empty())
1680    {
1681        osg::notify(osg::INFO)<<"Viewer::realize() - No valid contexts found, setting up view across all screens."<<std::endl;
1682   
1683        // no windows are already set up so set up a default view       
1684       
1685        const char* ptr = 0;
1686        int screenNum = -1;
1687        if ((ptr = getenv("OSG_SCREEN")) != 0)
1688        {
1689            if (strlen(ptr)!=0) screenNum = atoi(ptr);
1690            else screenNum = -1;
1691        }
1692       
1693        int x = -1, y = -1, width = -1, height = -1;
1694        if ((ptr = getenv("OSG_WINDOW")) != 0)
1695        {
1696            std::istringstream iss(ptr);
1697            iss >> x >> y >> width >> height;
1698        }
1699
1700        if (width>0 && height>0)
1701        {
1702            if (screenNum>=0) setUpViewInWindow(x, y, width, height, screenNum);
1703            else setUpViewInWindow(x,y,width,height);
1704        }
1705        else if (screenNum>=0)
1706        {
1707            setUpViewOnSingleScreen(screenNum);
1708        }
1709        else
1710        {
1711            setUpViewAcrossAllScreens();
1712        }
1713
1714        getContexts(contexts);
1715    }
1716
1717    if (contexts.empty())
1718    {
1719        osg::notify(osg::NOTICE)<<"Viewer::realize() - failed to set up any windows"<<std::endl;
1720        _done = true;
1721        return;
1722    }
1723   
1724    setUpRenderingSupport();
1725   
1726    for(Contexts::iterator citr = contexts.begin();
1727        citr != contexts.end();
1728        ++citr)
1729    {
1730        osg::GraphicsContext* gc = *citr;
1731        gc->realize();
1732       
1733        if (_realizeOperation.valid() && gc->valid())
1734        {
1735            gc->makeCurrent();
1736           
1737            (*_realizeOperation)(gc);
1738           
1739            gc->releaseContext();
1740        }
1741    }
1742   
1743    bool grabFocus = true;
1744    if (grabFocus)
1745    {
1746        for(Contexts::iterator citr = contexts.begin();
1747            citr != contexts.end();
1748            ++citr)
1749        {
1750            osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
1751            if (gw)
1752            {
1753                gw->grabFocusIfPointerInWindow();   
1754            }
1755        }
1756    }
1757   
1758    // initialize the global timer to be relative to the current time.
1759    osg::Timer::instance()->setStartTick();
1760
1761    // pass on the start tick to all the associated eventqueues
1762    setStartTick(osg::Timer::instance()->getStartTick());
1763
1764    setUpThreading();
1765}
1766
1767
1768void Viewer::frame(double simulationTime)
1769{
1770    if (_done) return;
1771
1772    // osg::notify(osg::NOTICE)<<std::endl<<"Viewer::frame()"<<std::endl<<std::endl;
1773
1774    if (_firstFrame)
1775    {
1776        init();
1777       
1778        if (!isRealized())
1779        {
1780            realize();
1781        }
1782       
1783        _firstFrame = false;
1784    }
1785    advance(simulationTime);
1786   
1787    eventTraversal();
1788    updateTraversal();
1789    renderingTraversals();
1790}
1791
1792void Viewer::advance(double simulationTime)
1793{
1794    if (_done) return;
1795
1796    double prevousReferenceTime = _frameStamp->getReferenceTime();
1797    int previousFrameNumber = _frameStamp->getFrameNumber();
1798
1799    _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1);
1800
1801    _frameStamp->setReferenceTime( osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick()) );
1802
1803    if (simulationTime==USE_REFERENCE_TIME)
1804    {
1805        _frameStamp->setSimulationTime(_frameStamp->getReferenceTime());
1806    }
1807    else
1808    {
1809        _frameStamp->setSimulationTime(simulationTime);
1810    }
1811   
1812    if (getStats() && getStats()->collectStats("frame_rate"))
1813    {
1814        // update previous frame stats
1815        double deltaFrameTime = _frameStamp->getReferenceTime() - prevousReferenceTime;
1816        getStats()->setAttribute(previousFrameNumber, "Frame duration", deltaFrameTime);
1817        getStats()->setAttribute(previousFrameNumber, "Frame rate", 1.0/deltaFrameTime);
1818
1819        // update current frames stats
1820        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Reference time", _frameStamp->getReferenceTime());
1821    }
1822
1823    if (osg::Referenced::getDeleteHandler())
1824    {
1825        osg::Referenced::getDeleteHandler()->flush();
1826        osg::Referenced::getDeleteHandler()->setFrameNumber(_frameStamp->getFrameNumber());
1827    }
1828
1829}
1830
1831void Viewer::eventTraversal()
1832{
1833    if (_done) return;
1834
1835    double beginEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
1836
1837    // osg::notify(osg::NOTICE)<<"Viewer::frameEventTraversal()."<<std::endl;
1838   
1839    // need to copy events from the GraphicsWindow's into local EventQueue;
1840    osgGA::EventQueue::Events events;
1841
1842    Contexts contexts;
1843    getContexts(contexts);
1844
1845    osgGA::GUIEventAdapter* eventState = getEventQueue()->getCurrentEventState();
1846    osg::Matrix masterCameraVPW = getCamera()->getViewMatrix() * getCamera()->getProjectionMatrix();
1847    if (getCamera()->getViewport())
1848    {
1849        osg::Viewport* viewport = getCamera()->getViewport();
1850        masterCameraVPW *= viewport->computeWindowMatrix();
1851        eventState->setInputRange( viewport->x(), viewport->y(), viewport->x() + viewport->width(), viewport->y() + viewport->height());
1852    }
1853    else
1854    {
1855        eventState->setInputRange(-1.0, -1.0, 1.0, 1.0);
1856    }
1857
1858
1859    for(Contexts::iterator citr = contexts.begin();
1860        citr != contexts.end();
1861        ++citr)
1862    {
1863        osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
1864        if (gw)
1865        {
1866            gw->checkEvents();
1867           
1868            osgGA::EventQueue::Events gw_events;
1869            gw->getEventQueue()->takeEvents(gw_events);
1870           
1871            osgGA::EventQueue::Events::iterator itr;
1872            for(itr = gw_events.begin();
1873                itr != gw_events.end();
1874                ++itr)
1875            {
1876                osgGA::GUIEventAdapter* event = itr->get();
1877               
1878                bool pointerEvent = false;
1879
1880                float x = event->getX();
1881                float y = event->getY();
1882               
1883                bool invert_y = event->getMouseYOrientation()==osgGA::GUIEventAdapter::Y_INCREASING_DOWNWARDS;
1884                if (invert_y && gw->getTraits()) y = gw->getTraits()->height - y;
1885               
1886                switch(event->getEventType())
1887                {
1888                    case(osgGA::GUIEventAdapter::PUSH):
1889                    case(osgGA::GUIEventAdapter::RELEASE):
1890                    case(osgGA::GUIEventAdapter::DRAG):
1891                    case(osgGA::GUIEventAdapter::MOVE):
1892                    {
1893                        pointerEvent = true;
1894                       
1895                        if (event->getEventType()!=osgGA::GUIEventAdapter::DRAG || !getCameraWithFocus())
1896                        {
1897                            osg::GraphicsContext::Cameras& cameras = gw->getCameras();
1898                            for(osg::GraphicsContext::Cameras::iterator citr = cameras.begin();
1899                                citr != cameras.end();
1900                                ++citr)
1901                            {
1902                                osg::Camera* camera = *citr;
1903                                if (camera->getView()==this &&
1904                                    camera->getAllowEventFocus() &&
1905                                    camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER)
1906                                {
1907                                    osg::Viewport* viewport = camera ? camera->getViewport() : 0;
1908                                    if (viewport &&
1909                                        x >= viewport->x() && y >= viewport->y() &&
1910                                        x <= (viewport->x()+viewport->width()) && y <= (viewport->y()+viewport->height()) )
1911                                    {
1912                                        // osg::notify(osg::NOTICE)<<"setCamera with focus "<<camera->getName()<<" x="<<x<<" y="<<y<<std::endl;
1913                                        setCameraWithFocus(camera);
1914                                    }
1915                                }
1916                            }
1917                        }
1918                       
1919                        break;
1920                    }
1921                    default:
1922                        break;
1923                }
1924               
1925                if (pointerEvent)
1926                {
1927                    if (getCameraWithFocus())
1928                    {
1929                        osg::Viewport* viewport = getCameraWithFocus()->getViewport();
1930                        osg::Matrix localCameraVPW = getCameraWithFocus()->getViewMatrix() * getCameraWithFocus()->getProjectionMatrix();
1931                        if (viewport) localCameraVPW *= viewport->computeWindowMatrix();
1932
1933                        osg::Matrix matrix( osg::Matrix::inverse(localCameraVPW) * masterCameraVPW );
1934
1935                        osg::Vec3d new_coord = osg::Vec3d(x,y,0.0) * matrix;
1936
1937                        x = new_coord.x();
1938                        y = new_coord.y();                               
1939
1940                        // osg::notify(osg::NOTICE)<<"pointer event new_coord.x()="<<new_coord.x()<<" new_coord.y()="<<new_coord.y()<<std::endl;
1941
1942                        event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
1943                        event->setX(x);
1944                        event->setY(y);
1945                        event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
1946
1947                    }
1948                    else
1949                    {
1950                        x = eventState->getXmin() + (x/double(gw->getTraits()->width))*(eventState->getXmax() - eventState->getXmin());
1951                        y = eventState->getYmin() + (y/double(gw->getTraits()->height))*(eventState->getYmax() - eventState->getYmin());
1952                        // osg::notify(osg::NOTICE)<<"new x = "<<x<<" new y = "<<y<<std::endl;
1953
1954                        event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
1955                        event->setX(x);
1956                        event->setY(y);
1957                        event->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
1958                    }
1959                   
1960                    // pass along the new pointer events details to the eventState of the viewer
1961                    eventState->setX(x);
1962                    eventState->setY(y);
1963                    eventState->setButtonMask(event->getButtonMask());
1964                    eventState->setMouseYOrientation(osgGA::GUIEventAdapter::Y_INCREASING_UPWARDS);
1965
1966                }
1967                else
1968                {
1969                    event->setInputRange(eventState->getXmin(), eventState->getYmin(), eventState->getXmax(), eventState->getYmax());
1970                    event->setX(eventState->getX());
1971                    event->setY(eventState->getY());
1972                    event->setButtonMask(eventState->getButtonMask());
1973                    event->setMouseYOrientation(eventState->getMouseYOrientation());
1974                }
1975                //osg::notify(osg::NOTICE)<<"   mouse x = "<<event->getX()<<" y="<<event->getY()<<std::endl;
1976                // osg::notify(osg::NOTICE)<<"   mouse Xmin = "<<event->getXmin()<<" Ymin="<<event->getYmin()<<" xMax="<<event->getXmax()<<" Ymax="<<event->getYmax()<<std::endl;
1977            }
1978
1979            for(itr = gw_events.begin();
1980                itr != gw_events.end();
1981                ++itr)
1982            {
1983                osgGA::GUIEventAdapter* event = itr->get();
1984                switch(event->getEventType())
1985                {
1986                    case(osgGA::GUIEventAdapter::CLOSE_WINDOW):
1987                    {
1988                        bool wasThreading = areThreadsRunning();
1989                        if (wasThreading) stopThreading();
1990                       
1991                        gw->close();
1992                       
1993                        if (wasThreading) startThreading();
1994                       
1995                        break;
1996                    }
1997                    default:
1998                        break;
1999                }
2000            }
2001
2002            events.insert(events.end(), gw_events.begin(), gw_events.end());
2003
2004        }
2005    }
2006   
2007
2008    // osg::notify(osg::NOTICE)<<"mouseEventState Xmin = "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl;
2009
2010
2011    _eventQueue->frame( getFrameStamp()->getReferenceTime() );
2012    _eventQueue->takeEvents(events);
2013
2014
2015#if 0
2016    // osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
2017    for(osgGA::EventQueue::Events::iterator itr = events.begin();
2018        itr != events.end();
2019        ++itr)
2020    {
2021        osgGA::GUIEventAdapter* event = itr->get();
2022        switch(event->getEventType())
2023        {
2024            case(osgGA::GUIEventAdapter::PUSH):
2025                osg::notify(osg::NOTICE)<<"  PUSH "<<event->getButton()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2026                break;
2027            case(osgGA::GUIEventAdapter::RELEASE):
2028                osg::notify(osg::NOTICE)<<"  RELEASE "<<event->getButton()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2029                break;
2030            case(osgGA::GUIEventAdapter::DRAG):
2031                osg::notify(osg::NOTICE)<<"  DRAG "<<event->getButtonMask()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2032                break;
2033            case(osgGA::GUIEventAdapter::MOVE):
2034                osg::notify(osg::NOTICE)<<"  MOVE "<<event->getButtonMask()<<" x="<<event->getX()<<" y="<<event->getY()<<std::endl;
2035                break;
2036            case(osgGA::GUIEventAdapter::SCROLL):
2037                osg::notify(osg::NOTICE)<<"  SCROLL "<<event->getScrollingMotion()<<std::endl;
2038                break;
2039            case(osgGA::GUIEventAdapter::KEYDOWN):
2040                osg::notify(osg::NOTICE)<<"  KEYDOWN '"<<(char)event->getKey()<<"'"<<std::endl;
2041                break;
2042            case(osgGA::GUIEventAdapter::KEYUP):
2043                osg::notify(osg::NOTICE)<<"  KEYUP '"<<(char)event->getKey()<<"'"<<std::endl;
2044                break;
2045            case(osgGA::GUIEventAdapter::RESIZE):
2046                osg::notify(osg::NOTICE)<<"  RESIZE "<<event->getWindowX()<<"/"<<event->getWindowY()<<" x "<<event->getWindowWidth()<<"/"<<event->getWindowHeight() << std::endl;
2047                break;
2048            case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
2049                osg::notify(osg::NOTICE)<<"  QUIT_APPLICATION " << std::endl;
2050                break;
2051            case(osgGA::GUIEventAdapter::FRAME):
2052                // osg::notify(osg::NOTICE)<<"  FRAME "<<std::endl;
2053                break;
2054            default:
2055                // osg::notify(osg::NOTICE)<<"  Event not handled"<<std::endl;
2056                break;
2057        }
2058    }
2059#endif
2060
2061    // osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
2062   
2063    if ((_keyEventSetsDone!=0) || _quitEventSetsDone)
2064    {
2065        for(osgGA::EventQueue::Events::iterator itr = events.begin();
2066            itr != events.end();
2067            ++itr)
2068        {
2069            osgGA::GUIEventAdapter* event = itr->get();
2070            switch(event->getEventType())
2071            {
2072                case(osgGA::GUIEventAdapter::KEYUP):
2073                    if (_keyEventSetsDone && event->getKey()==_keyEventSetsDone) _done = true;
2074                    break;
2075               
2076                case(osgGA::GUIEventAdapter::QUIT_APPLICATION):
2077                    if (_quitEventSetsDone) _done = true;
2078                    break;
2079                   
2080                default:
2081                    break;
2082            }
2083        }
2084    }
2085       
2086    if (_done) return;
2087
2088    for(osgGA::EventQueue::Events::iterator itr = events.begin();
2089        itr != events.end();
2090        ++itr)
2091    {
2092        osgGA::GUIEventAdapter* event = itr->get();
2093
2094        for(EventHandlers::iterator hitr = _eventHandlers.begin();
2095            hitr != _eventHandlers.end();
2096            ++hitr)
2097        {
2098            if ((*hitr)->handle( *event, *this, 0, 0)) event->setHandled(true);
2099        }
2100
2101        if (_cameraManipulator.valid())
2102        {
2103            if (_cameraManipulator->handle( *event, *this)) event->setHandled(true);
2104        }
2105       
2106    }
2107
2108    if (_eventVisitor.valid() && _scene.valid())
2109    {
2110        _eventVisitor->setFrameStamp(getFrameStamp());
2111        _eventVisitor->setTraversalNumber(getFrameStamp()->getFrameNumber());
2112
2113        for(osgGA::EventQueue::Events::iterator itr = events.begin();
2114            itr != events.end();
2115            ++itr)
2116        {
2117            osgGA::GUIEventAdapter* event = itr->get();
2118
2119            _eventVisitor->reset();
2120            _eventVisitor->addEvent( event );
2121
2122            getSceneData()->accept(*_eventVisitor);
2123
2124            // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
2125            // leave that to the scene update traversal.
2126            osg::NodeVisitor::TraversalMode tm = _eventVisitor->getTraversalMode();
2127            _eventVisitor->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
2128
2129            if (_camera.valid() && _camera->getEventCallback()) _camera->accept(*_eventVisitor);
2130
2131            for(unsigned int i=0; i<getNumSlaves(); ++i)
2132            {
2133                osg::Camera* camera = getSlave(i)._camera.get();
2134                if (camera && camera->getEventCallback()) camera->accept(*_eventVisitor);
2135            }
2136
2137            _eventVisitor->setTraversalMode(tm);
2138
2139        }
2140    }
2141
2142    if (getStats() && getStats()->collectStats("event"))
2143    {
2144        double endEventTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2145
2146        // update current frames stats
2147        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal begin time", beginEventTraversal);
2148        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal end time", endEventTraversal);
2149        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Event traversal time taken", endEventTraversal-beginEventTraversal);
2150    }
2151
2152
2153}
2154
2155void Viewer::updateTraversal()
2156{
2157    if (_done) return;
2158
2159    double beginUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2160
2161    // do the update traversal of the scene.
2162    if (_scene.valid()) _scene->updateTraversal();
2163
2164    osgUtil::UpdateVisitor* uv = _scene.valid() ? _scene->getUpdateVisitor() : 0;
2165    if (uv)
2166    {
2167        // call any camera update callbacks, but only traverse that callback, don't traverse its subgraph
2168        // leave that to the scene update traversal.
2169        osg::NodeVisitor::TraversalMode tm = uv->getTraversalMode();
2170        uv->setTraversalMode(osg::NodeVisitor::TRAVERSE_NONE);
2171
2172        if (_camera.valid() && _camera->getUpdateCallback()) _camera->accept(*uv);
2173
2174        for(unsigned int i=0; i<getNumSlaves(); ++i)
2175        {
2176            osg::Camera* camera = getSlave(i)._camera.get();
2177            if (camera && camera->getUpdateCallback()) camera->accept(*uv);
2178        }
2179
2180        uv->setTraversalMode(tm);
2181    }
2182
2183    if (_cameraManipulator.valid())
2184    {
2185        setFusionDistance( getCameraManipulator()->getFusionDistanceMode(),
2186                            getCameraManipulator()->getFusionDistanceValue() );
2187
2188        _camera->setViewMatrix(_cameraManipulator->getInverseMatrix());
2189    }
2190
2191    updateSlaves();
2192
2193    if (getStats() && getStats()->collectStats("update"))
2194    {
2195        double endUpdateTraversal = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2196
2197        // update current frames stats
2198        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal begin time", beginUpdateTraversal);
2199        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal end time", endUpdateTraversal);
2200        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Update traversal time taken", endUpdateTraversal-beginUpdateTraversal);
2201    }
2202}
2203
2204void Viewer::renderingTraversals()
2205{
2206    // check to see if windows are still valid
2207    checkWindowStatus();
2208
2209    if (_done) return;
2210
2211    double beginRenderingTraversals = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2212
2213    osgDB::DatabasePager* dp = _scene.valid() ? _scene->getDatabasePager() : 0;
2214    if (dp)
2215    {
2216        dp->signalBeginFrame(getFrameStamp());
2217    }
2218
2219    // osg::notify(osg::NOTICE)<<std::endl<<"Joing _startRenderingBarrier block"<<std::endl;
2220   
2221
2222    Contexts contexts;
2223    getContexts(contexts);
2224   
2225    Contexts::iterator itr;
2226
2227    // dispatch the the rendering threads
2228    if (_startRenderingBarrier.valid()) _startRenderingBarrier->block();
2229
2230    if (_endDynamicDrawBlock.valid())
2231    {
2232        _endDynamicDrawBlock->reset();
2233    }
2234   
2235    // reset any double buffer graphics objects
2236    for(itr = contexts.begin();
2237        itr != contexts.end();
2238        ++itr)
2239    {
2240        osg::GraphicsContext* gc = (*itr);
2241       
2242        OpenThreads::ScopedLock<OpenThreads::Mutex> lock( *(gc->getOperationsMutex()) );
2243        osg::GraphicsContext::OperationQueue& operations = gc->getOperationsQueue();
2244        for(osg::GraphicsContext::OperationQueue::iterator oitr = operations.begin();
2245            oitr != operations.end();
2246            ++oitr)
2247        {
2248            ViewerDoubleBufferedRenderingOperation* vdbro = dynamic_cast<ViewerDoubleBufferedRenderingOperation*>(oitr->get());
2249            if (vdbro)
2250            {
2251                if (!vdbro->getGraphicsThreadDoesCull() && !(vdbro->getCamera()->getCameraThread()))
2252                {
2253                    vdbro->cull();
2254                }
2255            }
2256        }
2257    }
2258
2259    for(itr = contexts.begin();
2260        itr != contexts.end();
2261        ++itr)
2262    {
2263        if (_done) return;
2264        if (!((*itr)->getGraphicsThread()) && (*itr)->valid())
2265        {
2266            makeCurrent(*itr);
2267            (*itr)->runOperations();
2268        }
2269    }
2270
2271    // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<<std::endl;
2272
2273    // wait till the rendering dispatch is done.
2274    if (_endRenderingDispatchBarrier.valid()) _endRenderingDispatchBarrier->block();
2275
2276    for(itr = contexts.begin();
2277        itr != contexts.end();
2278        ++itr)
2279    {
2280        if (_done) return;
2281
2282        if (!((*itr)->getGraphicsThread()) && (*itr)->valid())
2283        {
2284            makeCurrent(*itr);
2285            (*itr)->swapBuffers();
2286        }
2287    }
2288
2289    if (dp)
2290    {
2291        dp->signalEndFrame();
2292    }
2293
2294    // wait till the dynamic draw is complete.
2295    if (_endDynamicDrawBlock.valid())
2296    {
2297        // osg::Timer_t startTick = osg::Timer::instance()->tick();
2298        _endDynamicDrawBlock->block();
2299        // osg::notify(osg::NOTICE)<<"Time waiting "<<osg::Timer::instance()->delta_m(startTick, osg::Timer::instance()->tick())<<std::endl;;
2300    }
2301
2302
2303    if (getStats() && getStats()->collectStats("update"))
2304    {
2305        double endRenderingTraversals = osg::Timer::instance()->delta_s(_startTick, osg::Timer::instance()->tick());
2306
2307        // update current frames stats
2308        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals begin time ", beginRenderingTraversals);
2309        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals end time ", endRenderingTraversals);
2310        getStats()->setAttribute(_frameStamp->getFrameNumber(), "Rendering traversals time taken", endRenderingTraversals-beginRenderingTraversals);
2311    }
2312}
2313
2314void Viewer::getUsage(osg::ApplicationUsage& usage) const
2315{
2316    if (_cameraManipulator.valid())
2317    {
2318        _cameraManipulator->getUsage(usage);
2319    }
2320
2321    for(EventHandlers::const_iterator hitr = _eventHandlers.begin();
2322        hitr != _eventHandlers.end();
2323        ++hitr)
2324    {
2325        (*hitr)->getUsage(usage);
2326    }
2327
2328}
Note: See TracBrowser for help on using the browser.