Added cloning of the StateSet before modification to work around threading issue

relating to the StateSet being modified by the event/update thread and read from
the draw thread at the same time.
This commit is contained in:
Robert Osfield
2008-03-14 13:21:35 +00:00
parent 8be3123cbf
commit 9c56c5277f

View File

@@ -56,6 +56,35 @@ const StateSet *StateSetManipulator::getStateSet() const
return _stateset.get();
}
void StateSetManipulator::clone()
{
if (!_stateset) return;
// we clone the StateSet so that any draw traversals that might be running at the time of the
// event traversal won't change the same StateSet that is being read. One could just set the
// DataVariance to DYNAMIC to avoid this overlap, but this would introduce a performance penalty.
StateSet::ParentList parents = _stateset->getParents();
osg::ref_ptr<osg::StateSet> newStateSet = dynamic_cast<osg::StateSet*>(_stateset->clone(osg::CopyOp::SHALLOW_COPY));
// change the parents of the original StateSet to point to the new stateset
for(StateSet::ParentList::iterator itr = parents.begin();
itr != parents.end();
++itr)
{
osg::Object* object = *itr;
osg::Node* node = dynamic_cast<osg::Node*>(object);
if (node) node->setStateSet(newStateSet.get());
else
{
osg::Drawable* drawable = dynamic_cast<osg::Drawable*>(object);
if (drawable) drawable->setStateSet(newStateSet.get());
}
}
_stateset = newStateSet;
}
bool StateSetManipulator::handle(const GUIEventAdapter& ea,GUIActionAdapter& aa)
{
if(!_stateset.valid()) return false;
@@ -119,6 +148,10 @@ void StateSetManipulator::getUsage(osg::ApplicationUsage& usage) const
void StateSetManipulator::setBackfaceEnabled(bool newbackface)
{
if (_backface == newbackface) return;
clone();
_backface = newbackface;
if( _backface ) _stateset->setMode(GL_CULL_FACE,osg::StateAttribute::ON);
else _stateset->setMode(GL_CULL_FACE,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
@@ -126,6 +159,10 @@ void StateSetManipulator::setBackfaceEnabled(bool newbackface)
void StateSetManipulator::setLightingEnabled(bool newlighting)
{
if (_lighting == newlighting) return;
clone();
_lighting = newlighting;
if( _lighting ) _stateset->setMode(GL_LIGHTING,osg::StateAttribute::ON);
else _stateset->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
@@ -133,6 +170,10 @@ void StateSetManipulator::setLightingEnabled(bool newlighting)
void StateSetManipulator::setTextureEnabled(bool newtexture)
{
if (_texture==newtexture) return;
clone();
_texture = newtexture;
// osg::ref_ptr< osg::Texture > tex = dynamic_cast<osg::Texture*>
// ( _stateset->getAttribute( osg::StateAttribute::TEXTURE ) );
@@ -152,6 +193,8 @@ void StateSetManipulator::setTextureEnabled(bool newtexture)
void StateSetManipulator::setPolygonMode(osg::PolygonMode::Mode newpolygonmode)
{
clone();
osg::PolygonMode* polyModeObj = getOrCreatePolygonMode();
polyModeObj->setMode(osg::PolygonMode::FRONT_AND_BACK,newpolygonmode);
@@ -159,6 +202,8 @@ void StateSetManipulator::setPolygonMode(osg::PolygonMode::Mode newpolygonmode)
void StateSetManipulator::cyclePolygonMode()
{
clone();
osg::PolygonMode* polyModeObj = getOrCreatePolygonMode();
osg::PolygonMode::Mode currentMode = getPolygonMode();