diff options
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.patch | 114 |
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 + |