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
This commit is contained in:
Rui Matos 2014-05-12 15:11:53 +02:00 committed by Jasper St. Pierre
parent 80de15face
commit f55737ec06
3 changed files with 31 additions and 20 deletions

View File

@ -38,6 +38,8 @@ struct _MetaCompositor
gint switch_workspace_in_progress; gint switch_workspace_in_progress;
MetaPluginManager *plugin_mgr; MetaPluginManager *plugin_mgr;
gboolean frame_has_updated_xsurfaces;
}; };
/* Wait 2ms after vblank before starting to draw next frame */ /* Wait 2ms after vblank before starting to draw next frame */

View File

@ -146,6 +146,8 @@ process_damage (MetaCompositor *compositor,
{ {
MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window));
meta_window_actor_process_x11_damage (window_actor, event); meta_window_actor_process_x11_damage (window_actor, event);
compositor->frame_has_updated_xsurfaces = TRUE;
} }
/* compat helper */ /* compat helper */
@ -1135,6 +1137,33 @@ pre_paint_windows (MetaCompositor *compositor)
for (l = compositor->windows; l; l = l->next) for (l = compositor->windows; l; l = l->next)
meta_window_actor_pre_paint (l->data); 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 static gboolean

View File

@ -239,26 +239,6 @@ meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
XDamageSubtract (xdisplay, priv->damage, None, None); XDamageSubtract (xdisplay, priv->damage, None, None);
meta_error_trap_pop (display); 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; priv->received_damage = FALSE;
} }