OpenSceneGraph/include/osg/FrameBufferObject
Robert Osfield 4e69d46289 Further work on trying to get glGenerateMipMapEXT working in conjunction with
frame buffer objects.  Still don't work under Linux yet through :-|
2005-07-27 11:27:44 +00:00

344 lines
12 KiB
C++

/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2005 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 <osg/GL>
#include <osg/Texture>
#include <osg/buffered_value>
#include <osg/CameraNode>
#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_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:
typedef void APIENTRY TglBindRenderbufferEXT(GLenum, GLuint);
typedef void APIENTRY TglGenRenderbuffersEXT(GLsizei, GLuint *);
typedef void APIENTRY TglRenderbufferStorageEXT(GLenum, GLenum, GLsizei, GLsizei);
typedef void APIENTRY TglBindFramebufferEXT(GLenum, GLuint);
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 TglFramebufferRenderbufferEXT(GLenum, GLenum, GLenum, GLuint);
typedef void APIENTRY TglGenerateMipmapEXT(GLenum);
TglBindRenderbufferEXT *glBindRenderbufferEXT;
TglGenRenderbuffersEXT *glGenRenderbuffersEXT;
TglRenderbufferStorageEXT *glRenderbufferStorageEXT;
TglBindFramebufferEXT *glBindFramebufferEXT;
TglGenFramebuffersEXT *glGenFramebuffersEXT;
TglCheckFramebufferStatusEXT *glCheckFramebufferStatusEXT;
TglFramebufferTexture1DEXT *glFramebufferTexture1DEXT;
TglFramebufferTexture2DEXT *glFramebufferTexture2DEXT;
TglFramebufferTexture3DEXT *glFramebufferTexture3DEXT;
TglFramebufferRenderbufferEXT *glFramebufferRenderbufferEXT;
TglGenerateMipmapEXT *glGenerateMipmapEXT;
static FBOExtensions *instance(unsigned contextID)
{
static buffered_object<FBOExtensions *> _instances;
FBOExtensions *ext = _instances[contextID];
if (!ext)
{
ext = new FBOExtensions(contextID);
_instances[contextID] = ext;
}
return ext;
}
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;
protected:
virtual ~RenderBuffer() {}
RenderBuffer &operator=(const RenderBuffer &) { return *this; }
inline void dirtyAll() const;
private:
mutable buffered_value<GLuint> _objectID;
mutable buffered_value<int> _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 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(TextureCubeMap* target, int face, int level = 0);
explicit FrameBufferAttachment(TextureRectangle* target);
explicit FrameBufferAttachment(CameraNode::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<GLenum, FrameBufferAttachment> 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;
protected:
virtual ~FrameBufferObject() {}
FrameBufferObject &operator=(const FrameBufferObject &) { return *this; }
inline void dirtyAll();
private:
AttachmentMap _attachments;
mutable buffered_value<int> _dirtyAttachmentList;
mutable buffered_value<int> _unsupported;
mutable buffered_value<GLuint> _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