[Xquartz-changes] xserver: Branch 'server-1.8-apple' - 13 commits

Jeremy Huddleston jeremyhu at freedesktop.org
Tue Jun 22 14:45:20 PDT 2010


Rebased ref, commits from common ancestor:
commit 5182e5b77f68d100e9f912df5709c5bf5a2d6721
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Feb 12 19:48:52 2010 -0800

    fb: Revert fb changes that broke XQuartz
    
    http://bugs.freedesktop.org/show_bug.cgi?id=26124
    
    Revert "Fix source pictures getting random transforms after 2d6a8f668342a5190cdf43b5."
    Revert "fb: Adjust transform or composite coordinates for pixman operations"
    
    http://bugs.freedesktop.org/26124
    
    This reverts commit a72c65e9176c51de95db2fdbf4c5d946a4911695.
    This reverts commit a6bd5d2e482a5aa84acb3d4932e2a166d8670ef1.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>

diff --git a/fb/fb.h b/fb/fb.h
index 02d6c03..ed21f9e 100644
--- a/fb/fb.h
+++ b/fb/fb.h
@@ -2082,11 +2082,8 @@ fbFillRegionSolid (DrawablePtr	pDrawable,
 		   FbBits	xor);
 
 extern _X_EXPORT pixman_image_t *
-image_from_pict (PicturePtr	pict,
-		 Bool		has_clip,
-		 int		*xoff,
-		 int		*yoff);
-
+image_from_pict (PicturePtr pict,
+		 Bool       has_clip);
 extern _X_EXPORT void free_pixman_pict (PicturePtr, pixman_image_t *);
 
 #endif /* _FB_H_ */
diff --git a/fb/fbpict.c b/fb/fbpict.c
index dddfce8..07a2286 100644
--- a/fb/fbpict.c
+++ b/fb/fbpict.c
@@ -158,24 +158,19 @@ fbComposite (CARD8      op,
 	     CARD16     height)
 {
     pixman_image_t *src, *mask, *dest;
-    int src_xoff, src_yoff;
-    int msk_xoff, msk_yoff;
-    int dst_xoff, dst_yoff;
     
     miCompositeSourceValidate (pSrc, xSrc - xDst, ySrc - yDst, width, height);
     if (pMask)
 	miCompositeSourceValidate (pMask, xMask - xDst, yMask - yDst, width, height);
     
-    src = image_from_pict (pSrc, FALSE, &src_xoff, &src_yoff);
-    mask = image_from_pict (pMask, FALSE, &msk_xoff, &msk_yoff);
-    dest = image_from_pict (pDst, TRUE, &dst_xoff, &dst_yoff);
+    src = image_from_pict (pSrc, TRUE);
+    mask = image_from_pict (pMask, TRUE);
+    dest = image_from_pict (pDst, TRUE);
 
     if (src && dest && !(pMask && !mask))
     {
 	pixman_image_composite (op, src, mask, dest,
-				xSrc + src_xoff, ySrc + src_yoff,
-				xMask + msk_xoff, yMask + msk_yoff,
-				xDst + dst_xoff, yDst + dst_yoff,
+				xSrc, ySrc, xMask, yMask, xDst, yDst,
 				width, height);
     }
 
@@ -275,22 +270,22 @@ create_conical_gradient_image (PictGradient *gradient)
 
 static pixman_image_t *
 create_bits_picture (PicturePtr pict,
-		     Bool       has_clip,
-		     int	*xoff,
-		     int	*yoff)
+		     Bool       has_clip)
 {
-    PixmapPtr pixmap;
     FbBits *bits;
     FbStride stride;
-    int bpp;
+    int bpp, xoff, yoff;
     pixman_image_t *image;
     
-    fbGetDrawablePixmap (pict->pDrawable, pixmap, *xoff, *yoff);
-    fbGetPixmapBitsData(pixmap, bits, stride, bpp);
+    fbGetDrawable (pict->pDrawable, bits, stride, bpp, xoff, yoff);
+
+    bits = (FbBits*)((CARD8*)bits +
+		     (pict->pDrawable->y + yoff) * stride * sizeof(FbBits) +
+		     (pict->pDrawable->x + xoff) * (bpp / 8));
 
     image = pixman_image_create_bits (
 	pict->format,
-	pixmap->drawable.width, pixmap->drawable.height,
+	pict->pDrawable->width, pict->pDrawable->height,
 	(uint32_t *)bits, stride * sizeof (FbStride));
     
     
@@ -316,52 +311,30 @@ create_bits_picture (PicturePtr pict,
 	if (pict->clientClipType != CT_NONE)
 	    pixman_image_set_has_client_clip (image, TRUE);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, *xoff, *yoff);
+	pixman_region_translate (pict->pCompositeClip, - pict->pDrawable->x, - pict->pDrawable->y);
 
 	pixman_image_set_clip_region (image, pict->pCompositeClip);
 
-	if (*xoff || *yoff)
-	    pixman_region_translate (pict->pCompositeClip, -*xoff, -*yoff);
+	pixman_region_translate (pict->pCompositeClip, pict->pDrawable->x, pict->pDrawable->y);
     }
     
     /* Indexed table */
     if (pict->pFormat->index.devPrivate)
 	pixman_image_set_indexed (image, pict->pFormat->index.devPrivate);
 
-    /* Add in drawable origin to position within the image */
-    *xoff += pict->pDrawable->x;
-    *yoff += pict->pDrawable->y;
-
     return image;
 }
 
 static void
