X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fframebuffer.cpp;h=cf3761d0abb2d26d639ace3ac1a16c8ea9534cb9;hb=6a4907898281b738111e0c6527cc46f8810dc123;hp=7ae391a4a18c600dfe68c7461419dcaf3928d412;hpb=119d9819ac9e9a8d274d2410beffe54e470485a3;p=libs%2Fgl.git diff --git a/source/framebuffer.cpp b/source/framebuffer.cpp index 7ae391a4..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,49 +34,136 @@ Framebuffer::~Framebuffer() void Framebuffer::bind() const { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); - cur_fbo=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(); } -FramebufferStatus Framebuffer::check_status() const +void Framebuffer::detach(FramebufferAttachment attch) { - maybe_bind(); - return static_cast(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); + 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; + } } -const Framebuffer *Framebuffer::current() +FramebufferStatus Framebuffer::check_status() const { - return cur_fbo; + bind(); + return static_cast(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); } void Framebuffer::unbind() { - if(cur_fbo) + if(set_current(0)) { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - cur_fbo=0; + viewport(sys_viewport[0], sys_viewport[1], sys_viewport[2], sys_viewport[3]); } } -void Framebuffer::maybe_bind() const +Framebuffer::Attachment &Framebuffer::get_or_create_attachment(FramebufferAttachment attch) { - if(cur_fbo!=this) - bind(); + for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) + if(i->attachment==attch) + return *i; + attachments.push_back(Attachment(attch)); + return attachments.back(); } -const Framebuffer *Framebuffer::cur_fbo=0; +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); + } +} + +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) +{ + glViewport(x, y, w, h); +} + +void clear(BufferBits bits) +{ + glClear(bits); +} + +void draw_buffer(RWBuffer buf) +{ + glDrawBuffer(buf); +} + +void read_buffer(RWBuffer buf) +{ + glReadBuffer(buf); +} } // namespace GL } // namespace Msp