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

Revision 10740, 29.2 kB (checked in by robert, 4 years ago)

Added glContexVersion, glContextFlags and glContextProfileMask members to osg::GraphicsContext::Traits to support GL3 graphics context creation.

Moved the handling of DisplaySettings? into Traits constructor.

Added support for s/getGLContextVersion(), s/getGLContextFlags() and s/getGLContextProfileMask() to osg::DisplaySettings?.

Added command line and env var support for setting the GLContextVersion, GLContextFlags and GLContextProfileMask to osg::DisplaySettings?.

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