-set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+set_image_properties (pixman_image_t *image, PicturePtr pict)
 {
     pixman_repeat_t repeat;
     pixman_filter_t filter;
     
     if (pict->transform)
     {
-	/* For source images, adjust the transform to account
-	 * for the drawable offset within the pixman image,
-	 * then set the offset to 0 as it will be used
-	 * to compute positions within the transformed image.
-	 */
-	if (!has_clip) {
-	    struct pixman_transform	adjusted;
-
-	    adjusted = *pict->transform;
-	    pixman_transform_translate(&adjusted,
-				       NULL,
-				       pixman_int_to_fixed(*xoff),
-				       pixman_int_to_fixed(*yoff));
-	    pixman_image_set_transform (image, &adjusted);
-	    *xoff = 0;
-	    *yoff = 0;
-	} else
-	    pixman_image_set_transform (image, pict->transform);
+	pixman_image_set_transform (
+	    image, (pixman_transform_t *)pict->transform);
     }
     
     switch (pict->repeatType)
@@ -388,8 +361,7 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
     
     if (pict->alphaMap)
     {
-	int alpha_xoff, alpha_yoff;
-	pixman_image_t *alpha_map = image_from_pict (pict->alphaMap, FALSE, &alpha_xoff, &alpha_yoff);
+	pixman_image_t *alpha_map = image_from_pict (pict->alphaMap, TRUE);
 	
 	pixman_image_set_alpha_map (
 	    image, alpha_map, pict->alphaOrigin.x, pict->alphaOrigin.y);
@@ -422,7 +394,8 @@ set_image_properties (pixman_image_t *image, PicturePtr pict, Bool has_clip, int
 }
 
 pixman_image_t *
-image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
+image_from_pict (PicturePtr pict,
+		 Bool has_clip)
 {
     pixman_image_t *image = NULL;
 
@@ -431,7 +404,7 @@ image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
 
     if (pict->pDrawable)
     {
-	image = create_bits_picture (pict, has_clip, xoff, yoff);
+	image = create_bits_picture (pict, has_clip);
     }
     else if (pict->pSourcePict)
     {
@@ -452,11 +425,10 @@ image_from_pict (PicturePtr pict, Bool has_clip, int *xoff, int *yoff)
 	    else if (sp->type == SourcePictTypeConical)
 		image = create_conical_gradient_image (gradient);
 	}
-	*xoff = *yoff = 0;
     }
     
     if (image)
-	set_image_properties (image, pict, has_clip, xoff, yoff);
+	set_image_properties (image, pict);
     
     return image;
 }
diff --git a/fb/fbtrap.c b/fb/fbtrap.c
index 515e2e1..830603a 100644
--- a/fb/fbtrap.c
+++ b/fb/fbtrap.c
@@ -40,8 +40,7 @@ fbAddTraps (PicturePtr	pPicture,
 	    int		ntrap,
 	    xTrap	*traps)
 {
-    int image_xoff, image_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &image_xoff, &image_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
@@ -57,8 +56,7 @@ fbRasterizeTrapezoid (PicturePtr    pPicture,
 		      int	    x_off,
 		      int	    y_off)
 {
-    int	mask_xoff, mask_yoff;
-    pixman_image_t *image = image_from_pict (pPicture, FALSE, &mask_xoff, &mask_yoff);
+    pixman_image_t *image = image_from_pict (pPicture, FALSE);
 
     if (!image)
 	return;
commit 2854039f2d88d36e351354d0b186dad4eb82bb0e
Author: Jeremy Huddleston <jeremyhu at apple.com>
Date:   Fri Apr 30 13:08:25 2010 -0700

    Workaround the GC clipping problem in miPaintWindow and add some debugging output.
    
    Signed-off-by: Jeremy Huddleston <jeremyhu at apple.com>
    (cherry picked from commit a9c526bbe10ecf97b6c065fdbc03cc341917a5a6)

diff --git a/mi/miexpose.c b/mi/miexpose.c
index f52b492..21493cb 100644
--- a/mi/miexpose.c
+++ b/mi/miexpose.c
@@ -524,6 +524,7 @@ void RootlessSetPixmapOfAncestors(WindowPtr pWin);
 void RootlessStartDrawing(WindowPtr pWin);
 void RootlessDamageRegion(WindowPtr pWin, RegionPtr prgn);
 Bool IsFramedWindow(WindowPtr pWin);
+#include "../fb/fb.h"
 #endif 
 
 void
@@ -551,24 +552,37 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     Bool	solid = TRUE;
     DrawablePtr	drawable = &pWin->drawable;
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("START %d BS %d (pR = %ld)\n", what, pWin->backgroundState, ParentRelative);
+    ErrorF("      Rgn: %d %d %d %d\n", prgn->extents.x1, prgn->extents.y1,
+	                               prgn->extents.x2 - prgn->extents.x1,
+	                               prgn->extents.y2 - prgn->extents.y1);
+    ErrorF("      Win: %d %d (%d %d) %d %d\n", pWin->origin.x, pWin->origin.y,
+	                                       pWin->winSize.extents.x1, pWin->winSize.extents.y1,
+	                                       pWin->winSize.extents.x2 - pWin->winSize.extents.x1,
+					       pWin->winSize.extents.y2 - pWin->winSize.extents.y1);
+    ErrorF("     Draw: %d %d %d %d\n", pWin->drawable.x, pWin->drawable.y,
+				       pWin->drawable.width, pWin->drawable.height);
+#endif
+
 #ifdef ROOTLESS
     if(!drawable || drawable->type == UNDRAWABLE_WINDOW)
 	return;
-
-    if(IsFramedWindow(pWin)) {
-        RootlessStartDrawing(pWin);
-        RootlessDamageRegion(pWin, prgn);
-    
-        if(pWin->backgroundState == ParentRelative) {
-            if((what == PW_BACKGROUND) || 
-               (what == PW_BORDER && !pWin->borderIsPixel))
-                RootlessSetPixmapOfAncestors(pWin);
-        }
-    }
 #endif
     
     if (what == PW_BACKGROUND)
     {
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+
+	    if(pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	while (pWin->backgroundState == ParentRelative)
 	    pWin = pWin->parent;
 
@@ -590,6 +604,18 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     {
 	PixmapPtr   pixmap;
 
+#ifdef ROOTLESS
+	if(IsFramedWindow(pWin)) {
+	    RootlessStartDrawing(pWin);
+	    RootlessDamageRegion(pWin, prgn);
+	    
+	    if(!pWin->borderIsPixel &&
+		pWin->backgroundState == ParentRelative) {
+		RootlessSetPixmapOfAncestors(pWin);
+	    }
+	}
+#endif
+
 	tile_x_off = drawable->x;
 	tile_y_off = drawable->y;
 	
@@ -598,6 +624,12 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
 	    return;
 	pixmap = (*pScreen->GetWindowPixmap) ((WindowPtr) drawable);
 	drawable = &pixmap->drawable;
+
+#ifdef XQUARTZ_CLIP_DEBUG
+	ErrorF("     Draw: %d %d %d %d\n",
+	       drawable->x, drawable->y, drawable->width, drawable->height);    
+#endif
+	
 #ifdef COMPOSITE
 	draw_x_off = pixmap->screen_x;
 	draw_y_off = pixmap->screen_y;
@@ -660,6 +692,57 @@ miPaintWindow(WindowPtr pWin, RegionPtr prgn, int what)
     dixChangeGC (NullClient, pGC, gcmask, NULL, gcval);
     ValidateGC (drawable, pGC);
 
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);
+#endif
+    
+#ifdef XQUARTZ
+    /* Looks like our clipping isn't set right for some reason:
+     * http://xquartz.macosforge.org/trac/ticket/290
+     */
+    if(what == PW_BORDER) {
+
+#if 0
+	if(solid) {
+#if 1
+	    fbFillRegionSolid(&pWin->drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       pWin->drawable.bitsPerPixel));
+#else
+	    fbFillRegionSolid(drawable,
+			      prgn,
+			      0,
+			      fbReplicatePixel(fill.pixel,
+					       drawable->bitsPerPixel));
+#endif
+	    return;
+	}
+#endif
+    
+	pGC->pCompositeClip->extents.x1 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y1 += prgn->extents.y1;
+	pGC->pCompositeClip->extents.x2 += prgn->extents.x1;
+	pGC->pCompositeClip->extents.y2 += prgn->extents.y1;
+	
+	if(pGC->pCompositeClip->extents.x2 > drawable->pScreen->width)
+	    pGC->pCompositeClip->extents.x2 = drawable->pScreen->width;
+	if(pGC->pCompositeClip->extents.y2 > drawable->pScreen->height)
+	    pGC->pCompositeClip->extents.y2 = drawable->pScreen->height;
+    }
+#endif
+
+#ifdef XQUARTZ_CLIP_DEBUG
+    ErrorF("       GC: %d %d %d %d\n",
+	   pGC->pCompositeClip->extents.x1, pGC->pCompositeClip->extents.y1,
+	   pGC->pCompositeClip->extents.x2 - pGC->pCompositeClip->extents.x1,
+	   pGC->pCompositeClip->extents.y2 - pGC->pCompositeClip->extents.y1);    
+#endif
+
     numRects = REGION_NUM_RECTS(prgn);
     pbox = REGION_RECTS(prgn);
     for (i= numRects; --i >= 0; pbox++, prect++)
commit 2ae159bad4178bd0d0b4664b895e085835396ffc
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jun 21 11:41:22 2010 +1000

    xserver 1.8.1.902
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/configure.ac b/configure.ac
index 73a7b62..01d3d17 100644
--- a/configure.ac
+++ b/configure.ac
@@ -26,8 +26,8 @@ dnl
 dnl Process this file with autoconf to create configure.
 
 AC_PREREQ(2.57)
-AC_INIT([xorg-server], 1.8.1.901, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
-RELEASE_DATE="2010-05-11"
+AC_INIT([xorg-server], 1.8.1.902, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+RELEASE_DATE="2010-06-21"
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_INIT_AUTOMAKE([foreign dist-bzip2])
 AM_MAINTAINER_MODE
commit 600bdf0350f538e7baa6b48f37f77c905e6fd17d
Merge: cc9f680... 5986030...
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jun 21 11:34:35 2010 +1000

    Merge branch 'dri2-backports' into server-1.8-branch

commit cc9f6806ac0d45e122c24c0e99c1db70a6d5ca12
Author: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
Date:   Sun Jun 13 18:05:26 2010 +0200

    DRI2/xserver: Don't hang in glXSwapBuffers if drawable moves between crtc's (bug 28383)
    
    Detect if a drawable has been moved from an original crtc to a new crtc
    with a lower current vblank count than the original crtc inbetween
    glXSwapBuffers() calls. Reinitialize drawable's last_swap_target
    before scheduling next swap if such a move has taken place.
    
    last_swap_target defines the baseline for scheduling the next swap.
    If a movement between crtc's is not taken into account, the swap may
    schedule for a vblank count on the new crtc far in the future, resulting
    in a apparent "hang" of the drawable for a long time.
    
    Fixes Bugzilla bug #28383.
    
    Signed-off-by: Mario Kleiner <mario.kleiner at tuebingen.mpg.de>
    Reviewed-by: Jesse Barnes <jbarnes at virtuousgeek.org>
    Signed-off-by: Keith Packard <keithp at keithp.com>
    (cherry picked from commit 75beadd766fed7b12a76e59e57c244e297c2d2cb)

diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 7d670ff..62734d1 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -614,6 +614,7 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
     DRI2DrawablePtr pPriv;
     DRI2BufferPtr   pDestBuffer = NULL, pSrcBuffer = NULL;
     int             ret, i;
+    CARD64          ust, current_msc;
 
     pPriv = DRI2GetDrawable(pDraw);
     if (pPriv == NULL) {
@@ -658,12 +659,26 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
      * need to schedule a swap for the last swap target + the swap interval.
      */
     if (target_msc == 0 && divisor == 0 && remainder == 0) {
+	/* If the current vblank count of the drawable's crtc is lower
+	 * than the count stored in last_swap_target from a previous swap
+	 * then reinitialize last_swap_target to the current crtc's msc,
+	 * otherwise the swap will hang. This will happen if the drawable
+	 * is moved to a crtc with a lower refresh rate, or a crtc that just
+	 * got enabled.
+	 */
+	if (!(*ds->GetMSC)(pDraw, &ust, &current_msc))
+	    pPriv->last_swap_target = 0;
+
+	if (current_msc < pPriv->last_swap_target)
+	    pPriv->last_swap_target = current_msc;
+
 	/*
 	 * Swap target for this swap is last swap target + swap interval since
 	 * we have to account for the current swap count, interval, and the
 	 * number of pending swaps.
 	 */
 	*swap_target = pPriv->last_swap_target + pPriv->swap_interval;
+
     } else {
 	/* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
 	*swap_target = target_msc;
commit 557301d5c7631e84ad769e6f40a3172a3fdd2369
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Tue Jun 15 13:22:20 2010 +1000

    dix: the default axis mode is Relative, not "0".
    
    Yay for readability.
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>

diff --git a/dix/devices.c b/dix/devices.c
index 91dd4fd..2226ff2 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -1484,7 +1484,7 @@ InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, Atom* btn_
 
     return(InitButtonClassDeviceStruct(dev, numButtons, btn_labels, map) &&
 	   InitValuatorClassDeviceStruct(dev, numAxes, axes_labels,
-					 numMotionEvents, 0) &&
+					 numMotionEvents, Relative) &&
 	   InitPtrFeedbackClassDeviceStruct(dev, controlProc));
 }
 
commit e50f84d69811baea04ef559d846e4588c4bc4c8e
Author: Éric Piel <E.A.B.Piel at tudelft.nl>
Date:   Fri Jun 11 09:16:32 2010 -0700

    exa: fix ExaCheckCopyNtoN for exa_classic when source = dest
    
    In case you want to copy a region with source = dest, you have the same pixmap
    as source and dest.
    
    At the end of exaPixmapIsOffscreen_classic() the devPrivate.ptr is reset to
    NULL (look at the sources).
    
    Now this is what happens in ExaCheckCopyNtoN:
    
    exaPrepareAccess( pDst );
       Calls IsOffscreen()
          sets devPrivate.ptr to NULL
       sets up devPrivate.ptr to real pointer
       Everything OK
    exaPrepareAccess( pSrc );
       Calls IsOffscreen()
          sets devPrivate.ptr to NULL
       BAILS OUT CAUSE OF NESTED OPERATION SINCE DST EQUALS SRC
    
    We end up with devPrivate.ptr as NULL, and that is clearly wrong.
    
    In particular this fixes a segfault when using the psb driver (bug 28077)
    
    Signed-off-by: Éric Piel <eric.piel at tremplin-utc.net>
    Reviewed-by: Michel Dänzer <michel at daenzer.net>
    Signed-off-by: Keith Packard <keithp at keithp.com>
    (cherry picked from commit 7e8f1001217326cc451974bacf25275420c4bb4e)

diff --git a/exa/exa_classic.c b/exa/exa_classic.c
index c31e2d4..9bc369e 100644
--- a/exa/exa_classic.c
+++ b/exa/exa_classic.c
@@ -256,9 +256,10 @@ exaPixmapHasGpuCopy_classic(PixmapPtr pPixmap)
     Bool ret;
 
     if (pExaScr->info->PixmapIsOffscreen) {
+	void* old_ptr = pPixmap->devPrivate.ptr;
 	pPixmap->devPrivate.ptr = ExaGetPixmapAddress(pPixmap);
 	ret = pExaScr->info->PixmapIsOffscreen(pPixmap);
-	pPixmap->devPrivate.ptr = NULL;
+	pPixmap->devPrivate.ptr = old_ptr;
     } else
 	ret = (pExaPixmap->use_gpu_copy && pExaPixmap->fb_ptr);
 
commit 75c1ba8b4fd0cbf5a6eb41fefc4ec728790589df
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Thu Jun 10 12:21:36 2010 +1000

    Xi: don't copy the modifier key count when copying device classes (#25480)
    
    The modifier key count is maintained by the XKB layer and
    increased/decreased for all modifiers that set state.
    
    Test case, MD/SD modifier key count in comment:
    1. keyboard 1: press and hold Shift_L    # SD:1     MD:1
    2. keyboard 2: press and release Shift_L # SD:1,0   MD:1,0
    <class copy happens>                     # SD:1     MD:1
    3. keyboard 1: release Shift_L           # SD:0     MD:1
    4. keyboard 1: press and release Shift_L # SD:1,0   MD:2,1
    
    The modifier is now logically down on the MD but not on keyboard 1 or
    keyboard 2.
    
    XKB is layered in before the DIX, it increases/decreases the modifier key
    count accordingly. In the above example, during (2), the MD gets the key
    release and thus clears the modifier bit. (3) doesn't forward the release to
    the MD because it is already cleared. The copy of modifierKeysDown when the
    lastSlave changes however increases the counter for the held key. On (4),
    the press and release are both forwarded to the MD, causing a offset by 1
    and thus do not clear the logical modifier state.
    
    X.Org Bug 25480 <http://bugs.freedesktop.org/show_bug.cgi?id=25480>
    
    Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
    Acked-by: Daniel Stone <daniel at fooishbar.org>
    (cherry picked from commit dc614484f93b67e8b62dbb1bb2fd247fe5a4c850)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e680f6f..566b0ef 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -196,16 +196,12 @@ void
 CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
 {
     KeyClassPtr mk = master->key;
-    KeyClassPtr dk = device->key;
-    int i;
 
     if (device == master)
         return;
 
     mk->sourceid = device->id;
 
-    for (i = 0; i < 8; i++)
-        mk->modifierKeyCount[i] = dk->modifierKeyCount[i];
 
     if (!XkbCopyDeviceKeymap(master, device))
         FatalError("Couldn't pivot keymap from device to core!\n");
commit 598603021f6c4fa64161366177e93de67511bc2e
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Jun 2 11:13:17 2010 +1000

    dri2: Take an XID for tracking the DRI2 drawable
    
    Some pixmaps (window pixmaps and scratch pixmaps) don't have the
    drawable->id set and thus DRI2 gets confused when using that field
    for looking up the DRI2 drawable.  Go back to using privates for getting
    at the DRI2 drawable from a DrawablePtr.  We need to keep the resource
    tracking in place so we can remove the DRI2 drawable when the X resource
    it was created for goes away.  Additionally, we also now track the DRI2
    drawable using a client XID so we can reclaim the DRI2 drawable even if
    the client goes before the drawable and doesn't destroy the DRI2 drawable.
    
    Tested-by: Owen W. Taylor <otaylor at fishsoup.net>
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    (cherry picked from commit 9de0e31746d5f0d9d39d11c94ec3cbc04a9935fc)
    
    Conflicts:
    
    	hw/xfree86/dri2/dri2.c

diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index 087d52e..ec3bbe6 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -512,8 +512,9 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
     if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
 	return NULL;
 
-    pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen,
-						pDraw, GLX_DRAWABLE_WINDOW,
+    pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
+						pDraw, drawId,
+						GLX_DRAWABLE_WINDOW,
 						drawId, glxc->config);
 
     /* since we are creating the drawablePrivate, drawId should be new */
@@ -1104,15 +1105,17 @@ __glXDrawableRelease(__GLXdrawable *drawable)
 }
 
 static int 
-DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config,
-		    DrawablePtr pDraw, XID glxDrawableId, int type)
+DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
+		    __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
+		    XID glxDrawableId, int type)
 {
     __GLXdrawable *pGlxDraw;
 
     if (pGlxScreen->pScreen != pDraw->pScreen)
 	return BadMatch;
 
-    pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type,
+    pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
+					  drawableId, type,
 					  glxDrawableId, config);
     if (pGlxDraw == NULL)
 	return BadAlloc;
@@ -1125,7 +1128,7 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf
     /* Add the glx drawable under the XID of the underlying X drawable
      * too.  That way we'll get a callback in DrawableGone and can
      * clean up properly when the drawable is destroyed. */
-    if (pDraw->id != glxDrawableId &&
+    if (drawableId != glxDrawableId &&
 	!AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
 	pGlxDraw->destroy (pGlxDraw);
 	return BadAlloc;
@@ -1153,7 +1156,7 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config
 	return BadPixmap;
     }
 
-    err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw,
+    err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
 			      glxDrawableId, GLX_DRAWABLE_PIXMAP);
 
     return err;
@@ -1316,7 +1319,8 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
 	return BadAlloc;
 
     return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
-			       glxDrawableId, GLX_DRAWABLE_PBUFFER);
+			       glxDrawableId, glxDrawableId,
+			       GLX_DRAWABLE_PBUFFER);
 }
 
 int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
@@ -1439,7 +1443,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
 	return err;
 
     return DoCreateGLXDrawable(client, pGlxScreen, config,
-			       pDraw, req->glxwindow, GLX_DRAWABLE_WINDOW);
+			       pDraw, req->window,
+			       req->glxwindow, GLX_DRAWABLE_WINDOW);
 }
 
 int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)
