xserver: Branch 'master' - 6 commits

Maarten Maathuis madman2003 at kemper.freedesktop.org
Wed Mar 4 07:53:32 PST 2009


 exa/exa.c           |  215 +++++++++++++++++++++++++++++++++++++++++-----------
 exa/exa.h           |    5 +
 exa/exa_migration.c |   32 ++-----
 exa/exa_priv.h      |   16 +++
 exa/exa_unaccel.c   |   12 +-
 5 files changed, 211 insertions(+), 69 deletions(-)

New commits:
commit ce6e1771be5f2c21af6f72a9705795df26210413
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Mon Mar 2 17:05:28 2009 +0100

    exa: fix a serious issue in exaChangeWindowAttributes (and some more related things)
    
    - fbChangeWindowAttributes can create pixmaps (and access them) without use preparing access.
    - Also handle the destroyed pixmaps by finishing them first.
    - Switch to DEST indices again in exaCreatePixmapWithPrepare, because they are obviously being rendered to.
    - Also avoid calling FinishAccess on pixmaps that are destroyed (and their memory potentially invalid).

diff --git a/exa/exa.c b/exa/exa.c
index d4a3cd7..b5f3542 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -743,11 +743,46 @@ exaCreatePixmapWithPrepare(ScreenPtr pScreen, int w, int h, int depth,
     if (!pPixmap)
 	return NULL;
 
-    exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_SRC);
+    /* Note the usage of ExaDoPrepareAccess, this allowed because:
+     * The pixmap is new, so not offscreen in the classic exa case.
+     * For EXA_HANDLES_PIXMAPS the driver will handle whatever is needed.
+     * We want to signal that the pixmaps will be used as destination.
+     */
+    if (pExaScr->prepare_access[EXA_PREPARE_DEST] == NULL) {
+	ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
+	pExaScr->prepare_access[EXA_PREPARE_DEST] = pPixmap;
+    } else if (pExaScr->prepare_access[EXA_PREPARE_AUX_DEST] == NULL) {
+	ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+	pExaScr->prepare_access[EXA_PREPARE_AUX_DEST] = pPixmap;
+    } else {
+	FatalError("exaCreatePixmapWithPrepare can only accomodate two pixmaps, we're at three.\n");
+    }
 
     return pPixmap;
 }
 
+static Bool
+exaDestroyPixmapWithFinish(PixmapPtr pPixmap)
+{
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
+    ExaScreenPriv(pScreen);
+    int i;
+    Bool ret;
+
+    for (i = 0; i < 6; i++)
+	if (pExaScr->prepare_access[i] == pPixmap)
+	    exaFinishAccess(&pPixmap->drawable, i);
+
+    /* This swaps between this function and the real upper layer function.
+     * Normally this would swap to the fb layer pointer, this is a very special case.
+     */
+    swap(pExaScr, pScreen, DestroyPixmap);
+    ret = pScreen->DestroyPixmap(pPixmap);
+    swap(pExaScr, pScreen, DestroyPixmap);
+
+    return ret;
+}
+
 static void
 exaValidateGC(GCPtr pGC,
 		unsigned long changes,
@@ -760,6 +795,7 @@ exaValidateGC(GCPtr pGC,
     ScreenPtr pScreen = pDrawable->pScreen;
     ExaScreenPriv(pScreen);
     CreatePixmapProcPtr old_ptr = NULL;
+    DestroyPixmapProcPtr old_ptr2 = NULL;
     PixmapPtr pTile = NULL;
     EXA_GC_PROLOGUE(pGC);
 
@@ -768,6 +804,11 @@ exaValidateGC(GCPtr pGC,
     /* create a new upper layer pointer. */
     wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmapWithPrepare);
 
+    /* save the "fb" pointer. */
+    old_ptr2 = pExaScr->SavedDestroyPixmap;
+    /* create a new upper layer pointer. */
+    wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmapWithFinish);
+
     /* Either of these conditions is enough to trigger access to a tile pixmap. */
     /* With pGC->tileIsPixel == 1, you run the risk of dereferencing an invalid tile pixmap pointer. */
     if (pGC->fillStyle == FillTiled || ((changes & GCTile) && !pGC->tileIsPixel)) {
@@ -792,8 +833,8 @@ exaValidateGC(GCPtr pGC,
 
     (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
 
-    if (pTile)
-	exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC);
+    if (pExaScr->prepare_access[EXA_PREPARE_SRC]) /* tile */
+	exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_SRC]->drawable, EXA_PREPARE_SRC);
     if (pGC->stipple)
         exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
 
@@ -802,9 +843,18 @@ exaValidateGC(GCPtr pGC,
     /* restore copy of fb layer pointer. */
     pExaScr->SavedCreatePixmap = old_ptr;
 
-    if (pGC->fillStyle == FillTiled && pTile != pGC->tile.pixmap)
-	exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_AUX_SRC);
-    
+    /* switch back to the normal upper layer. */
+    unwrap(pExaScr, pScreen, DestroyPixmap);
+    /* restore copy of fb layer pointer. */
+    pExaScr->SavedDestroyPixmap = old_ptr2;
+
+    if (pExaScr->prepare_access[EXA_PREPARE_DEST])
+	exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_DEST]->drawable,
+		EXA_PREPARE_DEST);
+    if (pExaScr->prepare_access[EXA_PREPARE_AUX_DEST])
+	exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_AUX_DEST]->drawable,
+		EXA_PREPARE_AUX_DEST);
+
     EXA_GC_EPILOGUE(pGC);
 }
 
