[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xorg-server: Changes to 'upstream-experimental'



 configure.ac                   |    6 
 hw/xfree86/Makefile.am         |    1 
 hw/xfree86/common/xf86Module.h |    2 
 hw/xfree86/common/xf86xv.c     |   66 ++++
 hw/xfree86/common/xf86xv.h     |    3 
 hw/xfree86/common/xf86xvpriv.h |    1 
 hw/xfree86/ddc/xf86DDC.c       |    7 
 hw/xfree86/fbdevhw/fbdevhw.c   |  160 +++++++---
 hw/xfree86/loader/Makefile.am  |    3 
 hw/xfree86/loader/loadmod.c    |    3 
 hw/xfree86/loader/xf86sym.c    |    7 
 hw/xfree86/modes/Makefile.am   |    4 
 hw/xfree86/modes/xf86Crtc.c    |   49 +++
 hw/xfree86/modes/xf86Crtc.h    |  114 +++++++
 hw/xfree86/modes/xf86Cursors.c |  607 +++++++++++++++++++++++++++++++++++++++++
 hw/xfree86/modes/xf86RandR12.c |    7 
 hw/xfree86/modes/xf86Rotate.c  |   93 ++++--
 hw/xfree86/ramdac/Makefile.am  |    6 
 hw/xfree86/ramdac/xf86Cursor.h |    3 
 randr/mirandr.c                |   11 
 randr/randr.c                  |    2 
 randr/randrstr.h               |   27 -
 randr/rrcrtc.c                 |  175 ++++++-----
 randr/rrinfo.c                 |   11 
 randr/rroutput.c               |   54 +--
 randr/rrproperty.c             |  184 ++++++++----
 26 files changed, 1290 insertions(+), 316 deletions(-)

New commits:
commit 00e33f87f429a5e9e29da30071f03972a4033b8d
Author: Keith Packard <keithp@neko.keithp.com>
Date:   Mon Mar 26 21:21:50 2007 -0700

    Set version to 1.2.99.903 (1.3 RC3)

diff --git a/configure.ac b/configure.ac
index ed2c631..6ba4d03 100644
--- a/configure.ac
+++ b/configure.ac
@@ -25,7 +25,7 @@ dnl Process this file with autoconf to create configure.
 AC_PREREQ(2.57)
 dnl This is the not the Xorg version number, it's the server version number.
 dnl Yes, that's weird.
-AC_INIT([xorg-server], 1.2.99.902, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
+AC_INIT([xorg-server], 1.2.99.903, [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg], xorg-server)
 AC_CONFIG_SRCDIR([Makefile.am])
 AM_INIT_AUTOMAKE([dist-bzip2 foreign])
 AM_MAINTAINER_MODE
@@ -40,8 +40,8 @@ DEFAULT_VENDOR_NAME_SHORT="X.Org"
 DEFAULT_VERSION_MAJOR=1
 DEFAULT_VERSION_MINOR=2
 DEFAULT_VERSION_PATCH=99
-DEFAULT_VERSION_SNAP=902
-DEFAULT_RELEASE_DATE="14 March 2007"
+DEFAULT_VERSION_SNAP=903
+DEFAULT_RELEASE_DATE="26 March 2007"
 DEFAULT_VENDOR_WEB="http://wiki.x.org";
 
 dnl this gets generated by autoheader, and thus contains all the defines.  we

commit 4fd2d3aedfae838940d61598466f89fdb47b1557
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Tue Jan 23 10:15:22 2007 +0100

    Bump video driver ABI version to 1.2.
    
    This is necessary because server-1.2-branch bumped to 1.1 for xf86CVTMode and
    we have xf86XVFillKeyHelperDrawable on top of that.
    (cherry picked from commit 788cfce911793a26aed16f38f30678ecee82c873)
    
    Conflicts:
    
    	hw/xfree86/common/xf86Module.h
    
    Avoid picking up XInput ABI change.

diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index edae6f2..e54d9be 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -84,7 +84,7 @@ typedef enum {
  * mask is 0xFFFF0000.
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 3)
-#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(1, 1)
+#define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(1, 2)
 #define ABI_XINPUT_VERSION	SET_ABI_VERSION(0, 7)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(0, 3)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 5)

commit dc914ced69e1e619a944c7dcb940c25e195cd4f3
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Sun Oct 15 16:48:59 2006 +0200

    Add per-drawable Xv colour key helper function.
    
    This allows overlay Xv adaptors to work slightly better with compositing
    managers.
    
    Bump the video driver ABI minor so drivers only need to check for this at build
    time.
    (cherry picked from commit a232693c8c2a206aac47c07b133c071938204e0b)
    
    Conflicts:
    
    	hw/xfree86/common/xf86Module.h
    
    Avoid picking up XInput ABI version change.

diff --git a/hw/xfree86/common/xf86xv.c b/hw/xfree86/common/xf86xv.c
index 89cb6ba..3e908b8 100644
--- a/hw/xfree86/common/xf86xv.c
+++ b/hw/xfree86/common/xf86xv.c
@@ -974,6 +974,7 @@ xf86XVEnlistPortInWindow(WindowPtr pWin, XvPortRecPrivatePtr portPriv)
    if(!winPriv) {
 	winPriv = xalloc(sizeof(XF86XVWindowRec));
 	if(!winPriv) return BadAlloc;
+	memset(winPriv, 0, sizeof(XF86XVWindowRec));
 	winPriv->PortRec = portPriv;
 	winPriv->next = PrivRoot;
 	pWin->devPrivates[XF86XVWindowIndex].ptr = (pointer)winPriv;
@@ -1026,6 +1027,9 @@ xf86XVDestroyWindow(WindowPtr pWin)
 
      pPriv->pDraw = NULL;
      tmp = WinPriv;
+     if(WinPriv->pGC) {
+       FreeGC(WinPriv->pGC, 0);
+     }
      WinPriv = WinPriv->next;
      xfree(tmp);
   }
@@ -1118,6 +1122,8 @@ xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
   while(WinPriv) {
      pPriv = WinPriv->PortRec;
 
+     if(!pPriv) goto next;
+ 
      if(pPriv->pCompositeClip && pPriv->FreeCompositeClip)
 	REGION_DESTROY(pScreen, pPriv->pCompositeClip);
 
@@ -1148,6 +1154,7 @@ xf86XVClipNotify(WindowPtr pWin, int dx, int dy)
 	}
      }
 
+next:
      pPrev = WinPriv;
      WinPriv = WinPriv->next;
   }
@@ -1739,9 +1746,13 @@ xf86XVPutImage(
      REGION_UNINIT(pScreen, &VPReg);
   }
 
-  if(portPriv->pDraw) {
+  /* If we are changing windows, unregister our port in the old window */
+  if(portPriv->pDraw && (portPriv->pDraw != pDraw))
      xf86XVRemovePortFromWindow((WindowPtr)(portPriv->pDraw), portPriv);
-  }
+
+  /* Register our port with the new window */
+  ret =  xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
+  if(ret != Success) goto PUT_IMAGE_BAILOUT;
 
   if(!REGION_NOTEMPTY(pScreen, &ClipRegion)) {
      clippedAway = TRUE;
@@ -1772,7 +1783,6 @@ xf86XVPutImage(
   if((ret == Success) &&
 	(portPriv->AdaptorRec->flags & VIDEO_OVERLAID_IMAGES)) {
 
-     xf86XVEnlistPortInWindow((WindowPtr)pDraw, portPriv);
      portPriv->isOn = XV_ON;
      portPriv->pDraw = pDraw;
      portPriv->drw_x = drw_x;  portPriv->drw_y = drw_y;
@@ -1813,6 +1823,56 @@ xf86XVQueryImageAttributes(
 			format->id, width, height, pitches, offsets);
 }
 
+
+_X_EXPORT void
+xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr clipboxes)
+{
+   ScreenPtr pScreen = pDraw->pScreen;
+   WindowPtr pWin = (WindowPtr)pDraw;
+   XF86XVWindowPtr pPriv = GET_XF86XV_WINDOW(pWin);
+   GCPtr pGC = NULL;
+   XID pval[2];
+   BoxPtr pbox = REGION_RECTS(clipboxes);
+   int i, nbox = REGION_NUM_RECTS(clipboxes);
+   xRectangle *rects;
+
+   if(!xf86Screens[pScreen->myNum]->vtSema) return;
+
+   if(pPriv)
+      pGC = pPriv->pGC;
+
+   if(!pGC) {
+       int status;
+       pval[0] = key;
+       pval[1] = IncludeInferiors;
+       pGC = CreateGC(pDraw, GCForeground | GCSubwindowMode, pval, &status);
+       if(!pGC) return;
+       ValidateGC(pDraw, pGC);
+       if (pPriv) pPriv->pGC = pGC;
+   } else if (key != pGC->fgPixel){
+       pval[0] = key;
+       ChangeGC(pGC, GCForeground, pval);
+       ValidateGC(pDraw, pGC);
+   }
+
+   REGION_TRANSLATE(pDraw->pScreen, clipboxes, -pDraw->x, -pDraw->y);
+
+   rects = ALLOCATE_LOCAL(nbox * sizeof(xRectangle));
+
+   for(i = 0; i < nbox; i++, pbox++) {
+      rects[i].x = pbox->x1;
+      rects[i].y = pbox->y1;
+      rects[i].width = pbox->x2 - pbox->x1;
+      rects[i].height = pbox->y2 - pbox->y1;
+   }
+
+   (*pGC->ops->PolyFillRect)(pDraw, pGC, nbox, rects);
+
+   if (!pPriv) FreeGC(pGC, 0);
+
+   DEALLOCATE_LOCAL(rects);
+}
+
 _X_EXPORT void
 xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes)
 {
diff --git a/hw/xfree86/common/xf86xv.h b/hw/xfree86/common/xf86xv.h
index e0feb57..817e2b9 100644
--- a/hw/xfree86/common/xf86xv.h
+++ b/hw/xfree86/common/xf86xv.h
@@ -232,6 +232,9 @@ void xf86XVFreeVideoAdaptorRec(XF86VideoAdaptorPtr ptr);
 void
 xf86XVFillKeyHelper (ScreenPtr pScreen, CARD32 key, RegionPtr clipboxes);
 
+void
+xf86XVFillKeyHelperDrawable (DrawablePtr pDraw, CARD32 key, RegionPtr clipboxes);
+
 Bool
 xf86XVClipVideoHelper(
     BoxPtr dst,
diff --git a/hw/xfree86/common/xf86xvpriv.h b/hw/xfree86/common/xf86xvpriv.h
index ced0536..e716c9c 100644
--- a/hw/xfree86/common/xf86xvpriv.h
+++ b/hw/xfree86/common/xf86xvpriv.h
@@ -80,6 +80,7 @@ typedef struct {
 typedef struct _XF86XVWindowRec{
    XvPortRecPrivatePtr PortRec;
    struct _XF86XVWindowRec *next;
+   GCPtr pGC;
 } XF86XVWindowRec, *XF86XVWindowPtr;
 
 #endif  /* _XF86XVPRIV_H_ */
diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c
index 3103976..09d6681 100644
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@ -632,6 +632,7 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMFUNC(xf86XVAllocateVideoAdaptorRec)
     SYMFUNC(xf86XVFreeVideoAdaptorRec)
     SYMFUNC(xf86XVFillKeyHelper)
+    SYMFUNC(xf86XVFillKeyHelperDrawable)
     SYMFUNC(xf86XVClipVideoHelper)
     SYMFUNC(xf86XVCopyYUV12ToPacked)
     SYMFUNC(xf86XVCopyPacked)

commit 96636598ee8a024b2fc93e2779b581446fa22d83
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Fri Jan 19 18:30:21 2007 +0100

    fbdevhw: Only deal with RGB weight if default visual is True- or DirectColor.
    (cherry picked from commit 14d6a9b327381a6bb2dac59c62728e5fd0f0bcfb)

diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c
index 8b163be..a573b8f 100644
--- a/hw/xfree86/fbdevhw/fbdevhw.c
+++ b/hw/xfree86/fbdevhw/fbdevhw.c
@@ -187,9 +187,16 @@ xfree2fbdev_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var)
 			      pScrn->virtualX;
 	var->yres_virtual   = pScrn->virtualY;
 	var->bits_per_pixel = pScrn->bitsPerPixel;
-	var->red.length     = pScrn->weight.red;
-	var->green.length   = pScrn->weight.green;
-	var->blue.length    = pScrn->weight.blue;
+	if (pScrn->defaultVisual == TrueColor ||
+	    pScrn->defaultVisual == DirectColor) {
+	    var->red.length     = pScrn->weight.red;
+	    var->green.length   = pScrn->weight.green;
+	    var->blue.length    = pScrn->weight.blue;
+	} else {
+	    var->red.length     = 8;
+	    var->green.length   = 8;
+	    var->blue.length    = 8;
+	}
 }
 
 static void
@@ -746,15 +753,18 @@ fbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
 		return FALSE;
 	}
 
