diff options
Diffstat (limited to 'x11-wm')
-rw-r--r-- | x11-wm/mutter/files/mutter-3.16.3-GL_EXT_x11_sync_object.patch | 840 | ||||
-rw-r--r-- | x11-wm/mutter/files/mutter-3.16.3-crash-border.patch | 32 | ||||
-rw-r--r-- | x11-wm/mutter/files/mutter-3.16.3-fallback-keymap.patch | 28 | ||||
-rw-r--r-- | x11-wm/mutter/files/mutter-3.16.3-fix-race.patch | 114 | ||||
-rw-r--r-- | x11-wm/mutter/files/mutter-3.16.3-fix-return.patch | 32 | ||||
-rw-r--r-- | x11-wm/mutter/files/mutter-3.16.3-flickering.patch | 114 | ||||
-rw-r--r-- | x11-wm/mutter/mutter-3.16.3-r1.ebuild | 114 |
7 files changed, 1274 insertions, 0 deletions
diff --git a/x11-wm/mutter/files/mutter-3.16.3-GL_EXT_x11_sync_object.patch b/x11-wm/mutter/files/mutter-3.16.3-GL_EXT_x11_sync_object.patch new file mode 100644 index 000000000000..401c1752bd8b --- /dev/null +++ b/x11-wm/mutter/files/mutter-3.16.3-GL_EXT_x11_sync_object.patch @@ -0,0 +1,840 @@ +From 9cc80497a262edafc58062fd860ef7a9dcab688c Mon Sep 17 00:00:00 2001 +From: Rui Matos <tiagomatos@gmail.com> +Date: Fri, 18 Apr 2014 20:21:20 +0200 +Subject: compositor: Add support for GL_EXT_x11_sync_object + +If GL advertises this extension we'll use it to synchronize X with GL +rendering instead of relying on the XSync() behavior with open source +drivers. + +Some driver bugs were uncovered while working on this so if we have +had to reboot the ring a few times, something is probably wrong and +we're likely to just make things worse by continuing to try. Let's +err on the side of caution, disable ourselves and fallback to the +XSync() path in the compositor. + +https://bugzilla.gnome.org/show_bug.cgi?id=728464 + +diff --git a/configure.ac b/configure.ac +index 01d75cb..6eea6b2 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -332,6 +332,11 @@ fi + + GTK_DOC_CHECK([1.15], [--flavour no-tmpl]) + ++AC_CHECK_DECL([GL_EXT_x11_sync_object], ++ [], ++ [AC_MSG_ERROR([GL_EXT_x11_sync_object definition not found, please update your GL headers])], ++ [#include <GL/glx.h>]) ++ + #### Warnings (last since -Werror can disturb other tests) + + # Stay command-line compatible with the gnome-common configure option. Here +diff --git a/src/Makefile.am b/src/Makefile.am +index baadb41..a4e07a9 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -139,6 +139,8 @@ libmutter_la_SOURCES = \ + compositor/meta-surface-actor.h \ + compositor/meta-surface-actor-x11.c \ + compositor/meta-surface-actor-x11.h \ ++ compositor/meta-sync-ring.c \ ++ compositor/meta-sync-ring.h \ + compositor/meta-texture-rectangle.c \ + compositor/meta-texture-rectangle.h \ + compositor/meta-texture-tower.c \ +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index 3ff8431..ac38ffc 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -45,6 +45,7 @@ + #include <meta/util.h> + #include "display-private.h" + #include "compositor/compositor-private.h" ++#include "compositor/meta-sync-ring.h" + + struct _MetaBackendX11Private + { +@@ -255,6 +256,8 @@ handle_host_xevent (MetaBackend *backend, + MetaCompositor *compositor = display->compositor; + if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event)) + bypass_clutter = TRUE; ++ if (compositor->have_x11_sync_object) ++ meta_sync_ring_handle_event (event); + } + } + +diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h +index 80fb4e2..9e3e73d 100644 +--- a/src/compositor/compositor-private.h ++++ b/src/compositor/compositor-private.h +@@ -15,7 +15,8 @@ struct _MetaCompositor + { + MetaDisplay *display; + +- guint repaint_func_id; ++ guint pre_paint_func_id; ++ guint post_paint_func_id; + + gint64 server_time_query_time; + gint64 server_time_offset; +@@ -40,6 +41,7 @@ struct _MetaCompositor + MetaPluginManager *plugin_mgr; + + gboolean frame_has_updated_xsurfaces; ++ gboolean have_x11_sync_object; + }; + + /* Wait 2ms after vblank before starting to draw next frame */ +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index 250d489..554faa1 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -79,6 +79,7 @@ + #include "frame.h" + #include <X11/extensions/shape.h> + #include <X11/extensions/Xcomposite.h> ++#include "meta-sync-ring.h" + + #include "backends/x11/meta-backend-x11.h" + +@@ -125,7 +126,11 @@ meta_switch_workspace_completed (MetaCompositor *compositor) + void + meta_compositor_destroy (MetaCompositor *compositor) + { +- clutter_threads_remove_repaint_func (compositor->repaint_func_id); ++ clutter_threads_remove_repaint_func (compositor->pre_paint_func_id); ++ clutter_threads_remove_repaint_func (compositor->post_paint_func_id); ++ ++ if (compositor->have_x11_sync_object) ++ meta_sync_ring_destroy (); + } + + static void +@@ -468,13 +473,11 @@ meta_compositor_manage (MetaCompositor *compositor) + MetaDisplay *display = compositor->display; + Display *xdisplay = display->xdisplay; + MetaScreen *screen = display->screen; ++ MetaBackend *backend = meta_get_backend (); + + meta_screen_set_cm_selection (display->screen); + +- { +- MetaBackend *backend = meta_get_backend (); +- compositor->stage = meta_backend_get_stage (backend); +- } ++ compositor->stage = meta_backend_get_stage (backend); + + /* We use connect_after() here to accomodate code in GNOME Shell that, + * when benchmarking drawing performance, connects to ::after-paint +@@ -510,7 +513,7 @@ meta_compositor_manage (MetaCompositor *compositor) + + compositor->output = screen->composite_overlay_window; + +- xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (meta_get_backend ())); ++ xwin = meta_backend_x11_get_xwindow (META_BACKEND_X11 (backend)); + + XReparentWindow (xdisplay, xwin, compositor->output, 0, 0); + +@@ -530,6 +533,9 @@ meta_compositor_manage (MetaCompositor *compositor) + * contents until we show the stage. + */ + XMapWindow (xdisplay, compositor->output); ++ ++ compositor->have_x11_sync_object = ++ meta_sync_ring_init (meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend))); + } + + redirect_windows (display->screen); +@@ -1044,11 +1050,12 @@ frame_callback (CoglOnscreen *onscreen, + } + } + +-static void +-pre_paint_windows (MetaCompositor *compositor) ++static gboolean ++meta_pre_paint_func (gpointer data) + { + GList *l; + MetaWindowActor *top_window; ++ MetaCompositor *compositor = data; + + if (compositor->onscreen == NULL) + { +@@ -1060,7 +1067,7 @@ pre_paint_windows (MetaCompositor *compositor) + } + + if (compositor->windows == NULL) +- return; ++ return TRUE; + + top_window = g_list_last (compositor->windows)->data; + +@@ -1077,10 +1084,12 @@ pre_paint_windows (MetaCompositor *compositor) + { + /* We need to make sure that any X drawing that happens before + * the XDamageSubtract() for each window above is visible to +- * subsequent GL rendering; the only standardized way to do this +- * is EXT_x11_sync_object, which isn't yet widely available. For +- * now, we count on details of Xorg and the open source drivers, +- * and hope for the best otherwise. ++ * subsequent GL rendering; the standardized way to do this is ++ * GL_EXT_X11_sync_object. Since this isn't implemented yet in ++ * mesa, we also have a path that relies on the implementation ++ * of the open source drivers. ++ * ++ * Anything else, we just hope for the best. + * + * Xorg and open source driver specifics: + * +@@ -1095,17 +1104,28 @@ pre_paint_windows (MetaCompositor *compositor) + * round trip request at this point is sufficient to flush the + * GLX buffers. + */ +- XSync (compositor->display->xdisplay, False); +- +- compositor->frame_has_updated_xsurfaces = FALSE; ++ if (compositor->have_x11_sync_object) ++ compositor->have_x11_sync_object = meta_sync_ring_insert_wait (); ++ else ++ XSync (compositor->display->xdisplay, False); + } ++ ++ return TRUE; + } + + static gboolean +-meta_repaint_func (gpointer data) ++meta_post_paint_func (gpointer data) + { + MetaCompositor *compositor = data; +- pre_paint_windows (compositor); ++ ++ if (compositor->frame_has_updated_xsurfaces) ++ { ++ if (compositor->have_x11_sync_object) ++ compositor->have_x11_sync_object = meta_sync_ring_after_frame (); ++ ++ compositor->frame_has_updated_xsurfaces = FALSE; ++ } ++ + return TRUE; + } + +@@ -1140,10 +1160,16 @@ meta_compositor_new (MetaDisplay *display) + G_CALLBACK (on_shadow_factory_changed), + compositor); + +- compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func, +- compositor, +- NULL); +- ++ compositor->pre_paint_func_id = ++ clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_PRE_PAINT, ++ meta_pre_paint_func, ++ compositor, ++ NULL); ++ compositor->post_paint_func_id = ++ clutter_threads_add_repaint_func_full (CLUTTER_REPAINT_FLAGS_POST_PAINT, ++ meta_post_paint_func, ++ compositor, ++ NULL); + return compositor; + } + +diff --git a/src/compositor/meta-sync-ring.c b/src/compositor/meta-sync-ring.c +new file mode 100644 +index 0000000..4ee61f8 +--- /dev/null ++++ b/src/compositor/meta-sync-ring.c +@@ -0,0 +1,566 @@ ++/* ++ * This is based on an original C++ implementation for compiz that ++ * carries the following copyright notice: ++ * ++ * ++ * Copyright © 2011 NVIDIA Corporation ++ * ++ * Permission to use, copy, modify, distribute, and sell this software ++ * and its documentation for any purpose is hereby granted without ++ * fee, provided that the above copyright notice appear in all copies ++ * and that both that copyright notice and this permission notice ++ * appear in supporting documentation, and that the name of NVIDIA ++ * Corporation not be used in advertising or publicity pertaining to ++ * distribution of the software without specific, written prior ++ * permission. NVIDIA Corporation makes no representations about the ++ * suitability of this software for any purpose. It is provided "as ++ * is" without express or implied warranty. ++ * ++ * NVIDIA CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS ++ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND ++ * FITNESS, IN NO EVENT SHALL NVIDIA CORPORATION BE LIABLE FOR ANY ++ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN ++ * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING ++ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ++ * SOFTWARE. ++ * ++ * Authors: James Jones <jajones@nvidia.com> ++ */ ++ ++#include <string.h> ++ ++#include <GL/gl.h> ++#include <GL/glx.h> ++#include <X11/extensions/sync.h> ++ ++#include <cogl/cogl.h> ++#include <clutter/clutter.h> ++ ++#include <meta/util.h> ++ ++#include "meta-sync-ring.h" ++ ++/* Theory of operation: ++ * ++ * We use a ring of NUM_SYNCS fence objects. On each frame we advance ++ * to the next fence in the ring. For each fence we do: ++ * ++ * 1. fence is XSyncTriggerFence()'d and glWaitSync()'d ++ * 2. NUM_SYNCS / 2 frames later, fence should be triggered ++ * 3. fence is XSyncResetFence()'d ++ * 4. NUM_SYNCS / 2 frames later, fence should be reset ++ * 5. go back to 1 and re-use fence ++ * ++ * glClientWaitSync() and XAlarms are used in steps 2 and 4, ++ * respectively, to double-check the expectections. ++ */ ++ ++#define NUM_SYNCS 10 ++#define MAX_SYNC_WAIT_TIME (1 * 1000 * 1000 * 1000) /* one sec */ ++#define MAX_REBOOT_ATTEMPTS 2 ++ ++typedef enum ++{ ++ META_SYNC_STATE_READY, ++ META_SYNC_STATE_WAITING, ++ META_SYNC_STATE_DONE, ++ META_SYNC_STATE_RESET_PENDING, ++} MetaSyncState; ++ ++typedef struct ++{ ++ Display *xdisplay; ++ ++ XSyncFence xfence; ++ GLsync glsync; ++ ++ XSyncCounter xcounter; ++ XSyncAlarm xalarm; ++ XSyncValue next_counter_value; ++ ++ MetaSyncState state; ++} MetaSync; ++ ++typedef struct ++{ ++ Display *xdisplay; ++ int xsync_event_base; ++ int xsync_error_base; ++ ++ GHashTable *alarm_to_sync; ++ ++ MetaSync *syncs_array[NUM_SYNCS]; ++ guint current_sync_idx; ++ MetaSync *current_sync; ++ guint warmup_syncs; ++ ++ guint reboots; ++} MetaSyncRing; ++ ++static MetaSyncRing meta_sync_ring = { 0 }; ++ ++static XSyncValue SYNC_VALUE_ZERO; ++static XSyncValue SYNC_VALUE_ONE; ++ ++static const char* (*meta_gl_get_string) (GLenum name); ++static void (*meta_gl_get_integerv) (GLenum pname, ++ GLint *params); ++static const char* (*meta_gl_get_stringi) (GLenum name, ++ GLuint index); ++static void (*meta_gl_delete_sync) (GLsync sync); ++static GLenum (*meta_gl_client_wait_sync) (GLsync sync, ++ GLbitfield flags, ++ GLuint64 timeout); ++static void (*meta_gl_wait_sync) (GLsync sync, ++ GLbitfield flags, ++ GLuint64 timeout); ++static GLsync (*meta_gl_import_sync) (GLenum external_sync_type, ++ GLintptr external_sync, ++ GLbitfield flags); ++ ++static MetaSyncRing * ++meta_sync_ring_get (void) ++{ ++ if (meta_sync_ring.reboots > MAX_REBOOT_ATTEMPTS) ++ return NULL; ++ ++ return &meta_sync_ring; ++} ++ ++static gboolean ++load_gl_symbol (const char *name, ++ void **func) ++{ ++ *func = cogl_get_proc_address (name); ++ if (!*func) ++ { ++ meta_verbose ("MetaSyncRing: failed to resolve required GL symbol \"%s\"\n", name); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++static gboolean ++check_gl_extensions (void) ++{ ++ ClutterBackend *backend; ++ CoglContext *cogl_context; ++ CoglDisplay *cogl_display; ++ CoglRenderer *cogl_renderer; ++ ++ backend = clutter_get_default_backend (); ++ cogl_context = clutter_backend_get_cogl_context (backend); ++ cogl_display = cogl_context_get_display (cogl_context); ++ cogl_renderer = cogl_display_get_renderer (cogl_display); ++ ++ switch (cogl_renderer_get_driver (cogl_renderer)) ++ { ++ case COGL_DRIVER_GL3: ++ { ++ int num_extensions, i; ++ gboolean arb_sync = FALSE; ++ gboolean x11_sync_object = FALSE; ++ ++ meta_gl_get_integerv (GL_NUM_EXTENSIONS, &num_extensions); ++ ++ for (i = 0; i < num_extensions; ++i) ++ { ++ const char *ext = meta_gl_get_stringi (GL_EXTENSIONS, i); ++ ++ if (g_strcmp0 ("GL_ARB_sync", ext) == 0) ++ arb_sync = TRUE; ++ else if (g_strcmp0 ("GL_EXT_x11_sync_object", ext) == 0) ++ x11_sync_object = TRUE; ++ } ++ ++ return arb_sync && x11_sync_object; ++ } ++ case COGL_DRIVER_GL: ++ { ++ const char *extensions = meta_gl_get_string (GL_EXTENSIONS); ++ return (extensions != NULL && ++ strstr (extensions, "GL_ARB_sync") != NULL && ++ strstr (extensions, "GL_EXT_x11_sync_object") != NULL); ++ } ++ default: ++ break; ++ } ++ ++ return FALSE; ++} ++ ++static gboolean ++load_required_symbols (void) ++{ ++ static gboolean success = FALSE; ++ ++ if (success) ++ return TRUE; ++ ++ /* We don't link against libGL directly because cogl may want to ++ * use something else. This assumes that cogl has been initialized ++ * and dynamically loaded libGL at this point. ++ */ ++ ++ if (!load_gl_symbol ("glGetString", (void **) &meta_gl_get_string)) ++ goto out; ++ if (!load_gl_symbol ("glGetIntegerv", (void **) &meta_gl_get_integerv)) ++ goto out; ++ if (!load_gl_symbol ("glGetStringi", (void **) &meta_gl_get_stringi)) ++ goto out; ++ ++ if (!check_gl_extensions ()) ++ { ++ meta_verbose ("MetaSyncRing: couldn't find required GL extensions\n"); ++ goto out; ++ } ++ ++ if (!load_gl_symbol ("glDeleteSync", (void **) &meta_gl_delete_sync)) ++ goto out; ++ if (!load_gl_symbol ("glClientWaitSync", (void **) &meta_gl_client_wait_sync)) ++ goto out; ++ if (!load_gl_symbol ("glWaitSync", (void **) &meta_gl_wait_sync)) ++ goto out; ++ if (!load_gl_symbol ("glImportSyncEXT", (void **) &meta_gl_import_sync)) ++ goto out; ++ ++ success = TRUE; ++ out: ++ return success; ++} ++ ++static void ++meta_sync_insert (MetaSync *self) ++{ ++ g_return_if_fail (self->state == META_SYNC_STATE_READY); ++ ++ XSyncTriggerFence (self->xdisplay, self->xfence); ++ XFlush (self->xdisplay); ++ ++ meta_gl_wait_sync (self->glsync, 0, GL_TIMEOUT_IGNORED); ++ ++ self->state = META_SYNC_STATE_WAITING; ++} ++ ++static GLenum ++meta_sync_check_update_finished (MetaSync *self, ++ GLuint64 timeout) ++{ ++ GLenum status = GL_WAIT_FAILED; ++ ++ switch (self->state) ++ { ++ case META_SYNC_STATE_DONE: ++ status = GL_ALREADY_SIGNALED; ++ break; ++ case META_SYNC_STATE_WAITING: ++ status = meta_gl_client_wait_sync (self->glsync, 0, timeout); ++ if (status == GL_ALREADY_SIGNALED || status == GL_CONDITION_SATISFIED) ++ self->state = META_SYNC_STATE_DONE; ++ break; ++ default: ++ break; ++ } ++ ++ g_warn_if_fail (status != GL_WAIT_FAILED); ++ ++ return status; ++} ++ ++static void ++meta_sync_reset (MetaSync *self) ++{ ++ XSyncAlarmAttributes attrs; ++ int overflow; ++ ++ g_return_if_fail (self->state == META_SYNC_STATE_DONE); ++ ++ XSyncResetFence (self->xdisplay, self->xfence); ++ ++ attrs.trigger.wait_value = self->next_counter_value; ++ ++ XSyncChangeAlarm (self->xdisplay, self->xalarm, XSyncCAValue, &attrs); ++ XSyncSetCounter (self->xdisplay, self->xcounter, self->next_counter_value); ++ ++ XSyncValueAdd (&self->next_counter_value, ++ self->next_counter_value, ++ SYNC_VALUE_ONE, ++ &overflow); ++ ++ self->state = META_SYNC_STATE_RESET_PENDING; ++} ++ ++static void ++meta_sync_handle_event (MetaSync *self, ++ XSyncAlarmNotifyEvent *event) ++{ ++ g_return_if_fail (event->alarm == self->xalarm); ++ g_return_if_fail (self->state == META_SYNC_STATE_RESET_PENDING); ++ ++ self->state = META_SYNC_STATE_READY; ++} ++ ++static MetaSync * ++meta_sync_new (Display *xdisplay) ++{ ++ MetaSync *self; ++ XSyncAlarmAttributes attrs; ++ ++ self = g_malloc0 (sizeof (MetaSync)); ++ ++ 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->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO); ++ ++ attrs.trigger.counter = self->xcounter; ++ attrs.trigger.value_type = XSyncAbsolute; ++ attrs.trigger.wait_value = SYNC_VALUE_ONE; ++ attrs.trigger.test_type = XSyncPositiveTransition; ++ attrs.events = TRUE; ++ self->xalarm = XSyncCreateAlarm (xdisplay, ++ XSyncCACounter | ++ XSyncCAValueType | ++ XSyncCAValue | ++ XSyncCATestType | ++ XSyncCAEvents, ++ &attrs); ++ ++ XSyncIntToValue (&self->next_counter_value, 1); ++ ++ self->state = META_SYNC_STATE_READY; ++ ++ return self; ++} ++ ++static Bool ++alarm_event_predicate (Display *dpy, ++ XEvent *event, ++ XPointer data) ++{ ++ MetaSyncRing *ring = meta_sync_ring_get (); ++ ++ if (!ring) ++ return False; ++ ++ if (event->type == ring->xsync_event_base + XSyncAlarmNotify) ++ { ++ if (((MetaSync *) data)->xalarm == ((XSyncAlarmNotifyEvent *) event)->alarm) ++ return True; ++ } ++ return False; ++} ++ ++static void ++meta_sync_free (MetaSync *self) ++{ ++ /* When our assumptions don't hold, something has gone wrong but we ++ * don't know what, so we reboot the ring. While doing that, we ++ * trigger fences before deleting them to try to get ourselves out ++ * of a potentially stuck GPU state. ++ */ ++ switch (self->state) ++ { ++ case META_SYNC_STATE_WAITING: ++ case META_SYNC_STATE_DONE: ++ /* nothing to do */ ++ break; ++ case META_SYNC_STATE_RESET_PENDING: ++ { ++ XEvent event; ++ XIfEvent (self->xdisplay, &event, alarm_event_predicate, (XPointer) self); ++ meta_sync_handle_event (self, (XSyncAlarmNotifyEvent *) &event); ++ } ++ /* fall through */ ++ case META_SYNC_STATE_READY: ++ XSyncTriggerFence (self->xdisplay, self->xfence); ++ XFlush (self->xdisplay); ++ break; ++ default: ++ break; ++ } ++ ++ meta_gl_delete_sync (self->glsync); ++ XSyncDestroyFence (self->xdisplay, self->xfence); ++ XSyncDestroyCounter (self->xdisplay, self->xcounter); ++ XSyncDestroyAlarm (self->xdisplay, self->xalarm); ++ ++ g_free (self); ++} ++ ++gboolean ++meta_sync_ring_init (Display *xdisplay) ++{ ++ gint major, minor; ++ guint i; ++ MetaSyncRing *ring = meta_sync_ring_get (); ++ ++ if (!ring) ++ return FALSE; ++ ++ g_return_val_if_fail (xdisplay != NULL, FALSE); ++ g_return_val_if_fail (ring->xdisplay == NULL, FALSE); ++ ++ if (!load_required_symbols ()) ++ return FALSE; ++ ++ if (!XSyncQueryExtension (xdisplay, &ring->xsync_event_base, &ring->xsync_error_base) || ++ !XSyncInitialize (xdisplay, &major, &minor)) ++ return FALSE; ++ ++ XSyncIntToValue (&SYNC_VALUE_ZERO, 0); ++ XSyncIntToValue (&SYNC_VALUE_ONE, 1); ++ ++ ring->xdisplay = xdisplay; ++ ++ ring->alarm_to_sync = g_hash_table_new (NULL, NULL); ++ ++ for (i = 0; i < NUM_SYNCS; ++i) ++ { ++ MetaSync *sync = meta_sync_new (ring->xdisplay); ++ ring->syncs_array[i] = sync; ++ g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync); ++ } ++ ++ ring->current_sync_idx = 0; ++ ring->current_sync = ring->syncs_array[0]; ++ ring->warmup_syncs = 0; ++ ++ return TRUE; ++} ++ ++void ++meta_sync_ring_destroy (void) ++{ ++ guint i; ++ MetaSyncRing *ring = meta_sync_ring_get (); ++ ++ if (!ring) ++ return; ++ ++ g_return_if_fail (ring->xdisplay != NULL); ++ ++ ring->current_sync_idx = 0; ++ ring->current_sync = NULL; ++ ring->warmup_syncs = 0; ++ ++ for (i = 0; i < NUM_SYNCS; ++i) ++ meta_sync_free (ring->syncs_array[i]); ++ ++ g_hash_table_destroy (ring->alarm_to_sync); ++ ++ ring->xsync_event_base = 0; ++ ring->xsync_error_base = 0; ++ ring->xdisplay = NULL; ++} ++ ++static gboolean ++meta_sync_ring_reboot (Display *xdisplay) ++{ ++ MetaSyncRing *ring = meta_sync_ring_get (); ++ ++ if (!ring) ++ return FALSE; ++ ++ meta_sync_ring_destroy (); ++ ++ ring->reboots += 1; ++ ++ if (!meta_sync_ring_get ()) ++ { ++ meta_warning ("MetaSyncRing: Too many reboots -- disabling\n"); ++ return FALSE; ++ } ++ ++ return meta_sync_ring_init (xdisplay); ++} ++ ++gboolean ++meta_sync_ring_after_frame (void) ++{ ++ MetaSyncRing *ring = meta_sync_ring_get (); ++ ++ if (!ring) ++ return FALSE; ++ ++ g_return_if_fail (ring->xdisplay != NULL); ++ ++ if (ring->warmup_syncs >= NUM_SYNCS / 2) ++ { ++ guint reset_sync_idx = (ring->current_sync_idx + NUM_SYNCS - (NUM_SYNCS / 2)) % NUM_SYNCS; ++ MetaSync *sync_to_reset = ring->syncs_array[reset_sync_idx]; ++ ++ GLenum status = meta_sync_check_update_finished (sync_to_reset, 0); ++ if (status == GL_TIMEOUT_EXPIRED) ++ { ++ meta_warning ("MetaSyncRing: We should never wait for a sync -- add more syncs?\n"); ++ status = meta_sync_check_update_finished (sync_to_reset, MAX_SYNC_WAIT_TIME); ++ } ++ ++ if (status != GL_ALREADY_SIGNALED && status != GL_CONDITION_SATISFIED) ++ { ++ meta_warning ("MetaSyncRing: Timed out waiting for sync object.\n"); ++ return meta_sync_ring_reboot (ring->xdisplay); ++ } ++ ++ meta_sync_reset (sync_to_reset); ++ } ++ else ++ { ++ ring->warmup_syncs += 1; ++ } ++ ++ ring->current_sync_idx += 1; ++ ring->current_sync_idx %= NUM_SYNCS; ++ ++ ring->current_sync = ring->syncs_array[ring->current_sync_idx]; ++ ++ return TRUE; ++} ++ ++gboolean ++meta_sync_ring_insert_wait (void) ++{ ++ MetaSyncRing *ring = meta_sync_ring_get (); ++ ++ if (!ring) ++ return FALSE; ++ ++ g_return_if_fail (ring->xdisplay != NULL); ++ ++ if (ring->current_sync->state != META_SYNC_STATE_READY) ++ { ++ meta_warning ("MetaSyncRing: Sync object is not ready -- were events handled properly?\n"); ++ if (!meta_sync_ring_reboot (ring->xdisplay)) ++ return FALSE; ++ } ++ ++ meta_sync_insert (ring->current_sync); ++ ++ return TRUE; ++} ++ ++void ++meta_sync_ring_handle_event (XEvent *xevent) ++{ ++ XSyncAlarmNotifyEvent *event; ++ MetaSync *sync; ++ MetaSyncRing *ring = meta_sync_ring_get (); ++ ++ if (!ring) ++ return; ++ ++ g_return_if_fail (ring->xdisplay != NULL); ++ ++ if (xevent->type != (ring->xsync_event_base + XSyncAlarmNotify)) ++ return; ++ ++ event = (XSyncAlarmNotifyEvent *) xevent; ++ ++ sync = g_hash_table_lookup (ring->alarm_to_sync, (gpointer) event->alarm); ++ if (sync) ++ meta_sync_handle_event (sync, event); ++} +diff --git a/src/compositor/meta-sync-ring.h b/src/compositor/meta-sync-ring.h +new file mode 100644 +index 0000000..6dca8ef +--- /dev/null ++++ b/src/compositor/meta-sync-ring.h +@@ -0,0 +1,14 @@ ++#ifndef _META_SYNC_RING_H_ ++#define _META_SYNC_RING_H_ ++ ++#include <glib.h> ++ ++#include <X11/Xlib.h> ++ ++gboolean meta_sync_ring_init (Display *dpy); ++void meta_sync_ring_destroy (void); ++gboolean meta_sync_ring_after_frame (void); ++gboolean meta_sync_ring_insert_wait (void); ++void meta_sync_ring_handle_event (XEvent *event); ++ ++#endif /* _META_SYNC_RING_H_ */ +-- +cgit v0.10.2 + diff --git a/x11-wm/mutter/files/mutter-3.16.3-crash-border.patch b/x11-wm/mutter/files/mutter-3.16.3-crash-border.patch new file mode 100644 index 000000000000..9cbd0d06e44a --- /dev/null +++ b/x11-wm/mutter/files/mutter-3.16.3-crash-border.patch @@ -0,0 +1,32 @@ +From f60c33b5afc4b1dff0b31f17d7ae222db8aa789f Mon Sep 17 00:00:00 2001 +From: Marek Chalupa <mchqwerty@gmail.com> +Date: Fri, 3 Jul 2015 11:28:00 +0200 +Subject: frames: handle META_FRAME_CONTROL_NONE on left click + +We can get this operation in some cases, for example when +we're trying to resize window that cannot be resized. +This can occur with maximized windows that have a border +(without border we couldn't resize them by mouse in maximized state). +In this case we reached abort() beacuse we did not handle this op. + +https://bugzilla.gnome.org/show_bug.cgi?id=751884 + +diff --git a/src/ui/frames.c b/src/ui/frames.c +index 362d7b6..a2f7f45 100644 +--- a/src/ui/frames.c ++++ b/src/ui/frames.c +@@ -1053,6 +1053,11 @@ meta_frame_left_click_event (MetaUIFrame *frame, + } + + return TRUE; ++ case META_FRAME_CONTROL_NONE: ++ /* We can get this for example when trying to resize window ++ * that cannot be resized (e. g. it is maximized and the theme ++ * currently used has borders for maximized windows), see #751884 */ ++ return FALSE; + default: + g_assert_not_reached (); + } +-- +cgit v0.10.2 + diff --git a/x11-wm/mutter/files/mutter-3.16.3-fallback-keymap.patch b/x11-wm/mutter/files/mutter-3.16.3-fallback-keymap.patch new file mode 100644 index 000000000000..f77234ba3b20 --- /dev/null +++ b/x11-wm/mutter/files/mutter-3.16.3-fallback-keymap.patch @@ -0,0 +1,28 @@ +From 9abc0712836c9e56ed08796645874cc0d10b1826 Mon Sep 17 00:00:00 2001 +From: Rui Matos <tiagomatos@gmail.com> +Date: Mon, 21 Sep 2015 17:25:40 +0200 +Subject: backend-x11: Fallback to a default keymap if getting it from X fails + +This shouldn't fail but apparently sometimes it does and in that case +having a possibly wrong idea of the keymap is still better than +crashing. + +https://bugzilla.gnome.org/show_bug.cgi?id=754979 + +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index 7ad28fd..dbcd13f 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -760,6 +760,9 @@ meta_backend_x11_get_keymap (MetaBackend *backend) + priv->xcb, + xkb_x11_get_core_keyboard_device_id (priv->xcb), + XKB_KEYMAP_COMPILE_NO_FLAGS); ++ if (priv->keymap == NULL) ++ priv->keymap = xkb_keymap_new_from_names (context, NULL, XKB_KEYMAP_COMPILE_NO_FLAGS); ++ + xkb_context_unref (context); + } + +-- +cgit v0.10.2 + 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 + diff --git a/x11-wm/mutter/files/mutter-3.16.3-fix-return.patch b/x11-wm/mutter/files/mutter-3.16.3-fix-return.patch new file mode 100644 index 000000000000..2898d5238813 --- /dev/null +++ b/x11-wm/mutter/files/mutter-3.16.3-fix-return.patch @@ -0,0 +1,32 @@ +From a54b1261d3ec5ccf7a8262c88557b6b952bc8a2e Mon Sep 17 00:00:00 2001 +From: Ting-Wei Lan <lantw@src.gnome.org> +Date: Sat, 8 Aug 2015 20:12:09 +0800 +Subject: build: Fix return value in meta-sync-ring.c + +https://bugzilla.gnome.org/show_bug.cgi?id=753380 + +diff --git a/src/compositor/meta-sync-ring.c b/src/compositor/meta-sync-ring.c +index 44b1c41..217ebe5 100644 +--- a/src/compositor/meta-sync-ring.c ++++ b/src/compositor/meta-sync-ring.c +@@ -499,7 +499,7 @@ meta_sync_ring_after_frame (void) + if (!ring) + return FALSE; + +- g_return_if_fail (ring->xdisplay != NULL); ++ g_return_val_if_fail (ring->xdisplay != NULL, FALSE); + + if (ring->warmup_syncs >= NUM_SYNCS / 2) + { +@@ -542,7 +542,7 @@ meta_sync_ring_insert_wait (void) + if (!ring) + return FALSE; + +- g_return_if_fail (ring->xdisplay != NULL); ++ g_return_val_if_fail (ring->xdisplay != NULL, FALSE); + + if (ring->current_sync->state != META_SYNC_STATE_READY) + { +-- +cgit v0.10.2 + diff --git a/x11-wm/mutter/files/mutter-3.16.3-flickering.patch b/x11-wm/mutter/files/mutter-3.16.3-flickering.patch new file mode 100644 index 000000000000..6267a4e33348 --- /dev/null +++ b/x11-wm/mutter/files/mutter-3.16.3-flickering.patch @@ -0,0 +1,114 @@ +From 916070cc7218cc80f4565ea265b0dd6e5e93cb98 Mon Sep 17 00:00:00 2001 +From: Rui Matos <tiagomatos@gmail.com> +Date: Wed, 12 Aug 2015 15:26:34 +0200 +Subject: compositor: Handle fences in the frontend X connection + +Since mutter has two X connections and does damage handling on the +frontend while fence triggering is done on the backend, we have a race +between XDamageSubtract() and XSyncFenceTrigger() causing missed +redraws in the GL_EXT_X11_sync_object path. + +If the fence trigger gets processed first by the server, any client +drawing that happens between that and the damage subtract being +processed and is completely contained in the last damage event box +that mutter got, won't be included in the current frame nor will it +cause a new damage event. + +A simple fix for this would be XSync()ing on the frontend connection +after doing all the damage subtracts but that would add a round trip +on every frame again which defeats the asynchronous design of X +fences. + +Instead, if we move fence handling to the frontend we automatically +get the right ordering between damage subtracts and fence triggers. + +https://bugzilla.gnome.org/show_bug.cgi?id=728464 + +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index ac38ffc..3ff8431 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -45,7 +45,6 @@ + #include <meta/util.h> + #include "display-private.h" + #include "compositor/compositor-private.h" +-#include "compositor/meta-sync-ring.h" + + struct _MetaBackendX11Private + { +@@ -256,8 +255,6 @@ handle_host_xevent (MetaBackend *backend, + MetaCompositor *compositor = display->compositor; + if (meta_plugin_manager_xevent_filter (compositor->plugin_mgr, event)) + bypass_clutter = TRUE; +- if (compositor->have_x11_sync_object) +- meta_sync_ring_handle_event (event); + } + } + +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index 554faa1..2e182c2 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -534,8 +534,7 @@ meta_compositor_manage (MetaCompositor *compositor) + */ + XMapWindow (xdisplay, compositor->output); + +- compositor->have_x11_sync_object = +- meta_sync_ring_init (meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend))); ++ compositor->have_x11_sync_object = meta_sync_ring_init (xdisplay); + } + + redirect_windows (display->screen); +@@ -737,6 +736,9 @@ meta_compositor_process_event (MetaCompositor *compositor, + process_damage (compositor, (XDamageNotifyEvent *) event, window); + } + ++ if (compositor->have_x11_sync_object) ++ meta_sync_ring_handle_event (event); ++ + /* Clutter needs to know about MapNotify events otherwise it will + think the stage is invisible */ + if (!meta_is_wayland_compositor () && event->type == MapNotify) +diff --git a/src/compositor/meta-sync-ring.c b/src/compositor/meta-sync-ring.c +index 217ebe5..336ccd4 100644 +--- a/src/compositor/meta-sync-ring.c ++++ b/src/compositor/meta-sync-ring.c +@@ -322,7 +322,7 @@ meta_sync_new (Display *xdisplay) + self->xdisplay = xdisplay; + + self->xfence = XSyncCreateFence (xdisplay, DefaultRootWindow (xdisplay), FALSE); +- self->gl_x11_sync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0); ++ self->gl_x11_sync = 0; + self->gpu_fence = 0; + + self->xcounter = XSyncCreateCounter (xdisplay, SYNC_VALUE_ZERO); +@@ -347,6 +347,13 @@ meta_sync_new (Display *xdisplay) + return self; + } + ++static void ++meta_sync_import (MetaSync *self) ++{ ++ g_return_if_fail (self->gl_x11_sync == 0); ++ self->gl_x11_sync = meta_gl_import_sync (GL_SYNC_X11_FENCE_EXT, self->xfence, 0); ++} ++ + static Bool + alarm_event_predicate (Display *dpy, + XEvent *event, +@@ -437,6 +444,12 @@ meta_sync_ring_init (Display *xdisplay) + ring->syncs_array[i] = sync; + g_hash_table_replace (ring->alarm_to_sync, (gpointer) sync->xalarm, sync); + } ++ /* Since the connection we create the X fences on isn't the same as ++ * the one used for the GLX context, we need to XSync() here to ++ * ensure glImportSync() succeeds. */ ++ XSync (xdisplay, False); ++ for (i = 0; i < NUM_SYNCS; ++i) ++ meta_sync_import (ring->syncs_array[i]); + + ring->current_sync_idx = 0; + ring->current_sync = ring->syncs_array[0]; +-- +cgit v0.10.2 + diff --git a/x11-wm/mutter/mutter-3.16.3-r1.ebuild b/x11-wm/mutter/mutter-3.16.3-r1.ebuild new file mode 100644 index 000000000000..98cc39c2a7d0 --- /dev/null +++ b/x11-wm/mutter/mutter-3.16.3-r1.ebuild @@ -0,0 +1,114 @@ +# Copyright 1999-2015 Gentoo Foundation +# Distributed under the terms of the GNU General Public License v2 +# $Id$ + +EAPI="5" +GCONF_DEBUG="yes" + +inherit autotools eutils gnome2 + +DESCRIPTION="GNOME 3 compositing window manager based on Clutter" +HOMEPAGE="https://git.gnome.org/browse/mutter/" + +LICENSE="GPL-2+" +SLOT="0" +IUSE="+introspection +kms test wayland" +KEYWORDS="~alpha ~amd64 ~arm ~ia64 ~ppc ~ppc64 ~sparc ~x86" + +# libXi-1.7.4 or newer needed per: +# https://bugzilla.gnome.org/show_bug.cgi?id=738944 +COMMON_DEPEND=" + >=x11-libs/pango-1.2[X,introspection?] + >=x11-libs/cairo-1.10[X] + >=x11-libs/gtk+-3.9.11:3[X,introspection?] + >=dev-libs/glib-2.36.0:2[dbus] + >=media-libs/clutter-1.21.3:1.0[introspection?] + >=media-libs/cogl-1.17.1:1.0=[introspection?] + >=media-libs/libcanberra-0.26[gtk3] + >=x11-libs/startup-notification-0.7 + >=x11-libs/libXcomposite-0.2 + >=gnome-base/gsettings-desktop-schemas-3.15.92[introspection?] + gnome-base/gnome-desktop:3= + >sys-power/upower-0.99:= + + x11-libs/libICE + x11-libs/libSM + x11-libs/libX11 + >=x11-libs/libXcomposite-0.2 + x11-libs/libXcursor + x11-libs/libXdamage + x11-libs/libXext + x11-libs/libXfixes + >=x11-libs/libXi-1.7.4 + x11-libs/libXinerama + x11-libs/libXrandr + x11-libs/libXrender + x11-libs/libxcb + x11-libs/libxkbfile + >=x11-libs/libxkbcommon-0.4.3[X] + x11-misc/xkeyboard-config + + gnome-extra/zenity + + introspection? ( >=dev-libs/gobject-introspection-1.42:= ) + kms? ( + dev-libs/libinput + >=media-libs/clutter-1.20[egl] + media-libs/cogl:1.0=[kms] + >=media-libs/mesa-10.3[gbm] + sys-apps/systemd + virtual/libgudev + x11-libs/libdrm:= ) + wayland? ( + >=dev-libs/wayland-1.6.90 + >=media-libs/clutter-1.20[wayland] + x11-base/xorg-server[wayland] ) +" +DEPEND="${COMMON_DEPEND} + >=dev-util/gtk-doc-am-1.15 + >=dev-util/intltool-0.41 + sys-devel/gettext + virtual/pkgconfig + x11-proto/xextproto + x11-proto/xineramaproto + x11-proto/xproto + test? ( app-text/docbook-xml-dtd:4.5 ) +" +RDEPEND="${COMMON_DEPEND} + !x11-misc/expocity +" + +src_prepare() { + # Fallback to a default keymap if getting it from X fails (from 'master') + epatch "${FILESDIR}"/${PN}-3.16.3-fallback-keymap.patch + + # frames: handle META_FRAME_CONTROL_NONE on left click (from '3.16') + epatch "${FILESDIR}"/${P}-crash-border.patch + + # compositor: Add support for GL_EXT_x11_sync_object (from '3.16') + epatch "${FILESDIR}"/${P}-GL_EXT_x11_sync_object.patch + + # compositor: Fix GL_EXT_x11_sync_object race condition (from '3.16') + epatch "${FILESDIR}"/${P}-fix-race.patch + + # build: Fix return value in meta-sync-ring.c (from '3.16') + epatch "${FILESDIR}"/${P}-fix-return.patch + + # compositor: Handle fences in the frontend X connection (from '3.16') + epatch "${FILESDIR}"/${P}-flickering.patch + + eautoreconf + gnome2_src_prepare +} + +src_configure() { + gnome2_src_configure \ + --disable-static \ + --enable-sm \ + --enable-startup-notification \ + --enable-verbose-mode \ + --with-libcanberra \ + $(use_enable introspection) \ + $(use_enable kms native-backend) \ + $(use_enable wayland) +} |