diff options
author | Michel Dänzer <daenzer@vmware.com> | 2009-02-27 16:37:28 +0100 |
---|---|---|
committer | Michel Dänzer <daenzer@vmware.com> | 2009-02-27 16:37:28 +0100 |
commit | 4cfb36f6ad2df01215028fec48d99239a0e4496b (patch) | |
tree | ea547b39c0e7ab0248bed546e689c7bbd478b429 | |
parent | 4bf707f01822abe99286909fd561da7e7a4211d6 (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.c | 13 | ||||
-rw-r--r-- | exa/exa.h | 14 | ||||
-rw-r--r-- | exa/exa_unaccel.c | 25 |
3 files changed, 51 insertions, 1 deletions
@@ -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. @@ -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, ®ion); + /* 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 (®ion, pSrc, pMask, pDst, xSrc, ySrc, xMask, yMask, xDst, yDst, width, height)) return; exaGetDrawableDeltas (pDst->pDrawable, exaGetDrawablePixmap(pDst->pDrawable), &xoff, &yoff); REGION_TRANSLATE(pScreen, ®ion, xoff, yoff); + if (pDst->alphaMap && pDst->alphaMap->pDrawable) + exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX0, + ®ion); + exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, ®ion); - } 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, ®ion); } void ExaCheckAddTraps (PicturePtr pPicture, |