@@ -891,22 +941,50 @@ exaChangeWindowAttributes(WindowPtr pWin, unsigned long mask)
     Bool ret;
     ScreenPtr pScreen = pWin->drawable.pScreen;
     ExaScreenPriv(pScreen);
+    CreatePixmapProcPtr old_ptr = NULL;
+    DestroyPixmapProcPtr old_ptr2 = NULL;
+
+    /* save the "fb" pointer. */
+    old_ptr = pExaScr->SavedCreatePixmap;
+    /* create a new upper layer pointer. */
+    wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmapWithPrepare);
+
+    /* save the "fb" pointer. */
+    old_ptr2 = pExaScr->SavedDestroyPixmap;
+    /* create a new upper layer pointer. */
+    wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmapWithFinish);
 
     if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 
-        exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
+	exaPrepareAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
 
     if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
-        exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
+	exaPrepareAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
 
     swap(pExaScr, pScreen, ChangeWindowAttributes);
     ret = pScreen->ChangeWindowAttributes(pWin, mask);
     swap(pExaScr, pScreen, ChangeWindowAttributes);
 
-    if ((mask & CWBorderPixmap) && pWin->borderIsPixel == FALSE)
-        exaFinishAccess(&pWin->border.pixmap->drawable, EXA_PREPARE_MASK);
+    if (pExaScr->prepare_access[EXA_PREPARE_SRC]) /* background */
+	exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_SRC]->drawable, EXA_PREPARE_SRC);
+    if (pExaScr->prepare_access[EXA_PREPARE_MASK]) /* border */
+	exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_MASK]->drawable, EXA_PREPARE_MASK);
 
-    if ((mask & CWBackPixmap) && pWin->backgroundState == BackgroundPixmap) 
-        exaFinishAccess(&pWin->background.pixmap->drawable, EXA_PREPARE_SRC);
+    /* switch back to the normal upper layer. */
+    unwrap(pExaScr, pScreen, CreatePixmap);
+    /* restore copy of fb layer pointer. */
+    pExaScr->SavedCreatePixmap = old_ptr;
+
+    /* switch back to the normal upper layer. */
+    unwrap(pExaScr, pScreen, DestroyPixmap);
+    /* restore copy of fb layer pointer. */
+    pExaScr->SavedDestroyPixmap = old_ptr2;
+
+    if (pExaScr->prepare_access[EXA_PREPARE_DEST])
+	exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_DEST]->drawable,
+		EXA_PREPARE_DEST);
+    if (pExaScr->prepare_access[EXA_PREPARE_AUX_DEST])
+	exaFinishAccess(&pExaScr->prepare_access[EXA_PREPARE_AUX_DEST]->drawable,
+		EXA_PREPARE_AUX_DEST);
 
     return ret;
 }
