[PATCH v2 2/8] randr/xf86: Add PRIME Synchronization / Double Buffer

Alex Goins agoins at nvidia.com
Tue Jan 5 13:56:00 PST 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

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                 | 80 ++++++++++++++++++++++++++++++++++--------
 4 files changed, 74 insertions(+), 15 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 472721a..c6b0627 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 ec26fcd..62ed311 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.
@@ -383,14 +380,32 @@ rrDestroySharedPixmap(RRCrtcPtr crtc, PixmapPtr pPixmap) {
 void
 RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
 {
-    ScreenPtr master = crtc->pScreen->current_master;
     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) {
+            crtc->pScreen->DisableSharedPixmapFlipping(crtc->devPrivate);
+
+            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);
 }
 
@@ -431,14 +446,20 @@ rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height,
     ScreenPtr master = crtc->pScreen->current_master;
     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);
@@ -451,16 +472,47 @@ 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 (crtc->pScreen->EnableSharedPixmapFlipping &&
+        crtc->pScreen->DisableSharedPixmapFlipping &&
+        master->StartFlippingPixmapTracking &&
+        master->PresentSharedPixmap &&
+        master->StopFlippingPixmapTracking) {
+
+        PixmapPtr spix_back = rrCreateSharedPixmap(crtc, master,
+                                                   width, height, depth,
+                                                   x, y, rotation);
+        if (spix_back == NULL) {
+            goto nosync;
+        }
+
+        crtc->scanout_pixmap_back = spix_back;
+
+        crtc->pScreen->EnableSharedPixmapFlipping(crtc->devPrivate);
+
+        master->StartFlippingPixmapTracking(mscreenpix,
+                                            spix_front, spix_back,
+                                            x, y, 0, 0, rotation);
+
+        master->PresentSharedPixmap(spix_front);
+
+        return TRUE;
+    }
+
+nosync:
+    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