[PATCH v4 03/13] randr/xf86: Add PRIME Synchronization / Double Buffer
Alex Goins
agoins at nvidia.com
Fri Mar 4 02:47:48 UTC 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
v4: Detach scanout pixmap when destroying scanout_pixmap_back, to avoid
dangling pointers in some drivers
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 | 100 +++++++++++++++++++++++++++++++++++------
4 files changed, 95 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..4992c5e 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,63 @@ 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) {
+ /* Destroying a scanout pixmap could break some drivers */
+ pSlaveScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
+
+ rrDestroySharedPixmap(crtc, crtc->scanout_pixmap_back);
+ crtc->scanout_pixmap_back = NULL;
+
+ /* Restore first scanout pixmap */
+ pSlaveScrPriv->rrCrtcSetScanoutPixmap(crtc, crtc->scanout_pixmap);
+ }
+ }
+
+ 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