diff --git a/glx/glxdri.c b/glx/glxdri.c
index 21e44d1..e4870c3 100644
--- a/glx/glxdri.c
+++ b/glx/glxdri.c
@@ -682,10 +682,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
 }
 
 static __GLXdrawable *
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
+__glXDRIscreenCreateDrawable(ClientPtr client,
+			     __GLXscreen *screen,
 			     DrawablePtr pDraw,
-			     int type,
 			     XID drawId,
+			     int type,
+			     XID glxDrawId,
 			     __GLXconfig *glxConfig)
 {
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
@@ -699,7 +701,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
 	return NULL;
 
     if (!__glXDrawableInit(&private->base, screen,
-			   pDraw, type, drawId, glxConfig)) {
+			   pDraw, type, glxDrawId, glxConfig)) {
         xfree(private);
 	return NULL;
     }
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 2975bb3..a580df3 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -430,10 +430,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
 }
 
 static __GLXdrawable *
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
+__glXDRIscreenCreateDrawable(ClientPtr client,
+			     __GLXscreen *screen,
 			     DrawablePtr pDraw,
-			     int type,
 			     XID drawId,
+			     int type,
+			     XID glxDrawId,
 			     __GLXconfig *glxConfig)
 {
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
@@ -446,7 +448,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
 
     private->screen = driScreen;
     if (!__glXDrawableInit(&private->base, screen,
-			   pDraw, type, drawId, glxConfig)) {
+			   pDraw, type, glxDrawId, glxConfig)) {
         xfree(private);
 	return NULL;
     }
