summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <daenzer@vmware.com>2009-02-27 16:37:28 +0100
committerMichel Dänzer <daenzer@vmware.com>2009-02-27 16:37:28 +0100
commit4cfb36f6ad2df01215028fec48d99239a0e4496b (patch)
treeea547b39c0e7ab0248bed546e689c7bbd478b429
parent4bf707f01822abe99286909fd561da7e7a4211d6 (diff)
EXA: Handle separate alpha maps properly in Composite fallback, take two.
Preserve the EXA ABI by introducing a new driver flag EXA_SUPPORTS_PREPARE_AUX. If the driver doesn't set this flag, we have to assume any Prepare/FinishAccess driver hooks can't handle the EXA_PREPARE_AUX* indices, so we move out such pixmaps at PrepareAccess time. Fixes https://bugs.freedesktop.org/show_bug.cgi?id=18710 . Signed-off-by: Michel Dänzer <daenzer@vmware.com>
-rw-r--r--exa/exa.c13
-rw-r--r--exa/exa.h14
-rw-r--r--exa/exa_unaccel.c25
3 files changed, 51 insertions, 1 deletions
diff --git a/exa/exa.c b/exa/exa.c
index a64769905..5425f902e 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -535,12 +535,18 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
exaWaitSync (pDrawable->pScreen);
if (pExaScr->info->PrepareAccess == NULL)
return;
+ if (index >= EXA_PREPARE_AUX0 &&
+ !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
+ exaMoveOutPixmap (pPixmap);
+ return;
+ }
+
if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
ExaPixmapPriv (pPixmap);
if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
FatalError("Driver failed PrepareAccess on a pinned pixmap\n");
exaMoveOutPixmap (pPixmap);
}
@@ -594,12 +600,19 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
if (pExaScr->info->FinishAccess == NULL)
return;
if (!exaPixmapIsOffscreen (pPixmap))
return;
+ if (index >= EXA_PREPARE_AUX0 &&
+ !(pExaScr->info->flags & EXA_SUPPORTS_PREPARE_AUX)) {
+ ErrorF("EXA bug: Trying to call driver FinishAccess hook with "
+ "unsupported index EXA_PREPARE_AUX*\n");
+ return;
+ }
+
(*pExaScr->info->FinishAccess) (pPixmap, index);
}
/**
* Here begins EXA's GC code.
* Do not ever access the fb/mi layer directly.
diff --git a/exa/exa.h b/exa/exa.h
index 21a0f1abf..12959e127 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -669,12 +669,19 @@ typedef struct _ExaDriver {
#define EXA_PREPARE_SRC 1
/**
* EXA_PREPARE_SRC is the index for a second pixmap that may be read
* from.
*/
#define EXA_PREPARE_MASK 2
+ /**
+ * EXA_PREPARE_AUX* are additional indices for other purposes, e.g.
+ * separate alpha maps with Composite operations.
+ */
+ #define EXA_PREPARE_AUX0 3
+ #define EXA_PREPARE_AUX1 4
+ #define EXA_PREPARE_AUX2 5
/** @} */
/**
* maxPitchPixels controls the pitch limitation for rendering from
* the card.
* The driver should never receive a request for rendering a pixmap
@@ -739,12 +746,19 @@ typedef struct _ExaDriver {
/**
* EXA_HANDLES_PIXMAPS indicates to EXA that the driver can handle
* all pixmap addressing and migration.
*/
#define EXA_HANDLES_PIXMAPS (1 << 3)
+/**
+ * EXA_SUPPORTS_PREPARE_AUX indicates to EXA that the driver can handle the
+ * EXA_PREPARE_AUX* indices in the Prepare/FinishAccess hooks. If there are no
+ * such hooks, this flag has no effect.
+ */
+#define EXA_SUPPORTS_PREPARE_AUX (1 << 4)
+
/** @} */
/* in exa.c */
extern _X_EXPORT ExaDriverPtr
exaDriverAlloc(void);
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index c821f0da8..9a0b0e5af 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -389,27 +389,44 @@ ExaCheckComposite (CARD8 op,
ExaScreenPriv(pScreen);
RegionRec region;
int xoff, yoff;
REGION_NULL(pScreen, &region);
+ /* We need to prepare access to any separate alpha maps first, in case the
+ * driver doesn't support EXA_PREPARE_AUX*, in which case EXA_PREPARE_SRC
+ * may be used for moving them out.
+ */
+ if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
+ exaPrepareAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
+ if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
+ exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
+
if (!exaOpReadsDestination(op)) {
if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
xSrc, ySrc, xMask, yMask, xDst, yDst,
width, height))
return;
exaGetDrawableDeltas (pDst->pDrawable,
exaGetDrawablePixmap(pDst->pDrawable),
&xoff, &yoff);
REGION_TRANSLATE(pScreen, &region, xoff, yoff);
+ if (pDst->alphaMap && pDst->alphaMap->pDrawable)
+ exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0,
+ &region);
+
exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, &region);
- } else
+ } else {
+ if (pDst->alphaMap && pDst->alphaMap->pDrawable)
+ exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
+
exaPrepareAccess (pDst->pDrawable, EXA_PREPARE_DEST);
+ }
EXA_FALLBACK(("from picts %p/%p to pict %p\n",
pSrc, pMask, pDst));
if (pSrc->pDrawable != NULL)
exaPrepareAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
@@ -430,15 +447,21 @@ ExaCheckComposite (CARD8 op,
width,
height);
swap(pExaScr, ps, Composite);
#endif /* RENDER */
if (pMask && pMask->pDrawable != NULL)
exaFinishAccess (pMask->pDrawable, EXA_PREPARE_MASK);
+ if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
+ exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX1);
if (pSrc->pDrawable != NULL)
exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
+ if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
+ exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX2);
exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST);
+ if (pDst->alphaMap && pDst->alphaMap->pDrawable)
+ exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0);
REGION_UNINIT(pScreen, &region);
}
void
ExaCheckAddTraps (PicturePtr pPicture,