From f55737ec06611cf5cdacf32809cffe2332e7894a Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Mon, 12 May 2014 15:11:53 +0200 Subject: [PATCH] compositor: Sync X drawing only once per frame We only need to call XSync() once per frame to synchronize X with GL drawing. https://bugzilla.gnome.org/show_bug.cgi?id=728464 --- src/compositor/compositor-private.h | 2 ++ src/compositor/compositor.c | 29 +++++++++++++++++++++++++ src/compositor/meta-surface-actor-x11.c | 20 ----------------- 3 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h index ef0a53457..a41f56365 100644 --- a/src/compositor/compositor-private.h +++ b/src/compositor/compositor-private.h @@ -38,6 +38,8 @@ struct _MetaCompositor gint switch_workspace_in_progress; MetaPluginManager *plugin_mgr; + + gboolean frame_has_updated_xsurfaces; }; /* Wait 2ms after vblank before starting to draw next frame */ diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c index 318e07ac7..3e5a205e8 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -146,6 +146,8 @@ process_damage (MetaCompositor *compositor, { MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); meta_window_actor_process_x11_damage (window_actor, event); + + compositor->frame_has_updated_xsurfaces = TRUE; } /* compat helper */ @@ -1135,6 +1137,33 @@ pre_paint_windows (MetaCompositor *compositor) for (l = compositor->windows; l; l = l->next) meta_window_actor_pre_paint (l->data); + + if (compositor->frame_has_updated_xsurfaces) + { + /* 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. + * + * Xorg and open source driver specifics: + * + * The X server makes sure to flush drawing to the kernel before + * sending out damage events, but since we use + * DamageReportBoundingBox there may be drawing between the last + * damage event and the XDamageSubtract() that needs to be + * flushed as well. + * + * Xorg always makes sure that drawing is flushed to the kernel + * before writing events or responses to the client, so any + * round trip request at this point is sufficient to flush the + * GLX buffers. + */ + XSync (compositor->display->xdisplay, False); + + compositor->frame_has_updated_xsurfaces = FALSE; + } } static gboolean diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c index 78004f573..9322081fa 100644 --- a/src/compositor/meta-surface-actor-x11.c +++ b/src/compositor/meta-surface-actor-x11.c @@ -239,26 +239,6 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor) XDamageSubtract (xdisplay, priv->damage, None, None); meta_error_trap_pop (display); - /* We need to make sure that any X drawing that happens before the - * XDamageSubtract() 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. - * - * Xorg and open source driver specifics: - * - * The X server makes sure to flush drawing to the kernel before - * sending out damage events, but since we use DamageReportBoundingBox - * there may be drawing between the last damage event and the - * XDamageSubtract() that needs to be flushed as well. - * - * Xorg always makes sure that drawing is flushed to the kernel - * before writing events or responses to the client, so any round trip - * request at this point is sufficient to flush the GLX buffers. - */ - XSync (xdisplay, False); - priv->received_damage = FALSE; }