X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fframebuffer.cpp;h=3ac742bd209fd0e89c05d723c082524b4799c02c;hp=7ae391a4a18c600dfe68c7461419dcaf3928d412;hb=f14435e58bfa0fa697a06ba9a454bb30cd37d9d8;hpb=119d9819ac9e9a8d274d2410beffe54e470485a3 diff --git a/source/framebuffer.cpp b/source/framebuffer.cpp index 7ae391a4..3ac742bd 100644 --- a/source/framebuffer.cpp +++ b/source/framebuffer.cpp @@ -1,77 +1,245 @@ -/* $Id$ - -This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions -Distributed under the LGPL -*/ - #include "extension.h" +#include "ext_framebuffer_blit.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(unsigned i): + id(i), + dirty(0) +{ + if(id) + throw InvalidParameterValue("System framebuffer must have id 0"); + + int viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + width = viewport[2]; + height = viewport[3]; +} + +Framebuffer::Framebuffer(): + width(0), + height(0), + dirty(0) { static RequireExtension _ext("GL_EXT_framebuffer_object"); glGenFramebuffersEXT(1, &id); - bind(); } Framebuffer::~Framebuffer() { - glDeleteFramebuffersEXT(1, &id); + if(id) + glDeleteFramebuffersEXT(1, &id); + if(current()==this) + unbind(); } -void Framebuffer::bind() const +void Framebuffer::update_attachment(unsigned mask) const +{ + if(current()==this) + { + GLenum color_buf = GL_NONE; + for(unsigned i=0; iget_id()); + else if(attch.type==GL_TEXTURE_2D) + { + static_cast(attch.tex)->allocate(attch.level); + glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, attch.attachment, attch.type, attch.tex->get_id(), attch.level); + } + else + glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch.attachment, 0, 0); + } + + if(attch.attachment>=COLOR_ATTACHMENT0 && attch.attachment<=COLOR_ATTACHMENT3) + color_buf = attch.attachment; + } + + glDrawBuffer(color_buf); + } + else + dirty |= mask; +} + +void Framebuffer::check_size() { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); - cur_fbo=this; + for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) + if(i->type) + { + if(i->type==GL_RENDERBUFFER_EXT) + { + width = i->rbuf->get_width(); + height = i->rbuf->get_height(); + } + else if(i->type==GL_TEXTURE_2D) + { + Texture2D *tex = static_cast(i->tex); + width = tex->get_width(); + height = tex->get_height(); + } + if(current()==this) + glViewport(0, 0, width, height); + break; + } } void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf) { - maybe_bind(); - glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, attch, GL_RENDERBUFFER_EXT, rbuf.get_id()); + if(!id) + throw InvalidState("Can't attach to system framebuffer"); + + unsigned i = get_attachment_index(attch); + attachments[i].set(rbuf); + update_attachment(1<(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); } -const Framebuffer *Framebuffer::current() +void Framebuffer::clear(BufferBits bits) { - return cur_fbo; + Bind _bind(this, true); + glClear(bits); } -void Framebuffer::unbind() +void Framebuffer::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) +{ + static RequireExtension _ext("GL_EXT_framebuffer_blit"); + + const Framebuffer *old = current(); + if(set_current(this)) + { + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, id); + if(dirty) + { + update_attachment(dirty); + dirty = 0; + } + } + if(old!=&other) + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, other.id); + + glBlitFramebufferEXT(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, bits, (filter ? GL_LINEAR : GL_NEAREST)); + + set_current(old); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (old ? old->id : 0)); +} + +void Framebuffer::blit_from(const Framebuffer &other, int sx, int sy, unsigned wd, unsigned ht, int dx, int dy, BufferBits bits) +{ + blit_from(other, sx, sy, sx+wd, sy+ht, dx, dy, dx+wd, dy+ht, bits, false); +} + +void Framebuffer::blit_from(const Framebuffer &other, BufferBits bits, bool filter) { - if(cur_fbo) + blit_from(other, 0, 0, other.width, other.height, 0, 0, width, height, bits, filter); +} + +void Framebuffer::bind() const +{ + if(set_current(this)) { - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); - cur_fbo=0; + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, id); + if(dirty) + { + update_attachment(dirty); + dirty = 0; + } + if(width && height) + glViewport(0, 0, width, height); } } -void Framebuffer::maybe_bind() const +const Framebuffer *Framebuffer::current() +{ + if(!cur_obj) + cur_obj = &system(); + return cur_obj; +} + +void Framebuffer::unbind() { - if(cur_fbo!=this) - bind(); + system().bind(); } -const Framebuffer *Framebuffer::cur_fbo=0; +Framebuffer &Framebuffer::system() +{ + static Framebuffer sys_framebuf(0); + return sys_framebuf; +} + +unsigned Framebuffer::get_attachment_index(FramebufferAttachment attch) +{ + for(unsigned i=0; i