Added handling of automatic setting up of the contextID.

This commit is contained in:
Robert Osfield 2005-07-25 14:28:22 +00:00
parent 3c23a42f17
commit 384830d37e
5 changed files with 137 additions and 17 deletions

View File

@ -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> _traits;
ref_ptr<State> _state;

View File

@ -13,6 +13,8 @@
#include <osg/GraphicsContext>
#include <osg/Notify>
#include <map>
using namespace osg;
@ -36,8 +38,90 @@ GraphicsContext* GraphicsContext::createGraphicsContext(Traits* traits)
return 0;
}
typedef std::map<unsigned int, unsigned int> ContextIDMap;
static ContextIDMap s_contextIDMap;
static OpenThreads::Mutex s_contextIDMapMutex;
unsigned int GraphicsContext::createNewContextID()
{
OpenThreads::ScopedLock<OpenThreads::Mutex> 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="<<itr->first<<std::endl;
return itr->first;
}
}
unsigned int contextID = s_contextIDMap.size();
s_contextIDMap[contextID] = 1;
osg::notify(osg::INFO)<<"GraphicsContext::createNewContextID() creating contextID="<<contextID<<std::endl;
if ( (contextID+1) > osg::DisplaySettings::instance()->getMaxNumberOfGraphicsContexts() )
{
osg::notify(osg::INFO)<<"Updating the MaxNumberOfGraphicsContexts to "<<contextID+1<<std::endl;
// update the the maximum number of graphics contexts,
// to ensure that texture objects and display buffers are configured to the correct size.
osg::DisplaySettings::instance()->setMaxNumberOfGraphicsContexts( contextID + 1 );
}
return contextID;
}
void GraphicsContext::incrementContextIDUsageCount(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
osg::notify(osg::INFO)<<"GraphicsContext::incrementContextIDUsageCount("<<contextID<<") to "<<s_contextIDMap[contextID]<<std::endl;
++s_contextIDMap[contextID];
}
void GraphicsContext::decrementContextIDUsageCount(unsigned int contextID)
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(s_contextIDMapMutex);
if (s_contextIDMap[contextID]!=0)
{
--s_contextIDMap[contextID];
}
else
{
osg::notify(osg::NOTICE)<<"Warning: decrementContextIDUsageCount("<<contextID<<") called on expired contextID."<<std::endl;
}
osg::notify(osg::INFO)<<"GraphicsContext::decrementContextIDUsageCount("<<contextID<<") to "<<s_contextIDMap[contextID]<<std::endl;
}
GraphicsContext::GraphicsContext():
_threadOfLastMakeCurrent(0)
{
}
GraphicsContext::~GraphicsContext()
{
if (_state.valid())
{
decrementContextIDUsageCount(_state->getContextID());
}
}

View File

@ -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();
}

View File

@ -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<Producer::RenderSurface*,osg::State*> 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
{

View File

@ -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());