-	/* XXX: This is a hack, but it should be a NOP for all the setups that
-	 * worked before and actually seems to fix some others...
-	 */
-	pScrn->offset.red   = fPtr->var.red.offset;
-	pScrn->offset.green = fPtr->var.green.offset;
-	pScrn->offset.blue  = fPtr->var.blue.offset;
-	pScrn->mask.red     = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset;
-	pScrn->mask.green   = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset;
-	pScrn->mask.blue    = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset;
+	if (pScrn->defaultVisual == TrueColor ||
+	    pScrn->defaultVisual == DirectColor) {
+	    /* XXX: This is a hack, but it should be a NOP for all the setups that
+	     * worked before and actually seems to fix some others...
+	     */
+	    pScrn->offset.red   = fPtr->var.red.offset;
+	    pScrn->offset.green = fPtr->var.green.offset;
+	    pScrn->offset.blue  = fPtr->var.blue.offset;
+	    pScrn->mask.red     = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset;
+	    pScrn->mask.green   = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset;
+	    pScrn->mask.blue    = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset;
+	}
 
 	return TRUE;
 }

commit 7679b2c6139ee7345b4f65ab84384162bbd796ae
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Fri Jan 19 18:28:05 2007 +0100

    fbdevhw: Consider mode set equal to mode requested if virtual width is larger.
    (cherry picked from commit 27a01e100bff21ac0b70c6d72071d7226fc91264)

diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c
index 8f78b85..8b163be 100644
--- a/hw/xfree86/fbdevhw/fbdevhw.c
+++ b/hw/xfree86/fbdevhw/fbdevhw.c
@@ -229,23 +229,23 @@ xfree2fbdev_timing(DisplayModePtr mode, struct fb_var_screeninfo *var)
 }
 
 static Bool
-fbdev_modes_equal(struct fb_var_screeninfo *one, struct fb_var_screeninfo *two)
-{
-	return (one->xres_virtual == two->xres_virtual &&
-		one->yres_virtual == two->yres_virtual &&
-		one->bits_per_pixel == two->bits_per_pixel &&
-		one->red.length == two->red.length &&
-		one->green.length == two->green.length &&
-		one->blue.length == two->blue.length &&
-		one->xres == two->xres && one->yres == two->yres &&
-		one->pixclock == two->pixclock &&
-		one->right_margin == two->right_margin &&
-		one->hsync_len == two->hsync_len &&
-		one->left_margin == two->left_margin &&
-		one->lower_margin == two->lower_margin &&
-		one->vsync_len == two->vsync_len &&
-		one->upper_margin == two->upper_margin &&
-		one->sync == two->sync && one->vmode == two->vmode);
+fbdev_modes_equal(struct fb_var_screeninfo *set, struct fb_var_screeninfo *req)
+{
+	return (set->xres_virtual >= req->xres_virtual &&
+		set->yres_virtual == req->yres_virtual &&
+		set->bits_per_pixel == req->bits_per_pixel &&
+		set->red.length == req->red.length &&
+		set->green.length == req->green.length &&
+		set->blue.length == req->blue.length &&
+		set->xres == req->xres && set->yres == req->yres &&
+		set->pixclock == req->pixclock &&
+		set->right_margin == req->right_margin &&
+		set->hsync_len == req->hsync_len &&
+		set->left_margin == req->left_margin &&
+		set->lower_margin == req->lower_margin &&
+		set->vsync_len == req->vsync_len &&
+		set->upper_margin == req->upper_margin &&
+		set->sync == req->sync && set->vmode == req->vmode);
 }
 
 static void

commit 1c2793d3ec4c82c7205abb10a1f4d093864425ea
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Sun Dec 31 17:59:44 2006 +0100

    fbdevhw: Override RGB offsets and masks after setting initial mode.
    
    This is a hack, but it should be a NOP for all the setups that worked before
    and actually seems to fix some others...
    
    Based on a patch by Peter Teichmann from
    http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=338241 .
    (cherry picked from commit dc5eb4523298f966bd5fd9ae6672160034b5e82c)

diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c
index a9288a7..8f78b85 100644
--- a/hw/xfree86/fbdevhw/fbdevhw.c
+++ b/hw/xfree86/fbdevhw/fbdevhw.c
@@ -745,6 +745,17 @@ fbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
 			   "FBIOGET_VSCREENINFO: %s\n", strerror(errno));
 		return FALSE;
 	}
+
+	/* XXX: This is a hack, but it should be a NOP for all the setups that
+	 * worked before and actually seems to fix some others...
+	 */
+	pScrn->offset.red   = fPtr->var.red.offset;
+	pScrn->offset.green = fPtr->var.green.offset;
+	pScrn->offset.blue  = fPtr->var.blue.offset;
+	pScrn->mask.red     = ((1 << fPtr->var.red.length) - 1) << fPtr->var.red.offset;
+	pScrn->mask.green   = ((1 << fPtr->var.green.length) - 1) << fPtr->var.green.offset;
+	pScrn->mask.blue    = ((1 << fPtr->var.blue.length) - 1) << fPtr->var.blue.offset;
+
 	return TRUE;
 }
 

commit d7bcad9c694a13c702e429d8364035850d8f8bb7
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Sun Dec 31 17:23:31 2006 +0100

    fbdevhw: Use displayWidth for fbdev virtual width when appropriate.
    
    The fbdev API doesn't allow setting the pitch explicitly, so we have to set
    the virtual width to the pitch we're using for drawing. This fixes corruption
    after changing the virtual width with RandR.
    (cherry picked from commit d077c0da470ab7291e8d838eaace57b066477d6f)

diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c
index 83b0dc1..a9288a7 100644
--- a/hw/xfree86/fbdevhw/fbdevhw.c
+++ b/hw/xfree86/fbdevhw/fbdevhw.c
@@ -183,7 +183,8 @@ print_xfree_mode(char *txt, DisplayModePtr mode)
 static void
 xfree2fbdev_fblayout(ScrnInfoPtr pScrn, struct fb_var_screeninfo *var)
 {
-	var->xres_virtual   = pScrn->virtualX;
+	var->xres_virtual   = pScrn->displayWidth ? pScrn->displayWidth :
+			      pScrn->virtualX;
 	var->yres_virtual   = pScrn->virtualY;
 	var->bits_per_pixel = pScrn->bitsPerPixel;
 	var->red.length     = pScrn->weight.red;

commit 28af734cb7f2e5e40f6524411f77eba0e3960a8d
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Sat Dec 30 16:44:31 2006 +0100

    fbdevhw: Fix some issues with the previous commit.
    
    Fix a TRACE_ENTER typo and only update the internal fbdev mode state cache
    after actually setting a mode.
    (cherry picked from commit c385bcf0bde38dd869f7065f859dd4b4126f5690)

diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c
index 303ad14..83b0dc1 100644
--- a/hw/xfree86/fbdevhw/fbdevhw.c
+++ b/hw/xfree86/fbdevhw/fbdevhw.c
@@ -496,7 +496,7 @@ fbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check)
 	fbdevHWPtr fPtr = FBDEVHWPTR(pScrn);
 	struct fb_var_screeninfo req_var = fPtr->var, set_var;
 	
-	TRACE_ENTER("ModeInit");
+	TRACE_ENTER("SetMode");
 
 	xfree2fbdev_fblayout(pScrn, &req_var);
 	xfree2fbdev_timing(mode, &req_var);
@@ -528,7 +528,8 @@ fbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check)
 		return FALSE;
 	}
 
-	fPtr->var = set_var;
+	if (!check)
+		fPtr->var = set_var;
 
 	return TRUE;
 }

commit c0459d7476f408806b1e7202b960ee0b3911774a
Author: Michel Dänzer <michel@tungstengraphics.com>
Date:   Sat Dec 30 10:18:28 2006 +0100

    fbdevhw: Consolidate modeset ioctl calling, report failure if it modifies mode.
    
    The fbdev API allows the driver to 'accept' modes it doesn't really support by
    modifying it to the nearest supported mode. Without this check, e.g. vesafb
    would appear to accept all modes, even though it actually can't set any modes
    other than the bootup mode at all.
    (cherry picked from commit f6815cb68b0f6698497348fc6e4214dacef33b95)

diff --git a/hw/xfree86/fbdevhw/fbdevhw.c b/hw/xfree86/fbdevhw/fbdevhw.c
index 70bed62..303ad14 100644
--- a/hw/xfree86/fbdevhw/fbdevhw.c
+++ b/hw/xfree86/fbdevhw/fbdevhw.c
@@ -227,6 +227,26 @@ xfree2fbdev_timing(DisplayModePtr mode, struct fb_var_screeninfo *var)
 		var->vmode = FB_VMODE_NONINTERLACED;
 }
 
+static Bool
+fbdev_modes_equal(struct fb_var_screeninfo *one, struct fb_var_screeninfo *two)
+{
+	return (one->xres_virtual == two->xres_virtual &&
+		one->yres_virtual == two->yres_virtual &&
+		one->bits_per_pixel == two->bits_per_pixel &&
+		one->red.length == two->red.length &&
+		one->green.length == two->green.length &&
+		one->blue.length == two->blue.length &&
+		one->xres == two->xres && one->yres == two->yres &&
+		one->pixclock == two->pixclock &&
+		one->right_margin == two->right_margin &&
+		one->hsync_len == two->hsync_len &&
+		one->left_margin == two->left_margin &&
+		one->lower_margin == two->lower_margin &&
+		one->vsync_len == two->vsync_len &&
+		one->upper_margin == two->upper_margin &&
+		one->sync == two->sync && one->vmode == two->vmode);
+}
+
 static void
 fbdev2xfree_timing(struct fb_var_screeninfo *var, DisplayModePtr mode)
 {
@@ -470,13 +490,52 @@ fbdevHWGetVidmem(ScrnInfoPtr pScrn)
 	return fPtr->fix.smem_len;
 }
 
+static Bool
+fbdevHWSetMode(ScrnInfoPtr pScrn, DisplayModePtr mode, Bool check)
+{
+	fbdevHWPtr fPtr = FBDEVHWPTR(pScrn);
+	struct fb_var_screeninfo req_var = fPtr->var, set_var;
+	
+	TRACE_ENTER("ModeInit");
+
+	xfree2fbdev_fblayout(pScrn, &req_var);
+	xfree2fbdev_timing(mode, &req_var);
+
+#if DEBUG
+	print_xfree_mode("init", mode);
+	print_fbdev_mode("init", &req_var);
+#endif
+
+	set_var = req_var;
+
+	if (check)
+		set_var.activate = FB_ACTIVATE_TEST;
+
+	if (0 != ioctl(fPtr->fd, FBIOPUT_VSCREENINFO, (void*)(&set_var))) {
+		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+			   "FBIOPUT_VSCREENINFO: %s\n", strerror(errno));
+		return FALSE;
+	}
+
+	if (!fbdev_modes_equal(&set_var, &req_var)) {
+		if (!check)
+			xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+				   "FBIOPUT_VSCREENINFO succeeded but modified "
+				   "mode\n");
+#if DEBUG
+		print_fbdev_mode("returned", &set_var);
+#endif
+		return FALSE;
+	}
+
+	fPtr->var = set_var;
+
+	return TRUE;
+}
+
 void
 fbdevHWSetVideoModes(ScrnInfoPtr pScrn)
 {
-	fbdevHWPtr fPtr = FBDEVHWPTR(pScrn);
-	int virtX = pScrn->display->virtualX;
-	int virtY = pScrn->display->virtualY;
-	struct fb_var_screeninfo var;
 	char **modename;
 	DisplayModePtr mode,this,last = pScrn->modes;
 
@@ -484,6 +543,9 @@ fbdevHWSetVideoModes(ScrnInfoPtr pScrn)
 	if (NULL == pScrn->display->modes)
 		return;
 
+	pScrn->virtualX = pScrn->display->virtualX;
+	pScrn->virtualY = pScrn->display->virtualY;
+
 	for (modename = pScrn->display->modes; *modename != NULL; modename++) {
 		for (mode = pScrn->monitor->Modes; mode != NULL; mode = mode->next)
 			if (0 == strcmp(mode->name,*modename))
@@ -493,27 +555,20 @@ fbdevHWSetVideoModes(ScrnInfoPtr pScrn)
 				   "\tmode \"%s\" not found\n", *modename);
 			continue;
 		}
-		memset(&var,0,sizeof(var));
-		xfree2fbdev_timing(mode,&var);
-		var.xres_virtual = virtX;
-		var.yres_virtual = virtY;
-		var.bits_per_pixel = pScrn->bitsPerPixel;
-		var.red.length = pScrn->weight.red;
-		var.green.length = pScrn->weight.green;
-		var.blue.length = pScrn->weight.blue;
-
-		var.activate = FB_ACTIVATE_TEST;
-		if (var.xres_virtual < var.xres) var.xres_virtual = var.xres;
-		if (var.yres_virtual < var.yres) var.yres_virtual = var.yres;
-		if (-1 == ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&var))) {
+
+		if (!fbdevHWSetMode(pScrn, mode, TRUE)) {
 			xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 				   "\tmode \"%s\" test failed\n", *modename);
 			continue;
 		}
 		xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 			   "\tmode \"%s\" ok\n", *modename);
-		if (virtX < var.xres) virtX = var.xres;
-		if (virtY < var.yres) virtY = var.yres;
+
+		if (pScrn->virtualX < mode->HDisplay)
+			pScrn->virtualX = mode->HDisplay;
+		if (pScrn->virtualY < mode->VDisplay)
+			pScrn->virtualY = mode->VDisplay;
+
 		if (NULL == pScrn->modes) {
 			pScrn->modes = xnfalloc(sizeof(DisplayModeRec));
 			this = pScrn->modes;
@@ -530,8 +585,6 @@ fbdevHWSetVideoModes(ScrnInfoPtr pScrn)
 		}
 		last = this;
 	}
