xserver: Branch 'server-1.7-branch' - 5 commits

Peter Hutterer whot at kemper.freedesktop.org
Fri Sep 25 20:17:46 PDT 2009


 Xi/queryst.c                |    2 
 configure.ac                |   20 ++--
 dix/events.c                |    4 
 exa/exa.c                   |   78 ++++++-------------
 exa/exa_migration_classic.c |   30 ++++++-
 exa/exa_migration_mixed.c   |  179 +++++++++++++++++++++++---------------------
 exa/exa_mixed.c             |   87 ++++++++-------------
 exa/exa_priv.h              |   22 ++++-
 exa/exa_unaccel.c           |   52 +++++++-----
 hw/kdrive/ephyr/ephyr.c     |    4 
 hw/kdrive/src/kinfo.c       |    6 +
 11 files changed, 257 insertions(+), 227 deletions(-)

New commits:
commit e5371c7fc895c51092bd5b2d303e4835c123bd5c
Author: Michel Dänzer <daenzer at vmware.com>
Date:   Sat Sep 26 01:59:39 2009 +0200

    EXA: Extend mixed pixmaps scheme to allow driver PrepareAccess hook to fail.
    
    If the PrepareAccess hook fails, use the DownloadFromScreen hook to retrieve
    driver pixmap contents to a system RAM copy, perform software rendering on that
    and copy the results back using the UploadToScreen hook. Use the classic
    migration logic to minimize transfers (which as a bonus allows slightly
    cleaning up some of the existing mixed pixmap code).
    
    This enables things that weren't possible before with driver-allocated pixmap
    storage: If some (or all) GPU pixmap storage can't be mapped directly by the
    CPU, this can be handled between the PrepareAccess and
    DownloadFrom/UploadToScreen hooks, e.g.:
    
    * Radeon KMS on big endian machines can fail PrepareAccess if the pixmap
      requires byte-swapping and swap bytes in DownloadFrom/UploadToScreen.
    * Environments where GPU and CPU don't have a shared address space at all.
      Here the driver PrepareAccess hook will always fail and leave all transfers
      between GPU / CPU storage to the Download/From/UploadToScreen hooks.
    
    Drivers which can handle all pixmaps in the PrepareAccess hook should notice
    little if any difference.
    (cherry picked from commit 1818cbd70fc1f2e1487b4c678e67e28f1265c0ef)

diff --git a/exa/exa.c b/exa/exa.c
index 483e3b4..e264d44 100644
--- a/exa/exa.c
+++ b/exa/exa.c
@@ -286,11 +286,10 @@ exaGetOffscreenPixmap (DrawablePtr pDrawable, int *xp, int *yp)
  * Returns TRUE if pixmap can be accessed offscreen.
  */
 Bool
-ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
+ExaDoPrepareAccess(PixmapPtr pPixmap, int index)
 {
-    ScreenPtr pScreen = pDrawable->pScreen;
+    ScreenPtr pScreen = pPixmap->drawable.pScreen;
     ExaScreenPriv (pScreen);
-    PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
     ExaPixmapPriv(pPixmap);
     Bool offscreen;
     int i;
@@ -324,7 +323,7 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
 
     offscreen = exaPixmapIsOffscreen(pPixmap);
 
-    if (offscreen)
+    if (offscreen && pExaPixmap->fb_ptr)
 	pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
     else
 	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
@@ -333,20 +332,10 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
     pExaScr->access[index].pixmap = pPixmap;
     pExaScr->access[index].count = 1;
 
-    if (!offscreen) {
-	/* Do we need to allocate our system buffer? */
-	if ((pExaScr->info->flags & EXA_HANDLES_PIXMAPS) && (pExaScr->info->flags & EXA_MIXED_PIXMAPS)) {
-	    if (!pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap)) {
-		pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch * pDrawable->height);
-		if (!pExaPixmap->sys_ptr)
-		    FatalError("EXA: malloc failed for size %d bytes\n", pExaPixmap->sys_pitch * pDrawable->height);
-		pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
-	    }
-	}
+    if (!offscreen)
 	return FALSE;
-    }
 
-    exaWaitSync (pDrawable->pScreen);
+    exaWaitSync (pScreen);
 
     if (pExaScr->info->PrepareAccess == NULL)
 	return TRUE;
@@ -360,7 +349,8 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
     }
 
     if (!(*pExaScr->info->PrepareAccess) (pPixmap, index)) {
-	if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED)
+	if (pExaPixmap->score == EXA_PIXMAP_SCORE_PINNED &&
+	    !(pExaScr->info->flags & EXA_MIXED_PIXMAPS))
 	    FatalError("Driver failed PrepareAccess on a pinned pixmap.\n");
 	exaMoveOutPixmap (pPixmap);
 
@@ -370,31 +360,6 @@ ExaDoPrepareAccess(DrawablePtr pDrawable, int index)
     return TRUE;
 }
 
