root/OpenSceneGraph/trunk/src/osg/GraphicsContext.cpp @ 10764

Revision 10764, 29.2 kB (checked in by robert, 5 years ago)

<iterator>, <stdlib.h> and <ctype.h> includes required for QNX compiler

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
RevLine 
[5328]1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
[4402]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
[7194]14#include <stdlib.h>
[4402]15
16#include <osg/GraphicsContext>
[5863]17#include <osg/Camera>
18#include <osg/View>
[7773]19#include <osg/GLObjects>
[5863]20
[5933]21#include <osg/FrameBufferObject>
22#include <osg/Program>
23#include <osg/Drawable>
24#include <osg/FragmentProgram>
25#include <osg/VertexProgram>
26
[7071]27#include <OpenThreads/ReentrantMutex>
28
[4415]29#include <osg/Notify>
[5863]30
[4415]31#include <map>
[5845]32#include <sstream>
[7073]33#include <algorithm>
[10764]34#include <iterator>
[4402]35
36using namespace osg;
37
[7071]38/////////////////////////////////////////////////////////////////////////////
[7782]39
40
41// Use a static reference pointer to hold the window system interface.
42// Wrap this within a function, in order to control the order in which
43// the static pointer's constructor is executed.
44
45static ref_ptr<GraphicsContext::WindowingSystemInterface> &windowingSystemInterfaceRef()
46{
47    static ref_ptr<GraphicsContext::WindowingSystemInterface> s_WindowingSystemInterface;
48    return s_WindowingSystemInterface;
49}
50
51
[7071]52//  GraphicsContext static method implementations
53
[5822]54void GraphicsContext::setWindowingSystemInterface(WindowingSystemInterface* callback)
[4402]55{
[7782]56    ref_ptr<GraphicsContext::WindowingSystemInterface> &wsref = windowingSystemInterfaceRef();
57    wsref = callback;
58    osg::notify(osg::INFO)<<"GraphicsContext::setWindowingSystemInterface() "<<wsref.get()<<"\t"<<&wsref<<std::endl;
[4402]59}
60
[5822]61GraphicsContext::WindowingSystemInterface* GraphicsContext::getWindowingSystemInterface()
[4402]62{
[7782]63    ref_ptr<GraphicsContext::WindowingSystemInterface> &wsref = windowingSystemInterfaceRef();
64    osg::notify(osg::INFO)<<"GraphicsContext::getWindowingSystemInterface() "<<wsref.get()<<"\t"<<&wsref<<std::endl;
65    return wsref.get();
[4402]66}
67
68GraphicsContext* GraphicsContext::createGraphicsContext(Traits* traits)
69{
[7782]70    ref_ptr<GraphicsContext::WindowingSystemInterface> &wsref = windowingSystemInterfaceRef();
71    if ( wsref.valid())
[7762]72    {
73        // catch any undefined values.
74        if (traits) traits->setUndefinedScreenDetailsToDefaultScreen();
75       
[7782]76        return wsref->createGraphicsContext(traits);
[7762]77    }
[4402]78    else
79        return 0;   
80}
81
[7182]82GraphicsContext::ScreenIdentifier::ScreenIdentifier():
83    displayNum(0),
84    screenNum(0) {}
[4415]85
[7182]86GraphicsContext::ScreenIdentifier::ScreenIdentifier(int in_screenNum):
87    displayNum(0),
88    screenNum(in_screenNum) {}
89
90GraphicsContext::ScreenIdentifier::ScreenIdentifier(const std::string& in_hostName,int in_displayNum, int in_screenNum):
91    hostName(in_hostName),
92    displayNum(in_displayNum),
93    screenNum(in_screenNum) {}
94
[5845]95std::string GraphicsContext::ScreenIdentifier::displayName() const
96{
97    std::stringstream ostr;
98    ostr<<hostName<<":"<<displayNum<<"."<<screenNum;
99    return ostr.str();
100}
101
[7182]102void GraphicsContext::ScreenIdentifier::readDISPLAY()
103{
104    const char* ptr = 0;
105    if ((ptr=getenv("DISPLAY")) != 0)
106    {
107        setScreenIdentifier(ptr);
108    }
109}
[5845]110
[7182]111void GraphicsContext::ScreenIdentifier::setScreenIdentifier(const std::string& displayName)
112{
113    std::string::size_type colon = displayName.find_last_of(':');
114    std::string::size_type point = displayName.find_last_of('.');
115   
116    if (point!=std::string::npos &&
117        colon==std::string::npos &&
118        point < colon) point = std::string::npos;
119
120    if (colon==std::string::npos)
121    {
122        hostName = "";
123    }
124    else
125    {
126        hostName = displayName.substr(0,colon);
127    }
128   
129    std::string::size_type startOfDisplayNum = (colon==std::string::npos) ? 0 : colon+1;
130    std::string::size_type endOfDisplayNum = (point==std::string::npos) ?  displayName.size() : point;
131
132    if (startOfDisplayNum<endOfDisplayNum)
133    {
134        displayNum = atoi(displayName.substr(startOfDisplayNum,endOfDisplayNum-startOfDisplayNum).c_str());
135    }
136    else
137    {
138        displayNum = -1;
139    }
140
141    if (point!=std::string::npos && point+1<displayName.size())
142    {
143        screenNum = atoi(displayName.substr(point+1,displayName.size()-point-1).c_str());
144    }
145    else
146    {
147        screenNum = -1;
148    }
149
150#if 0   
151    osg::notify(osg::NOTICE)<<"   hostName ["<<hostName<<"]"<<std::endl;
152    osg::notify(osg::NOTICE)<<"   displayNum "<<displayNum<<std::endl;
153    osg::notify(osg::NOTICE)<<"   screenNum "<<screenNum<<std::endl;
154#endif
155}
156
[10740]157GraphicsContext::Traits::Traits(DisplaySettings* ds):
158            x(0),
159            y(0),
160            width(0),
161            height(0),
162            windowDecoration(false),
163            supportsResize(true),
164            red(8),
165            blue(8),
166            green(8),
167            alpha(0),
168            depth(24),
169            stencil(0),
170            sampleBuffers(0),
171            samples(0),
172            pbuffer(false),
173            quadBufferStereo(false),
174            doubleBuffer(false),
175            target(0),
176            format(0),
177            level(0),
178            face(0),
179            mipMapGeneration(false),
180            vsync(true),
181            useMultiThreadedOpenGLEngine(false),
182            useCursor(true),
183            glContextVersion("1.0"),
184            glContextFlags(0),
185            glContextProfileMask(0),
186            sharedContext(0),
187            setInheritedWindowPixelFormat(false),
188            overrideRedirect(false)
189{
190    if (ds)
191    {
192        alpha = ds->getMinimumNumAlphaBits();
193        stencil = ds->getMinimumNumStencilBits();
194        sampleBuffers = ds->getMultiSamples();
195        samples = ds->getNumMultiSamples();
196        if (ds->getStereo())
197        {
198            switch(ds->getStereoMode())
199            {
200                case(osg::DisplaySettings::QUAD_BUFFER): quadBufferStereo = true; break;
201                case(osg::DisplaySettings::VERTICAL_INTERLACE):
202                case(osg::DisplaySettings::CHECKERBOARD):
203                case(osg::DisplaySettings::HORIZONTAL_INTERLACE): stencil = 8; break;
204                default: break;
205            }
206        }
207       
208        glContextVersion = ds->getGLContextVersion();
209        glContextFlags = ds->getGLContextFlags();
210        glContextProfileMask = ds->getGLContextProfileMask();
211    }
212}
213
[7071]214class ContextData
215{
216public:
217
218    ContextData():
219        _numContexts(0) {}
220
221    unsigned int _numContexts;
222   
223    void incrementUsageCount() {  ++_numContexts; }
224
225    void decrementUsageCount()
226    {
227        --_numContexts;
228
229        osg::notify(osg::INFO)<<"decrementUsageCount()"<<_numContexts<<std::endl;
230
231        if (_numContexts <= 1 && _compileContext.valid())
232        {
233            osg::notify(osg::INFO)<<"resetting compileContext "<<_compileContext.get()<<" refCount "<<_compileContext->referenceCount()<<std::endl;
234           
235            _compileContext = 0;
236        }
237    }
238   
239    osg::ref_ptr<osg::GraphicsContext> _compileContext;
240
241};
242
243
244typedef std::map<unsigned int, ContextData>  ContextIDMap;
[4415]245static ContextIDMap s_contextIDMap;
[7071]246static OpenThreads::ReentrantMutex s_contextIDMapMutex;
247static GraphicsContext::GraphicsContexts s_registeredContexts;
[4415]248
249unsigned int GraphicsContext::createNewContextID()
250{
251    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
252   
253    // first check to see if we can reuse contextID;
254    for(ContextIDMap::iterator itr = s_contextIDMap.begin();
255        itr != s_contextIDMap.end();
256        ++itr)
257    {
[7071]258        if (itr->second._numContexts == 0)
[4415]259        {
260
261            // reuse contextID;
[7071]262            itr->second._numContexts = 1;
[4415]263
[4883]264            osg::notify(osg::INFO)<<"GraphicsContext::createNewContextID() reusing contextID="<<itr->first<<std::endl;
[4415]265
266            return itr->first;
267        }
268    }
269
270    unsigned int contextID = s_contextIDMap.size();
[7071]271    s_contextIDMap[contextID]._numContexts = 1;
[4415]272   
273    osg::notify(osg::INFO)<<"GraphicsContext::createNewContextID() creating contextID="<<contextID<<std::endl;
[8499]274    osg::notify(osg::INFO)<<"Updating the MaxNumberOfGraphicsContexts to "<<contextID+1<<std::endl;
[4415]275
[8499]276    // update the the maximum number of graphics contexts,
277    // to ensure that texture objects and display buffers are configured to the correct size.
278    osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts( contextID + 1 );
[4415]279
280    return contextID;   
281}
282
[7071]283unsigned int GraphicsContext::getMaxContextID()
284{
285    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
[7130]286    unsigned int maxContextID = 0;
287    for(ContextIDMap::iterator itr = s_contextIDMap.begin();
288        itr != s_contextIDMap.end();
289        ++itr)
290    {
291        if (itr->first > maxContextID) maxContextID = itr->first;
292    }
293    return maxContextID;
[7071]294}
295
296
[4415]297void GraphicsContext::incrementContextIDUsageCount(unsigned int contextID)
298{
299    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
300   
[7071]301    osg::notify(osg::INFO)<<"GraphicsContext::incrementContextIDUsageCount("<<contextID<<") to "<<s_contextIDMap[contextID]._numContexts<<std::endl;
[4415]302
[7071]303    s_contextIDMap[contextID].incrementUsageCount();
[4415]304}
305
306void GraphicsContext::decrementContextIDUsageCount(unsigned int contextID)
307{
308
309    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
310
[7071]311    if (s_contextIDMap[contextID]._numContexts!=0)
[4415]312    {
[7071]313        s_contextIDMap[contextID].decrementUsageCount();
[4415]314    }
315    else
316    {
317        osg::notify(osg::NOTICE)<<"Warning: decrementContextIDUsageCount("<<contextID<<") called on expired contextID."<<std::endl;
318    }
319
[7071]320    osg::notify(osg::INFO)<<"GraphicsContext::decrementContextIDUsageCount("<<contextID<<") to "<<s_contextIDMap[contextID]._numContexts<<std::endl;
[4415]321
322}
323
324
[7071]325void GraphicsContext::registerGraphicsContext(GraphicsContext* gc)
326{
327    osg::notify(osg::INFO)<<"GraphicsContext::registerGraphicsContext "<<gc<<std::endl;
328
329    if (!gc) return;
330
331    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
332
333    GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc);
334    if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr);
335
336    s_registeredContexts.push_back(gc);
337}
338
339void GraphicsContext::unregisterGraphicsContext(GraphicsContext* gc)
340{
341    osg::notify(osg::INFO)<<"GraphicsContext::unregisterGraphicsContext "<<gc<<std::endl;
342
343    if (!gc) return;
344
345    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
346
347    GraphicsContexts::iterator itr = std::find(s_registeredContexts.begin(), s_registeredContexts.end(), gc);
348    if (itr != s_registeredContexts.end()) s_registeredContexts.erase(itr);
349}
350
351GraphicsContext::GraphicsContexts GraphicsContext::getAllRegisteredGraphicsContexts()
352{
353    osg::notify(osg::INFO)<<"GraphicsContext::getAllRegisteredGraphicsContexts s_registeredContexts.size()="<<s_registeredContexts.size()<<std::endl;
354    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
355    return s_registeredContexts;
356}
357
358GraphicsContext::GraphicsContexts GraphicsContext::getRegisteredGraphicsContexts(unsigned int contextID)
359{
360    GraphicsContexts contexts;
361
362    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
363    for(GraphicsContexts::iterator itr = s_registeredContexts.begin();
364        itr != s_registeredContexts.end();
365        ++itr)
366    {
367        GraphicsContext* gc = *itr;
368        if (gc->getState() && gc->getState()->getContextID()==contextID) contexts.push_back(gc);
369    }
370
371    osg::notify(osg::INFO)<<"GraphicsContext::getRegisteredGraphicsContexts "<<contextID<<" contexts.size()="<<contexts.size()<<std::endl;
372   
373    return contexts;
374}
375
376GraphicsContext* GraphicsContext::getOrCreateCompileContext(unsigned int contextID)
377{
[9868]378    osg::notify(osg::NOTICE)<<"GraphicsContext::createCompileContext."<<std::endl;
[7071]379
380    {   
381        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
382        if (s_contextIDMap[contextID]._compileContext.valid()) return s_contextIDMap[contextID]._compileContext.get();
383    }
384   
385    GraphicsContext::GraphicsContexts contexts = GraphicsContext::getRegisteredGraphicsContexts(contextID);
386    if (contexts.empty()) return 0;
387   
388    GraphicsContext* src_gc = contexts.front();
389    const osg::GraphicsContext::Traits* src_traits = src_gc->getTraits();
390
391    osg::GraphicsContext::Traits* traits = new osg::GraphicsContext::Traits;
392    traits->screenNum = src_traits->screenNum;
393    traits->displayNum = src_traits->displayNum;
394    traits->hostName = src_traits->hostName;
395    traits->width = 100;
396    traits->height = 100;
397    traits->red = src_traits->red;
398    traits->green = src_traits->green;
399    traits->blue = src_traits->blue;
400    traits->alpha = src_traits->alpha;
401    traits->depth = src_traits->depth;
402    traits->sharedContext = src_gc;
403    traits->pbuffer = true;
404
[7130]405    osg::ref_ptr<osg::GraphicsContext> gc = osg::GraphicsContext::createGraphicsContext(traits);
406    if (gc.valid() && gc->realize())
[7071]407    {   
408        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
409        s_contextIDMap[contextID]._compileContext = gc;
[9868]410        osg::notify(osg::NOTICE)<<"   succeeded GraphicsContext::createCompileContext."<<std::endl;
[7130]411        return gc.release();
[7071]412    }
[7130]413    else
414    {
415        return 0;
416    }
[7071]417   
418}
419
420void GraphicsContext::setCompileContext(unsigned int contextID, GraphicsContext* gc)
421{
422    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
423    s_contextIDMap[contextID]._compileContext = gc;
424}
425
426GraphicsContext* GraphicsContext::getCompileContext(unsigned int contextID)
427{
[7130]428    // osg::notify(osg::NOTICE)<<"GraphicsContext::getCompileContext "<<contextID<<std::endl;
[7071]429    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
[7130]430    ContextIDMap::iterator itr = s_contextIDMap.find(contextID);
431    if (itr != s_contextIDMap.end()) return itr->second._compileContext.get();
432    else return 0;
[7071]433}
434
435
436/////////////////////////////////////////////////////////////////////////////
437//
438//  GraphicsContext standard method implementations
439//
[4402]440GraphicsContext::GraphicsContext():
[5907]441    _clearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)),
442    _clearMask(0),
[9916]443    _threadOfLastMakeCurrent(0),
444    _lastClearTick(0)
[4402]445{
[5885]446    setThreadSafeRefUnref(true);
[6267]447    _operationsBlock = new RefBlock;
[7071]448
449    registerGraphicsContext(this);
[4402]450}
451
[6088]452GraphicsContext::GraphicsContext(const GraphicsContext&, const osg::CopyOp&):
453    _clearColor(osg::Vec4(0.0f,0.0f,0.0f,1.0f)),
454    _clearMask(0),
[9916]455    _threadOfLastMakeCurrent(0),
456    _lastClearTick(0)
[6088]457{
458    setThreadSafeRefUnref(true);
[6267]459    _operationsBlock = new RefBlock;
[7071]460
461    registerGraphicsContext(this);
[6088]462}
463
[4415]464GraphicsContext::~GraphicsContext()
465{
[4477]466    close(false);
[7071]467
468    unregisterGraphicsContext(this);
[4415]469}
470
[5907]471void GraphicsContext::clear()
472{
[9916]473    _lastClearTick = osg::Timer::instance()->tick();
474
[5907]475    if (_clearMask==0 || !_traits) return;
476
477    glViewport(0, 0, _traits->width, _traits->height);
478    glScissor(0, 0, _traits->width, _traits->height);
479
480    glClearColor( _clearColor[0], _clearColor[1], _clearColor[2], _clearColor[3]);
481
482    glClear( _clearMask );
483}
484
[4446]485bool GraphicsContext::realize()
486{
487    if (realizeImplementation())
488    {
489        return true;
490    }
491    else
492    {   
493        return false;
494    }
495}
496
[4477]497void GraphicsContext::close(bool callCloseImplementation)
[4446]498{
[5934]499    osg::notify(osg::INFO)<<"close("<<callCloseImplementation<<")"<<this<<std::endl;
[5933]500
[4446]501    // switch off the graphics thread...
502    setGraphicsThread(0);
503   
[5933]504   
[5934]505    bool sharedContextExists = false;
506   
507    if (_state.valid())
[5933]508    {
[5934]509        OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
[7071]510        if (s_contextIDMap[_state->getContextID()]._numContexts>1) sharedContextExists = true;
[5934]511    }
[5933]512
[7648]513    // release all the OpenGL objects in the scene graphs associated with this
[5934]514    for(Cameras::iterator itr = _cameras.begin();
515        itr != _cameras.end();
516        ++itr)
517    {
518        Camera* camera = (*itr);
519        if (camera)
[5933]520        {
[5934]521            osg::notify(osg::INFO)<<"Releasing GL objects for Camera="<<camera<<" _state="<<_state.get()<<std::endl;
522            camera->releaseGLObjects(_state.get());
[5933]523        }
[5934]524    }
[5933]525
526
[5934]527    if (callCloseImplementation && _state.valid() && isRealized())
528    {
529        osg::notify(osg::INFO)<<"Closing still viable window "<<sharedContextExists<<" _state->getContextID()="<<_state->getContextID()<<std::endl;
[5933]530
[7595]531        if (makeCurrent())
532        {
[5933]533       
[7595]534            osg::notify(osg::INFO)<<"Doing Flush"<<std::endl;
[5933]535
[7773]536            osg::flushAllDeletedGLObjects(_state->getContextID());
[5933]537
[7773]538            osg::notify(osg::INFO)<<"Done Flush "<<std::endl;
[5933]539
[7595]540            _state->reset();
541
542            releaseContext();
543        }
544        else
545        {
[7773]546            osg::notify(osg::INFO)<<"makeCurrent did not succeed, could not do flush/deletion of OpenGL objects."<<std::endl;
[7595]547        }
[5933]548    }
549   
[4477]550    if (callCloseImplementation) closeImplementation();
551
[7773]552
553    // now discard any deleted deleted OpenGL objects that the are still hanging around - such as due to
554    // the the flushDelete*() methods not being invoked, such as when using GraphicContextEmbedded where makeCurrent
555    // does not work.
[4477]556    if (_state.valid())
557    {
[7773]558        osg::notify(osg::INFO)<<"Doing discard of deleted OpenGL objects."<<std::endl;
559
560        osg::discardAllDeletedGLObjects(_state->getContextID());
561    }
562
563    if (_state.valid())
564    {
[4477]565        decrementContextIDUsageCount(_state->getContextID());
566       
567        _state = 0;
568    }
[4446]569}
570
571
[5934]572bool GraphicsContext::makeCurrent()
[4442]573{
[5934]574    bool result = makeCurrentImplementation();
[4442]575   
[5934]576    if (result)
[4442]577    {
[5934]578        _threadOfLastMakeCurrent = OpenThreads::Thread::CurrentThread();
[7134]579
[7648]580        // initialize extension process, not only initializes on first
[7134]581        // call, will be a non-op on subsequent calls.       
582        getState()->initializeExtensionProcs();
[4442]583    }
[5934]584   
585    return result;
[4442]586}
587
[5934]588bool GraphicsContext::makeContextCurrent(GraphicsContext* readContext)
[4442]589{
[5934]590    bool result = makeContextCurrentImplementation(readContext);
[4442]591
[5934]592    if (result)
593    {
594        _threadOfLastMakeCurrent = OpenThreads::Thread::CurrentThread();
[7134]595
[7648]596        // initialize extension process, not only initializes on first
[7134]597        // call, will be a non-op on subsequent calls.       
598        getState()->initializeExtensionProcs();
[5934]599    }
600   
601    return result;
[4442]602}
603
[5934]604bool GraphicsContext::releaseContext()
[4442]605{
[5934]606    bool result = releaseContextImplementation();
607   
608    _threadOfLastMakeCurrent = (OpenThreads::Thread*)(-1);
609   
610    return result;
[4442]611}
[4446]612
613void GraphicsContext::swapBuffers()
614{
615    if (isCurrent())
616    {
617        swapBuffersImplementation();
[5907]618        clear();
[4446]619    }
620    else if (_graphicsThread.valid() &&
621             _threadOfLastMakeCurrent == _graphicsThread.get())
622    {
623        _graphicsThread->add(new SwapBuffersOperation);
624    }
625    else
626    {
627        makeCurrent();
628        swapBuffersImplementation();
[5907]629        clear();
[4446]630    }
631}
632
633
634
635void GraphicsContext::createGraphicsThread()
636{
637    if (!_graphicsThread)
638    {
[7108]639        setGraphicsThread(new GraphicsThread);
[4446]640    }
641}
642
[7108]643void GraphicsContext::setGraphicsThread(GraphicsThread* gt)
[4446]644{
645    if (_graphicsThread==gt) return;
646
647    if (_graphicsThread.valid())
648    {
649        // need to kill the thread in some way...
650        _graphicsThread->cancel();
[6088]651        _graphicsThread->setParent(0);
[4446]652    }
653
654    _graphicsThread = gt;
655   
656    if (_graphicsThread.valid())
657    {
[6088]658        _graphicsThread->setParent(this);
[4446]659    }
660}
[5838]661
[6088]662void GraphicsContext::add(Operation* operation)
[5838]663{
664    osg::notify(osg::INFO)<<"Doing add"<<std::endl;
665
[7648]666    // acquire the lock on the operations queue to prevent anyone else for modifying it at the same time
[5838]667    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
668
669    // add the operation to the end of the list
670    _operations.push_back(operation);
671
672    _operationsBlock->set(true);
673}
674
[6088]675void GraphicsContext::remove(Operation* operation)
[5838]676{
677    osg::notify(osg::INFO)<<"Doing remove operation"<<std::endl;
678
[7648]679    // acquire the lock on the operations queue to prevent anyone else for modifying it at the same time
[5838]680    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
681
682    for(OperationQueue::iterator itr = _operations.begin();
683        itr!=_operations.end();)
684    {
685        if ((*itr)==operation) itr = _operations.erase(itr);
686        else ++itr;
687    }
688
689    if (_operations.empty())
690    {
691        _operationsBlock->set(false);
692    }
693}
694
695void GraphicsContext::remove(const std::string& name)
696{
697    osg::notify(osg::INFO)<<"Doing remove named operation"<<std::endl;
698   
[7648]699    // acquire the lock on the operations queue to prevent anyone else for modifying it at the same time
[5838]700    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
701
[7648]702    // find the remove all operations with specified name
[5838]703    for(OperationQueue::iterator itr = _operations.begin();
704        itr!=_operations.end();)
705    {
706        if ((*itr)->getName()==name) itr = _operations.erase(itr);
707        else ++itr;
708    }
709
710    if (_operations.empty())
711    {
712        _operationsBlock->set(false);
713    }
714}
715
716void GraphicsContext::removeAllOperations()
717{
718    osg::notify(osg::INFO)<<"Doing remove all operations"<<std::endl;
719
720    OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
721    _operations.clear();
722    _operationsBlock->set(false);
723}
724
[7306]725
726struct CameraRenderOrderSortOp
727{
728    inline bool operator() (const Camera* lhs,const Camera* rhs) const
729    {
730        if (lhs->getRenderOrder()<rhs->getRenderOrder()) return true;
731        if (rhs->getRenderOrder()<lhs->getRenderOrder()) return false;
[8872]732        return lhs->getRenderOrderNum()<rhs->getRenderOrderNum();
[7306]733    }
734};
735
736
[5838]737void GraphicsContext::runOperations()
738{
[7306]739    // sort the cameras into order
740    typedef std::vector<Camera*> CameraVector;
[7494]741    CameraVector camerasCopy;
742    std::copy(_cameras.begin(), _cameras.end(), std::back_inserter(camerasCopy));
[7306]743    std::sort(camerasCopy.begin(), camerasCopy.end(), CameraRenderOrderSortOp());
744   
745    for(CameraVector::iterator itr = camerasCopy.begin();
746        itr != camerasCopy.end();
[7178]747        ++itr)
748    {
749        osg::Camera* camera = *itr;
750        if (camera->getRenderer()) (*(camera->getRenderer()))(this);
751    }
752
[5838]753    for(OperationQueue::iterator itr = _operations.begin();
754        itr != _operations.end();
755        )
756    {
757        {
758            OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
759            _currentOperation = *itr;
760
761            if (!_currentOperation->getKeep())
762            {
763                itr = _operations.erase(itr);
764
765                if (_operations.empty())
766                {
767                    _operationsBlock->set(false);
768                }
769            }
770            else
771            {
772                ++itr;
773            }
774        }
775               
776        if (_currentOperation.valid())
777        {
[6452]778            // osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "<<this<<std::endl;
[5838]779
780            // call the graphics operation.
781            (*_currentOperation)(this);
782
783            {           
784                OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_operationsMutex);
785                _currentOperation = 0;
786            }
787        }
788    }
789}
[5863]790
791void GraphicsContext::addCamera(osg::Camera* camera)
792{
793    _cameras.push_back(camera);
794}
795
796void GraphicsContext::removeCamera(osg::Camera* camera)
797{
[8499]798    Cameras::iterator itr = std::find(_cameras.begin(), _cameras.end(), camera);
799    if (itr != _cameras.end())
[5863]800    {
[8499]801        // find a set of nodes attached the camera that we are removing that isn't
802        // shared by any other cameras on this GraphicsContext
803        typedef std::set<Node*> NodeSet;
804        NodeSet nodes;
805        for(unsigned int i=0; i<camera->getNumChildren(); ++i)
[5863]806        {
[8499]807            nodes.insert(camera->getChild(i));           
[5863]808        }
[8499]809       
810        for(Cameras::iterator citr = _cameras.begin();
811            citr != _cameras.end();
812            ++citr)
813        {
814            if (citr != itr)
815            {
816                osg::Camera* otherCamera = *citr;
817                for(unsigned int i=0; i<otherCamera->getNumChildren(); ++i)
818                {
819                    NodeSet::iterator nitr = nodes.find(otherCamera->getChild(i));
820                    if (nitr != nodes.end()) nodes.erase(nitr);
821                }
822            }           
823        }
824       
825        // now release the GLobjects associated with these non shared nodes
826        for(NodeSet::iterator nitr = nodes.begin();
827            nitr != nodes.end();
828            ++nitr)
829        {
830            const_cast<osg::Node*>(*nitr)->releaseGLObjects(_state.get());
831        }
832
833        // release the context of the any RenderingCache that the Camera has.
834        if (camera->getRenderingCache())
835        {
836            camera->getRenderingCache()->releaseGLObjects(_state.get());
837        }
838
839        _cameras.erase(itr);
840
[5863]841    }
842}
843
[5933]844void GraphicsContext::resizedImplementation(int x, int y, int width, int height)
[5863]845{
846    if (!_traits) return;
847   
848    double widthChangeRatio = double(width) / double(_traits->width);
849    double heigtChangeRatio = double(height) / double(_traits->height);
850    double aspectRatioChange = widthChangeRatio / heigtChangeRatio;
851   
852    for(Cameras::iterator itr = _cameras.begin();
853        itr != _cameras.end();
854        ++itr)
855    {
856        Camera* camera = (*itr);
[7897]857       
858        // resize doesn't affect Cameras set up with FBO's.
859        if (camera->getRenderTargetImplementation()==osg::Camera::FRAME_BUFFER_OBJECT) continue;
860       
[5863]861        Viewport* viewport = camera->getViewport();
862        if (viewport)
863        {
864            if (viewport->x()==0 && viewport->y()==0 &&
865                viewport->width()>=_traits->width && viewport->height()>=_traits->height)
866            {
867                viewport->setViewport(0,0,width,height);
868            }
869            else
870            {
871                viewport->x() = static_cast<osg::Viewport::value_type>(double(viewport->x())*widthChangeRatio);
872                viewport->y() = static_cast<osg::Viewport::value_type>(double(viewport->y())*heigtChangeRatio);
873                viewport->width() = static_cast<osg::Viewport::value_type>(double(viewport->width())*widthChangeRatio);
874                viewport->height() = static_cast<osg::Viewport::value_type>(double(viewport->height())*heigtChangeRatio);
875            }
876        }
877
878        // if aspect ratio adjusted change the project matrix to suit.
879        if (aspectRatioChange != 1.0)
880        {
881            osg::View* view = camera->getView();
882            osg::View::Slave* slave = view ? view->findSlaveForCamera(camera) : 0;
[10154]883
[10260]884
[10154]885            if (slave)
[5863]886            {
[10154]887                if (camera->getReferenceFrame()==osg::Transform::RELATIVE_RF)
[6729]888                {
[10154]889                    switch(view->getCamera()->getProjectionResizePolicy())
890                    {
891                        case(osg::Camera::HORIZONTAL): slave->_projectionOffset *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0); break;
892                        case(osg::Camera::VERTICAL): slave->_projectionOffset *= osg::Matrix::scale(1.0, aspectRatioChange,1.0); break;
893                        default: break;
894                    }
[6729]895                }
[10154]896                else
897                {
898                    switch(camera->getProjectionResizePolicy())
899                    {
900                        case(osg::Camera::HORIZONTAL): camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0); break;
901                        case(osg::Camera::VERTICAL): camera->getProjectionMatrix() *= osg::Matrix::scale(1.0, aspectRatioChange,1.0); break;
902                        default: break;
903                    }
904                }
[5863]905            }
906            else
907            {
[6790]908                Camera::ProjectionResizePolicy policy = view ? view->getCamera()->getProjectionResizePolicy() : camera->getProjectionResizePolicy();
909                switch(policy)
[5863]910                {
[6729]911                    case(osg::Camera::HORIZONTAL): camera->getProjectionMatrix() *= osg::Matrix::scale(1.0/aspectRatioChange,1.0,1.0); break;
912                    case(osg::Camera::VERTICAL): camera->getProjectionMatrix() *= osg::Matrix::scale(1.0, aspectRatioChange,1.0); break;
913                    default: break;
[5863]914                }
[10260]915
916                osg::Camera* master = view ? view->getCamera() : 0;
917                if (view && camera==master)
918                {
919                    for(unsigned int i=0; i<view->getNumSlaves(); ++i)
920                    {
921                        osg::View::Slave& child = view->getSlave(i);
922                        if (child._camera.valid() && child._camera->getReferenceFrame()==osg::Transform::RELATIVE_RF)
923                        {
924                            // scale the slaves by the inverse of the change that has been applied to master, to avoid them be
925                            // scaled twice (such as when both master and slave are on the same GraphicsContexts) or by the wrong scale
926                            // when master and slave are on different GraphicsContexts.
927                            switch(policy)
928                            {
929                                case(osg::Camera::HORIZONTAL): child._projectionOffset *= osg::Matrix::scale(aspectRatioChange,1.0,1.0); break;
930                                case(osg::Camera::VERTICAL): child._projectionOffset *= osg::Matrix::scale(1.0, 1.0/aspectRatioChange,1.0); break;
931                                default: break;
932                            }
933                        }
934                    }
935                }
936
937
[5863]938            }
939
[10154]940        }
[5863]941
942    }
[10154]943
[5863]944    _traits->x = x;
945    _traits->y = y;
946    _traits->width = width;
947    _traits->height = height;
948}
Note: See TracBrowser for help on using the browser.