mesa/glthread: restore the dispatch table when incompatible gl calls are detected
authorGregory Hainaut <gregory.hainaut@gmail.com>
Sun, 12 Feb 2017 14:21:47 +0000 (15:21 +0100)
committerTimothy Arceri <tarceri@itsqueeze.com>
Thu, 16 Mar 2017 03:14:19 +0000 (14:14 +1100)
While a context only has a single glthread, the context itself can be
attached to several threads. Therefore the dispatch table must be
updated in all threads before the destruction of glthread. In others
words, glthread can only be destroyed safely when the context is deleted.

Fixes remaining crashes in the glx-multithread-makecurrent* tests.

V2: (Timothy Arceri) updated gl_API.dtd marshal_fail description.

Signed-off-by: Gregory Hainaut <gregory.hainaut@gmail.com>
Acked-by: Timothy Arceri <tarceri@itsqueeze.com>
Acked-by: Marek Olšák <maraeo@gmail.com>
Tested-by: Dieter Nützel <Dieter@nuetzel-hh.de>
Tested-by: Mike Lothian <mike@fireburn.co.uk>
src/mapi/glapi/gen/gl_API.dtd
src/mapi/glapi/gen/gl_marshal.py
src/mesa/main/glthread.c
src/mesa/main/glthread.h

index dc4a199bb99fddfbd44f403d57af81e80ff675e7..b464250777c08c3807836f12655a2c4ba2feefc9 100644 (file)
@@ -131,9 +131,9 @@ param:
         If "draw", it will follow the "async" rules except that "indices" are
         ignored (since they may come from a VBO).
      marshal_fail - an expression that, if it evaluates true, causes glthread
-        to finish and tear down before the Mesa implementation is called
-        directly.  Used to disable glthread for GL compatibility interactions
-        that we don't want to track state for.
+        to switch back to the Mesa implementation and call it directly.  Used
+        to disable glthread for GL compatibility interactions that we don't
+        want to track state for.
 
 glx:
      rop - Opcode value for "render" commands
index 165275904ff920d657f6b16c4db2af047033818c..d73f08b66848988373030d86a4a3ef500e8d98dd 100644 (file)
@@ -239,7 +239,8 @@ class PrintCode(gl_XML.gl_print_base):
             if func.marshal_fail:
                 out('if ({0}) {{'.format(func.marshal_fail))
                 with indent():
-                    out('_mesa_glthread_destroy(ctx);')
+                    out('_mesa_glthread_finish(ctx);')
+                    out('_mesa_glthread_restore_dispatch(ctx);')
                     self.print_sync_dispatch(func)
                     out('return;')
                 out('}')
index 8ee7d8dadac501f64020f4b0c222bc29dbdd44a8..623266f484b9642b6f1d7739d3d06c029177f883 100644 (file)
@@ -173,6 +173,12 @@ _mesa_glthread_destroy(struct gl_context *ctx)
    free(glthread);
    ctx->GLThread = NULL;
 
+   _mesa_glthread_restore_dispatch(ctx);
+}
+
+void
+_mesa_glthread_restore_dispatch(struct gl_context *ctx)
+{
    /* Remove ourselves from the dispatch table except if another ctx/thread
     * already installed a new dispatch table.
     *
index 04eb5ffabc46fcea7fef1f57f40fe014705b964a..327c549858cd061289cd502afa98fb0eaf2387f1 100644 (file)
@@ -119,6 +119,7 @@ struct glthread_batch
 void _mesa_glthread_init(struct gl_context *ctx);
 void _mesa_glthread_destroy(struct gl_context *ctx);
 
+void _mesa_glthread_restore_dispatch(struct gl_context *ctx);
 void _mesa_glthread_flush_batch(struct gl_context *ctx);
 void _mesa_glthread_finish(struct gl_context *ctx);
 
@@ -138,5 +139,11 @@ static inline void
 _mesa_glthread_finish(struct gl_context *ctx)
 {
 }
+
+static inline void
+_mesa_glthread_restore_dispatch(struct gl_context *ctx);
+{
+}
+
 #endif /* !HAVE_PTHREAD */
 #endif /* _GLTHREAD_H*/