-	pScrn->virtualX     = virtX;
-	pScrn->virtualY     = virtY;
 }
 
 DisplayModePtr
@@ -673,21 +726,12 @@ fbdevHWModeInit(ScrnInfoPtr pScrn, DisplayModePtr mode)
 {	
 	fbdevHWPtr fPtr = FBDEVHWPTR(pScrn);
 	
-	TRACE_ENTER("ModeInit");
-	xfree2fbdev_fblayout(pScrn, &fPtr->var);
-	xfree2fbdev_timing(mode,  &fPtr->var);
-#if DEBUG
-	print_xfree_mode("init",mode);
-	print_fbdev_mode("init",&fPtr->var);
-#endif
 	pScrn->vtSema = TRUE;
 
 	/* set */
-	if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->var))) {
-		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-			   "FBIOPUT_VSCREENINFO: %s\n", strerror(errno));
+	if (!fbdevHWSetMode(pScrn, mode, FALSE))
 		return FALSE;
-	}
+
 	/* read back */
 	if (0 != ioctl(fPtr->fd,FBIOGET_FSCREENINFO,(void*)(&fPtr->fix))) {
 		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -767,18 +811,12 @@ ModeStatus
 fbdevHWValidMode(int scrnIndex, DisplayModePtr mode, Bool verbose, int flags)
 {
 	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-	fbdevHWPtr fPtr = FBDEVHWPTR(pScrn);
-	struct fb_var_screeninfo var;
 
 	TRACE_ENTER("ValidMode");
-	memcpy(&var,&fPtr->var,sizeof(var));
-	xfree2fbdev_timing(mode, &var);
-	var.activate = FB_ACTIVATE_TEST;
-	if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->var))) {
-		xf86DrvMsg(scrnIndex, X_ERROR,
-			   "FBIOPUT_VSCREENINFO: %s\n", strerror(errno));
+
+	if (!fbdevHWSetMode(pScrn, mode, TRUE))
 		return MODE_BAD;
-	}
+
 	return MODE_OK;
 }
 
@@ -786,15 +824,12 @@ Bool
 fbdevHWSwitchMode(int scrnIndex, DisplayModePtr mode, int flags)
 {
 	ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
-	fbdevHWPtr fPtr = FBDEVHWPTR(pScrn);
 
 	TRACE_ENTER("SwitchMode");
-	xfree2fbdev_timing(mode, &fPtr->var);
-	if (0 != ioctl(fPtr->fd,FBIOPUT_VSCREENINFO,(void*)(&fPtr->var))) {
-		xf86DrvMsg(scrnIndex, X_ERROR,
-			   "FBIOPUT_VSCREENINFO: %s\n", strerror(errno));
+
+	if (!fbdevHWSetMode(pScrn, mode, FALSE))
 		return FALSE;
-	}
+
 	return TRUE;
 }
 

commit 57e87e0d006cbf1f5b175fe02eeb981f741d92f0
Author: Keith Packard <keithp@neko.keithp.com>
Date:   Fri Mar 23 23:41:36 2007 -0700

    Make pending properties force mode set. And, remove AttachScreen calls.
    
    Yes, two changes in one commit. Sorry 'bout that.
    
    The first change ensures that when pending property values have been
    changed, a mode set to the current mode will actually do something, rather
    than being identified as a no-op. In addition, the driver no longer needs to
    manage the migration of pending to current values, that is handled both
    within the xf86 mode setting code (to deal with non-RandR changes) as well
    as within the RandR extension itself.
    
    The second change eliminates the two-call Create/AttachScreen stuff that was
    done in a failed attempt to create RandR resources before the screen
    structures were allocated. Merging these back into the Create function is
    cleaner.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index b9895d9..7d86b66 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -312,7 +312,13 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
     {
 	xf86OutputPtr output = xf86_config->output[i];
 	if (output->crtc == crtc)
+	{
 	    output->funcs->commit(output);
+#ifdef RANDR_12_INTERFACE
+	    if (output->randr_output)
+		RRPostPendingProperties (output->randr_output);
+#endif
+	}
     }
 
     /* XXX free adjustedmode */
diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c
index 4213fea..6f52ee2 100644
--- a/hw/xfree86/modes/xf86RandR12.c
+++ b/hw/xfree86/modes/xf86RandR12.c
@@ -1011,8 +1011,7 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     {
 	xf86CrtcPtr    crtc = config->crtc[c];
 	
-	crtc->randr_crtc = RRCrtcCreate (crtc);
-	RRCrtcAttachScreen (crtc->randr_crtc, pScreen);
+	crtc->randr_crtc = RRCrtcCreate (pScreen, crtc);
 	RRCrtcGammaSetSize (crtc->randr_crtc, 256);
     }
     /*
@@ -1022,13 +1021,13 @@ xf86RandR12CreateObjects12 (ScreenPtr pScreen)
     {
 	xf86OutputPtr	output = config->output[o];
 
-	output->randr_output = RROutputCreate (output->name, 
+	output->randr_output = RROutputCreate (pScreen, output->name, 
 					       strlen (output->name),
 					       output);
-	RROutputAttachScreen (output->randr_output, pScreen);
 
 	if (output->funcs->create_resources != NULL)
 	    output->funcs->create_resources(output);
+	RRPostPendingProperties (output->randr_output);
     }
     return TRUE;
 }
diff --git a/randr/mirandr.c b/randr/mirandr.c
index 47136fb..3c4991e 100644
--- a/randr/mirandr.c
+++ b/randr/mirandr.c
@@ -133,20 +133,13 @@ miRandRInit (ScreenPtr pScreen)
     if (!mode)
 	return FALSE;
     
-    crtc = RRCrtcCreate (NULL);
+    crtc = RRCrtcCreate (pScreen, NULL);
     if (!crtc)
 	return FALSE;
-    if (!RRCrtcAttachScreen (crtc, pScreen))
-    {
-	RRCrtcDestroy (crtc);
-	return FALSE;
-    }
     
-    output = RROutputCreate ("screen", 6, NULL);
+    output = RROutputCreate (pScreen, "screen", 6, NULL);
     if (!output)
 	return FALSE;
-    if (!RROutputAttachScreen (output, pScreen))
-	return FALSE;
     if (!RROutputSetClones (output, NULL, 0))
 	return FALSE;
     if (!RROutputSetModes (output, &mode, 1, 0))
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 40d3eec..6deaf47 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -138,6 +138,7 @@ struct _rrOutput {
     RRModePtr	    *userModes;
     Bool	    changed;
     RRPropertyPtr   properties;
+    Bool	    pendingProperties;
     void	    *devPrivate;
 };
 
@@ -496,7 +497,7 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged);
  * Create a CRTC
  */
 RRCrtcPtr
-RRCrtcCreate (void	*devPrivate);
+RRCrtcCreate (ScreenPtr pScreen, void	*devPrivate);
 
 /*
  * Set the allowed rotations on a CRTC
@@ -505,14 +506,6 @@ void
 RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations);
 
 /*
- * Attach a CRTC to a screen. Once done, this cannot be
- * undone without destroying the CRTC; it is separate from Create
- * only to allow an xf86-based driver to create objects in preinit
- */
-Bool
-RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen);
-    
-/*
  * Notify the extension that the Crtc has been reconfigured,
  * the driver calls this whenever it has updated the mode
  */
@@ -668,19 +661,12 @@ RROutputChanged (RROutputPtr output, Bool configChanged);
  */
 
 RROutputPtr
-RROutputCreate (const char  *name,
+RROutputCreate (ScreenPtr   pScreen,
+		const char  *name,
 		int	    nameLength,
 		void	    *devPrivate);
 
 /*
- * Attach an output to a screen, again split from creation so
- * xf86 DDXen can create randr resources before the ScreenRec
- * exists
- */
-Bool
-RROutputAttachScreen (RROutputPtr output, ScreenPtr pScreen);
-
-/*
  * Notify extension that output parameters have been changed
  */
 Bool
@@ -760,7 +746,7 @@ void
 RRDeleteOutputProperty (RROutputPtr output, Atom property);
 
 Bool
-RRPostPendingProperty (RROutputPtr output, Atom property);
+RRPostPendingProperties (RROutputPtr output);
     
 int
 RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index da88253..1a2a3a7 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -51,17 +51,32 @@ RRCrtcChanged (RRCrtcPtr crtc, Bool layoutChanged)
  * Create a CRTC
  */
 RRCrtcPtr
-RRCrtcCreate (void	*devPrivate)
+RRCrtcCreate (ScreenPtr pScreen, void *devPrivate)
 {
-    RRCrtcPtr	crtc;
-    
+    RRCrtcPtr	    crtc;
+    RRCrtcPtr	    *crtcs;
+    rrScrPrivPtr    pScrPriv;
+
     if (!RRInit())
 	return NULL;
+    
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    /* make space for the crtc pointer */
+    if (pScrPriv->numCrtcs)
+	crtcs = xrealloc (pScrPriv->crtcs, 
+			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
+    else
+	crtcs = xalloc (sizeof (RRCrtcPtr));
+    if (!crtcs)
+	return FALSE;
+    pScrPriv->crtcs = crtcs;
+    
     crtc = xalloc (sizeof (RRCrtcRec));
     if (!crtc)
 	return NULL;
     crtc->id = FakeClientID (0);
-    crtc->pScreen = NULL;
+    crtc->pScreen = pScreen;
     crtc->mode = NULL;
     crtc->x = 0;
     crtc->y = 0;
@@ -77,6 +92,10 @@ RRCrtcCreate (void	*devPrivate)
     if (!AddResource (crtc->id, RRCrtcType, (pointer) crtc))
 	return NULL;
 
+    /* attach the screen and crtc together */
+    crtc->pScreen = pScreen;
+    pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
+    
     return crtc;
 }
 
@@ -90,36 +109,6 @@ RRCrtcSetRotations (RRCrtcPtr crtc, Rotation rotations)
 }
 
 /*
- * Attach a Crtc to a screen. This is done as a separate step
- * so that an xf86-based driver can create CRTCs in PreInit
- * before the Screen has been created
- */
-
-Bool
-RRCrtcAttachScreen (RRCrtcPtr crtc, ScreenPtr pScreen)
-{
-    rrScrPriv (pScreen);
-    RRCrtcPtr	*crtcs;
-
-    /* make space for the crtc pointer */
-    if (pScrPriv->numCrtcs)
-	crtcs = xrealloc (pScrPriv->crtcs, 
-			  (pScrPriv->numCrtcs + 1) * sizeof (RRCrtcPtr));
-    else
-	crtcs = xalloc (sizeof (RRCrtcPtr));
-    if (!crtcs)
-	return FALSE;
-    
-    /* attach the screen and crtc together */
-    crtc->pScreen = pScreen;
-    pScrPriv->crtcs = crtcs;
-    pScrPriv->crtcs[pScrPriv->numCrtcs++] = crtc;
-
-    RRCrtcChanged (crtc, TRUE);
-    return TRUE;
-}
-
-/*
  * Notify the extension that the Crtc has been reconfigured,
  * the driver calls this whenever it has updated the mode
  */
@@ -258,6 +247,22 @@ RRDeliverCrtcEvent (ClientPtr client, WindowPtr pWin, RRCrtcPtr crtc)
     WriteEventsToClient (client, 1, (xEvent *) &ce);
 }
 
+static Bool
+RRCrtcPendingProperties (RRCrtcPtr crtc)
+{
+    ScreenPtr	pScreen = crtc->pScreen;
+    rrScrPriv(pScreen);
+    int		o;
+
+    for (o = 0; o < pScrPriv->numOutputs; o++)
+    {
+	RROutputPtr output = pScrPriv->outputs[o];
+	if (output->crtc == crtc && output->pendingProperties)
+	    return TRUE;
+    }
+    return FALSE;
+}
+
 /*
  * Request that the Crtc be reconfigured
  */
@@ -280,7 +285,8 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	crtc->y == y &&
 	crtc->rotation == rotation &&
 	crtc->numOutputs == numOutputs &&
-	!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)))
+	!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)) &&
+	!RRCrtcPendingProperties (crtc))
     {
 	ret = TRUE;
     }
@@ -337,7 +343,13 @@ RRCrtcSet (RRCrtcPtr    crtc,
 #endif
 	}
 	if (ret)
+	{
+	    int	o;
 	    RRTellChanged (pScreen);
+
+	    for (o = 0; o < numOutputs; o++)
+		RRPostPendingProperties (outputs[o]);
+	}
     }
     return ret;
 }
