diff --git a/examples/osgcamera/osgcamera.cpp b/examples/osgcamera/osgcamera.cpp index 2d8b68336..f7cdc6193 100644 --- a/examples/osgcamera/osgcamera.cpp +++ b/examples/osgcamera/osgcamera.cpp @@ -3,58 +3,11 @@ // Simple example of use of Producer::RenderSurface to create an OpenGL // graphics window, and OSG for rendering. -#include -#include -#include - -#include -#include -#include -#include #include -#include -#include - -#include - -#include -#include -#include - - -#if !defined(_WIN32) - #include - #include - -void renderCamera(osg::Camera* camera) -{ - osg::GraphicsContext* gc = camera->getGraphicsContext(); - if (!gc) return; - - osgUtil::SceneView* sceneView = dynamic_cast(camera->getRenderingCache(0)); - if (!sceneView) return; - - gc->makeCurrent(); - - sceneView->cull(); - sceneView->draw(); - - gc->swapBuffers(); -} - -void setUpFrameStamp(osg::Camera* camera, osg::FrameStamp* frameStamp, osg::Node* loadedModel) -{ - osgUtil::SceneView* sceneView = dynamic_cast(camera->getRenderingCache(0)); - if (!sceneView) return; - - sceneView->setFrameStamp(frameStamp); - - sceneView->setSceneData(loadedModel); - -} +#include int main( int argc, char **argv ) { @@ -64,6 +17,10 @@ int main( int argc, char **argv ) return 1; } + + osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts(2); + osg::Referenced::setThreadSafeReferenceCounting(true); + // load the scene. osg::ref_ptr loadedModel = osgDB::readNodeFile(argv[1]); if (!loadedModel) @@ -87,398 +44,5 @@ int main( int argc, char **argv ) viewer.frame(); } -} - - -#else - - -////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// -// ORIGINAL osgcamera example code. - -//////////////////////////////////////////////////////////////////////////////// -// -// -// **************** THIS IS AN EXPERIMENTAL IMPLEMENTATION *************** -// ************************** PLEASE DO NOT COPY ************************ -// -// -/////////////////////////////////////////////////////////////////////////////// - - -// Compile operation, that compile OpenGL objects. -struct CompileOperation : public osg::GraphicsThread::Operation -{ - CompileOperation(osg::Node* scene): - osg::GraphicsThread::Operation("Compile",false), - _scene(scene) - { - } - - virtual void operator () (osg::GraphicsContext* context) - { - std::cout<<"Compile"<getState()); - - // do the compile traversal - _scene->accept(compileVisitor); - } - - osg::ref_ptr _scene; -}; - -// Cull operation, that does a cull on the scene graph. -struct CullOperation : public osg::GraphicsThread::Operation -{ - CullOperation(osgUtil::SceneView* sceneView): - osg::GraphicsThread::Operation("Cull",true), - _sceneView(sceneView) - { - } - - virtual void operator () (osg::GraphicsContext* context) - { - _sceneView->setState(context->getState()); - _sceneView->cull(); - } - - osg::ref_ptr _sceneView; -}; - -// Draw operation, that does a draw on the scene graph. -struct DrawOperation : public osg::GraphicsThread::Operation -{ - DrawOperation(osgUtil::SceneView* sceneView): - osg::GraphicsThread::Operation("Draw",true), - _sceneView(sceneView) - { - } - - virtual void operator () (osg::GraphicsContext*) - { - _sceneView->draw(); - } - - osg::ref_ptr _sceneView; -}; - -struct CleanUpOperation : public osg::GraphicsThread::Operation -{ - CleanUpOperation(osgUtil::SceneView* sceneView): - osg::GraphicsThread::Operation("CleanUp",false), - _sceneView(sceneView) - { - } - - virtual void operator () (osg::GraphicsContext*) - { - _sceneView->releaseAllGLObjects(); - _sceneView->flushAllDeletedGLObjects(); - } - - osg::ref_ptr _sceneView; -}; - -// main does the following steps to create a multi-thread, multiple camera/graphics context view of a scene graph. -// -// 1) load the scene graph -// -// 2) create a list of camera, each with their own graphis context, with a graphics thread for each context. -// -// 3) set up the graphic threads so that the do an initial compile OpenGL objects operation, this is done once, and then this compile op is disgarded -// -// 4) set up the graphics thread so that it has all the graphics ops required for the main loop, these ops are: -// 4.a) frame begin barrair, syncronizes all the waiting graphic threads so they don't run while update is occuring -// 4.b) frame operation - the cull and draw for each camera -// 4.c) frame end barrier, releases the update thread once all graphic threads have dispatched all their OpenGL commands -// 4.d) pre swap barrier, barrier which ensures that all graphics threads have sent their data down to the gfx card. -// 4.e) swap buffers, do the swap buffers on all the graphics contexts. -// -// 5. The main loop: -// 5.a) update -// 5.b) join the frame begin barrrier, releasing all the graphics threads to do their stuff -// 5.c) block on the frame end barrier, waiting till all the graphics threads have done their cull/draws. -// 5.d) check to see if any of the windows has been closed. -// -int main( int argc, char **argv ) -{ - osg::Referenced::setThreadSafeReferenceCounting(true); - - // use an ArgumentParser object to manage the program arguments. - osg::ArgumentParser arguments(&argc,argv); - - std::string windowingLibrary("osgProducer"); - while (arguments.read("--windowing",windowingLibrary)) {} - - // load the osgProducer library manually. - osg::ref_ptr windowingLib = - osgDB::DynamicLibrary::loadLibrary(osgDB::Registry::instance()->createLibraryNameForNodeKit(windowingLibrary)); - - - if (!windowingLib) - { - std::cout<<"Error: failed to loading windowing library: "< view = new osgViewer::View; - view->setUpViewAcrossAllScreens(); - - - - - unsigned int numScreens = wsi->getNumScreens(); - - unsigned int numberCameras = numScreens; - while (arguments.read("--cameras",numberCameras)) {} - - unsigned int xpos = 0; - unsigned int ypos = 400; - unsigned int width = 400; - unsigned int height = 400; - - while (arguments.read("--xpos",xpos)) {} - while (arguments.read("--ypos",ypos)) {} - while (arguments.read("--height",height)) {} - while (arguments.read("--width",width)) {} - - unsigned int maxNumFrames = 1000; - while (arguments.read("--max-num-frames",maxNumFrames)) {} - - // load the scene. - osg::ref_ptr loadedModel = osgDB::readNodeFiles(arguments); - if (!loadedModel) - { - std::cout << argv[0] <<": No data loaded." << std::endl; - return 1; - } - - - // 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; - - unsigned int frameNum = 0; - - osgUtil::UpdateVisitor updateVisitor; - updateVisitor.setFrameStamp(frameStamp.get()); - - typedef std::list< osg::ref_ptr > CameraList; - typedef std::set< osg::GraphicsContext* > GraphicsContextSet; - - CameraList cameraList; - GraphicsContextSet graphicsContextSet; - - - - // create the cameras, graphic contexts and graphic threads. - bool shareContexts = false; - osg::GraphicsContext* previousContext = 0; - for(unsigned int i=0; i< numberCameras; ++i) - { - osg::ref_ptr camera = new osg::Camera; - camera->addChild(loadedModel.get()); - - osg::ref_ptr traits = new osg::GraphicsContext::Traits; - traits->_windowName = "osgcamera"; - traits->_screenNum = i % numScreens; - traits->_x = xpos; - traits->_y = ypos; - traits->_width = width; - traits->_height = height; - traits->_windowDecoration = true; - traits->_doubleBuffer = true; - traits->_sharedContext = shareContexts ? previousContext : 0; - - xpos += width; - - osg::ref_ptr gfxc = osg::GraphicsContext::createGraphicsContext(traits.get()); - - if (!gfxc) - { - std::cout<<"Unable to create window."<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); - - // graphics thread will realize the window. - gfxc->createGraphicsThread(); - - cameraList.push_back(camera); - - previousContext = gfxc.get(); - } - - - // build the list of unique graphics contexts. - CameraList::iterator citr; - for(citr = cameraList.begin(); - citr != cameraList.end(); - ++citr) - { - graphicsContextSet.insert(const_cast((*citr)->getGraphicsContext())); - } - - - std::cout<<"Number of cameras = "<delta_s(previous_tick,current_tick)<accept(updateVisitor); - - // dispatch the frame. - frameBeginBarrierOp->block(); - - // wait till the frame is done. - frameEndBarrierOp->block(); - - // 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; - } - - } - - - std::cout<<"Exiting application"<getGraphicsThread(); - if (thread) - { - thread->removeAllOperations(); - thread->setDone(true); - } - } - - std::cout<<"Removed all operations"< #include +#include + namespace osgViewer { /** View holds a single view on a scene, this view may be composed of one or more slave cameras.*/ @@ -64,6 +66,9 @@ class OSGVIEWER_EXPORT View : public osg::View osg::ref_ptr _cameraManipulator; EventHandlers _eventHandlers; + typedef std::map, osg::ref_ptr > CameraSceneViewMap; + CameraSceneViewMap _cameraSceneViewMap; + }; } diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index 2fc609666..d896d6415 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -53,16 +53,20 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View /** Clean up all OpenGL objects associated with this viewer's scenegraph.*/ virtual void cleanup(); - + public: - + void init(); + + typedef std::vector Contexts; + void getContexts(Contexts& contexts); + bool _firstFrame; bool _done; - - protected: - + osg::ref_ptr _startRenderingBarrier; + osg::ref_ptr _endRenderingDispatchBarrier; + }; diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index 46fe8e92e..350f63d69 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -242,11 +242,12 @@ void GraphicsContext::setGraphicsThread(GraphicsThread* gt) if (_graphicsThread.valid()) { _graphicsThread->_graphicsContext = this; - +#if 0 if (!_graphicsThread->isRunning()) { _graphicsThread->startThread(); } +#endif } } diff --git a/src/osg/GraphicsThread.cpp b/src/osg/GraphicsThread.cpp index 6d0bb2807..ff0a27921 100644 --- a/src/osg/GraphicsThread.cpp +++ b/src/osg/GraphicsThread.cpp @@ -253,14 +253,29 @@ void GraphicsThread::run() { if (!_graphicsContext->isRealized()) { +#if 0 + + osg::notify(osg::NOTICE)<<"Forced to do a realize in GraphicsThread::run."<realize(); + contextRealizedInThisThread = true; +#else + while (!_graphicsContext->isRealized() && !_done) + { + osg::notify(osg::INFO)<<"Waiting in GraphicsThread::run for GraphicsContext to realize."<makeCurrent(); + + _graphicsContext->makeCurrentImplementation(); } + // _graphicsContext->makeCurrentImplementation(); + // create a local object to clean up once the thread is cancelled. ThreadExitTidyUp threadExitTypeUp(_graphicsContext, contextRealizedInThisThread); @@ -272,7 +287,7 @@ void GraphicsThread::run() do { - osg::notify(osg::INFO)<<"In main loop "<getReferenceTime(); + osg::Timer_t currentTick = osg::Timer::instance()->tick(); _frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(_startTick,currentTick)); _frameStamp->setFrameNumber(_frameStamp->getFrameNumber()+1); + + // osg::notify(osg::NOTICE)<<"Frame rate = "<<1.0/(_frameStamp->getReferenceTime()-previousTime)<setDefaults(); - _sceneView->setCamera(camera); - _sceneView->setState(camera->getGraphicsContext()->getState()); - _sceneView->setSceneData(view->getSceneData()); - _sceneView->setFrameStamp(frameStamp); - _sceneView->getCullVisitor()->setDatabaseRequestHandler(_databasePager.get()); } virtual void operator () (osg::GraphicsContext*) { + if (!_sceneView) return; + _sceneView->cull(); _sceneView->draw(); @@ -197,17 +193,29 @@ struct RenderingOperation : public osg::GraphicsContext::Operation } } - osg::ref_ptr _sceneView; - osg::ref_ptr _databasePager; + osg::observer_ptr _sceneView; + osg::observer_ptr _databasePager; }; void View::setUpRenderingSupport() { osg::FrameStamp* frameStamp = _scene->getFrameStamp(); + // what should we do with the old sceneViews? + _cameraSceneViewMap.clear(); + if (_camera.valid() && _camera->getGraphicsContext()) { - _camera->getGraphicsContext()->add(new RenderingOperation(this, _camera.get(), _scene->getDatabasePager(), frameStamp)); + osgUtil::SceneView* sceneView = new osgUtil::SceneView; + _cameraSceneViewMap[_camera] = sceneView; + + sceneView->setDefaults(); + sceneView->setCamera(_camera.get()); + sceneView->setState(_camera->getGraphicsContext()->getState()); + sceneView->setSceneData(getSceneData()); + sceneView->setFrameStamp(frameStamp); + + _camera->getGraphicsContext()->add(new RenderingOperation(sceneView, _scene->getDatabasePager())); } for(unsigned i=0; igetGraphicsContext()) { - slave._camera->getGraphicsContext()->add(new RenderingOperation(this, slave._camera.get(), _scene->getDatabasePager(), frameStamp)); + osgUtil::SceneView* sceneView = new osgUtil::SceneView; + _cameraSceneViewMap[slave._camera] = sceneView; + + sceneView->setDefaults(); + sceneView->setCamera(slave._camera.get()); + sceneView->setState(slave._camera->getGraphicsContext()->getState()); + sceneView->setSceneData(getSceneData()); + sceneView->setFrameStamp(frameStamp); + + slave._camera->getGraphicsContext()->add(new RenderingOperation(sceneView, _scene->getDatabasePager())); } } } diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 23011b9e9..d65946331 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -15,6 +15,8 @@ */ #include +#include +#include using namespace osgViewer; @@ -24,7 +26,7 @@ public: virtual ~ActionAdapter() {} virtual void requestRedraw() { /*osg::notify(osg::NOTICE)<<"requestRedraw()"<setGraphicsThread(0); + } + + if (_scene.valid() && _scene->getDatabasePager()) + { + _scene->getDatabasePager()->cancel(); + _scene->setDatabasePager(0); + } +#endif } void Viewer::init() @@ -53,13 +74,14 @@ void Viewer::init() } } -void Viewer::realize() +void Viewer::getContexts(Contexts& contexts) { - osg::notify(osg::INFO)<<"Viewer::realize()"< ContextSet; + ContextSet contextSet; if (_camera.valid() && _camera->getGraphicsContext()) { - _camera->getGraphicsContext()->realize(); + contextSet.insert(_camera->getGraphicsContext()); } for(unsigned int i=0; igetGraphicsContext()) { - osg::notify(osg::INFO)<<" slave realize()"<getGraphicsContext()->realize(); + contextSet.insert(slave._camera->getGraphicsContext()); } } + contexts.clear(); + contexts.reserve(contextSet.size()); + + for(ContextSet::iterator itr = contextSet.begin(); + itr != contextSet.end(); + ++itr) + { + contexts.push_back(const_cast(*itr)); + } +} + +OpenThreads::Mutex mutex; + +// Compile operation, that compile OpenGL objects. +struct CompileOperation : public osg::GraphicsThread::Operation +{ + CompileOperation(osg::Node* scene): + osg::GraphicsThread::Operation("Compile",false), + _scene(scene) + { + } + + virtual void operator () (osg::GraphicsContext* context) + { + // OpenThreads::ScopedLock lock(mutex); + // osg::notify(osg::NOTICE)<<"Compile "<makeCurrentImplementation(); + + osgUtil::GLObjectsVisitor compileVisitor; + compileVisitor.setState(context->getState()); + + // do the compile traversal + _scene->accept(compileVisitor); + + // osg::notify(osg::NOTICE)<<"Done Compile "< _scene; +}; + + +// Draw operation, that does a draw on the scene graph. +struct RunOperations : public osg::GraphicsThread::Operation +{ + RunOperations(osg::GraphicsContext* gc): + osg::GraphicsThread::Operation("RunOperation",true), + _originalContext(gc) + { + } + + virtual void operator () (osg::GraphicsContext* gc) + { + gc->runOperations(); + } + + osg::GraphicsContext* _originalContext; +}; + + +void Viewer::realize() +{ + osg::notify(osg::INFO)<<"Viewer::realize()"< 1; + + if (multiThreaded) + { + _startRenderingBarrier = new osg::BarrierOperation(contexts.size()+1, osg::BarrierOperation::NO_OPERATION); + _endRenderingDispatchBarrier = new osg::BarrierOperation(contexts.size()+1, osg::BarrierOperation::NO_OPERATION); + osg::ref_ptr swapOp = new osg::SwapBuffersOperation(); + + for(citr = contexts.begin(); + citr != contexts.end(); + ++citr) + { + osg::GraphicsContext* gc = (*citr); + + // create the a graphics thread for this context + gc->createGraphicsThread(); + + gc->getGraphicsThread()->add(new CompileOperation(getSceneData())); + + // add the startRenderingBarrier + gc->getGraphicsThread()->add(_startRenderingBarrier.get()); + + // add the rendering operation itself. + gc->getGraphicsThread()->add(new RunOperations(gc)); + + // add the endRenderingDispatchBarrier + gc->getGraphicsThread()->add(_endRenderingDispatchBarrier.get()); + + // add the swap buffers + gc->getGraphicsThread()->add(swapOp.get()); + + } + + } + + for(citr = contexts.begin(); + citr != contexts.end(); + ++citr) + { + (*citr)->realize(); + } + + OpenThreads::Thread::YieldCurrentThread(); + bool grabFocus = true; if (grabFocus) { - if (_camera.valid() && _camera->getGraphicsContext()) + for(citr = contexts.begin(); + citr != contexts.end(); + ++citr) { - osgViewer::GraphicsWindow* gw = dynamic_cast(_camera->getGraphicsContext()); - gw->grabFocusIfPointerInWindow(); - } - - for(unsigned int i=0; igetGraphicsContext()) + osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); + if (gw) { - osg::notify(osg::INFO)<<" slave realize()"<getGraphicsContext()->realize(); - osgViewer::GraphicsWindow* gw = dynamic_cast(slave._camera->getGraphicsContext()); - gw->grabFocusIfPointerInWindow(); + gw->grabFocusIfPointerInWindow(); } } + } + + if (multiThreaded) + { + for(citr = contexts.begin(); + citr != contexts.end(); + ++citr) + { + osg::GraphicsContext* gc = (*citr); + if (!gc->getGraphicsThread()->isRunning()) + { + gc->getGraphicsThread()->startThread(); + } + } } + } @@ -131,9 +273,14 @@ void Viewer::frameEventTraversal() // need to copy events from the GraphicsWindow's into local EventQueue; osgGA::EventQueue::Events events; - if (_camera.valid() && _camera->getGraphicsContext()) + Contexts contexts; + getContexts(contexts); + + for(Contexts::iterator citr = contexts.begin(); + citr != contexts.end(); + ++citr) { - osgViewer::GraphicsWindow* gw = dynamic_cast(_camera->getGraphicsContext()); + osgViewer::GraphicsWindow* gw = dynamic_cast(*citr); if (gw) { gw->checkEvents(); @@ -141,20 +288,6 @@ void Viewer::frameEventTraversal() } } - for(unsigned int i=0; igetGraphicsContext()) - { - osgViewer::GraphicsWindow* gw = dynamic_cast(slave._camera->getGraphicsContext()); - if (gw) - { - gw->checkEvents(); - gw->getEventQueue()->takeEvents(events); - } - } - } - _eventQueue->frame( _scene->getFrameStamp()->getReferenceTime() ); _eventQueue->takeEvents(events); @@ -274,48 +407,49 @@ void Viewer::frameRenderingTraversals() dp->signalBeginFrame(_scene->getFrameStamp()); } - - typedef std::set GraphicsContexts; - GraphicsContexts contexts; - - if (_camera.valid() && _camera->getGraphicsContext()) - { - osgViewer::GraphicsWindow* gw = dynamic_cast(_camera->getGraphicsContext()); - if (gw) - { - contexts.insert(gw); - } - } + bool multiThreaded = _startRenderingBarrier.valid(); - for(unsigned int i=0; igetGraphicsContext()) - { - osgViewer::GraphicsWindow* gw = dynamic_cast(slave._camera->getGraphicsContext()); - if (gw) - { - contexts.insert(gw); - } - } - } - + // sleep(1); - for(GraphicsContexts::iterator itr = contexts.begin(); - itr != contexts.end(); - ++itr) - { - if (_done) return; - const_cast(*itr)->makeCurrent(); - const_cast(*itr)->runOperations(); + // osg::notify(osg::NOTICE)<block(); + + // osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<block(); + + // osg::notify(osg::NOTICE)<<"Leaving _endRenderingDispatchBarrier block"<(*itr)->swapBuffers(); + Contexts contexts; + getContexts(contexts); + + Contexts::iterator itr; + for(itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + if (_done) return; + (*itr)->makeCurrent(); + (*itr)->runOperations(); + } + + + for(itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + (*itr)->makeCurrent(); + (*itr)->swapBuffers(); + } + } if (dp)