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

Revision 13041, 29.7 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

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