[PATCH 05/11] randr/xf86: Add PRIME Synchronization / Double Buffer

Alex Goins agoins at nvidia.com
Wed Nov 25 18:39:29 PST 2015


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.

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.

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                 | 71 ++++++++++++++++++++++++++++++++++++------
 4 files changed, 69 insertions(+), 11 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 6e459ed..ef8c63e 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -385,10 +385,26 @@ RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc)
     mscreenpix = master->GetScreenPixmap(master);
 
     pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
+
     if (crtc->scanout_pixmap) {
+        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 +447,18 @@ rrSetupPixmapSharing(RRCrtcPtr crtc, int width, int height,
     PixmapPtr mscreenpix;
     PixmapPtr protopix = master->GetScreenPixmap(master);
     rrScrPriv(crtc->pScreen);
-    PixmapPtr spix;
+    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 +471,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->PresentTrackedFlippingPixmap &&
+        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->PresentTrackedFlippingPixmap(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