1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version. The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * OpenSceneGraph Public License for more details.
14// initial FBO support written by Marco Jez, June 2005.
16#ifndef OSG_FRAMEBUFFEROBJECT
17#define OSG_FRAMEBUFFEROBJECT 1
21#include <osg/buffered_value>
24#ifndef GL_EXT_framebuffer_object
25#define GL_EXT_framebuffer_object 1
26#define GL_FRAMEBUFFER_EXT 0x8D40
27#define GL_RENDERBUFFER_EXT 0x8D41
28// #define GL_STENCIL_INDEX_EXT 0x8D45 // removed in rev. #114 of the spec
29#define GL_STENCIL_INDEX1_EXT 0x8D46
30#define GL_STENCIL_INDEX4_EXT 0x8D47
31#define GL_STENCIL_INDEX8_EXT 0x8D48
32#define GL_STENCIL_INDEX16_EXT 0x8D49
33#define GL_RENDERBUFFER_WIDTH_EXT 0x8D42
34#define GL_RENDERBUFFER_HEIGHT_EXT 0x8D43
35#define GL_RENDERBUFFER_INTERNAL_FORMAT_EXT 0x8D44
36#define GL_RENDERBUFFER_RED_SIZE_EXT 0x8D50
37#define GL_RENDERBUFFER_GREEN_SIZE_EXT 0x8D51
38#define GL_RENDERBUFFER_BLUE_SIZE_EXT 0x8D52
39#define GL_RENDERBUFFER_ALPHA_SIZE_EXT 0x8D53
40#define GL_RENDERBUFFER_DEPTH_SIZE_EXT 0x8D54
41#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
42#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT 0x8CD0
43#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT 0x8CD1
44#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL_EXT 0x8CD2
45#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE_EXT 0x8CD3
46#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT 0x8CD4
47#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
48#define GL_COLOR_ATTACHMENT0_EXT 0x8CE0
49#define GL_COLOR_ATTACHMENT1_EXT 0x8CE1
50#define GL_COLOR_ATTACHMENT2_EXT 0x8CE2
51#define GL_COLOR_ATTACHMENT3_EXT 0x8CE3
52#define GL_COLOR_ATTACHMENT4_EXT 0x8CE4
53#define GL_COLOR_ATTACHMENT5_EXT 0x8CE5
54#define GL_COLOR_ATTACHMENT6_EXT 0x8CE6
55#define GL_COLOR_ATTACHMENT7_EXT 0x8CE7
56#define GL_COLOR_ATTACHMENT8_EXT 0x8CE8
57#define GL_COLOR_ATTACHMENT9_EXT 0x8CE9
58#define GL_COLOR_ATTACHMENT10_EXT 0x8CEA
59#define GL_COLOR_ATTACHMENT11_EXT 0x8CEB
60#define GL_COLOR_ATTACHMENT12_EXT 0x8CEC
61#define GL_COLOR_ATTACHMENT13_EXT 0x8CED
62#define GL_COLOR_ATTACHMENT14_EXT 0x8CEE
63#define GL_COLOR_ATTACHMENT15_EXT 0x8CEF
64#define GL_DEPTH_ATTACHMENT_EXT 0x8D00
65#define GL_STENCIL_ATTACHMENT_EXT 0x8D20
66#define GL_FRAMEBUFFER_COMPLETE_EXT 0x8CD5
67#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT 0x8CD6
68#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT 0x8CD7
69#define GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT 0x8CD8
70#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT 0x8CD9
71#define GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT 0x8CDA
72#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT 0x8CDB
73#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT 0x8CDC
74#define GL_FRAMEBUFFER_UNSUPPORTED_EXT 0x8CDD
75#define GL_FRAMEBUFFER_BINDING_EXT 0x8CA6
76#define GL_RENDERBUFFER_BINDING_EXT 0x8CA7
77#define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF
78#define GL_MAX_RENDERBUFFER_SIZE_EXT 0x84E8
79#define GL_INVALID_FRAMEBUFFER_OPERATION_EXT 0x0506
82#ifndef GL_EXT_framebuffer_blit
83#define GL_EXT_framebuffer_blit 1
84#define GL_DRAW_FRAMEBUFFER_BINDING_EXT 0x8CA6
85#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
86#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
87#define GL_READ_FRAMEBUFFER_BINDING_EXT 0x8CAA
90#ifndef GL_EXT_framebuffer_multisample
91#define GL_EXT_framebuffer_multisample 1
92#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
93#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
94#define GL_MAX_SAMPLES_EXT 0x8D57
97#ifndef GL_MAX_SAMPLES_EXT
98// Workaround for Centos 5 and other distros that define
99// GL_EXT_framebuffer_multisample but not GL_MAX_SAMPLES_EXT
100#define GL_MAX_SAMPLES_EXT 0x8D57
103#ifndef GL_NV_framebuffer_multisample_coverage
104#define GL_NV_framebuffer_multisample_coverage 1
105#define GL_RENDERBUFFER_COVERAGE_SAMPLES_NV 0x8CAB
106#define GL_RENDERBUFFER_COLOR_SAMPLES_NV 0x8E10
107#define GL_MAX_MULTISAMPLE_COVERAGE_MODES_NV 0x8E11
108#define GL_MULTISAMPLE_COVERAGE_MODES_NV 0x8E12
111#ifndef GL_EXT_packed_depth_stencil
112#define GL_EXT_packed_depth_stencil 1
113#define GL_DEPTH_STENCIL_EXT 0x84F9
114#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
115#define GL_DEPTH24_STENCIL8_EXT 0x88F0
116#define GL_TEXTURE_STENCIL_SIZE_EXT 0x88F1
122/**************************************************************************
124 **************************************************************************/
126class OSG_EXPORT RenderBuffer: public Object
130 RenderBuffer(int width, int height, GLenum internalFormat, int samples=0, int colorSamples=0);
131 RenderBuffer(const RenderBuffer& copy, const CopyOp& copyop = CopyOp::SHALLOW_COPY);
133 META_Object(osg, RenderBuffer);
135 inline int getWidth() const;
136 inline int getHeight() const;
137 inline void setWidth(int w);
138 inline void setHeight(int h);
139 inline void setSize(int w, int h);
140 inline GLenum getInternalFormat() const;
141 inline void setInternalFormat(GLenum format);
142 inline int getSamples() const;
143 inline int getColorSamples() const;
144 inline void setSamples(int samples);
145 inline void setColorSamples(int colorSamples);
147 GLuint getObjectID(unsigned int contextID, const GLExtensions *ext) const;
148 inline int compare(const RenderBuffer &rb) const;
150 static int getMaxSamples(unsigned int contextID, const GLExtensions* ext);
152 /** Resize any per context GLObject buffers to specified size. */
153 virtual void resizeGLObjectBuffers(unsigned int maxSize);
155 /** If State is non-zero, this function releases any associated OpenGL objects for
156 * the specified graphics context. Otherwise, releases OpenGL objexts
157 * for all graphics contexts. */
158 virtual void releaseGLObjects(osg::State* = 0) const;
161 virtual ~RenderBuffer();
162 RenderBuffer &operator=(const RenderBuffer &) { return *this; }
164 inline void dirtyAll() const;
167 mutable buffered_value<GLuint> _objectID;
168 mutable buffered_value<int> _dirty;
170 GLenum _internalFormat;
173 // "samples" in the framebuffer_multisample extension is equivalent to
174 // "coverageSamples" in the framebuffer_multisample_coverage extension.
181 inline int RenderBuffer::getWidth() const
186 inline int RenderBuffer::getHeight() const
191 inline void RenderBuffer::setWidth(int w)
197 inline void RenderBuffer::setHeight(int h)
203 inline void RenderBuffer::setSize(int w, int h)
210 inline GLenum RenderBuffer::getInternalFormat() const
212 return _internalFormat;
215 inline void RenderBuffer::setInternalFormat(GLenum format)
217 _internalFormat = format;
221 inline int RenderBuffer::getSamples() const
226 inline int RenderBuffer::getColorSamples() const
228 return _colorSamples;
231 inline void RenderBuffer::setSamples(int samples)
237 inline void RenderBuffer::setColorSamples(int colorSamples)
239 _colorSamples = colorSamples;
243 inline void RenderBuffer::dirtyAll() const
245 _dirty.setAllElementsTo(1);
248 inline int RenderBuffer::compare(const RenderBuffer &rb) const
250 if (&rb == this) return 0;
251 if (_internalFormat < rb._internalFormat) return -1;
252 if (_internalFormat > rb._internalFormat) return 1;
253 if (_width < rb._width) return -1;
254 if (_width > rb._width) return 1;
255 if (_height < rb._height) return -1;
256 if (_height > rb._height) return 1;
260/**************************************************************************
261 * FrameBufferAttachement
262 **************************************************************************/
265class Texture2DMultisample;
269class TextureRectangle;
271class OSG_EXPORT FrameBufferAttachment
274 FrameBufferAttachment();
275 FrameBufferAttachment(const FrameBufferAttachment& copy);
277 explicit FrameBufferAttachment(RenderBuffer* target);
278 explicit FrameBufferAttachment(Texture1D* target, unsigned int level = 0);
279 explicit FrameBufferAttachment(Texture2D* target, unsigned int level = 0);
280 explicit FrameBufferAttachment(Texture2DMultisample* target, unsigned int level = 0);
281 explicit FrameBufferAttachment(Texture3D* target, unsigned int zoffset, unsigned int level = 0);
282 explicit FrameBufferAttachment(Texture2DArray* target, unsigned int layer, unsigned int level = 0);
283 explicit FrameBufferAttachment(TextureCubeMap* target, unsigned int face, unsigned int level = 0);
284 explicit FrameBufferAttachment(TextureRectangle* target);
285 explicit FrameBufferAttachment(Camera::Attachment& attachment);
287 ~FrameBufferAttachment();
289 FrameBufferAttachment&operator = (const FrameBufferAttachment& copy);
291 bool isMultisample() const;
292 void createRequiredTexturesAndApplyGenerateMipMap(State& state, const GLExtensions* ext) const;
293 void attach(State &state, GLenum target, GLenum attachment_point, const GLExtensions* ext) const;
294 int compare(const FrameBufferAttachment &fa) const;
296 RenderBuffer* getRenderBuffer();
297 const RenderBuffer* getRenderBuffer() const;
299 Texture* getTexture();
300 const Texture* getTexture() const;
302 unsigned int getCubeMapFace() const;
303 unsigned int getTextureLevel() const;
304 unsigned int getTexture3DZOffset() const;
305 unsigned int getTextureArrayLayer() const;
307 void resizeGLObjectBuffers(unsigned int maxSize);
308 void releaseGLObjects(osg::State* = 0) const;
311 // use the Pimpl idiom to avoid dependency from
312 // all Texture* headers
317/**************************************************************************
319 **************************************************************************/
320class OSG_EXPORT FrameBufferObject: public StateAttribute
323 typedef std::map<Camera::BufferComponent, FrameBufferAttachment> AttachmentMap;
324 typedef std::vector<GLenum> MultipleRenderingTargets;
326 typedef Camera::BufferComponent BufferComponent;
329 FrameBufferObject(const FrameBufferObject& copy, const CopyOp& copyop = CopyOp::SHALLOW_COPY);
331 META_StateAttribute(osg, FrameBufferObject, FRAME_BUFFER_OBJECT);
333 inline const AttachmentMap& getAttachmentMap() const;
336 void setAttachment(BufferComponent attachment_point, const FrameBufferAttachment &attachment);
337 inline const FrameBufferAttachment& getAttachment(BufferComponent attachment_point) const;
338 inline bool hasAttachment(BufferComponent attachment_point) const;
340 inline bool hasMultipleRenderingTargets() const { return !_drawBuffers.empty(); }
341 inline const MultipleRenderingTargets& getMultipleRenderingTargets() const { return _drawBuffers; }
343 bool isMultisample() const;
345 int compare(const StateAttribute &sa) const;
347 void apply(State &state) const;
349 inline GLuint getHandle(unsigned int contextID) const
351 return _fboID[contextID];
356 READ_FRAMEBUFFER = GL_READ_FRAMEBUFFER_EXT,
357 DRAW_FRAMEBUFFER = GL_DRAW_FRAMEBUFFER_EXT,
358 READ_DRAW_FRAMEBUFFER = GL_FRAMEBUFFER_EXT
361 /** Bind the FBO as either the read or draw target, or both. */
362 void apply(State &state, BindTarget target) const;
364 /** Resize any per context GLObject buffers to specified size. */
365 virtual void resizeGLObjectBuffers(unsigned int maxSize);
367 /** If State is non-zero, this function releases any associated OpenGL objects for
368 * the specified graphics context. Otherwise, releases OpenGL objexts
369 * for all graphics contexts. */
370 virtual void releaseGLObjects(osg::State* = 0) const;
373 virtual ~FrameBufferObject();
374 FrameBufferObject& operator = (const FrameBufferObject&) { return *this; }
376 void updateDrawBuffers();
378 inline void dirtyAll();
380 GLenum convertBufferComponentToGLenum(BufferComponent attachment_point) const;
383 AttachmentMap _attachments;
385 // Buffers passed to glDrawBuffers when using multiple render targets.
386 MultipleRenderingTargets _drawBuffers;
388 mutable buffered_value<int> _dirtyAttachmentList;
389 mutable buffered_value<int> _unsupported;
390 mutable buffered_value<GLuint> _fboID;
396inline const FrameBufferObject::AttachmentMap &FrameBufferObject::getAttachmentMap() const
401inline bool FrameBufferObject::hasAttachment(FrameBufferObject::BufferComponent attachment_point) const
403 return _attachments.find(attachment_point) != _attachments.end();
406inline const FrameBufferAttachment &FrameBufferObject::getAttachment(FrameBufferObject::BufferComponent attachment_point) const
408 return _attachments.find(attachment_point)->second;
411inline void FrameBufferObject::dirtyAll()
413 _dirtyAttachmentList.setAllElementsTo(1);
416class OSG_EXPORT GLRenderBufferManager : public GLObjectManager
419 GLRenderBufferManager(unsigned int contextID);
420 virtual void deleteGLObject(GLuint globj);
423class OSG_EXPORT GLFrameBufferObjectManager : public GLObjectManager
426 GLFrameBufferObjectManager(unsigned int contextID);
427 virtual void deleteGLObject(GLuint globj);