X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fcore%2Fframebuffer.cpp;h=01a4107494387cac61ce8c46e90dd7234e07d5b4;hb=d6122b75b00c0889a54536b5cea971d08184af8f;hp=851b6431b2fb134d470b1116262411af471532be;hpb=a4d83d3748cdde8cf30683d36a040d3dfacfd693;p=libs%2Fgl.git diff --git a/source/core/framebuffer.cpp b/source/core/framebuffer.cpp index 851b6431..01a41074 100644 --- a/source/core/framebuffer.cpp +++ b/source/core/framebuffer.cpp @@ -1,10 +1,13 @@ #include #include +#include +#include #include #include #include #include #include +#include #include "error.h" #include "framebuffer.h" #include "misc.h" @@ -18,59 +21,37 @@ using namespace std; namespace Msp { namespace GL { -void operator<<(LexicalConverter &conv, FramebufferStatus status) -{ - switch(status) - { - case FRAMEBUFFER_INCOMPLETE_ATTACHMENT: - conv.result("incomplete attachment"); - break; - case FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: - conv.result("missing attachment"); - break; - case FRAMEBUFFER_INCOMPLETE_DIMENSIONS: - conv.result("mismatched attachment dimensions"); - break; - case FRAMEBUFFER_INCOMPLETE_FORMATS: - conv.result("mismatched attachment formats"); - break; - case FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: - conv.result("missing draw buffer attachment"); - break; - case FRAMEBUFFER_INCOMPLETE_READ_BUFFER: - conv.result("missing read buffer attachment"); - break; - case FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: - conv.result("mismatched attachment sample counts"); - break; - case FRAMEBUFFER_INCOMPLETE_LAYER_COUNT: - conv.result("mismatched attachment layer counts"); - break; - case FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS: - conv.result("mismatched attachment layering"); - break; - case FRAMEBUFFER_UNSUPPORTED: - conv.result("unsupported"); - break; - default: - conv.result(lexical_cast(status, "%#x")); - break; - } -} - -framebuffer_incomplete::framebuffer_incomplete(FramebufferStatus status): - runtime_error(lexical_cast(status)) +framebuffer_incomplete::framebuffer_incomplete(const std::string &reason): + runtime_error(reason) { } Framebuffer::Framebuffer(unsigned i): id(i), - status(FRAMEBUFFER_COMPLETE), + status(GL_FRAMEBUFFER_COMPLETE), dirty(0) { if(id) throw invalid_argument("System framebuffer must have id 0"); + if(EXT_framebuffer_object) + { + int value; + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_BACK, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &value); + if(value==GL_NONE) + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_FRONT, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &value); + if(value!=GL_NONE) + format = (format,COLOR_ATTACHMENT); + + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &value); + if(value!=GL_NONE) + format = (format,DEPTH_ATTACHMENT); + + glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_STENCIL, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &value); + if(value!=GL_NONE) + format = (format,STENCIL_ATTACHMENT); + } + int view[4]; glGetIntegerv(GL_VIEWPORT, view); width = view[2]; @@ -100,7 +81,7 @@ void Framebuffer::init() width = 0; height = 0; - status = FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; + status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; dirty = 0; if(ARB_direct_state_access) @@ -117,11 +98,24 @@ Framebuffer::~Framebuffer() void Framebuffer::set_format(const FrameFormat &fmt) { - if(!format.empty()) + if(!format.empty() || !id) throw invalid_operation("Framebuffer::set_format"); if(fmt.empty()) 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()); } @@ -139,24 +133,23 @@ void Framebuffer::update() const const Attachment &attch = attachments[i]; if(attch.tex) { - GLenum type = attch.tex->get_target(); if(ARB_direct_state_access) { - if(type==GL_TEXTURE_2D || type==GL_TEXTURE_2D_MULTISAMPLE || attch.layer<0) - glNamedFramebufferTexture(id, gl_attach_point, attch.tex->get_id(), attch.level); + if(attch.tex->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->get_id(), attch.level, attch.layer); + glNamedFramebufferTextureLayer(id, gl_attach_point, attch.tex->id, attch.level, attch.layer); } - 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.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->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); + 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); @@ -193,9 +186,9 @@ void Framebuffer::update() const } if(ARB_direct_state_access) - status = static_cast(glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER)); + status = glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER); else - status = static_cast(glCheckFramebufferStatus(GL_FRAMEBUFFER)); + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); dirty = 0; } @@ -206,28 +199,27 @@ void Framebuffer::check_size() for(Attachment &a: attachments) if(a.tex) { - GLenum type = a.tex->get_target(); unsigned w = 0; unsigned h = 0; - if(type==GL_TEXTURE_2D) + if(a.tex->target==GL_TEXTURE_2D) { Texture2D *tex = static_cast(a.tex); w = max(tex->get_width()>>a.level, 1U); h = max(tex->get_height()>>a.level, 1U); } - else if(type==GL_TEXTURE_2D_MULTISAMPLE) + else if(a.tex->target==GL_TEXTURE_2D_MULTISAMPLE) { Texture2DMultisample *tex = static_cast(a.tex); w = tex->get_width(); h = tex->get_height(); } - else if(type==GL_TEXTURE_3D || type==GL_TEXTURE_2D_ARRAY) + else if(a.tex->target==GL_TEXTURE_3D || a.tex->target==GL_TEXTURE_2D_ARRAY) { Texture3D *tex = static_cast(a.tex); w = max(tex->get_width()>>a.level, 1U); h = max(tex->get_height()>>a.level, 1U); } - else if(type==GL_TEXTURE_CUBE_MAP) + else if(a.tex->target==GL_TEXTURE_CUBE_MAP) { w = max(static_cast(a.tex)->get_size()>>a.level, 1U); h = w; @@ -273,7 +265,6 @@ void Framebuffer::set_attachment(FrameAttachment attch, Texture &tex, unsigned l void Framebuffer::attach(FrameAttachment attch, Texture2D &tex, unsigned level) { - tex.allocate(level); set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, 0, 0); } @@ -284,27 +275,23 @@ void Framebuffer::attach(FrameAttachment attch, Texture2DMultisample &tex) void Framebuffer::attach(FrameAttachment attch, Texture3D &tex, unsigned layer, unsigned level) { - tex.allocate(level); set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, layer, 0); } void Framebuffer::attach(FrameAttachment attch, TextureCube &tex, TextureCubeFace face, unsigned level) { - tex.allocate(level); - set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, TextureCube::get_face_index(face), 0); + set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, face, 0); } void Framebuffer::attach_layered(FrameAttachment attch, Texture3D &tex, unsigned level) { static Require _req(ARB_geometry_shader4); - tex.allocate(level); set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0); } void Framebuffer::attach_layered(FrameAttachment attch, TextureCube &tex, unsigned level) { static Require _req(ARB_geometry_shader4); - tex.allocate(level); set_attachment(make_typed_attachment(attch, tex.get_format()), tex, level, -1, 0); } @@ -333,8 +320,24 @@ void Framebuffer::resize(const WindowView &view) void Framebuffer::require_complete() const { - if(status!=FRAMEBUFFER_COMPLETE) - throw framebuffer_incomplete(status); + if(!id) + return; + + bool layered = (!attachments.empty() && attachments.front().layer<0); + for(const Attachment &a: attachments) + { + if(!a.tex) + throw framebuffer_incomplete("missing attachment"); + if(layered!=(a.layer<0)) + throw framebuffer_incomplete("inconsistent layering"); + } + + if(status==GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT) + throw framebuffer_incomplete("incomplete or unsupported attachment"); + if(status==GL_FRAMEBUFFER_UNSUPPORTED) + throw framebuffer_incomplete("unsupported configuration"); + if(status!=GL_FRAMEBUFFER_COMPLETE) + throw framebuffer_incomplete(Msp::format("incomplete (%#x)", status)); } void Framebuffer::set_debug_name(const string &name)