commit 7fb68e8b31d259325ce311ad67befc43a933f009
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Sat Feb 28 22:29:42 2009 +0100

    exa: remove a few pExaPixmap checks.
    
    - And make some fatal for a debug build.

diff --git a/exa/exa_migration.c b/exa/exa_migration.c
index 8b91150..f6805cb 100644
--- a/exa/exa_migration.c
+++ b/exa/exa_migration.c
@@ -43,16 +43,18 @@
 
 /**
  * Returns TRUE if the pixmap is not movable.  This is the case where it's a
- * fake pixmap for the frontbuffer (no pixmap private) or it's a scratch
- * pixmap created by some other X Server internals (the score says it's
- * pinned).
+ * pixmap which has no private (almost always bad) or it's a scratch pixmap created by
+ * some X Server internal component (the score says it's pinned).
  */
 static Bool
 exaPixmapIsPinned (PixmapPtr pPix)
 {
     ExaPixmapPriv (pPix);
 
-    return pExaPixmap == NULL || pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
+    if (pExaPixmap == NULL)
+	EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsPinned was called on a non-exa pixmap.\n"), TRUE);
+
+    return pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED;
 }
 
 /**
@@ -86,8 +88,10 @@ exaPixmapIsDirty (PixmapPtr pPix)
 {
     ExaPixmapPriv (pPix);
 
-    return pExaPixmap == NULL ||
-	REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)) ||
+    if (pExaPixmap == NULL)
+	EXA_FatalErrorDebugWithRet(("EXA bug: exaPixmapIsDirty was called on a non-exa pixmap.\n"), TRUE);
+
+    return REGION_NOTEMPTY (pScreen, DamageRegion(pExaPixmap->pDamage)) ||
 	!REGION_EQUAL(pScreen, &pExaPixmap->validSys, &pExaPixmap->validFB);
 }
 
@@ -460,13 +464,6 @@ exaMigrateTowardFb (ExaMigrationPtr migrate)
     PixmapPtr pPixmap = migrate->pPix;
     ExaPixmapPriv (pPixmap);
 
-    if (pExaPixmap == NULL) {
-	DBG_MIGRATE(("UseScreen: ignoring exa-uncontrolled pixmap %p (%s)\n",
-		     (pointer)pPixmap,
-		     exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
-	return;
-    }
-
     if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED) {
 	DBG_MIGRATE(("UseScreen: not migrating pinned pixmap %p\n",
 		     (pointer)pPixmap));
@@ -507,13 +504,6 @@ exaMigrateTowardSys (ExaMigrationPtr migrate)
     PixmapPtr pPixmap = migrate->pPix;
     ExaPixmapPriv (pPixmap);
 
-    if (pExaPixmap == NULL) {
-	DBG_MIGRATE(("UseMem: ignoring exa-uncontrolled pixmap %p (%s)\n",
-		     (pointer)pPixmap,
-		     exaPixmapIsOffscreen(pPixmap) ? "s" : "m"));
-	return;
-    }
-
     DBG_MIGRATE(("UseMem: %p score %d\n", (pointer)pPixmap, pExaPixmap->score));
 
     if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
@@ -625,6 +615,8 @@ exaDoMigration (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
 
     if (pExaScr->info->flags & EXA_HANDLES_PIXMAPS)
         return;
+    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+	return;
 
     /* If this debugging flag is set, check each pixmap for whether it is marked
      * as clean, and if so, actually check if that's the case.  This should help
commit bd2f35ef0d4b8c56eb205b8694b4fe5d2fa2c049
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Sat Feb 28 22:15:04 2009 +0100

    exa: fix unwrapping of ModifyPixmapHeader upon CloseScreen.
    
    - Cleanup wrapping too.

diff --git a/exa/exa.c b/exa/exa.c
index 0ecbcf7..d4a3cd7 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -978,6 +978,8 @@ exaCloseScreen(int i, ScreenPtr pScreen)
 	unwrap(pExaScr, pScreen, CreatePixmap);
     if (pExaScr->SavedDestroyPixmap)
 	unwrap(pExaScr, pScreen, DestroyPixmap);
+    if (pExaScr->SavedModifyPixmapHeader)
+	unwrap(pExaScr, pScreen, ModifyPixmapHeader);
     unwrap(pExaScr, pScreen, CopyWindow);
     unwrap(pExaScr, pScreen, ChangeWindowAttributes);
     unwrap(pExaScr, pScreen, BitmapToRegion);
@@ -1104,7 +1106,6 @@ exaDriverInit (ScreenPtr		pScreen,
 #endif
 
     pExaScr = xcalloc (sizeof (ExaScreenPrivRec), 1);
-
     if (!pExaScr) {
         LogMessage(X_WARNING, "EXA(%d): Failed to allocate screen private\n",
 		   pScreen->myNum);
@@ -1169,8 +1170,7 @@ exaDriverInit (ScreenPtr		pScreen,
 	wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap);
 	wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap);
 
-	pExaScr->SavedModifyPixmapHeader = pScreen->ModifyPixmapHeader;
-	pScreen->ModifyPixmapHeader = exaModifyPixmapHeader;
+	wrap(pExaScr, pScreen, ModifyPixmapHeader, exaModifyPixmapHeader);
 	if (!pExaScr->info->CreatePixmap) {
 	    LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
 		       pScreen->myNum,
commit da8ea41a542787691ea1120e5c8c7dc3182cbea5
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Sat Feb 28 21:59:09 2009 +0100

    exa: increase/rework safety checks in Prepare/FinishAccess.

diff --git a/exa/exa.c b/exa/exa.c
index f4fba57..0ecbcf7 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -450,15 +450,28 @@ exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
 	}
     }
 
-
     if (pExaScr->info->ModifyPixmapHeader) {
 	ret = pExaScr->info->ModifyPixmapHeader(pPixmap, width, height, depth,
 						bitsPerPixel, devKind, pPixData);
+	/* For EXA_HANDLES_PIXMAPS, we set pPixData to NULL.
+	 * If pPixmap->devPrivate.ptr is non-NULL, then we've got a non-offscreen pixmap.
+	 * We need to store the pointer, because PrepareAccess won't be called.
+	 */
+	if (!pPixData && pPixmap->devPrivate.ptr && pPixmap->devKind) {
+	    pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+	    pExaPixmap->sys_pitch = pPixmap->devKind;
+	}
 	if (ret == TRUE)
