meta: Save and restore the framebuffer using gl_framebuffer instead of GL API object...
authorIan Romanick <ian.d.romanick@intel.com>
Fri, 13 Nov 2015 18:51:01 +0000 (10:51 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Tue, 1 Mar 2016 19:07:19 +0000 (11:07 -0800)
Some meta operations can be called recursively.  Future changes (the
"Don't pollute the ... namespace" changes) will cause objects with
invalid names to be used.  If a nested meta operation tries to restore
an object named 0xDEADBEEF, it will fail.

This also fixes another latent bug in meta.  In a multithreaded,
multicontext application, one thread can delete an object that is bound
in another thread.  That object continues to exist until it is unbound
(i.e., its refcount drops to zero).  Meta unbinds objects all over the
place.  As a result, the rebind in _mesa_meta_end could fail because the
object vanished!

See https://bugs.freedesktop.org/show_bug.cgi?id=92363#c8.

Using _mesa_reference_<object type> to save and restore the objects
prevents the refcount from going to zero.

Signed-off-by: Ian Romanick <ian.d.romanick@intel.com>
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=92363
Reviewed-by: Topi Pohjolainen <topi.pohjolainen@intel.com>
src/mesa/drivers/common/meta.c
src/mesa/drivers/common/meta.h

index c99a2203cf205f994e5d78402d21c805469f5693..1222c9bbe73805fb738b7b24fadb99a87b196605 100644 (file)
@@ -48,6 +48,7 @@
 #include "main/feedback.h"
 #include "main/formats.h"
 #include "main/format_unpack.h"
+#include "main/framebuffer.h"
 #include "main/glformats.h"
 #include "main/image.h"
 #include "main/macros.h"
@@ -825,8 +826,8 @@ _mesa_meta_begin(struct gl_context *ctx, GLbitfield state)
       if (ctx->RasterDiscard)
          _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE);
 
-      save->DrawBufferName = ctx->DrawBuffer->Name;
-      save->ReadBufferName = ctx->ReadBuffer->Name;
+      _mesa_reference_framebuffer(&save->DrawBuffer, ctx->DrawBuffer);
+      _mesa_reference_framebuffer(&save->ReadBuffer, ctx->ReadBuffer);
    }
 }
 
@@ -1212,11 +1213,9 @@ _mesa_meta_end(struct gl_context *ctx)
    if (save->TransformFeedbackNeedsResume)
       _mesa_ResumeTransformFeedback();
 
-   if (ctx->DrawBuffer->Name != save->DrawBufferName)
-      _mesa_BindFramebuffer(GL_DRAW_FRAMEBUFFER, save->DrawBufferName);
-
-   if (ctx->ReadBuffer->Name != save->ReadBufferName)
-      _mesa_BindFramebuffer(GL_READ_FRAMEBUFFER, save->ReadBufferName);
+   _mesa_bind_framebuffers(ctx, save->DrawBuffer, save->ReadBuffer);
+   _mesa_reference_framebuffer(&save->DrawBuffer, NULL);
+   _mesa_reference_framebuffer(&save->ReadBuffer, NULL);
 
    if (state & MESA_META_DRAW_BUFFERS) {
       _mesa_drawbuffers(ctx, ctx->DrawBuffer, ctx->Const.MaxDrawBuffers,
index ee920351c357077870bdc3fd47a441980944aada..03d86c8190dd8e792d855fe713cfbda3224e09be 100644 (file)
@@ -186,7 +186,8 @@ struct save_state
    GLboolean RasterDiscard;
    GLboolean TransformFeedbackNeedsResume;
 
-   GLuint DrawBufferName, ReadBufferName;
+   struct gl_framebuffer *DrawBuffer;
+   struct gl_framebuffer *ReadBuffer;
 
    /** MESA_META_DRAW_BUFFERS */
    GLenum ColorDrawBuffers[MAX_DRAW_BUFFERS];