@@ -457,7 +459,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
     private->base.waitGL	= __glXDRIdrawableWaitGL;
     private->base.waitX		= __glXDRIdrawableWaitX;
 
-    if (DRI2CreateDrawable(pDraw)) {
+    if (DRI2CreateDrawable(client, pDraw, drawId)) {
 	    xfree(private);
 	    return NULL;
     }
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
index c647d83..6a34393 100644
--- a/glx/glxdriswrast.c
+++ b/glx/glxdriswrast.c
@@ -301,10 +301,12 @@ glxChangeGC(GCPtr gc, BITS32 mask, CARD32 val)
 }
 
 static __GLXdrawable *
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
+__glXDRIscreenCreateDrawable(ClientPtr client,
+			     __GLXscreen *screen,
 			     DrawablePtr pDraw,
-			     int type,
 			     XID drawId,
+			     int type,
+			     XID glxDrawId,
 			     __GLXconfig *glxConfig)
 {
     __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
@@ -319,7 +321,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
 
     private->screen = driScreen;
     if (!__glXDrawableInit(&private->base, screen,
-			   pDraw, type, drawId, glxConfig)) {
+			   pDraw, type, glxDrawId, glxConfig)) {
         xfree(private);
 	return NULL;
     }
diff --git a/glx/glxscreens.h b/glx/glxscreens.h
index d52099f..861e03c 100644
--- a/glx/glxscreens.h
+++ b/glx/glxscreens.h
@@ -134,10 +134,12 @@ struct __GLXscreen {
 				    __GLXconfig *modes,
 				    __GLXcontext *shareContext);
 