-	    return ret;
+	    goto out;
     }
-    return pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
+    ret = pExaScr->SavedModifyPixmapHeader(pPixmap, width, height, depth,
 					    bitsPerPixel, devKind, pPixData);
+
+out:
+    /* Always NULL this, we don't want lingering pointers. */
+    pPixmap->devPrivate.ptr = NULL;
+
+    return ret;
 }
 
 /**
@@ -523,16 +536,43 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
 Bool
 ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
 {
-    ScreenPtr	    pScreen = pDrawable->pScreen;
-    ExaScreenPriv  (pScreen);
-    PixmapPtr	    pPixmap = exaGetDrawablePixmap (pDrawable);
-    Bool	    offscreen = exaPixmapIsOffscreen(pPixmap);
+    ScreenPtr pScreen = pDrawable->pScreen;
+    ExaScreenPriv (pScreen);
+    PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
+    ExaPixmapPriv(pPixmap);
+    Bool offscreen;
+
+    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+	return FALSE;
+
+    if (pExaPixmap == NULL)
+	EXA_FatalErrorDebugWithRet(("EXA bug: ExaDoPrepareAccess was called on a non-exa pixmap.\n"), FALSE);
 
-    /* Unhide pixmap pointer */
-    if (pPixmap->devPrivate.ptr == NULL && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
-	pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
+    /* Check if we're dealing SRC == DST or similar.
+     * In that case the first PrepareAccess has already set pPixmap->devPrivate.ptr.
+     */
+    if (pPixmap->devPrivate.ptr != NULL) {
+	int i;
+	for (i = 0; i < 6; i++)
+	    if (pExaScr->prepare_access[i] == pPixmap)
+		break;
+
+	/* No known PrepareAccess or double prepare on the same index. */
+	if (i == 6 || i == index)
+	    EXA_FatalErrorDebug(("EXA bug: pPixmap->devPrivate.ptr was %p, but should have been NULL.\n",
+		pPixmap->devPrivate.ptr));
     }
 
+    offscreen = exaPixmapIsOffscreen(pPixmap);
+
+    if (offscreen)
+	pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
+    else
+	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+
+    /* Store so we can check SRC and DEST being the same. */
+    pExaScr->prepare_access[index] = pPixmap;
+
     if (!offscreen)
 	return FALSE;
 
@@ -548,9 +588,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
     }
 
     if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
