X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fcore%2Fframebuffer.cpp;h=e9d8863ca16e4e0379a11e9777def136cb596d2e;hp=4dbb30929e05dc38ff822c981b51e251613f61bb;hb=3a1b9cbe2441ae670a97541dc8ccb0a2860c8302;hpb=ce3658993ce2f6b7527a04a36a5e1af349c6f2e9 diff --git a/source/core/framebuffer.cpp b/source/core/framebuffer.cpp index 4dbb3092..e9d8863c 100644 --- a/source/core/framebuffer.cpp +++ b/source/core/framebuffer.cpp @@ -8,8 +8,8 @@ #include "error.h" #include "framebuffer.h" #include "misc.h" -#include "renderbuffer.h" #include "texture2d.h" +#include "texture2dmultisample.h" #include "texture3d.h" #include "windowview.h" @@ -77,14 +77,32 @@ Framebuffer::Framebuffer(unsigned i): height = view[3]; } -Framebuffer::Framebuffer(): - width(0), - height(0), - status(FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT), - dirty(0) +Framebuffer::Framebuffer() +{ + init(); +} + +Framebuffer::Framebuffer(FrameAttachment fa) +{ + init(); + set_format(fa); +} + +Framebuffer::Framebuffer(const FrameFormat &f) +{ + init(); + set_format(f); +} + +void Framebuffer::init() { static Require _req(EXT_framebuffer_object); + width = 0; + height = 0; + status = FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; + dirty = 0; + if(ARB_direct_state_access) glCreateFramebuffers(1, &id); else @@ -97,50 +115,57 @@ Framebuffer::~Framebuffer() glDeleteFramebuffers(1, &id); } +void Framebuffer::set_format(const FrameFormat &fmt) +{ + if(!format.empty()) + throw invalid_operation("Framebuffer::set_format"); + if(fmt.empty()) + throw invalid_argument("Framebuffer::set_format"); + + format = fmt; + attachments.resize(format.size()); +} + void Framebuffer::update() const { vector color_bufs; - color_bufs.reserve(attachments.size()); - for(unsigned i=0; i(*j)); if(dirty&(1<get_id()); - else - glFramebufferRenderbuffer(GL_FRAMEBUFFER, attch.attachment, GL_RENDERBUFFER, attch.rbuf->get_id()); - } - else if(attch.type) + const Attachment &attch = attachments[i]; + if(attch.tex) { + GLenum type = attch.tex->get_target(); if(ARB_direct_state_access) { - if(attch.type==GL_TEXTURE_2D || attch.layer<0) - glNamedFramebufferTexture(id, attch.attachment, attch.tex->get_id(), attch.level); + if(type==GL_TEXTURE_2D || type==GL_TEXTURE_2D_MULTISAMPLE || attch.layer<0) + glNamedFramebufferTexture(id, gl_attach_point, attch.tex->get_id(), attch.level); else - glNamedFramebufferTextureLayer(id, attch.attachment, attch.tex->get_id(), attch.level, attch.layer); + glNamedFramebufferTextureLayer(id, gl_attach_point, attch.tex->get_id(), attch.level, attch.layer); } - else if(attch.type==GL_TEXTURE_2D) - glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, attch.type, attch.tex->get_id(), attch.level); + else if(type==GL_TEXTURE_2D || type==GL_TEXTURE_2D_MULTISAMPLE) + glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, type, attch.tex->get_id(), attch.level); else if(attch.layer<0) - glFramebufferTexture(GL_FRAMEBUFFER, attch.attachment, attch.tex->get_id(), attch.level); - else if(attch.type==GL_TEXTURE_2D_ARRAY) - glFramebufferTextureLayer(GL_FRAMEBUFFER, attch.attachment, attch.tex->get_id(), attch.level, attch.layer); - else if(attch.type==GL_TEXTURE_3D) - glFramebufferTexture3D(GL_FRAMEBUFFER, attch.attachment, attch.type, attch.tex->get_id(), attch.level, attch.layer); - else if(attch.type==GL_TEXTURE_CUBE_MAP) - glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, TextureCube::enumerate_faces(attch.layer), attch.tex->get_id(), attch.level); + glFramebufferTexture(GL_FRAMEBUFFER, gl_attach_point, attch.tex->get_id(), attch.level); + else if(type==GL_TEXTURE_2D_ARRAY) + glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attach_point, attch.tex->get_id(), attch.level, attch.layer); + else if(type==GL_TEXTURE_3D) + glFramebufferTexture3D(GL_FRAMEBUFFER, gl_attach_point, type, attch.tex->get_id(), attch.level, attch.layer); + else if(type==GL_TEXTURE_CUBE_MAP) + glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, TextureCube::enumerate_faces(attch.layer), attch.tex->get_id(), attch.level); } else if(ARB_direct_state_access) - glNamedFramebufferRenderbuffer(id, attch.attachment, 0, 0); + glNamedFramebufferTexture(id, gl_attach_point, 0, 0); else - glFramebufferRenderbuffer(GL_FRAMEBUFFER, attch.attachment, 0, 0); + glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, GL_TEXTURE_2D, 0, 0); } - if(attch.attachment>=COLOR_ATTACHMENT0 && attch.attachment<=COLOR_ATTACHMENT3) - color_bufs.push_back(attch.attachment); + if(gl_attach_point!=GL_DEPTH_ATTACHMENT && gl_attach_point!=GL_STENCIL_ATTACHMENT) + color_bufs.push_back(gl_attach_point); } if(color_bufs.size()>1) @@ -175,107 +200,121 @@ void Framebuffer::update() const void Framebuffer::check_size() { - for(vector::iterator i=attachments.begin(); i!=attachments.end(); ++i) - if(i->type) + bool first = true; + for(Attachment &a: attachments) + if(a.tex) { - if(i->type==GL_RENDERBUFFER) + GLenum type = a.tex->get_target(); + unsigned w = 0; + unsigned h = 0; + if(type==GL_TEXTURE_2D) { - width = i->rbuf->get_width(); - height = i->rbuf->get_height(); + Texture2D *tex = static_cast(a.tex); + w = max(tex->get_width()>>a.level, 1U); + h = max(tex->get_height()>>a.level, 1U); } - else if(i->type==GL_TEXTURE_2D) + else if(type==GL_TEXTURE_2D_MULTISAMPLE) { - Texture2D *tex = static_cast(i->tex); - width = max(tex->get_width()>>i->level, 1U); - height = max(tex->get_height()>>i->level, 1U); + Texture2DMultisample *tex = static_cast(a.tex); + w = tex->get_width(); + h = tex->get_height(); } - else if(i->type==GL_TEXTURE_3D || i->type==GL_TEXTURE_2D_ARRAY) + else if(type==GL_TEXTURE_3D || type==GL_TEXTURE_2D_ARRAY) { - Texture3D *tex = static_cast(i->tex); - width = max(tex->get_width()>>i->level, 1U); - height = max(tex->get_height()>>i->level, 1U); + Texture3D *tex = static_cast(a.tex); + w = max(tex->get_width()>>a.level, 1U); + h = max(tex->get_height()>>a.level, 1U); } - else if(i->type==GL_TEXTURE_CUBE_MAP) + else if(type==GL_TEXTURE_CUBE_MAP) { - width = max(static_cast(i->tex)->get_size()>>i->level, 1U); - height = width; + w = max(static_cast(a.tex)->get_size()>>a.level, 1U); + h = w; } - break; - } -} -unsigned Framebuffer::get_attachment_index(FramebufferAttachment attch) -{ - for(unsigned i=0; i1 && samples!=format.get_samples()) || (format.get_samples()==1 && samples)) + throw incompatible_data("Framebuffer::attach"); -void Framebuffer::attach(FramebufferAttachment attch, Renderbuffer &rbuf) -{ - if(!id) - throw invalid_operation("Framebuffer::attach"); + unsigned i = 0; + for(const uint16_t *j=format.begin(); j!=format.end(); ++j, ++i) + if(*j==attch) + { + attachments[i].set(tex, level, layer); + dirty |= 1<=0) + { + attachments[i].clear(); + dirty |= 1<