summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-06-21 11:43:09 +0100
committerDave Airlie <airlied@redhat.com>2012-06-21 13:54:48 +0100
commitf74509960ecb379012ce134c2a48d53a5fb04ec7 (patch)
tree1b3d3a49b00d0c30d99bc08ee4dbfa1ee12ba0ce
parentc4fe8d073993922f477900ebc337d04e7af171f6 (diff)
dri2/randr: add new way to force a front pixmapprime-dri2-hack
After ickle disliked part of my previous attempt this tries to do things via the server and the current modesetting channels. Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--dix/pixmap.c28
-rw-r--r--hw/xfree86/dri2/dri2.c67
-rw-r--r--hw/xfree86/modes/xf86Crtc.h2
-rw-r--r--hw/xfree86/modes/xf86RandR12.c3
-rw-r--r--include/pixmap.h2
-rw-r--r--include/scrnintstr.h3
-rw-r--r--randr/randr.c2
-rw-r--r--randr/randrstr.h3
-rw-r--r--randr/rrcrtc.c64
9 files changed, 137 insertions, 37 deletions
diff --git a/dix/pixmap.c b/dix/pixmap.c
index c5c277449..804038f41 100644
--- a/dix/pixmap.c
+++ b/dix/pixmap.c
@@ -220,3 +220,31 @@ Bool PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region)
pScreen->SourceValidate = SourceValidate;
return TRUE;
}
+
+PixmapPtr PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave)
+{
+ PixmapPtr spix;
+ int ret;
+ int fd_handle;
+ ScreenPtr master = pixmap->drawable.pScreen;
+ int depth = pixmap->drawable.depth;
+
+ ret = master->SharePixmapBacking(pixmap, &fd_handle);
+ if (ret == FALSE)
+ return NULL;
+
+ spix = slave->CreatePixmap(slave, 0, 0, depth,
+ CREATE_PIXMAP_USAGE_SHARED);
+ slave->ModifyPixmapHeader(spix, pixmap->drawable.width,
+ pixmap->drawable.height, depth, 0,
+ pixmap->devKind, NULL);
+
+ ret = slave->SetSharedPixmapBacking(spix, fd_handle);
+ if (ret == FALSE) {
+ slave->DestroyPixmap(spix);
+ return NULL;
+ }
+
+ spix->master_pixmap = pixmap;
+ return spix;
+}
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 1176878b7..7a3dd6628 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -99,6 +99,7 @@ typedef struct _DRI2Drawable {
unsigned long serialNumber;
Bool needInvalidate;
int prime_id;
+ PixmapPtr redirectpixmap;
} DRI2DrawableRec, *DRI2DrawablePtr;
typedef struct _DRI2Screen {
@@ -231,7 +232,7 @@ DRI2AllocateDrawable(DrawablePtr pDraw)
xorg_list_init(&pPriv->reference_list);
pPriv->serialNumber = DRI2DrawableSerial(pDraw);
pPriv->needInvalidate = FALSE;
-
+ pPriv->redirectpixmap = NULL;
if (pDraw->type == DRAWABLE_WINDOW) {
pWin = (WindowPtr) pDraw;
dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
@@ -398,6 +399,12 @@ DRI2DrawableGone(pointer p, XID id)
free(pPriv->buffers);
}
+ if (pPriv->redirectpixmap) {
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
+ (*pDraw->pScreen->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, FALSE);
+ (*pDraw->pScreen->DestroyPixmap)(pPriv->redirectpixmap);
+ }
+
free(pPriv);
return Success;
@@ -745,31 +752,52 @@ DrawablePtr DRI2UpdatePrime(DrawablePtr pDraw, DRI2BufferPtr pDest)
ScreenPtr master, slave;
int fd_handle;
Bool ret;
-
+ Bool set_front = FALSE;
master = mpix->drawable.pScreen;
- ret = master->SharePixmapBacking(mpix, &fd_handle);
- if (ret == FALSE) {
- ErrorF("share pixmap backing failed\n");
- return;
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr)pDraw;
+ PixmapPtr pPixmap = pDraw->pScreen->GetWindowPixmap(pWin);
+ DRI2ScreenPtr ds;
+
+ if (pDraw->pScreen->GetScreenPixmap(pDraw->pScreen) == pPixmap) {
+ if (pPriv->redirectpixmap &&
+ pPriv->redirectpixmap->drawable.width == pDraw->width &&
+ pPriv->redirectpixmap->drawable.height == pDraw->height &&
+ pPriv->redirectpixmap->drawable.depth == pDraw->depth) {
+ mpix = pPriv->redirectpixmap;
+ } else {
+ ErrorF("creating redirect pixmap\n");
+ ds = DRI2GetScreen(master);
+
+ if (master->ReplaceScanoutPixmap) {
+ mpix = (*master->CreatePixmap)(master, pDraw->width, pDraw->height,
+ pDraw->depth, CREATE_PIXMAP_USAGE_SHARED);
+ if (!mpix)
+ return NULL;
+
+ set_front = TRUE;
+ pPriv->redirectpixmap = mpix;
+ } else
+ return NULL;
+ }
+ } else if (pPriv->redirectpixmap) {
+ ErrorF("destroying redirect pixmap\n");
+ (*master->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, FALSE);
+ (*mpix->drawable.pScreen->DestroyPixmap)(pPriv->redirectpixmap);
+ pPriv->redirectpixmap = NULL;
+ }
}
slave = GetScreenPrime(pDraw->pScreen, pPriv->prime_id);
- spix = slave->CreatePixmap(slave, 0, 0, (pDest->format != 0) ? pDest->format : mpix->drawable.depth, CREATE_PIXMAP_USAGE_SHARED);
- if (!spix) {
- ErrorF("failed to create pixmap for sharing\n");
- return;
- }
+ spix = PixmapShareToSlave(mpix, slave);
+ if (!spix)
+ return NULL;
- slave->ModifyPixmapHeader(spix, mpix->drawable.width,
- mpix->drawable.height,
- (pDest->format != 0) ? pDest->format : mpix->drawable.depth,
- 0, mpix->devKind, NULL);
- ret = slave->SetSharedPixmapBacking(spix, fd_handle);
- if (ret == FALSE) {
- ErrorF("failed to set pixmap backing store\n");
- return FALSE;
+ if (set_front) {
+ (*master->ReplaceScanoutPixmap)(pDraw, pPriv->redirectpixmap, TRUE);
}
#ifdef COMPOSITE
spix->screen_x = mpix->screen_x;
@@ -793,7 +821,6 @@ static void dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
else
(*ds->CopyRegion) (pDraw, pRegion, pDest, pSrc);
- ErrorF("prime id %d\n", pPriv->prime_id);
/* cause damage to the box */
if (pPriv->prime_id) {
BoxRec box;
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 662157bdc..5686a1e2f 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -377,6 +377,8 @@ struct _xf86Crtc {
* Added in ABI version 4
*/
Bool driverIsPerformingTransform;
+
+ PixmapPtr current_scanout;
};
typedef struct _xf86OutputFuncs {
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 26223cb4f..3a36ade88 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1157,6 +1157,8 @@ xf86RandR12CrtcSet(ScreenPtr pScreen,
if (rotation != crtc->rotation)
changed = TRUE;
+ if (crtc->current_scanout != randr_crtc->scanout_pixmap)
+ changed = TRUE;
transform = RRCrtcGetTransform(randr_crtc);
if ((transform != NULL) != crtc->transformPresent)
changed = TRUE;
@@ -1218,6 +1220,7 @@ xf86RandR12CrtcSet(ScreenPtr pScreen,
*/
crtc->desiredMode = mode;
crtc->desiredRotation = rotation;
+ crtc->current_scanout = randr_crtc->scanout_pixmap;
if (transform) {
crtc->desiredTransform = *transform;
crtc->desiredTransformPresent = TRUE;
diff --git a/include/pixmap.h b/include/pixmap.h
index 6c85a2e5f..413c51c55 100644
--- a/include/pixmap.h
+++ b/include/pixmap.h
@@ -125,4 +125,6 @@ PixmapStopDirtyTracking(PixmapPtr src, PixmapPtr slave_dst);
extern _X_EXPORT Bool
PixmapSyncDirtyHelper(PixmapDirtyUpdatePtr dirty, RegionPtr dirty_region);
+extern _X_EXPORT PixmapPtr
+PixmapShareToSlave(PixmapPtr pixmap, ScreenPtr slave);
#endif /* PIXMAP_H */
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index a65b09ec8..e602017df 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -351,6 +351,8 @@ typedef Bool (*StartPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr,
typedef Bool (*StopPixmapTrackingProcPtr)(PixmapPtr, PixmapPtr);
+typedef Bool (*ReplaceScanoutPixmapProcPtr)(DrawablePtr, PixmapPtr, Bool);
+
typedef struct _Screen {
int myNum; /* index of this instance in Screens[] */
ATOM id;
@@ -508,6 +510,7 @@ typedef struct _Screen {
struct xorg_list offload_slave_list;
struct xorg_list offload_head;
+ ReplaceScanoutPixmapProcPtr ReplaceScanoutPixmap;
} ScreenRec;
static inline RegionPtr
diff --git a/randr/randr.c b/randr/randr.c
index 215974852..c2d4c444a 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -295,7 +295,7 @@ RRScreenInit(ScreenPtr pScreen)
wrap(pScrPriv, pScreen, CloseScreen, RRCloseScreen);
pScreen->ConstrainCursorHarder = RRConstrainCursorHarder;
-
+ pScreen->ReplaceScanoutPixmap = RRReplaceScanoutPixmap;
pScrPriv->numOutputs = 0;
pScrPriv->outputs = NULL;
pScrPriv->numCrtcs = 0;
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 93d74e8f9..dd87feb30 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -668,6 +668,9 @@ extern _X_EXPORT void
extern _X_EXPORT void
RRCrtcDetachScanoutPixmap(RRCrtcPtr crtc);
+extern _X_EXPORT Bool
+ RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable);
+
/*
* Crtc dispatch
*/
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 1ca33a4b8..ba3ff8f0b 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -423,26 +423,12 @@ rrCreateSharedPixmap(RRCrtcPtr crtc, int width, int height,
if (!mpix)
return FALSE;
- ret = master->SharePixmapBacking(mpix, &fd_handle);
- if (ret == FALSE) {
+ spix = PixmapShareToSlave(mpix, crtc->pScreen);
+ if (spix == NULL) {
master->DestroyPixmap(mpix);
return FALSE;
}
- spix = crtc->pScreen->CreatePixmap(crtc->pScreen, 0, 0, depth,
- CREATE_PIXMAP_USAGE_SHARED);
- crtc->pScreen->ModifyPixmapHeader(spix, width, height, depth, 0,
- mpix->devKind, NULL);
-
- ret = crtc->pScreen->SetSharedPixmapBacking(spix, fd_handle);
- if (ret == FALSE) {
- ErrorF("failed to slave pixmap\n");
- crtc->pScreen->DestroyPixmap(spix);
- master->DestroyPixmap(mpix);
- return FALSE;
- }
-
- spix->master_pixmap = mpix;
ret = pScrPriv->rrCrtcSetScanoutPixmap(crtc, spix);
if (ret == FALSE) {
ErrorF("failed to set shadow slave pixmap\n");
@@ -1658,3 +1644,49 @@ RRConstrainCursorHarder(DeviceIntPtr pDev, ScreenPtr pScreen, int mode, int *x,
return;
}
}
+
+Bool
+RRReplaceScanoutPixmap(DrawablePtr pDrawable, PixmapPtr pPixmap, Bool enable)
+{
+ rrScrPriv(pDrawable->pScreen);
+ int i;
+ Bool size_fits = FALSE;
+ Bool changed = FALSE;
+ for (i = 0; i < pScrPriv->numCrtcs; i++) {
+ RRCrtcPtr crtc = pScrPriv->crtcs[i];
+
+ if (!crtc->mode)
+ continue;
+
+ changed = FALSE;
+ if (crtc->x == pDrawable->x &&
+ crtc->y == pDrawable->y &&
+ crtc->mode->mode.width == pDrawable->width &&
+ crtc->mode->mode.height == pDrawable->height)
+ size_fits = TRUE;
+
+ if (crtc->scanout_pixmap == pPixmap) {
+ if (size_fits)
+ return;
+ if (enable == FALSE) {
+ pScrPriv->rrCrtcSetScanoutPixmap(crtc, NULL);
+ crtc->scanout_pixmap = NULL;
+ changed = TRUE;
+ }
+ } else {
+ if (!size_fits)
+ return;
+ if (enable) {
+ crtc->scanout_pixmap = pPixmap;
+ pScrPriv->rrCrtcSetScanoutPixmap(crtc, pPixmap);
+ changed = TRUE;
+ }
+ }
+
+ if (changed && pScrPriv->rrCrtcSet) {
+ (*pScrPriv->rrCrtcSet) (pDrawable->pScreen, crtc, crtc->mode, crtc->x, crtc->y,
+ crtc->rotation, crtc->numOutputs, crtc->outputs);
+
+ }
+ }
+}