[PATCH v3 2/9] randr/xf86: Add PRIME Synchronization / Double Buffer

Alex Goins agoins at nvidia.com
Wed Feb 3 05:22:43 CET 2016


Changes PRIME to use double buffering and synchronization if all required
driver functions are available.

rrcrtc.c:
    Changes rrSetupPixmapSharing() to use double buffering and
    synchronization in the case that all required driver functions are
    available. Otherwise, falls back to unsynchronized single buffer.

    Changes RRCrtcDetachScanoutPixmap() to properly clean up in the case of
    double buffering.

    Moves StopPixmapTracking() from rrDestroySharedPixmap() to
    RRCrtcDetachScanoutPixmap().

randrstr.h:
    Adds scanout_pixmap_back to struct _rrCrtc to facilitate PRIME
    double buffering.

xf86Crtc.h:
    Adds current_scanout_back to _xf86Crtc to facilitate detection
    of changes to it in xf86RandR12CrtcSet().

xf86RandR12.c:
    Changes xf86RandR12CrtcSet() to detect changes in
    scanout_pixmap_back.

    Adds scanout_pixmap_back to struct _rrCrtc to facilitate PRIME double
    buffering.

v1: Initial commit
v2: Rename PresentTrackedFlippingPixmap to PresentSharedPixmap
v3: Refactor to accomodate moving (rr)StartFlippingPixmapTracking and
    (rr)(Enable/Disable)SharedPixmapFlipping to rrScrPrivRec from ScreenRec
    Add fallback if flipping funcs fail

