-/* $Id$
-
-This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
-Distributed under the LGPL
-*/
-
#ifndef MSP_GL_FRAMEBUFFER_H_
#define MSP_GL_FRAMEBUFFER_H_
-#include <GL/gl.h>
-#include "types.h"
+#include <vector>
+#include "bindable.h"
+#include "gl.h"
+#include "texturecube.h"
+#include <msp/gl/extensions/ext_framebuffer_object.h>
+#include <msp/gl/extensions/msp_stereo_rendering.h>
namespace Msp {
namespace GL {
class Renderbuffer;
+class Texture;
class Texture2D;
+class Texture3D;
enum FramebufferAttachment
{
- COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0_EXT,
- COLOR_ATTACHMENT1 = GL_COLOR_ATTACHMENT1_EXT,
- COLOR_ATTACHMENT2 = GL_COLOR_ATTACHMENT2_EXT,
- COLOR_ATTACHMENT3 = GL_COLOR_ATTACHMENT3_EXT,
- DEPTH_ATTACHMENT = GL_DEPTH_ATTACHMENT_EXT,
- STENCIL_ATTACHMENT = GL_STENCIL_ATTACHMENT_EXT
+ COLOR_ATTACHMENT0 = GL_COLOR_ATTACHMENT0,
+ COLOR_ATTACHMENT1 = GL_COLOR_ATTACHMENT1,
+ COLOR_ATTACHMENT2 = GL_COLOR_ATTACHMENT2,
+ COLOR_ATTACHMENT3 = GL_COLOR_ATTACHMENT3,
+ DEPTH_ATTACHMENT = GL_DEPTH_ATTACHMENT,
+ STENCIL_ATTACHMENT = GL_STENCIL_ATTACHMENT
};
enum FramebufferStatus
{
- FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT,
- FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT,
- FRAMEBUFFER_INCOMPLETE_DIMENSIONS = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT,
- FRAMEBUFFER_INCOMPLETE_FORMATS = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT,
- FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT,
- FRAMEBUFFER_INCOMPLETE_READ_BUFFER = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT,
- FRAMEBUFFER_UNSUPPORTED = GL_FRAMEBUFFER_UNSUPPORTED_EXT,
- FRAMEBUFFER_COMPLETE = GL_FRAMEBUFFER_COMPLETE_EXT
+ FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
+ FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
+ FRAMEBUFFER_INCOMPLETE_DIMENSIONS = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
+ FRAMEBUFFER_INCOMPLETE_FORMATS = GL_FRAMEBUFFER_INCOMPLETE_FORMATS,
+ FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER,
+ FRAMEBUFFER_INCOMPLETE_READ_BUFFER = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER,
+ FRAMEBUFFER_UNSUPPORTED = GL_FRAMEBUFFER_UNSUPPORTED,
+ FRAMEBUFFER_COMPLETE = GL_FRAMEBUFFER_COMPLETE
+};
+
+enum BufferBits
+{
+ COLOR_BUFFER_BIT = GL_COLOR_BUFFER_BIT,
+ DEPTH_BUFFER_BIT = GL_DEPTH_BUFFER_BIT,
+ STENCIL_BUFFER_BIT = GL_STENCIL_BUFFER_BIT
+};
+
+enum RWBuffer
+{
+ NO_BUFFER = GL_NONE,
+ FRONT_LEFT = GL_FRONT_LEFT,
+ FRONT_RIGHT = GL_FRONT_RIGHT,
+ BACK_LEFT = GL_BACK_LEFT,
+ BACK_RIGHT = GL_BACK_RIGHT,
+ FRONT = GL_FRONT,
+ BACK = GL_BACK,
+ LEFT = GL_LEFT,
+ RIGHT = GL_RIGHT,
+ FRONT_AND_BACK = GL_FRONT_AND_BACK
+};
+
+class framebuffer_incomplete: public std::runtime_error
+{
+public:
+ framebuffer_incomplete(FramebufferStatus);
+ virtual ~framebuffer_incomplete() throw() { }
};
/**
buffers. Renderbuffers and Textures can be attached to the logical buffers. At
least one image must be attached for the framebuffer to be usable.
-Requires the GL_EXT_framebuffer_object extension.
+Requires the GL_EXT_framebuffer_object extension. The blit functions require
+the GL_EXT_framebuffer_blit extension.
*/
-class Framebuffer
+class Framebuffer: public Bindable<Framebuffer>
{
private:
- uint id;
-
- static const Framebuffer *current;
-
+ struct Attachment
+ {
+ FramebufferAttachment attachment;
+ GLenum type;
+ union
+ {
+ Renderbuffer *rbuf;
+ Texture *tex;
+ };
+ unsigned level;
+ unsigned layer;
+
+ Attachment(FramebufferAttachment);
+ void set(Renderbuffer &);
+ void set(Texture &, unsigned, unsigned);
+ void clear();
+ };
+
+ struct Viewport
+ {
+ int left;
+ int bottom;
+ unsigned width;
+ unsigned height;
+
+ Viewport();
+ };
+
+ unsigned id;
+ std::vector<Attachment> attachments;
+ unsigned width;
+ unsigned height;
+ Viewport view;
+ mutable unsigned dirty;
+
+ Framebuffer(unsigned);
public:
Framebuffer();
~Framebuffer();
- void bind() const;
+ unsigned get_width() const { return width; }
+ unsigned get_height() const { return height; }
+private:
+ void update_attachment(unsigned) const;
+ void check_size();
+ unsigned get_attachment_index(FramebufferAttachment);
+public:
void attach(FramebufferAttachment attch, Renderbuffer &rbuf);
- void attach(FramebufferAttachment attch, Texture2D &tex, int level);
-
- /**
- Checks the completeness status of the framebuffer. Returns
- FRAMEBUFFER_COMPLETE if the framebuffer is complate and can be rendered to,
- or one of the error status codes otherwise.
- */
+ void attach(FramebufferAttachment attch, Texture2D &tex, unsigned level = 0);
+ void attach(FramebufferAttachment attch, Texture3D &tex, unsigned layer, unsigned level = 0);
+ void attach(FramebufferAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level = 0);
+ void detach(FramebufferAttachment attch);
+
+ /** Checks the completeness of the framebuffer. Returns
+ FRAMEBUFFER_COMPLETE if the framebuffer is complete and can be rendered to,
+ or one of the error status codes otherwise. */
FramebufferStatus check_status() const;
+ /** Ensures that the framebuffer is complete, throwing an exception if it
+ isn't. */
+ void require_complete() const;
+
+ void viewport(int, int, unsigned, unsigned);
+ void reset_viewport();
+
+ void clear(BufferBits);
+
+ /** Blits a region from another framebuffer into this one. If the source
+ and destination regions have different dimensions, the contents will be
+ stretched. If filter is true, linear interpolation will be used, otherwise
+ no interpolation is done. */
+ void blit_from(const Framebuffer &other, int sx0, int sy0, int sx1, int sy1,
+ int dx0, int dy0, int dx1, int dy1, BufferBits bits, bool filter);
+
+ /** Blits a region from another framebuffer into this one, retaining its
+ dimensions. */
+ void blit_from(const Framebuffer & other, int sx, int sy,
+ unsigned wd, unsigned ht, int dx, int dy, BufferBits bits);
+
+ /** Blits the entire contents of another framebuffer into this one. */
+ void blit_from(const Framebuffer &other, BufferBits bits, bool filter);
+
+ void bind() const;
+
+ static const Framebuffer *current();
static void unbind();
-private:
- void maybe_bind() const;
+
+ static Framebuffer &system();
};
+inline BufferBits operator|(BufferBits a, BufferBits b)
+{ return static_cast<BufferBits>(static_cast<int>(a)|static_cast<int>(b)); }
+
} // namespace GL
} // namespace Msp