Implemented perliminary multi-threading support in osgViewer::Viewer
This commit is contained in:
parent
b4ec8a8275
commit
bd6b7d581e
@ -3,58 +3,11 @@
|
||||
// Simple example of use of Producer::RenderSurface to create an OpenGL
|
||||
// graphics window, and OSG for rendering.
|
||||
|
||||
#include <osg/Timer>
|
||||
#include <osg/GraphicsContext>
|
||||
#include <osg/GraphicsThread>
|
||||
|
||||
#include <osgUtil/UpdateVisitor>
|
||||
#include <osgUtil/CullVisitor>
|
||||
#include <osgUtil/SceneView>
|
||||
#include <osgUtil/GLObjectsVisitor>
|
||||
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgDB/DynamicLibrary>
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include <osgViewer/View>
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
|
||||
#include <osgGA/TrackballManipulator>
|
||||
|
||||
void renderCamera(osg::Camera* camera)
|
||||
{
|
||||
osg::GraphicsContext* gc = camera->getGraphicsContext();
|
||||
if (!gc) return;
|
||||
|
||||
osgUtil::SceneView* sceneView = dynamic_cast<osgUtil::SceneView*>(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<osgUtil::SceneView*>(camera->getRenderingCache(0));
|
||||
if (!sceneView) return;
|
||||
|
||||
sceneView->setFrameStamp(frameStamp);
|
||||
|
||||
sceneView->setSceneData(loadedModel);
|
||||
|
||||
}
|
||||
#include <iostream>
|
||||
|
||||
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<osg::Node> 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"<<std::endl;
|
||||
|
||||
osgUtil::GLObjectsVisitor compileVisitor;
|
||||
compileVisitor.setState(context->getState());
|
||||
|
||||
// do the compile traversal
|
||||
_scene->accept(compileVisitor);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::Node> _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<osgUtil::SceneView> _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<osgUtil::SceneView> _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<osgUtil::SceneView> _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<osgDB::DynamicLibrary> windowingLib =
|
||||
osgDB::DynamicLibrary::loadLibrary(osgDB::Registry::instance()->createLibraryNameForNodeKit(windowingLibrary));
|
||||
|
||||
|
||||
if (!windowingLib)
|
||||
{
|
||||
std::cout<<"Error: failed to loading windowing library: "<<windowingLibrary<<std::endl;
|
||||
}
|
||||
|
||||
osg::GraphicsContext::GraphicsContext::WindowingSystemInterface* wsi = osg::GraphicsContext::getWindowingSystemInterface();
|
||||
if (!wsi)
|
||||
{
|
||||
std::cout<<"No WindowSystemInterface available, cannot create windows."<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
osg::ref_ptr<osgViewer::View> 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<osg::Node> 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<osg::FrameStamp> frameStamp = new osg::FrameStamp;
|
||||
|
||||
unsigned int frameNum = 0;
|
||||
|
||||
osgUtil::UpdateVisitor updateVisitor;
|
||||
updateVisitor.setFrameStamp(frameStamp.get());
|
||||
|
||||
typedef std::list< osg::ref_ptr<osg::Camera> > 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<osg::Camera> camera = new osg::Camera;
|
||||
camera->addChild(loadedModel.get());
|
||||
|
||||
osg::ref_ptr<osg::GraphicsContext::Traits> 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<osg::GraphicsContext> gfxc = osg::GraphicsContext::createGraphicsContext(traits.get());
|
||||
|
||||
if (!gfxc)
|
||||
{
|
||||
std::cout<<"Unable to create window."<<std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// 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<osg::GraphicsContext*>((*citr)->getGraphicsContext()));
|
||||
}
|
||||
|
||||
|
||||
std::cout<<"Number of cameras = "<<cameraList.size()<<std::endl;
|
||||
std::cout<<"Number of graphics contexts = "<<graphicsContextSet.size()<<std::endl;
|
||||
|
||||
|
||||
// first the compile of the GL Objects, do it syncronously.
|
||||
GraphicsContextSet::iterator gitr;
|
||||
osg::ref_ptr<CompileOperation> compileOp = new CompileOperation(loadedModel.get());
|
||||
for(gitr = graphicsContextSet.begin();
|
||||
gitr != graphicsContextSet.end();
|
||||
++gitr)
|
||||
{
|
||||
osg::GraphicsContext* context = *gitr;
|
||||
context->getGraphicsThread()->add(compileOp.get(), false);
|
||||
}
|
||||
|
||||
|
||||
// second the begin frame barrier to all graphics threads
|
||||
osg::ref_ptr<osg::BarrierOperation> frameBeginBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
|
||||
for(gitr = graphicsContextSet.begin();
|
||||
gitr != graphicsContextSet.end();
|
||||
++gitr)
|
||||
{
|
||||
osg::GraphicsContext* context = *gitr;
|
||||
context->getGraphicsThread()->add(frameBeginBarrierOp.get(), false);
|
||||
}
|
||||
|
||||
osg::ref_ptr<osg::BarrierOperation> glFinishBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FINISH);
|
||||
|
||||
// we can put a finish in to gate rendering throughput, so that each new frame starts with a clean sheet.
|
||||
// you should only enable one of these, doFinishBeforeNewDraw will allow for the better parallism of the two finish approaches
|
||||
// note, both are disabled right now, as glFinish is spin locking the CPU, not something that we want...
|
||||
bool doFinishBeforeNewDraw = false;
|
||||
bool doFinishAfterSwap = false;
|
||||
|
||||
// third add the frame for each camera.
|
||||
for(citr = cameraList.begin();
|
||||
citr != cameraList.end();
|
||||
++citr)
|
||||
{
|
||||
osg::Camera* camera = citr->get();
|
||||
osg::GraphicsThread* graphicsThread = camera->getGraphicsContext()->getGraphicsThread();
|
||||
|
||||
// create a scene view to do the cull and draw
|
||||
osgUtil::SceneView* sceneView = new osgUtil::SceneView;
|
||||
sceneView->setDefaults();
|
||||
sceneView->setFrameStamp(frameStamp.get());
|
||||
sceneView->setCamera(camera);
|
||||
|
||||
// cull traversal operation
|
||||
graphicsThread->add( new CullOperation(sceneView), false);
|
||||
|
||||
// optionally add glFinish barrier to ensure that all OpenGL commands are completed before we start dispatching a new frame
|
||||
if (doFinishBeforeNewDraw) graphicsThread->add( glFinishBarrierOp.get(), false);
|
||||
|
||||
// draw traversal operation.
|
||||
graphicsThread->add( new DrawOperation(sceneView), false);
|
||||
}
|
||||
|
||||
// fourth add the frame end barrier, the pre swap barrier and finally the swap buffers to each graphics thread.
|
||||
// The frame end barrier tells the main thead that the draw dispatch/read phase of the scene graph is complete.
|
||||
// The pre swap barrier is an optional extra, which does a flush before joining the barrier, using this all graphics threads
|
||||
// are held back until they have all dispatched their fifo to the graphics hardware.
|
||||
// The swapOp just issues a swap buffers for each of the graphics contexts.
|
||||
osg::ref_ptr<osg::BarrierOperation> frameEndBarrierOp = new osg::BarrierOperation(graphicsContextSet.size()+1, osg::BarrierOperation::NO_OPERATION);
|
||||
osg::ref_ptr<osg::BarrierOperation> preSwapBarrierOp = new osg::BarrierOperation(graphicsContextSet.size(), osg::BarrierOperation::GL_FLUSH);
|
||||
osg::ref_ptr<osg::SwapBuffersOperation> swapOp = new osg::SwapBuffersOperation();
|
||||
for(gitr = graphicsContextSet.begin();
|
||||
gitr != graphicsContextSet.end();
|
||||
++gitr)
|
||||
{
|
||||
osg::GraphicsContext* context = *gitr;
|
||||
|
||||
context->getGraphicsThread()->add(frameEndBarrierOp.get(), false);
|
||||
// context->getGraphicsThread()->add(preSwapBarrierOp.get(), false);
|
||||
context->getGraphicsThread()->add(swapOp.get(), false);
|
||||
|
||||
// optionally add finish barrier to ensure that we don't do any other graphics work till the current OpenGL commands are complete.
|
||||
if (doFinishAfterSwap) context->getGraphicsThread()->add(glFinishBarrierOp.get(), false);
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
bool done = false;
|
||||
|
||||
// main loop - update scene graph, dispatch frame, wait for frame done.
|
||||
while( !done && frameNum<maxNumFrames)
|
||||
{
|
||||
|
||||
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)<<std::endl;
|
||||
previous_tick = current_tick;
|
||||
|
||||
|
||||
// do the update traversal.
|
||||
loadedModel->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"<<std::endl;
|
||||
|
||||
// start clean up.
|
||||
for(gitr = graphicsContextSet.begin();
|
||||
gitr != graphicsContextSet.end();
|
||||
++gitr)
|
||||
{
|
||||
osg::GraphicsContext* context = *gitr;
|
||||
osg::GraphicsThread* thread = context->getGraphicsThread();
|
||||
if (thread)
|
||||
{
|
||||
thread->removeAllOperations();
|
||||
thread->setDone(true);
|
||||
}
|
||||
}
|
||||
|
||||
std::cout<<"Removed all operations"<<std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <osgGA/MatrixManipulator>
|
||||
#include <osgViewer/Scene>
|
||||
|
||||
#include <osgUtil/SceneView>
|
||||
|
||||
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<osgGA::MatrixManipulator> _cameraManipulator;
|
||||
EventHandlers _eventHandlers;
|
||||
|
||||
typedef std::map<osg::ref_ptr<osg::Camera>, osg::ref_ptr<osgUtil::SceneView> > CameraSceneViewMap;
|
||||
CameraSceneViewMap _cameraSceneViewMap;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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<osg::GraphicsContext*> Contexts;
|
||||
void getContexts(Contexts& contexts);
|
||||
|
||||
bool _firstFrame;
|
||||
bool _done;
|
||||
|
||||
protected:
|
||||
|
||||
|
||||
osg::ref_ptr<osg::BarrierOperation> _startRenderingBarrier;
|
||||
osg::ref_ptr<osg::BarrierOperation> _endRenderingDispatchBarrier;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -242,11 +242,12 @@ void GraphicsContext::setGraphicsThread(GraphicsThread* gt)
|
||||
if (_graphicsThread.valid())
|
||||
{
|
||||
_graphicsThread->_graphicsContext = this;
|
||||
|
||||
#if 0
|
||||
if (!_graphicsThread->isRunning())
|
||||
{
|
||||
_graphicsThread->startThread();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user