diff --git a/randr/rrinfo.c b/randr/rrinfo.c
index 549d501..5ef1a6b 100644
--- a/randr/rrinfo.c
+++ b/randr/rrinfo.c
@@ -91,19 +91,12 @@ RRScanOldConfig (ScreenPtr pScreen, Rotation rotations)
     if (pScrPriv->numOutputs == 0 &&
 	pScrPriv->numCrtcs == 0)
     {
-	crtc = RRCrtcCreate (NULL);
+	crtc = RRCrtcCreate (pScreen, NULL);
 	if (!crtc)
 	    return;
-	if (!RRCrtcAttachScreen (crtc, pScreen))
-	{
-	    RRCrtcDestroy (crtc);
-	    return;
-	}
-	output = RROutputCreate ("default", 7, NULL);
+	output = RROutputCreate (pScreen, "default", 7, NULL);
 	if (!output)
 	    return;
-	if (!RROutputAttachScreen (output, pScreen))
-	    return;
 	RROutputSetCrtcs (output, &crtc, 1);
 	RROutputSetCrtc (output, crtc);
 	RROutputSetConnection (output, RR_Connected);
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 09f2afd..c773279 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -47,19 +47,35 @@ RROutputChanged (RROutputPtr output, Bool configChanged)
  */
 
 RROutputPtr
-RROutputCreate (const char  *name,
+RROutputCreate (ScreenPtr   pScreen,
+		const char  *name,
 		int	    nameLength,
 		void	    *devPrivate)
 {
-    RROutputPtr	output;
+    RROutputPtr	    output;
+    RROutputPtr	    *outputs;
+    rrScrPrivPtr    pScrPriv;
 
     if (!RRInit())
 	return NULL;
+    
+    pScrPriv = rrGetScrPriv(pScreen);
+
+    if (pScrPriv->numOutputs)
+	outputs = xrealloc (pScrPriv->outputs, 
+			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
+    else
+	outputs = xalloc (sizeof (RROutputPtr));
+    if (!outputs)
+	return FALSE;
+
+    pScrPriv->outputs = outputs;
+    
     output = xalloc (sizeof (RROutputRec) + nameLength + 1);
     if (!output)
 	return NULL;
     output->id = FakeClientID (0);
-    output->pScreen = NULL;
+    output->pScreen = pScreen;
     output->name = (char *) (output + 1);
     output->nameLength = nameLength;
     memcpy (output->name, name, nameLength);
@@ -85,36 +101,11 @@ RROutputCreate (const char  *name,
     if (!AddResource (output->id, RROutputType, (pointer) output))
 	return NULL;
 
+    pScrPriv->outputs[pScrPriv->numOutputs++] = output;
     return output;
 }
 
 /*
- * Attach an Output to a screen. This is done as a separate step
- * so that an xf86-based driver can create Outputs in PreInit
- * before the Screen has been created
- */
-
-Bool
-RROutputAttachScreen (RROutputPtr output, ScreenPtr pScreen)
-{
-    rrScrPriv (pScreen);
-    RROutputPtr	*outputs;
-    
-    if (pScrPriv->numOutputs)
-	outputs = xrealloc (pScrPriv->outputs, 
-			    (pScrPriv->numOutputs + 1) * sizeof (RROutputPtr));
-    else
-	outputs = xalloc (sizeof (RROutputPtr));
-    if (!outputs)
-	return FALSE;
-    output->pScreen = pScreen;
-    pScrPriv->outputs = outputs;
-    pScrPriv->outputs[pScrPriv->numOutputs++] = output;
-    RROutputChanged (output, FALSE);
-    return TRUE;
-}
-		      
-/*
  * Notify extension that output parameters have been changed
  */
 Bool
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index afac351..00dd750 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -27,7 +27,7 @@
 static void
 RRDeliverEvent (ScreenPtr pScreen, xEvent *event, CARD32 mask)
 {
-    
+
 }
 
 void
@@ -50,7 +50,7 @@ RRDeleteAllOutputProperties (RROutputPtr output)
 	    xfree(prop->current.data);
 	if (prop->pending.data)
 	    xfree(prop->pending.data);
-        xfree(prop);
+	xfree(prop);
     }
 }
 
@@ -67,7 +67,7 @@ static RRPropertyPtr
 RRCreateOutputProperty (Atom property)
 {
     RRPropertyPtr   prop;
-    
+
     prop = (RRPropertyPtr)xalloc(sizeof(RRPropertyRec));
     if (!prop)
 	return NULL;
@@ -139,7 +139,7 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
     prop = RRQueryOutputProperty (output, property);
     if (!prop)   /* just add to list */
     {
-        prop = RRCreateOutputProperty (property);
+	prop = RRCreateOutputProperty (property);
 	if (!prop)
 	    return(BadAlloc);
 	add = TRUE;
@@ -149,11 +149,11 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 	prop_value = &prop->pending;
     else
 	prop_value = &prop->current;
-    
+
     /* To append or prepend to a property the request format and type
-	    must match those of the already defined property.  The
-	    existing format and type are irrelevant when using the mode
-	    "PropModeReplace" since they will be written over. */
+     must match those of the already defined property.  The
+     existing format and type are irrelevant when using the mode
+     "PropModeReplace" since they will be written over. */
 
     if ((format != prop_value->format) && (mode != PropModeReplace))
 	return(BadMatch);
@@ -167,8 +167,8 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 
     if (mode == PropModeReplace || len > 0)
     {
-	pointer	    new_data, old_data;
-	
+	pointer	    new_data = NULL, old_data = NULL;
+
 	total_size = total_len * size_in_bytes;
 	new_value.data = (pointer)xalloc (total_size);
 	if (!new_value.data && total_size)
@@ -197,11 +197,12 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 				  (prop_value->size * size_in_bytes));
 	    break;
 	}
-	memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
+	if (new_data)
+	    memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
 	if (old_data)
 	    memcpy ((char *) old_data, (char *) prop_value->data, 
 		    prop_value->size * size_in_bytes);
-	
+
 	if (pending && pScrPriv->rrOutputSetProperty &&
 	    !pScrPriv->rrOutputSetProperty(output->pScreen, output,
 					   prop->propertyName, &new_value))
@@ -214,18 +215,21 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 	    xfree (prop_value->data);
 	*prop_value = new_value;
     }
-    
+
     else if (len == 0)
     {
 	/* do nothing */
     }
-    
+
     if (add)
     {
 	prop->next = output->properties;
 	output->properties = prop;
     }
 
+    if (pending && prop->is_pending)
+	output->pendingProperties = TRUE;
+
     if (sendevent)
     {
 	event.type = RREventBase + RRNotify;
@@ -240,30 +244,45 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 }
 
 Bool
-RRPostPendingProperty (RROutputPtr output, Atom property)
+RRPostPendingProperties (RROutputPtr output)
 {
-    RRPropertyPtr		    prop = RRQueryOutputProperty (output, property);
-    RRPropertyValuePtr		    pending_value;
-    RRPropertyValuePtr		    current_value;
-    
-    if (!prop)
-	return FALSE;
-    if (!prop->is_pending)
-	return FALSE;
-    pending_value = &prop->pending;
-    current_value = &prop->current;
-
-    if (pending_value->type == current_value->type &&
-	pending_value->format == current_value->format &&
-	pending_value->size == current_value->size &&
-	!memcmp (pending_value->data, current_value->data, pending_value->size))
+    RRPropertyValuePtr	pending_value;
+    RRPropertyValuePtr	current_value;
+    RRPropertyPtr	property;
+    Bool		ret = TRUE;
+
+    if (!output->pendingProperties)
 	return TRUE;
     
-    if (RRChangeOutputProperty (output, property, 
-				pending_value->type, pending_value->format, PropModeReplace,
-				pending_value->size, pending_value->data, TRUE, FALSE) != Success)
-	return FALSE;
-    return TRUE;
+    output->pendingProperties = FALSE;
+    for (property = output->properties; property; property = property->next)
+    {
+	/* Skip non-pending properties */
+	if (!property->is_pending)
+	    continue;
+	
+	pending_value = &property->pending;
+	current_value = &property->current;
+
+	/*
+	 * If the pending and current values are equal, don't mark it
+	 * as changed (which would deliver an event)
+	 */
+	if (pending_value->type == current_value->type &&
+	    pending_value->format == current_value->format &&
+	    pending_value->size == current_value->size &&
+	    !memcmp (pending_value->data, current_value->data,
+		     pending_value->size))
+	    continue;
+
+	if (RRChangeOutputProperty (output, property->propertyName,
+				    pending_value->type, pending_value->format,
+				    PropModeReplace, pending_value->size,
+				    pending_value->data, TRUE,
+				    FALSE) != Success)
+	    ret = FALSE;
+    }
+    return ret;
 }
 
 RRPropertyPtr

commit 36e5227215e0912ddf8a010db042467f00efe0fc
Author: Keith Packard <keithp@neko.keithp.com>
Date:   Fri Mar 23 14:39:10 2007 -0700

    Ensure that crtc desired values track most recent mode.
    
    desiredX and desiredY were not recorded during xf86InitialConfiguration.
    desiredX, desiredY and desiredRotation were not recorded during
    xf86SetSingleMode.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 2341715..b9895d9 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1589,6 +1589,8 @@ xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
 	{
 	    crtc->desiredMode = *mode;
 	    crtc->desiredRotation = output->initial_rotation;
+	    crtc->desiredX = output->initial_x;
+	    crtc->desiredY = output->initial_y;
 	    crtc->enabled = TRUE;
 	    crtc->x = output->initial_x;
 	    crtc->y = output->initial_y;
@@ -1813,7 +1815,12 @@ xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
 	if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0))
 	    ok = FALSE;
 	else
+	{
 	    crtc->desiredMode = *crtc_mode;
+	    crtc->desiredRotation = rotation;
+	    crtc->desiredX = 0;
+	    crtc->desiredY = 0;
+	}
     }
     xf86DisableUnusedFunctions(pScrn);
     return ok;

commit 945aa0aa556429b50dea8e8ebc0008304b093eb7
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Fri Mar 23 01:17:14 2007 -0700

    Incorrect extra memory copy in RRChangeOutputProperty.
    
    Left over from previous version of the code, this memmove will break when
    the mode is not Replace.

diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index a57bd74..afac351 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -177,8 +177,6 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 		RRDestroyOutputProperty (prop);
 	    return BadAlloc;
 	}
-	if (len)
-	    memmove((char *)new_value.data, (char *)value, total_size);
 	new_value.size = len;
 	new_value.type = type;
 	new_value.format = format;

commit 8eb288fbd69e2ffd02521d2c6a964c8180d08ec8
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Fri Mar 23 01:05:55 2007 -0700

    Fix Pending property API, adding RRPostPendingProperty.
    
    Pending Properties take effect when the driver says they do, so provide an
    API to tell DIX when a property effect is made. Also, allow driver
    to reject property values in RRChangeOutputProperty.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index fad0752..2341715 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -1923,7 +1923,7 @@ xf86OutputSetEDIDProperty (xf86OutputPtr output, void *data, int data_len)
 
     if (data_len != 0) {
 	RRChangeOutputProperty(output->randr_output, edid_atom, XA_INTEGER, 8,
-			       PropModeReplace, data_len, data, FALSE);
+			       PropModeReplace, data_len, data, FALSE, TRUE);
     } else {
 	RRDeleteOutputProperty(output->randr_output, edid_atom);
     }
diff --git a/randr/randrstr.h b/randr/randrstr.h
index 3968103..40d3eec 100644
--- a/randr/randrstr.h
+++ b/randr/randrstr.h
@@ -759,10 +759,13 @@ RRQueryOutputProperty (RROutputPtr output, Atom property);
 void
 RRDeleteOutputProperty (RROutputPtr output, Atom property);
 
+Bool
+RRPostPendingProperty (RROutputPtr output, Atom property);
+    
 int
 RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 			int format, int mode, unsigned long len,
-			pointer value, Bool sendevent);
+			pointer value, Bool sendevent, Bool pending);
 
 int
 RRConfigureOutputProperty (RROutputPtr output, Atom property,
diff --git a/randr/rrproperty.c b/randr/rrproperty.c
index e020d5b..a57bd74 100644
--- a/randr/rrproperty.c
+++ b/randr/rrproperty.c
@@ -121,19 +121,19 @@ RRDeleteOutputProperty (RROutputPtr output, Atom property)
 int
 RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 			int format, int mode, unsigned long len,
-			pointer value, Bool sendevent)
+			pointer value, Bool sendevent, Bool pending)
 {
     RRPropertyPtr		    prop;
     xRROutputPropertyNotifyEvent    event;
     rrScrPrivPtr		    pScrPriv = rrGetScrPriv(output->pScreen);
-    int				    sizeInBytes;
-    int				    totalSize;
-    pointer			    data;
+    int				    size_in_bytes;
+    int				    total_size;
+    unsigned long		    total_len;
     RRPropertyValuePtr		    prop_value;
+    RRPropertyValueRec		    new_value;
     Bool			    add = FALSE;
 
-    sizeInBytes = format >> 3;
-    totalSize = len * sizeInBytes;
+    size_in_bytes = format >> 3;
 
     /* first see if property already exists */
     prop = RRQueryOutputProperty (output, property);
@@ -145,7 +145,7 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 	add = TRUE;
 	mode = PropModeReplace;
     }
-    if (prop->is_pending)
+    if (pending && prop->is_pending)
 	prop_value = &prop->pending;
     else
 	prop_value = &prop->current;
@@ -159,68 +159,75 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
 	return(BadMatch);
     if ((prop_value->type != type) && (mode != PropModeReplace))
 	return(BadMatch);
+    new_value = *prop_value;
     if (mode == PropModeReplace)
