diff --git a/include/osg/CameraNode b/include/osg/CameraNode index b0720b035..0769ac5b6 100644 --- a/include/osg/CameraNode +++ b/include/osg/CameraNode @@ -22,6 +22,8 @@ #include #include +#include + namespace osg { /** CameraNode - is a subclass of Transform which represents encapsulates the settings of a Camera. @@ -273,13 +275,13 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings /** Set the Rendering object that is used to implement rendering of the subgraph.*/ - void setRenderingCache(osg::Object* rc) { _renderingCache = rc; } + void setRenderingCache(unsigned int contextID, osg::Object* rc) { _renderingCache[contextID] = rc; } /** Get the Rendering object that is used to implement rendering of the subgraph.*/ - osg::Object* getRenderingCache() { return _renderingCache.get(); } + osg::Object* getRenderingCache(unsigned int contextID) { return _renderingCache[contextID].get(); } /** Get the const Rendering object that is used to implement rendering of the subgraph.*/ - const osg::Object* getRenderingCache() const { return _renderingCache.get(); } + const osg::Object* getRenderingCache(unsigned int contextID) const { return _renderingCache[contextID].get(); } /** Draw callback for custom operations.*/ @@ -303,6 +305,7 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings /** Get the const post draw callback.*/ const DrawCallback* getPostDrawCallback() const { return _postDrawCallback.get(); } + OpenThreads::Mutex& getDataChangeMutex() const { return _dataChangeMutex; } public: @@ -315,6 +318,8 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings protected : virtual ~CameraNode(); + + mutable OpenThreads::Mutex _dataChangeMutex; Vec4 _clearColor; GLbitfield _clearMask; @@ -334,10 +339,10 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings RenderTargetImplementation _renderTargetFallback; BufferAttachmentMap _bufferAttachmentMap; - ref_ptr _graphicsContext; - ref_ptr _renderingCache; + ref_ptr _graphicsContext; + buffered_object< ref_ptr > _renderingCache; - ref_ptr _postDrawCallback; + ref_ptr _postDrawCallback; }; } diff --git a/src/osg/FrameBufferObject.cpp b/src/osg/FrameBufferObject.cpp index 38d7f5c8d..089b89b2e 100644 --- a/src/osg/FrameBufferObject.cpp +++ b/src/osg/FrameBufferObject.cpp @@ -404,9 +404,6 @@ void FrameBufferObject::apply(State &state) const return; - - state.checkGLErrors("A"); - FBOExtensions* ext = FBOExtensions::instance(contextID); if (!ext->isSupported()) { @@ -421,8 +418,6 @@ void FrameBufferObject::apply(State &state) const return; } - state.checkGLErrors("B"); - int &dirtyAttachmentList = _dirtyAttachmentList[contextID]; GLuint &fboID = _fboID[contextID]; @@ -439,10 +434,16 @@ void FrameBufferObject::apply(State &state) const } - state.checkGLErrors("C"); - if (dirtyAttachmentList) { + // the set of of attachements appears to be thread sensitive, it shouldn't be because + // OpenGL FBO handles osg::FrameBufferObject has are multi-buffered... + // so as a temporary fix will stick in a mutex to ensure that only one thread passes through here + // at one time. + static OpenThreads::Mutex s_mutex; + OpenThreads::ScopedLock lock(s_mutex); + + // create textures and mipmaps before we bind the frame buffer object for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i) { @@ -452,12 +453,8 @@ void FrameBufferObject::apply(State &state) const } - state.checkGLErrors("D"); - ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID); - state.checkGLErrors("E"); - if (dirtyAttachmentList) { for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i) @@ -467,7 +464,7 @@ void FrameBufferObject::apply(State &state) const } dirtyAttachmentList = 0; } - state.checkGLErrors("F"); + } int FrameBufferObject::compare(const StateAttribute &sa) const diff --git a/src/osgUtil/CullVisitor.cpp b/src/osgUtil/CullVisitor.cpp index 23c8cc991..6c630d113 100644 --- a/src/osgUtil/CullVisitor.cpp +++ b/src/osgUtil/CullVisitor.cpp @@ -1097,12 +1097,15 @@ void CullVisitor::apply(osg::CameraNode& camera) // will do later. osgUtil::RenderStage* previous_stage = getCurrentRenderBin()->getStage(); + unsigned int contextID = getState() ? getState()->getContextID() : 0; // use render to texture stage. // create the render to texture stage. - osg::ref_ptr rtts = dynamic_cast(camera.getRenderingCache()); + osg::ref_ptr rtts = dynamic_cast(camera.getRenderingCache(contextID)); if (!rtts) { + OpenThreads::ScopedLock lock(camera.getDataChangeMutex()); + rtts = new osgUtil::RenderStage; rtts->setCameraNode(&camera); @@ -1126,7 +1129,7 @@ void CullVisitor::apply(osg::CameraNode& camera) rtts->setReadBuffer(previous_stage->getReadBuffer()); } - camera.setRenderingCache(rtts.get()); + camera.setRenderingCache(contextID, rtts.get()); } else { diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 6f59ba0f5..d2d65b385 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -286,6 +286,8 @@ void RenderStage::runCameraSetUp(osg::State& state) { osg::notify(osg::INFO)<<"Setting up osg::CameraNode::FRAME_BUFFER_OBJECT"< lock(_camera->getDataChangeMutex()); + _fbo = new osg::FrameBufferObject; setDrawBuffer(GL_NONE); @@ -766,7 +768,7 @@ void RenderStage::draw(osg::State& state,RenderLeaf*& previous) void RenderStage::drawImplementation(osg::State& state,RenderLeaf*& previous) { - + if (!_viewport) { notify(FATAL) << "Error: cannot draw stage due to undefined viewport."<< std::endl; diff --git a/src/osgWrappers/osg/CameraNode.cpp b/src/osgWrappers/osg/CameraNode.cpp index dac428362..443fc1444 100644 --- a/src/osgWrappers/osg/CameraNode.cpp +++ b/src/osgWrappers/osg/CameraNode.cpp @@ -129,18 +129,20 @@ BEGIN_OBJECT_REFLECTOR(osg::CameraNode) I_Method1(void, setGraphicsContext, IN, osg::GraphicsContext *, context); I_Method0(osg::GraphicsContext *, getGraphicsContext); I_Method0(const osg::GraphicsContext *, getGraphicsContext); - I_Method1(void, setRenderingCache, IN, osg::Object *, rc); - I_Method0(osg::Object *, getRenderingCache); - I_Method0(const osg::Object *, getRenderingCache); + I_Method2(void, setRenderingCache, IN, unsigned int, contextID, IN, osg::Object *, rc); + I_Method1(osg::Object *, getRenderingCache, IN, unsigned int, contextID); + I_Method1(const osg::Object *, getRenderingCache, IN, unsigned int, contextID); I_Method1(void, setPostDrawCallback, IN, osg::CameraNode::DrawCallback *, cb); I_Method0(osg::CameraNode::DrawCallback *, getPostDrawCallback); I_Method0(const osg::CameraNode::DrawCallback *, getPostDrawCallback); + I_Method0(OpenThreads::Mutex &, getDataChangeMutex); I_Method2(bool, computeLocalToWorldMatrix, IN, osg::Matrix &, matrix, IN, osg::NodeVisitor *, x); I_Method2(bool, computeWorldToLocalMatrix, IN, osg::Matrix &, matrix, IN, osg::NodeVisitor *, x); I_ReadOnlyProperty(osg::CameraNode::BufferAttachmentMap &, BufferAttachmentMap); I_Property(const osg::Vec4 &, ClearColor); I_Property(GLbitfield, ClearMask); I_Property(osg::ColorMask *, ColorMask); + I_ReadOnlyProperty(OpenThreads::Mutex &, DataChangeMutex); I_Property(GLenum, DrawBuffer); I_Property(osg::GraphicsContext *, GraphicsContext); I_ReadOnlyProperty(osg::Matrixd, InverseViewMatrix); @@ -150,7 +152,7 @@ BEGIN_OBJECT_REFLECTOR(osg::CameraNode) I_Property(osg::CameraNode::RenderOrder, RenderOrder); I_ReadOnlyProperty(osg::CameraNode::RenderTargetImplementation, RenderTargetFallback); I_Property(osg::CameraNode::RenderTargetImplementation, RenderTargetImplementation); - I_Property(osg::Object *, RenderingCache); + I_IndexedProperty1(osg::Object *, RenderingCache, unsigned int, contextID); I_Property(osg::CameraNode::TransformOrder, TransformOrder); I_Property(const osg::Matrixd &, ViewMatrix); I_Property(osg::Viewport *, Viewport);