diff --git a/include/osg/GraphicsContext b/include/osg/GraphicsContext index f79e3892c..ca73d0f77 100644 --- a/include/osg/GraphicsContext +++ b/include/osg/GraphicsContext @@ -19,10 +19,12 @@ namespace osg { +/** Base class for providing Windowing API agnostic access to creating and managing graphics context.*/ class OSG_EXPORT GraphicsContext : public Referenced { public: + /** GraphicsContext Traits object provides the specification of what type of graphics context is required.*/ struct Traits : public osg::Referenced { Traits(): @@ -87,6 +89,7 @@ class OSG_EXPORT GraphicsContext : public Referenced }; + /** Callback to be implemented to provide access to Windowing API's ability to create Windows/pbuffers.*/ struct CreateGraphicContexCallback : public osg::Referenced { virtual GraphicsContext* createGraphicsContext(Traits* traits) = 0; @@ -95,11 +98,24 @@ class OSG_EXPORT GraphicsContext : public Referenced }; + /** Set the create graphics context callback - this callback should be supplied by the windows toolkit. */ static void setCreateGraphicsContextCallback(CreateGraphicContexCallback* callback); + /** Get the create graphics context callback*/ static CreateGraphicContexCallback* getCreateGraphicsContextCallback(); + /** Create a graphics context for a specified set of traits.*/ static GraphicsContext* createGraphicsContext(Traits* traits); + + /** Create a contextID for a new graphics context, this contextID is used to set up the osg::State associate with context. + * Automatically increments the usage count of the contextID to 1.*/ + static unsigned int createNewContextID(); + + /** Increment the usage count associate with a contextID. The usage count speficies how many graphics contexts a specific contextID is shared between.*/ + static void incrementContextIDUsageCount(unsigned int contextID); + + /** 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: @@ -139,7 +155,7 @@ class OSG_EXPORT GraphicsContext : public Referenced GraphicsContext(); - virtual ~GraphicsContext() {} + virtual ~GraphicsContext(); ref_ptr _traits; ref_ptr _state; diff --git a/src/osg/GraphicsContext.cpp b/src/osg/GraphicsContext.cpp index 8fd01e4fe..d8a1cf1a3 100644 --- a/src/osg/GraphicsContext.cpp +++ b/src/osg/GraphicsContext.cpp @@ -13,6 +13,8 @@ #include +#include +#include using namespace osg; @@ -36,8 +38,90 @@ GraphicsContext* GraphicsContext::createGraphicsContext(Traits* traits) return 0; } + +typedef std::map ContextIDMap; +static ContextIDMap s_contextIDMap; +static OpenThreads::Mutex s_contextIDMapMutex; + +unsigned int GraphicsContext::createNewContextID() +{ + OpenThreads::ScopedLock lock(s_contextIDMapMutex); + + // first check to see if we can reuse contextID; + for(ContextIDMap::iterator itr = s_contextIDMap.begin(); + itr != s_contextIDMap.end(); + ++itr) + { + if (itr->second == 0) + { + + // reuse contextID; + itr->second = 1; + + osg::notify(osg::NOTICE)<<"GraphicsContext::createNewContextID() reusing contextID="<first<first; + } + } + + unsigned int contextID = s_contextIDMap.size(); + s_contextIDMap[contextID] = 1; + + osg::notify(osg::INFO)<<"GraphicsContext::createNewContextID() creating contextID="< osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts() ) + { + osg::notify(osg::INFO)<<"Updating the MaxNumberOfGraphicsContexts to "<setMaxNumberOfGraphicsContexts( contextID + 1 ); + } + + + return contextID; +} + +void GraphicsContext::incrementContextIDUsageCount(unsigned int contextID) +{ + OpenThreads::ScopedLock lock(s_contextIDMapMutex); + + osg::notify(osg::INFO)<<"GraphicsContext::incrementContextIDUsageCount("< lock(s_contextIDMapMutex); + + + if (s_contextIDMap[contextID]!=0) + { + --s_contextIDMap[contextID]; + } + else + { + osg::notify(osg::NOTICE)<<"Warning: decrementContextIDUsageCount("<getContextID()); + } +} + diff --git a/src/osgProducer/GraphicsContextImplementation.cpp b/src/osgProducer/GraphicsContextImplementation.cpp index ad5230409..b51490903 100644 --- a/src/osgProducer/GraphicsContextImplementation.cpp +++ b/src/osgProducer/GraphicsContextImplementation.cpp @@ -99,18 +99,26 @@ GraphicsContextImplementation::GraphicsContextImplementation(Traits* traits) // different graphics context so we have our own state. setState(new osg::State); + if (sharedContext->getState()) + { + getState()->setContextID( sharedContext->getState()->getContextID() ); + incrementContextIDUsageCount( sharedContext->getState()->getContextID() ); + } + else + { + getState()->setContextID( GraphicsContext::createNewContextID() ); + } + // but we share texture objects etc. so we also share the same contextID - getState()->setContextID( sharedContext->getState() ? sharedContext->getState()->getContextID() : 1 ); - - _rs->realize(0, sharedContext->_rs->getGLContext()); + _rs->realize( 0, sharedContext->_rs->getGLContext() ); + } else { - static int count = 1; // need to do something here.... - setState(new osg::State); - getState()->setContextID(count++); + setState( new osg::State ); + getState()->setContextID( GraphicsContext::createNewContextID() ); _rs->realize(); } diff --git a/src/osgProducer/OsgCameraGroup.cpp b/src/osgProducer/OsgCameraGroup.cpp index 62d32f373..9d358a6a1 100644 --- a/src/osgProducer/OsgCameraGroup.cpp +++ b/src/osgProducer/OsgCameraGroup.cpp @@ -239,10 +239,6 @@ void OsgCameraGroup::_init() _start_tick = _timer.tick(); if (!_frameStamp) _frameStamp = new osg::FrameStamp; - - // set up the maximum number of graphics contexts, before loading the scene graph - // to ensure that texture objects and display buffers are configured to the correct size. - osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts( getNumberOfCameras() ); _applicationUsage = osg::ApplicationUsage::instance(); @@ -410,8 +406,6 @@ bool OsgCameraGroup::realize() if (!_ds) _ds = osg::DisplaySettings::instance(); - _ds->setMaxNumberOfGraphicsContexts( _cfg->getNumberOfCameras() ); - _shvec.clear(); osg::Node* node = getTopMostSceneData(); @@ -440,6 +434,8 @@ bool OsgCameraGroup::realize() // use a std::map to keep track of what render surfaces are associated with what state. typedef std::map RenderSurfaceStateMap; RenderSurfaceStateMap _renderSurfaceStateMap; + + bool needToCreatedNewContextID = true; unsigned int contextID = 0; for(unsigned int i = 0; i < _cfg->getNumberOfCameras(); i++ ) @@ -461,11 +457,21 @@ bool OsgCameraGroup::realize() if (_renderSurfaceStateMap.count(rs)==0) { _renderSurfaceStateMap[rs] = sv->getState(); + + if (needToCreatedNewContextID) + { + // create a unique contextID for this graphics context. + contextID = osg::GraphicsContext::createNewContextID(); + + // if we are sharing our graphics context then when needn't create any more. + needToCreatedNewContextID = !Producer::RenderSurface::allGLContextsAreShared(); + } + else + { + osg::GraphicsContext::incrementContextIDUsageCount(contextID); + } + sv->getState()->setContextID(contextID); - - // if we aren't share OpenGL objects between graphics contexts then need to increment the contextID - // to ensure that the OSG generates seperate objects for each graphics context. - if (!Producer::RenderSurface::allGLContextsAreShared()) ++contextID; } else { diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 5eeb69747..4e189a5fb 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1272,6 +1272,12 @@ void CullVisitor::apply(osg::CameraNode& camera) traits->_blue = 8; traits->_alpha = 0; // ??? } + + // share OpenGL objects if possible... + if (_state.valid() && _state->getGraphicsContext()) + { + traits->_sharedContext = _state->getGraphicsContext(); + } // create the graphics context according to these traits. context = osg::GraphicsContext::createGraphicsContext(traits.get());