Implemented perliminary multi-threading support in osgViewer::Viewer

This commit is contained in:
Robert Osfield
2006-12-22 17:46:21 +00:00
parent b4ec8a8275
commit bd6b7d581e
9 changed files with 315 additions and 539 deletions

View File

@@ -242,11 +242,12 @@ void GraphicsContext::setGraphicsThread(GraphicsThread* gt)
if (_graphicsThread.valid())
{
_graphicsThread->_graphicsContext = this;
#if 0
if (!_graphicsThread->isRunning())
{
_graphicsThread->startThread();
}
#endif
}
}

View File

@@ -253,14 +253,29 @@ void GraphicsThread::run()
{
if (!_graphicsContext->isRealized())
{
#if 0
osg::notify(osg::NOTICE)<<"Forced to do a realize in GraphicsThread::run."<<std::endl;
_graphicsContext->realize();
contextRealizedInThisThread = true;
#else
while (!_graphicsContext->isRealized() && !_done)
{
osg::notify(osg::INFO)<<"Waiting in GraphicsThread::run for GraphicsContext to realize."<<std::endl;
YieldCurrentThread();
}
osg::notify(osg::INFO)<<"GraphicsThread::run now released as GraphicsContext has been realized."<<std::endl;
#endif
}
osg::notify(osg::INFO)<<"Doing make current"<<std::endl;
_graphicsContext->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 "<<this<<std::endl;
// osg::notify(osg::NOTICE)<<"In main loop "<<this<<std::endl;
if (_operations.empty())
{
@@ -346,6 +361,8 @@ void GraphicsThread::run()
YieldCurrentThread();
firstTime = false;
}
// osg::notify(osg::NOTICE)<<"operations.size()="<<_operations.size()<<" done="<<_done<<" testCancel()"<<testCancel()<<std::endl;
} while (!testCancel() && !_done);

View File

@@ -219,7 +219,7 @@ void GraphicsWindowX11::init()
// need to pick up from traits
GLXContext sharedGLContext = 0;
_glxContext = glXCreateContext( _display, _visualInfo, sharedGLContext, GL_TRUE );
_glxContext = glXCreateContext( _display, _visualInfo, sharedGLContext, True );
if (!_glxContext)
{
@@ -325,7 +325,11 @@ void GraphicsWindowX11::init()
bool GraphicsWindowX11::realizeImplementation()
{
if (_realized) return true;
if (_realized)
{
osg::notify(osg::NOTICE)<<"GraphicsWindowX11::realizeImplementation() Already realized"<<std::endl;
return true;
}
if (!_initialized) init();
@@ -335,8 +339,6 @@ bool GraphicsWindowX11::realizeImplementation()
Window temp = _window;
XSetWMColormapWindows( _display, _window, &temp, 1);
makeCurrent();
_realized = true;
return true;
@@ -344,7 +346,13 @@ bool GraphicsWindowX11::realizeImplementation()
void GraphicsWindowX11::makeCurrentImplementation()
{
// osg::notify(osg::NOTICE)<<"makeCurrentImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
// osg::notify(osg::NOTICE)<<" glXMakeCurrent ("<<_display<<","<<_window<<","<<_glxContext<<std::endl;
// checkEvents();
glXMakeCurrent( _display, _window, _glxContext );
}
@@ -371,7 +379,18 @@ void GraphicsWindowX11::closeImplementation()
void GraphicsWindowX11::swapBuffersImplementation()
{
// osg::notify(osg::NOTICE)<<"swapBuffersImplementation "<<this<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
// makeCurrentImplementation();
glXSwapBuffers(_display, _window);
#if 0
checkEvents();
#endif
// glFlush();
}
void GraphicsWindowX11::checkEvents()
@@ -419,13 +438,13 @@ void GraphicsWindowX11::checkEvents()
case MapNotify :
{
osg::notify(osg::NOTICE)<<"MapNotify"<<std::endl;
osg::notify(osg::INFO)<<"MapNotify"<<std::endl;
XWindowAttributes watt;
do
XGetWindowAttributes(_display, _window, &watt );
while( watt.map_state != IsViewable );
osg::notify(osg::NOTICE)<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
osg::notify(osg::INFO)<<"MapNotify x="<<watt.x<<" y="<<watt.y<<" width="<<watt.width<<", height="<<watt.height<<std::endl;
_traits->_width = watt.width;
_traits->_height = watt.height;
@@ -631,6 +650,17 @@ struct X11WindowingSystemInterface : public osg::GraphicsContext::WindowingSyste
X11WindowingSystemInterface()
{
#if 1
if (XInitThreads() == 0)
{
osg::notify(osg::NOTICE) << "Error: XInitThreads() failed. Aborting." << std::endl;
exit(1);
}
else
{
osg::notify(osg::INFO) << "X11WindowingSystemInterface, xInitThreads() multi-threaded X support initialized.\n";
}
#endif
}
virtual unsigned int getNumScreens(const osg::GraphicsContext::ScreenIdentifier& si)

View File

@@ -66,9 +66,13 @@ void Scene::setDatabasePager(osgDB::DatabasePager* dp)
void Scene::frameAdvance()
{
// double previousTime = _frameStamp->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)<<std::endl;
}
void Scene::frameEventTraversal()

View File

@@ -170,22 +170,18 @@ void View::setUpViewAcrossAllScreens()
// Draw operation, that does a draw on the scene graph.
struct RenderingOperation : public osg::GraphicsContext::Operation
{
RenderingOperation(osgViewer::View* view, osg::Camera* camera, osgDB::DatabasePager* databasePager, osg::FrameStamp* frameStamp):
RenderingOperation(osgUtil::SceneView* sceneView, osgDB::DatabasePager* databasePager):
osg::GraphicsContext::Operation("Render",true),
_sceneView(sceneView),
_databasePager(databasePager)
{
_sceneView = new osgUtil::SceneView;
_sceneView->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<osgUtil::SceneView> _sceneView;
osg::ref_ptr<osgDB::DatabasePager> _databasePager;
osg::observer_ptr<osgUtil::SceneView> _sceneView;
osg::observer_ptr<osgDB::DatabasePager> _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; i<getNumSlaves(); ++i)
@@ -215,7 +223,16 @@ void View::setUpRenderingSupport()
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
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()));
}
}
}

