summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'x11-wm/mutter/files/mutter-3.16.3-fix-race.patch')
-rw-r--r--x11-wm/mutter/files/mutter-3.16.3-fix-race.patch114
1 files changed, 114 insertions, 0 deletions
diff --git a/x11-wm/mutter/files/mutter-3.16.3-fix-race.patch b/x11-wm/mutter/files/mutter-3.16.3-fix-race.patch
new file mode 100644
index 000000000000..a0b493b64f4c
--- /dev/null
+++ b/x11-wm/mutter/files/mutter-3.16.3-fix-race.patch
@@ -0,0 +1,114 @@
+From c77e482b60bea40a422691b16af02a429d9c2edc Mon Sep 17 00:00:00 2001
+From: Aaron Plattner <aplattner@nvidia.com>
+Date: Mon, 3 Aug 2015 21:15:15 -0700
+Subject: compositor: Fix GL_EXT_x11_sync_object race condition
+
+The compositor maintains a ring of shared fences with the X server in order to
+properly synchronize rendering between the X server and the compositor's GPU
+channel. When all of the fences have been used, the compositor needs to reset
+one so that it can be reused. It does this by first waiting on the CPU for the
+fence to become triggered, and then sending a request to the X server to reset
+the fence.
+
+If the compositor's GPU channel is busy processing other work (e.g. the desktop
+switcher animation), then the X server may process the reset request before the
+GPU has consumed the fence. This causes the GPU channel to hang.
+
+Fix the problem by having the compositor's GPU channel trigger its own fence
+after waiting for the X server's fence. Wait for that fence on the CPU before
+sending the reset request to the X server. This ensures that the GPU has
+consumed the X11 fence before the server resets it.
+
+Signed-off-by: Aaron Plattner <aplattner@nvidia.com>
+
+https://bugzilla.gnome.org/show_bug.cgi?id=728464
+
+diff --git a/src/compositor/meta-sync-ring.c b/src/compositor/meta-sync-ring.c
+index 4ee61f8..44b1c41 100644
+--- a/src/compositor/meta-sync-ring.c
++++ b/src/compositor/meta-sync-ring.c
+@@ -73,7 +73,8 @@ typedef struct
+ Display *xdisplay;
+
+ XSyncFence xfence;
+- GLsync glsync;
++ GLsync gl_x11_sync;
++ GLsync gpu_fence;
+
+ XSyncCounter xcounter;
+ XSyncAlarm xalarm;
+@@ -118,6 +119,8 @@ static void (*meta_gl_wait_sync) (GLsync sync,
+ static GLsync (*meta_gl_import_sync) (GLenum external_sync_type,
+ GLintptr external_sync,
+ GLbitfield flags);
++static GLsync (*meta_gl_fence_sync) (GLenum condition,
++ GLbitfield flags);
+
+ static MetaSyncRing *
+ meta_sync_ring_get (void)
+@@ -224,6 +227,8 @@ load_required_symbols (void)
+ goto out;
+ if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync))
+ goto out;
++ if (!load_gl_symbol ("glFenceSync", (void **) &meta_gl_fence_sync))
++ goto out;
+
+ success = TRUE;
+ out:
+@@ -238,7 +243,8 @@ meta_sync_insert (MetaSync *self)
+ XSyncTriggerFence (self->xdisplay, self->xfence);
+ XFlush (self->xdisplay);
+
+- meta_gl_wait_sync (self->glsync, 0, GL_TIMEOUT_IGNORED);
++ meta_gl_wait_sync (self->gl_x11_sync, 0, GL_TIMEOUT_IGNORED);
++ self->gpu_fence = meta_gl_fence_sync (GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+
+ self->state = META_SYNC_STATE_WAITING;
+ }
+@@ -255,9 +261,13 @@ meta_sync_check_update_finished (MetaSync *self,
+ status = GL_ALREADY_SIGNALED;
+ break;
+ case META_SYNC_STATE_WAITING:
+- status = meta_gl_client_wait_sync (self->glsync, 0, timeout);
++ status = meta_gl_client_wait_sync (self->gpu_fence, 0, timeout);
+ if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED)
+- self->state = META_SYNC_STATE_DONE;
++ {
++ self->state = META_SYNC_STATE_DONE;
++ meta_gl_delete_sync (self->gpu_fence);
++ self->gpu_fence = 0;
++ }
+ break;
+ default:
+ break;
+@@ -312,7 +322,8 @@ meta_sync_new (Display *xdisplay)
+ self->xdisplay = xdisplay;
+
+ self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE);
+- self->glsync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
++ self->gl_x11_sync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0);
++ self->gpu_fence = 0;
+
+ self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO);
+
+@@ -365,6 +376,8 @@ meta_sync_free (MetaSync *self)
+ switch (self->state)
+ {
+ case META_SYNC_STATE_WAITING:
++ meta_gl_delete_sync (self->gpu_fence);
++ break;
+ case META_SYNC_STATE_DONE:
+ /* nothing to do */
+ break;
+@@ -383,7 +396,7 @@ meta_sync_free (MetaSync *self)
+ break;
+ }
+
+- meta_gl_delete_sync (self->glsync);
++ meta_gl_delete_sync (self->gl_x11_sync);
+ XSyncDestroyFence (self->xdisplay, self->xfence);
+ XSyncDestroyCounter (self->xdisplay, self->xcounter);
+ XSyncDestroyAlarm (self->xdisplay, self->xalarm);
+--
+cgit v0.10.2
+