-    __GLXdrawable *(*createDrawable)(__GLXscreen *context,
+    __GLXdrawable *(*createDrawable)(ClientPtr client,
+				     __GLXscreen *context,
 				     DrawablePtr pDraw,
-				     int type,
 				     XID drawId,
+				     int type,
+				     XID glxDrawId,
 				     __GLXconfig *modes);
     int            (*swapInterval)  (__GLXdrawable *drawable,
 				     int interval);
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index e8985b0..dd9bb41 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -37,6 +37,7 @@
 #include <errno.h>
 #include <xf86drm.h>
 #include "xf86Module.h"
+#include "list.h"
 #include "scrnintstr.h"
 #include "windowstr.h"
 #include "dixstruct.h"
@@ -50,12 +51,18 @@ CARD8 dri2_minor;
 
 static int           dri2ScreenPrivateKeyIndex;
 static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
+static int dri2WindowPrivateKeyIndex;
+static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
+static int dri2PixmapPrivateKeyIndex;
+static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
 static RESTYPE       dri2DrawableRes;
 
 typedef struct _DRI2Screen *DRI2ScreenPtr;
 
 typedef struct _DRI2Drawable {
     DRI2ScreenPtr        dri2_screen;
+    DrawablePtr		 drawable;
+    struct list		 reference_list;
     int			 width;
     int			 height;
     DRI2BufferPtr	*buffers;
@@ -74,6 +81,7 @@ typedef struct _DRI2Drawable {
 
 typedef struct _DRI2Screen {
     ScreenPtr			 screen;
+    int				 refcnt;
     unsigned int		 numDrivers;
     const char			**driverNames;
     const char			*deviceName;
@@ -99,35 +107,33 @@ DRI2GetScreen(ScreenPtr pScreen)
 static DRI2DrawablePtr
 DRI2GetDrawable(DrawablePtr pDraw)
 {
-    DRI2DrawablePtr pPriv;
-    int rc;
-
-    rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
-				 dri2DrawableRes, NULL, DixReadAccess);
-    if (rc != Success)
-	return NULL;
+    WindowPtr pWin;
+    PixmapPtr pPixmap;
 
-    return pPriv;
+    if (pDraw->type == DRAWABLE_WINDOW) {
+	pWin = (WindowPtr) pDraw;
+	return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
+    } else {
+	pPixmap = (PixmapPtr) pDraw;
+	return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
+    }
 }
 
-int
-DRI2CreateDrawable(DrawablePtr pDraw)
+static DRI2DrawablePtr
+DRI2AllocateDrawable(DrawablePtr pDraw)
 {
     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
     DRI2DrawablePtr pPriv;
     CARD64          ust;
-    int rc;
-
-    rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
-				 dri2DrawableRes, NULL, DixReadAccess);
-    if (rc == Success || rc != BadValue)
-	return rc;
+    WindowPtr pWin;
+    PixmapPtr pPixmap;
 
     pPriv = xalloc(sizeof *pPriv);
     if (pPriv == NULL)
-	return BadAlloc;
+	return NULL;
 
-    pPriv->dri2_screen = DRI2GetScreen(pDraw->pScreen);
+    pPriv->dri2_screen = ds;
+    pPriv->drawable = pDraw;
     pPriv->width = pDraw->width;
     pPriv->height = pDraw->height;
     pPriv->buffers = NULL;
@@ -145,9 +151,77 @@ DRI2CreateDrawable(DrawablePtr pDraw)
     pPriv->swap_limit = 1; /* default to double buffering */
     pPriv->last_swap_msc = 0;
     pPriv->last_swap_ust = 0;
+    list_init(&pPriv->reference_list);
 
-    if (!AddResource(pDraw->id, dri2DrawableRes, pPriv))
+    if (pDraw->type == DRAWABLE_WINDOW) {
+	pWin = (WindowPtr) pDraw;
+	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
+    } else {
+	pPixmap = (PixmapPtr) pDraw;
+	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
+    }
+
+    return pPriv;
+}
+
+typedef struct DRI2DrawableRefRec {
+    XID id;
+    XID dri2_id;
+    struct list link;
+} DRI2DrawableRefRec, *DRI2DrawableRefPtr;
+
+static DRI2DrawableRefPtr
+DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id)
+{
+    DRI2DrawableRefPtr ref;
+
+    list_for_each_entry(ref, &pPriv->reference_list, link) {
+	if (ref->id == id)
+	    return ref;
+    }
+    
+    return NULL;
+}
+
+static int
+DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id)
+{
+    DRI2DrawableRefPtr ref;
+
+    ref = malloc(sizeof *ref);
+    if (ref == NULL)
+	return BadAlloc;
+	
+    if (!AddResource(dri2_id, dri2DrawableRes, pPriv))
+	return BadAlloc;
+    if (!DRI2LookupDrawableRef(pPriv, id))
+	if (!AddResource(id, dri2DrawableRes, pPriv))
+	    return BadAlloc;
+
+    ref->id = id;
+    ref->dri2_id = dri2_id; 
+    list_add(&ref->link, &pPriv->reference_list);
+
+    return Success;
+}
+
+int
+DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id)
+{
+    DRI2DrawablePtr pPriv;
+    XID dri2_id;
+    int rc;
+
+    pPriv = DRI2GetDrawable(pDraw);
+    if (pPriv == NULL)
+	pPriv = DRI2AllocateDrawable(pDraw);
+    if (pPriv == NULL)
 	return BadAlloc;
+    
+    dri2_id = FakeClientID(client->index);
+    rc = DRI2AddDrawableRef(pPriv, id, dri2_id);
+    if (rc != Success)
+	return rc;
 
     return Success;
 }
