[PATCH v6 11/11] modesetting: Implement PRIME syncing as a source

Alex Goins agoins at nvidia.com
Sat Jun 11 00:21:05 UTC 2016


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

Signed-off-by: Alex Goins <agoins at nvidia.com>
---
 hw/xfree86/drivers/modesetting/driver.c          | 137 +++++++++++++++++++++++
 hw/xfree86/drivers/modesetting/drmmode_display.h |   8 +-
 2 files changed, 144 insertions(+), 1 deletion(-)

diff --git a/hw/xfree86/drivers/modesetting/driver.c b/hw/xfree86/drivers/modesetting/driver.c
index 403cb96..bf3ddbf 100644
--- a/hw/xfree86/drivers/modesetting/driver.c
+++ b/hw/xfree86/drivers/modesetting/driver.c
@@ -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)
 {
@@ -1010,6 +1042,90 @@ msDisableSharedPixmapFlipping(RRCrtcPtr crtc)
 }
 
 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)
 {
     ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
@@ -1076,6 +1192,8 @@ CreateScreenResources(ScreenPtr pScreen)
     pScrPriv->rrEnableSharedPixmapFlipping = msEnableSharedPixmapFlipping;
     pScrPriv->rrDisableSharedPixmapFlipping = msDisableSharedPixmapFlipping;
 
+    pScrPriv->rrStartFlippingPixmapTracking = msStartFlippingPixmapTracking;
+
     return ret;
 }
 
@@ -1139,6 +1257,20 @@ msSetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
 }
 
 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)
 {
     Bool ret = FALSE;
@@ -1336,6 +1468,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;
diff --git a/hw/xfree86/drivers/modesetting/drmmode_display.h b/hw/xfree86/drivers/modesetting/drmmode_display.h
index 3161bba..6d2c0a4 100644
--- a/hw/xfree86/drivers/modesetting/drmmode_display.h
+++ b/hw/xfree86/drivers/modesetting/drmmode_display.h
@@ -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;
-- 
1.9.1



More information about the xorg-devel mailing list