-	ExaPixmapPriv (pPixmap);
 	if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
-	    FatalError("Driver failed PrepareAccess on a pinned pixmap\n");
+	    FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
 	exaMoveOutPixmap (pPixmap);
 
 	return FALSE;
@@ -604,10 +643,20 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
     PixmapPtr	    pPixmap = exaGetDrawablePixmap (pDrawable);
     ExaPixmapPriv  (pPixmap);
 
-    /* Rehide pixmap pointer if we're doing that. */
-    if (pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
-	pPixmap->devPrivate.ptr = NULL;
-    }
+    if (!(pExaScr->info->flags & EXA_OFFSCREEN_PIXMAPS))
+	return;
+
+    if (pExaPixmap == NULL)
+	EXA_FatalErrorDebugWithRet(("EXA bug: exaFinishAccesss was called on a non-exa pixmap.\n"),);
+
+    /* Avoid mismatching indices. */
+    if (pExaScr->prepare_access[index] != pPixmap)
+	EXA_FatalErrorDebug(("EXA bug: Calling FinishAccess on pixmap %p with index %d while "
+			"it should have been %p.\n", pPixmap, index, pExaScr->prepare_access[index]));
+    pExaScr->prepare_access[index] = NULL;
+
+    /* We always hide the devPrivate.ptr. */
+    pPixmap->devPrivate.ptr = NULL;
 
     if (pExaScr->info->FinishAccess == NULL)
 	return;
diff --git a/exa/exa.h b/exa/exa.h
index 8339a3e..d7219f0 100644
--- a/exa/exa.h
+++ b/exa/exa.h
@@ -695,6 +695,11 @@ typedef struct _ExaDriver {
     /* Hooks to allow driver to its own pixmap memory management */
     void *(*CreatePixmap)(ScreenPtr pScreen, int size, int align);
     void (*DestroyPixmap)(ScreenPtr pScreen, void *driverPriv);
+    /**
+     * Returning a pixmap with non-NULL devPrivate.ptr implies a pixmap which is
+     * not offscreen, which will never be accelerated and Prepare/FinishAccess won't
+     * be called.
+     */
     Bool (*ModifyPixmapHeader)(PixmapPtr pPixmap, int width, int height,
                               int depth, int bitsPerPixel, int devKind,
                               pointer pPixData);
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index a037eb0..9efbbc9 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -85,6 +85,18 @@ exaDrawableLocation(DrawablePtr pDrawable);
 #define EXA_MAX_FB   FB_OVERLAY_MAX
 #endif
 
+#ifdef DEBUG
+#define EXA_FatalErrorDebug(x) FatalError x
+#define EXA_FatalErrorDebugWithRet(x, ret) FatalError x
+#else
+#define EXA_FatalErrorDebug(x) ErrorF x
+#define EXA_FatalErrorDebugWithRet(x, ret) \
+do { \
+    ErrorF x; \
+    return ret; \
+} while (0)
+#endif
+
 /**
  * This is the list of migration heuristics supported by EXA.  See
  * exaDoMigration() for what their implementations do.
@@ -158,6 +170,10 @@ typedef struct {
     unsigned			 disableFbCount;
     Bool			 optimize_migration;
     unsigned			 offScreenCounter;
+
+    /* Store all accessed pixmaps, so we can check for duplicates. */
+    PixmapPtr prepare_access[6];
+
     /* Holds information on fallbacks that cannot be relayed otherwise. */
     unsigned int fallback_flags;
 
commit 3ea3d505e8128ab3e878edcef697fd5656b0c917
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Sun Mar 1 01:15:28 2009 +0100

    exa: avoid a potential Prepare/FinishAccess inbalance.

diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index d16ecf7..4279c87 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -405,7 +405,7 @@ ExaCheckComposite (CARD8      op,
 	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
 				       xSrc, ySrc, xMask, yMask, xDst, yDst,
 				       width, height))