-void
-exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
-{
-    PixmapPtr pPixmap = exaGetDrawablePixmap (pDrawable);
-    ExaScreenPriv(pPixmap->drawable.pScreen);
-
-    if (pExaScr->do_migration) {
-	ExaMigrationRec pixmaps[1];
-
-	if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
-	    pixmaps[0].as_dst = TRUE;
-	    pixmaps[0].as_src = FALSE;
-	} else {
-	    pixmaps[0].as_dst = FALSE;
-	    pixmaps[0].as_src = TRUE;
-	}
-	pixmaps[0].pPix = pPixmap;
-	pixmaps[0].pReg = pReg;
-
-	exaDoMigration(pixmaps, 1, FALSE);
-    }
-
-    ExaDoPrepareAccess(pDrawable, index);
-}
-
 /**
  * exaPrepareAccess() is EXA's wrapper for the driver's PrepareAccess() handler.
  *
@@ -404,7 +369,13 @@ exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg)
 void
 exaPrepareAccess(DrawablePtr pDrawable, int index)
 {
-    exaPrepareAccessReg(pDrawable, index, NULL);
+    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+    ExaScreenPriv(pDrawable->pScreen);
+
+    if (pExaScr->prepare_access_reg)
+	pExaScr->prepare_access_reg(pPixmap, index, NULL);
+    else
+	(void)ExaDoPrepareAccess(pPixmap, index);
 }
 
 /**
@@ -432,7 +403,6 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
 	if (pExaScr->access[i].pixmap == pPixmap) {
 	    if (--pExaScr->access[i].count > 0)
 		return;
-	    index = i;
 	    break;
 	}
     }
@@ -442,25 +412,25 @@ exaFinishAccess(DrawablePtr pDrawable, int index)
 	EXA_FatalErrorDebug(("EXA bug: FinishAccess called without PrepareAccess for pixmap 0x%p.\n",
 			     pPixmap));
 
-    pExaScr->access[index].pixmap = NULL;
+    pExaScr->access[i].pixmap = NULL;
 
     /* We always hide the devPrivate.ptr. */
     pPixmap->devPrivate.ptr = NULL;
 
-    if (pExaScr->info->FinishAccess == NULL)
-	return;
+    if (pExaScr->finish_access)
+	pExaScr->finish_access(pPixmap, index);
 
-    if (!exaPixmapIsOffscreen (pPixmap))
+    if (!pExaScr->info->FinishAccess || !exaPixmapIsOffscreen(pPixmap))
 	return;
 
-    if (index >= EXA_PREPARE_AUX_DEST &&
+    if (i >= EXA_PREPARE_AUX_DEST &&
 	!(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);
+    (*pExaScr->info->FinishAccess) (pPixmap, i);
 }
 
 /**
@@ -537,7 +507,7 @@ exaCreatePixmapWithPrepare(ScreenPtr pScreen, int w, int h, int depth,
      * For EXA_HANDLES_PIXMAPS the driver will handle whatever is needed.
      * We want to signal that the pixmaps will be used as destination.
      */
-    ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_AUX_DEST);
+    ExaDoPrepareAccess(pPixmap, EXA_PREPARE_AUX_DEST);
 
     return pPixmap;
 }
@@ -1071,6 +1041,8 @@ exaDriverInit (ScreenPtr		pScreen,
 		pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_mixed;
 		pExaScr->do_move_in_pixmap = exaMoveInPixmap_mixed;
 		pExaScr->do_move_out_pixmap = NULL;
+		pExaScr->prepare_access_reg = exaPrepareAccessReg_mixed;
+		pExaScr->finish_access = exaFinishAccess_mixed;
 	    } else {
 		wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_driver);
 		wrap(pExaScr, pScreen, DestroyPixmap, exaDestroyPixmap_driver);
