]> git.tdb.fi Git - libs/gl.git/blobdiff - source/backends/opengl/framebuffer_backend.cpp
Rework multisample resolve to use resolve attachments
[libs/gl.git] / source / backends / opengl / framebuffer_backend.cpp
index 18566ac3c2553fd82ea1dd71ab735dc0f3cd3168..8ba947dfe1eb0528e91521fa3d853ec04a74e082 100644 (file)
@@ -43,6 +43,8 @@ OpenGLFramebuffer::~OpenGLFramebuffer()
 {
        if(id)
                glDeleteFramebuffers(1, &id);
+       if(resolve_id)
+               glDeleteFramebuffers(1, &resolve_id);
 }
 
 void OpenGLFramebuffer::set_system_format(const FrameFormat &fmt)
@@ -69,6 +71,17 @@ bool OpenGLFramebuffer::is_format_supported(const FrameFormat &fmt)
        return true;
 }
 
+void OpenGLFramebuffer::format_changed(const FrameFormat &format)
+{
+       if(format.get_samples()>1 && !resolve_id)
+       {
+               if(ARB_direct_state_access)
+                       glCreateFramebuffers(1, &resolve_id);
+               else
+                       glGenFramebuffers(1, &resolve_id);
+       }
+}
+
 void OpenGLFramebuffer::require_layered()
 {
        static Require _req(ARB_geometry_shader4);
@@ -85,6 +98,25 @@ void OpenGLFramebuffer::update(unsigned mask) const
 {
        const Framebuffer &self = *static_cast<const Framebuffer *>(this);
 
+       update(mask, false);
+       if(self.has_resolve_attachments())
+       {
+               if(!ARB_direct_state_access)
+                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_id);
+
+               update(mask, true);
+
+               if(!ARB_direct_state_access)
+                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
+       }
+}
+
+void OpenGLFramebuffer::update(unsigned mask, bool resolve) const
+{
+       const Framebuffer &self = *static_cast<const Framebuffer *>(this);
+       unsigned obj_id = (resolve ? resolve_id : id);
+       Texture *Framebuffer::Attachment::*member = (resolve ? &Framebuffer::Attachment::resolve : &Framebuffer::Attachment::tex);
+
        vector<GLenum> color_bufs;
        color_bufs.reserve(self.format.size());
        unsigned i = 0;
@@ -94,28 +126,29 @@ void OpenGLFramebuffer::update(unsigned mask) const
                if(mask&(1<<i))
                {
                        const Framebuffer::Attachment &attch = self.attachments[i];
-                       if(attch.tex)
+                       Texture *tex = attch.*member;
+                       if(tex)
                        {
                                if(ARB_direct_state_access)
                                {
-                                       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);
+                                       if(tex->target==GL_TEXTURE_2D || tex->target==GL_TEXTURE_2D_MULTISAMPLE || attch.layer<0)
+                                               glNamedFramebufferTexture(obj_id, gl_attach_point, tex->id, attch.level);
                                        else
-                                               glNamedFramebufferTextureLayer(id, gl_attach_point, attch.tex->id, attch.level, attch.layer);
+                                               glNamedFramebufferTextureLayer(obj_id, gl_attach_point, 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(tex->target==GL_TEXTURE_2D || tex->target==GL_TEXTURE_2D_MULTISAMPLE)
+                                       glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, tex->target, 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<TextureCubeFace>(attch.layer)), attch.tex->id, attch.level);
+                                       glFramebufferTexture(GL_FRAMEBUFFER, gl_attach_point, tex->id, attch.level);
+                               else if(tex->target==GL_TEXTURE_2D_ARRAY)
+                                       glFramebufferTextureLayer(GL_FRAMEBUFFER, gl_attach_point, tex->id, attch.level, attch.layer);
+                               else if(tex->target==GL_TEXTURE_3D)
+                                       glFramebufferTexture3D(GL_FRAMEBUFFER, gl_attach_point, tex->target, tex->id, attch.level, attch.layer);
+                               else if(tex->target==GL_TEXTURE_CUBE_MAP)
+                                       glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, get_gl_cube_face(static_cast<TextureCubeFace>(attch.layer)), tex->id, attch.level);
                        }
                        else if(ARB_direct_state_access)
-                               glNamedFramebufferTexture(id, gl_attach_point, 0, 0);
+                               glNamedFramebufferTexture(obj_id, gl_attach_point, 0, 0);
                        else
                                glFramebufferTexture2D(GL_FRAMEBUFFER, gl_attach_point, GL_TEXTURE_2D, 0, 0);
                }
@@ -134,8 +167,8 @@ void OpenGLFramebuffer::update(unsigned mask) const
        {
                /* 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);
+               glNamedFramebufferDrawBuffers(obj_id, color_bufs.size(), &color_bufs[0]);
+               glNamedFramebufferReadBuffer(obj_id, first_buffer);
        }
        else
        {
@@ -148,10 +181,13 @@ void OpenGLFramebuffer::update(unsigned mask) const
                        glReadBuffer(first_buffer);
        }
 
-       if(ARB_direct_state_access)
-               status = glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER);
-       else
-               status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+       if(!resolve)
+       {
+               if(ARB_direct_state_access)
+                       status = glCheckNamedFramebufferStatus(obj_id, GL_FRAMEBUFFER);
+               else
+                       status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+       }
 }
 
 void OpenGLFramebuffer::require_complete() const
@@ -168,7 +204,14 @@ void OpenGLFramebuffer::set_debug_name(const string &name)
 {
 #ifdef DEBUG
        if(KHR_debug)
+       {
                glObjectLabel(GL_FRAMEBUFFER, id, name.size(), name.c_str());
+               if(resolve_id)
+               {
+                       string resolve_name = name+" [resolve]";
+                       glObjectLabel(GL_FRAMEBUFFER, resolve_id, resolve_name.size(), resolve_name.c_str());
+               }
+       }
 #else
        (void)name;
 #endif