#include <msp/gl/extensions/ext_texture3d.h>
#include <msp/gl/extensions/msp_buffer_control.h>
#include <msp/gl/extensions/khr_debug.h>
+#include <msp/strings/format.h>
#include "error.h"
#include "framebuffer.h"
#include "misc.h"
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<string, unsigned>(status, "%#x"));
- break;
- }
-}
-
-framebuffer_incomplete::framebuffer_incomplete(FramebufferStatus status):
- runtime_error(lexical_cast<string>(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)
width = 0;
height = 0;
- status = FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+ status = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
dirty = 0;
if(ARB_direct_state_access)
}
if(ARB_direct_state_access)
- status = static_cast<FramebufferStatus>(glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER));
+ status = glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER);
else
- status = static_cast<FramebufferStatus>(glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
dirty = 0;
}
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)
class Texture3D;
class WindowView;
-enum FramebufferStatus
-{
- FRAMEBUFFER_INCOMPLETE_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
- FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
- FRAMEBUFFER_INCOMPLETE_DIMENSIONS = GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT,
- FRAMEBUFFER_INCOMPLETE_FORMATS = GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT,
- FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER,
- FRAMEBUFFER_INCOMPLETE_READ_BUFFER = GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER,
- FRAMEBUFFER_INCOMPLETE_MULTISAMPLE = GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
- FRAMEBUFFER_INCOMPLETE_LAYER_COUNT = GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB,
- FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS = GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS,
- FRAMEBUFFER_UNSUPPORTED = GL_FRAMEBUFFER_UNSUPPORTED,
- FRAMEBUFFER_COMPLETE = GL_FRAMEBUFFER_COMPLETE
-};
-
enum BufferBits
{
COLOR_BUFFER_BIT = GL_COLOR_BUFFER_BIT,
class framebuffer_incomplete: public std::runtime_error
{
public:
- framebuffer_incomplete(FramebufferStatus);
+ framebuffer_incomplete(const std::string &);
virtual ~framebuffer_incomplete() throw() { }
};
std::vector<Attachment> attachments;
unsigned width;
unsigned height;
- mutable FramebufferStatus status;
+ mutable unsigned status;
mutable unsigned dirty;
Framebuffer(unsigned);
void resize(const WindowView &);
- /** Returns FRAMEBUFFER_COMPLETE if the framebuffer is complete and can be
- rendered to, or one of the error status codes otherwise. */
- FramebufferStatus get_status() const { return status; }
-
/** Ensures that the framebuffer is complete, throwing an exception if it
isn't. */
void require_complete() const;