/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ // initial FBO support written by Marco Jez, June 2005. #ifndef OSG_FRAMEBUFFEROBJECT #define OSG_FRAMEBUFFEROBJECT 1 #include #include #include #include #ifndef GL_EXT_framebuffer_object #define GL_EXT_framebuffer_object 1 #define GL_FRAMEBUFFER_EXT 0x8D40 #define GL_RENDERBUFFER_EXT 0x8D41 #define GL_STENCIL_INDEX_EXT 0x8D45 #define GL_STENCIL_INDEX1_EXT 0x8D46 #define GL_STENCIL_INDEX4_EXT 0x8D47 #define GL_STENCIL_INDEX8_EXT 0x8D48 #define GL_STENCIL_INDEX16_EXT 0x8D49 #define GL_RENDERBUFFER_WIDTH_EXT 0x8D42 #define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43 #define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44 #define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50 #define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51 #define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52 #define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53 #define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54 #define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0 #define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4 #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 #define GL_COLOR_ATTACHMENT0_EXT 0x8CE0 #define GL_COLOR_ATTACHMENT1_EXT 0x8CE1 #define GL_COLOR_ATTACHMENT2_EXT 0x8CE2 #define GL_COLOR_ATTACHMENT3_EXT 0x8CE3 #define GL_COLOR_ATTACHMENT4_EXT 0x8CE4 #define GL_COLOR_ATTACHMENT5_EXT 0x8CE5 #define GL_COLOR_ATTACHMENT6_EXT 0x8CE6 #define GL_COLOR_ATTACHMENT7_EXT 0x8CE7 #define GL_COLOR_ATTACHMENT8_EXT 0x8CE8 #define GL_COLOR_ATTACHMENT9_EXT 0x8CE9 #define GL_COLOR_ATTACHMENT10_EXT 0x8CEA #define GL_COLOR_ATTACHMENT11_EXT 0x8CEB #define GL_COLOR_ATTACHMENT12_EXT 0x8CEC #define GL_COLOR_ATTACHMENT13_EXT 0x8CED #define GL_COLOR_ATTACHMENT14_EXT 0x8CEE #define GL_COLOR_ATTACHMENT15_EXT 0x8CEF #define GL_DEPTH_ATTACHMENT_EXT 0x8D00 #define GL_STENCIL_ATTACHMENT_EXT 0x8D20 #define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5 #define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6 #define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7 #define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8 #define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9 #define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA #define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC #define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD #define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6 #define GL_RENDERBUFFER_BINDING_EXT 0x8CA7 #define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF #define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8 #define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506 #endif #ifndef GL_VERSION_1_4 #define GL_DEPTH_COMPONENT16 0x81A5 #define GL_DEPTH_COMPONENT24 0x81A6 #define GL_DEPTH_COMPONENT32 0x81A7 #endif namespace osg { /************************************************************************** * FBOExtensions **************************************************************************/ class OSG_EXPORT FBOExtensions : public osg::Referenced { public: typedef void APIENTRY TglBindRenderbufferEXT(GLenum, GLuint); typedef void APIENTRY TglDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers); typedef void APIENTRY TglGenRenderbuffersEXT(GLsizei, GLuint *); typedef void APIENTRY TglRenderbufferStorageEXT(GLenum, GLenum, GLsizei, GLsizei); typedef void APIENTRY TglBindFramebufferEXT(GLenum, GLuint); typedef void APIENTRY TglDeleteFramebuffersEXT(GLsizei n, const GLuint *framebuffers); typedef void APIENTRY TglGenFramebuffersEXT(GLsizei, GLuint *); typedef GLenum APIENTRY TglCheckFramebufferStatusEXT(GLenum); typedef void APIENTRY TglFramebufferTexture1DEXT(GLenum, GLenum, GLenum, GLuint, GLint); typedef void APIENTRY TglFramebufferTexture2DEXT(GLenum, GLenum, GLenum, GLuint, GLint); typedef void APIENTRY TglFramebufferTexture3DEXT(GLenum, GLenum, GLenum, GLuint, GLint, GLint); typedef void APIENTRY TglFramebufferTextureLayerEXT(GLenum, GLenum, GLuint, GLint, GLint); typedef void APIENTRY TglFramebufferRenderbufferEXT(GLenum, GLenum, GLenum, GLuint); typedef void APIENTRY TglGenerateMipmapEXT(GLenum); typedef void APIENTRY TglRenderbufferStorageMultisampleCoverageNV(GLenum, GLuint, GLuint, GLenum, GLuint, GLuint); TglBindRenderbufferEXT* glBindRenderbufferEXT; TglGenRenderbuffersEXT* glGenRenderbuffersEXT; TglDeleteRenderbuffersEXT* glDeleteRenderbuffersEXT; TglRenderbufferStorageEXT* glRenderbufferStorageEXT; TglRenderbufferStorageMultisampleCoverageNV* glRenderbufferStorageMultisampleCoverageNV; TglBindFramebufferEXT* glBindFramebufferEXT; TglDeleteFramebuffersEXT* glDeleteFramebuffersEXT; TglGenFramebuffersEXT* glGenFramebuffersEXT; TglCheckFramebufferStatusEXT* glCheckFramebufferStatusEXT; TglFramebufferTexture1DEXT* glFramebufferTexture1DEXT; TglFramebufferTexture2DEXT* glFramebufferTexture2DEXT; TglFramebufferTexture3DEXT* glFramebufferTexture3DEXT; TglFramebufferTextureLayerEXT* glFramebufferTextureLayerEXT; TglFramebufferRenderbufferEXT* glFramebufferRenderbufferEXT; TglGenerateMipmapEXT* glGenerateMipmapEXT; static FBOExtensions* instance(unsigned contextID, bool createIfNotInitalized); bool isSupported() const { return _supported; } protected: FBOExtensions(unsigned int contextID); private: bool _supported; }; /************************************************************************** * RenderBuffer **************************************************************************/ class OSG_EXPORT RenderBuffer: public Object { public: RenderBuffer(); RenderBuffer(int width, int height, GLenum internalFormat); RenderBuffer(const RenderBuffer& copy, const CopyOp& copyop = CopyOp::SHALLOW_COPY); META_Object(osg, RenderBuffer); inline int getWidth() const; inline int getHeight() const; inline void setWidth(int w); inline void setHeight(int h); inline void setSize(int w, int h); inline GLenum getInternalFormat() const; inline void setInternalFormat(GLenum format); GLuint getObjectID(unsigned int contextID, const FBOExtensions *ext) const; inline int compare(const RenderBuffer &rb) const; /** Mark internal RenderBuffer for deletion. * Deletion requests are queued until they can be executed * in the proper GL context. */ static void deleteRenderBuffer(unsigned int contextID, GLuint rb); /** flush all the cached RenderBuffers which need to be deleted * in the OpenGL context related to contextID.*/ static void flushDeletedRenderBuffers(unsigned int contextID,double currentTime, double& availableTime); /** discard all the cached RenderBuffers which need to be deleted in the OpenGL context related to contextID. * Note, unlike flush no OpenGL calls are made, instead the handles are all removed. * this call is useful for when an OpenGL context has been destroyed. */ static void discardDeletedRenderBuffers(unsigned int contextID); protected: virtual ~RenderBuffer(); RenderBuffer &operator=(const RenderBuffer &) { return *this; } inline void dirtyAll() const; private: mutable buffered_value _objectID; mutable buffered_value _dirty; GLenum _internalFormat; int _width; int _height; }; // INLINE METHODS inline int RenderBuffer::getWidth() const { return _width; } inline int RenderBuffer::getHeight() const { return _height; } inline void RenderBuffer::setWidth(int w) { _width = w; dirtyAll(); } inline void RenderBuffer::setHeight(int h) { _height = h; dirtyAll(); } inline void RenderBuffer::setSize(int w, int h) { _width = w; _height = h; dirtyAll(); } inline GLenum RenderBuffer::getInternalFormat() const { return _internalFormat; } inline void RenderBuffer::setInternalFormat(GLenum format) { _internalFormat = format; dirtyAll(); } inline void RenderBuffer::dirtyAll() const { _dirty.setAllElementsTo(1); } inline int RenderBuffer::compare(const RenderBuffer &rb) const { if (&rb == this) return 0; if (_internalFormat < rb._internalFormat) return -1; if (_internalFormat > rb._internalFormat) return 1; if (_width < rb._width) return -1; if (_width > rb._width) return 1; if (_height < rb._height) return -1; if (_height > rb._height) return 1; return 0; } /************************************************************************** * FrameBufferAttachement **************************************************************************/ class Texture1D; class Texture2D; class Texture3D; class Texture2DArray; class TextureCubeMap; class TextureRectangle; class OSG_EXPORT FrameBufferAttachment { public: FrameBufferAttachment(); FrameBufferAttachment(const FrameBufferAttachment& copy); explicit FrameBufferAttachment(RenderBuffer* target); explicit FrameBufferAttachment(Texture1D* target, int level = 0); explicit FrameBufferAttachment(Texture2D* target, int level = 0); explicit FrameBufferAttachment(Texture3D* target, int zoffset, int level = 0); explicit FrameBufferAttachment(Texture2DArray* target, int layer, int level = 0); explicit FrameBufferAttachment(TextureCubeMap* target, int face, int level = 0); explicit FrameBufferAttachment(TextureRectangle* target); explicit FrameBufferAttachment(Camera::Attachment& attachment); ~FrameBufferAttachment(); FrameBufferAttachment&operator = (const FrameBufferAttachment& copy); void createRequiredTexturesAndApplyGenerateMipMap(State& state, const FBOExtensions* ext) const; void attach(State &state, GLenum attachment_point, const FBOExtensions* ext) const; int compare(const FrameBufferAttachment &fa) const; private: // use the Pimpl idiom to avoid dependency from // all Texture* headers struct Pimpl; Pimpl* _ximpl; }; /************************************************************************** * FrameBufferObject **************************************************************************/ class OSG_EXPORT FrameBufferObject: public StateAttribute { public: typedef std::map AttachmentMap; 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 bool hasAttachment(GLenum attachment_point) const; inline const FrameBufferAttachment& getAttachment(GLenum attachment_point) const; inline void setAttachment(GLenum attachment_point, const FrameBufferAttachment &attachment); int compare(const StateAttribute &sa) const; void apply(State &state) const; /** Mark internal FBO for deletion. * Deletion requests are queued until they can be executed * in the proper GL context. */ static void deleteFrameBufferObject(unsigned int contextID, GLuint program); /** flush all the cached FBOs which need to be deleted * in the OpenGL context related to contextID.*/ static void flushDeletedFrameBufferObjects(unsigned int contextID,double currentTime, double& availableTime); /** discard all the cached FBOs which need to be deleted * in the OpenGL context related to contextID.*/ static void discardDeletedFrameBufferObjects(unsigned int contextID); protected: virtual ~FrameBufferObject(); FrameBufferObject& operator = (const FrameBufferObject&) { return *this; } inline void dirtyAll(); private: AttachmentMap _attachments; mutable buffered_value _dirtyAttachmentList; mutable buffered_value _unsupported; mutable buffered_value _fboID; }; // INLINE METHODS inline const FrameBufferObject::AttachmentMap &FrameBufferObject::getAttachmentMap() const { return _attachments; } inline bool FrameBufferObject::hasAttachment(GLenum attachment_point) const { return _attachments.find(attachment_point) != _attachments.end(); } inline const FrameBufferAttachment &FrameBufferObject::getAttachment(GLenum attachment_point) const { 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); } } #endif