+void Framebuffer::blit_from(const Framebuffer &other, BufferBits bits, bool filter)
+{
+ 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, id);
+ if(dirty)
+ {
+ update_attachment(dirty);
+ dirty = 0;
+ }
+ if(width && height)
+ glViewport(0, 0, width, height);
+ }
+}
+
+const Framebuffer *Framebuffer::current()
+{
+ if(!cur_obj)
+ cur_obj = &system();
+ return cur_obj;
+}
+
+void Framebuffer::unbind()
+{
+ system().bind();
+}
+
+Framebuffer &Framebuffer::system()
+{
+ static Framebuffer sys_framebuf(0);
+ return sys_framebuf;
+}
+
+unsigned Framebuffer::get_attachment_index(FramebufferAttachment attch)
+{
+ for(unsigned i=0; i<attachments.size(); ++i)
+ if(attachments[i].attachment==attch)
+ return i;
+ attachments.push_back(Attachment(attch));
+ return attachments.size()-1;
+}
+
+
+Framebuffer::Attachment::Attachment(FramebufferAttachment a):
+ attachment(a),
+ type(0),
+ level(0)
+{ }
+
+void Framebuffer::Attachment::set(Renderbuffer &r)
+{
+ type = GL_RENDERBUFFER_EXT;
+ rbuf = &r;
+ level = 0;
+}
+
+void Framebuffer::Attachment::set(Texture &t, unsigned l)
+{
+ type = t.get_target();
+ tex = &t;
+ level = l;
+}
+
+void Framebuffer::Attachment::clear()
+{
+ type = 0;
+}