modesetting: Fix reverse prime update lagging on secondary GPU outputs

When using secondary GPU outputs the primary GPU's blockhandler
will copy changes from its framebuffer to a pixmap shared with the
secondary GPU.

In reverse prime setups the secondary GPU's blockhandler will do another
copy from the shared pixmap to its own framebuffer.

Before this commit, if the primary GPU's blockhandler would run after
the secondary GPU's blockhandler and no events were pending, then the
secondary GPU's blockhandler would not run until some events came in
(WaitForSomething() would block in the poll call), resulting in the
secondary GPU output sometimes showing stale contents (e.g. a just closed
window) for easily up to 10 seconds.

This commit fixes this by setting the timeout passed into the
blockhandler to 0 if any shared pixmaps were updated by the primary GPU,
forcing an immediate re-run of all blockhandlers.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Hans de Goede 2016-09-15 14:35:52 +02:00 committed by Adam Jackson
parent e8695100b1
commit 299cbb9267

View File

@ -584,7 +584,7 @@ dispatch_slave_dirty(ScreenPtr pScreen)
}
static void
redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty, int *timeout)
{
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
RegionRec pixregion;
@ -602,6 +602,9 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
*/
if (ms->drmmode.glamor)
glamor_finish(screen);
/* Ensure the slave processes the damage immediately */
if (timeout)
*timeout = 0;
}
DamageRegionProcessPending(&dirty->slave_dst->drawable);
@ -609,7 +612,7 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
}
static void
ms_dirty_update(ScreenPtr screen)
ms_dirty_update(ScreenPtr screen, int *timeout)
{
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
@ -636,7 +639,7 @@ ms_dirty_update(ScreenPtr screen)
if (ppriv->defer_dirty_update)
continue;
redisplay_dirty(screen, ent);
redisplay_dirty(screen, ent, timeout);
DamageEmpty(ent->damage);
}
}
@ -672,7 +675,7 @@ msBlockHandler(ScreenPtr pScreen, void *timeout)
else if (ms->dirty_enabled)
dispatch_dirty(pScreen);
ms_dirty_update(pScreen);
ms_dirty_update(pScreen, timeout);
}
static void
@ -1261,7 +1264,7 @@ msPresentSharedPixmap(PixmapPtr slave_dst)
RegionPtr region = DamageRegion(ppriv->dirty->damage);
if (RegionNotEmpty(region)) {
redisplay_dirty(ppriv->slave_src->drawable.pScreen, ppriv->dirty);
redisplay_dirty(ppriv->slave_src->drawable.pScreen, ppriv->dirty, NULL);
DamageEmpty(ppriv->dirty->damage);
return TRUE;