X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fframebuffer.cpp;h=cf3761d0abb2d26d639ace3ac1a16c8ea9534cb9;hb=020811d96d5c823686e5c2b0a392b95d1a321f05;hp=97a0147d4d3e2966777f715cd537022976a44a1c;hpb=dc1d1159a61f378bda11e5989ad694a86b9a3c77;p=libs%2Fgl.git diff --git a/source/framebuffer.cpp b/source/framebuffer.cpp index 97a0147d..cf3761d0 100644 --- a/source/framebuffer.cpp +++ b/source/framebuffer.cpp @@ -8,13 +8,18 @@ Distributed under the LGPL #include "extension.h" #include "ext_framebuffer_object.h" #include "framebuffer.h" +#include "misc.h" #include "renderbuffer.h" #include "texture2d.h" +using namespace std; + namespace Msp { namespace GL { -Framebuffer::Framebuffer() +Framebuffer::Framebuffer(): + width(0), + height(0) { static RequireExtension _ext("GL_EXT_framebuffer_object"); @@ -29,44 +34,136 @@ Framebuffer::~Framebuffer() void Framebuffer::bind() const { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); - current=this; + const Framebuffer *old = current(); + if(set_current(this)) + { + if(!old) + get(GL_VIEWPORT, sys_viewport); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); + if(width && height) + viewport(0, 0, width, height); + } } void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf) { - maybe_bind(); + bind(); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, rbuf.get_id()); + get_or_create_attachment(attch) = rbuf; + check_size(); } void Framebuffer::attach(FramebufferAttachment attch, Texture2D &tex, int level) { - maybe_bind(); + bind(); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch, tex.get_target(), tex.get_id(), level); + get_or_create_attachment(attch) = tex; + check_size(); +} + +void Framebuffer::detach(FramebufferAttachment attch) +{ + bind(); + for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) + if(i->attachment==attch) + { + if(i->type==GL_RENDERBUFFER_EXT) + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, 0); + else if(i->type==GL_TEXTURE_2D) + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch, GL_TEXTURE_2D, 0, 0); + attachments.erase(i); + check_size(); + return; + } } FramebufferStatus Framebuffer::check_status() const { - maybe_bind(); + bind(); return static_cast(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); } void Framebuffer::unbind() { - if(current) + if(set_current(0)) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - current=0; + viewport(sys_viewport[0], sys_viewport[1], sys_viewport[2], sys_viewport[3]); + } +} + +Framebuffer::Attachment &Framebuffer::get_or_create_attachment(FramebufferAttachment attch) +{ + for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) + if(i->attachment==attch) + return *i; + attachments.push_back(Attachment(attch)); + return attachments.back(); +} + +void Framebuffer::check_size() +{ + if(!attachments.empty()) + { + const Attachment &attch = attachments.front(); + if(attch.type==GL_RENDERBUFFER_EXT) + { + width = attch.rbuf->get_width(); + height = attch.rbuf->get_height(); + } + else if(attch.type==GL_TEXTURE_2D) + { + Texture2D *tex = static_cast(attch.tex); + width = tex->get_width(); + height = tex->get_height(); + } + if(current()==this) + viewport(0, 0, width, height); } } -void Framebuffer::maybe_bind() const +int Framebuffer::sys_viewport[4] = { 0, 0, 1, 1 }; + + +Framebuffer::Attachment::Attachment(FramebufferAttachment a): + attachment(a), + type(0) +{ } + +Framebuffer::Attachment &Framebuffer::Attachment::operator=(Renderbuffer &r) +{ + type = GL_RENDERBUFFER_EXT; + rbuf = &r; + return *this; +} + +Framebuffer::Attachment &Framebuffer::Attachment::operator=(Texture &t) +{ + type = t.get_target(); + tex = &t; + return *this; +} + + +void viewport(int x, int y, unsigned w, unsigned h) { - if(current!=this) - bind(); + glViewport(x, y, w, h); } -const Framebuffer *Framebuffer::current=0; +void clear(BufferBits bits) +{ + glClear(bits); +} + +void draw_buffer(RWBuffer buf) +{ + glDrawBuffer(buf); +} + +void read_buffer(RWBuffer buf) +{ + glReadBuffer(buf); +} } // namespace GL } // namespace Msp