Signed-off-by: Alex Goins <agoins at nvidia.com>
---
 hw/xfree86/modes/xf86Crtc.h    |  4 ++
 hw/xfree86/modes/xf86RandR12.c |  4 +-
 randr/randrstr.h               |  1 +
 randr/rrcrtc.c                 | 94 ++++++++++++++++++++++++++++++++++++------
 4 files changed, 89 insertions(+), 14 deletions(-)

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 8b01608..8518411 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -392,6 +392,10 @@ struct _xf86Crtc {
     /* Added in ABI version 5
      */
     PixmapPtr current_scanout;
+
+    /* Added in ABI version 6
+     */
+    PixmapPtr current_scanout_back;
 };
 
 typedef struct _xf86OutputFuncs {
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index eae7016..3d561df 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1154,7 +1154,8 @@ xf86RandR12CrtcSet(ScreenPtr pScreen,
     if (rotation != crtc->rotation)
         changed = TRUE;
 
-    if (crtc->current_scanout != randr_crtc->scanout_pixmap)
+    if (crtc->current_scanout != randr_crtc->scanout_pixmap ||
+        crtc->current_scanout_back != randr_crtc->scanout_pixmap_back)
         changed = TRUE;
 
     transform = RRCrtcGetTransform(randr_crtc);
@@ -1219,6 +1220,7 @@ xf86RandR12CrtcSet(ScreenPtr pScreen,
             xf86SaveModeContents(&crtc->desiredMode, &mode);
             crtc->desiredRotation = rotation;
             crtc->current_scanout = randr_crtc->scanout_pixmap;
+            crtc->current_scanout_back = randr_crtc->scanout_pixmap_back;
             if (transform) {
                 crtc->desiredTransform = *transform;
                 crtc->desiredTransformPresent = TRUE;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index b8f5819..b36d304 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -130,6 +130,7 @@ struct _rrCrtc {
     struct pict_f_transform f_inverse;
 
     PixmapPtr scanout_pixmap;
+    PixmapPtr scanout_pixmap_back;
 };
 
 struct _rrOutput {
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 566a3db..f3a8d05 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -366,9 +366,6 @@ rrDestroySharedPixmap(RRCrtcPtr crtc, PixmapPtr pPixmap) {
     ScreenPtr master = crtc->pScreen->current_master;
 
     if (master && pPixmap->master_pixmap) {
-        PixmapPtr mscreenpix = master->GetScreenPixmap(master);
-
-        master->StopPixmapTracking(mscreenpix, pPixmap);
         /*
          * Unref the pixmap twice: once for the original reference, and once
          * for the reference implicitly added by PixmapShareToSlave.
@@ -386,10 +383,31 @@ RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
     rrScrPriv(crtc->pScreen);
 
     pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
+
     if (crtc->scanout_pixmap) {
+        ScreenPtr master = crtc->pScreen->current_master;
+        PixmapPtr mscreenpix = master->GetScreenPixmap(master);
+
+        if (crtc->scanout_pixmap_back) {
+            rrScrPrivPtr pSlaveScrPriv = rrGetScrPriv(crtc->pScreen);
+
+            pSlaveScrPriv->rrDisableSharedPixmapFlipping(crtc);
+
+            master->StopFlippingPixmapTracking(mscreenpix,
+                                               crtc->scanout_pixmap,
+                                               crtc->scanout_pixmap_back);
+
+            rrDestroySharedPixmap(crtc, crtc->scanout_pixmap_back);
+            crtc->scanout_pixmap_back = NULL;
+        }
+        else {
+            master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap);
+        }
+
         rrDestroySharedPixmap(crtc, crtc->scanout_pixmap);
+        crtc->scanout_pixmap = NULL;
     }
-    crtc->scanout_pixmap = NULL;
+
     RRCrtcChanged(crtc, TRUE);
 }
 
@@ -428,16 +446,25 @@ rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height,
                      int x, int y, Rotation rotation)
 {
     ScreenPtr master = crtc->pScreen->current_master;
+    rrScrPrivPtr pMasterScrPriv = rrGetScrPriv(master);
+    rrScrPrivPtr pSlaveScrPriv = rrGetScrPriv(crtc->pScreen);
+
     int depth;
     PixmapPtr mscreenpix;
-    PixmapPtr spix;
+    PixmapPtr protopix = master->GetScreenPixmap(master);
+    rrScrPriv(crtc->pScreen);
+    PixmapPtr spix_front;
 
     /* create a pixmap on the master screen,
        then get a shared handle for it
        create a shared pixmap on the slave screen using the handle
-       set the master screen to do dirty updates to the shared pixmap
-       from the screen pixmap.
        set slave screen to scanout shared linear pixmap
+
+       if synchronized, repeat above and setup for flipping between
+       shared pixmaps
+
+       set the master screen to do dirty updates to the shared pixmap(s)
+       from the screen pixmap.
     */
 
     mscreenpix = master->GetScreenPixmap(master);
@@ -450,16 +477,57 @@ rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height,
         return TRUE;
     }
 
-    spix = rrCreateSharedPixmap(crtc, master,
-                                width, height, depth,
-                                x, y, rotation);
-    if (spix == NULL) {
+    spix_front = rrCreateSharedPixmap(crtc, master,
+                                      width, height, depth,
+                                      x, y, rotation);
+    if (spix_front == NULL) {
         return FALSE;
     }
 
-    crtc->scanout_pixmap = spix;
+    crtc->scanout_pixmap = spix_front;
+
+    /* Both source and sink must support required ABI funcs for flipping */
+    if (pSlaveScrPriv->rrEnableSharedPixmapFlipping &&
+        pSlaveScrPriv->rrDisableSharedPixmapFlipping &&
+        pMasterScrPriv->rrStartFlippingPixmapTracking &&
+        master->PresentSharedPixmap &&
+        master->StopFlippingPixmapTracking) {
+
+        PixmapPtr spix_back = rrCreateSharedPixmap(crtc, master,
+                                                   width, height, depth,
+                                                   x, y, rotation);
+        if (spix_back == NULL)
+            goto fail;
+
+        crtc->scanout_pixmap_back = spix_back;
+
+        if (!pSlaveScrPriv->rrEnableSharedPixmapFlipping(crtc))
+            goto fail;
+
+        if (!pMasterScrPriv->rrStartFlippingPixmapTracking(crtc, mscreenpix,
+                                                          spix_front,
+                                                          spix_back,
+                                                          x, y, 0, 0,
+                                                          rotation)) {
+            pSlaveScrPriv->rrDisableSharedPixmapFlipping(crtc);
+            goto fail;
+        }
+
+        master->PresentSharedPixmap(spix_front);
+
+        return TRUE;
+
+fail: /* If flipping funcs fail, just fall back to unsynchronized */
+        if (crtc->scanout_pixmap_back) {
+            rrDestroySharedPixmap(crtc, crtc->scanout_pixmap_back);
+            crtc->scanout_pixmap_back = NULL;
+        }
+    }
+
+    ErrorF("randr: falling back to unsynchronized pixmap sharing\n");
+
+    master->StartPixmapTracking(mscreenpix, spix_front, x, y, 0, 0, rotation);
 
-    master->StartPixmapTracking(mscreenpix, spix, x, y, 0, 0, rotation);
     return TRUE;
 }
 
-- 
1.9.1



More information about the xorg-devel mailing list