+	total_len = len;
+    else
+	total_len = prop_value->size + len;
+
+    if (mode == PropModeReplace || len > 0)
     {
-	if (totalSize != prop_value->size * (prop_value->format >> 3))
+	pointer	    new_data, old_data;
+	
+	total_size = total_len * size_in_bytes;
+	new_value.data = (pointer)xalloc (total_size);
+	if (!new_value.data && total_size)
 	{
-	    if (prop_value->data)
-		data = (pointer)xrealloc(prop_value->data, totalSize);
-	    else
-		data = (pointer)xalloc (totalSize);
-	    if (!data && len)
-	    {
-		if (add)
-		    RRDestroyOutputProperty (prop);
-		return(BadAlloc);
-	    }
-	    prop_value->data = data;
+	    if (add)
+		RRDestroyOutputProperty (prop);
+	    return BadAlloc;
 	}
 	if (len)
-	    memmove((char *)prop_value->data, (char *)value, totalSize);
-	prop_value->size = len;
-	prop_value->type = type;
-	prop_value->format = format;
+	    memmove((char *)new_value.data, (char *)value, total_size);
+	new_value.size = len;
+	new_value.type = type;
+	new_value.format = format;
+
+	switch (mode) {
+	case PropModeReplace:
+	    new_data = new_value.data;
+	    old_data = NULL;
+	    break;
+	case PropModeAppend:
+	    new_data = (pointer) (((char *) new_value.data) + 
+				  (prop_value->size * size_in_bytes));
+	    old_data = new_value.data;
+	    break;
+	case PropModePrepend:
+	    new_data = new_value.data;
+	    old_data = (pointer) (((char *) new_value.data) + 
+				  (prop_value->size * size_in_bytes));
+	    break;
+	}
+	memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
+	if (old_data)
+	    memcpy ((char *) old_data, (char *) prop_value->data, 
+		    prop_value->size * size_in_bytes);
+	
+	if (pending && pScrPriv->rrOutputSetProperty &&
+	    !pScrPriv->rrOutputSetProperty(output->pScreen, output,
+					   prop->propertyName, &new_value))
+	{
+	    if (new_value.data)
+		xfree (new_value.data);
+	    return (BadValue);
+	}
+	if (prop_value->data)
+	    xfree (prop_value->data);
+	*prop_value = new_value;
     }
+    
     else if (len == 0)
     {
 	/* do nothing */
     }
-    else if (mode == PropModeAppend)
-    {
-	data = (pointer)xrealloc(prop_value->data,
-				 sizeInBytes * (len + prop_value->size));
-	if (!data)
-	    return(BadAlloc);
-	prop_value->data = data;
-	memmove(&((char *)data)[prop_value->size * sizeInBytes], 
-		(char *)value,
-	      totalSize);
-	prop_value->size += len;
-    }
-    else if (mode == PropModePrepend)
-    {
-	data = (pointer)xalloc(sizeInBytes * (len + prop_value->size));
-	if (!data)
-	    return(BadAlloc);
-	memmove(&((char *)data)[totalSize], (char *)prop_value->data, 
-	      (int)(prop_value->size * sizeInBytes));
-	memmove((char *)data, (char *)value, totalSize);
-	xfree(prop_value->data);
-	prop_value->data = data;
-	prop_value->size += len;
-    }
+    
     if (add)
     {
 	prop->next = output->properties;
 	output->properties = prop;
     }
 
-    if (!prop->is_pending && pScrPriv->rrOutputSetProperty) {
-	/* What should we do in case of failure? */
-	pScrPriv->rrOutputSetProperty(output->pScreen, output,
-				      prop->propertyName, prop_value);
-    }
-
     if (sendevent)
     {
 	event.type = RREventBase + RRNotify;
@@ -234,6 +241,33 @@ RRChangeOutputProperty (RROutputPtr output, Atom property, Atom type,
     return(Success);
 }
 
+Bool
+RRPostPendingProperty (RROutputPtr output, Atom property)
+{
+    RRPropertyPtr		    prop = RRQueryOutputProperty (output, property);
+    RRPropertyValuePtr		    pending_value;
+    RRPropertyValuePtr		    current_value;
+    
+    if (!prop)
+	return FALSE;
+    if (!prop->is_pending)
+	return FALSE;
+    pending_value = &prop->pending;
+    current_value = &prop->current;
+
+    if (pending_value->type == current_value->type &&
+	pending_value->format == current_value->format &&
+	pending_value->size == current_value->size &&
+	!memcmp (pending_value->data, current_value->data, pending_value->size))
+	return TRUE;
+    
+    if (RRChangeOutputProperty (output, property, 
+				pending_value->type, pending_value->format, PropModeReplace,
+				pending_value->size, pending_value->data, TRUE, FALSE) != Success)
+	return FALSE;
+    return TRUE;
+}
+
 RRPropertyPtr
 RRQueryOutputProperty (RROutputPtr output, Atom property)
 {
@@ -474,7 +508,7 @@ ProcRRChangeOutputProperty (ClientPtr client)
 
     err = RRChangeOutputProperty(output, stuff->property,
 				 stuff->type, (int)format,
-				 (int)mode, len, (pointer)&stuff[1], TRUE);
+				 (int)mode, len, (pointer)&stuff[1], TRUE, TRUE);
     if (err != Success)
 	return err;
     else
@@ -508,8 +542,8 @@ int
 ProcRRGetOutputProperty (ClientPtr client)
 {
     REQUEST(xRRGetOutputPropertyReq);
-    RRPropertyPtr			prop, *prev;
-    RRPropertyValuePtr			prop_value;
+    RRPropertyPtr		prop, *prev;
+    RRPropertyValuePtr		prop_value;
     unsigned long		n, len, ind;
     RROutputPtr			output;
     xRRGetOutputPropertyReply	reply;
@@ -600,7 +634,10 @@ ProcRRGetOutputProperty (ClientPtr client)
     reply.bytesAfter = n - (ind + len);
     reply.format = prop_value->format;
     reply.length = (len + 3) >> 2;
-    reply.nItems = len / (prop_value->format / 8 );
+    if (prop_value->format)
+	reply.nItems = len / (prop_value->format / 8);
+    else
+	reply.nItems = 0;
     reply.propertyType = prop_value->type;
 
     if (stuff->delete && (reply.bytesAfter == 0))

commit 9ca7ba5d6012295a77ed773c656e786440da973d
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Fri Mar 23 01:03:40 2007 -0700

    Make sure RandR events are delivered from RRCrtcSet.
    
    Some paths were skipping the event delivery stage.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 1b3c230..da88253 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -271,6 +271,8 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	   RROutputPtr  *outputs)
 {
     ScreenPtr	pScreen = crtc->pScreen;
+    Bool	ret = FALSE;
+    rrScrPriv(pScreen);
 
     /* See if nothing changed */
     if (crtc->mode == mode &&
@@ -280,61 +282,64 @@ RRCrtcSet (RRCrtcPtr    crtc,
 	crtc->numOutputs == numOutputs &&
 	!memcmp (crtc->outputs, outputs, numOutputs * sizeof (RROutputPtr)))
     {
-	return TRUE;
+	ret = TRUE;
     }
-    if (pScreen)
+    else
     {
 #if RANDR_12_INTERFACE
-	rrScrPriv(pScreen);
 	if (pScrPriv->rrCrtcSet)
 	{
-	    return (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
-					   rotation, numOutputs, outputs);
+	    ret = (*pScrPriv->rrCrtcSet) (pScreen, crtc, mode, x, y, 
+					  rotation, numOutputs, outputs);
 	}
+	else
 #endif
-#if RANDR_10_INTERFACE
-	if (pScrPriv->rrSetConfig)
 	{
-	    RRScreenSize	    size;
-	    RRScreenRate	    rate;
-	    Bool		    ret;
-
-	    if (!mode)
-	    {
-		RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL);
-		return TRUE;
-	    }
-
-	    size.width = mode->mode.width;
-	    size.height = mode->mode.height;
-	    if (outputs[0]->mmWidth && outputs[0]->mmHeight)
-	    {
-		size.mmWidth = outputs[0]->mmWidth;
-		size.mmHeight = outputs[0]->mmHeight;
-	    }
-	    else
-	    {
-		size.mmWidth = pScreen->mmWidth;
-		size.mmHeight = pScreen->mmHeight;
-	    }
-	    size.nRates = 1;
-	    rate.rate = RRVerticalRefresh (&mode->mode);
-	    size.pRates = &rate;
-	    ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
-	    /*
-	     * Old 1.0 interface tied screen size to mode size
-	     */
-	    if (ret)
+#if RANDR_10_INTERFACE
+	    if (pScrPriv->rrSetConfig)
 	    {
-		RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs);
-		RRScreenSizeNotify (pScreen);
+		RRScreenSize	    size;
+		RRScreenRate	    rate;
+
+		if (!mode)
+		{
+		    RRCrtcNotify (crtc, NULL, x, y, rotation, 0, NULL);
+		    ret = TRUE;
+		}
+		else
+		{
+		    size.width = mode->mode.width;
+		    size.height = mode->mode.height;
+		    if (outputs[0]->mmWidth && outputs[0]->mmHeight)
+		    {
+			size.mmWidth = outputs[0]->mmWidth;
+			size.mmHeight = outputs[0]->mmHeight;
+		    }
+		    else
+		    {
+			size.mmWidth = pScreen->mmWidth;
+			size.mmHeight = pScreen->mmHeight;
+		    }
+		    size.nRates = 1;
+		    rate.rate = RRVerticalRefresh (&mode->mode);
+		    size.pRates = &rate;
+		    ret = (*pScrPriv->rrSetConfig) (pScreen, rotation, rate.rate, &size);
+		    /*
+		     * Old 1.0 interface tied screen size to mode size
+		     */
+		    if (ret)
+		    {
+			RRCrtcNotify (crtc, mode, x, y, rotation, 1, outputs);
+			RRScreenSizeNotify (pScreen);
+		    }
+		}
 	    }
-	    return ret;
-	}
 #endif
-	RRTellChanged (pScreen);
+	}
+	if (ret)
+	    RRTellChanged (pScreen);
     }
-    return FALSE;
+    return ret;
 }
 
 /*
@@ -716,6 +721,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	goto sendReply;
     }
     
+#if 0
     /*
      * if the client's config timestamp is not the same as the last config
      * timestamp, then the config information isn't up-to-date and
@@ -726,6 +732,7 @@ ProcRRSetCrtcConfig (ClientPtr client)
 	rep.status = RRSetConfigInvalidConfigTime;
 	goto sendReply;
     }
+#endif
     
     /*
      * Validate requested rotation

commit 492c768065f49306a2194a88edf96b85de0ff4ff
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Fri Mar 23 00:59:11 2007 -0700

    Clean up xf86CrtcRec and xf86OutputRec objects at CloseScreen.
    
    Erase pointers to structures which are freed at server reset time.

diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index a875cdf..fad0752 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -573,11 +573,25 @@ xf86CrtcCloseScreen (int index, ScreenPtr screen)
 {
     ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			o, c;
     
     screen->CloseScreen = config->CloseScreen;
 
     xf86RotateCloseScreen (screen);
 
+    for (o = 0; o < config->num_output; o++)
+    {
+	xf86OutputPtr	output = config->output[o];
+
+	output->crtc = NULL;
+	output->randr_output = NULL;
+    }
+    for (c = 0; c < config->num_crtc; c++)
+    {
+	xf86CrtcPtr	crtc = config->crtc[c];
+
+	crtc->randr_crtc = NULL;
+    }
     return screen->CloseScreen (index, screen);
 }
 

commit 16f4c0c1750824f2e5a001cef82a4122a7a2beb0
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Fri Mar 23 00:57:18 2007 -0700

    Clear allocated RandR screen private structure.
    
    Use xcalloc instead of xalloc when allocating this structure to ensure
    consistent contents at startup.

diff --git a/randr/randr.c b/randr/randr.c
index 5fa9baf..4dd0ee5 100644
--- a/randr/randr.c
+++ b/randr/randr.c
@@ -230,7 +230,7 @@ Bool RRScreenInit(ScreenPtr pScreen)
 	RRScreenGeneration = serverGeneration;
     }
 
-    pScrPriv = (rrScrPrivPtr) xalloc (sizeof (rrScrPrivRec));
+    pScrPriv = (rrScrPrivPtr) xcalloc (1, sizeof (rrScrPrivRec));
     if (!pScrPriv)
 	return FALSE;
 

commit f8db7665dcd7af78ca4db2461e0bf787ec662cb1
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Tue Mar 20 07:17:27 2007 -0700

    Clean up Rotate state on server reset.
    
    The rotation state is stored in the xf86_config structure which is not
    re-initialized at server reset time. Clean it up at CloseScreen time.

diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c
index f468b1f..3103976 100644
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@ -1180,6 +1180,7 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMVAR(pciNumBuses)
 
     /* modes */
+    SYMVAR(xf86CrtcConfigPrivateIndex)
     SYMFUNC(xf86CrtcConfigInit)
     SYMFUNC(xf86CrtcConfigPrivateIndex)
     SYMFUNC(xf86CrtcCreate)
diff --git a/hw/xfree86/modes/xf86Crtc.c b/hw/xfree86/modes/xf86Crtc.c
index 1a42920..a875cdf 100644
--- a/hw/xfree86/modes/xf86Crtc.c
+++ b/hw/xfree86/modes/xf86Crtc.c
@@ -566,6 +566,22 @@ xf86CrtcCreateScreenResources (ScreenPtr screen)
 }
 
 /*
+ * Clean up config on server reset
+ */
+static Bool
+xf86CrtcCloseScreen (int index, ScreenPtr screen)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
+    
+    screen->CloseScreen = config->CloseScreen;
+
+    xf86RotateCloseScreen (screen);
+
+    return screen->CloseScreen (index, screen);
+}
+
+/*
  * Called at ScreenInit time to set up
  */
 Bool