@@ -1079,6 +1051,8 @@ exaDriverInit (ScreenPtr		pScreen,
 		pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_driver;
 		pExaScr->do_move_in_pixmap = NULL;
 		pExaScr->do_move_out_pixmap = NULL;
+		pExaScr->prepare_access_reg = NULL;
+		pExaScr->finish_access = NULL;
 	    }
 	} else {
 	    wrap(pExaScr, pScreen, CreatePixmap, exaCreatePixmap_classic);
@@ -1088,6 +1062,8 @@ exaDriverInit (ScreenPtr		pScreen,
 	    pExaScr->pixmap_is_offscreen = exaPixmapIsOffscreen_classic;
 	    pExaScr->do_move_in_pixmap = exaMoveInPixmap_classic;
 	    pExaScr->do_move_out_pixmap = exaMoveOutPixmap_classic;
+	    pExaScr->prepare_access_reg = exaPrepareAccessReg_classic;
+	    pExaScr->finish_access = NULL;
 	}
 	if (!(pExaScr->info->flags & EXA_HANDLES_PIXMAPS)) {
 	    LogMessage(X_INFO, "EXA(%d): Offscreen pixmap area of %lu bytes\n",
diff --git a/exa/exa_migration_classic.c b/exa/exa_migration_classic.c
index d8e1e86..0032f02 100644
--- a/exa/exa_migration_classic.c
+++ b/exa/exa_migration_classic.c
@@ -120,7 +120,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
     Bool need_sync = FALSE;
 
     /* Damaged bits are valid in current copy but invalid in other one */
-    if (exaPixmapIsOffscreen(pPixmap)) {
+    if (pExaPixmap->offscreen) {
 	REGION_UNION(pScreen, &pExaPixmap->validFB, &pExaPixmap->validFB,
 		     damage);
 	REGION_SUBTRACT(pScreen, &pExaPixmap->validSys, &pExaPixmap->validSys,
@@ -225,7 +225,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
 				    pExaPixmap->sys_pitch))
 	{
 	    if (!access_prepared) {
-		ExaDoPrepareAccess(&pPixmap->drawable, fallback_index);
+		ExaDoPrepareAccess(pPixmap, fallback_index);
 		access_prepared = TRUE;
 	    }
 	    exaMemcpyBox (pPixmap, pBox,
@@ -263,7 +263,7 @@ exaCopyDirty(ExaMigrationPtr migrate, RegionPtr pValidDst, RegionPtr pValidSrc,
  * the framebuffer  memory copy to the system memory copy.  Both areas must be
  * allocated.
  */
-static void
+void
 exaCopyDirtyToSys (ExaMigrationPtr migrate)
 {
     PixmapPtr pPixmap = migrate->pPix;
@@ -281,7 +281,7 @@ exaCopyDirtyToSys (ExaMigrationPtr migrate)
  * the system memory copy to the framebuffer memory copy.  Both areas must be
  * allocated.
  */
-static void
+void
 exaCopyDirtyToFb (ExaMigrationPtr migrate)
 {
     PixmapPtr pPixmap = migrate->pPix;
@@ -545,7 +545,7 @@ exaAssertNotDirty (PixmapPtr pPixmap)
     pExaPixmap->offscreen = TRUE;
     pPixmap->devKind = pExaPixmap->fb_pitch;
 
-    if (!ExaDoPrepareAccess(&pPixmap->drawable, EXA_PREPARE_SRC))
+    if (!ExaDoPrepareAccess(pPixmap, EXA_PREPARE_SRC))
 	goto skip;
 
     while (nbox--) {
@@ -718,3 +718,23 @@ exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
 	}
     }
 }
+
+void
+exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg)
+{
+    ExaMigrationRec pixmaps[1];
+
+    if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
+	pixmaps[0].as_dst = TRUE;
+	pixmaps[0].as_src = FALSE;
+    } else {
+	pixmaps[0].as_dst = FALSE;
+	pixmaps[0].as_src = TRUE;
+    }
+    pixmaps[0].pPix = pPixmap;
+    pixmaps[0].pReg = pReg;
+
+    exaDoMigration(pixmaps, 1, FALSE);
+
+    (void)ExaDoPrepareAccess(pPixmap, index);
+}
diff --git a/exa/exa_migration_mixed.c b/exa/exa_migration_mixed.c
index d1ee987..f42c9c2 100644
--- a/exa/exa_migration_mixed.c
+++ b/exa/exa_migration_mixed.c
@@ -31,55 +31,16 @@
 #include "exa_priv.h"
 #include "exa.h"
 
-static void
-exaUploadFallback(PixmapPtr pPixmap, CARD8 *src, int src_pitch)
-{
-    ExaPixmapPriv(pPixmap);
-    RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
-    GCPtr pGC = GetScratchGC (pPixmap->drawable.depth,
-		pPixmap->drawable.pScreen);
-    int nbox, cpp = pPixmap->drawable.bitsPerPixel / 8;
-    DamagePtr backup = pExaPixmap->pDamage;
-    BoxPtr pbox;
-    CARD8 *src2;
-
-    /* We don't want damage optimisations. */
-    pExaPixmap->pDamage = NULL;
-    ValidateGC (&pPixmap->drawable, pGC);
-
-    pbox = REGION_RECTS(damage);
-    nbox = REGION_NUM_RECTS(damage);
-
-    while (nbox--) {
-	src2 = src + pbox->y1 * src_pitch + pbox->x1 * cpp;
-
-	ExaCheckPutImage(&pPixmap->drawable, pGC,
-	    pPixmap->drawable.depth, pbox->x1, pbox->y1,
-	    pbox->x2 - pbox->x1, pbox->y2 - pbox->y1, 0,
-	    ZPixmap, (char*) src2);
-
-	pbox++;
-    }
-
-    FreeScratchGC (pGC);
-    pExaPixmap->pDamage = backup;
-}
-
 void
 exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
 {
     ScreenPtr pScreen = pPixmap->drawable.pScreen;
     ExaScreenPriv(pScreen);
     ExaPixmapPriv(pPixmap);
-    RegionPtr damage = DamageRegion (pExaPixmap->pDamage);
-    void *sys_buffer = pExaPixmap->sys_ptr;
     int w = pPixmap->drawable.width, h = pPixmap->drawable.height;
     int depth = pPixmap->drawable.depth, bpp = pPixmap->drawable.bitsPerPixel;
     int usage_hint = pPixmap->usage_hint;
-    int sys_pitch = pExaPixmap->sys_pitch;
-    int paddedWidth = sys_pitch;
-    int nbox;
-    BoxPtr pbox;
+    int paddedWidth = pExaPixmap->sys_pitch;
 
     /* Already done. */
     if (pExaPixmap->driverPriv)
@@ -105,50 +66,8 @@ exaCreateDriverPixmap_mixed(PixmapPtr pPixmap)
     if (!pExaPixmap->driverPriv)
 	return;
 
-    pExaPixmap->offscreen = TRUE;
-    pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL;
-    pExaPixmap->sys_pitch = pPixmap->devKind = 0;
-
-    pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
     (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
 				paddedWidth, NULL);
-
-    /* scratch pixmaps */
-    if (!w || !h)
-	goto finish;
-
-    /* we do not malloc memory by default. */
-    if (!sys_buffer)
-	goto finish;
-
-    if (!pExaScr->info->UploadToScreen)
-	goto fallback;
-
-    pbox = REGION_RECTS(damage);
-    nbox = REGION_NUM_RECTS(damage);
-
-    while (nbox--) {
-	if (!pExaScr->info->UploadToScreen(pPixmap, pbox->x1, pbox->y1, pbox->x2 - pbox->x1,
-		pbox->y2 - pbox->y1, (char *) (sys_buffer) + pbox->y1 * sys_pitch + pbox->x1 * (bpp / 8), sys_pitch))
-	    goto fallback;
-
-	pbox++;
-    }
-
-    goto finish;
-
-fallback:
-    exaUploadFallback(pPixmap, sys_buffer, sys_pitch);
-
-finish:
-    free(sys_buffer);
-
-    /* We no longer need this. */
-    if (pExaPixmap->pDamage) {
-	DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
-	DamageDestroy(pExaPixmap->pDamage);
-	pExaPixmap->pDamage = NULL;
-    }
 }
 
 void
@@ -175,8 +94,16 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel)
     for (i = 0; i < npixmaps; i++) {
 	PixmapPtr pPixmap = pixmaps[i].pPix;
 	ExaPixmapPriv(pPixmap);
+
 	if (!pExaPixmap->driverPriv)
 	    exaCreateDriverPixmap_mixed(pPixmap);
+
+	if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) {
+	    pPixmap->devKind = pExaPixmap->fb_pitch;
+	    exaCopyDirtyToFb(pixmaps + i);
+	}
+
+	pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap);
     }
 }
 
@@ -192,3 +119,91 @@ exaMoveInPixmap_mixed(PixmapPtr pPixmap)
 
     exaDoMigration(pixmaps, 1, TRUE);
 }
