diff options
-rw-r--r-- | hw/xfree86/modes/xf86Crtc.h | 4 | ||||
-rw-r--r-- | hw/xfree86/modes/xf86RandR12.c | 4 | ||||
-rw-r--r-- | randr/randrstr.h | 1 | ||||
-rw-r--r-- | randr/rrcrtc.c | 131 |
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 && |