#include <msp/gl/extensions/arb_draw_buffers.h>
+#include <msp/gl/extensions/arb_direct_state_access.h>
#include <msp/gl/extensions/ext_framebuffer_blit.h>
#include <msp/gl/extensions/ext_framebuffer_object.h>
#include <msp/gl/extensions/msp_draw_buffer.h>
{
static Require _req(EXT_framebuffer_object);
- glGenFramebuffers(1, &id);
+ if(ARB_direct_state_access)
+ glCreateFramebuffers(1, &id);
+ else
+ glGenFramebuffers(1, &id);
}
Framebuffer::~Framebuffer()
void Framebuffer::update_attachment(unsigned mask) const
{
- if(current()!=this)
+ if(!ARB_direct_state_access && current()!=this)
{
dirty |= mask;
return;
if(mask&(1<<i))
{
if(attch.type==GL_RENDERBUFFER)
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, attch.attachment, GL_RENDERBUFFER, attch.rbuf->get_id());
+ {
+ if(ARB_direct_state_access)
+ glNamedFramebufferRenderbuffer(id, attch.attachment, GL_RENDERBUFFER, attch.rbuf->get_id());
+ else
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, attch.attachment, GL_RENDERBUFFER, attch.rbuf->get_id());
+ }
else if(attch.type==GL_TEXTURE_2D)
{
static_cast<Texture2D *>(attch.tex)->allocate(attch.level);
- glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, attch.type, attch.tex->get_id(), attch.level);
+ if(ARB_direct_state_access)
+ glNamedFramebufferTexture(id, attch.attachment, attch.tex->get_id(), attch.level);
+ else
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, attch.type, attch.tex->get_id(), attch.level);
}
else if(attch.type==GL_TEXTURE_CUBE_MAP)
{
static_cast<TextureCube *>(attch.tex)->allocate(attch.level);
- glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, attch.cube_face, attch.tex->get_id(), attch.level);
+ if(ARB_direct_state_access)
+ glNamedFramebufferTextureLayer(id, attch.attachment, attch.tex->get_id(), attch.level, attch.layer);
+ else
+ glFramebufferTexture2D(GL_FRAMEBUFFER, attch.attachment, TextureCube::enumerate_faces(attch.layer), attch.tex->get_id(), attch.level);
}
+ else if(ARB_direct_state_access)
+ glNamedFramebufferRenderbuffer(id, attch.attachment, 0, 0);
else
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attch.attachment, 0, 0);
}
static Require _req(ARB_draw_buffers);
GLenum first_buffer = (color_bufs.empty() ? GL_NONE : color_bufs.front());
- if(ARB_draw_buffers)
- glDrawBuffers(color_bufs.size(), &color_bufs[0]);
- else if(MSP_draw_buffer)
- glDrawBuffer(first_buffer);
+ 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_draw_buffer)
+ glDrawBuffer(first_buffer);
- if(MSP_draw_buffer)
- glReadBuffer(first_buffer);
+ if(MSP_draw_buffer)
+ glReadBuffer(first_buffer);
+ }
}
void Framebuffer::check_size()
throw invalid_operation("Framebuffer::attach");
unsigned i = get_attachment_index(attch);
- attachments[i].set(tex, 0, level);
+ attachments[i].set(tex, level, 0);
update_attachment(1<<i);
check_size();
}
throw invalid_operation("Framebuffer::attach");
unsigned i = get_attachment_index(attch);
- attachments[i].set(tex, face, level);
+ attachments[i].set(tex, level, TextureCube::get_face_index(face));
update_attachment(1<<i);
check_size();
}
FramebufferStatus Framebuffer::check_status() const
{
- BindRestore _bind(this);
- return static_cast<FramebufferStatus>(glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ if(ARB_direct_state_access)
+ return static_cast<FramebufferStatus>(glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER));
+ else
+ {
+ BindRestore _bind(this);
+ return static_cast<FramebufferStatus>(glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ }
}
void Framebuffer::require_complete() const
{
static Require _req(EXT_framebuffer_blit);
+ if(ARB_direct_state_access)
+ {
+ glBlitNamedFramebuffer(other.id, id, sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, bits, (filter ? GL_LINEAR : GL_NEAREST));
+ return;
+ }
+
const Framebuffer *old = current();
if(set_current(this))
{
Framebuffer::Attachment::Attachment(FramebufferAttachment a):
attachment(a),
type(0),
- level(0)
+ level(0),
+ layer(0)
{ }
void Framebuffer::Attachment::set(Renderbuffer &r)
type = GL_RENDERBUFFER;
rbuf = &r;
level = 0;
+ layer = 0;
}
-void Framebuffer::Attachment::set(Texture &t, GLenum f, unsigned l)
+void Framebuffer::Attachment::set(Texture &t, unsigned l, unsigned z)
{
type = t.get_target();
tex = &t;
- cube_face = f;
level = l;
+ layer = z;
}
void Framebuffer::Attachment::clear()