+
+/* With mixed pixmaps, if we fail to get direct access to the driver pixmap, we
+ * use the DownloadFromScreen hook to retrieve contents to a copy in system
+ * memory, perform software rendering on that and move back the results with the
+ * UploadToScreen hook (see exaFinishAccess_mixed).
+ */
+void
+exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg)
+{
+    if (!ExaDoPrepareAccess(pPixmap, index)) {
+	ExaPixmapPriv(pPixmap);
+	Bool is_offscreen = exaPixmapIsOffscreen(pPixmap);
+	ExaMigrationRec pixmaps[1];
+
+	/* Do we need to allocate our system buffer? */
+	if (!pExaPixmap->sys_ptr) {
+	    pExaPixmap->sys_ptr = malloc(pExaPixmap->sys_pitch *
+					 pPixmap->drawable.height);
+	    if (!pExaPixmap->sys_ptr)
+		FatalError("EXA: malloc failed for size %d bytes\n",
+			   pExaPixmap->sys_pitch * pPixmap->drawable.height);
+	}
+
+	if (index == EXA_PREPARE_DEST || index == EXA_PREPARE_AUX_DEST) {
+	    pixmaps[0].as_dst = TRUE;
+	    pixmaps[0].as_src = FALSE;
+	} else {
+	    pixmaps[0].as_dst = FALSE;
+	    pixmaps[0].as_src = TRUE;
+	}
+	pixmaps[0].pPix = pPixmap;
+	pixmaps[0].pReg = pReg;
+
+	if (!pExaPixmap->pDamage && (is_offscreen || !exaPixmapIsPinned(pPixmap))) {
+	    Bool as_dst = pixmaps[0].as_dst;
+
+	    /* Set up damage tracking */
+	    pExaPixmap->pDamage = DamageCreate(NULL, NULL, DamageReportNone,
+					       TRUE, pPixmap->drawable.pScreen,
+					       pPixmap);
+
+	    DamageRegister(&pPixmap->drawable, pExaPixmap->pDamage);
+	    /* This ensures that pending damage reflects the current operation. */
+	    /* This is used by exa to optimize migration. */
+	    DamageSetReportAfterOp(pExaPixmap->pDamage, TRUE);
+
+	    if (is_offscreen) {
+		exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+			       pPixmap->drawable.height);
+
+		/* We don't know which region of the destination will be damaged,
+		 * have to assume all of it
+		 */
+		if (as_dst) {
+		    pixmaps[0].as_dst = FALSE;
+		    pixmaps[0].as_src = TRUE;
+		    pixmaps[0].pReg = NULL;
+		}
+		pPixmap->devKind = pExaPixmap->fb_pitch;
+		exaCopyDirtyToSys(pixmaps);
+	    }
+
+	    if (as_dst)
+		exaPixmapDirty(pPixmap, 0, 0, pPixmap->drawable.width,
+			       pPixmap->drawable.height);
+	} else if (is_offscreen) {
+	    pPixmap->devKind = pExaPixmap->fb_pitch;
+	    exaCopyDirtyToSys(pixmaps);
+	}
+
+	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+	pPixmap->devKind = pExaPixmap->sys_pitch;
+	pExaPixmap->offscreen = FALSE;
+    }
+}
+
+/* Move back results of software rendering on system memory copy of mixed driver
+ * pixmap (see exaPrepareAccessReg_mixed).
+ */
+void exaFinishAccess_mixed(PixmapPtr pPixmap, int index)
+{
+    ExaPixmapPriv(pPixmap);
+
+    if (pExaPixmap->pDamage && exaPixmapIsOffscreen(pPixmap)) {
+	DamageRegionProcessPending(&pPixmap->drawable);
+	exaMoveInPixmap_mixed(pPixmap);
+    }
+}
diff --git a/exa/exa_mixed.c b/exa/exa_mixed.c
index 6aa73f2..167ffa9 100644
--- a/exa/exa_mixed.c
+++ b/exa/exa_mixed.c
@@ -32,8 +32,6 @@
 #include "exa.h"
 
 /* This file holds the driver allocated pixmaps + better initial placement code.
- * A pinned pixmap implies one that is either driver based already or otherwise altered.
- * Proper care is taken to free the initially allocated buffer.
  */
 
 static _X_INLINE void*
@@ -46,9 +44,6 @@ ExaGetPixmapAddress(PixmapPtr p)
 
 /**
  * exaCreatePixmap() creates a new pixmap.
- *
- * Pixmaps are always marked as pinned, unless the pixmap can still be transfered to a
- * driver pixmaps.
  */
 PixmapPtr
 exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
@@ -85,7 +80,6 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
     pExaPixmap->sys_pitch = paddedWidth;
 
     pExaPixmap->area = NULL;
-    pExaPixmap->offscreen = FALSE;
     pExaPixmap->fb_ptr = NULL;
     pExaPixmap->pDamage = NULL;
 
