summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/xfree86/modes/xf86Crtc.h4
-rw-r--r--hw/xfree86/modes/xf86RandR12.c4
-rw-r--r--randr/randrstr.h1
-rw-r--r--randr/rrcrtc.c131
4 files changed, 111 insertions, 29 deletions
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index fb1dd4f31..14ba9d714 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -405,6 +405,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 4a21766e0..9f932705f 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 3e37df7d7..ada1348d2 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 ea91ab703..089fc1a79 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.
@@ -387,11 +384,29 @@ 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) {
+ pScrPriv->rrDisableSharedPixmapFlipping(crtc);
+
+ master->StopFlippingPixmapTracking(mscreenpix,
+ crtc->scanout_pixmap,
+ crtc->scanout_pixmap_back);
+
+ rrDestroySharedPixmap(crtc, crtc->scanout_pixmap_back);
+ crtc->scanout_pixmap_back = NULL;
+ }
+ else {
+ pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
+ master->StopPixmapTracking(mscreenpix, crtc->scanout_pixmap);
+ }
+
rrDestroySharedPixmap(crtc, crtc->scanout_pixmap);
+ crtc->scanout_pixmap = NULL;
}
- crtc->scanout_pixmap = NULL;
+
RRCrtcChanged(crtc, TRUE);
}
@@ -400,9 +415,7 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, ScreenPtr master,
int width, int height, int depth,
int x, int y, Rotation rotation)
{
- Bool ret;
PixmapPtr mpix, spix;
- rrScrPriv(crtc->pScreen);
mpix = master->CreatePixmap(master, width, height, depth,
CREATE_PIXMAP_USAGE_SHARED);
@@ -415,13 +428,6 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, ScreenPtr master,
return NULL;
}
- ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix);
- if (ret == FALSE) {
- rrDestroySharedPixmap(crtc, spix);
- ErrorF("randr: failed to set shadow slave pixmap\n");
- return NULL;
- }
-
return spix;
}
@@ -430,16 +436,30 @@ 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;
-
- /* 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
+ 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.
+
+ If sync == FALSE --
+ Set slave screen to scanout shared linear pixmap.
+ Set the master screen to do dirty updates to the shared pixmap
+ from the screen pixmap on its own accord.
+
+ If sync == TRUE --
+ If any of the below steps fail, clean up and fall back to sync == FALSE.
+ Create another shared pixmap on the slave screen using the handle.
+ Set slave screen to prepare for scanout and flipping between shared
+ linear pixmaps.
+ Set the master screen to do dirty updates to the shared pixmaps from the
+ screen pixmap when prompted to by us or the slave.
+ Prompt the master to do a dirty update on the first shared pixmap, then
+ defer to the slave.
*/
mscreenpix = master->GetScreenPixmap(master);
@@ -452,16 +472,65 @@ 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;
+ /* 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;
+
+ if (!pSlaveScrPriv->rrEnableSharedPixmapFlipping(crtc,
+ spix_front, spix_back))
+ goto fail;
+
+ crtc->scanout_pixmap = spix_front;
+ crtc->scanout_pixmap_back = spix_back;
+
+ 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 (spix_back)
+ rrDestroySharedPixmap(crtc, spix_back);
+
+ crtc->scanout_pixmap = NULL;
+ crtc->scanout_pixmap_back = NULL;
+ }
+
+ ErrorF("randr: falling back to unsynchronized pixmap sharing\n");
+
+ if (!pSlaveScrPriv->rrCrtcSetScanoutPixmap(crtc, spix_front)) {
+ rrDestroySharedPixmap(crtc, spix_front);
+ ErrorF("randr: failed to set shadow slave pixmap\n");
+ return FALSE;
+ }
+ crtc->scanout_pixmap = spix_front;
+
+ master->StartPixmapTracking(mscreenpix, spix_front, x, y, 0, 0, rotation);
- master->StartPixmapTracking(mscreenpix, spix, x, y, 0, 0, rotation);
return TRUE;
}
@@ -1751,6 +1820,12 @@ RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
if (!crtc->scanout_pixmap && !enable)
continue;
+ /* not supported with double buffering, needs ABI change for 2 ppix */
+ if (crtc->scanout_pixmap_back) {
+ ret = FALSE;
+ continue;
+ }
+
size_fits = (crtc->mode &&
crtc->x == pDrawable->x &&
crtc->y == pDrawable->y &&