X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fcore%2Fframebuffer.cpp;h=45eaff656b65322a5d137133061e9e2ce35924ac;hp=1dd2f61f9bab10139772b8619075370df41b2849;hb=HEAD;hpb=ad574f042d59513eec36af64c38aaf9abe6deed2 diff --git a/source/core/framebuffer.cpp b/source/core/framebuffer.cpp index 1dd2f61f..4f30dbb1 100644 --- a/source/core/framebuffer.cpp +++ b/source/core/framebuffer.cpp @@ -1,16 +1,5 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include "error.h" #include "framebuffer.h" -#include "misc.h" #include "texture2d.h" #include "texture2dmultisample.h" #include "texture3d.h" @@ -26,152 +15,41 @@ framebuffer_incomplete::framebuffer_incomplete(const std::string &reason): { } -Framebuffer::Framebuffer(unsigned i): - id(i), - status(GL_FRAMEBUFFER_COMPLETE), - dirty(0) -{ - if(id) - throw invalid_argument("System framebuffer must have id 0"); - - int view[4]; - glGetIntegerv(GL_VIEWPORT, view); - width = view[2]; - height = view[3]; -} +Framebuffer::Framebuffer(bool s): + FramebufferBackend(s) +{ } -Framebuffer::Framebuffer() -{ - init(); -} +Framebuffer::Framebuffer(): + FramebufferBackend(false) +{ } -Framebuffer::Framebuffer(FrameAttachment fa) +Framebuffer::Framebuffer(FrameAttachment fa): + Framebuffer() { - init(); set_format(fa); } -Framebuffer::Framebuffer(const FrameFormat &f) +Framebuffer::Framebuffer(const FrameFormat &f): + Framebuffer() { - init(); set_format(f); } -void Framebuffer::init() -{ - static Require _req(EXT_framebuffer_object); - - width = 0; - height = 0; - status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; - dirty = 0; - - if(ARB_direct_state_access) - glCreateFramebuffers(1, &id); - else - glGenFramebuffers(1, &id); -} - -Framebuffer::~Framebuffer() -{ - if(id) - glDeleteFramebuffers(1, &id); -} - void Framebuffer::set_format(const FrameFormat &fmt) { if(!format.empty()) throw invalid_operation("Framebuffer::set_format"); - if(fmt.empty()) + if(fmt.empty() || !is_format_supported(fmt)) throw invalid_argument("Framebuffer::set_format"); - if(ARB_internalformat_query && ARB_internalformat_query2) - { - unsigned target = (fmt.get_samples()>1 ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D); - for(FrameAttachment a: fmt) - { - unsigned pf = get_gl_pixelformat(get_attachment_pixelformat(a)); - int supported = 0; - glGetInternalformativ(target, pf, GL_FRAMEBUFFER_RENDERABLE, 1, &supported); - if(supported!=GL_FULL_SUPPORT) - throw invalid_argument("Framebuffer::set_format"); - } - } - format = fmt; attachments.resize(format.size()); + format_changed(format); } void Framebuffer::update() const { - vector color_bufs; - color_bufs.reserve(format.size()); - unsigned i = 0; - for(FrameAttachment a: format) - { - GLenum gl_attach_point = get_gl_attachment(a); - if(dirty&(1<target==GL_TEXTURE_2D || attch.tex->target==GL_TEXTURE_2D_MULTISAMPLE || attch.layer<0) - glNamedFramebufferTexture(id, gl_attach_point, attch.tex->id, attch.level); - else - glNamedFramebufferTextureLayer(id, gl_attach_point, attch.tex->id, attch.level, attch.layer); - } - else if(attch.tex->target==GL_TEXTURE_2D || attch.tex->target==GL_TEXTURE_2D_MULTISAMPLE) - glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, attch.tex->target, attch.tex->id, attch.level); - else if(attch.layer<0) - glFramebufferTexture(GL_FRAMEBUFFER, gl_attach_point, attch.tex->id, attch.level); - else if(attch.tex->target==GL_TEXTURE_2D_ARRAY) - glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attach_point, attch.tex->id, attch.level, attch.layer); - else if(attch.tex->target==GL_TEXTURE_3D) - glFramebufferTexture3D(GL_FRAMEBUFFER, gl_attach_point, attch.tex->target, attch.tex->id, attch.level, attch.layer); - else if(attch.tex->target==GL_TEXTURE_CUBE_MAP) - glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, get_gl_cube_face(static_cast(attch.layer)), attch.tex->id, attch.level); - } - else if(ARB_direct_state_access) - glNamedFramebufferTexture(id, gl_attach_point, 0, 0); - else - glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, GL_TEXTURE_2D, 0, 0); - } - - if(gl_attach_point!=GL_DEPTH_ATTACHMENT && gl_attach_point!=GL_STENCIL_ATTACHMENT) - color_bufs.push_back(gl_attach_point); - - ++i; - } - - if(color_bufs.size()>1) - static Require _req(ARB_draw_buffers); - - GLenum first_buffer = (color_bufs.empty() ? GL_NONE : color_bufs.front()); - if(ARB_direct_state_access) - { - /* ARB_direct_state_access ties the availability of these functions to - framebuffers themselves, so no further checks are needed. */ - glNamedFramebufferDrawBuffers(id, color_bufs.size(), &color_bufs[0]); - glNamedFramebufferReadBuffer(id, first_buffer); - } - else - { - if(ARB_draw_buffers) - glDrawBuffers(color_bufs.size(), &color_bufs[0]); - else if(MSP_buffer_control) - glDrawBuffer(first_buffer); - - if(MSP_buffer_control) - glReadBuffer(first_buffer); - } - - if(ARB_direct_state_access) - status = glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER); - else - status = glCheckFramebufferStatus(GL_FRAMEBUFFER); - + FramebufferBackend::update(dirty); dirty = 0; } @@ -183,47 +61,49 @@ void Framebuffer::check_size() { unsigned w = 0; unsigned h = 0; - if(a.tex->target==GL_TEXTURE_2D) + unsigned l = 1; + if(const Texture2D *tex2d = dynamic_cast(a.tex)) { - Texture2D *tex = static_cast(a.tex); - w = max(tex->get_width()>>a.level, 1U); - h = max(tex->get_height()>>a.level, 1U); + w = max(tex2d->get_width()>>a.level, 1U); + h = max(tex2d->get_height()>>a.level, 1U); } - else if(a.tex->target==GL_TEXTURE_2D_MULTISAMPLE) + else if(const Texture2DMultisample *tex2d_ms = dynamic_cast(a.tex)) { - Texture2DMultisample *tex = static_cast(a.tex); - w = tex->get_width(); - h = tex->get_height(); + w = tex2d_ms->get_width(); + h = tex2d_ms->get_height(); } - else if(a.tex->target==GL_TEXTURE_3D || a.tex->target==GL_TEXTURE_2D_ARRAY) + else if(const Texture3D *tex3d = dynamic_cast(a.tex)) { - Texture3D *tex = static_cast(a.tex); - w = max(tex->get_width()>>a.level, 1U); - h = max(tex->get_height()>>a.level, 1U); + w = max(tex3d->get_width()>>a.level, 1U); + h = max(tex3d->get_height()>>a.level, 1U); + l = (a.layer<0 ? tex3d->get_depth() : 1); } - else if(a.tex->target==GL_TEXTURE_CUBE_MAP) + else if(const TextureCube *tex_cube = dynamic_cast(a.tex)) { - w = max(static_cast(a.tex)->get_size()>>a.level, 1U); + w = max(tex_cube->get_size()>>a.level, 1U); h = w; + l = (a.layer<0 ? 6 : 1); } if(first) { width = w; height = h; + layers = l; first = false; } else { width = min(width, w); height = min(height, h); + layers = min(layers, l); } } } -void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, unsigned level, int layer, unsigned samples) +void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, Texture *res, unsigned level, int layer, unsigned samples) { - if(format.empty() || !id) + if(format.empty() || attachments.empty()) throw invalid_operation("Framebuffer::attach"); if((format.get_samples()>1 && samples!=format.get_samples()) || (format.get_samples()==1 && samples)) @@ -234,7 +114,7 @@ void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, unsigned l { if(a==attch) { - attachments[i].set(tex, level, layer); + attachments[i].set(tex, res, level, layer); dirty |= 1<=0 ? attachments[i].tex : 0); } -void Framebuffer::require_complete() const +const Texture *Framebuffer::get_attachment(unsigned i) const +{ + return (i=0 ? attachments[i].resolve : 0); +} + +const Texture *Framebuffer::get_resolve_attachment(unsigned i) const +{ + return (i