@@ -596,6 +612,10 @@ xf86CrtcScreenInit (ScreenPtr screen)
     /* Wrap CreateScreenResources so we can initialize the RandR code */
     config->CreateScreenResources = screen->CreateScreenResources;
     screen->CreateScreenResources = xf86CrtcCreateScreenResources;
+
+    config->CloseScreen = screen->CloseScreen;
+    screen->CloseScreen = xf86CrtcCloseScreen;
+    
     return TRUE;
 }
 
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index b751592..42daf60 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -544,6 +544,8 @@ typedef struct _xf86CrtcConfig {
 
     CreateScreenResourcesProcPtr    CreateScreenResources;
 
+    CloseScreenProcPtr		    CloseScreen;
+
     /* Cursor information */
     xf86CursorInfoPtr	cursor_info;
     CursorPtr		cursor;
@@ -593,6 +595,12 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
 Bool
 xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
 
+/*
+ * Clean up rotation during CloseScreen
+ */
+void
+xf86RotateCloseScreen (ScreenPtr pScreen);
+
 /**
  * Return whether any output is assigned to the crtc
  */
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index e82b69e..e8fafd0 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -321,36 +321,68 @@ xf86RotateWakeupHandler(pointer data, int i, pointer LastSelectMask)
 {
 }
 
-Bool
-xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+static void
+xf86RotateDestroy (xf86CrtcPtr crtc)
 {
     ScrnInfoPtr		pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     ScreenPtr		pScreen = pScrn->pScreen;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			c;
     
-    if (rotation == RR_Rotate_0)
+    /* Free memory from rotation */
+    if (crtc->rotatedPixmap || crtc->rotatedData)
     {
-	/* Free memory from rotation */
+	crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData);
+	crtc->rotatedPixmap = NULL;
+	crtc->rotatedData = NULL;
+    }
+
+    for (c = 0; c < xf86_config->num_crtc; c++)
 	if (crtc->rotatedPixmap || crtc->rotatedData)
-	{
-	    crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData);
-	    crtc->rotatedPixmap = NULL;
-	    crtc->rotatedData = NULL;
-	}
+	    return;
 
-	if (xf86_config->rotation_damage)
+    /*
+     * Clean up damage structures when no crtcs are rotated
+     */
+    if (xf86_config->rotation_damage)
+    {
+	/* Free damage structure */
+	if (xf86_config->rotation_damage_registered)
 	{
-	    /* Free damage structure */
 	    DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
 			      xf86_config->rotation_damage);
 	    xf86_config->rotation_damage_registered = FALSE;
-	    DamageDestroy (xf86_config->rotation_damage);
-	    xf86_config->rotation_damage = NULL;
-	    /* Free block/wakeup handler */
-	    RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
-					  xf86RotateWakeupHandler,
-					  (pointer) pScreen);
 	}
+	DamageDestroy (xf86_config->rotation_damage);
+	xf86_config->rotation_damage = NULL;
+	/* Free block/wakeup handler */
+	RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
+				      xf86RotateWakeupHandler,
+				      (pointer) pScreen);
+    }
+}
+
+void
+xf86RotateCloseScreen (ScreenPtr screen)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++)
+	xf86RotateDestroy (xf86_config->crtc[c]);
+}
+
+Bool
+xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+{
+    ScrnInfoPtr		pScrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    ScreenPtr		pScreen = pScrn->pScreen;
+    
+    if (rotation == RR_Rotate_0)
+    {
+	xf86RotateDestroy (crtc);
     }
     else
     {

commit 0f80340a526b2838b9f39145f29941222e84184b
Author: Keith Packard <keithp@neko.keithp.com>
Date:   Sat Mar 17 20:14:05 2007 -0700

    Slow down DDC I2C bus using a RiseFallTime of 20us for old monitors.
    
    This time value makes the bus run slowly enough for even the least reliable
    of monitors. Thanks to Pavel Troller for finding the necessary change.

diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c
index 0f24c52..8080c8d 100644
--- a/hw/xfree86/ddc/xf86DDC.c
+++ b/hw/xfree86/ddc/xf86DDC.c
@@ -337,6 +337,12 @@ DDCRead_DDC2(int scrnIndex, I2CBusPtr pBus, int start, int len)
     unsigned char *R_Buffer;
     int i;
     
+    /*
+     * Slow down the bus so that older monitors don't 
+     * miss things.
+     */
+    pBus->RiseFallTime = 20;
+    
     if (!(dev = xf86I2CFindDev(pBus, 0x00A0))) {
 	dev = xf86CreateI2CDevRec();
 	dev->DevName = "ddc2";

commit 52fccb9d9fdbb1c9dc3f5225600004cd94e42a4a
Author: Keith Packard <keithp@neko.keithp.com>
Date:   Sat Mar 17 17:26:11 2007 -0700

    Remove extra (and wrong) I2C ByteTimeout setting in DDC code.
    
    The DDC code sets the I2C timeouts to VESA standards, except that it had an
    extra setting of the ByteTimeout value which was wrong (off by a factor of
    50). Removing this should help DDC work on many more monitors. Note that the
    Intel driver duplicated these settings, along with the error. Yay for cult
    and paste coding.

diff --git a/hw/xfree86/ddc/xf86DDC.c b/hw/xfree86/ddc/xf86DDC.c
index 4ce585c..0f24c52 100644
--- a/hw/xfree86/ddc/xf86DDC.c
+++ b/hw/xfree86/ddc/xf86DDC.c
@@ -344,7 +344,6 @@ DDCRead_DDC2(int scrnIndex, I2CBusPtr pBus, int start, int len)
 	dev->ByteTimeout = 2200; /* VESA DDC spec 3 p. 43 (+10 %) */
 	dev->StartTimeout = 550;
 	dev->BitTimeout = 40;
-	dev->ByteTimeout = 40;
 	dev->AcknTimeout = 40;
 
 	dev->pI2CBus = pBus;

commit f521308ad2c06afa00143d3ab407e18d5293d497
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Thu Mar 15 20:26:07 2007 -0700

    Correct ref counting of RRMode structures
    
    RRModes are referenced by the resource db, RROutput and RRCrtc structures.
    Ensure that the mode reference count is decremented each time a reference is
    lost from one of these sources. The missing destroys were in
    RRCrtcDestroyResource and RROutputDestroyResource, which only happen at
    server reset time, so modes would be unavailable in subsequent server
    generations.

diff --git a/randr/rrcrtc.c b/randr/rrcrtc.c
index 43a6fca..1b3c230 100644
--- a/randr/rrcrtc.c
+++ b/randr/rrcrtc.c
@@ -370,6 +370,8 @@ RRCrtcDestroyResource (pointer value, XID pid)
     }
     if (crtc->gammaRed)
 	xfree (crtc->gammaRed);
+    if (crtc->mode)
+	RRModeDestroy (crtc->mode);
     xfree (crtc);
     return 1;
 }
diff --git a/randr/rroutput.c b/randr/rroutput.c
index 31ec924..09f2afd 100644
--- a/randr/rroutput.c
+++ b/randr/rroutput.c
@@ -406,9 +406,12 @@ RROutputDestroyResource (pointer value, XID pid)
 	    }
 	}
     }
-    /* XXX destroy all modes? */
     if (output->modes)
+    {
+	for (m = 0; m < output->numModes; m++)
+	    RRModeDestroy (output->modes[m]);
 	xfree (output->modes);
+    }
     
     for (m = 0; m < output->numUserModes; m++)
 	RRModeDestroy (output->userModes[m]);

commit b14f003b0ed1252766c9e3b1c086ea2809521047
Author: Keith Packard <keithp@neko.keithp.com>
Date:   Thu Mar 15 16:16:16 2007 -0700

    Don't wedge when rotating more than one CRTC.
    
    Rotation block handler was re-registering the rotation damage structure,
    creating an infinite loop in the damage code. Track registration of the
    damage structure to avoid this.

diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index df8a8aa..b751592 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -529,7 +529,8 @@ typedef struct _xf86CrtcConfig {
     int			maxWidth, maxHeight;
     
     /* For crtc-based rotation */
-    DamagePtr   rotationDamage;
+    DamagePtr		rotation_damage;
+    Bool		rotation_damage_registered;
 
     /* DGA */
     unsigned int	dga_flags;
diff --git a/hw/xfree86/modes/xf86Rotate.c b/hw/xfree86/modes/xf86Rotate.c
index 6826b62..e82b69e 100644
--- a/hw/xfree86/modes/xf86Rotate.c
+++ b/hw/xfree86/modes/xf86Rotate.c
@@ -251,9 +251,13 @@ xf86RotatePrepare (ScreenPtr pScreen)
 							     crtc->rotatedData,
 							     crtc->mode.HDisplay,
 							     crtc->mode.VDisplay);
-	    /* Hook damage to screen pixmap */
-	    DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
-			    xf86_config->rotationDamage);
+	    if (!xf86_config->rotation_damage_registered)
+	    {
+		/* Hook damage to screen pixmap */
+		DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+				xf86_config->rotation_damage);
+		xf86_config->rotation_damage_registered = TRUE;
+	    }
 	    
 	    xf86CrtcDamageShadow (crtc);
 	}
@@ -265,7 +269,7 @@ xf86RotateRedisplay(ScreenPtr pScreen)
 {
     ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    DamagePtr		damage = xf86_config->rotationDamage;
+    DamagePtr		damage = xf86_config->rotation_damage;
     RegionPtr		region;
 
     if (!damage)
@@ -334,13 +338,14 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	    crtc->rotatedData = NULL;
 	}
 
-	if (xf86_config->rotationDamage)
+	if (xf86_config->rotation_damage)
 	{
 	    /* Free damage structure */
 	    DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
-			      xf86_config->rotationDamage);
-	    DamageDestroy (xf86_config->rotationDamage);
-	    xf86_config->rotationDamage = NULL;
+			      xf86_config->rotation_damage);
+	    xf86_config->rotation_damage_registered = FALSE;
+	    DamageDestroy (xf86_config->rotation_damage);
+	    xf86_config->rotation_damage = NULL;
 	    /* Free block/wakeup handler */
 	    RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
 					  xf86RotateWakeupHandler,
@@ -382,13 +387,13 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	    xf86CrtcDamageShadow (crtc);
 	}
 	
