diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index a3a1809d5..667555d66 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -15,10 +15,7 @@ #define OSG_GRAPHICSCONTEXT 1 #include - -#include - -#include +#include namespace osg { @@ -144,57 +141,44 @@ class OSG_EXPORT GraphicsContext : public Referenced /** Return true if the graphics context has been realised and is ready to use.*/ virtual bool isRealized() const = 0; - /** Release the graphics context.*/ - virtual void release() = 0; + /** close the graphics context.*/ + virtual void close() = 0; - /** Make this graphics context current.*/ - virtual void makeCurrent() = 0; + /** Make this graphics context current. + * Implementated by first aquiring a lock of the GraphicsContext mutex, and then doing a call to makeCurrentImplementation(). */ + void makeCurrent(); - /** Make this graphics context current with specified read context.*/ - virtual void makeContextCurrent(GraphicsContext* readContext) = 0; + /** Make this graphics context current with specified read context. + * Implementated by first aquiring a lock of the GraphicsContext mutex, and then doing a call to makeContextCurrentImplementation(). */ + void makeContextCurrent(GraphicsContext* readContext); - virtual void releaseContext() = 0; + /** Release the graphics context by unlocking the GraphicsContext mutex.*/ + void releaseContext(); /** Return true if the current thread has this OpenGL graphics context.*/ inline bool isCurrent() const { return _threadOfLastMakeCurrent == OpenThreads::Thread::CurrentThread(); } + /** Make this graphics context current.*/ + virtual void makeCurrentImplementation() = 0; + + /** Make this graphics context current with specified read context.*/ + virtual void makeContextCurrentImplementation(GraphicsContext* readContext) = 0; + /** Bind the graphics context to associated texture.*/ virtual void bindPBufferToTexture(GLenum buffer) = 0; /** swap the front and back buffers.*/ virtual void swapBuffers() = 0; - public: - - - struct GraphicsOperation : public Referenced - { - virtual void operator () (GraphicsContext& context) {} - }; - - class GraphicsThread : public Referenced, OpenThreads::Thread - { - public: - GraphicsThread() {} - - typedef std::list< ref_ptr > OperationList; - - void add(GraphicsOperation* operation); - - virtual void run(); - - protected: - virtual ~GraphicsThread() {} - - OpenThreads::Mutex _runListMutex; - OperationList _operations; - - }; - + /** Assign a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/ void setGraphicsThread(GraphicsThread* gt) { _graphicsThread = gt; } + + /** Get the graphics thread assigned the graphics context.*/ GraphicsThread* getGraphicsThread() { return _graphicsThread.get(); } + + /** Get the const graphics thread assigned the graphics context.*/ const GraphicsThread* getGraphicsThread() const { return _graphicsThread.get(); } protected: @@ -205,6 +189,7 @@ class OSG_EXPORT GraphicsContext : public Referenced ref_ptr _traits; ref_ptr _state; + OpenThreads::Mutex _mutex; OpenThreads::Thread* _threadOfLastMakeCurrent; ref_ptr _graphicsThread; diff --git a/include/osgDB/DatabasePager b/include/osgDB/DatabasePager index 3b8fc45a8..d02c2ad2e 100644 --- a/include/osgDB/DatabasePager +++ b/include/osgDB/DatabasePager @@ -18,6 +18,7 @@ #include #include #include +#include #include #include @@ -32,54 +33,6 @@ namespace osgDB { -class Block: public osg::Referenced { - public: - Block():_released(false) {} - - inline void block() - { - OpenThreads::ScopedLock mutlock(_mut); - if( !_released ) - _cond.wait(&_mut); - } - - inline void release() - { - OpenThreads::ScopedLock mutlock(_mut); - if (!_released) - { - _released = true; - _cond.broadcast(); - } - } - - inline void reset() - { - OpenThreads::ScopedLock mutlock(_mut); - _released = false; - } - - inline void set(bool doRelease) - { - if (doRelease!=_released) - { - if (doRelease) release(); - else reset(); - } - } - - protected: - - ~Block() - { - release(); - } - - private: - OpenThreads::Mutex _mut; - OpenThreads::Condition _cond; - bool _released; -}; /** Database paging class which manages the loading of files in a background thread, * and syncronizing of loaded models with the main scene graph.*/ @@ -125,7 +78,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl /** Get the whether UseFrameBlock is on or off.*/ bool getUseFrameBlock() const { return _useFrameBlock; } - Block* getFrameBlock() { return _frameBlock.get(); } + osg::Block* getFrameBlock() { return _frameBlock.get(); } /** Set the priority of the database pager thread during the frame (i.e. while cull and draw are running.)*/ void setThreadPriorityDuringFrame(ThreadPriority duringFrame) { _threadPriorityDuringFrame = duringFrame; } @@ -313,7 +266,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl bool _startThreadCalled; - osg::ref_ptr _databasePagerThreadBlock; + osg::ref_ptr _databasePagerThreadBlock; inline void updateDatabasePagerThreadBlock() { @@ -345,7 +298,7 @@ class OSGDB_EXPORT DatabasePager : public osg::NodeVisitor::DatabaseRequestHandl bool _useFrameBlock; int _numFramesActive; mutable OpenThreads::Mutex _numFramesActiveMutex; - osg::ref_ptr _frameBlock; + osg::ref_ptr _frameBlock; int _frameNumber; ThreadPriority _threadPriorityDuringFrame; diff --git a/include/osgProducer/GraphicsContextImplementation b/include/osgProducer/GraphicsContextImplementation index e70939bd4..e3fb29427 100644 --- a/include/osgProducer/GraphicsContextImplementation +++ b/include/osgProducer/GraphicsContextImplementation @@ -51,13 +51,13 @@ class OSGPRODUCER_EXPORT GraphicsContextImplementation : public osg::GraphicsCon virtual bool isRealized() const { return _rs.valid() && _rs->isRealized(); } /** Release the graphics context.*/ - virtual void release(); + virtual void close(); /** Make this graphics context current.*/ - virtual void makeCurrent(); + virtual void makeCurrentImplementation(); /** Make this graphics context current with specified read context.*/ - virtual void makeContextCurrent(GraphicsContext* readContext); + virtual void makeContextCurrentImplementation(GraphicsContext* readContext); /** Bind the graphics context to associated texture.*/ virtual void bindPBufferToTexture(GLenum buffer); diff --git a/src/osg/GNUmakefile b/src/osg/GNUmakefile index a4a5fa41a..733640772 100644 --- a/src/osg/GNUmakefile +++ b/src/osg/GNUmakefile @@ -45,6 +45,7 @@ CXXFILES =\ Geometry.cpp\ GLExtensions.cpp\ GraphicsContext.cpp\ + GraphicsThread.cpp\ Group.cpp\ Image.cpp\ ImageStream.cpp\ diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index d8a1cf1a3..e7209d01d 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -125,3 +125,43 @@ GraphicsContext::~GraphicsContext() } } +void GraphicsContext::makeCurrent() +{ + + ReleaseContext_Block_MakeCurrentOperation* rcbmco = 0; + + if (_graphicsThread.valid() && + _threadOfLastMakeCurrent == _graphicsThread.get()) + { + // create a relase contex, block and make current operation to stop the graphics thread while we use the graphics context for ourselves + rcbmco = new ReleaseContext_Block_MakeCurrentOperation; + _graphicsThread->add(rcbmco); + } + + if (!isCurrent()) _mutex.lock(); + + makeCurrentImplementation(); + + _threadOfLastMakeCurrent = OpenThreads::Thread::CurrentThread(); + + if (rcbmco) + { + // Let the "relase contex, block and make current operation" proceed, which will now move on to trying to aquire the graphics + // contex itself with a makeCurrent(), this will then block on the GraphicsContext mutex till releaseContext() releases it. + rcbmco->release(); + } +} + +void GraphicsContext::makeContextCurrent(GraphicsContext* readContext) +{ + if (!isCurrent()) _mutex.lock(); + + makeContextCurrentImplementation(readContext); + + _threadOfLastMakeCurrent = OpenThreads::Thread::CurrentThread(); +} + +void GraphicsContext::releaseContext() +{ + _mutex.unlock(); +} diff --git a/src/osgDB/DatabasePager.cpp b/src/osgDB/DatabasePager.cpp index dca8fc345..c5007fe3e 100644 --- a/src/osgDB/DatabasePager.cpp +++ b/src/osgDB/DatabasePager.cpp @@ -37,8 +37,8 @@ DatabasePager::DatabasePager() _useFrameBlock = false; _numFramesActive = 0; _frameNumber = 0; - _frameBlock = new Block; - _databasePagerThreadBlock = new Block; + _frameBlock = new osg::Block; + _databasePagerThreadBlock = new osg::Block; _threadPriorityDuringFrame = THREAD_PRIORITY_MIN; _threadPriorityOutwithFrame = THREAD_PRIORITY_MIN; diff --git a/src/osgProducer/GraphicsContextImplementation.cpp b/src/osgProducer/GraphicsContextImplementation.cpp index 8f63bdbae..5bbb46bbc 100644 --- a/src/osgProducer/GraphicsContextImplementation.cpp +++ b/src/osgProducer/GraphicsContextImplementation.cpp @@ -159,7 +159,7 @@ GraphicsContextImplementation::GraphicsContextImplementation(Producer::RenderSur GraphicsContextImplementation::~GraphicsContextImplementation() { - release(); + close(); } bool GraphicsContextImplementation::realize() @@ -184,7 +184,7 @@ bool GraphicsContextImplementation::realize() } } -void GraphicsContextImplementation::makeCurrent() +void GraphicsContextImplementation::makeCurrentImplementation() { if (!_rs) return; @@ -193,7 +193,7 @@ void GraphicsContextImplementation::makeCurrent() _rs->makeCurrent(); } -void GraphicsContextImplementation::makeContextCurrent(GraphicsContext* readContext) +void GraphicsContextImplementation::makeContextCurrentImplementation(GraphicsContext* readContext) { if (!_rs) return; @@ -207,7 +207,7 @@ void GraphicsContextImplementation::makeContextCurrent(GraphicsContext* readCont _rs->makeCurrent(); } -void GraphicsContextImplementation::release() +void GraphicsContextImplementation::close() { if (!_rs) return; diff --git a/src/osgProducer/Viewer.cpp b/src/osgProducer/Viewer.cpp index a773678d8..b49333f21 100644 --- a/src/osgProducer/Viewer.cpp +++ b/src/osgProducer/Viewer.cpp @@ -684,8 +684,7 @@ void Viewer::update() // create an event to signal the new frame. osg::ref_ptr frame_event = new osgProducer::EventAdapter; -// frame_event->adaptFrame(__frameStamp->getReferenceTime()); - frame_event->adaptFrame(_kbmcb->getTime()); + frame_event->adaptFrame(_frameStamp->getReferenceTime()); queue.push_back(frame_event); if (_eventVisitor.valid()) diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 8aa51bfc5..713cdf8d5 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -160,6 +160,10 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) if (_graphicsContext.valid() && _graphicsContext != callingContext) { + // show we release the context so that others can use it?? will do so right + // now as an experiment. + callingContext->releaseContext(); + useState = _graphicsContext->getState(); useContext = _graphicsContext.get(); useContext->makeCurrent();