@@ -156,13 +230,45 @@ static int DRI2DrawableGone(pointer p, XID id)
 {
     DRI2DrawablePtr pPriv = p;
     DRI2ScreenPtr   ds = pPriv->dri2_screen;
-    DrawablePtr     root;
+    DRI2DrawableRefPtr ref, next;
+    WindowPtr pWin;
+    PixmapPtr pPixmap;
+    DrawablePtr pDraw;
     int i;
 
-    root = &WindowTable[ds->screen->myNum]->drawable;
+    list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) {
+	if (ref->dri2_id == id) {
+	    list_del(&ref->link);
+	    /* If this was the last ref under this X drawable XID,
+	     * unregister the X drawable resource. */
+	    if (!DRI2LookupDrawableRef(pPriv, ref->id))
+		FreeResourceByType(ref->id, dri2DrawableRes, TRUE);
+	    free(ref);
+	    break;
+	}
+
+	if (ref->id == id) {
+	    list_del(&ref->link);
+	    FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE);
+	    free(ref);
+	}
+    }
+
+    if (!list_is_empty(&pPriv->reference_list))
+	return Success;
+
+    pDraw = pPriv->drawable;
+    if (pDraw->type == DRAWABLE_WINDOW) {
+	pWin = (WindowPtr) pDraw;
+	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
+    } else {
+	pPixmap = (PixmapPtr) pDraw;
+	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
+    }
+
     if (pPriv->buffers != NULL) {
 	for (i = 0; i < pPriv->bufferCount; i++)
-	    (*ds->DestroyBuffer)(root, pPriv->buffers[i]);
+	    (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
 
 	xfree(pPriv->buffers);
     }
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
index ce8a5df..5415a0b 100644
--- a/hw/xfree86/dri2/dri2.h
+++ b/hw/xfree86/dri2/dri2.h
@@ -198,7 +198,8 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
 
 extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
 
-extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
+extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
+					DrawablePtr pDraw, XID id);
 
 extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
 
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 17df130..58eaa10 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -167,7 +167,7 @@ ProcDRI2CreateDrawable(ClientPtr client)
 		       &pDrawable, &status))
 	return status;
 
-    status = DRI2CreateDrawable(pDrawable);
+    status = DRI2CreateDrawable(client, pDrawable, stuff->drawable);
     if (status != Success)
 	return status;
 
commit 7faff42deb4b5a71504377375eba95c3cac2e013
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Wed Jun 2 11:11:21 2010 +1000

    Revert "Revert "DRI2: Track DRI2 drawables as resources, not privates""
    
    This reverts commit c394b17266301d363a9e234f58f8015f74e01307. Follow-up
    patch should fix the reason this was reverted in the first place.
    
    Conflicts:
    
    	hw/xfree86/dri2/dri2.c

diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index e84c28b..2975bb3 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -105,11 +105,6 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
     
     (*core->destroyDrawable)(private->driDrawable);
 
-    /* If the X window was destroyed, the dri DestroyWindow hook will
-     * aready have taken care of this, so only call if pDraw isn't NULL. */
-    if (drawable->pDraw != NULL)
-	DRI2DestroyDrawable(drawable->pDraw);
-
     __glXDrawableRelease(drawable);
 
     xfree(private);
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
index 2bdb733..e8985b0 100644
--- a/hw/xfree86/dri2/dri2.c
+++ b/hw/xfree86/dri2/dri2.c
@@ -48,15 +48,14 @@
 CARD8 dri2_major; /* version of DRI2 supported by DDX */
 CARD8 dri2_minor;
 
-static int dri2ScreenPrivateKeyIndex;
+static int           dri2ScreenPrivateKeyIndex;
 static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