View File

@@ -15,6 +15,8 @@
*/
#include <osgViewer/Viewer>
#include <osgUtil/GLObjectsVisitor>
#include <osg/GLExtensions>
using namespace osgViewer;
@@ -24,7 +26,7 @@ public:
virtual ~ActionAdapter() {}
virtual void requestRedraw() { /*osg::notify(osg::NOTICE)<<"requestRedraw()"<<std::endl;*/ }
virtual void requestContinuousUpdate(bool needed=true) { /*osg::notify(osg::NOTICE)<<"requestContinuousUpdate("<<needed<<")"<<std::endl;*/ }
virtual void requestContinuousUpdate(bool =true) { /*osg::notify(osg::NOTICE)<<"requestContinuousUpdate("<<needed<<")"<<std::endl;*/ }
virtual void requestWarpPointer(float x,float y) { osg::notify(osg::NOTICE)<<"requestWarpPointer("<<x<<","<<y<<")"<<std::endl; }
};
@@ -37,6 +39,25 @@ Viewer::Viewer():
Viewer::~Viewer()
{
#if 0
Contexts contexts;
getContexts(contexts);
// cancel any graphics threads.
for(Contexts::iterator citr = contexts.begin();
citr != contexts.end();
++citr)
{
osg::GraphicsContext* gc = (*citr);
gc->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()"<<std::endl;
typedef std::set<osg::GraphicsContext*> ContextSet;
ContextSet contextSet;
if (_camera.valid() && _camera->getGraphicsContext())
{
_camera->getGraphicsContext()->realize();
contextSet.insert(_camera->getGraphicsContext());
}
for(unsigned int i=0; i<getNumSlaves(); ++i)
@@ -67,33 +89,153 @@ void Viewer::realize()
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osg::notify(osg::INFO)<<" slave realize()"<<std::endl;
slave._camera->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<osg::GraphicsContext*>(*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<OpenThreads::Mutex> lock(mutex);
// osg::notify(osg::NOTICE)<<"Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
// context->makeCurrentImplementation();
osgUtil::GLObjectsVisitor compileVisitor;
compileVisitor.setState(context->getState());
// do the compile traversal
_scene->accept(compileVisitor);
// osg::notify(osg::NOTICE)<<"Done Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
}
osg::ref_ptr<osg::Node> _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()"<<std::endl;
Contexts::iterator citr;
Contexts contexts;
getContexts(contexts);
bool multiThreaded = getNumSlaves() > 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<osg::SwapBuffersOperation> 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<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
gw->grabFocusIfPointerInWindow();
}
for(unsigned int i=0; i<getNumSlaves(); ++i)
{
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
if (gw)
{
osg::notify(osg::INFO)<<" slave realize()"<<std::endl;
slave._camera->getGraphicsContext()->realize();
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(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<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(*citr);
if (gw)
{
gw->checkEvents();
@@ -141,20 +288,6 @@ void Viewer::frameEventTraversal()
}
}
for(unsigned int i=0; i<getNumSlaves(); ++i)
{
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(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<osg::GraphicsContext*> GraphicsContexts;
GraphicsContexts contexts;
if (_camera.valid() && _camera->getGraphicsContext())
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(_camera->getGraphicsContext());
if (gw)
{
contexts.insert(gw);
}
}
bool multiThreaded = _startRenderingBarrier.valid();
for(unsigned int i=0; i<getNumSlaves(); ++i)
if (multiThreaded)
{
Slave& slave = getSlave(i);
if (slave._camera.valid() && slave._camera->getGraphicsContext())
{
osgViewer::GraphicsWindow* gw = dynamic_cast<osgViewer::GraphicsWindow*>(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<osg::GraphicsContext*>(*itr)->makeCurrent();
const_cast<osg::GraphicsContext*>(*itr)->runOperations();
// osg::notify(osg::NOTICE)<<std::endl<<"Joing _startRenderingBarrier block"<<std::endl;
// dispatch the the rendering threads
_startRenderingBarrier->block();
// osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<<std::endl;
// wait till the rendering dispatch is done.
_endRenderingDispatchBarrier->block();
// osg::notify(osg::NOTICE)<<"Leaving _endRenderingDispatchBarrier block"<<std::endl<<std::endl;
}
for(GraphicsContexts::iterator itr = contexts.begin();
itr != contexts.end();
++itr)
else
{
const_cast<osg::GraphicsContext*>(*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)