@@ -93,36 +87,15 @@ exaCreatePixmap_mixed(ScreenPtr pScreen, int w, int h, int depth,
     exaSetAccelBlock(pExaScr, pExaPixmap,
 	w, h, bpp);
 
-    /* Avoid freeing sys_ptr. */
-    pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
-
     (*pScreen->ModifyPixmapHeader)(pPixmap, w, h, 0, 0,
 				    paddedWidth, NULL);
 
-    /* We want to be able to transfer the pixmap to driver memory later on. */
-    pExaPixmap->score = EXA_PIXMAP_SCORE_INIT;
-
     /* A scratch pixmap will become a driver pixmap right away. */
     if (!w || !h) {
 	exaCreateDriverPixmap_mixed(pPixmap);
-    } else {
-	/* Set up damage tracking */
-	pExaPixmap->pDamage = DamageCreate (NULL, NULL,
-					    DamageReportNone, TRUE,
-					    pScreen, pPixmap);
-
-	if (pExaPixmap->pDamage == NULL) {
-	    swap(pExaScr, pScreen, DestroyPixmap);
-	    pScreen->DestroyPixmap (pPixmap);
-	    swap(pExaScr, pScreen, DestroyPixmap);
-	    return NULL;
-	}
-
-	DamageRegister (&pPixmap->drawable, pExaPixmap->pDamage);
-	/* This ensures that pending damage reflects the current operation. */
-	/* This is used by exa to optimize migration. */
-	DamageSetReportAfterOp (pExaPixmap->pDamage, TRUE);
-    }
+	pExaPixmap->offscreen = exaPixmapIsOffscreen(pPixmap);
+    } else
+	pExaPixmap->offscreen = FALSE;
 
     return pPixmap;
 }
@@ -134,7 +107,7 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
     ScreenPtr pScreen = pPixmap->drawable.pScreen;
     ExaScreenPrivPtr pExaScr;
     ExaPixmapPrivPtr pExaPixmap;
-    Bool ret;
+    Bool ret, is_offscreen;
 
     if (!pPixmap)
         return FALSE;
@@ -142,26 +115,23 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
     pExaScr = ExaGetScreenPriv(pScreen);
     pExaPixmap = ExaGetPixmapPriv(pPixmap);
 
-    if (pExaPixmap) {
-	if (!exaPixmapIsPinned(pPixmap)) {
-	    free(pExaPixmap->sys_ptr);
-	    pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr = NULL;
-	    pExaPixmap->sys_pitch = pPixmap->devKind = 0;
-
-	    /* We no longer need this. */
+    if (pPixData) {
+	if (pExaPixmap->driverPriv) {
 	    if (pExaPixmap->pDamage) {
 		DamageUnregister(&pPixmap->drawable, pExaPixmap->pDamage);
 		DamageDestroy(pExaPixmap->pDamage);
 		pExaPixmap->pDamage = NULL;
 	    }
-	}
 
-        if (pPixData)
-            pExaPixmap->sys_ptr = pPixData;
+	    pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
+	    pExaPixmap->driverPriv = NULL;
+	}
 
-        if (devKind > 0)
-            pExaPixmap->sys_pitch = devKind;
+	pExaPixmap->offscreen = FALSE;
+	pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+    }
 
+    if (pExaPixmap->driverPriv) {
         if (width > 0 && height > 0 && bitsPerPixel > 0) {
             exaSetFbPitch(pExaScr, pExaPixmap,
                           width, height, bitsPerPixel);
@@ -169,9 +139,15 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
             exaSetAccelBlock(pExaScr, pExaPixmap,
                              width, height, bitsPerPixel);
         }
+    }
 
-	/* Anything can happen, don't try to predict it all. */
-	pExaPixmap->score = EXA_PIXMAP_SCORE_PINNED;
+    is_offscreen = exaPixmapIsOffscreen(pPixmap);
+    if (is_offscreen) {
+	pPixmap->devPrivate.ptr = pExaPixmap->fb_ptr;
+	pPixmap->devKind = pExaPixmap->fb_pitch;
+    } else {
+	pPixmap->devPrivate.ptr = pExaPixmap->sys_ptr;
+	pPixmap->devKind = pExaPixmap->sys_pitch;
     }
 
     /* Only pass driver pixmaps to the driver. */
@@ -182,10 +158,6 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
 	 * 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)
 	    goto out;
     }
@@ -196,6 +168,13 @@ exaModifyPixmapHeader_mixed(PixmapPtr pPixmap, int width, int height, int depth,
     swap(pExaScr, pScreen, ModifyPixmapHeader);
 
 out:
+    if (is_offscreen) {
+	pExaPixmap->fb_ptr = pPixmap->devPrivate.ptr;
+	pExaPixmap->fb_pitch = pPixmap->devKind;
+    } else {
+	pExaPixmap->sys_ptr = pPixmap->devPrivate.ptr;
+	pExaPixmap->sys_pitch = pPixmap->devKind;
+    }
     /* Always NULL this, we don't want lingering pointers. */
     pPixmap->devPrivate.ptr = NULL;
 
@@ -215,10 +194,14 @@ exaDestroyPixmap_mixed(PixmapPtr pPixmap)
 
 	if (pExaPixmap->driverPriv)
 	    pExaScr->info->DestroyPixmap(pScreen, pExaPixmap->driverPriv);
-	else if (pExaPixmap->sys_ptr && !exaPixmapIsPinned(pPixmap))
-	    free(pExaPixmap->sys_ptr);
 	pExaPixmap->driverPriv = NULL;
-	pExaPixmap->sys_ptr = NULL;
+
+	if (pExaPixmap->pDamage) {
+	    if (pExaPixmap->sys_ptr)
+		free(pExaPixmap->sys_ptr);
+	    pExaPixmap->sys_ptr = NULL;
+	    pExaPixmap->pDamage = NULL;
+	}
     }
 
     swap(pExaScr, pScreen, DestroyPixmap);
