From 4fc9af7ea0c18bb332bb251a320bb62593312824 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 21 Dec 2006 16:56:20 +0000 Subject: [PATCH] Moved rendering support into GraphisContext, osgViewer::Viewer/View, and added frame stamp updating and update traversal to osgViewer::Scene/Viewer. Updated osgcamera example to use new Viewer API calls instead of using local rendering calls. --- examples/osgcamera/osgcamera.cpp | 63 +++-------------- include/osg/GraphicsContext | 52 ++++++++++++++ include/osg/GraphicsThread | 4 +- include/osgViewer/Viewer | 16 +++-- src/osg/GraphicsContext.cpp | 104 ++++++++++++++++++++++++++++ src/osg/GraphicsThread.cpp | 10 +++ src/osgViewer/GraphicsWindowX11.cpp | 18 ++--- src/osgViewer/Scene.cpp | 8 +++ src/osgViewer/View.cpp | 41 ++++++++--- src/osgViewer/Viewer.cpp | 91 ++++++++++++++++++++---- 10 files changed, 311 insertions(+), 96 deletions(-) diff --git a/examples/osgcamera/osgcamera.cpp b/examples/osgcamera/osgcamera.cpp index d75bd7f1d..2d8b68336 100644 --- a/examples/osgcamera/osgcamera.cpp +++ b/examples/osgcamera/osgcamera.cpp @@ -71,67 +71,22 @@ int main( int argc, char **argv ) std::cout << argv[0] <<": No data loaded." << std::endl; return 1; } - - // 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)); - osg::ref_ptr viewer = new osgViewer::Viewer; - viewer->setSceneData(loadedModel.get()); - viewer->setCameraManipulator(new osgGA::TrackballManipulator()); - viewer->setUpViewAcrossAllScreens(); - viewer->realize(); + osgViewer::Viewer viewer; - viewer->getCamera()->setClearColor(osg::Vec4f(0.6f,0.6f,0.8f,1.0f)); - - osg::ref_ptr frameStamp = new osg::FrameStamp; + viewer.setSceneData(loadedModel.get()); - unsigned int frameNum = 0; + viewer.setCameraManipulator(new osgGA::TrackballManipulator()); + viewer.getCamera()->setClearColor(osg::Vec4f(0.6f,0.6f,0.8f,1.0f)); - osgUtil::UpdateVisitor updateVisitor; - updateVisitor.setFrameStamp(frameStamp.get()); - - setUpFrameStamp(viewer->getCamera(), frameStamp.get(), loadedModel.get()); - for(unsigned i=0; igetNumSlaves(); ++i) + viewer.setUpViewAcrossAllScreens(); + viewer.realize(); + + while(!viewer.done()) { - osg::View::Slave& slave = viewer->getSlave(i); - setUpFrameStamp(slave._camera.get(), frameStamp.get(), loadedModel.get()); + viewer.frame(); } - // record the timer tick at the start of rendering. - osg::Timer_t start_tick = osg::Timer::instance()->tick(); - osg::Timer_t previous_tick = start_tick; - - while(true) - { - osg::Timer_t current_tick = osg::Timer::instance()->tick(); - - frameStamp->setReferenceTime(osg::Timer::instance()->delta_s(start_tick,current_tick)); - frameStamp->setFrameNumber(frameNum++); - - //std::cout<<"Frame rate "<<1.0/osg::Timer::instance()->delta_s(previous_tick,current_tick)<accept(updateVisitor); - - viewer->frameAdvance(); - viewer->frameEventTraversal(); - viewer->frameUpdateTraversal(); - - // viewer->getCamera()->setViewMatrix(viewMatrix); - - - if (viewer->getCamera() && viewer->getCamera()->getGraphicsContext()) renderCamera(viewer->getCamera()); - - for(unsigned i=0; igetNumSlaves(); ++i) - { - osg::View::Slave& slave = viewer->getSlave(i); - if (slave._camera.valid() && slave._camera->getGraphicsContext()) renderCamera(slave._camera.get()); - } - - } } diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index 76f65656d..e8bfb9ded 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -136,6 +136,52 @@ class OSG_EXPORT GraphicsContext : public Referenced /** Decrement the usage count associate with a contextID. Once the contextID goes to 0 the contextID is then free to be reused.*/ static void decrementContextIDUsageCount(unsigned int contextID); + public: + + /** Base class for implementing graphics operations.*/ + struct OSG_EXPORT Operation : virtual public Referenced + { + Operation(const std::string& name, bool keep): + _name(name), + _keep(keep) {} + + /** Set the human readable name of the operation.*/ + void setName(const std::string& name) { _name = name; } + + /** Get the human readable name of the operation.*/ + const std::string& getName() const { return _name; } + + /** Set whether the operation should be kept once its been applied.*/ + void setKeep(bool keep) { _keep = keep; } + + /** Get whether the operation should be kept once its been applied.*/ + bool getKeep() const { return _keep; } + + /** if this operation is a barrier then release it.*/ + virtual void release() {} + + /** Do the actual task of this operation.*/ + virtual void operator () (GraphicsContext*) {} + + std::string _name; + bool _keep; + }; + + /** Add operation to end of OperationQueue.*/ + void add(Operation* operation); + + /** Remove operation from OperationQueue.*/ + void remove(Operation* operation); + + /** Remove named operation from OperationQueue.*/ + void remove(const std::string& name); + + /** Remove all operations from OperationQueue.*/ + void removeAllOperations(); + + /** Run the operations. */ + void runOperations(); + public: /** Get the traits of the GraphicsContext.*/ @@ -242,6 +288,12 @@ class OSG_EXPORT GraphicsContext : public Referenced OpenThreads::Mutex _mutex; OpenThreads::Thread* _threadOfLastMakeCurrent; + typedef std::list< ref_ptr > OperationQueue; + OpenThreads::Mutex _operationsMutex; + osg::ref_ptr _operationsBlock; + OperationQueue _operations; + osg::ref_ptr _currentOperation; + ref_ptr _graphicsThread; }; diff --git a/include/osg/GraphicsThread b/include/osg/GraphicsThread index 68ab7c381..7555ee766 100644 --- a/include/osg/GraphicsThread +++ b/include/osg/GraphicsThread @@ -81,7 +81,7 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread public: GraphicsThread(); - /** Base class for implementing GraphicsThread operations.*/ + /** Base class for implementing graphics operations.*/ struct OSG_EXPORT Operation : virtual public Referenced { Operation(const std::string& name, bool keep): @@ -109,7 +109,7 @@ class OSG_EXPORT GraphicsThread : public Referenced, public OpenThreads::Thread std::string _name; bool _keep; }; - + /** Add operation to end of OperationQueue, this will be * executed by the graphics thread once this operation gets to the head of the queue.*/ void add(Operation* operation, bool waitForCompletion=false); diff --git a/include/osgViewer/Viewer b/include/osgViewer/Viewer index 0f57985c2..2fc609666 100644 --- a/include/osgViewer/Viewer +++ b/include/osgViewer/Viewer @@ -32,27 +32,33 @@ class OSGVIEWER_EXPORT Viewer : public osgViewer::View /** set up windows and associated threads.*/ void realize(); + void setDone(bool done) { _done = done; } + + bool done() { return _done; } + /** Render a complete new frame. - * Calls frameAdvance(), frameEventTraversal(), frameUpateTraversal(), frameCullTraversal() and frameDrawTraversal(). - * Note, no internal makeCurrent() is issued before, or swap buffers called after frame(), these operations are the responsibility of the calling code.*/ + * Calls frameAdvance(), frameEventTraversal(), frameUpateTraversal(), frameRenderingTraversals(). */ virtual void frame(); virtual void frameAdvance(); + virtual void frameEventTraversal(); + virtual void frameUpdateTraversal(); - virtual void frameCullTraversal(); - virtual void frameDrawTraversal(); + + virtual void frameRenderingTraversals(); /** Release all OpenGL objects associated with this viewer's scenegraph. Note, does not deleted the actual OpenGL objects, it just releases them to the pending GL object delete lists which will need flushing once a valid graphics context is obtained.*/ virtual void releaseAllGLObjects(); - /** Clean up all OpenGL objects associated with this viewer's scenegraph. Note, must only be called from the graphics context associated with this viewer.*/ + /** Clean up all OpenGL objects associated with this viewer's scenegraph.*/ virtual void cleanup(); public: void init(); bool _firstFrame; + bool _done; protected: diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index 5b63b065f..46fe8e92e 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -115,6 +115,7 @@ void GraphicsContext::decrementContextIDUsageCount(unsigned int contextID) GraphicsContext::GraphicsContext(): _threadOfLastMakeCurrent(0) { + _operationsBlock = new Block; } GraphicsContext::~GraphicsContext() @@ -248,3 +249,106 @@ void GraphicsContext::setGraphicsThread(GraphicsThread* gt) } } } + +void GraphicsContext::add(Operation* operation) +{ + osg::notify(osg::INFO)<<"Doing add"< lock(_operationsMutex); + + // add the operation to the end of the list + _operations.push_back(operation); + + _operationsBlock->set(true); +} + +void GraphicsContext::remove(Operation* operation) +{ + osg::notify(osg::INFO)<<"Doing remove operation"< lock(_operationsMutex); + + for(OperationQueue::iterator itr = _operations.begin(); + itr!=_operations.end();) + { + if ((*itr)==operation) itr = _operations.erase(itr); + else ++itr; + } + + if (_operations.empty()) + { + _operationsBlock->set(false); + } +} + +void GraphicsContext::remove(const std::string& name) +{ + osg::notify(osg::INFO)<<"Doing remove named operation"< lock(_operationsMutex); + + // find the remove all operations with specificed name + for(OperationQueue::iterator itr = _operations.begin(); + itr!=_operations.end();) + { + if ((*itr)->getName()==name) itr = _operations.erase(itr); + else ++itr; + } + + if (_operations.empty()) + { + _operationsBlock->set(false); + } +} + +void GraphicsContext::removeAllOperations() +{ + osg::notify(osg::INFO)<<"Doing remove all operations"< lock(_operationsMutex); + _operations.clear(); + _operationsBlock->set(false); +} + +void GraphicsContext::runOperations() +{ + for(OperationQueue::iterator itr = _operations.begin(); + itr != _operations.end(); + ) + { + { + OpenThreads::ScopedLock lock(_operationsMutex); + _currentOperation = *itr; + + if (!_currentOperation->getKeep()) + { + itr = _operations.erase(itr); + + if (_operations.empty()) + { + _operationsBlock->set(false); + } + } + else + { + ++itr; + } + } + + if (_currentOperation.valid()) + { + osg::notify(osg::INFO)<<"Doing op "<<_currentOperation->getName()<<" "< lock(_operationsMutex); + _currentOperation = 0; + } + } + } +} diff --git a/src/osg/GraphicsThread.cpp b/src/osg/GraphicsThread.cpp index 132e550c1..6d0bb2807 100644 --- a/src/osg/GraphicsThread.cpp +++ b/src/osg/GraphicsThread.cpp @@ -223,6 +223,11 @@ void GraphicsThread::remove(const std::string& name) if ((*itr)->getName()==name) itr = _operations.erase(itr); else ++itr; } + + if (_operations.empty()) + { + _operationsBlock->set(false); + } } void GraphicsThread::removeAllOperations() @@ -231,6 +236,11 @@ void GraphicsThread::removeAllOperations() OpenThreads::ScopedLock lock(_operationsMutex); _operations.clear(); + + if (_operations.empty()) + { + _operationsBlock->set(false); + } } diff --git a/src/osgViewer/GraphicsWindowX11.cpp b/src/osgViewer/GraphicsWindowX11.cpp index c0125b4eb..c26c8e357 100644 --- a/src/osgViewer/GraphicsWindowX11.cpp +++ b/src/osgViewer/GraphicsWindowX11.cpp @@ -232,7 +232,6 @@ void GraphicsWindowX11::init() XWindowAttributes watt; XGetWindowAttributes( _display, _parent, &watt ); // unsigned int parentWindowHeight = watt.height; - osg::notify(osg::NOTICE)<<"First watt.x = "<(gc.get()); if (gw) { - osg::notify(osg::NOTICE)<<" GraphicsWindow has been created successfully."<getEventQueue()->setUseFixedMouseInputRange(true); gw->getEventQueue()->getCurrentEventState()->setInputRange(inputRangeMinX, inputRangeMinY, inputRangeMinX+float(width),inputRangeMinY+float(height) ); @@ -167,14 +167,37 @@ void View::setUpViewAcrossAllScreens() assignSceneDataToCameras(); } +// Draw operation, that does a draw on the scene graph. +struct RenderingOperation : public osg::GraphicsContext::Operation +{ + RenderingOperation(osgViewer::View* view, osg::Camera* camera, osg::FrameStamp* frameStamp): + osg::GraphicsContext::Operation("Render",true) + { + _sceneView = new osgUtil::SceneView; + _sceneView->setDefaults(); + _sceneView->setCamera(camera); + _sceneView->setState(camera->getGraphicsContext()->getState()); + _sceneView->setSceneData(view->getSceneData()); + _sceneView->setFrameStamp(frameStamp); + + } + + virtual void operator () (osg::GraphicsContext*) + { + _sceneView->cull(); + _sceneView->draw(); + } + + osg::ref_ptr _sceneView; +}; + void View::setUpRenderingSupport() { + osg::FrameStamp* frameStamp = _scene->getFrameStamp(); + if (_camera.valid() && _camera->getGraphicsContext()) { - osg::ref_ptr sceneView = new osgUtil::SceneView; - sceneView->setState(_camera->getGraphicsContext()->getState()); - sceneView->setCamera(_camera.get()); - _camera->setRenderingCache(0, sceneView.get()); + _camera->getGraphicsContext()->add(new RenderingOperation(this, _camera.get(), frameStamp)); } for(unsigned i=0; igetGraphicsContext()) { - osg::ref_ptr sceneView = new osgUtil::SceneView; - sceneView->setDefaults(); - sceneView->setState(slave._camera->getGraphicsContext()->getState()); - sceneView->setCamera(slave._camera.get()); - slave._camera->setRenderingCache(0, sceneView.get()); + slave._camera->getGraphicsContext()->add(new RenderingOperation(this, slave._camera.get(), frameStamp)); } } } diff --git a/src/osgViewer/Viewer.cpp b/src/osgViewer/Viewer.cpp index 6fc8dab50..af2428d16 100644 --- a/src/osgViewer/Viewer.cpp +++ b/src/osgViewer/Viewer.cpp @@ -30,7 +30,8 @@ public: }; Viewer::Viewer(): - _firstFrame(true) + _firstFrame(true), + _done(false) { } @@ -40,7 +41,7 @@ Viewer::~Viewer() void Viewer::init() { - osg::notify(osg::NOTICE)<<"Viewer::init()"< initEvent = _eventQueue->createEvent(); initEvent->setEventType(osgGA::GUIEventAdapter::FRAME); @@ -54,7 +55,7 @@ void Viewer::init() void Viewer::realize() { - osg::notify(osg::NOTICE)<<"Viewer::realize()"<getGraphicsContext()) { @@ -66,7 +67,7 @@ void Viewer::realize() Slave& slave = getSlave(i); if (slave._camera.valid() && slave._camera->getGraphicsContext()) { - osg::notify(osg::NOTICE)<<" slave realize()"<getGraphicsContext()->realize(); } } @@ -85,7 +86,7 @@ void Viewer::realize() Slave& slave = getSlave(i); if (slave._camera.valid() && slave._camera->getGraphicsContext()) { - osg::notify(osg::NOTICE)<<" slave realize()"<getGraphicsContext()->realize(); osgViewer::GraphicsWindow* gw = dynamic_cast(slave._camera->getGraphicsContext()); gw->grabFocusIfPointerInWindow(); @@ -98,20 +99,24 @@ void Viewer::realize() void Viewer::frame() { + if (_done) return; + if (_firstFrame) { init(); _firstFrame = false; } + frameAdvance(); frameEventTraversal(); frameUpdateTraversal(); - frameCullTraversal(); - frameDrawTraversal(); + frameRenderingTraversals(); } void Viewer::frameAdvance() { + if (_done) return; + // osg::notify(osg::NOTICE)<<"Viewer::frameAdvance()."<frameAdvance(); @@ -119,6 +124,8 @@ void Viewer::frameAdvance() void Viewer::frameEventTraversal() { + if (_done) return; + // osg::notify(osg::NOTICE)<<"Viewer::frameEventTraversal()."<get(); + switch(event->getEventType()) + { + case(osgGA::GUIEventAdapter::KEYUP): + if (event->getKey()=='q') _done = true; + break; + default: + break; + } + } + + if (_done) return; + ActionAdapter aa; for(osgGA::EventQueue::Events::iterator itr = events.begin(); @@ -227,6 +252,10 @@ void Viewer::frameEventTraversal() void Viewer::frameUpdateTraversal() { + if (_done) return; + + if (_scene.valid()) _scene->frameUpdateTraversal(); + if (_cameraManipulator.valid()) { _camera->setViewMatrix(_cameraManipulator->getInverseMatrix()); @@ -235,14 +264,50 @@ void Viewer::frameUpdateTraversal() updateSlaves(); } -void Viewer::frameCullTraversal() +void Viewer::frameRenderingTraversals() { - osg::notify(osg::NOTICE)<<"Viewer::frameCullTraversal() not implemented yet."< GraphicsContexts; + GraphicsContexts contexts; + + if (_camera.valid() && _camera->getGraphicsContext()) + { + osgViewer::GraphicsWindow* gw = dynamic_cast(_camera->getGraphicsContext()); + if (gw) + { + contexts.insert(gw); + } + } + + for(unsigned int i=0; igetGraphicsContext()) + { + osgViewer::GraphicsWindow* gw = dynamic_cast(slave._camera->getGraphicsContext()); + if (gw) + { + contexts.insert(gw); + } + } + } + + for(GraphicsContexts::iterator itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + if (_done) return; + const_cast(*itr)->makeCurrent(); + const_cast(*itr)->runOperations(); + } + + for(GraphicsContexts::iterator itr = contexts.begin(); + itr != contexts.end(); + ++itr) + { + const_cast(*itr)->swapBuffers(); + } } void Viewer::releaseAllGLObjects()