-	if (!xf86_config->rotationDamage)
+	if (!xf86_config->rotation_damage)
 	{
 	    /* Create damage structure */
-	    xf86_config->rotationDamage = DamageCreate (NULL, NULL,
+	    xf86_config->rotation_damage = DamageCreate (NULL, NULL,
 						DamageReportNone,
 						TRUE, pScreen, pScreen);
-	    if (!xf86_config->rotationDamage)
+	    if (!xf86_config->rotation_damage)
 		goto bail2;
 	    
 	    /* Assign block/wakeup handler */
@@ -402,8 +407,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
 	if (0)
 	{
 bail3:
-	    DamageDestroy (xf86_config->rotationDamage);
-	    xf86_config->rotationDamage = NULL;
+	    DamageDestroy (xf86_config->rotation_damage);
+	    xf86_config->rotation_damage = NULL;
 	    
 bail2:
 	    if (shadow || shadowData)

commit 5b77bf2d020b1ee56c1c5f2db089a8f7f64a76a6
Author: Keith Packard <keithp@neko.keithp.com>
Date:   Thu Mar 15 10:50:45 2007 -0700

    Allow xf86_reload_cursors during server init.
    
    xf86_reload_cursors is supposed to be called from the crtc mode setting
    commit hook; as that happens during server initialization, check for this
    case.

diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
index 095df48..009cccf 100644
--- a/hw/xfree86/modes/xf86Cursors.c
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -548,12 +548,24 @@ xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags)
 void
 xf86_reload_cursors (ScreenPtr screen)
 {
-    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
-    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
-    CursorPtr		cursor = xf86_config->cursor;
+    ScrnInfoPtr		scrn;
+    xf86CrtcConfigPtr   xf86_config;
+    xf86CursorInfoPtr   cursor_info;
+    CursorPtr		cursor;
     int			x, y;
     
+    /* initial mode setting will not have set a screen yet */
+    if (!screen)
+	return;
+    scrn = xf86Screens[screen->myNum];
+    xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+
+    /* make sure the cursor code has been initialized */
+    cursor_info = xf86_config->cursor_info;
+    if (!cursor_info)
+	return;
+    
+    cursor = xf86_config->cursor;
     GetSpritePosition (&x, &y);
     if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
 	(*cursor_info->HideCursor)(scrn);

commit 4d81c99a4660a0bf9014f789de55edabd185bd14
Author: Keith Packard <keithp@guitar.keithp.com>
Date:   Wed Mar 14 23:59:29 2007 -0700

    Create driver-independent CRTC-based cursor layer.
    
    This moves most of the cursor management code out of the intel driver and
    into the general server code. Of course, the hope is that this code will be
    useful for other driver writers as well.
    
    Check out xf86Crtc.h for the usage information, making sure you add the
    needed hooks to the crtc funcs structure for your driver.

diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 35f1aa9..0701cf5 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -48,6 +48,7 @@ XORG_LIBS = \
             parser/libxf86config.a \
 	    dixmods/libdixmods.la \
 	    modes/libxf86modes.a \
+	    ramdac/libramdac.a \
 	    ddc/libddc.a \
 	    i2c/libi2c.a \
             @XORG_LIBS@
diff --git a/hw/xfree86/loader/Makefile.am b/hw/xfree86/loader/Makefile.am
index 0a89d08..61bcb22 100644
--- a/hw/xfree86/loader/Makefile.am
+++ b/hw/xfree86/loader/Makefile.am
@@ -2,7 +2,8 @@ noinst_LIBRARIES = libloader.a
 
 INCLUDES = $(XORG_INCS) -I$(srcdir)/../parser -I$(srcdir)/../dixmods/extmod \
 	   -I$(srcdir)/../vbe -I$(top_srcdir)/miext/cw -I$(srcdir)/../int10 \
-	   -I$(srcdir)/../ddc -I$(srcdir)/../i2c -I$(srcdir)/../modes
+	   -I$(srcdir)/../ddc -I$(srcdir)/../i2c -I$(srcdir)/../modes \
+	   -I$(srcdir)/../ramdac
 
 #AM_LDFLAGS = -r
 AM_CFLAGS = -DIN_LOADER $(XORG_CFLAGS)
diff --git a/hw/xfree86/loader/loadmod.c b/hw/xfree86/loader/loadmod.c
index e489212..c220d8a 100644
--- a/hw/xfree86/loader/loadmod.c
+++ b/hw/xfree86/loader/loadmod.c
@@ -841,6 +841,7 @@ DuplicateModule(ModuleDescPtr mod, ModuleDescPtr parent)
 static const char *compiled_in_modules[] = {
     "ddc",
     "i2c",
+    "ramdac",
     NULL
 };
 
@@ -861,7 +862,7 @@ doLoadModule(const char *module, const char *path, const char **subdirlist,
     PatternPtr patterns = NULL;
     int noncanonical = 0;
     char *m = NULL;
-    char **cim;
+    const char **cim;
 
     xf86MsgVerb(X_INFO, 3, "LoadModule: \"%s\"", module);
 
diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c
index 2f1f6af..f468b1f 100644
--- a/hw/xfree86/loader/xf86sym.c
+++ b/hw/xfree86/loader/xf86sym.c
@@ -1230,6 +1230,11 @@ _X_HIDDEN void *xfree86LookupTab[] = {
     SYMFUNC(xf86RandR12SetConfig)
     SYMFUNC(xf86RandR12SetRotations)
 #endif
+    SYMFUNC(xf86_cursors_init)
+    SYMFUNC(xf86_reload_cursors)
+    SYMFUNC(xf86_show_cursors)
+    SYMFUNC(xf86_hide_cursors)
+    SYMFUNC(xf86_cursors_fini)
 
     SYMFUNC(xf86DoEDID_DDC1)
     SYMFUNC(xf86DoEDID_DDC2)
diff --git a/hw/xfree86/modes/Makefile.am b/hw/xfree86/modes/Makefile.am
index 60d2553..0841a6d 100644
--- a/hw/xfree86/modes/Makefile.am
+++ b/hw/xfree86/modes/Makefile.am
@@ -3,6 +3,7 @@ noinst_LIBRARIES = libxf86modes.a
 libxf86modes_a_SOURCES = \
 	xf86Crtc.c \
 	xf86Crtc.h \
+	xf86Cursors.c \
 	xf86cvt.c \
 	xf86DiDGA.c \
 	xf86EdidModes.c \
@@ -16,7 +17,8 @@ libxf86modes_a_SOURCES = \
 INCLUDES = $(XORG_INCS) -I$(srcdir)/../ddc -I$(srcdir)/../i2c \
 	   -I$(srcdir)/../loader -I$(srcdir)/../rac -I$(srcdir)/../parser \
            -I$(srcdir)/../scanpci -I$(srcdir)/../vbe -I$(srcdir)/../int10 \
-	   -I$(srcdir)/../vgahw -I$(srcdir)/../dixmods/extmod
+	   -I$(srcdir)/../vgahw -I$(srcdir)/../ramdac \
+	   -I$(srcdir)/../dixmods/extmod
 
 sdk_HEADERS = \
 	xf86Crtc.h \
diff --git a/hw/xfree86/modes/xf86Crtc.h b/hw/xfree86/modes/xf86Crtc.h
index 6152ae4..df8a8aa 100644
--- a/hw/xfree86/modes/xf86Crtc.h
+++ b/hw/xfree86/modes/xf86Crtc.h
@@ -28,6 +28,7 @@
 #include "xf86Rename.h"
 #endif
 #include "xf86Modes.h"
+#include "xf86Cursor.h"
 #include "damage.h"
 
 /* Compat definitions for older X Servers. */
@@ -37,6 +38,9 @@
 #ifndef M_T_DRIVER
 #define M_T_DRIVER	0x40
 #endif
+#ifndef HARDWARE_CURSOR_ARGB
+#define HARDWARE_CURSOR_ARGB				0x00004000
+#endif
 
 typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
 typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
@@ -155,6 +159,42 @@ typedef struct _xf86CrtcFuncs {
     (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap, void *data);
 
     /**
+     * Set cursor colors
+     */
+    void
+    (*set_cursor_colors) (xf86CrtcPtr crtc, int bg, int fg);
+
+    /**
+     * Set cursor position
+     */
+    void
+    (*set_cursor_position) (xf86CrtcPtr crtc, int x, int y);
+
+    /**
+     * Show cursor
+     */
+    void
+    (*show_cursor) (xf86CrtcPtr crtc);
+
+    /**
+     * Hide cursor
+     */
+    void
+    (*hide_cursor) (xf86CrtcPtr crtc);
+
+    /**
+     * Load monochrome image
+     */
+    void
+    (*load_cursor_image) (xf86CrtcPtr crtc, CARD8 *image);
+
+    /**
+     * Load ARGB image
+     */
+     void
+     (*load_cursor_argb) (xf86CrtcPtr crtc, CARD32 *image);
+     
+    /**
      * Clean up driver-specific bits of the crtc
      */
     void
@@ -174,12 +214,6 @@ struct _xf86Crtc {
      */
     Bool	    enabled;
     
-    /** Track whether cursor is within CRTC range  */
-    Bool	    cursorInRange;
-    
-    /** Track state of cursor associated with this CRTC */
-    Bool	    cursorShown;
-    
     /**
      * Active mode
      *
@@ -232,6 +266,19 @@ struct _xf86Crtc {
 #else
     void	    *randr_crtc;
 #endif
+
+    /**
+     * Current cursor is ARGB
+     */
+    Bool	    cursor_argb;
+    /**
+     * Track whether cursor is within CRTC range 
+     */
+    Bool	    cursor_in_range;
+    /**
+     * Track state of cursor associated with this CRTC
+     */
+    Bool	    cursor_shown;
 };
 
 typedef struct _xf86OutputFuncs {
@@ -495,6 +542,13 @@ typedef struct _xf86CrtcConfig {
     const xf86CrtcConfigFuncsRec *funcs;
 
     CreateScreenResourcesProcPtr    CreateScreenResources;
+
+    /* Cursor information */
+    xf86CursorInfoPtr	cursor_info;
+    CursorPtr		cursor;
+    CARD8		*cursor_image;
+    Bool		cursor_on;
+    CARD32		cursor_fg, cursor_bg;
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern int xf86CrtcConfigPrivateIndex;
@@ -637,4 +691,41 @@ xf86ConnectorGetName(xf86ConnectorType connector);
 Bool
 xf86SetDesiredModes (ScrnInfoPtr pScrn);
 
+/**
+ * Initialize the CRTC-based cursor code. CRTC function vectors must
+ * contain relevant cursor setting functions.
+ *
+ * Driver should call this from ScreenInit function
+ */
+Bool
+xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags);
+
+/**
+ * Called when anything on the screen is reconfigured.
+ *
+ * Reloads cursor images as needed, then adjusts cursor positions.
+ * 
+ * Driver should call this from crtc commit function.
+ */
+void
+xf86_reload_cursors (ScreenPtr screen);
+
+/**
+ * Called from EnterVT to turn the cursors back on
+ */
+void
+xf86_show_cursors (ScrnInfoPtr scrn);
+
+/**
+ * Called by the driver to turn cursors off
+ */
+void
+xf86_hide_cursors (ScrnInfoPtr scrn);
+
+/**
+ * Clean up CRTC-based cursor code. Driver must call this at CloseScreen time.
+ */
+void
+xf86_cursors_fini (ScreenPtr screen);
+    
 #endif /* _XF86CRTC_H_ */
diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c
new file mode 100644
index 0000000..095df48
--- /dev/null
+++ b/hw/xfree86/modes/xf86Cursors.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright © 2007 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission.  The copyright holders make no representations
+ * about the suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_XORG_CONFIG_H
+#include <xorg-config.h>
+#else
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+#include "xf86Crtc.h"
+#include "xf86Modes.h"
+#include "xf86RandR12.h"
+#include "X11/extensions/render.h"
+#define DPMS_SERVER
+#include "X11/extensions/dpms.h"
+#include "X11/Xatom.h"
+#ifdef RENDER
+#include "picturestr.h"
+#endif
+#include "cursorstr.h"
+
+/*
+ * Given a screen coordinate, rotate back to a cursor source coordinate
+ */
+static void
+xf86_crtc_rotate_coord (Rotation    rotation,
+			int	    width,
+			int	    height,
+			int	    x_dst,
+			int	    y_dst,
+			int	    *x_src,
+			int	    *y_src)
+{
+    if (rotation & RR_Reflect_X)
+	x_dst = width - x_dst - 1;
+    if (rotation & RR_Reflect_Y)
+	y_dst = height - y_dst - 1;
+    
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+	*x_src = x_dst;
+	*y_src = y_dst;
+	break;
+    case RR_Rotate_90:
+	*x_src = height - y_dst - 1;
+	*y_src = x_dst;
+	break;
+    case RR_Rotate_180:
+	*x_src = width - x_dst - 1;
+	*y_src = height - y_dst - 1;
+	break;
+    case RR_Rotate_270:
+	*x_src = y_dst;
+	*y_src = width - x_dst - 1;
+	break;
+    }
+}
+
+/*
+ * Convert an x coordinate to a position within the cursor bitmap
+ */
+static int
+cursor_bitpos (int flags, int x, Bool mask)
+{
+    if (flags & HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK)
+	mask = !mask;
+    if (flags & HARDWARE_CURSOR_NIBBLE_SWAPPED)
+	x = (x & ~3) | (3 - (x & 3));
+    if (flags & HARDWARE_CURSOR_BIT_ORDER_MSBFIRST)
+	x = (x & ~7) | (7 - (x & 7));
+    if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1)
+	x = (x << 1) + mask;
+    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8)
+	x = ((x & ~7) << 1) | (mask << 3) | (x & 7);
+    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_16)
+	x = ((x & ~15) << 1) | (mask << 4) | (x & 15);
+    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_32)
+	x = ((x & ~31) << 1) | (mask << 5) | (x & 31);
+    else if (flags & HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64)
+	x = ((x & ~63) << 1) | (mask << 6) | (x & 63);
+    return x;
+}
+
+/*
+ * Fetch one bit from a cursor bitmap
+ */
+static CARD8
+get_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
+{
+    x = cursor_bitpos (flags, x, mask);
+    image += y * stride;
+    return (image[(x >> 3)] >> (x & 7)) & 1;
+}
+
+/*
+ * Set one bit in a cursor bitmap
+ */
+static void
+set_bit (CARD8 *image, int stride, int flags, int x, int y, Bool mask)
+{
+    x = cursor_bitpos (flags, x, mask);
+    image += y * stride;
+    image[(x >> 3)] |= 1 << (x & 7);
+}
+    
+/*
+ * Load a two color cursor into a driver that supports only ARGB cursors
+ */
+static void
+xf86_crtc_convert_cursor_to_argb (xf86CrtcPtr crtc, unsigned char *src)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+    CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image;
+    int			x, y;
+    int			xin, yin;
+    int			stride = cursor_info->MaxWidth >> 2;
+    int			flags = cursor_info->Flags;
+    CARD32		bits;
+
+#ifdef ARGB_CURSOR
+    crtc->cursor_argb = FALSE;
+#endif
+
+    for (y = 0; y < cursor_info->MaxHeight; y++)
+	for (x = 0; x < cursor_info->MaxWidth; x++) 
+	{
+	    xf86_crtc_rotate_coord (crtc->rotation,
+				    cursor_info->MaxWidth,
+				    cursor_info->MaxHeight,
+				    x, y, &xin, &yin);
+	    if (get_bit (src, stride, flags, xin, yin, TRUE) ==
+		((flags & HARDWARE_CURSOR_INVERT_MASK) == 0))
+	    {
+		if (get_bit (src, stride, flags, xin, yin, FALSE))
+		    bits = xf86_config->cursor_fg;
+		else
+		    bits = xf86_config->cursor_bg;
+	    }
+	    else
+		bits = 0;
+	    cursor_image[y * cursor_info->MaxWidth + x] = bits;
+	}
+    crtc->funcs->load_cursor_argb (crtc, cursor_image);
+}
+
+/*
+ * Set the colors for a two-color cursor (ignore for ARGB cursors)
+ */
+static void
+xf86_set_cursor_colors (ScrnInfoPtr scrn, int bg, int fg)
+{
+    ScreenPtr		screen = scrn->pScreen;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    CursorPtr		cursor = xf86_config->cursor;
+    int			c;
+    CARD8		*bits = cursor ? cursor->devPriv[screen->myNum] : NULL;
+
+    /* Save ARGB versions of these colors */
+    xf86_config->cursor_fg = (CARD32) fg | 0xff000000;
+    xf86_config->cursor_bg = (CARD32) bg | 0xff000000;
+    
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (crtc->enabled && !crtc->cursor_argb)
+	{
+	    if (crtc->funcs->load_cursor_image)
+		crtc->funcs->set_cursor_colors (crtc, bg, fg);
+	    else if (bits)
+		xf86_crtc_convert_cursor_to_argb (crtc, bits);
+	}
+    }
+}
+
+static void
+xf86_crtc_hide_cursor (xf86CrtcPtr crtc)
+{
+    if (crtc->cursor_shown)
+    {
+	crtc->funcs->hide_cursor (crtc);
+	crtc->cursor_shown = FALSE;
+    }
+}
+
+void
+xf86_hide_cursors (ScrnInfoPtr scrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			c;
+
+    xf86_config->cursor_on = FALSE;
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (crtc->enabled)
+	    xf86_crtc_hide_cursor (crtc);
+    }
+}
+    
+static void
+xf86_crtc_show_cursor (xf86CrtcPtr crtc)
+{
+    if (!crtc->cursor_shown && crtc->cursor_in_range)
+    {
+	crtc->funcs->show_cursor (crtc);
+	crtc->cursor_shown = TRUE;
+    }
+}
+
+void
+xf86_show_cursors (ScrnInfoPtr scrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			c;
+
+    xf86_config->cursor_on = TRUE;
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (crtc->enabled)
+	    xf86_crtc_show_cursor (crtc);
+    }
+}
+    
+static void
+xf86_crtc_set_cursor_position (xf86CrtcPtr crtc, int x, int y)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+    DisplayModePtr	mode = &crtc->mode;
+    int			x_temp;
+    int			y_temp;
+    Bool		in_range;
+
+    /* 
+     * Move to crtc coordinate space
+     */
+    x -= crtc->x;
+    y -= crtc->y;
+    
+    /*
+     * Rotate
+     */
+    switch ((crtc->rotation) & 0xf) {
+    case RR_Rotate_0:
+	break;
+    case RR_Rotate_90:
+	x_temp = y;
+	y_temp = mode->VDisplay - cursor_info->MaxWidth - x;
+	x = x_temp;
+	y = y_temp;
+	break;
+    case RR_Rotate_180:
+	x_temp = mode->HDisplay - cursor_info->MaxWidth - x;
+	y_temp = mode->VDisplay - cursor_info->MaxHeight - y;
+	x = x_temp;
+	y = y_temp;
+	break;
+    case RR_Rotate_270:
+	x_temp = mode->HDisplay - cursor_info->MaxHeight -  y;
+	y_temp = x;
+	x = x_temp;
+	y = y_temp;
+	break;
+    }
+    
+    /*
+     * Reflect
+     */
+    if (crtc->rotation & RR_Reflect_X)
+	x = mode->HDisplay - cursor_info->MaxWidth - x;
+    if (crtc->rotation & RR_Reflect_Y)
+	y = mode->VDisplay - cursor_info->MaxHeight - y;
+
+    /*
+     * Disable the cursor when it is outside the viewport
+     */
+    in_range = TRUE;
+    if (x >= mode->HDisplay || y >= mode->VDisplay ||
+	x <= -cursor_info->MaxWidth || y <= -cursor_info->MaxHeight) 
+    {
+	in_range = FALSE;
+	x = 0;
+	y = 0;
+    }
+
+    crtc->cursor_in_range = in_range;
+    
+    if (in_range)
+    {
+	crtc->funcs->set_cursor_position (crtc, x, y);
+	xf86_crtc_show_cursor (crtc);
+    }
+    else
+	xf86_crtc_hide_cursor (crtc);
+}
+
+static void
+xf86_set_cursor_position (ScrnInfoPtr scrn, int x, int y)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			c;
+
+    /* undo what xf86HWCurs did to the coordinates */
+    x += scrn->frameX0;
+    y += scrn->frameY0;
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (crtc->enabled)
+	    xf86_crtc_set_cursor_position (crtc, x, y);
+    }
+}
+    
+/*
+ * Load a two-color cursor into a crtc, performing rotation as needed
+ */
+static void
+xf86_crtc_load_cursor_image (xf86CrtcPtr crtc, CARD8 *src)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+    CARD8		*cursor_image;
+
+#ifdef ARGB_CURSOR
+    crtc->cursor_argb = FALSE;
+#endif
+
+    if (crtc->rotation == RR_Rotate_0)
+	cursor_image = src;
+    else
+    {
+        int x, y;
+    	int xin, yin;
+	int stride = cursor_info->MaxWidth >> 2;
+	int flags = cursor_info->Flags;
+	
+	cursor_image = xf86_config->cursor_image;
+	memset(cursor_image, 0, cursor_info->MaxWidth * stride);
+	
+        for (y = 0; y < cursor_info->MaxHeight; y++)
+	    for (x = 0; x < cursor_info->MaxWidth; x++) 
+	    {
+		xf86_crtc_rotate_coord (crtc->rotation,
+					cursor_info->MaxWidth,
+					cursor_info->MaxHeight,
+					x, y, &xin, &yin);
+		if (get_bit(src, stride, flags, xin, yin, FALSE))
+		    set_bit(cursor_image, stride, flags, x, y, FALSE);
+		if (get_bit(src, stride, flags, xin, yin, TRUE))
+		    set_bit(cursor_image, stride, flags, x, y, TRUE);
+	    }
+    }
+    crtc->funcs->load_cursor_image (crtc, cursor_image);
+}
+    
+/*
+ * Load a cursor image into all active CRTCs
+ */
+static void
+xf86_load_cursor_image (ScrnInfoPtr scrn, unsigned char *src)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (crtc->enabled)
+	{
+	    if (crtc->funcs->load_cursor_image)
+		xf86_crtc_load_cursor_image (crtc, src);
+	    else if (crtc->funcs->load_cursor_argb)
+		xf86_crtc_convert_cursor_to_argb (crtc, src);
+	}
+    }
+}
+
+static Bool
+xf86_use_hw_cursor (ScreenPtr screen, CursorPtr cursor)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+
+    xf86_config->cursor = cursor;
+    
+    if (cursor->bits->width > cursor_info->MaxWidth ||
+	cursor->bits->height> cursor_info->MaxHeight)
+	return FALSE;
+
+    return TRUE;
+}
+
+static Bool
+xf86_use_hw_cursor_argb (ScreenPtr screen, CursorPtr cursor)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+    
+    xf86_config->cursor = cursor;
+    
+    /* Make sure ARGB support is available */
+    if ((cursor_info->Flags & HARDWARE_CURSOR_ARGB) == 0)
+	return FALSE;
+    
+    if (cursor->bits->width > cursor_info->MaxWidth ||
+	cursor->bits->height> cursor_info->MaxHeight)
+	return FALSE;
+
+    return TRUE;
+}
+
+static void
+xf86_crtc_load_cursor_argb (xf86CrtcPtr crtc, CursorPtr cursor)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+    CARD32		*cursor_image = (CARD32 *) xf86_config->cursor_image;
+    CARD32		*cursor_source = (CARD32 *) cursor->bits->argb;
+    int			x, y;
+    int			xin, yin;
+    CARD32		bits;
+    int			source_width = cursor->bits->width;
+    int			source_height = cursor->bits->height;
+    int			image_width = cursor_info->MaxWidth;
+    int			image_height = cursor_info->MaxHeight;
+    
+    for (y = 0; y < image_height; y++)
+	for (x = 0; x < image_width; x++)
+	{
+	    xf86_crtc_rotate_coord (crtc->rotation, image_width, image_height,
+				    x, y, &xin, &yin);
+	    if (xin < source_width && yin < source_height)
+		bits = cursor_source[yin * source_width + xin];
+	    else
+		bits = 0;
+	    cursor_image[y * image_width + x] = bits;
+	}
+    
+    crtc->funcs->load_cursor_argb (crtc, cursor_image);
+}
+
+static void
+xf86_load_cursor_argb (ScrnInfoPtr scrn, CursorPtr cursor)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			c;
+
+    for (c = 0; c < xf86_config->num_crtc; c++)
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (crtc->enabled)
+	    xf86_crtc_load_cursor_argb (crtc, cursor);
+    }
+}
+
+Bool
+xf86_cursors_init (ScreenPtr screen, int max_width, int max_height, int flags)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info;
+
+    cursor_info = xf86CreateCursorInfoRec();
+    if (!cursor_info)
+	return FALSE;
+
+    xf86_config->cursor_image = xalloc (max_width * max_height * 4);
+
+    if (!xf86_config->cursor_image)
+    {
+	xf86DestroyCursorInfoRec (cursor_info);
+	return FALSE;
+    }
+	
+    xf86_config->cursor_info = cursor_info;
+
+    cursor_info->MaxWidth = max_width;
+    cursor_info->MaxHeight = max_height;
+    cursor_info->Flags = flags;
+
+    cursor_info->SetCursorColors = xf86_set_cursor_colors;
+    cursor_info->SetCursorPosition = xf86_set_cursor_position;
+    cursor_info->LoadCursorImage = xf86_load_cursor_image;
+    cursor_info->HideCursor = xf86_hide_cursors;
+    cursor_info->ShowCursor = xf86_show_cursors;
+    cursor_info->UseHWCursor = xf86_use_hw_cursor;
+#ifdef ARGB_CURSOR
+    if (flags & HARDWARE_CURSOR_ARGB)
+    {
+	cursor_info->UseHWCursorARGB = xf86_use_hw_cursor_argb;
+	cursor_info->LoadCursorARGB = xf86_load_cursor_argb;
+    }
+#endif
+    
+    xf86_config->cursor = NULL;
+    xf86_hide_cursors (scrn);
+    
+    return xf86InitCursor (screen, cursor_info);
+}
+
+/**
+ * Called when anything on the screen is reconfigured.
+ *
+ * Reloads cursor images as needed, then adjusts cursor positions
+ */
+
+void
+xf86_reload_cursors (ScreenPtr screen)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    xf86CursorInfoPtr	cursor_info = xf86_config->cursor_info;
+    CursorPtr		cursor = xf86_config->cursor;
+    int			x, y;
+    
+    GetSpritePosition (&x, &y);
+    if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN))
+	(*cursor_info->HideCursor)(scrn);
+
+    if (cursor)
+    {
+#ifdef ARGB_CURSOR
+	if (cursor->bits->argb && cursor_info->LoadCursorARGB)
+	    (*cursor_info->LoadCursorARGB) (scrn, cursor);
+	else
+#endif
+	    (*cursor_info->LoadCursorImage)(cursor_info->pScrn,
+					    cursor->devPriv[screen->myNum]);
+
+	(*cursor_info->SetCursorPosition)(cursor_info->pScrn, x, y);
+	(*cursor_info->ShowCursor)(cursor_info->pScrn);
+    }
+}
+
+/**
+ * Clean up CRTC-based cursor code
+ */
+void
+xf86_cursors_fini (ScreenPtr screen)
+{
+    ScrnInfoPtr		scrn = xf86Screens[screen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    
+    if (xf86_config->cursor_info)
+    {
+	xf86DestroyCursorInfoRec (xf86_config->cursor_info);
+	xf86_config->cursor_info = NULL;
+    }
+    if (xf86_config->cursor_image)
+    {
+	xfree (xf86_config->cursor_image);
+	xf86_config->cursor_image = NULL;
+    }
+}
diff --git a/hw/xfree86/ramdac/Makefile.am b/hw/xfree86/ramdac/Makefile.am
index c9afdad..6725ed3 100644
--- a/hw/xfree86/ramdac/Makefile.am
+++ b/hw/xfree86/ramdac/Makefile.am
@@ -1,8 +1,6 @@
-module_LTLIBRARIES = libramdac.la
+noinst_LIBRARIES = libramdac.a
 
-libramdac_la_LDFLAGS = -avoid-version
-
-libramdac_la_SOURCES = xf86RamDacMod.c xf86RamDac.c xf86RamDacCmap.c \
+libramdac_a_SOURCES = xf86RamDac.c xf86RamDacCmap.c \
                       xf86Cursor.c xf86HWCurs.c IBM.c BT.c TI.c \
 		      xf86BitOrder.c
 
diff --git a/hw/xfree86/ramdac/xf86Cursor.h b/hw/xfree86/ramdac/xf86Cursor.h
index 08cca6b..469f48f 100644
--- a/hw/xfree86/ramdac/xf86Cursor.h
+++ b/hw/xfree86/ramdac/xf86Cursor.h
@@ -44,5 +44,8 @@ void xf86ForceHWCursor (ScreenPtr pScreen, Bool on);
 #define HARDWARE_CURSOR_NIBBLE_SWAPPED			0x00000800
 #define HARDWARE_CURSOR_SHOW_TRANSPARENT		0x00001000
 #define HARDWARE_CURSOR_UPDATE_UNHIDDEN			0x00002000
+#ifdef ARGB_CURSOR
+#define HARDWARE_CURSOR_ARGB				0x00004000
+#endif
 
 #endif /* _XF86CURSOR_H */



Reply to: