From ac07e07705450556a396fba2f7ad37d6fb3af083 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Sat, 20 Aug 2005 08:59:03 +0000 Subject: [PATCH] Further work on GraphicsContext/GraphicsThread --- examples/osgcamera/osgcamera.cpp | 347 +++++++++--------- include/osg/GraphicsContext | 63 +++- include/osg/GraphicsThread | 28 +- .../osgProducer/GraphicsContextImplementation | 10 +- include/osgUtil/RenderStage | 7 + src/osg/GraphicsContext.cpp | 99 ++++- src/osg/GraphicsThread.cpp | 108 +++++- .../GraphicsContextImplementation.cpp | 13 +- src/osgUtil/CullVisitor.cpp | 3 +- src/osgUtil/RenderStage.cpp | 199 ++++++---- 10 files changed, 582 insertions(+), 295 deletions(-) diff --git a/examples/osgcamera/osgcamera.cpp b/examples/osgcamera/osgcamera.cpp index 4c8dee961..97ccd9785 100644 --- a/examples/osgcamera/osgcamera.cpp +++ b/examples/osgcamera/osgcamera.cpp @@ -5,12 +5,16 @@ #include #include +#include #include #include +#include #include +#include +#include #include @@ -25,7 +29,41 @@ /////////////////////////////////////////////////////////////////////////////// -#if 1 +struct FrameOperation : public osg::GraphicsThread::Operation +{ + FrameOperation(osg::CameraNode* camera, osg::FrameStamp* frameStamp): + _camera(camera), + _frameStamp(frameStamp) + { + _sceneView = new osgUtil::SceneView; + _sceneView->setDefaults(); + _sceneView->setFrameStamp(_frameStamp.get()); + + if (camera->getNumChildren()>=1) + { + _sceneView->setSceneData(camera->getChild(0)); + } + } + + virtual void operator () (osg::GraphicsContext* context) + { + std::cout<<"FrameOperation draw begin"<setState(context->getState()); + _sceneView->setProjectionMatrix(_camera->getProjectionMatrix()); + _sceneView->setViewMatrix(_camera->getViewMatrix()); + _sceneView->setViewport(_camera->getViewport()); + + _sceneView->cull(); + _sceneView->draw(); + + std::cout<<"FrameOperation draw end"< _camera; + osg::ref_ptr _frameStamp; + osg::ref_ptr _sceneView; +}; int main( int argc, char **argv ) { @@ -42,222 +80,165 @@ int main( int argc, char **argv ) std::cout << argv[0] <<": No data loaded." << std::endl; return 1; } - - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - traits->_windowName = "osgcamera"; - traits->_x = 100; - traits->_y = 100; - traits->_width = 800; - traits->_height = 800; - traits->_windowDecoration = true; - traits->_doubleBuffer = true; - - osg::ref_ptr gfxc = osg::GraphicsContext::createGraphicsContext(traits.get()); - - if (!gfxc) - { - std::cout<<"Unable to create window."<realize(); - // create the view of the scene. - osg::ref_ptr camera = new osg::CameraNode; - camera->setRenderOrder(osg::CameraNode::NESTED_RENDER); - camera->setClearColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f)); - camera->setCullingActive(false); - - camera->addChild(loadedModel.get()); - + // set up the frame stamp for current frame to record the current time and frame number so that animtion code can advance correctly + osg::ref_ptr frameStamp = new osg::FrameStamp; - // initialize the view to look at the center of the scene graph - const osg::BoundingSphere& bs = loadedModel->getBound(); - osg::Matrix viewMatrix; - viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); - - // record the timer tick at the start of rendering. - osg::Timer_t start_tick = osg::Timer::instance()->tick(); - unsigned int frameNum = 0; + + osgUtil::UpdateVisitor updateVisitor; + updateVisitor.setFrameStamp(frameStamp.get()); + + + unsigned int numberCameras = 3; + unsigned int xpos = 0; + unsigned int ypos = 400; + unsigned int width = 400; + unsigned int height = 400; - // make the graphics context current - gfxc->makeCurrent(); - - osg::ref_ptr updateVisitor = new osgUtil::UpdateVisitor; - osg::ref_ptr cullVisitor = new osgUtil::CullVisitor; + typedef std::map< osg::ref_ptr, osg::ref_ptr > CameraMap; + typedef std::set< osg::GraphicsContext* > GraphicsContextSet; - osg::ref_ptr renderGraph = new osgUtil::RenderGraph; - cullVisitor->setRenderGraph(renderGraph.get()); + CameraMap cameraMap; + GraphicsContextSet graphicsContextSet; - osg::ref_ptr renderStage = new osgUtil::RenderStage; - cullVisitor->setRenderStage(renderStage.get()); - - // main loop (note, window toolkits which take control over the main loop will require a window redraw callback containing the code below.) - while( gfxc->isRealized() ) + for(unsigned int i=0; i< numberCameras; ++i) { - // set up the frame stamp for current frame to record the current time and frame number so that animtion code can advance correctly - osg::ref_ptr frameStamp = new osg::FrameStamp; - frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(start_tick,osg::Timer::instance()->tick())); - frameStamp->setFrameNumber(frameNum++); - - updateVisitor->reset(); - - // pass frame stamp to the SceneView so that the update, cull and draw traversals all use the same FrameStamp - updateVisitor->setFrameStamp(frameStamp.get()); - updateVisitor->setTraversalNumber(frameStamp->getFrameNumber()); + osg::ref_ptr camera = new osg::CameraNode; + camera->addChild(loadedModel.get()); - - // set the view + osg::ref_ptr traits = new osg::GraphicsContext::Traits; + traits->_windowName = "osgcamera"; + traits->_x = xpos; + traits->_y = ypos; + traits->_width = width; + traits->_height = height; + traits->_windowDecoration = true; + traits->_doubleBuffer = true; + + xpos += width; + + osg::ref_ptr gfxc = osg::GraphicsContext::createGraphicsContext(traits.get()); + + if (!gfxc) + { + std::cout<<"Unable to create window."<realize(); + + camera->setGraphicsContext(gfxc.get()); + + // initialize the view to look at the center of the scene graph + const osg::BoundingSphere& bs = loadedModel->getBound(); + osg::Matrix viewMatrix; + viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); + + camera->setViewport(0,0,traits->_width,traits->_height); + camera->setProjectionMatrixAsPerspective(50.0f,1.4f,1.0f,10000.0f); camera->setViewMatrix(viewMatrix); - // do the update traversal the scene graph - such as updating animations - camera->accept(*updateVisitor); - - cullVisitor->reset(); - cullVisitor->setFrameStamp(frameStamp.get()); - cullVisitor->setTraversalNumber(frameStamp->getFrameNumber()); - - // update the viewport dimensions, incase the window has been resized. - camera->setViewport(0,0,traits->_width,traits->_height); + gfxc->createGraphicsThread(); - renderGraph->clean(); - renderStage->reset(); - renderStage->setViewport(camera->getViewport()); - - osg::ref_ptr proj = new osg::RefMatrix(camera->getProjectionMatrix()); - osg::ref_ptr mv = new osg::RefMatrix(camera->getViewMatrix()); - - cullVisitor->pushViewport(camera->getViewport()); - cullVisitor->pushProjectionMatrix(proj.get()); - cullVisitor->pushModelViewMatrix(mv.get()); - - // do the cull traversal, collect all objects in the view frustum into a sorted set of rendering bins - //camera->accept(*cullVisitor); - loadedModel->accept(*cullVisitor); - - cullVisitor->popModelViewMatrix(); - cullVisitor->popProjectionMatrix(); - cullVisitor->popViewport(); - - renderStage->sort(); - - // prune out any empty RenderGraph children. - // note, this would be not required if the rendergraph had been - // reset at the start of each frame (see top of this method) but - // a clean has been used instead to try to minimize the amount of - // allocation and deleteing of the RenderGraph nodes. - renderGraph->prune(); - - renderStage->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); - - gfxc->getState()->setInitialViewMatrix(mv.get()); - - std::cout<<"before"<draw(*(gfxc->getState()), previous); - - // Swap Buffers - gfxc->swapBuffers(); - - std::cout<<"swap"<(citr->first->getGraphicsContext())); } - // load the scene. - osg::ref_ptr loadedModel = osgDB::readNodeFile(argv[1]); - if (!loadedModel) + osg::ref_ptr swapOp = new osg::SwapBuffersOperation(); + osg::ref_ptr frameEndBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION); + osg::ref_ptr preSwapBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FLUSH); + + std::cout<<"nubmer of gfx."<getGraphicsThread()->add(swapOp.get(), true); } - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - traits->_windowName = "osgcamera"; - traits->_x = 100; - traits->_y = 100; - traits->_width = 800; - traits->_height = 800; - traits->_windowDecoration = true; - traits->_doubleBuffer = true; - - osg::ref_ptr gfxc = osg::GraphicsContext::createGraphicsContext(traits.get()); - - if (!gfxc) - { - std::cout<<"Unable to create window."<realize(); - - // create the view of the scene. - osg::ref_ptr sceneView = new osgUtil::SceneView; - sceneView->setDefaults(); - sceneView->setSceneData(loadedModel.get()); - - // initialize the view to look at the center of the scene graph - const osg::BoundingSphere& bs = loadedModel->getBound(); - osg::Matrix viewMatrix; - viewMatrix.makeLookAt(bs.center()-osg::Vec3(0.0,2.0f*bs.radius(),0.0),bs.center(),osg::Vec3(0.0f,0.0f,1.0f)); - // record the timer tick at the start of rendering. osg::Timer_t start_tick = osg::Timer::instance()->tick(); - unsigned int frameNum = 0; - - // make the graphics context current - gfxc->makeCurrent(); + bool done = false; // main loop (note, window toolkits which take control over the main loop will require a window redraw callback containing the code below.) - while( gfxc->isRealized() ) + while( !done ) { - // set up the frame stamp for current frame to record the current time and frame number so that animtion code can advance correctly - osg::ref_ptr frameStamp = new osg::FrameStamp; + std::cout<<"Frame "<setReferenceTime(osg::Timer::instance()->delta_s(start_tick,osg::Timer::instance()->tick())); frameStamp->setFrameNumber(frameNum++); - // pass frame stamp to the SceneView so that the update, cull and draw traversals all use the same FrameStamp - sceneView->setFrameStamp(frameStamp.get()); - - // update the viewport dimensions, incase the window has been resized. - sceneView->setViewport(0,0,traits->_width,traits->_height); - - // set the view - sceneView->setViewMatrix(viewMatrix); + std::cout<<"Frame rate "<<(double)frameNum / frameStamp->getReferenceTime()<update(); - - // do the cull traversal, collect all objects in the view frustum into a sorted set of rendering bins - sceneView->cull(); - - // draw the rendering bins. - sceneView->draw(); - // Swap Buffers - gfxc->swapBuffers(); + loadedModel->accept(updateVisitor); + + // issue the frame for each camera. + for(citr = cameraMap.begin(); + citr != cameraMap.end(); + ++citr) + { + osg::CameraNode* camera = const_cast(citr->first.get()); + camera->getGraphicsContext()->getGraphicsThread()->add( citr->second.get(), false); + } + + for(gitr = graphicsContextSet.begin(); + gitr != graphicsContextSet.end(); + ++gitr) + { + osg::GraphicsContext* context = *gitr; + context->getGraphicsThread()->add(frameEndBarrierOp.get(), false); + context->getGraphicsThread()->add(preSwapBarrierOp.get(), false); + } + + std::cout<<"Join frameEndBarrierOp block "<tick(); + frameEndBarrierOp->block(); + osg::Timer_t after_tick = osg::Timer::instance()->tick(); + std::cout<<"Leave frameEndBarrierOp block "<delta_s(before_tick,after_tick)<tick(); +// preSwapBarrierOp->block(); + after_tick = osg::Timer::instance()->tick(); + std::cout<<"Leave preSwapBarrierOp block "<delta_s(before_tick,after_tick)<getGraphicsThread()->add(swapOp.get(), false); + } + + // check if any of the windows are closed + for(gitr = graphicsContextSet.begin(); + gitr != graphicsContextSet.end(); + ++gitr) + { + osg::GraphicsContext* context = *gitr; + if (!context->isRealized()) done = true; + } + } return 0; } - -#endif diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index 667555d66..ba4745a15 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -136,13 +136,16 @@ class OSG_EXPORT GraphicsContext : public Referenced /** Realise the GraphicsContext.*/ - virtual bool realize() = 0; - - /** Return true if the graphics context has been realised and is ready to use.*/ - virtual bool isRealized() const = 0; + bool realize(); /** close the graphics context.*/ - virtual void close() = 0; + void close(); + + /** swap the front and back buffers.*/ + void swapBuffers(); + + /** Return true if the graphics context has been realised and is ready to use.*/ + inline bool isRealized() const { return isRealizedImplementation(); } /** Make this graphics context current. @@ -159,21 +162,16 @@ class OSG_EXPORT GraphicsContext : public Referenced /** 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; + inline void bindPBufferToTexture(GLenum buffer) { bindPBufferToTextureImplementation(buffer); } - /** swap the front and back buffers.*/ - virtual void swapBuffers() = 0; + + + /** Create a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/ + void createGraphicsThread(); /** Assign a graphics thread to the graphics context, so that the thread handles all OpenGL operations.*/ - void setGraphicsThread(GraphicsThread* gt) { _graphicsThread = gt; } + void setGraphicsThread(GraphicsThread* gt); /** Get the graphics thread assigned the graphics context.*/ GraphicsThread* getGraphicsThread() { return _graphicsThread.get(); } @@ -181,12 +179,45 @@ class OSG_EXPORT GraphicsContext : public Referenced /** Get the const graphics thread assigned the graphics context.*/ const GraphicsThread* getGraphicsThread() const { return _graphicsThread.get(); } + + /** Realise the GraphicsContext implementation, + * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ + virtual bool realizeImplementation() = 0; + + /** Return true if the graphics context has been realised, and is ready to use, implementation. + * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ + virtual bool isRealizedImplementation() const = 0; + + /** Close the graphics context implementation. + * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ + virtual void closeImplementation() = 0; + + /** Make this graphics context current implementation. + * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ + virtual void makeCurrentImplementation() = 0; + + /** Make this graphics context current with specified read context implementation. + * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ + virtual void makeContextCurrentImplementation(GraphicsContext* readContext) = 0; + + /** Pure virtual, Bind the graphics context to associated texture implementation. + * Pure virtual - must be implemented by concrate implementations of GraphicsContext. */ + virtual void bindPBufferToTextureImplementation(GLenum buffer) = 0; + + /** Swap the front and back buffers implementation. + * Pure virtual - must be implemented by Concrate implementations of GraphicsContext. */ + virtual void swapBuffersImplementation() = 0; + + protected: GraphicsContext(); virtual ~GraphicsContext(); + + bool _closeOnDestruction; + ref_ptr _traits; ref_ptr _state; OpenThreads::Mutex _mutex; diff --git a/include/osg/GraphicsThread b/include/osg/GraphicsThread index 193da8e10..afe49778b 100644 --- a/include/osg/GraphicsThread +++ b/include/osg/GraphicsThread @@ -79,8 +79,7 @@ class Block: public osg::Referenced { class GraphicsThread : public Referenced, public OpenThreads::Thread { public: - GraphicsThread(): _graphicsContext(0) {} - + GraphicsThread(); /** Base class for implementing GraphicsThread operations.*/ struct OSG_EXPORT Operation : public Referenced @@ -92,7 +91,11 @@ class GraphicsThread : public Referenced, public OpenThreads::Thread * executed by the graphics thread once this operation gets to the head of the queue.*/ void add(Operation* operation, bool waitForCompletion=false); + /** Run does the graphics thread run loop.*/ virtual void run(); + + /** Cancel this graphics thread.*/ + virtual int cancel(); protected: @@ -102,14 +105,18 @@ class GraphicsThread : public Referenced, public OpenThreads::Thread GraphicsContext* _graphicsContext; typedef std::list< ref_ptr > OperationQueue; - OpenThreads::Mutex _operationsMutex; - OperationQueue _operations; + + bool _done; + + OpenThreads::Mutex _operationsMutex; + osg::ref_ptr _operationsBlock; + OperationQueue _operations; }; /** SwapBufferOperation calls swap buffers on the GraphicsContext.*/ -struct OSG_EXPORT SwapBufferOperation : public GraphicsThread::Operation +struct OSG_EXPORT SwapBuffersOperation : public GraphicsThread::Operation { virtual void operator () (GraphicsContext* context); }; @@ -117,9 +124,18 @@ struct OSG_EXPORT SwapBufferOperation : public GraphicsThread::Operation /** BarrierOperation allows one syncronize multiple GraphicsThreads with each other.*/ struct OSG_EXPORT BarrierOperation : public GraphicsThread::Operation, public OpenThreads::Barrier { - BarrierOperation(int numThreads=0): OpenThreads::Barrier(numThreads) {} + enum PreBlockOp + { + NO_OPERATION, + GL_FLUSH, + GL_FINISH + }; + + BarrierOperation(int numThreads, PreBlockOp op=NO_OPERATION): OpenThreads::Barrier(numThreads), _preBlockOp(op) {} virtual void operator () (GraphicsContext* context); + + PreBlockOp _preBlockOp; }; /** ReleaseContext_Block_MakeCurrentOperation releases the context for another thread to aquire, diff --git a/include/osgProducer/GraphicsContextImplementation b/include/osgProducer/GraphicsContextImplementation index e3fb29427..e4c10db9a 100644 --- a/include/osgProducer/GraphicsContextImplementation +++ b/include/osgProducer/GraphicsContextImplementation @@ -45,13 +45,13 @@ class OSGPRODUCER_EXPORT GraphicsContextImplementation : public osg::GraphicsCon /** Realise the GraphicsContext.*/ - virtual bool realize(); + virtual bool realizeImplementation(); /** Return true if the graphics context has been realised and is ready to use.*/ - virtual bool isRealized() const { return _rs.valid() && _rs->isRealized(); } + virtual bool isRealizedImplementation() const { return _rs.valid() && _rs->isRealized(); } /** Release the graphics context.*/ - virtual void close(); + virtual void closeImplementation(); /** Make this graphics context current.*/ virtual void makeCurrentImplementation(); @@ -60,10 +60,10 @@ class OSGPRODUCER_EXPORT GraphicsContextImplementation : public osg::GraphicsCon virtual void makeContextCurrentImplementation(GraphicsContext* readContext); /** Bind the graphics context to associated texture.*/ - virtual void bindPBufferToTexture(GLenum buffer); + virtual void bindPBufferToTextureImplementation(GLenum buffer); /** swap the front and back buffers.*/ - virtual void swapBuffers(); + virtual void swapBuffersImplementation(); protected: diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index 10ffd83be..c45599b8c 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -171,14 +171,19 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin getRenderStageLighting()->addPositionedTextureAttribute(textureUnit, matrix,attr); } + void copyTexture(osg::State& state); + virtual void drawPreRenderStages(osg::State& state,RenderLeaf*& previous); virtual void draw(osg::State& state,RenderLeaf*& previous); + + virtual void drawInner(osg::State& state,RenderLeaf*& previous, bool& doCopyTexture); virtual void drawPostRenderStages(osg::State& state,RenderLeaf*& previous); virtual void drawImplementation(osg::State& state,RenderLeaf*& previous); + void addToDependencyList(RenderStage* rs) { addPreRenderStage(rs); } void addPreRenderStage(RenderStage* rs); @@ -187,10 +192,12 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin /** Extract stats for current draw list. */ bool getStats(Statistics* primStats); + protected: virtual ~RenderStage(); + typedef std::vector< osg::ref_ptr > RenderStageList; bool _stageDrawnThisFrame; diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index e7209d01d..44fe458bd 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -113,25 +113,62 @@ void GraphicsContext::decrementContextIDUsageCount(unsigned int contextID) GraphicsContext::GraphicsContext(): + _closeOnDestruction(true), _threadOfLastMakeCurrent(0) { } GraphicsContext::~GraphicsContext() { + // switch off the graphics thread... + setGraphicsThread(0); + if (_state.valid()) { decrementContextIDUsageCount(_state->getContextID()); } + + if (_closeOnDestruction) + { + close(); + } } +/** Realise the GraphicsContext.*/ +bool GraphicsContext::realize() +{ + if (realizeImplementation()) + { + if (_graphicsThread.valid() && !_graphicsThread->isRunning()) + { + _graphicsThread->startThread(); + } + return true; + } + else + { + return false; + } +} + +void GraphicsContext::close() +{ + // switch off the graphics thread... + setGraphicsThread(0); + + closeImplementation(); +} + + void GraphicsContext::makeCurrent() { + osg::notify(osg::NOTICE)<<"Doing GraphicsContext::makeCurrent"<<(unsigned int)OpenThreads::Thread::CurrentThread()<release(); } + + osg::notify(osg::NOTICE)<<"Done GraphicsContext::makeCurrentImplementation"<<(unsigned int)OpenThreads::Thread::CurrentThread()<add(new SwapBuffersOperation); + } + else + { + osg::notify(osg::NOTICE)<<"Doing GraphicsContext::swapBuffers() makeCurrent;swapBuffersImplementation;releaseContext"<<(unsigned int)OpenThreads::Thread::CurrentThread()<cancel(); + _graphicsThread->_graphicsContext = 0; + } + + _graphicsThread = gt; + + if (_graphicsThread.valid()) + { + _graphicsThread->_graphicsContext = this; + + if (!_graphicsThread->isRunning() && isRealized()) + { + _graphicsThread->startThread(); + } + } +} diff --git a/src/osg/GraphicsThread.cpp b/src/osg/GraphicsThread.cpp index 415b63172..e71064136 100644 --- a/src/osg/GraphicsThread.cpp +++ b/src/osg/GraphicsThread.cpp @@ -17,15 +17,70 @@ #include using namespace osg; +using namespace OpenThreads; +struct BlockOperation : public GraphicsThread::Operation, public Block +{ + BlockOperation() { reset(); } + + virtual void operator () (GraphicsContext*) + { + //osg::notify(osg::NOTICE)<<"BlockOperation doing release"<<(unsigned int)this<release(); + + // then wait for the the thread to stop running. + while(isRunning()) + { + // commenting out debug info as it was cashing crash on exit, presumable + // due to osg::notify or std::cout destructing earlier than this destructor. + osg::notify(osg::NOTICE)<<"Waiting for GraphicsThread to cancel"<set(true); } - if (barrier) + if (block) { // now we wait till the barrier is joined by the graphics thread. - barrier->block(); + block->block(); } } void GraphicsThread::run() { // make the graphics context current. - if (_graphicsContext) _graphicsContext->makeCurrent(); + if (_graphicsContext) + { + osg::notify(osg::NOTICE)<<"Doing make current"<makeCurrent(); + } - bool firstTime = false; + osg::notify(osg::NOTICE)<<"Doing run"<block(); + } + + // osg::notify(osg::NOTICE)<<"get op"< operation; // get the front of the file request list. @@ -71,12 +141,20 @@ void GraphicsThread::run() // remove it from the opeations queue _operations.erase(_operations.begin()); + + if (_operations.empty()) + { + _operationsBlock->set(false); + } + } } if (operation.valid()) { + // osg::notify(osg::NOTICE)<<"Doing op"<releaseContext(); } - -void SwapBufferOperation::operator () (GraphicsContext* context) + +void SwapBuffersOperation::operator () (GraphicsContext* context) { - if (context) context->swapBuffers(); + if (context) + { + context->swapBuffersImplementation(); + } } void BarrierOperation::operator () (GraphicsContext*) { + if (_preBlockOp==GL_FLUSH) glFlush(); + if (_preBlockOp==GL_FINISH) glFinish(); + block(); } diff --git a/src/osgProducer/GraphicsContextImplementation.cpp b/src/osgProducer/GraphicsContextImplementation.cpp index 5bbb46bbc..797b9cf1a 100644 --- a/src/osgProducer/GraphicsContextImplementation.cpp +++ b/src/osgProducer/GraphicsContextImplementation.cpp @@ -150,19 +150,20 @@ GraphicsContextImplementation::GraphicsContextImplementation(Traits* traits) //_rs->realize(); } + _closeOnDestruction = true; } GraphicsContextImplementation::GraphicsContextImplementation(Producer::RenderSurface* rs) { _rs = rs; + _closeOnDestruction = false; } GraphicsContextImplementation::~GraphicsContextImplementation() { - close(); } -bool GraphicsContextImplementation::realize() +bool GraphicsContextImplementation::realizeImplementation() { if (_rs.valid()) { @@ -188,6 +189,8 @@ void GraphicsContextImplementation::makeCurrentImplementation() { if (!_rs) return; + osg::notify(osg::NOTICE)<<"GraphicsContextImplementation::makeCurrentImplementation()"<setReadDrawable( 0 ); _rs->makeCurrent(); @@ -207,14 +210,14 @@ void GraphicsContextImplementation::makeContextCurrentImplementation(GraphicsCon _rs->makeCurrent(); } -void GraphicsContextImplementation::close() +void GraphicsContextImplementation::closeImplementation() { if (!_rs) return; // need to close render surface... } -void GraphicsContextImplementation::bindPBufferToTexture(GLenum buffer) +void GraphicsContextImplementation::bindPBufferToTextureImplementation(GLenum buffer) { if (!_rs) return; @@ -229,7 +232,7 @@ void GraphicsContextImplementation::bindPBufferToTexture(GLenum buffer) _rs->bindPBufferToTexture(bufferType); } -void GraphicsContextImplementation::swapBuffers() +void GraphicsContextImplementation::swapBuffersImplementation() { _rs->swapBuffers(); } diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 74289fcff..76d937271 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1332,8 +1332,9 @@ void CullVisitor::apply(osg::CameraNode& camera) rtts->setGraphicsContext(context.get()); - context->realize(); + context->createGraphicsThread(); + context->realize(); } } diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 713cdf8d5..c42b51eb4 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -143,32 +143,47 @@ void RenderStage::drawPreRenderStages(osg::State& state,RenderLeaf*& previous) //cout << "Done Drawing prerendering stages "<x()<<","<< _viewport->y()<<","<< _viewport->width()<<","<< _viewport->height()<releaseContext(); - - useState = _graphicsContext->getState(); - useContext = _graphicsContext.get(); - useContext->makeCurrent(); + glReadBuffer(_readBuffer); } + // need to implement texture cube map etc... + osg::Texture1D* texture1D = 0; + osg::Texture2D* texture2D = 0; + osg::Texture3D* texture3D = 0; + osg::TextureRectangle* textureRec = 0; + osg::TextureCubeMap* textureCubeMap = 0; + + if ((texture2D = dynamic_cast(_texture.get())) != 0) + { + texture2D->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); + } + else if ((textureRec = dynamic_cast(_texture.get())) != 0) + { + textureRec->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); + } + else if ((texture1D = dynamic_cast(_texture.get())) != 0) + { + // need to implement + texture1D->copyTexImage1D(state,_viewport->x(),_viewport->y(),_viewport->width()); + } + else if ((texture3D = dynamic_cast(_texture.get())) != 0) + { + // need to implement + texture3D->copyTexSubImage3D(state, 0, 0, _face, _viewport->x(), _viewport->y(), _viewport->width(), _viewport->height()); + } + else if ((textureCubeMap = dynamic_cast(_texture.get())) != 0) + { + // need to implement + textureCubeMap->copyTexSubImageCubeMap(state, _face, 0, 0, _viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); + } +} + +void RenderStage::drawInner(osg::State& state,RenderLeaf*& previous, bool& doCopyTexture) +{ if (_drawBuffer != GL_NONE) { glDrawBuffer(_drawBuffer); @@ -184,58 +199,17 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) if (fbo_supported) { - _fbo->apply(*useState); + _fbo->apply(state); } - // do the drawing itself. RenderBin::draw(state,previous); // now copy the rendered image to attached texture. - if (_texture.valid() && !fbo_supported) + if (doCopyTexture) { - if (callingContext && useContext!= callingContext) - { - // make the calling context use the pbuffer context for reading. - callingContext->makeContextCurrent(useContext); - - if (_readBuffer != GL_NONE) - { - glReadBuffer(_readBuffer); - } - } - - // need to implement texture cube map etc... - osg::Texture1D* texture1D = 0; - osg::Texture2D* texture2D = 0; - osg::Texture3D* texture3D = 0; - osg::TextureRectangle* textureRec = 0; - osg::TextureCubeMap* textureCubeMap = 0; - - if ((texture2D = dynamic_cast(_texture.get())) != 0) - { - texture2D->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); - } - else if ((textureRec = dynamic_cast(_texture.get())) != 0) - { - textureRec->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); - } - else if ((texture1D = dynamic_cast(_texture.get())) != 0) - { - // need to implement - texture1D->copyTexImage1D(state,_viewport->x(),_viewport->y(),_viewport->width()); - } - else if ((texture3D = dynamic_cast(_texture.get())) != 0) - { - // need to implement - texture3D->copyTexSubImage3D(state, 0, 0, _face, _viewport->x(), _viewport->y(), _viewport->width(), _viewport->height()); - } - else if ((textureCubeMap = dynamic_cast(_texture.get())) != 0) - { - // need to implement - textureCubeMap->copyTexSubImageCubeMap(state, _face, 0, 0, _viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); - } + copyTexture(state); } if (_image.valid()) @@ -260,6 +234,8 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) { // switch of the frame buffer object fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + + doCopyTexture = true; } if (fbo_supported && _camera) @@ -272,11 +248,100 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) { if (itr->second._texture.valid() && itr->second._mipMapGeneration) { - itr->second._texture->apply(*useState); + itr->second._texture->apply(state); // fbo_ext->glGenerateMipmapEXT(itr->second._texture->getTextureTarget()); } } } +} + +struct DrawInnerOperation : public osg::GraphicsThread::Operation +{ + DrawInnerOperation(RenderStage* stage) : _stage(stage) {} + + virtual void operator() (osg::GraphicsContext* context) + { + // osg::notify(osg::NOTICE)<<"DrawInnerOperation operator"<drawInner(*(context->getState()), previous, doCopyTexture); + } + } + + RenderStage* _stage; +}; + + +void RenderStage::draw(osg::State& state,RenderLeaf*& previous) +{ + if (_stageDrawnThisFrame) return; + + _stageDrawnThisFrame = true; + + // note, SceneView does call to drawPreRenderStages explicitly + // so there is no need to call it here. + drawPreRenderStages(state,previous); + + + osg::State* useState = &state; + osg::GraphicsContext* callingContext = state.getGraphicsContext(); + osg::GraphicsContext* useContext = callingContext; + osg::GraphicsThread* useThread = 0; + + 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(); + + useThread = useContext->getGraphicsThread(); + + if (!useThread) useContext->makeCurrent(); + } + + bool doCopyTexture = _texture.valid() ? + (callingContext != useContext) : + false; + + if (useThread) + { + useThread->add(new DrawInnerOperation( this ), true); + + doCopyTexture = false; + } + else + { + drawInner( *useState, previous, doCopyTexture); + } + + + // now copy the rendered image to attached texture. + if (_texture.valid() && !doCopyTexture) + { + if (callingContext && useContext!= callingContext) + { + // make the calling context use the pbuffer context for reading. + callingContext->makeContextCurrent(useContext); + } + + copyTexture(state); + } + + if (_camera && _camera->getPostDrawCallback()) + { + // if we have a camera with a post draw callback invoke it. + (*(_camera->getPostDrawCallback()))(*_camera); + } + + if (_graphicsContext.valid() && _graphicsContext != callingContext) + { + if (!useThread) useContext->releaseContext(); + } if (callingContext && useContext != callingContext) {