+ if(!ARB_direct_state_access && current()!=this)
+ {
+ dirty |= mask;
+ return;
+ }
+
+ std::vector<GLenum> color_bufs;
+ color_bufs.reserve(attachments.size());
+ for(unsigned i=0; i<attachments.size(); ++i)
+ {
+ const Attachment &attch = attachments[i];
+ if(mask&(1<<i))
+ {
+ if(attch.type==GL_RENDERBUFFER)
+ {
+ 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);
+ 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);
+ 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);
+ }
+
+ if(attch.attachment>=COLOR_ATTACHMENT0 && attch.attachment<=COLOR_ATTACHMENT3)
+ color_bufs.push_back(attch.attachment);
+ }
+
+ 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_draw_buffer)
+ glDrawBuffer(first_buffer);
+
+ if(MSP_draw_buffer)
+ glReadBuffer(first_buffer);
+ }
+}
+
+void Framebuffer::check_size()
+{
+ bool full_viewport = (view.left==0 && view.bottom==0 && view.width==width && view.height==height);
+ for(vector<Attachment>::iterator i=attachments.begin(); i!=attachments.end(); ++i)
+ if(i->type)
+ {
+ if(i->type==GL_RENDERBUFFER)
+ {
+ width = i->rbuf->get_width();
+ height = i->rbuf->get_height();
+ }
+ else if(i->type==GL_TEXTURE_2D)
+ {
+ Texture2D *tex = static_cast<Texture2D *>(i->tex);
+ width = tex->get_width();
+ height = tex->get_height();
+ }
+ else if(i->type==GL_TEXTURE_CUBE_MAP)
+ {
+ width = static_cast<TextureCube *>(i->tex)->get_size();
+ height = width;
+ }
+ if(full_viewport)
+ reset_viewport();
+ break;
+ }
+}
+
+unsigned Framebuffer::get_attachment_index(FramebufferAttachment attch)
+{
+ for(unsigned i=0; i<attachments.size(); ++i)
+ if(attachments[i].attachment==attch)
+ return i;
+ attachments.push_back(Attachment(attch));
+ return attachments.size()-1;