xserver: Branch 'master'

Maarten Maathuis madman2003 at kemper.freedesktop.org
Sun Feb 8 09:47:05 PST 2009


 exa/exa.c |   84 ++++++++++++++++++++++++++++++++++++++++----------------------
 1 file changed, 55 insertions(+), 29 deletions(-)

New commits:
commit 6fd8fe9cb993f9b733cf7d878bc324acd09aa48d
Author: Maarten Maathuis <madman2003 at gmail.com>
Date:   Sun Feb 8 18:43:15 2009 +0100

    exa: fix exaValidateGC.
    
    - use DEST in the createPixmap wrapper, because stipple already takes MASK (in case someone uses swappers).
    - Anticipate some of the less common situations when fbValidateDrawable will access tile related pixmaps.

diff --git a/exa/exa.c b/exa/exa.c
index 033b353..4a36008 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -637,12 +637,15 @@ const GCFuncs exaGCFuncs = {
 
 /*
  * This wrapper exists to allow fbValidateGC to work.
+ * Note that we no longer assume newly created pixmaps to be in normal ram.
+ * This assumption is certainly not garuanteed with driver allocated pixmaps.
  */
 static PixmapPtr
 exaCreatePixmapWithPrepare(ScreenPtr pScreen, int w, int h, int depth,
 		unsigned usage_hint)
 {
     PixmapPtr pPixmap;
+    ExaMigrationRec pixmaps[1];
     ExaScreenPriv(pScreen);
 
     /* This swaps between this function and the real upper layer function.
@@ -655,8 +658,16 @@ exaCreatePixmapWithPrepare(ScreenPtr pScreen, int w, int h, int depth,
     if (!pPixmap)
 	return NULL;
 
-    /* We use MASK, because SRC is already taken. */
-    exaPrepareAccess(&pPixmap->drawable, EXA_PREPARE_MASK);
+    /* We need to use DEST, but we don't actually want to migrate as dest. */
+    /* SRC is taken by tile, and MASK by stipple. */
+    pixmaps[0].as_dst = 0;
+    pixmaps[0].as_src = 1;
+    pixmaps[0].pPix = exaGetDrawablePixmap (&pPixmap->drawable);
+    pixmaps[0].pReg = NULL;
+
+    exaDoMigration(pixmaps, 1, FALSE);
+
+    ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_DEST);
 
     return pPixmap;
 }
@@ -675,35 +686,50 @@ exaValidateGC(GCPtr pGC,
     CreatePixmapProcPtr old_ptr = NULL;
     PixmapPtr pTile = NULL;
     EXA_GC_PROLOGUE(pGC);
-    if (changes & GCTile) {
-	/* save the "fb" pointer. */
-	old_ptr = pExaScr->SavedCreatePixmap;
-	/* create a new upper layer pointer. */
-	wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmapWithPrepare);
-	if (pGC->fillStyle == FillTiled)
-		pTile = pGC->tile.pixmap;
-	if (pTile)
-	    exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC);
-    }
-    exaPrepareAccessGC(pGC);
-    (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
-    exaFinishAccessGC(pGC);
-    if (changes & GCTile) {
-	/* switch back to the normal upper layer. */
-	unwrap(pExaScr, pScreen, CreatePixmap);
-	/* restore copy of fb layer pointer. */
-	pExaScr->SavedCreatePixmap = old_ptr;
-	if (pTile)
-	    exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC);
-
-	/* A new tile pixmap was created. */
-	if (pGC->tile.pixmap != pTile && pGC->fillStyle == FillTiled) {
-	    exaFinishAccess(&pGC->tile.pixmap->drawable, EXA_PREPARE_MASK);
-	    exaPixmapDirty(pGC->tile.pixmap, 0, 0,
-			   pGC->tile.pixmap->drawable.width,
-			   pGC->tile.pixmap->drawable.height);
+
+    /* save the "fb" pointer. */
+    old_ptr = pExaScr->SavedCreatePixmap;
+    /* create a new upper layer pointer. */
+    wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmapWithPrepare);
+
+    /* 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. */
+    /* XXX: find out who is forgetting to NULL these tile pixmap pointers. */
+    if (pGC->fillStyle == FillTiled || ((changes & GCTile) && !pGC->tileIsPixel)) {
+	pTile = pGC->tile.pixmap;
+
+	/* Sometimes tile pixmaps are swapped, you need access to:
+	 * - The current tile if it depth matches.
+	 * - Or the rotated tile if that one matches depth and !(changes & GCTile).
+	 * - Or the current tile pixmap and a newly created one.
+	 */
+	if (pTile && pTile->drawable.depth != pDrawable->depth && !(changes & GCTile)) {
+	    PixmapPtr pRotatedTile = fbGetRotatedPixmap(pGC);
+	    if (pRotatedTile->drawable.depth == pDrawable->depth)
+		pTile = pRotatedTile;
 	}
     }
+
+    if (pGC->stipple)
+        exaPrepareAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
+    if (pTile)
+	exaPrepareAccess(&pTile->drawable, EXA_PREPARE_SRC);
+
+    (*pGC->funcs->ValidateGC)(pGC, changes, pDrawable);
+
+    if (pTile)
+	exaFinishAccess(&pTile->drawable, EXA_PREPARE_SRC);
+    if (pGC->stipple)
+        exaFinishAccess(&pGC->stipple->drawable, EXA_PREPARE_MASK);
+
+    /* switch back to the normal upper layer. */
+    unwrap(pExaScr, pScreen, CreatePixmap);
+    /* 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_DEST);
+    
     EXA_GC_EPILOGUE(pGC);
 }
 


More information about the xorg-commit mailing list