diff --git a/exa/exa_priv.h b/exa/exa_priv.h
index 869cf17..1aec8e9 100644
--- a/exa/exa_priv.h
+++ b/exa/exa_priv.h
@@ -176,6 +176,8 @@ typedef struct {
     Bool (*pixmap_is_offscreen) (PixmapPtr pPixmap);
     void (*do_move_in_pixmap) (PixmapPtr pPixmap);
     void (*do_move_out_pixmap) (PixmapPtr pPixmap);
+    void (*prepare_access_reg)(PixmapPtr pPixmap, int index, RegionPtr pReg);
+    void (*finish_access)(PixmapPtr pPixmap, int index);
 
     Bool			 swappedOut;
     enum ExaMigrationHeuristic	 migration;
@@ -511,10 +513,7 @@ ExaOffscreenFini (ScreenPtr pScreen);
 
 /* exa.c */
 Bool
-ExaDoPrepareAccess(DrawablePtr pDrawable, int index);
-
-void
-exaPrepareAccessReg(DrawablePtr pDrawable, int index, RegionPtr pReg);
+ExaDoPrepareAccess(PixmapPtr pPixmap, int index);
 
 void
 exaPrepareAccess(DrawablePtr pDrawable, int index);
@@ -609,6 +608,12 @@ exaDoMigration_mixed(ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
 void
 exaMoveInPixmap_mixed(PixmapPtr pPixmap);
 
+void
+exaPrepareAccessReg_mixed(PixmapPtr pPixmap, int index, RegionPtr pReg);
+
+void
+exaFinishAccess_mixed(PixmapPtr pPixmap, int index);
+
 /* exa_render.c */
 Bool
 exaOpReadsDestination (CARD8 op);
@@ -665,6 +670,12 @@ exaGlyphs (CARD8	op,
 
 /* exa_migration_classic.c */
 void
+exaCopyDirtyToSys (ExaMigrationPtr migrate);
+
+void
+exaCopyDirtyToFb (ExaMigrationPtr migrate);
+
+void
 exaDoMigration_classic (ExaMigrationPtr pixmaps, int npixmaps, Bool can_accel);
 
 void
@@ -676,4 +687,7 @@ exaMoveOutPixmap_classic (PixmapPtr pPixmap);
 void
 exaMoveInPixmap_classic (PixmapPtr pPixmap);
 
+void
+exaPrepareAccessReg_classic(PixmapPtr pPixmap, int index, RegionPtr pReg);
+
 #endif /* EXAPRIV_H */
diff --git a/exa/exa_unaccel.c b/exa/exa_unaccel.c
index f4700ad..c8f0172 100644
--- a/exa/exa_unaccel.c
+++ b/exa/exa_unaccel.c
@@ -101,16 +101,19 @@ ExaCheckPutImage (DrawablePtr pDrawable, GCPtr pGC, int depth,
 		 int x, int y, int w, int h, int leftPad, int format,
 		 char *bits)
 {
-    ExaPixmapPriv(exaGetDrawablePixmap(pDrawable));
+    PixmapPtr pPixmap = exaGetDrawablePixmap(pDrawable);
+    ExaPixmapPriv(pPixmap);
+    ExaScreenPriv(pDrawable->pScreen);
 
     EXA_GC_PROLOGUE(pGC);
     EXA_FALLBACK(("to %p (%c)\n", pDrawable, exaDrawableLocation(pDrawable)));
-    if (exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
+    if (!pExaScr->prepare_access_reg || !pExaPixmap->pDamage ||
+	exaGCReadsDestination(pDrawable, pGC->planemask, pGC->fillStyle,
 			      pGC->alu, pGC->clientClipType))
 	exaPrepareAccess (pDrawable, EXA_PREPARE_DEST);
     else
-	exaPrepareAccessReg (pDrawable, EXA_PREPARE_DEST, pExaPixmap->pDamage ?
-			     DamagePendingRegion(pExaPixmap->pDamage) : NULL);
+	pExaScr->prepare_access_reg(pPixmap, EXA_PREPARE_DEST,
+				    DamagePendingRegion(pExaPixmap->pDamage));
     pGC->ops->PutImage (pDrawable, pGC, depth, x, y, w, h, leftPad, format, bits);
     exaFinishAccess (pDrawable, EXA_PREPARE_DEST);
     EXA_GC_EPILOGUE(pGC);
@@ -323,9 +326,6 @@ void
 ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
 		unsigned int format, unsigned long planeMask, char *d)
 {
-    BoxRec Box;
-    RegionRec Reg;
-    int xoff, yoff;
     ScreenPtr pScreen = pDrawable->pScreen;
     PixmapPtr pPix = exaGetDrawablePixmap (pDrawable);
     ExaScreenPriv(pScreen);
@@ -333,16 +333,24 @@ ExaCheckGetImage(DrawablePtr pDrawable, int x, int y, int w, int h,
     EXA_FALLBACK(("from %p (%c)\n", pDrawable,
 		  exaDrawableLocation(pDrawable)));
 
-    exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
+    if (pExaScr->prepare_access_reg) {
+	int xoff, yoff;
+	BoxRec Box;
+	RegionRec Reg;
+
+	exaGetDrawableDeltas(pDrawable, pPix, &xoff, &yoff);
+
+	Box.x1 = pDrawable->y + x + xoff;
+	Box.y1 = pDrawable->y + y + yoff;
+	Box.x2 = Box.x1 + w;
+	Box.y2 = Box.y1 + h;
 
-    Box.x1 = pDrawable->y + x + xoff;
-    Box.y1 = pDrawable->y + y + yoff;
-    Box.x2 = Box.x1 + w;
-    Box.y2 = Box.y1 + h;
+	REGION_INIT(pScreen, &Reg, &Box, 1);
 
-    REGION_INIT(pScreen, &Reg, &Box, 1);
+	pExaScr->prepare_access_reg(pPix, EXA_PREPARE_SRC, &Reg);
+    } else
+	exaPrepareAccess(pDrawable, EXA_PREPARE_SRC);
 
-    exaPrepareAccessReg (pDrawable, EXA_PREPARE_SRC, &Reg);
     swap(pExaScr, pScreen, GetImage);
     pScreen->GetImage (pDrawable, x, y, w, h, format, planeMask, d);
     swap(pExaScr, pScreen, GetImage);
@@ -401,23 +409,23 @@ ExaCheckComposite (CARD8      op,
     if (pMask && pMask->alphaMap && pMask->alphaMap->pDrawable)
 	exaPrepareAccess(pMask->alphaMap->pDrawable, EXA_PREPARE_AUX_MASK);
 
-    if (!exaOpReadsDestination(op)) {
+    if (!exaOpReadsDestination(op) && pExaScr->prepare_access_reg) {
+	PixmapPtr pDstPix;
+
 	if (!miComputeCompositeRegion (&region, pSrc, pMask, pDst,
 				       xSrc, ySrc, xMask, yMask, xDst, yDst,
 				       width, height))
 	    goto skip;
 
-	exaGetDrawableDeltas (pDst->pDrawable,
-			      exaGetDrawablePixmap(pDst->pDrawable),
-			      &xoff, &yoff);
-
+	pDstPix = exaGetDrawablePixmap(pDst->pDrawable);
+	exaGetDrawableDeltas (pDst->pDrawable, pDstPix, &xoff, &yoff);
 	REGION_TRANSLATE(pScreen, &region, xoff, yoff);
 
 	if (pDst->alphaMap && pDst->alphaMap->pDrawable)
-	    exaPrepareAccessReg(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST,
-				&region);
+	    pExaScr->prepare_access_reg(exaGetDrawablePixmap(pDst->alphaMap->pDrawable),
+					EXA_PREPARE_AUX_DEST, &region);
 
-	exaPrepareAccessReg (pDst->pDrawable, EXA_PREPARE_DEST, &region);
+	pExaScr->prepare_access_reg(pDstPix, EXA_PREPARE_DEST, &region);
     } else {
 	if (pDst->alphaMap && pDst->alphaMap->pDrawable)
 	    exaPrepareAccess(pDst->alphaMap->pDrawable, EXA_PREPARE_AUX_DEST);
commit cecd484fbb3db273472d0bf0ec45d8604ff0cde2
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Sep 22 20:34:54 2009 +1000

    Require libXext >= 1.0.99.4
    
    Reported-by: Tilman Sauerbeck
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 9fa73be9fa543a686ea35c861084f5af37d44caa)

diff --git a/configure.ac b/configure.ac
index 40cd017..469c374 100644
--- a/configure.ac
+++ b/configure.ac
@@ -738,6 +738,8 @@ dnl Core modules for most extensions, et al.
 REQUIRED_MODULES="[randrproto >= 1.2.99.3] [renderproto >= 0.11] [fixesproto >= 4.1] [damageproto >= 1.1] [xcmiscproto >= 1.2.0] [xextproto >= 7.0.99.3] [xproto >= 7.0.13] [xtrans >= 1.2.2] [bigreqsproto >= 1.1.0] fontsproto [inputproto >= 1.9.99.902] [kbproto >= 1.0.3]"
 REQUIRED_LIBS="xfont xau [pixman-1 >= 0.15.20]"
 
+LIBXEXT="xext >= 1.0.99.4"
+
 dnl HAVE_DBUS is true if we actually have the D-Bus library, whereas
 dnl CONFIG_DBUS_API is true if we want to enable the D-Bus config
 dnl API.
@@ -1360,7 +1362,7 @@ fi
 
 dnl Xnest DDX
 
-PKG_CHECK_MODULES(XNESTMODULES, [xfont xext x11 xau $XDMCP_MODULES], [have_xnest=yes], [have_xnest=no])
+PKG_CHECK_MODULES(XNESTMODULES, [xfont $LIBXEXT x11 xau $XDMCP_MODULES], [have_xnest=yes], [have_xnest=no])
 AC_MSG_CHECKING([whether to build Xnest DDX])
 if test "x$XNEST" = xauto; then
 	XNEST="$have_xnest"
@@ -1775,7 +1777,7 @@ AM_CONDITIONAL(STANDALONE_XPBPROXY, [test "x$STANDALONE_XPBPROXY" = xyes])
 dnl DMX DDX
 
 PKG_CHECK_MODULES([DMXMODULES],
-    [xmuu xext x11 xrender xfixes xfont xi >= 1.2.99.1 $DMXPROTO xau $XDMCP_MODULES],
+    [xmuu $LIBXEXT x11 xrender xfixes xfont xi >= 1.2.99.1 $DMXPROTO xau $XDMCP_MODULES],
     [have_dmx=yes], [have_dmx=no])
 AC_MSG_CHECKING([whether to build Xdmx DDX])
 if test "x$DMX" = xauto; then
@@ -1810,17 +1812,17 @@ dnl Linux sources in DMX require <linux/keyboard.h>
 	PKG_CHECK_MODULES([XDMXCONFIG_DEP], [xaw7 xmu xt xpm x11])
 	AC_SUBST(XDMXCONFIG_DEP_CFLAGS)
 	AC_SUBST(XDMXCONFIG_DEP_LIBS)
-	PKG_CHECK_MODULES([DMXEXAMPLES_DEP], [dmx xext x11])
+	PKG_CHECK_MODULES([DMXEXAMPLES_DEP], [dmx $LIBXEXT x11])
 	AC_SUBST(DMXEXAMPLES_DEP_LIBS)
-	PKG_CHECK_MODULES([DMXXMUEXAMPLES_DEP], [dmx xmu xext x11])
+	PKG_CHECK_MODULES([DMXXMUEXAMPLES_DEP], [dmx xmu $LIBXEXT x11])
 	AC_SUBST(DMXXMUEXAMPLES_DEP_LIBS)
-	PKG_CHECK_MODULES([DMXXIEXAMPLES_DEP], [dmx xi xext x11])
+	PKG_CHECK_MODULES([DMXXIEXAMPLES_DEP], [dmx xi $LIBXEXT x11])
 	AC_SUBST(DMXXIEXAMPLES_DEP_LIBS)
-	PKG_CHECK_MODULES([XTSTEXAMPLES_DEP], [xtst xext x11])
+	PKG_CHECK_MODULES([XTSTEXAMPLES_DEP], [xtst $LIBXEXT x11])
 	AC_SUBST(XTSTEXAMPLES_DEP_LIBS)
-	PKG_CHECK_MODULES([XRESEXAMPLES_DEP], [xres xext x11])
+	PKG_CHECK_MODULES([XRESEXAMPLES_DEP], [xres $LIBXEXT x11])
 	AC_SUBST(XRESEXAMPLES_DEP_LIBS)
-	PKG_CHECK_MODULES([X11EXAMPLES_DEP], [xext x11])
+	PKG_CHECK_MODULES([X11EXAMPLES_DEP], [$LIBXEXT x11])
 	AC_SUBST(X11EXAMPLES_DEP_LIBS)
 fi
 AM_CONDITIONAL([DMX_BUILD_LNX], [test "x$DMX_BUILD_LNX" = xyes])
@@ -1889,7 +1891,7 @@ if test "$KDRIVE" = yes; then
        XSDL_INCS="`sdl-config --cflags` $XSERVER_CFLAGS"
     fi
 
-    XEPHYR_REQUIRED_LIBS="x11 xext xfont xau xdmcp"
+    XEPHYR_REQUIRED_LIBS="x11 $LIBXEXT xfont xau xdmcp"
     if test "x$XV" = xyes; then
         XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS xv"
     fi
commit f188fabfe264dfec1950c168e2d9c22f13797b93
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Sep 23 11:43:27 2009 +1000

    kdrive: plug two memory leaks when freeing the KdKeyboard/Pointer.
    
    xkbRules, xkbModel and xkbLayout are strdup'd in KdNewKeyboard, need to be
    freed.
    
    The ephyr driver strdups the name on top of the already allocated
    kdrive-assigned name. Memory must be freed beforehand.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit a9c274df5c37cb4ece6449e934342d8ff8e61705)

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 296284a..254fcbc 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -1074,6 +1074,8 @@ MouseInit (KdPointerInfo *pi)
     ((EphyrPointerPrivate *)pi->driverPrivate)->enabled = FALSE;
     pi->nAxes = 3;
     pi->nButtons = 32;
+    if (pi->name)
+        xfree(pi->name);
     pi->name = strdup("Xephyr virtual mouse");
     ephyrMouse = pi;
     return Success;
@@ -1123,6 +1125,8 @@ EphyrKeyboardInit (KdKeyboardInfo *ki)
   }
   ki->minScanCode = ephyrKeySyms.minKeyCode;
   ki->maxScanCode = ephyrKeySyms.maxKeyCode;
+  if (ki->name)
+      xfree(ki->name);
   ki->name = strdup("Xephyr virtual keyboard");
   ephyrKbd = ki;
   return Success;
diff --git a/hw/kdrive/src/kinfo.c b/hw/kdrive/src/kinfo.c
index cb64613..4551fd7 100644
--- a/hw/kdrive/src/kinfo.c
+++ b/hw/kdrive/src/kinfo.c
@@ -166,6 +166,12 @@ KdFreeKeyboard(KdKeyboardInfo *ki)
         xfree(ki->name);
     if (ki->path)
         xfree(ki->path);
+    if (ki->xkbRules)
+        xfree(ki->xkbRules);
+    if (ki->xkbModel)
+        xfree(ki->xkbModel);
+    if (ki->xkbLayout)
+        xfree(ki->xkbLayout);
     ki->next = NULL;
     xfree(ki);
 }
commit 48ab48a6ce12605c7353b45dff4e3a4338b9132e
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Sep 23 11:44:12 2009 +1000

    dix: plug memory leak in DeviceEnterLeaveEvents.
    
    'event' must be freed before exiting.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit fd913136732ff14a0484ca28f60ac1fbf49be81d)

diff --git a/dix/events.c b/dix/events.c
index a79cf6d..d60b8a5 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -4414,10 +4414,12 @@ DeviceEnterLeaveEvent(
                         filter, grab);
     } else {
         if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event))
-            return;
+            goto out;
         DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter,
                               NullGrab);
     }
+
+out:
     xfree(event);
 }
 
commit 9e39491166eb4540bbc72e963e673c976301e936
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Sep 24 14:05:52 2009 +1000

    Xi: fix length calculation for ValuatorState in QueryDeviceState reply.
    
    The length field needs to include the bytes required for the valuators
    (INT32) as well.
    
    The reply length has the right value and since the valuator state is always
    last, clients didn't notice the wrong offset.
    
    Tested-by: Thomas Jaeger
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    (cherry picked from commit 6ee796e9bb4e46782b50a69c7b4fa5b49576f139)

diff --git a/Xi/queryst.c b/Xi/queryst.c
index 60ec32e..2ba1edb 100644
--- a/Xi/queryst.c
+++ b/Xi/queryst.c
@@ -147,7 +147,7 @@ ProcXQueryDeviceState(ClientPtr client)
     if (v != NULL) {
 	tv = (xValuatorState *) buf;
 	tv->class = ValuatorClass;
-	tv->length = sizeof(xValuatorState);
+	tv->length = sizeof(xValuatorState) + v->numAxes * 4;
 	tv->num_valuators = v->numAxes;
 	tv->mode = v->mode;
 	buf += sizeof(xValuatorState);


More information about the xorg-commit mailing list