-static int dri2WindowPrivateKeyIndex;
-static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
-static int dri2PixmapPrivateKeyIndex;
-static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
+static RESTYPE       dri2DrawableRes;
+
+typedef struct _DRI2Screen *DRI2ScreenPtr;
 
 typedef struct _DRI2Drawable {
-    unsigned int	 refCount;
+    DRI2ScreenPtr        dri2_screen;
     int			 width;
     int			 height;
     DRI2BufferPtr	*buffers;
@@ -73,9 +72,8 @@ typedef struct _DRI2Drawable {
     int			 swap_limit; /* for N-buffering */
 } DRI2DrawableRec, *DRI2DrawablePtr;
 
-typedef struct _DRI2Screen *DRI2ScreenPtr;
-
 typedef struct _DRI2Screen {
+    ScreenPtr			 screen;
     unsigned int		 numDrivers;
     const char			**driverNames;
     const char			*deviceName;
@@ -101,45 +99,35 @@ DRI2GetScreen(ScreenPtr pScreen)
 static DRI2DrawablePtr
 DRI2GetDrawable(DrawablePtr pDraw)
 {
-    WindowPtr		  pWin;
-    PixmapPtr		  pPixmap;
+    DRI2DrawablePtr pPriv;
+    int rc;
 
-    if (!pDraw)
+    rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
+				 dri2DrawableRes, NULL, DixReadAccess);
+    if (rc != Success)
 	return NULL;
 
-    if (pDraw->type == DRAWABLE_WINDOW)
-    {
-	pWin = (WindowPtr) pDraw;
-	return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
-    }
-    else
-    {
-	pPixmap = (PixmapPtr) pDraw;
-	return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
-    }
+    return pPriv;
 }
 
 int
 DRI2CreateDrawable(DrawablePtr pDraw)
 {
     DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
-    WindowPtr	    pWin;
-    PixmapPtr	    pPixmap;
     DRI2DrawablePtr pPriv;
     CARD64          ust;
+    int rc;
 
-    pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv != NULL)
-    {
-	pPriv->refCount++;
-	return Success;
-    }
+    rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
+				 dri2DrawableRes, NULL, DixReadAccess);
+    if (rc == Success || rc != BadValue)
+	return rc;
 
     pPriv = xalloc(sizeof *pPriv);
     if (pPriv == NULL)
 	return BadAlloc;
 
-    pPriv->refCount = 1;
+    pPriv->dri2_screen = DRI2GetScreen(pDraw->pScreen);
     pPriv->width = pDraw->width;
     pPriv->height = pDraw->height;
     pPriv->buffers = NULL;
@@ -158,43 +146,30 @@ DRI2CreateDrawable(DrawablePtr pDraw)
     pPriv->last_swap_msc = 0;
     pPriv->last_swap_ust = 0;
 
-    if (pDraw->type == DRAWABLE_WINDOW)
-    {
-	pWin = (WindowPtr) pDraw;
-	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
-    }
-    else
-    {
-	pPixmap = (PixmapPtr) pDraw;
-	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
-    }
+    if (!AddResource(pDraw->id, dri2DrawableRes, pPriv))
+	return BadAlloc;
 
     return Success;
 }
 
-static void
-DRI2FreeDrawable(DrawablePtr pDraw)
+static int DRI2DrawableGone(pointer p, XID id)
 {
-    DRI2DrawablePtr pPriv;
-    WindowPtr  	    pWin;
-    PixmapPtr	    pPixmap;
+    DRI2DrawablePtr pPriv = p;
+    DRI2ScreenPtr   ds = pPriv->dri2_screen;
+    DrawablePtr     root;
+    int i;
 
-    pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv == NULL)
-	return;
+    root = &WindowTable[ds->screen->myNum]->drawable;
+    if (pPriv->buffers != NULL) {
+	for (i = 0; i < pPriv->bufferCount; i++)
+	    (*ds->DestroyBuffer)(root, pPriv->buffers[i]);
+
+	xfree(pPriv->buffers);
+    }
 
     xfree(pPriv);
 
-    if (pDraw->type == DRAWABLE_WINDOW)
-    {
-	pWin = (WindowPtr) pDraw;
-	dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
-    }
-    else
-    {
-	pPixmap = (PixmapPtr) pDraw;
-	dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
-    }
+    return Success;
 }
 
 static int
@@ -506,9 +481,6 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
     pPriv->blockedClient = NULL;
     pPriv->blockedOnMsc = FALSE;
 
-    /* If there's still a swap pending, let DRI2SwapComplete free it */
-    if (pPriv->refCount == 0 && pPriv->swapsPending == 0)
-	DRI2FreeDrawable(pDraw);
 }
 
 static void
@@ -576,13 +548,6 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
     pPriv->last_swap_ust = ust;
 
     DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
-
-    /*
-     * It's normal for the app to have exited with a swap outstanding, but
-     * don't free the drawable until they're all complete.
-     */
-    if (pPriv->swapsPending == 0 && pPriv->refCount == 0)
-	DRI2FreeDrawable(pDraw);
 }
 
 Bool
@@ -750,7 +715,7 @@ DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
     Bool ret;
 
     pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv == NULL || pPriv->refCount == 0)
+    if (pPriv == NULL)
 	return BadDrawable;
 
     /* Old DDX just completes immediately */
@@ -774,7 +739,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
     DRI2DrawablePtr pPriv;
 
     pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv == NULL || pPriv->refCount == 0)
+    if (pPriv == NULL)
 	return BadDrawable;
 
     /* target_sbc == 0 means to block until all pending swaps are
@@ -800,36 +765,6 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
     return Success;
 }
 
-void
-DRI2DestroyDrawable(DrawablePtr pDraw)
-{
-    DRI2ScreenPtr   ds = DRI2GetScreen(pDraw->pScreen);
-    DRI2DrawablePtr pPriv;
-
-    pPriv = DRI2GetDrawable(pDraw);
-    if (pPriv == NULL)
-	return;
-
-    pPriv->refCount--;
-    if (pPriv->refCount > 0)
-	return;
-
-    if (pPriv->buffers != NULL) {
-	int i;
-
-	for (i = 0; i < pPriv->bufferCount; i++)
-	    (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
-
-	xfree(pPriv->buffers);
-    }
-
-    /* If the window is destroyed while we have a swap or wait pending, don't
-     * actually free the priv yet.  We'll need it in the DRI2SwapComplete()
-     * callback and we'll free it there once we're done. */
-    if (!pPriv->swapsPending && !pPriv->blockedClient)
-	DRI2FreeDrawable(pDraw);
-}
-
 Bool
 DRI2HasSwapControl(ScreenPtr pScreen)
 {
@@ -890,6 +825,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
     if (!ds)
 	return FALSE;
 
+    ds->screen         = pScreen;
     ds->fd	       = info->fd;
     ds->deviceName     = info->deviceName;
     dri2_major         = 1;
@@ -961,6 +897,8 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
 {
     static Bool setupDone = FALSE;
 
+    dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
+
     if (!setupDone)
     {
 	setupDone = TRUE;
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
index 094d54d..17df130 100644
--- a/hw/xfree86/dri2/dri2ext.c
+++ b/hw/xfree86/dri2/dri2ext.c
@@ -51,7 +51,6 @@
 #include "xf86Module.h"
 
 static ExtensionEntry	*dri2Extension;
-static RESTYPE		 dri2DrawableRes;
 
 static Bool
 validDrawable(ClientPtr client, XID drawable, Mask access_mode,
@@ -172,11 +171,6 @@ ProcDRI2CreateDrawable(ClientPtr client)
     if (status != Success)
 	return status;
 
-    if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) {
-	DRI2DestroyDrawable(pDrawable);
-	return BadAlloc;
-    }
-
     return client->noClientException;
 }
 
@@ -192,8 +186,6 @@ ProcDRI2DestroyDrawable(ClientPtr client)
 		       &pDrawable, &status))
 	return status;
 
