modesetting: Implement PRIME syncing as a source

Implements (Start/Stop)FlippingPixmapTracking, PresentSharedPixmap, and
RequestSharedPixmapNotifyDamage, the source functions for PRIME
synchronization and double buffering. Allows modesetting driver to be used
as a source with PRIME synchronization.

v1: N/A
v2: N/A
v3: N/A
v4: Initial commit
v5: Move disabling of reverse PRIME on sink to sink commit
v6: Rebase onto ToT
v7: Unchanged

Reviewed-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Alex Goins <agoins@nvidia.com>
This commit is contained in:
Alex Goins 2016-06-16 20:06:56 -07:00 committed by Adam Jackson
parent 44cb9578c0
commit b83dede9cb
2 changed files with 144 additions and 1 deletions

View File

@ -577,6 +577,8 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
static void
ms_dirty_update(ScreenPtr screen)
{
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(screen));
RegionPtr region;
PixmapDirtyUpdatePtr ent;
@ -586,12 +588,42 @@ ms_dirty_update(ScreenPtr screen)
xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
region = DamageRegion(ent->damage);
if (RegionNotEmpty(region)) {
msPixmapPrivPtr ppriv =
msGetPixmapPriv(&ms->drmmode, ent->slave_dst);
if (ppriv->notify_on_damage) {
ppriv->notify_on_damage = FALSE;
ent->slave_dst->drawable.pScreen->
SharedPixmapNotifyDamage(ent->slave_dst);
}
/* Requested manual updating */
if (ppriv->defer_dirty_update)
continue;
redisplay_dirty(screen, ent);
DamageEmpty(ent->damage);
}
}
}
static PixmapDirtyUpdatePtr
ms_dirty_get_ent(ScreenPtr screen, PixmapPtr slave_dst)
{
PixmapDirtyUpdatePtr ent;
if (xorg_list_is_empty(&screen->pixmap_dirty_list))
return NULL;
xorg_list_for_each_entry(ent, &screen->pixmap_dirty_list, ent) {
if (ent->slave_dst == slave_dst)
return ent;
}
return NULL;
}
static void
msBlockHandler(ScreenPtr pScreen, void *pTimeout, void *pReadmask)
{
@ -1016,6 +1048,90 @@ msDisableSharedPixmapFlipping(RRCrtcPtr crtc)
drmmode_DisableSharedPixmapFlipping(xf86Crtc, &ms->drmmode);
}
static Bool
msStartFlippingPixmapTracking(RRCrtcPtr crtc, PixmapPtr src,
PixmapPtr slave_dst1, PixmapPtr slave_dst2,
int x, int y, int dst_x, int dst_y,
Rotation rotation)
{
ScreenPtr pScreen = src->drawable.pScreen;
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, slave_dst1),
ppriv2 = msGetPixmapPriv(&ms->drmmode, slave_dst2);
if (!PixmapStartDirtyTracking(src, slave_dst1, x, y,
dst_x, dst_y, rotation)) {
return FALSE;
}
if (!PixmapStartDirtyTracking(src, slave_dst2, x, y,
dst_x, dst_y, rotation)) {
PixmapStopDirtyTracking(src, slave_dst1);
return FALSE;
}
ppriv1->slave_src = src;
ppriv2->slave_src = src;
ppriv1->dirty = ms_dirty_get_ent(pScreen, slave_dst1);
ppriv2->dirty = ms_dirty_get_ent(pScreen, slave_dst2);
ppriv1->defer_dirty_update = TRUE;
ppriv2->defer_dirty_update = TRUE;
return TRUE;
}
static Bool
msPresentSharedPixmap(PixmapPtr slave_dst)
{
ScreenPtr pScreen = slave_dst->drawable.pScreen;
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, slave_dst);
RegionPtr region = DamageRegion(ppriv->dirty->damage);
if (RegionNotEmpty(region)) {
redisplay_dirty(ppriv->slave_src->drawable.pScreen, ppriv->dirty);
DamageEmpty(ppriv->dirty->damage);
return TRUE;
}
return FALSE;
}
static Bool
msStopFlippingPixmapTracking(PixmapPtr src,
PixmapPtr slave_dst1, PixmapPtr slave_dst2)
{
ScreenPtr pScreen = src->drawable.pScreen;
modesettingPtr ms = modesettingPTR(xf86ScreenToScrn(pScreen));
msPixmapPrivPtr ppriv1 = msGetPixmapPriv(&ms->drmmode, slave_dst1),
ppriv2 = msGetPixmapPriv(&ms->drmmode, slave_dst2);
Bool ret = TRUE;
ret &= PixmapStopDirtyTracking(src, slave_dst1);
ret &= PixmapStopDirtyTracking(src, slave_dst2);
if (ret) {
ppriv1->slave_src = NULL;
ppriv2->slave_src = NULL;
ppriv1->dirty = NULL;
ppriv2->dirty = NULL;
ppriv1->defer_dirty_update = FALSE;
ppriv2->defer_dirty_update = FALSE;
}
return ret;
}
static Bool
CreateScreenResources(ScreenPtr pScreen)
{
@ -1083,6 +1199,8 @@ CreateScreenResources(ScreenPtr pScreen)
pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping;
pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping;
pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
return ret;
}
@ -1145,6 +1263,20 @@ msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
#endif
}
static Bool
msRequestSharedPixmapNotifyDamage(PixmapPtr ppix)
{
ScreenPtr screen = ppix->drawable.pScreen;
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
modesettingPtr ms = modesettingPTR(scrn);
msPixmapPrivPtr ppriv = msGetPixmapPriv(&ms->drmmode, ppix);
ppriv->notify_on_damage = TRUE;
return TRUE;
}
static Bool
msSharedPixmapNotifyDamage(PixmapPtr ppix)
{
@ -1343,6 +1475,11 @@ ScreenInit(ScreenPtr pScreen, int argc, char **argv)
pScreen->StopPixmapTracking = PixmapStopDirtyTracking;
pScreen->SharedPixmapNotifyDamage = msSharedPixmapNotifyDamage;
pScreen->RequestSharedPixmapNotifyDamage =
msRequestSharedPixmapNotifyDamage;
pScreen->PresentSharedPixmap = msPresentSharedPixmap;
pScreen->StopFlippingPixmapTracking = msStopFlippingPixmapTracking;
if (!xf86CrtcScreenInit(pScreen))
return FALSE;

View File

@ -152,9 +152,15 @@ typedef struct _msPixmapPriv {
DamagePtr slave_damage;
/** Fields for flipping shared pixmaps */
/** Sink fields for flipping shared pixmaps */
int flip_seq; /* seq of current page flip event handler */
Bool wait_for_damage; /* if we have requested damage notification from source */
/** Source fields for flipping shared pixmaps */
Bool defer_dirty_update; /* if we want to manually update */
PixmapDirtyUpdatePtr dirty; /* cached dirty ent to avoid searching list */
PixmapPtr slave_src; /* if we exported shared pixmap, dirty tracking src */
Bool notify_on_damage; /* if sink has requested damage notification */
} msPixmapPrivRec, *msPixmapPrivPtr;
extern DevPrivateKeyRec msPixmapPrivateKeyRec;