From 9724303f381348a9a035a4bbafb3ee245076f039 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 15 Apr 2008 19:36:40 +0000 Subject: [PATCH] From Art Trevs, moved multile render targets support from RenderStage into FrameBufferObject. From Robert Osfield, refactored the FrameBufferObejcts::_drawBuffers set up so that its done within the setAttachment method to avoid potential threading/execution order issues. --- include/osg/FrameBufferObject | 29 +++++++++++-------- include/osgUtil/RenderStage | 2 -- src/osg/FrameBufferObject.cpp | 34 +++++++++++++++++++++-- src/osgUtil/RenderStage.cpp | 25 ++++------------- src/osgWrappers/osg/FrameBufferObject.cpp | 21 ++++++++++++-- 5 files changed, 73 insertions(+), 38 deletions(-) diff --git a/include/osg/FrameBufferObject b/include/osg/FrameBufferObject index 595f58ac7..6be5110f3 100644 --- a/include/osg/FrameBufferObject +++ b/include/osg/FrameBufferObject @@ -296,18 +296,24 @@ namespace osg { public: typedef std::map AttachmentMap; + typedef std::vector MultipleRenderingTargets; FrameBufferObject(); FrameBufferObject(const FrameBufferObject& copy, const CopyOp& copyop = CopyOp::SHALLOW_COPY); META_StateAttribute(osg, FrameBufferObject, (StateAttribute::Type)0x101010/*FrameBufferObject*/); - inline const AttachmentMap &getAttachmentMap() const; + inline const AttachmentMap& getAttachmentMap() const; inline bool hasAttachment(GLenum attachment_point) const; + + void setAttachment(GLenum attachment_point, const FrameBufferAttachment &attachment); inline const FrameBufferAttachment& getAttachment(GLenum attachment_point) const; - inline void setAttachment(GLenum attachment_point, const FrameBufferAttachment &attachment); + + inline bool hasMultipleRenderingTargets() const { return !_drawBuffers.empty(); } + inline const MultipleRenderingTargets& getMultipleRenderingTargets() const { return _drawBuffers; } int compare(const StateAttribute &sa) const; + void apply(State &state) const; /** Mark internal FBO for deletion. @@ -330,10 +336,15 @@ namespace osg inline void dirtyAll(); private: - AttachmentMap _attachments; - mutable buffered_value _dirtyAttachmentList; - mutable buffered_value _unsupported; - mutable buffered_value _fboID; + AttachmentMap _attachments; + + // Buffers passed to glDrawBuffers when using multiple render targets. + MultipleRenderingTargets _drawBuffers; + + mutable buffered_value _dirtyAttachmentList; + mutable buffered_value _unsupported; + mutable buffered_value _fboID; + }; // INLINE METHODS @@ -353,12 +364,6 @@ namespace osg return _attachments.find(attachment_point)->second; } - inline void FrameBufferObject::setAttachment(GLenum attachment_point, const FrameBufferAttachment &attachment) - { - _attachments[attachment_point] = attachment; - dirtyAll(); - } - inline void FrameBufferObject::dirtyAll() { _dirtyAttachmentList.setAllElementsTo(1); diff --git a/include/osgUtil/RenderStage b/include/osgUtil/RenderStage index 199c9b47e..15c0d2fad 100644 --- a/include/osgUtil/RenderStage +++ b/include/osgUtil/RenderStage @@ -226,8 +226,6 @@ class OSGUTIL_EXPORT RenderStage : public RenderBin GLenum _drawBuffer; GLenum _readBuffer; - // Buffers passed to glDrawBuffers when using multiple render targets. - std::vector _drawBuffers; GLbitfield _clearMask; osg::ref_ptr _colorMask; osg::Vec4 _clearColor; diff --git a/src/osg/FrameBufferObject.cpp b/src/osg/FrameBufferObject.cpp index 59460be8e..720b285b8 100644 --- a/src/osg/FrameBufferObject.cpp +++ b/src/osg/FrameBufferObject.cpp @@ -556,7 +556,8 @@ FrameBufferObject::FrameBufferObject() FrameBufferObject::FrameBufferObject(const FrameBufferObject ©, const CopyOp ©op) : StateAttribute(copy, copyop), - _attachments(copy._attachments) + _attachments(copy._attachments), + _drawBuffers(copy._drawBuffers) { } @@ -568,6 +569,26 @@ FrameBufferObject::~FrameBufferObject() } } +void FrameBufferObject::setAttachment(GLenum attachment_point, const FrameBufferAttachment &attachment) +{ + _attachments[attachment_point] = attachment; + + _drawBuffers.clear(); + + // create textures and mipmaps before we bind the frame buffer object + for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i) + { + const FrameBufferAttachment &fa = i->second; + + // setup draw buffers based on the attachment definition + if (i->first >= GL_COLOR_ATTACHMENT0_EXT && i->first <= GL_COLOR_ATTACHMENT15_EXT) + _drawBuffers.push_back(i->first); + } + + + dirtyAll(); +} + void FrameBufferObject::apply(State &state) const { unsigned int contextID = state.getContextID(); @@ -615,7 +636,6 @@ void FrameBufferObject::apply(State &state) const 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) { @@ -628,6 +648,16 @@ void FrameBufferObject::apply(State &state) const ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID); + // enable drawing buffers to render the result to fbo + if (_drawBuffers.size() > 0) + { + GL2Extensions *gl2e = GL2Extensions::Get(state.getContextID(), true ); + if (gl2e) + { + gl2e->glDrawBuffers(_drawBuffers.size(), &(_drawBuffers[0])); + } + } + if (dirtyAttachmentList) { for (AttachmentMap::const_iterator i=_attachments.begin(); i!=_attachments.end(); ++i) diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index 79e214785..6f8aaed9a 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -92,7 +92,6 @@ RenderStage::RenderStage(const RenderStage& rhs,const osg::CopyOp& copyop): _viewport(rhs._viewport), _drawBuffer(rhs._drawBuffer), _readBuffer(rhs._readBuffer), - _drawBuffers(rhs._drawBuffers), _clearMask(rhs._clearMask), _colorMask(rhs._colorMask), _clearColor(rhs._clearColor), @@ -332,7 +331,6 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) bool colorAttached = false; bool depthAttached = false; bool stencilAttached = false; - _drawBuffers.clear(); // MRT buffers for(osg::Camera::BufferAttachmentMap::iterator itr = bufferAttachments.begin(); itr != bufferAttachments.end(); @@ -366,9 +364,6 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) { fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT+(buffer-osg::Camera::COLOR_BUFFER0), osg::FrameBufferAttachment(attachment)); colorAttached = true; - - // append to MRT buffer list - _drawBuffers.push_back(GL_COLOR_ATTACHMENT0_EXT+(buffer-osg::Camera::COLOR_BUFFER0)); break; } } @@ -395,7 +390,6 @@ void RenderStage::runCameraSetUp(osg::RenderInfo& renderInfo) fbo_supported = false; fbo_ext->glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); fbo = 0; - _drawBuffers.clear(); // clean up. double availableTime = 100.0f; @@ -707,7 +701,10 @@ void RenderStage::drawInner(osg::RenderInfo& renderInfo,RenderLeaf*& previous, b { osg::State& state = *renderInfo.getState(); - bool using_multiple_render_targets = !(_drawBuffers.empty()); + osg::FBOExtensions* fbo_ext = _fbo.valid() ? osg::FBOExtensions::instance(state.getContextID(),true) : 0; + bool fbo_supported = fbo_ext && fbo_ext->isSupported(); + + bool using_multiple_render_targets = fbo_supported && _fbo->hasMultipleRenderingTargets(); if (!using_multiple_render_targets) { @@ -722,21 +719,9 @@ void RenderStage::drawInner(osg::RenderInfo& renderInfo,RenderLeaf*& previous, b } } - osg::FBOExtensions* fbo_ext = _fbo.valid() ? osg::FBOExtensions::instance(state.getContextID(),true) : 0; - bool fbo_supported = fbo_ext && fbo_ext->isSupported(); - if (fbo_supported) { _fbo->apply(state); - - if (using_multiple_render_targets) - { - GL2Extensions *gl2e = GL2Extensions::Get(state.getContextID(), true ); - if (gl2e) - { - gl2e->glDrawBuffers(_drawBuffers.size(), &(_drawBuffers[0])); - } - } } // do the drawing itself. @@ -774,7 +759,7 @@ void RenderStage::drawInner(osg::RenderInfo& renderInfo,RenderLeaf*& previous, b int attachment=itr->first; if (attachment==osg::Camera::DEPTH_BUFFER || attachment==osg::Camera::STENCIL_BUFFER) { // assume first buffer rendered to is the one we want - glReadBuffer(_drawBuffers[0]); + glReadBuffer(_fbo->getMultipleRenderingTargets()[0]); } else { glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + (attachment - osg::Camera::COLOR_BUFFER0)); } diff --git a/src/osgWrappers/osg/FrameBufferObject.cpp b/src/osgWrappers/osg/FrameBufferObject.cpp index 8185e177a..0cc6bbe94 100644 --- a/src/osgWrappers/osg/FrameBufferObject.cpp +++ b/src/osgWrappers/osg/FrameBufferObject.cpp @@ -159,6 +159,8 @@ END_REFLECTOR TYPE_NAME_ALIAS(std::map< GLenum COMMA osg::FrameBufferAttachment >, osg::FrameBufferObject::AttachmentMap) +TYPE_NAME_ALIAS(std::vector< GLenum >, osg::FrameBufferObject::MultipleRenderingTargets) + BEGIN_OBJECT_REFLECTOR(osg::FrameBufferObject) I_DeclaringFile("osg/FrameBufferObject"); I_BaseType(osg::StateAttribute); @@ -209,14 +211,24 @@ BEGIN_OBJECT_REFLECTOR(osg::FrameBufferObject) __bool__hasAttachment__GLenum, "", ""); + I_Method2(void, setAttachment, IN, GLenum, attachment_point, IN, const osg::FrameBufferAttachment &, attachment, + Properties::NON_VIRTUAL, + __void__setAttachment__GLenum__C5_FrameBufferAttachment_R1, + "", + ""); I_Method1(const osg::FrameBufferAttachment &, getAttachment, IN, GLenum, attachment_point, Properties::NON_VIRTUAL, __C5_FrameBufferAttachment_R1__getAttachment__GLenum, "", ""); - I_Method2(void, setAttachment, IN, GLenum, attachment_point, IN, const osg::FrameBufferAttachment &, attachment, + I_Method0(bool, hasMultipleRenderingTargets, Properties::NON_VIRTUAL, - __void__setAttachment__GLenum__C5_FrameBufferAttachment_R1, + __bool__hasMultipleRenderingTargets, + "", + ""); + I_Method0(const osg::FrameBufferObject::MultipleRenderingTargets &, getMultipleRenderingTargets, + Properties::NON_VIRTUAL, + __C5_MultipleRenderingTargets_R1__getMultipleRenderingTargets, "", ""); I_Method1(int, compare, IN, const osg::StateAttribute &, sa, @@ -254,6 +266,9 @@ BEGIN_OBJECT_REFLECTOR(osg::FrameBufferObject) I_SimpleProperty(const osg::FrameBufferObject::AttachmentMap &, AttachmentMap, __C5_AttachmentMap_R1__getAttachmentMap, 0); + I_SimpleProperty(const osg::FrameBufferObject::MultipleRenderingTargets &, MultipleRenderingTargets, + __C5_MultipleRenderingTargets_R1__getMultipleRenderingTargets, + 0); I_SimpleProperty(osg::StateAttribute::Type, Type, __Type__getType, 0); @@ -374,3 +389,5 @@ END_REFLECTOR STD_MAP_REFLECTOR(std::map< GLenum COMMA osg::FrameBufferAttachment >) +STD_VECTOR_REFLECTOR(std::vector< GLenum >) +