-    FreeResourceByType(stuff->drawable, dri2DrawableRes, FALSE);
-
     return client->noClientException;
 }
 
@@ -627,25 +619,11 @@ SProcDRI2Dispatch (ClientPtr client)
     }
 }
 
-static int DRI2DrawableGone(pointer p, XID id)
-{
-    DrawablePtr pDrawable = p;
-
-    DRI2DestroyDrawable(pDrawable);
-
-    return Success;
-}
-
 int DRI2EventBase;
 
 static void
 DRI2ExtensionInit(void)
 {
-    dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
-
-    if (!dri2DrawableRes)
-	return;
-
     dri2Extension = AddExtension(DRI2_NAME,
 				 DRI2NumberEvents,
 				 DRI2NumberErrors,
commit 95f56176255d5b689b06793d9cbeed36c6a46227
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Sat May 1 13:15:00 2010 -0400

    list.h: Add list_for_each_entry_safe()
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    (cherry picked from commit 32381363cd8f43aeb741bad70bcf96a287dac0c9)

diff --git a/include/list.h b/include/list.h
index a126a65..89dc29d 100644
--- a/include/list.h
+++ b/include/list.h
@@ -94,4 +94,10 @@ list_is_empty(struct list *head)
 	 &pos->member != (head);					\
 	 pos = __container_of(pos->member.next, pos, member))
 
+#define list_for_each_entry_safe(pos, next, head, member)		\
+    for (pos = __container_of((head)->next, pos, member),		\
+	 next = __container_of(pos->member.next, pos, member);		\
+	 &pos->member != (head);					\
+	 pos = next, next = __container_of(next->member.next, next, member))
+
 #endif
commit 44521bb9d03a0b7af10f89c98e51bd4109fec327
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Sat May 1 13:13:54 2010 -0400

    glxdri2: Hard-code the extension version we need
    
    If we use the #define'd version from dri_interface.h, the server will
    require at least that version of the extension.  If we're compiling against
    a dri_interface.h with a newer version we don't really require, glxdri2
    will require a too high version of the extension.
    
    The right approach is to just hard-code the version we need instead of
    using the #defines.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Ian Romanick <ian.d.romanick at intel.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>
    (cherry picked from commit 4a8a615d01b9ed18c272414bd11dc2fc661727e5)

diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index e791bf6..e84c28b 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -658,7 +658,7 @@ initializeExtensions(__GLXDRIscreen *screen)
 
 #ifdef __DRI2_FLUSH
 	if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
-	    extensions[i]->version >= __DRI2_FLUSH_VERSION) {
+	    extensions[i]->version >= 3) {
 		screen->flush = (__DRI2flushExtension *) extensions[i];
 	}
 #endif
@@ -718,11 +718,11 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
     
     for (i = 0; extensions[i]; i++) {
         if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
-	    extensions[i]->version >= __DRI_CORE_VERSION) {
+	    extensions[i]->version >= 1) {
 		screen->core = (const __DRIcoreExtension *) extensions[i];
 	}
         if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
-	    extensions[i]->version >= __DRI_DRI2_VERSION) {
+	    extensions[i]->version >= 1) {
 		screen->dri2 = (const __DRIdri2Extension *) extensions[i];
 	}
     }
commit a847cc9bce744cab72637d62bc6bd45237bd3de5
Author: Kristian Høgsberg <krh at bitplanet.net>
Date:   Sat May 1 13:07:46 2010 -0400

    dix: Update element count in FreeResource*()
    
    FreeResource() keeps clientTable[cid].elements up to date with the
    number of resources allocated to the client.  The other free
    resource functions (FreeResourceByType(),
    FreeClientNeverRetainResources() and FreeClientResources()) don't
    maintain this invariant.
    
    Typically, the only consequence is that the element count is too high
    and we end up allocating the hash table bigger than necessary.  However,
    FreeResource() also relies on the element count to restart the search if
    the list of resources has been changed during a resource destruction
    callback.  Since FreeResourceByType() doesn't update the count, if we call
    that from a resource destruction callback from FreeResource(), the
    loop isn't restarted and we end up following an invalid next pointer.
    
    Furthermore, LookupClientResourceComplex() and
    FreeClientNeverRetainResources() don't use the element count to detect
    if a callback deleted a resource and may end up following an invalid
    next pointer if the resource system is called into recursively.
    
    Signed-off-by: Kristian Høgsberg <krh at bitplanet.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    (cherry picked from commit 6d7ba5e0fcb5d1bce6bb213dec009f3a0f802d26)

diff --git a/dix/resource.c b/dix/resource.c
index 91d0cfb..ab3762e 100644
--- a/dix/resource.c
+++ b/dix/resource.c
@@ -589,6 +589,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
 			      res->value, TypeNameString(res->type));
 #endif		    		    
 		*prev = res->next;
+		clientTable[cid].elements--;
 
 		CallResourceStateCallback(ResourceStateFreeing, res);
 
@@ -734,12 +735,14 @@ FreeClientNeverRetainResources(ClientPtr client)
     ResourcePtr *resources;
     ResourcePtr this;
     ResourcePtr *prev;
-    int j;
+    int j, elements;
+    int *eltptr;
 
     if (!client)
 	return;
 
     resources = clientTable[client->index].resources;
+    eltptr = &clientTable[client->index].elements;
     for (j=0; j < clientTable[client->index].buckets; j++) 
     {
 	prev = &resources[j];
@@ -753,11 +756,15 @@ FreeClientNeverRetainResources(ClientPtr client)
 			      this->value, TypeNameString(this->type));
 #endif		    
 		*prev = this->next;
+		clientTable[client->index].elements--;
 
 		CallResourceStateCallback(ResourceStateFreeing, this);
 
+		elements = *eltptr;
 		(*DeleteFuncs[rtype & TypeMask])(this->value, this->id);
 		xfree(this);
+		if (*eltptr != elements)
+		    prev = &resources[j]; /* prev may no longer be valid */
 	    }
 	    else
 		prev = &this->next;
@@ -804,6 +811,7 @@ FreeClientResources(ClientPtr client)
 			  this->value, TypeNameString(this->type));
 #endif		    
 	    *head = this->next;
+	    clientTable[client->index].elements--;
 
 	    CallResourceStateCallback(ResourceStateFreeing, this);
 


More information about the Xquartz-changes mailing list