-	    return;
+	    goto skip;
 
 	exaGetDrawableDeltas (pDst->pDrawable,
 			      exaGetDrawablePixmap(pDst->pDrawable),
@@ -450,16 +450,18 @@ ExaCheckComposite (CARD8      op,
 #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_AUX_MASK);
     if (pSrc->pDrawable != NULL)
 	exaFinishAccess (pSrc->pDrawable, EXA_PREPARE_SRC);
-    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
-	exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
     exaFinishAccess (pDst->pDrawable, EXA_PREPARE_DEST);
     if (pDst->alphaMap && pDst->alphaMap->pDrawable)
 	exaFinishAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
 
+skip:
+    if (pSrc->alphaMap && pSrc->alphaMap->pDrawable)
+	exaFinishAccess(pSrc->alphaMap->pDrawable, EXA_PREPARE_AUX_SRC);
+    if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
+	exaFinishAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
+
     REGION_UNINIT(pScreen, &region);
 }
 
commit 10334cf7e64e2e633cd507f2aa216027e840c8e5
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Sat Feb 28 21:46:00 2009 +0100

    exa: simplify exaPixmapIsOffscreen
    
    - This includes properly handling the framebuffer.

diff --git a/exa/exa.c b/exa/exa.c
index 994a67a..f4fba57 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -73,8 +73,9 @@ unsigned long
 exaGetPixmapOffset(PixmapPtr pPix)
 {
     ExaScreenPriv (pPix->drawable.pScreen);
+    ExaPixmapPriv (pPix);
 
-    return (CARD8 *)ExaGetPixmapAddress(pPix) - pExaScr->info->memoryBase;
+    return (CARD8 *)pExaPixmap->fb_ptr - pExaScr->info->memoryBase;
 }
 
 void *
@@ -424,6 +425,13 @@ exaModifyPixmapHeader(PixmapPtr pPixmap, int width, int height, int depth,
         if (devKind > 0)
             pExaPixmap->sys_pitch = devKind;
 
+	/* Is this the framebuffer (for classic exa)? */
+	if (pPixData && pPixData == pExaScr->info->memoryBase) {
+	    pExaPixmap->fb_ptr = pPixData;
+	    pExaPixmap->fb_pitch = devKind;
+	    pExaPixmap->offscreen = TRUE;
+	}
+
         if (width > 0 && height > 0 && bitsPerPixel > 0) {
             exaSetFbPitch(pExaScr, pExaPixmap,
                           width, height, bitsPerPixel);
@@ -471,22 +479,14 @@ exaPixmapIsOffscreen(PixmapPtr p)
     ScreenPtr	pScreen = p->drawable.pScreen;
     ExaScreenPriv(pScreen);
     ExaPixmapPriv(p);
-    void *save_ptr;
     Bool ret;
 
-    save_ptr = p->devPrivate.ptr;
-
-    if (!save_ptr && pExaPixmap && !(pExaScr->info->flags & EXA_HANDLES_PIXMAPS))
+    if (pExaScr->info->PixmapIsOffscreen) {
 	p->devPrivate.ptr = ExaGetPixmapAddress(p);
-
-    if (pExaScr->info->PixmapIsOffscreen)
 	ret = pExaScr->info->PixmapIsOffscreen(p);
-    else
-       ret = ((unsigned long) ((CARD8 *) p->devPrivate.ptr -
-			       (CARD8 *) pExaScr->info->memoryBase) <
-	      pExaScr->info->memorySize);
-
-    p->devPrivate.ptr = save_ptr;
+	p->devPrivate.ptr = NULL;
+    } else
+	ret = (pExaPixmap->offscreen && pExaPixmap->fb_ptr);
 
     return ret;
 }


More information about the xorg-commit mailing list