xf86-video-intel: Branch 'modesetting' - 23 commits - src/i830_crt.c src/i830_cursor.c src/i830_display.c src/i830_display.h src/i830_driver.c src/i830_exa.c src/i830.h src/i830_lvds.c src/i830_memory.c src/i830_modes.c src/i830_randr.c src/i830_tv.c src/i830_video.c src/i830_xf86Crtc.c src/i830_xf86Crtc.h src/i830_xf86Modes.c src/i830_xf86Modes.h src/i830_xf86Rename.h src/i830_xf86Rotate.c src/local_xf86Rename.h src/Makefile.am

Keith Packard keithp at kemper.freedesktop.org
Tue Jan 30 07:25:54 EET 2007


 src/Makefile.am        |    1 
 src/i830.h             |   23 ++
 src/i830_crt.c         |    2 
 src/i830_cursor.c      |  160 ++++++++++---------
 src/i830_display.c     |  291 +++++++++++++++--------------------
 src/i830_display.h     |    6 
 src/i830_driver.c      |   99 +++---------
 src/i830_exa.c         |   13 +
 src/i830_lvds.c        |    6 
 src/i830_memory.c      |  240 ++++++++++++++++++++---------
 src/i830_modes.c       |    6 
 src/i830_randr.c       |   46 +++--
 src/i830_tv.c          |    2 
 src/i830_video.c       |   22 --
 src/i830_xf86Crtc.c    |  323 +++++++++++++++++++++++++++++----------
 src/i830_xf86Crtc.h    |   85 ++++++++--
 src/i830_xf86Modes.c   |   26 +--
 src/i830_xf86Modes.h   |   69 +++-----
 src/i830_xf86Rename.h  |   66 ++++++++
 src/i830_xf86Rotate.c  |  401 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/local_xf86Rename.h |   23 ++
 21 files changed, 1327 insertions(+), 583 deletions(-)

New commits:
diff-tree c8581254cb811f76aa6eae49d74489b543b3eb05 (from parents)
Merge: 9da1791eeca446cd59e2e7d0803e8a7920dbbea5 d329fa121b2401cadb991c2854e077cfa68e15e8
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 29 21:25:13 2007 -0800

    Merge branch 'modesetting-rotation' into modesetting
    
    This adds reasonably driver-independent rotation support to the common
    layer. The piece required in the driver is to allocate and redirect the crtc
    to a shadow frame buffer. The driver uses Render to perform the actual
    rotation operation (which leaves us free to do fun projective transforms at
    some point in the future :-).

diff --cc src/i830_xf86Crtc.c
index 34fa736,c879d99..a209914
@@@ -1232,14 -1367,11 +1367,14 @@@
   * Otherwise, it will affect CRTCs before outputs.
   */
  void
- xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
+ xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
  {
-     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
      int			i;
  
-     if (!pScrn->vtSema)
++    if (!scrn->vtSema)
 +	return;
 +
      if (mode == DPMSModeOff) {
  	for (i = 0; i < config->num_output; i++) {
  	    xf86OutputPtr output = config->output[i];
@@@ -1264,24 -1396,34 +1399,52 @@@
  }
  
  /**
 + * Implement the screensaver by just calling down into the driver DPMS hooks.
 + *
 + * Even for monitors with no DPMS support, by the definition of our DPMS hooks,
 + * the outputs will still get disabled (blanked).
 + */
 +Bool
 +xf86SaveScreen(ScreenPtr pScreen, int mode)
 +{
 +    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 +
 +    if (xf86IsUnblank(mode))
 +	xf86DPMSSet(pScrn, DPMSModeOn, 0);
 +    else
 +	xf86DPMSSet(pScrn, DPMSModeOff, 0);
 +
 +    return TRUE;
 +}
 +
++/**
+  * Disable all inactive crtcs and outputs
+  */
+ void
+ xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
+ {
+     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+     int			o, c;
+ 
+     for (o = 0; o < xf86_config->num_output; o++) 
+     {
+ 	xf86OutputPtr  output = xf86_config->output[o];
+ 	if (!output->crtc) 
+ 	    (*output->funcs->dpms)(output, DPMSModeOff);
+     }
+ 
+     for (c = 0; c < xf86_config->num_crtc; c++) 
+     {
+ 	xf86CrtcPtr crtc = xf86_config->crtc[c];
+ 
+ 	if (!crtc->enabled) 
+ 	{
+ 	    crtc->funcs->dpms(crtc, DPMSModeOff);
+ 	    memset(&crtc->mode, 0, sizeof(crtc->mode));
+ 	}
+     }
+ }
+ 
 - 
  #ifdef RANDR_12_INTERFACE
  
  #define EDID_ATOM_NAME		"EDID_DATA"
diff --cc src/i830_xf86Crtc.h
index f8b561a,1c07ee8..6de2c92
@@@ -453,9 -508,9 +509,12 @@@
  void
  xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
      
 +Bool
 +xf86SaveScreen(ScreenPtr pScreen, int mode);
 +
+ void
+ xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
+ 
  /**
   * Set the EDID information for the specified output
   */
diff-tree d329fa121b2401cadb991c2854e077cfa68e15e8 (from 20419d664c77e9a1a2de82987838b45f44774b47)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 18:36:15 2007 -0800

    Fetch from root window instead of screen pixmap during rotation.
    
    The XAA Composite wrapper doesn't check for sourcing from the root pixmap
    when deciding whether to sync the hardware drawing. Fix the rotation code to
    reference the root window in IncludeInferiors mode to avoid reading without
    correct synchronization.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 7d056e5..3b8be61 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -138,7 +138,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 {
     ScrnInfoPtr		scrn = crtc->scrn;
     ScreenPtr		screen = scrn->pScreen;
-    PixmapPtr		src_pixmap = (*screen->GetScreenPixmap) (screen);
+    WindowPtr		root = WindowTable[screen->myNum];
     PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
     PictFormatPtr	format = compWindowFormat (WindowTable[screen->myNum]);
     int			error;
@@ -146,12 +146,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     PictTransform	transform;
     int			n = REGION_NUM_RECTS(region);
     BoxPtr		b = REGION_RECTS(region);
+    XID			include_inferiors = IncludeInferiors;
     
     src = CreatePicture (None,
-			 &src_pixmap->drawable,
+			 &root->drawable,
 			 format,
-			 0L,
-			 NULL,
+			 CPSubwindowMode,
+			 &include_inferiors,
 			 serverClient,
 			 &error);
     if (!src) {
diff-tree 20419d664c77e9a1a2de82987838b45f44774b47 (from 00decd3b6cea0de22c88b9504dbe26d680e8ab16)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 18:34:12 2007 -0800

    Paint ARGB cursor data to ARGB cursor memory space in frame buffer.
    
    When converting from global cursor to per-crtc cursor, the ARGB cursor data
    was accidentally painted to the wrong location, overwriting some critical
    data and causing the hardware to lock up. (along with generating a garbage
    cursor image from uninitialized data).

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index da220f5..464eb6d 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -389,7 +389,7 @@ static void I830CRTCLoadCursorARGB (xf86
 {
    I830Ptr pI830 = I830PTR(crtc->scrn);
    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem.Start);
+   CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem_argb.Start);
    CARD32 *image = (CARD32 *)pCurs->bits->argb;
    int x, y, w, h;
 
diff-tree 00decd3b6cea0de22c88b9504dbe26d680e8ab16 (from 7a5f17087bda2833e84fa7e7ff0cb168943b89b6)
Author: Krzysztof Halasa <khc at pm.waw.pl>
Date:   Sat Jan 27 12:29:31 2007 -0800

    Don't zero out mode structure after setting name field.
    
    Instead of using memset to zero the structure (at the wrong time, no less),
    use xcalloc to gather pre-initialized memory.

diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index f37eaeb..b5f06d6 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -564,7 +564,7 @@ xf86GetConfigModes (XF86ConfModeLinePtr 
     
     for (; conf_mode; conf_mode = (XF86ConfModeLinePtr) conf_mode->list.next)
     {
-        mode = xalloc(sizeof(DisplayModeRec));
+        mode = xcalloc(1, sizeof(DisplayModeRec));
 	if (!mode)
 	    continue;
         mode->name       = xstrdup(conf_mode->ml_identifier);
@@ -573,8 +573,6 @@ xf86GetConfigModes (XF86ConfModeLinePtr 
 	    xfree (mode);
 	    continue;
 	}
-	
-        memset(mode,'\0',sizeof(DisplayModeRec));
 	mode->type       = 0;
         mode->Clock      = conf_mode->ml_clock;
         mode->HDisplay   = conf_mode->ml_hdisplay;
diff-tree 7a5f17087bda2833e84fa7e7ff0cb168943b89b6 (from 2d95cb6f041653f7e530b1f32cf007929c23ef3b)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 00:11:21 2007 -0800

    Mark crtc region as damaged when rotation is set.
    
    When shadow frame buffer is allocated for rotation, it needs to be
    initialized by copying from the frame buffer. Do this by simply marking the
    entire screen as damaged which will force an update.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index abfaec6..7d056e5 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -328,6 +328,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	PixmapPtr   shadow = crtc->rotatedPixmap;
 	int	    old_width = shadow ? shadow->drawable.width : 0;
 	int	    old_height = shadow ? shadow->drawable.height : 0;
+	BoxRec	    damage_box;
+	RegionRec   damage_region;
 	
 	/* Allocate memory for rotation */
 	if (old_width != width || old_height != height)
@@ -363,6 +365,14 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	    {
 		goto bail3;
 	    }
+	    damage_box.x1 = 0;
+	    damage_box.y1 = 0;
+	    damage_box.x2 = mode_width (mode, rotation);
+	    damage_box.y2 = mode_height (mode, rotation);
+	    REGION_INIT (pScreen, &damage_region, &damage_box, 1);
+	    DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+				&damage_region);
+	    REGION_UNINIT (pScreen, &damage_region);
 	}
 	if (0)
 	{
diff-tree 2d95cb6f041653f7e530b1f32cf007929c23ef3b (from 5c1e27cdd243dc24dd2bfdeb46d757bbef6ba6af)
Author: Keith Packard <keithp at guitar.keithp.com>
Date:   Sat Jan 27 00:04:13 2007 -0800

    Make rotated pixmap size of mode, not rotated mode. Update only damage.
    
    Rotated pixmap should match size of displayed mode, not the rotated version
    of that size.
    
    Take damaged region, rotate each box and display them instead of displaying
    the whole screen after each damage update. This exposes a bug where the
    screen is not correctly damaged after rotation.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 8da79b6..abfaec6 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -94,6 +94,46 @@ compWindowFormat (WindowPtr pWin)
 }
 
 static void
+xf86RotateBox (BoxPtr dst, BoxPtr src, Rotation rotation,
+	       int dest_width, int dest_height)
+{
+    switch (rotation & 0xf) {
+    default:
+    case RR_Rotate_0:
+	*dst = *src;
+	break;
+    case RR_Rotate_90:
+	dst->x1 = src->y1;
+	dst->y1 = dest_height - src->x2;
+	dst->x2 = src->y2;
+	dst->y2 = dest_height - src->x1;
+	break;
+    case RR_Rotate_180:
+	dst->x1 = dest_width - src->x2;
+	dst->y1 = dest_height - src->y2;
+	dst->x2 = dest_width - src->x1;
+	dst->y2 = dest_height - src->y1;
+	break;
+    case RR_Rotate_270:
+	dst->x1 = dest_width - src->y2;
+	dst->y1 = src->x1;
+	dst->y2 = src->x2;
+	dst->x2 = dest_width - src->y1;
+	break;
+    }
+    if (rotation & RR_Reflect_X) {
+	int x1 = dst->x1;
+	dst->x1 = dest_width - dst->x2;
+	dst->x2 = dest_width - x1;
+    }
+    if (rotation & RR_Reflect_Y) {
+	int y1 = dst->y1;
+	dst->y1 = dest_height - dst->y2;
+	dst->y2 = dest_height - y1;
+    }
+}
+
+static void
 xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
 {
     ScrnInfoPtr		scrn = crtc->scrn;
@@ -104,6 +144,8 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     int			error;
     PicturePtr		src, dst;
     PictTransform	transform;
+    int			n = REGION_NUM_RECTS(region);
+    BoxPtr		b = REGION_RECTS(region);
     
     src = CreatePicture (None,
 			 &src_pixmap->drawable,
@@ -127,18 +169,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	ErrorF("couldn't create src pict\n");
 	return;
     }
-    /* Unfortunately, we don't do clipping on transformed source pictures.
-     * So we can't use this.  Instead, we'll just repaint the whole screen
-     * for now, and do transform of the source region into a dest region
-     * later.
-     */
-    /* SetPictureClipRegion (src, 0, 0, region); */
 
     memset (&transform, '\0', sizeof (transform));
     transform.matrix[2][2] = IntToxFixed(1);
     transform.matrix[0][2] = IntToxFixed(crtc->x);
     transform.matrix[1][2] = IntToxFixed(crtc->y);
     switch (crtc->rotation & 0xf) {
+    default:
     case RR_Rotate_0:
 	transform.matrix[0][0] = IntToxFixed(1);
 	transform.matrix[1][1] = IntToxFixed(1);
@@ -177,11 +214,19 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	return;
     }
 
-    CompositePicture (PictOpSrc,
-		      src, NULL, dst,
-		      0, 0, 0, 0, 0, 0,
-		      dst_pixmap->drawable.width,
-		      dst_pixmap->drawable.height);
+    while (n--)
+    {
+	BoxRec	dst_box;
+
+	xf86RotateBox (&dst_box, b, crtc->rotation,
+		       crtc->mode.HDisplay, crtc->mode.VDisplay);
+	CompositePicture (PictOpSrc,
+			  src, NULL, dst,
+			  dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
+			  dst_box.x2 - dst_box.x1,
+			  dst_box.y2 - dst_box.y1);
+	b++;
+    }
     FreePicture (src, None);
     FreePicture (dst, None);
 }
@@ -220,7 +265,7 @@ xf86RotateRedisplay(ScreenPtr pScreen)
 		
 		/* update damaged region */
 		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
-		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
+    		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
 		
 		REGION_UNINIT (pScreen, &crtc_damage);
 	    }
@@ -273,8 +318,13 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
     }
     else
     {
-	int	    width = mode_width (mode, rotation);
-	int	    height = mode_height (mode, rotation);
+	/* 
+	 * these are the size of the shadow pixmap, which
+	 * matches the mode, not the pre-rotated copy in the
+	 * frame buffer
+	 */
+	int	    width = mode->HDisplay;
+	int	    height = mode->VDisplay;
 	PixmapPtr   shadow = crtc->rotatedPixmap;
 	int	    old_width = shadow ? shadow->drawable.width : 0;
 	int	    old_height = shadow ? shadow->drawable.height : 0;
diff-tree 5c1e27cdd243dc24dd2bfdeb46d757bbef6ba6af (from 83cc4601b27d871484a2408f31154e9387064b9e)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 25 15:31:22 2007 -0800

    Make rotated shadow buffer allocation dynamic.
    
    For EXA, this requires version 2.1 of EXA to do rotation, as the VT switching
    issues were too complicated otherwise.

diff --git a/src/i830.h b/src/i830.h
index a7c889d..9ffae94 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -199,7 +199,13 @@ typedef struct _I830CrtcPrivateRec {
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 
-    I830MemRange rotate_mem;
+#ifdef I830_USE_XAA
+    FBLinearPtr rotate_mem_xaa;
+#endif
+#ifdef I830_USE_EXA
+    ExaOffscreenArea *rotate_mem_exa;
+#endif
+
     I830MemRange cursor_mem;
     I830MemRange cursor_mem_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
@@ -613,6 +619,14 @@ extern void i830WaitSync(ScrnInfoPtr pSc
 /* i830_memory.c */
 Bool I830BindAGPMemory(ScrnInfoPtr pScrn);
 Bool I830UnbindAGPMemory(ScrnInfoPtr pScrn);
+#ifdef I830_USE_XAA
+FBLinearPtr
+i830_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length,
+				 int granularity,
+				 MoveLinearCallbackProcPtr moveCB,
+				 RemoveLinearCallbackProcPtr removeCB,
+				 pointer privData);
+#endif /* I830_USE_EXA */
 
 /* i830_modes.c */
 DisplayModePtr i830_ddc_get_modes(xf86OutputPtr output);
diff --git a/src/i830_display.c b/src/i830_display.c
index 2313f76..8202985 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -342,8 +342,9 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (crtc->rotation != RR_Rotate_0) {
-	Start = intel_crtc->rotate_mem.Start;
+    if (crtc->rotatedPixmap != NULL) {
+	Start = (char *)crtc->rotatedPixmap->devPrivate.ptr -
+	    (char *)pI830->FbBase;
     } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->FrontBuffer.Start;
     } else {
@@ -895,31 +896,92 @@ static PixmapPtr
 i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
+    ScreenPtr pScreen = pScrn->pScreen;
     I830Ptr pI830 = I830PTR(pScrn);
     I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
     unsigned long rotate_pitch;
     PixmapPtr rotate_pixmap;
-    pointer rotate_offset;
-
-    if (intel_crtc->rotate_mem.Start == 0)
-	return NULL;
+    unsigned long rotate_offset;
+    int align = KB(4), size;
 
     rotate_pitch = pI830->displayWidth * pI830->cpp;
-    rotate_offset = pI830->FbBase + intel_crtc->rotate_mem.Start;
+    size = rotate_pitch * height;
+
+#ifdef I830_USE_EXA
+    /* We could get close to what we want here by just creating a pixmap like
+     * normal, but we have to lock it down in framebuffer, and there is no
+     * setter for offscreen area locking in EXA currently.  So, we just
+     * allocate offscreen memory and fake up a pixmap header for it.
+     */
+    if (pI830->useEXA) {
+	assert(intel_crtc->rotate_mem_exa == NULL);
+
+	intel_crtc->rotate_mem_exa = exaOffscreenAlloc(pScreen, size, align,
+						       TRUE, NULL, NULL);
+	if (intel_crtc->rotate_mem_exa == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Couldn't allocate shadow memory for rotated CRTC\n");
+	    return NULL;
+	}
+	rotate_offset = intel_crtc->rotate_mem_exa->offset;
+    }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+    if (!pI830->useEXA) {
+	/* The XFree86 linear allocator operates in units of screen pixels,
+	 * sadly.
+	 */
+	size = (size + pI830->cpp - 1) / pI830->cpp;
+	align = (align + pI830->cpp - 1) / pI830->cpp;
+
+	assert(intel_crtc->rotate_mem_xaa == NULL);
+
+	intel_crtc->rotate_mem_xaa =
+	    i830_xf86AllocateOffscreenLinear(pScreen, size, align,
+					     NULL, NULL, NULL);
+	if (intel_crtc->rotate_mem_xaa == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Couldn't allocate shadow memory for rotated CRTC\n");
+	    return NULL;
+	}
+	rotate_offset = pI830->FrontBuffer.Start +
+	    intel_crtc->rotate_mem_xaa->offset * pI830->cpp;
+    }
+#endif /* I830_USE_XAA */
 
     rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
 					   width, height,
 					   pScrn->depth,
 					   pScrn->bitsPerPixel,
 					   rotate_pitch,
-					   rotate_offset);
+					   pI830->FbBase + rotate_offset);
+    if (rotate_pixmap == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "Couldn't allocate shadow pixmap for rotated CRTC\n");
+    }
     return rotate_pixmap;
 }
 
 static void
 i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap)
 {
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+
     FreeScratchPixmapHeader(rotate_pixmap);
+#ifdef I830_USE_EXA
+    if (pI830->useEXA && intel_crtc->rotate_mem_exa != NULL) {
+	exaOffscreenFree(pScrn->pScreen, intel_crtc->rotate_mem_exa);
+	intel_crtc->rotate_mem_exa = NULL;
+    }
+#endif /* I830_USE_EXA */
+#ifdef I830_USE_XAA
+    if (!pI830->useEXA) {
+	xf86FreeOffscreenLinear(intel_crtc->rotate_mem_xaa);
+	intel_crtc->rotate_mem_xaa = NULL;
+    }
+#endif /* I830_USE_XAA */
 }
 
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 644ea57..19e97b0 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2879,7 +2879,23 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       shadowSetup(pScreen);
       /* support all rotations */
       xf86RandR12Init (pScreen);
-      xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270);
+      if (pI830->useEXA) {
+#ifdef I830_USE_EXA
+	 if (pI830->EXADriverPtr->exa_minor >= 1) {
+	    xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 |
+				     RR_Rotate_180 | RR_Rotate_270);
+	 } else {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "EXA version %d.%d too old to support rotation\n",
+		       pI830->EXADriverPtr->exa_major,
+		       pI830->EXADriverPtr->exa_minor);
+	    xf86RandR12SetRotations (pScreen, RR_Rotate_0);
+	 }
+#endif /* I830_USE_EXA */
+      } else {
+	 xf86RandR12SetRotations (pScreen, RR_Rotate_0 | RR_Rotate_90 |
+				  RR_Rotate_180 | RR_Rotate_270);
+      }
       pI830->PointerMoved = pScrn->PointerMoved;
       pScrn->PointerMoved = I830PointerMoved;
       pI830->CreateScreenResources = pScreen->CreateScreenResources;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index f1cd1e3..3fd5e4a 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -418,7 +418,7 @@ I830EXAInit(ScreenPtr pScreen)
     
     pI830->bufferOffset = 0;
     pI830->EXADriverPtr->exa_major = 2;
-    pI830->EXADriverPtr->exa_minor = 0;
+    pI830->EXADriverPtr->exa_minor = 1;
     pI830->EXADriverPtr->memoryBase = pI830->FbBase;
     pI830->EXADriverPtr->offScreenBase = pI830->Offscreen.Start;
     pI830->EXADriverPtr->memorySize = pI830->Offscreen.End;
@@ -520,9 +520,14 @@ I830EXAInit(ScreenPtr pScreen)
     }
 
     if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
-	xfree(pI830->EXADriverPtr);
-	pI830->noAccel = TRUE;
-	return FALSE;
+	xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		   "EXA initialization failed; trying older version\n");
+	pI830->EXADriverPtr->exa_minor = 0;
+	if(!exaDriverInit(pScreen, pI830->EXADriverPtr)) {
+	    xfree(pI830->EXADriverPtr);
+	    pI830->noAccel = TRUE;
+	    return FALSE;
+	}
     }
 
     I830SelectBuffer(pScrn, I830_SELECT_FRONT);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 14dacc8..24f0b29 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -769,63 +769,6 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
    return TRUE;
 }
 
-/**
- * Allocates memory for the rotated shadow buffers.
- *
- * This memory would be better allocated normally through the linear allocator,
- * but it gets rotation working for now.
- */
-static Bool
-I830AllocateRotateBuffers(xf86CrtcPtr crtc, const int flags)
-{
-   ScrnInfoPtr pScrn = crtc->scrn;
-   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
-   I830Ptr pI830 = I830PTR(pScrn);
-   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-   unsigned long avail, lineSize;
-   int verbosity = dryrun ? 4 : 1;
-   const char *s = dryrun ? "[dryrun] " : "";
-   int align, alignflags;
-   long size, alloced;
-   int rotate_width, rotate_height;
-
-   memset(&intel_crtc->rotate_mem, 0, sizeof(intel_crtc->rotate_mem));
-
-   rotate_width = pScrn->displayWidth;
-   if (pScrn->virtualX > pScrn->virtualY)
-      rotate_height = pScrn->virtualX;
-   else
-      rotate_height = pScrn->virtualY;
-
-   lineSize = pScrn->displayWidth * pI830->cpp;
-   avail = pScrn->videoRam * 1024;
-
-   align = KB(64);
-   alignflags = 0;
-
-   size = lineSize * rotate_height;
-   size = ROUND_TO_PAGE(size);
-   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-		  "%sInitial %sshadow framebuffer allocation size: "
-		  "%ld kByte\n",
-		  s, (intel_crtc->pipe == 0) ? "" : "secondary ",
-		  size / 1024);
-   alloced = I830AllocVidMem(pScrn, &intel_crtc->rotate_mem,
-			     &pI830->StolenPool, size, align,
-			     flags | alignflags |
-			     FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
-   if (alloced < size) {
-      if (!dryrun) {
-	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
-		    "%sshadow framebuffer. Is your VideoRAM set too low?\n",
-		    (intel_crtc->pipe == 0) ? "" : "secondary ");
-      }
-      return FALSE;
-   }
-
-   return TRUE;
-}
-
 static Bool
 I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags)
 {
@@ -981,10 +924,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 return FALSE;
       }
 
-      for (i = 0; i < xf86_config->num_crtc; i++) {
-	 I830AllocateRotateBuffers(xf86_config->crtc[i], flags);
-      }
-
 #ifdef I830_USE_EXA
       if (pI830->useEXA) {
 	 /* Default EXA to having 3 screens worth of offscreen memory space
@@ -1619,7 +1558,6 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
    for (i = 0; i < xf86_config->num_crtc; i++) {
       I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-      I830FixOffset(pScrn, &intel_crtc->rotate_mem);
       I830FixOffset(pScrn, &intel_crtc->cursor_mem);
       I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb);
    }
@@ -2028,8 +1966,6 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
       for (i = 0; i < xf86_config->num_crtc; i++) {
 	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-	 if (!BindMemRange(pScrn, &intel_crtc->rotate_mem))
-	    return FALSE;
 	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem))
 	    return FALSE;
 	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
@@ -2130,8 +2066,6 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
       for (i = 0; i < xf86_config->num_crtc; i++) {
 	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
 
-	 if (!UnbindMemRange(pScrn, &intel_crtc->rotate_mem))
-	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem))
 	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
@@ -2209,3 +2143,41 @@ I830CheckAvailableMemory(ScrnInfoPtr pSc
 
    return maxPages * 4;
 }
+
+#ifdef I830_USE_XAA
+/**
+ * Allocates memory from the XF86 linear allocator, but also purges
+ * memory if possible to cause the allocation to succeed.
+ */
+FBLinearPtr
+i830_xf86AllocateOffscreenLinear(ScreenPtr pScreen, int length,
+				 int granularity,
+				 MoveLinearCallbackProcPtr moveCB,
+				 RemoveLinearCallbackProcPtr removeCB,
+				 pointer privData)
+{
+   FBLinearPtr linear;
+   int max_size;
+
+   linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
+					removeCB, privData);
+   if (linear != NULL)
+      return linear;
+
+   /* The above allocation didn't succeed, so purge unlocked stuff and try
+    * again.
+    */
+   xf86QueryLargestOffscreenLinear(pScreen, &max_size, granularity,
+				   PRIORITY_EXTREME);
+
+   if (max_size < length)
+      return NULL;
+
+   xf86PurgeUnlockedOffscreenAreas(pScreen);
+
+   linear = xf86AllocateOffscreenLinear(pScreen, length, granularity, moveCB,
+					removeCB, privData);
+
+   return linear;
+}
+#endif
diff --git a/src/i830_video.c b/src/i830_video.c
index 79f5a7c..22f5bee 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2073,8 +2073,6 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
 #endif /* I830_USE_EXA */
 #ifdef I830_USE_XAA
    if (!pI830->useEXA) {
-      int max_size;
-
       /* Converts an offset from XAA's linear allocator to an offset from the
        * start of fb.
        */
@@ -2100,25 +2098,11 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
 	 xf86FreeOffscreenLinear(linear->xaa);
       }
 
-      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
-						NULL, NULL, NULL);
-      if (linear->xaa != NULL) {
-	 linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
+      linear->xaa = i830_xf86AllocateOffscreenLinear(pScreen, size, align,
+						     NULL, NULL, NULL);
+      if (linear->xaa == NULL)
 	 return;
-      }
-
-      xf86QueryLargestOffscreenLinear(pScreen, &max_size, align,
-				      PRIORITY_EXTREME);
-
-      if (max_size < size) {
-	 ErrorF("No memory available\n");
-	 linear->offset = 0;
-	 return;
-      }
 
-      xf86PurgeUnlockedOffscreenAreas(pScreen);
-      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
-						NULL, NULL, NULL);
       linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
    }
 #endif /* I830_USE_XAA */
diff-tree 83cc4601b27d871484a2408f31154e9387064b9e (from e21332419581eff1d7651741bae0b640c84d0ecd)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 24 16:52:22 2007 +0800

    Fix a possible failure to misalign video allocation in XAA.

diff --git a/src/i830_video.c b/src/i830_video.c
index a330eb5..79f5a7c 100644
--- a/src/i830_video.c
+++ b/src/i830_video.c
@@ -2117,7 +2117,7 @@ I830AllocateMemory(ScrnInfoPtr pScrn, st
       }
 
       xf86PurgeUnlockedOffscreenAreas(pScreen);
-      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, 4,
+      linear->xaa = xf86AllocateOffscreenLinear(pScreen, size, align,
 						NULL, NULL, NULL);
       linear->offset = XAA_OFFSET_TO_OFFSET(linear->xaa->offset);
    }
diff-tree e21332419581eff1d7651741bae0b640c84d0ecd (from 74ebff6732b9bfcf8c865b52cbebfd9bf6b73eb2)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 24 12:32:38 2007 +0800

    Warning fix.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index bb5bc38..da220f5 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -486,8 +486,8 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     {
 	xf86CrtcPtr	    crtc = xf86_config->crtc[pipe];
 	DisplayModePtr	    mode = &crtc->mode;
-	int		    thisx;
-	int		    thisy;
+	int		    thisx = 0;
+	int		    thisy = 0;
 	int hotspotx = 0, hotspoty = 0;
 
 	if (!crtc->enabled)
diff-tree 74ebff6732b9bfcf8c865b52cbebfd9bf6b73eb2 (from 8759f4d89a141f7d69f1894ec3059ba6bd1cf86b)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 14:26:21 2007 -0800

    Allocate separate cursor memory per CRTC and rotate cursors appropriately.
    
    Also, add bind/unbind of the shadow rotate buffers, which was missed in a
    previous commit.

diff --git a/src/i830.h b/src/i830.h
index c792073..a7c889d 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -200,6 +200,8 @@ typedef struct _I830CrtcPrivateRec {
     CARD8 lut_r[256], lut_g[256], lut_b[256];
 
     I830MemRange rotate_mem;
+    I830MemRange cursor_mem;
+    I830MemRange cursor_mem_argb;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
@@ -276,8 +278,6 @@ typedef struct _I830Rec {
    I830MemRange EXAStateMem;  /* specific exa state for G965 */
 #endif
    /* Regions allocated either from the above pools, or from agpgart. */
-   I830MemRange	*CursorMem;
-   I830MemRange	*CursorMemARGB;
    I830RingBuffer *LpRing;
 
 #if REMAP_RESERVED
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 364320e..bb5bc38 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -94,9 +94,9 @@ I830SetPipeCursorBase (xf86CrtcPtr crtc)
 	FatalError("Bad pipe number for cursor base setting\n");
 
     if (pI830->CursorIsARGB)
-	cursor_mem = pI830->CursorMemARGB;
+	cursor_mem = &intel_crtc->cursor_mem_argb;
     else
-	cursor_mem = pI830->CursorMem;
+	cursor_mem = &intel_crtc->cursor_mem;
 
     if (pI830->CursorNeedsPhysical) {
 	OUTREG(cursor_base, cursor_mem->Physical);
@@ -251,21 +251,13 @@ I830CursorInit(ScreenPtr pScreen)
    infoPtr->HideCursor = I830HideCursor;
    infoPtr->ShowCursor = I830ShowCursor;
    infoPtr->UseHWCursor = I830UseHWCursor;
-
-   pI830->pCurs = NULL;
-
 #ifdef ARGB_CURSOR
-   pI830->CursorIsARGB = FALSE;
-
-   if (pI830->CursorMemARGB->Start) {
-      /* Use ARGB if we were able to allocate the 16kb needed */
-      infoPtr->UseHWCursorARGB = I830UseHWCursorARGB;
-      infoPtr->LoadCursorARGB = I830LoadCursorARGB;
-   }
+   infoPtr->UseHWCursorARGB = I830UseHWCursorARGB;
+   infoPtr->LoadCursorARGB = I830LoadCursorARGB;
 #endif
 
-   if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) 
-      return FALSE;
+   pI830->pCurs = NULL;
+
 
    I830HideCursor(pScrn);
 
@@ -280,18 +272,16 @@ I830UseHWCursor(ScreenPtr pScreen, Curso
 
    pI830->pCurs = pCurs;
 
-   DPRINTF(PFX, "I830UseHWCursor\n");
-   if (pI830->CursorNeedsPhysical && !pI830->CursorMem->Physical) 
-      return FALSE;
-
    return TRUE;
 }
 
 static void
-I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+I830CRTCLoadCursorImage(xf86CrtcPtr crtc, unsigned char *src)
 {
+   ScrnInfoPtr pScrn = crtc->scrn;
    I830Ptr pI830 = I830PTR(pScrn);
-   CARD8 *pcurs = (CARD8 *) (pI830->FbBase + pI830->CursorMem->Start);
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   CARD8 *pcurs = (CARD8 *) (pI830->FbBase + intel_crtc->cursor_mem.Start);
    int x, y;
 
    DPRINTF(PFX, "I830LoadCursorImage\n");
@@ -310,7 +300,7 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, u
     (*(image + (x) / 8 + (y) * (128/8)) |=\
      (int) (1 <<  (7-((x) % 8))))
 
-   switch (pI830->rotation) {
+   switch (crtc->rotation) {
       case RR_Rotate_90:
          for (y = 0; y < 64; y++) {
             for (x = 0; x < 64; x++) {
@@ -353,6 +343,17 @@ I830LoadCursorImage(ScrnInfoPtr pScrn, u
    }
 }
 
+static void
+I830LoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src)
+{
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int pipe;
+
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) {
+       I830CRTCLoadCursorImage(xf86_config->crtc[pipe], src);
+    }
+}
+
 #ifdef ARGB_CURSOR
 #include "cursorstr.h"
 
@@ -360,15 +361,22 @@ static Bool I830UseHWCursorARGB (ScreenP
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+   int i;
 
    DPRINTF(PFX, "I830UseHWCursorARGB\n");
 
    pI830->pCurs = pCurs;
 
-   if (pScrn->bitsPerPixel == 8)
-      return FALSE;
+   /* Check that our ARGB allocations succeeded */
+   for (i = 0; i < xf86_config->num_crtc; i++) {
+      I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+      if (!intel_crtc->cursor_mem_argb.Start)
+	 return FALSE;
+   }
 
-   if (pI830->CursorNeedsPhysical && !pI830->CursorMemARGB->Physical) 
+   if (pScrn->bitsPerPixel == 8)
       return FALSE;
 
    if (pCurs->bits->height <= 64 && pCurs->bits->width <= 64) 
@@ -377,10 +385,11 @@ static Bool I830UseHWCursorARGB (ScreenP
    return FALSE;
 }
 
-static void I830LoadCursorARGB (ScrnInfoPtr pScrn, CursorPtr pCurs)
+static void I830CRTCLoadCursorARGB (xf86CrtcPtr crtc, CursorPtr pCurs)
 {
-   I830Ptr pI830 = I830PTR(pScrn);
-   CARD32 *dst = (CARD32 *) (pI830->FbBase + pI830->CursorMemARGB->Start);
+   I830Ptr pI830 = I830PTR(crtc->scrn);
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   CARD32 *dst = (CARD32 *) (pI830->FbBase + intel_crtc->cursor_mem.Start);
    CARD32 *image = (CARD32 *)pCurs->bits->argb;
    int x, y, w, h;
 
@@ -394,7 +403,7 @@ static void I830LoadCursorARGB (ScrnInfo
    w = pCurs->bits->width;
    h = pCurs->bits->height;
 
-   switch (pI830->rotation) {
+   switch (crtc->rotation) {
       case RR_Rotate_90:
          for (y = 0; y < h; y++) {
             for (x = 0; x < w; x++)
@@ -447,12 +456,23 @@ static void I830LoadCursorARGB (ScrnInfo
           *dst++ = 0;
    }
 }
+
+static void
+I830LoadCursorARGB(ScrnInfoPtr pScrn, CursorPtr pCurs)
+{
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int pipe;
+
+    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) {
+       I830CRTCLoadCursorARGB(xf86_config->crtc[pipe], pCurs);
+    }
+}
 #endif
 
 static void
 I830SetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
 {
-   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
     Bool inrange;
@@ -473,7 +493,6 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	if (!crtc->enabled)
 	    continue;
 
-	/* XXX: deal with hotspot issues */
 	switch (crtc->rotation) {
 	case RR_Rotate_0:
 	    thisx = (root_x - crtc->x);
@@ -482,18 +501,18 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 	case RR_Rotate_90:
 	    thisx = (root_y - crtc->y);
 	    thisy = mode->VDisplay - (root_x - crtc->x);
-	    /*hotspoty = I810_CURSOR_X;*/
+	    hotspoty = I810_CURSOR_X;
 	    break;
 	case RR_Rotate_180:
 	    thisx = mode->HDisplay - (root_x - crtc->x);
 	    thisy = mode->VDisplay - (root_y - crtc->y);
-	    /*hotspotx = I810_CURSOR_X;
-	      hotspoty = I810_CURSOR_Y;*/
+	    hotspotx = I810_CURSOR_X;
+	    hotspoty = I810_CURSOR_Y;
 	    break;
 	case RR_Rotate_270:
 	    thisx = mode->VDisplay - (root_y - crtc->y);
 	    thisy = (root_x - crtc->x);
-	    /*hotspotx = I810_CURSOR_Y;*/
+	    hotspotx = I810_CURSOR_Y;
 	    break;
 	}
 
@@ -542,19 +561,11 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
 static void
 I830ShowCursor(ScrnInfoPtr pScrn)
 {
-   xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-   I830Ptr pI830 = I830PTR(pScrn);
+    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    I830Ptr pI830 = I830PTR(pScrn);
     int pipe;
 
-   DPRINTF(PFX, "I830ShowCursor\n");
-   DPRINTF(PFX,
-	   "Value of CursorMem->Physical is %x, "
-	   " Value of CursorMem->Start is %x ",
-	   pI830->CursorMem->Physical, pI830->CursorMem->Start);
-   DPRINTF(PFX,
-	   "Value of CursorMemARGB->Physical is %x, "
-	   " Value of CursorMemARGB->Start is %x ",
-	   pI830->CursorMemARGB->Physical, pI830->CursorMemARGB->Start);
+    DPRINTF(PFX, "I830ShowCursor\n");
 
     pI830->cursorOn = TRUE;
     for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 84fd9d8..644ea57 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -765,12 +765,6 @@ PreInitCleanup(ScrnInfoPtr pScrn)
       if (pI830->LpRing)
          xfree(pI830->LpRing);
       pI830->LpRing = NULL;
-      if (pI830->CursorMem)
-         xfree(pI830->CursorMem);
-      pI830->CursorMem = NULL;
-      if (pI830->CursorMemARGB) 
-         xfree(pI830->CursorMemARGB);
-      pI830->CursorMemARGB = NULL;
       if (pI830->OverlayMem)
          xfree(pI830->OverlayMem);
       pI830->OverlayMem = NULL;
@@ -1527,12 +1521,10 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    /* Alloc our pointers for the primary head */
    if (I830IsPrimary(pScrn)) {
       pI830->LpRing = xalloc(sizeof(I830RingBuffer));
-      pI830->CursorMem = xalloc(sizeof(I830MemRange));
-      pI830->CursorMemARGB = xalloc(sizeof(I830MemRange));
       pI830->OverlayMem = xalloc(sizeof(I830MemRange));
       pI830->overlayOn = xalloc(sizeof(Bool));
       pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
+      if (!pI830->LpRing ||
           !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
@@ -2583,17 +2575,13 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (I830IsPrimary(pScrn)) {
       if (!pI830->LpRing)
          pI830->LpRing = xalloc(sizeof(I830RingBuffer));
-      if (!pI830->CursorMem)
-         pI830->CursorMem = xalloc(sizeof(I830MemRange));
-      if (!pI830->CursorMemARGB)
-         pI830->CursorMemARGB = xalloc(sizeof(I830MemRange));
       if (!pI830->OverlayMem)
          pI830->OverlayMem = xalloc(sizeof(I830MemRange));
       if (!pI830->overlayOn)
          pI830->overlayOn = xalloc(sizeof(Bool));
       if (!pI830->used3D)
          pI830->used3D = xalloc(sizeof(int));
-      if (!pI830->LpRing || !pI830->CursorMem || !pI830->CursorMemARGB ||
+      if (!pI830->LpRing ||
           !pI830->OverlayMem || !pI830->overlayOn || !pI830->used3D) {
          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		 "Could not allocate primary data structures.\n");
@@ -2608,8 +2596,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
    if (!I830IsPrimary(pScrn)) {
       pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
       pI830->LpRing = pI8301->LpRing;
-      pI830->CursorMem = pI8301->CursorMem;
-      pI830->CursorMemARGB = pI8301->CursorMemARGB;
       pI830->OverlayMem = pI8301->OverlayMem;
       pI830->overlayOn = pI8301->overlayOn;
       pI830->used3D = pI8301->used3D;
@@ -2658,15 +2644,6 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       }
    }
 
-   if (!pI830->SWCursor) {
-      if (pI830->CursorMem->Size == 0) {
-	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		     "Disabling HW cursor because the cursor memory "
-		      "allocation failed.\n");
-	   pI830->SWCursor = TRUE;
-      }
-   }
-
 #ifdef I830_XV
    if (pI830->XvEnabled) {
       if (pI830->noAccel) {
@@ -3354,10 +3331,6 @@ I830CloseScreen(int scrnIndex, ScreenPtr
 
       xfree(pI830->LpRing);
       pI830->LpRing = NULL;
-      xfree(pI830->CursorMem);
-      pI830->CursorMem = NULL;
-      xfree(pI830->CursorMemARGB);
-      pI830->CursorMemARGB = NULL;
       xfree(pI830->OverlayMem);
       pI830->OverlayMem = NULL;
       xfree(pI830->overlayOn);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index ae14c06..14dacc8 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -826,6 +826,91 @@ I830AllocateRotateBuffers(xf86CrtcPtr cr
    return TRUE;
 }
 
+static Bool
+I830AllocateCursorBuffers(xf86CrtcPtr crtc, const int flags)
+{
+   ScrnInfoPtr pScrn = crtc->scrn;
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   I830Ptr pI830 = I830PTR(pScrn);
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   long size, alloced;
+   int cursFlags = 0;
+
+   /* Clear cursor info */
+   memset(&intel_crtc->cursor_mem, 0, sizeof(I830MemRange));
+   intel_crtc->cursor_mem.Key = -1;
+   memset(&intel_crtc->cursor_mem_argb, 0, sizeof(I830MemRange));
+   intel_crtc->cursor_mem_argb.Key = -1;
+
+   if (pI830->SWCursor)
+      return FALSE;
+
+   /*
+    * Mouse cursor -- The i810-i830 need a physical address in system
+    * memory from which to upload the cursor.  We get this from
+    * the agpgart module using a special memory type.
+    */
+
+   size = HWCURSOR_SIZE;
+   cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+   if (pI830->CursorNeedsPhysical)
+      cursFlags |= NEED_PHYSICAL_ADDR;
+
+   alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem,
+			     &pI830->StolenPool, size,
+			     GTT_PAGE_SIZE, flags | cursFlags);
+   if (alloced < size ||
+       (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem.Physical))
+   {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate HW cursor space.\n");
+	 return FALSE;
+      }
+   } else {
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		     "%sAllocated %ld kB for HW cursor at 0x%lx", s,
+		     alloced / 1024, intel_crtc->cursor_mem.Start);
+      if (pI830->CursorNeedsPhysical) {
+	 xf86ErrorFVerb(verbosity, " (0x%08lx)",
+			intel_crtc->cursor_mem.Physical);
+      }
+      xf86ErrorFVerb(verbosity, "\n");
+   }
+
+   /* Allocate the ARGB cursor space.  Its success is optional -- we won't set
+    * SWCursor if it fails.
+    */
+   size = HWCURSOR_SIZE_ARGB;
+   cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
+   if (pI830->CursorNeedsPhysical)
+      cursFlags |= NEED_PHYSICAL_ADDR;
+
+   alloced = I830AllocVidMem(pScrn, &intel_crtc->cursor_mem_argb,
+			     &pI830->StolenPool, size,
+			     GTT_PAGE_SIZE, flags | cursFlags);
+   if (alloced < size ||
+       (pI830->CursorNeedsPhysical && !intel_crtc->cursor_mem_argb.Physical)) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate HW (ARGB) cursor space.\n");
+      }
+   } else {
+      xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		     "%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
+		     alloced / 1024, intel_crtc->cursor_mem_argb.Start);
+      if (pI830->CursorNeedsPhysical) {
+	 xf86ErrorFVerb(verbosity, " (0x%08lx)",
+			intel_crtc->cursor_mem_argb.Physical);
+      }
+      xf86ErrorFVerb(verbosity, "\n");
+   }
+
+   return FALSE;
+}
+
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
@@ -834,6 +919,7 @@ Bool
 I830Allocate2DMemory(ScrnInfoPtr pScrn, const int flags)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
    long size, alloced;
    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
    int verbosity = dryrun ? 4 : 1;
@@ -871,8 +957,6 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	   pI830->StolenPool.Free.Size);
 
    if (flags & ALLOC_INITIAL) {
-      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-
       if (pI830->NeedRingBufferLow)
 	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);
 
@@ -1041,63 +1125,18 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
    }
 #endif
 
-   /* Clear cursor info */
-   memset(pI830->CursorMem, 0, sizeof(I830MemRange));
-   pI830->CursorMem->Key = -1;
-   memset(pI830->CursorMemARGB, 0, sizeof(I830MemRange));
-   pI830->CursorMemARGB->Key = -1;
-
-   if (!pI830->SWCursor) {
-      int cursFlags = 0;
-      /*
-       * Mouse cursor -- The i810-i830 need a physical address in system
-       * memory from which to upload the cursor.  We get this from
-       * the agpgart module using a special memory type.
-       */
-
-      size = HWCURSOR_SIZE;
-      cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
-      if (pI830->CursorNeedsPhysical)
-	 cursFlags |= NEED_PHYSICAL_ADDR;
-
-      alloced = I830AllocVidMem(pScrn, pI830->CursorMem,
-				&(pI830->StolenPool), size,
-				GTT_PAGE_SIZE, flags | cursFlags);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW cursor space.\n");
-	 }
-      } else {
-	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			"%sAllocated %ld kB for HW cursor at 0x%lx", s,
-			alloced / 1024, pI830->CursorMem->Start);
-	 if (pI830->CursorNeedsPhysical)
-	    xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMem->Physical);
-	 xf86ErrorFVerb(verbosity, "\n");
-      }
-
-      size = HWCURSOR_SIZE_ARGB;
-      cursFlags = FROM_ANYWHERE | ALLOCATE_AT_TOP;
-      if (pI830->CursorNeedsPhysical)
-	 cursFlags |= NEED_PHYSICAL_ADDR;
-
-      alloced = I830AllocVidMem(pScrn, pI830->CursorMemARGB,
-				&(pI830->StolenPool), size,
-				GTT_PAGE_SIZE, flags | cursFlags);
-      if (alloced < size) {
-	 if (!dryrun) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		       "Failed to allocate HW (ARGB) cursor space.\n");
-	 }
-      } else {
-	 xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
-			"%sAllocated %ld kB for HW (ARGB) cursor at 0x%lx", s,
-			alloced / 1024, pI830->CursorMemARGB->Start);
-	 if (pI830->CursorNeedsPhysical)
-	    xf86ErrorFVerb(verbosity, " (0x%08lx)", pI830->CursorMemARGB->Physical);
-	 xf86ErrorFVerb(verbosity, "\n");
-      }
+   if (!pI830->SWCursor && !dryrun) {
+       for (i = 0; i < xf86_config->num_crtc; i++) {
+	   if (!I830AllocateCursorBuffers(xf86_config->crtc[i], flags) &&
+	       pI830->SWCursor)
+	   {
+	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			  "Disabling HW cursor because the cursor memory "
+			  "allocation failed.\n");
+	       pI830->SWCursor = TRUE;
+	       break;
+	   }
+       }
    }
 
 #ifdef I830_XV
@@ -1567,6 +1606,8 @@ Bool
 I830FixupOffsets(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
+   xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+   int i;
 
    DPRINTF(PFX, "I830FixupOffsets\n");
 
@@ -1574,8 +1615,15 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
       I830FixOffset(pScrn, &(pI830->FrontBuffer2));
    I830FixOffset(pScrn, &(pI830->FrontBuffer));
-   I830FixOffset(pScrn, pI830->CursorMem);
-   I830FixOffset(pScrn, pI830->CursorMemARGB);
+
+   for (i = 0; i < xf86_config->num_crtc; i++) {
+      I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+      I830FixOffset(pScrn, &intel_crtc->rotate_mem);
+      I830FixOffset(pScrn, &intel_crtc->cursor_mem);
+      I830FixOffset(pScrn, &intel_crtc->cursor_mem_argb);
+   }
+
    I830FixOffset(pScrn, &(pI830->LpRing->mem));
    I830FixOffset(pScrn, &(pI830->Scratch));
    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
@@ -1958,6 +2006,9 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
       return TRUE;
 
    if (xf86AgpGARTSupported() && !pI830->GttBound) {
+      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+      int i;
+
       if (!xf86AcquireGART(pScrn->scrnIndex))
 	 return FALSE;
 
@@ -1973,10 +2024,17 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
       if (!BindMemRange(pScrn, &(pI830->FrontBuffer)))
 	 return FALSE;
-      if (!BindMemRange(pScrn, pI830->CursorMem))
-	 return FALSE;
-      if (!BindMemRange(pScrn, pI830->CursorMemARGB))
-	 return FALSE;
+
+      for (i = 0; i < xf86_config->num_crtc; i++) {
+	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+	 if (!BindMemRange(pScrn, &intel_crtc->rotate_mem))
+	    return FALSE;
+	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem))
+	    return FALSE;
+	 if (!BindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
+	    return FALSE;
+      }
       if (!BindMemRange(pScrn, &(pI830->LpRing->mem)))
 	 return FALSE;
       if (!BindMemRange(pScrn, &(pI830->Scratch)))
@@ -2053,6 +2111,8 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
       return TRUE;
 
    if (xf86AgpGARTSupported() && pI830->GttBound) {
+      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+      int i;
 
 #if REMAP_RESERVED
       /* "unbind" the pre-allocated region. */
@@ -2066,10 +2126,18 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
       if (!UnbindMemRange(pScrn, &(pI830->FrontBuffer)))
 	 return FALSE;
-      if (!UnbindMemRange(pScrn, pI830->CursorMem))
-	 return FALSE;
-      if (!UnbindMemRange(pScrn, pI830->CursorMemARGB))
-	 return FALSE;
+
+      for (i = 0; i < xf86_config->num_crtc; i++) {
+	 I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+
+	 if (!UnbindMemRange(pScrn, &intel_crtc->rotate_mem))
+	    return FALSE;
+	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem))
+	    return FALSE;
+	 if (!UnbindMemRange(pScrn, &intel_crtc->cursor_mem_argb))
+	    return FALSE;
+      }
+
       if (!UnbindMemRange(pScrn, &(pI830->LpRing->mem)))
 	 return FALSE;
       if (!UnbindMemRange(pScrn, &(pI830->Scratch)))
diff-tree 8759f4d89a141f7d69f1894ec3059ba6bd1cf86b (from b296cd9b8f63ab80e8fe46fcfcdba2e9af846468)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 13:13:25 2007 -0800

    Partially deal with cursor rotation.
    
    The remaining issue is having a cursor image per CRTC so that the cursors can
    be rotated on the independently rotated CRTCs.

diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 5e7a21a..364320e 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -456,49 +456,50 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     I830Ptr pI830 = I830PTR(pScrn);
     CARD32 temp;
     Bool inrange;
-    int oldx = x, oldy = y;
-    int hotspotx = 0, hotspoty = 0;
+    int root_x = x, root_y = y;
     int pipe;
 
-    oldx += pScrn->frameX0; /* undo what xf86HWCurs did */
-    oldy += pScrn->frameY0;
-
-    switch (pI830->rotation) {
-    case RR_Rotate_0:
-	x = oldx;
-	y = oldy;
-	break;
-    case RR_Rotate_90:
-	x = oldy;
-	y = pScrn->pScreen->width - oldx;
-	hotspoty = I810_CURSOR_X;
-	break;
-    case RR_Rotate_180:
-	x = pScrn->pScreen->width - oldx;
-	y = pScrn->pScreen->height - oldy;
-	hotspotx = I810_CURSOR_X;
-	hotspoty = I810_CURSOR_Y;
-	break;
-    case RR_Rotate_270:
-	x = pScrn->pScreen->height - oldy;
-	y = oldx;
-	hotspotx = I810_CURSOR_Y;
-	break;
-    }
-
-    x -= hotspotx;
-    y -= hotspoty;
+    root_x = x + pScrn->frameX0; /* undo what xf86HWCurs did */
+    root_y = y + pScrn->frameY0;
 
     for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
     {
-	xf86CrtcPtr    crtc = xf86_config->crtc[pipe];
+	xf86CrtcPtr	    crtc = xf86_config->crtc[pipe];
 	DisplayModePtr	    mode = &crtc->mode;
-	int		    thisx = x - crtc->x;
-	int		    thisy = y - crtc->y;
+	int		    thisx;
+	int		    thisy;
+	int hotspotx = 0, hotspoty = 0;
 
 	if (!crtc->enabled)
 	    continue;
 
+	/* XXX: deal with hotspot issues */
+	switch (crtc->rotation) {
+	case RR_Rotate_0:
+	    thisx = (root_x - crtc->x);
+	    thisy = (root_y - crtc->y);
+	    break;
+	case RR_Rotate_90:
+	    thisx = (root_y - crtc->y);
+	    thisy = mode->VDisplay - (root_x - crtc->x);
+	    /*hotspoty = I810_CURSOR_X;*/
+	    break;
+	case RR_Rotate_180:
+	    thisx = mode->HDisplay - (root_x - crtc->x);
+	    thisy = mode->VDisplay - (root_y - crtc->y);
+	    /*hotspotx = I810_CURSOR_X;
+	      hotspoty = I810_CURSOR_Y;*/
+	    break;
+	case RR_Rotate_270:
+	    thisx = mode->VDisplay - (root_y - crtc->y);
+	    thisy = (root_x - crtc->x);
+	    /*hotspotx = I810_CURSOR_Y;*/
+	    break;
+	}
+
+	thisx -= hotspotx;
+	thisy -= hotspoty;
+
 	/*
 	 * There is a screen display problem when the cursor position is set
 	 * wholely outside of the viewport.  We trap that here, turning the
diff-tree b296cd9b8f63ab80e8fe46fcfcdba2e9af846468 (from d2ae2e2ccc3a8e7dc84745c235836cba150754d8)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 13:02:26 2007 -0800

    Fix transformation matrices for rotation at 90 and 270 degrees.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 670ad7a..8da79b6 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -144,23 +144,20 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	transform.matrix[1][1] = IntToxFixed(1);
 	break;
     case RR_Rotate_90:
-	/* XXX probably wrong */
-	transform.matrix[0][1] = IntToxFixed(1);
-	transform.matrix[1][0] = IntToxFixed(-1);
-	transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
+	transform.matrix[0][1] = IntToxFixed(-1);
+	transform.matrix[1][0] = IntToxFixed(1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     case RR_Rotate_180:
-	/* XXX probably wrong */
 	transform.matrix[0][0] = IntToxFixed(-1);
 	transform.matrix[1][1] = IntToxFixed(-1);
 	transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay);
 	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     case RR_Rotate_270:
-	/* XXX probably wrong */
-	transform.matrix[0][1] = IntToxFixed(-1);
-	transform.matrix[1][0] = IntToxFixed(1);
-	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
+	transform.matrix[0][1] = IntToxFixed(1);
+	transform.matrix[1][0] = IntToxFixed(-1);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     }
 
diff-tree d2ae2e2ccc3a8e7dc84745c235836cba150754d8 (from 92b0f3d2013c32d94fe57fe674da1b195288f347)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:37:14 2007 -0800

    Update CRTC values first so they can be used by the driver in mode setting.
    
    With this, the screen now gets rotated, though there are major issues.

diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index a926e9f..c879d99 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -154,6 +154,9 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
     Bool		ret = FALSE;
     Bool		didLock = FALSE;
     DisplayModePtr	adjusted_mode;
+    DisplayModeRec	saved_mode;
+    int			saved_x, saved_y;
+    Rotation		saved_rotation;
 
     adjusted_mode = xf86DuplicateMode(mode);
 
@@ -167,6 +170,18 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 
     didLock = crtc->funcs->lock (crtc);
 
+    saved_mode = crtc->mode;
+    saved_x = crtc->x;
+    saved_y = crtc->y;
+    saved_rotation = crtc->rotation;
+    /* Update crtc values up front so the driver can rely on them for mode
+     * setting.
+     */
+    crtc->mode = *mode;
+    crtc->x = x;
+    crtc->y = y;
+    crtc->rotation = rotation;
+
     /* XXX short-circuit changes to base location only */
     
     /* Pass our mode to the outputs and the CRTC to give them a chance to
@@ -180,18 +195,15 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    continue;
 
 	if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
-	    ret = FALSE;
 	    goto done;
 	}
     }
 
     if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
-	ret = FALSE;
 	goto done;
     }
 
     if (!xf86CrtcRotate (crtc, mode, rotation)) {
-	ret = FALSE;
 	goto done;
     }
 
@@ -228,14 +240,16 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    output->funcs->dpms(output, DPMSModeOn);
     }
 
-    crtc->mode = *mode;
-    crtc->x = x;
-    crtc->y = y;
-    crtc->rotation = rotation;
-
     /* XXX free adjustedmode */
     ret = TRUE;
 done:
+    if (!ret) {
+	crtc->x = saved_x;
+	crtc->y = saved_y;
+	crtc->rotation = saved_rotation;
+	crtc->mode = saved_mode;
+    }
+
     if (didLock)
 	crtc->funcs->unlock (crtc);
 
diff-tree 92b0f3d2013c32d94fe57fe674da1b195288f347 (from 14d265a02312e9cda7a21614d77525c7140c0ca8)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:23:22 2007 -0800

    Disable the clipping for now, since it won't work.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 39733fd..670ad7a 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -127,7 +127,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	ErrorF("couldn't create src pict\n");
 	return;
     }
-    SetPictureClipRegion (src, 0, 0, region);
+    /* Unfortunately, we don't do clipping on transformed source pictures.
+     * So we can't use this.  Instead, we'll just repaint the whole screen
+     * for now, and do transform of the source region into a dest region
+     * later.
+     */
+    /* SetPictureClipRegion (src, 0, 0, region); */
+
     memset (&transform, '\0', sizeof (transform));
     transform.matrix[2][2] = IntToxFixed(1);
     transform.matrix[0][2] = IntToxFixed(crtc->x);
diff-tree 14d265a02312e9cda7a21614d77525c7140c0ca8 (from cc09dc3efe7279bf67512babb0f6cdaeba654772)
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 11:21:58 2007 -0800

    Store fixed values, not integers, in the transformation matrix.
    
    Also, add a bit more error checking.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 14c0c5d..39733fd 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -112,8 +112,10 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 			 NULL,
 			 serverClient,
 			 &error);
-    if (!src)
+    if (!src) {
+	ErrorF("couldn't create src pict\n");
 	return;
+    }
     dst = CreatePicture (None,
 			 &dst_pixmap->drawable,
 			 format,
@@ -121,38 +123,41 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 			 NULL,
 			 serverClient,
 			 &error);
-    if (!dst)
+    if (!dst) {
+	ErrorF("couldn't create src pict\n");
 	return;
+    }
     SetPictureClipRegion (src, 0, 0, region);
     memset (&transform, '\0', sizeof (transform));
-    transform.matrix[2][2] = 1;
-    transform.matrix[0][2] = crtc->x;
-    transform.matrix[1][2] = crtc->y;
+    transform.matrix[2][2] = IntToxFixed(1);
+    transform.matrix[0][2] = IntToxFixed(crtc->x);
+    transform.matrix[1][2] = IntToxFixed(crtc->y);
     switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
-	transform.matrix[0][0] = 1;
-	transform.matrix[1][1] = 1;
+	transform.matrix[0][0] = IntToxFixed(1);
+	transform.matrix[1][1] = IntToxFixed(1);
 	break;
     case RR_Rotate_90:
 	/* XXX probably wrong */
-	transform.matrix[0][1] = 1;
-	transform.matrix[1][0] = -1;
-	transform.matrix[1][2] += crtc->mode.HDisplay;
+	transform.matrix[0][1] = IntToxFixed(1);
+	transform.matrix[1][0] = IntToxFixed(-1);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
 	break;
     case RR_Rotate_180:
 	/* XXX probably wrong */
-	transform.matrix[0][0] = -1;
-	transform.matrix[1][1] = -1;
-	transform.matrix[0][2] += crtc->mode.HDisplay;
-	transform.matrix[1][2] += crtc->mode.VDisplay;
+	transform.matrix[0][0] = IntToxFixed(-1);
+	transform.matrix[1][1] = IntToxFixed(-1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.HDisplay);
+	transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     case RR_Rotate_270:
 	/* XXX probably wrong */
-	transform.matrix[0][1] = -1;
-	transform.matrix[1][0] = 1;
-	transform.matrix[0][2] += crtc->mode.VDisplay;
+	transform.matrix[0][1] = IntToxFixed(-1);
+	transform.matrix[1][0] = IntToxFixed(1);
+	transform.matrix[0][2] += IntToxFixed(crtc->mode.VDisplay);
 	break;
     }
+
     /* handle reflection */
     if (crtc->rotation & RR_Reflect_X)
     {
@@ -162,7 +167,13 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     {
 	/* XXX figure this out too */
     }
-    SetPictureTransform (src, &transform);
+
+    error = SetPictureTransform (src, &transform);
+    if (error) {
+	ErrorF("Couldn't set transform\n");
+	return;
+    }
+
     CompositePicture (PictOpSrc,
 		      src, NULL, dst,
 		      0, 0, 0, 0, 0, 0,
diff-tree cc09dc3efe7279bf67512babb0f6cdaeba654772 (from parents)
Merge: 53e765d1cf5016961c25a798a27f0fe09bd1f237 3094100cdd04560af1b098bbe8024ae5270a10f4
Author: Eric Anholt <eric at anholt.net>
Date:   Thu Jan 18 10:20:36 2007 -0800

    Merge branch 'modesetting' into modesetting-rotation

diff-tree 53e765d1cf5016961c25a798a27f0fe09bd1f237 (from f256243fff195f73bc8aa72e8dd2c6f7b33446cf)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 16:56:06 2007 -0800

    Fix broken last-minute change in determining whether we're rotated or not.

diff --git a/src/i830_display.c b/src/i830_display.c
index 08842ec..2313f76 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -342,7 +342,7 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (intel_crtc->rotate_mem.Start != 0) {
+    if (crtc->rotation != RR_Rotate_0) {
 	Start = intel_crtc->rotate_mem.Start;
     } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->FrontBuffer.Start;
diff-tree f256243fff195f73bc8aa72e8dd2c6f7b33446cf (from d17c386aee55bd223297adf78cf0fc1db43baf2d)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 16:01:18 2007 -0800

    Allocate per-crtc rotation buffers and hook up RandR 1.2 per-CRTC rotation.
    
    It currently displays garbage.

diff --git a/src/i830.h b/src/i830.h
index 66dad9b..c792073 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -195,8 +195,11 @@ extern const char *i830_output_type_name
 
 typedef struct _I830CrtcPrivateRec {
     int			    pipe;
+
     /* Lookup table values to be set when the CRTC is enabled */
     CARD8 lut_r[256], lut_g[256], lut_b[256];
+
+    I830MemRange rotate_mem;
 } I830CrtcPrivateRec, *I830CrtcPrivatePtr;
 
 #define I830CrtcPrivate(c) ((I830CrtcPrivatePtr) (c)->driver_private)
diff --git a/src/i830_display.c b/src/i830_display.c
index de6c722..08842ec 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -342,9 +342,11 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
     int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
 
-    if (I830IsPrimary(pScrn))
+    if (intel_crtc->rotate_mem.Start != 0) {
+	Start = intel_crtc->rotate_mem.Start;
+    } else if (I830IsPrimary(pScrn)) {
 	Start = pI830->FrontBuffer.Start;
-    else {
+    } else {
 	I830Ptr pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
 	Start = pI8301->FrontBuffer2.Start;
     }
@@ -883,6 +885,45 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CA
 }
 
 /**
+ * Creates a locked-in-framebuffer pixmap of the given width and height for
+ * this CRTC's rotated shadow framebuffer.
+ *
+ * The current implementation uses fixed buffers allocated at startup at the
+ * maximal size.
+ */
+static PixmapPtr
+i830_crtc_shadow_create(xf86CrtcPtr crtc, int width, int height)
+{
+    ScrnInfoPtr pScrn = crtc->scrn;
+    I830Ptr pI830 = I830PTR(pScrn);
+    I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+    unsigned long rotate_pitch;
+    PixmapPtr rotate_pixmap;
+    pointer rotate_offset;
+
+    if (intel_crtc->rotate_mem.Start == 0)
+	return NULL;
+
+    rotate_pitch = pI830->displayWidth * pI830->cpp;
+    rotate_offset = pI830->FbBase + intel_crtc->rotate_mem.Start;
+
+    rotate_pixmap = GetScratchPixmapHeader(pScrn->pScreen,
+					   width, height,
+					   pScrn->depth,
+					   pScrn->bitsPerPixel,
+					   rotate_pitch,
+					   rotate_offset);
+    return rotate_pixmap;
+}
+
+static void
+i830_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap)
+{
+    FreeScratchPixmapHeader(rotate_pixmap);
+}
+
+
+/**
  * This function configures the screens in clone mode on
  * all active outputs using a mode similar to the specified mode.
  */
@@ -1038,6 +1079,8 @@ static const xf86CrtcFuncsRec i830_crtc_
     .mode_fixup = i830_crtc_mode_fixup,
     .mode_set = i830_crtc_mode_set,
     .gamma_set = i830_crtc_gamma_set,
+    .shadow_create = i830_crtc_shadow_create,
+    .shadow_destroy = i830_crtc_shadow_destroy,
     .destroy = NULL, /* XXX */
 };
 
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 426242a..ae14c06 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -769,6 +769,63 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
    return TRUE;
 }
 
+/**
+ * Allocates memory for the rotated shadow buffers.
+ *
+ * This memory would be better allocated normally through the linear allocator,
+ * but it gets rotation working for now.
+ */
+static Bool
+I830AllocateRotateBuffers(xf86CrtcPtr crtc, const int flags)
+{
+   ScrnInfoPtr pScrn = crtc->scrn;
+   I830CrtcPrivatePtr intel_crtc = crtc->driver_private;
+   I830Ptr pI830 = I830PTR(pScrn);
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   unsigned long avail, lineSize;
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   int align, alignflags;
+   long size, alloced;
+   int rotate_width, rotate_height;
+
+   memset(&intel_crtc->rotate_mem, 0, sizeof(intel_crtc->rotate_mem));
+
+   rotate_width = pScrn->displayWidth;
+   if (pScrn->virtualX > pScrn->virtualY)
+      rotate_height = pScrn->virtualX;
+   else
+      rotate_height = pScrn->virtualY;
+
+   lineSize = pScrn->displayWidth * pI830->cpp;
+   avail = pScrn->videoRam * 1024;
+
+   align = KB(64);
+   alignflags = 0;
+
+   size = lineSize * rotate_height;
+   size = ROUND_TO_PAGE(size);
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sInitial %sshadow framebuffer allocation size: "
+		  "%ld kByte\n",
+		  s, (intel_crtc->pipe == 0) ? "" : "secondary ",
+		  size / 1024);
+   alloced = I830AllocVidMem(pScrn, &intel_crtc->rotate_mem,
+			     &pI830->StolenPool, size, align,
+			     flags | alignflags |
+			     FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
+		    "%sshadow framebuffer. Is your VideoRAM set too low?\n",
+		    (intel_crtc->pipe == 0) ? "" : "secondary ");
+      }
+      return FALSE;
+   }
+
+   return TRUE;
+}
+
 /*
  * Allocate memory for 2D operation.  This includes the (front) framebuffer,
  * ring buffer, scratch memory, HW cursor.
@@ -782,7 +839,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
    int verbosity = dryrun ? 4 : 1;
    const char *s = dryrun ? "[dryrun] " : "";
    Bool tileable;
-   int align, alignflags;
+   int align, alignflags, i;
 
    DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
 	   BOOLTOSTRING(flags & ALLOC_INITIAL));
@@ -814,6 +871,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	   pI830->StolenPool.Free.Size);
 
    if (flags & ALLOC_INITIAL) {
+      xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
 
       if (pI830->NeedRingBufferLow)
 	 AllocateRingBuffer(pScrn, flags | FORCE_LOW);
@@ -839,6 +897,10 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 return FALSE;
       }
 
+      for (i = 0; i < xf86_config->num_crtc; i++) {
+	 I830AllocateRotateBuffers(xf86_config->crtc[i], flags);
+      }
+
 #ifdef I830_USE_EXA
       if (pI830->useEXA) {
 	 /* Default EXA to having 3 screens worth of offscreen memory space
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 504ea0b..a926e9f 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -190,13 +190,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	goto done;
     }
 
-#if 0
-    if (!xf86CrtcRotate (crtc, mode, rotation))
-    {
+    if (!xf86CrtcRotate (crtc, mode, rotation)) {
 	ret = FALSE;
 	goto done;
     }
-#endif
 
     /* Disable the outputs and CRTCs before setting the mode. */
     for (i = 0; i < xf86_config->num_output; i++) {
diff-tree d17c386aee55bd223297adf78cf0fc1db43baf2d (from 67a152c43cb7231695b99030c952c52d4edd1e65)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 15:49:08 2007 -0800

    Fix some segfaults: crtc->rotatedPixmap not set and dangling damage pointer.

diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 5482a6e..14c0c5d 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -247,6 +247,8 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	if (xf86_config->rotationDamage)
 	{
 	    /* Free damage structure */
+	    DamageUnregister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+			      xf86_config->rotationDamage);
 	    DamageDestroy (xf86_config->rotationDamage);
 	    xf86_config->rotationDamage = NULL;
 	    /* Free block/wakeup handler */
@@ -274,6 +276,7 @@ xf86CrtcRotate (xf86CrtcPtr crtc, Displa
 	    shadow = crtc->funcs->shadow_create (crtc, width, height);
 	    if (!shadow)
 		goto bail1;
+	    crtc->rotatedPixmap = shadow;
 	}
 	
 	if (!xf86_config->rotationDamage)
diff-tree 67a152c43cb7231695b99030c952c52d4edd1e65 (from a52df90ffcb19e7c0a3b8018db3cd1391a3ec343)
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jan 17 14:35:31 2007 -0800

    Set all CRTCs' allowable rotations when xf86RandR12SetRotations() is called.

diff --git a/src/i830_randr.c b/src/i830_randr.c
index 3aaf88b..c1e9ac0 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -494,8 +494,19 @@ void
 xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
 {
     XF86RandRInfoPtr	randrp = XF86RANDRINFO(pScreen);
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			c;
 
     randrp->supported_rotations = rotations;
+
+#if RANDR_12_INTERFACE
+    for (c = 0; c < config->num_crtc; c++) {
+	xf86CrtcPtr    crtc = config->crtc[c];
+
+	RRCrtcSetRotations (crtc->randr_crtc, rotations);
+    }
+#endif
 }
 
 void
diff-tree a52df90ffcb19e7c0a3b8018db3cd1391a3ec343 (from parents)
Merge: 37946c9c8a4afa4a4fc1fe9864a8eec1c4571d2c 45696aa29124e2852f94880642e70bb2e0cee827
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Jan 16 12:20:26 2007 +1100

    Merge branch 'modesetting' into modesetting-rotation
    
    Conflicts:
    
    	src/i830_driver.c
    	src/i830_randr.c
    
    Just a few sync changes.

diff --cc src/i830_driver.c
index 56a599c,20781aa..84fd9d8
@@@ -3016,14 -3015,8 +3015,10 @@@
     if (crtc && crtc->enabled)
     {
        /* Sync the engine before adjust frame */
-       if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
- 	 (*pI830->AccelInfoRec->Sync)(pScrn);
- 	 pI830->AccelInfoRec->NeedToSync = FALSE;
-       }
-       /* XXX should have xf86-based frame adjuster */
+       i830WaitSync(pScrn);
        i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
 +      crtc->x = output->initial_x + x;
 +      crtc->y = output->initial_y + y;
     }
  }
  
diff-tree 37946c9c8a4afa4a4fc1fe9864a8eec1c4571d2c (from bfeda3bfc59d309772398f688d29452ba97f3973)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Tue Jan 16 12:14:55 2007 +1100

    Interim work on rotation support with new xf86 code.
    
    Yes, there are lots of bits tied together here, and we should split this
    patch apart.
    
    Move I830 mode setting to xf86 mode setting.
    
    Make mode setting function also set the base address. This should fix
    problems where the base gets set incorrectly at times.
    
    Add driver-independent rotation support, requires driver-specific hooks for
    shadow pixmap allocation, otherwise it uses Render for painting.

diff --git a/src/i830.h b/src/i830.h
index 95bea2f..66dad9b 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -221,6 +221,7 @@ enum last_3d {
     LAST_3D_ROTATION
 };
 
+#if 0
 typedef struct _I830PipeRec {
    Bool		  enabled;
    int		  x;
@@ -233,6 +234,7 @@ typedef struct _I830PipeRec {
    RRCrtcPtr	  randr_crtc;
 #endif
 } I830PipeRec, *I830PipePtr;
+#endif
 
 typedef struct _I830Rec {
    unsigned char *MMIOBase;
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 00e637a..573e652 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -314,7 +314,7 @@ i830_crt_detect(xf86OutputPtr output)
 	if (intel_output->load_detect_temp)
 	{
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
 	}
 	connected = i830_crt_detect_load (crtc, output);
 
diff --git a/src/i830_cursor.c b/src/i830_cursor.c
index 81cb3bd..5e7a21a 100644
--- a/src/i830_cursor.c
+++ b/src/i830_cursor.c
@@ -492,7 +492,7 @@ I830SetCursorPosition(ScrnInfoPtr pScrn,
     for (pipe = 0; pipe < xf86_config->num_crtc; pipe++)
     {
 	xf86CrtcPtr    crtc = xf86_config->crtc[pipe];
-	DisplayModePtr	    mode = &crtc->curMode;
+	DisplayModePtr	    mode = &crtc->mode;
 	int		    thisx = x - crtc->x;
 	int		    thisy = y - crtc->y;
 
diff --git a/src/i830_display.c b/src/i830_display.c
index d80eb4e..de6c722 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -358,9 +358,6 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 	(void) INREG(dspbase);
     }
-
-    crtc->x = x;
-    crtc->y = y;
 }
 
 /**
@@ -601,7 +598,8 @@ i830_crtc_mode_fixup(xf86CrtcPtr crtc, D
  */
 static void
 i830_crtc_mode_set(xf86CrtcPtr crtc, DisplayModePtr mode,
-		   DisplayModePtr adjusted_mode)
+		   DisplayModePtr adjusted_mode,
+		   int x, int y)
 {
     ScrnInfoPtr pScrn = crtc->scrn;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -837,7 +835,7 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     
     OUTREG(dspcntr_reg, dspcntr);
     /* Flush the plane changes */
-    i830PipeSetBase(crtc, crtc->x, crtc->y);
+    i830PipeSetBase(crtc, x, y);
     
     i830WaitForVblank(pScrn);
 }
@@ -901,7 +899,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
     {
 	ok = xf86CrtcSetMode(crtc,
 			     i830PipeFindClosestMode(crtc, pMode),
-			     rotation);
+			     rotation, 0, 0);
 	if (!ok)
 	    goto done;
 	crtc->desiredMode = *pMode;
diff --git a/src/i830_driver.c b/src/i830_driver.c
index daa5a3b..56a599c 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3020,7 +3020,10 @@ i830AdjustFrame(int scrnIndex, int x, in
 	 (*pI830->AccelInfoRec->Sync)(pScrn);
 	 pI830->AccelInfoRec->NeedToSync = FALSE;
       }
+      /* XXX should have xf86-based frame adjuster */
       i830PipeSetBase(crtc, output->initial_x + x, output->initial_y + y);
+      crtc->x = output->initial_x + x;
+      crtc->y = output->initial_y + y;
    }
 }
 
@@ -3138,14 +3141,17 @@ I830EnterVT(int scrnIndex, int flags)
       xf86CrtcPtr	crtc = xf86_config->crtc[i];
 
       /* Mark that we'll need to re-set the mode for sure */
-      memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+      memset(&crtc->mode, 0, sizeof(crtc->mode));
       if (!crtc->desiredMode.CrtcHDisplay)
       {
 	 crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode);
 	 crtc->desiredRotation = RR_Rotate_0;
+	 crtc->desiredX = 0;
+	 crtc->desiredY = 0;
       }
       
-      if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation))
+      if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation,
+			    crtc->desiredX, crtc->desiredY))
 	 return FALSE;
    }
 
diff --git a/src/i830_randr.c b/src/i830_randr.c
index d6df419..3aaf88b 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -393,8 +393,8 @@ xf86RandR12CreateScreenResources (Screen
     for (c = 0; c < config->num_crtc; c++)
     {
 	xf86CrtcPtr crtc = config->crtc[c];
-	int	    crtc_width = crtc->x + crtc->curMode.HDisplay;
-	int	    crtc_height = crtc->y + crtc->curMode.VDisplay;
+	int	    crtc_width = crtc->x + crtc->mode.HDisplay;
+	int	    crtc_height = crtc->y + crtc->mode.VDisplay;
 	
 	if (crtc->enabled && crtc_width > width)
 	    width = crtc_width;
@@ -533,7 +533,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     xf86OutputPtr	output;
     int			i, j;
-    DisplayModePtr	curMode = &crtc->curMode;
+    DisplayModePtr	mode = &crtc->mode;
     Bool		ret;
 
     randr_outputs = ALLOCATE_LOCAL(config->num_output * sizeof (RROutputPtr));
@@ -541,7 +541,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	return FALSE;
     x = crtc->x;
     y = crtc->y;
-    rotation = crtc->curRotation;
+    rotation = crtc->rotation;
     numOutputs = 0;
     randr_mode = NULL;
     for (i = 0; i < config->num_output; i++)
@@ -558,7 +558,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	    for (j = 0; j < randr_output->numModes; j++)
 	    {
 		DisplayModePtr	outMode = randr_output->modes[j]->devPrivate;
-		if (xf86ModesEqual(curMode, outMode))
+		if (xf86ModesEqual(mode, outMode))
 		{
 		    randr_mode = randr_output->modes[j];
 		    break;
@@ -587,7 +587,6 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     xf86CrtcPtr		crtc = randr_crtc->devPrivate;
     DisplayModePtr	mode = randr_mode ? randr_mode->devPrivate : NULL;
     Bool		changed = FALSE;
-    Bool		pos_changed;
     int			o, ro;
     xf86CrtcPtr		*save_crtcs;
     Bool		save_enabled = crtc->enabled;
@@ -595,12 +594,11 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     save_crtcs = ALLOCATE_LOCAL(config->num_crtc * sizeof (xf86CrtcPtr));
     if ((mode != NULL) != crtc->enabled)
 	changed = TRUE;
-    else if (mode && !xf86ModesEqual (&crtc->curMode, mode))
+    else if (mode && !xf86ModesEqual (&crtc->mode, mode))
 	changed = TRUE;
     
-    pos_changed = changed;
     if (x != crtc->x || y != crtc->y)
-	pos_changed = TRUE;
+	changed = TRUE;
     for (o = 0; o < config->num_output; o++) 
     {
 	xf86OutputPtr  output = config->output[o];
@@ -627,18 +625,11 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
     /* XXX need device-independent mode setting code through an API */
     if (changed)
     {
-	I830Ptr pI830 = I830PTR(pScrn);
 	crtc->enabled = mode != NULL;
 
-	/* Sync the engine before adjust mode */
-	if (pI830->AccelInfoRec && pI830->AccelInfoRec->NeedToSync) {
-	    (*pI830->AccelInfoRec->Sync)(pScrn);
-	    pI830->AccelInfoRec->NeedToSync = FALSE;
-	}
-
 	if (mode)
 	{
-	    if (!xf86CrtcSetMode (crtc, mode, rotation))
+	    if (!xf86CrtcSetMode (crtc, mode, rotation, x, y))
 	    {
 		crtc->enabled = save_enabled;
 		for (o = 0; o < config->num_output; o++)
@@ -649,14 +640,16 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 		DEALLOCATE_LOCAL(save_crtcs);
 		return FALSE;
 	    }
+	    /*
+	     * Save the last successful setting for EnterVT
+	     */
 	    crtc->desiredMode = *mode;
+	    crtc->desiredRotation = rotation;
+	    crtc->desiredX = x;
+	    crtc->desiredY = y;
 	}
 	xf86DisableUnusedFunctions (pScrn);
-
-	i830DumpRegs(pScrn);
     }
-    if (pos_changed && mode)
-	i830PipeSetBase(crtc, x, y);
     DEALLOCATE_LOCAL(save_crtcs);
     return xf86RandR12CrtcNotify (randr_crtc);
 }
@@ -817,6 +810,8 @@ xf86RandR12SetInfo12 (ScreenPtr pScreen)
     return TRUE;
 }
 
+
+
 /*
  * Query the hardware for the current state, then mirror
  * that to RandR
diff --git a/src/i830_tv.c b/src/i830_tv.c
index a76cbff..79b6ae8 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1065,7 +1065,7 @@ i830_tv_detect(xf86OutputPtr output)
 	    /* we only need the pixel clock set correctly here */
 	    mode = reported_modes[0];
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0, 0, 0);
 	}
 	i830_tv_detect_type (crtc, output);
 	i830ReleaseLoadDetectPipe (output);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index 5eb55e9..504ea0b 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -87,7 +87,7 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 #ifdef RANDR_12_INTERFACE
     crtc->randr_crtc = NULL;
 #endif
-    crtc->curRotation = RR_Rotate_0;
+    crtc->rotation = RR_Rotate_0;
     crtc->desiredRotation = RR_Rotate_0;
     if (xf86_config->crtc)
 	crtcs = xrealloc (xf86_config->crtc,
@@ -145,7 +145,8 @@ xf86CrtcInUse (xf86CrtcPtr crtc)
  * Sets the given video mode on the given crtc
  */
 Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+		 int x, int y)
 {
     ScrnInfoPtr		scrn = crtc->scrn;
     xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -166,6 +167,8 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 
     didLock = crtc->funcs->lock (crtc);
 
+    /* XXX short-circuit changes to base location only */
+    
     /* Pass our mode to the outputs and the CRTC to give them a chance to
      * adjust it according to limitations or output properties, and also
      * a chance to reject the mode entirely.
@@ -211,7 +214,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
     /* Set up the DPLL and any output state that needs to adjust or depend
      * on the DPLL.
      */
-    crtc->funcs->mode_set(crtc, mode, adjusted_mode);
+    crtc->funcs->mode_set(crtc, mode, adjusted_mode, x, y);
     for (i = 0; i < xf86_config->num_output; i++) 
     {
 	xf86OutputPtr output = xf86_config->output[i];
@@ -228,7 +231,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, Displ
 	    output->funcs->dpms(output, DPMSModeOn);
     }
 
-    crtc->curMode = *mode;
+    crtc->mode = *mode;
+    crtc->x = x;
+    crtc->y = y;
+    crtc->rotation = rotation;
 
     /* XXX free adjustedmode */
     ret = TRUE;
@@ -1401,7 +1407,7 @@ xf86DisableUnusedFunctions(ScrnInfoPtr p
 	if (!crtc->enabled) 
 	{
 	    crtc->funcs->dpms(crtc, DPMSModeOff);
-	    memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+	    memset(&crtc->mode, 0, sizeof(crtc->mode));
 	}
     }
 }
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index e72dda6..4b17dce 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -70,7 +70,6 @@ typedef struct _xf86CrtcFuncs {
    void
     (*restore)(xf86CrtcPtr	crtc);
 
-
     /**
      * Lock CRTC prior to mode setting, mostly for DRI.
      * Returns whether unlock is needed
@@ -102,7 +101,8 @@ typedef struct _xf86CrtcFuncs {
     void
     (*mode_set)(xf86CrtcPtr crtc,
 		DisplayModePtr mode,
-		DisplayModePtr adjusted_mode);
+		DisplayModePtr adjusted_mode,
+		int x, int y);
 
     /* Set the color ramps for the CRTC to the given values. */
     void
@@ -141,13 +141,6 @@ struct _xf86Crtc {
      */
     Bool	    enabled;
     
-    /**
-     * Position on screen
-     *
-     * Locates this CRTC within the frame buffer
-     */
-    int		    x, y;
-    
     /** Track whether cursor is within CRTC range  */
     Bool	    cursorInRange;
     
@@ -161,9 +154,15 @@ struct _xf86Crtc {
      * It will be cleared when the VT is not active or
      * during server startup
      */
-    DisplayModeRec  curMode;
-    Rotation	    curRotation;
+    DisplayModeRec  mode;
+    Rotation	    rotation;
     PixmapPtr	    rotatedPixmap;
+    /**
+     * Position on screen
+     *
+     * Locates this CRTC within the frame buffer
+     */
+    int		    x, y;
     
     /**
      * Desired mode
@@ -175,6 +174,7 @@ struct _xf86Crtc {
      */
     DisplayModeRec  desiredMode;
     Rotation	    desiredRotation;
+    int		    desiredX, desiredY;
     
     /** crtc-specific functions */
     const xf86CrtcFuncsRec *funcs;
@@ -396,6 +396,10 @@ typedef struct _xf86CrtcConfig {
     
     /* For crtc-based rotation */
     DamagePtr   rotationDamage;
+
+    /* DGA */
+    unsigned int dga_flags;
+
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern int xf86CrtcConfigPrivateIndex;
@@ -448,7 +452,8 @@ xf86FreeCrtc (xf86CrtcPtr		crtc);
  * Sets the given video mode on the given crtc
  */
 Bool
-xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
+		 int x, int y);
 
 /*
  * Assign crtc rotation during mode set
diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
index 12b2091..5482a6e 100644
--- a/src/i830_xf86Rotate.c
+++ b/src/i830_xf86Rotate.c
@@ -128,7 +128,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
     transform.matrix[2][2] = 1;
     transform.matrix[0][2] = crtc->x;
     transform.matrix[1][2] = crtc->y;
-    switch (crtc->curRotation & 0xf) {
+    switch (crtc->rotation & 0xf) {
     case RR_Rotate_0:
 	transform.matrix[0][0] = 1;
 	transform.matrix[1][1] = 1;
@@ -137,28 +137,28 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crt
 	/* XXX probably wrong */
 	transform.matrix[0][1] = 1;
 	transform.matrix[1][0] = -1;
-	transform.matrix[1][2] += crtc->curMode.HDisplay;
+	transform.matrix[1][2] += crtc->mode.HDisplay;
 	break;
     case RR_Rotate_180:
 	/* XXX probably wrong */
 	transform.matrix[0][0] = -1;
 	transform.matrix[1][1] = -1;
-	transform.matrix[0][2] += crtc->curMode.HDisplay;
-	transform.matrix[1][2] += crtc->curMode.VDisplay;
+	transform.matrix[0][2] += crtc->mode.HDisplay;
+	transform.matrix[1][2] += crtc->mode.VDisplay;
 	break;
     case RR_Rotate_270:
 	/* XXX probably wrong */
 	transform.matrix[0][1] = -1;
 	transform.matrix[1][0] = 1;
-	transform.matrix[0][2] += crtc->curMode.VDisplay;
+	transform.matrix[0][2] += crtc->mode.VDisplay;
 	break;
     }
     /* handle reflection */
-    if (crtc->curRotation & RR_Reflect_X)
+    if (crtc->rotation & RR_Reflect_X)
     {
 	/* XXX figure this out */
     }
-    if (crtc->curRotation & RR_Reflect_Y)
+    if (crtc->rotation & RR_Reflect_Y)
     {
 	/* XXX figure this out too */
     }
@@ -191,16 +191,16 @@ xf86RotateRedisplay(ScreenPtr pScreen)
 	{
 	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];
 
-	    if (crtc->curRotation != RR_Rotate_0)
+	    if (crtc->rotation != RR_Rotate_0)
 	    {
 		BoxRec	    box;
 		RegionRec   crtc_damage;
 
 		/* compute portion of damage that overlaps crtc */
 		box.x1 = crtc->x;
-		box.x2 = crtc->x + mode_width (&crtc->curMode, crtc->curRotation);
+		box.x2 = crtc->x + mode_width (&crtc->mode, crtc->rotation);
 		box.y1 = crtc->y;
-		box.y2 = crtc->y + mode_height (&crtc->curMode, crtc->curRotation);
+		box.y2 = crtc->y + mode_height (&crtc->mode, crtc->rotation);
 		REGION_INIT(pScreen, &crtc_damage, &box, 1);
 		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
 		
@@ -319,6 +319,5 @@ bail1:
     }
     
     /* All done */
-    crtc->curRotation = rotation;
     return TRUE;
 }
diff-tree bfeda3bfc59d309772398f688d29452ba97f3973 (from da6a00f787e4d13e6b75768c1976f1c44ae5bf72)
Author: Keith Packard <keithp at neko.keithp.com>
Date:   Mon Jan 15 08:05:32 2007 +1100

    Convert I830PipeSetMode to xf86CrtcSetMode. Add rotation structures.
    
    Makes the mode setting logic device independent.
    Magic rename hooks allow multiple drivers to provide the
    generic code without name conflicts.
    Rotation code requires special pixmap creation hook, and uses
    Render to perform the actual rotation.

diff --git a/src/Makefile.am b/src/Makefile.am
index 80cea10..02e8576 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -85,6 +85,7 @@ i810_drv_la_SOURCES = \
 	 i830_xf86cvt.c \
 	 i830_xf86Crtc.h \
 	 i830_xf86Crtc.c \
+	 i830_xf86Rotate.c \
 	 i915_3d.c \
 	 i915_3d.h \
 	 i915_reg.h \
diff --git a/src/i830_crt.c b/src/i830_crt.c
index 4e9e370..00e637a 100644
--- a/src/i830_crt.c
+++ b/src/i830_crt.c
@@ -314,7 +314,7 @@ i830_crt_detect(xf86OutputPtr output)
 	if (intel_output->load_detect_temp)
 	{
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    i830PipeSetMode (crtc, &mode, FALSE);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
 	}
 	connected = i830_crt_detect_load (crtc, output);
 
diff --git a/src/i830_display.c b/src/i830_display.c
index f47a9db..d80eb4e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -465,23 +465,6 @@ i830PipeFindClosestMode(xf86CrtcPtr crtc
 }
 
 /**
- * Return whether any outputs are connected to the specified pipe
- */
-
-Bool
-i830PipeInUse (xf86CrtcPtr crtc)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int	i;
-    
-    for (i = 0; i < xf86_config->num_output; i++)
-	if (xf86_config->output[i]->crtc == crtc)
-	    return TRUE;
-    return FALSE;
-}
-
-/**
  * Sets the power management mode of the pipe and plane.
  *
  * This code should probably grow support for turning the cursor off and back
@@ -581,6 +564,27 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 }
 
 static Bool
+i830_crtc_lock (xf86CrtcPtr crtc)
+{
+   /* Sync the engine before mode switch */
+   i830WaitSync(crtc->scrn);
+
+#ifdef XF86DRI
+    return I830DRILock(crtc->scrn);
+#else
+    return FALSE;
+#endif
+}
+
+static void
+i830_crtc_unlock (xf86CrtcPtr crtc)
+{
+#ifdef XF86DRI
+    I830DRIUnlock (crtc->scrn);
+#endif
+}
+
+static Bool
 i830_crtc_mode_fixup(xf86CrtcPtr crtc, DisplayModePtr mode,
 		     DisplayModePtr adjusted_mode)
 {
@@ -881,165 +885,11 @@ i830_crtc_gamma_set(xf86CrtcPtr crtc, CA
 }
 
 /**
- * Sets the given video mode on the given pipe.
- *
- * Plane A is always output to pipe A, and plane B to pipe B.  The plane
- * will not be enabled if plane_enable is FALSE, which is used for
- * load detection, when something else will be output to the pipe other than
- * display data.
- */
-Bool
-i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode,
-		Bool plane_enable)
-{
-    ScrnInfoPtr pScrn = crtc->scrn;
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int i;
-    Bool ret = FALSE;
-#ifdef XF86DRI
-    Bool didLock = FALSE;
-#endif
-    DisplayModePtr adjusted_mode;
-
-    /* XXX: curMode */
-
-    adjusted_mode = xf86DuplicateMode(pMode);
-
-    crtc->enabled = i830PipeInUse (crtc);
-    
-    if (!crtc->enabled)
-    {
-	/* XXX disable crtc? */
-	return TRUE;
-    }
-
-#ifdef XF86DRI
-    didLock = I830DRILock(pScrn);
-#endif
-
-    /* Pass our mode to the outputs and the CRTC to give them a chance to
-     * adjust it according to limitations or output properties, and also
-     * a chance to reject the mode entirely.
-     */
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-
-	if (output->crtc != crtc)
-	    continue;
-
-	if (!output->funcs->mode_fixup(output, pMode, adjusted_mode)) {
-	    ret = FALSE;
-	    goto done;
-	}
-    }
-
-    if (!crtc->funcs->mode_fixup(crtc, pMode, adjusted_mode)) {
-	ret = FALSE;
-	goto done;
-    }
-
-    /* Disable the outputs and CRTCs before setting the mode. */
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-
-	if (output->crtc != crtc)
-	    continue;
-
-	/* Disable the output as the first thing we do. */
-	output->funcs->dpms(output, DPMSModeOff);
-    }
-
-    crtc->funcs->dpms(crtc, DPMSModeOff);
-
-    /* Set up the DPLL and any output state that needs to adjust or depend
-     * on the DPLL.
-     */
-    crtc->funcs->mode_set(crtc, pMode, adjusted_mode);
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-	if (output->crtc == crtc)
-	    output->funcs->mode_set(output, pMode, adjusted_mode);
-    }
-
-    /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
-    crtc->funcs->dpms(crtc, DPMSModeOn);
-    for (i = 0; i < xf86_config->num_output; i++) {
-	xf86OutputPtr output = xf86_config->output[i];
-	if (output->crtc == crtc)
-	    output->funcs->dpms(output, DPMSModeOn);
-    }
-
-#if 0
-    /*
-     * If the display isn't solid, it may be running out
-     * of memory bandwidth. This code will dump out the
-     * pipe status, if bit 31 is on, the fifo underran
-     */
-    for (i = 0; i < 4; i++) {
-	i830WaitForVblank(pScrn);
-    
-	OUTREG(pipestat_reg, INREG(pipestat_reg) | 0x80000000);
-    
-	i830WaitForVblank(pScrn);
-    
-	temp = INREG(pipestat_reg);
-	ErrorF ("pipe status 0x%x\n", temp);
-    }
-#endif
-    
-    crtc->curMode = *pMode;
-
-    /* XXX free adjustedmode */
-    ret = TRUE;
-done:
-#ifdef XF86DRI
-    if (didLock)
-	I830DRIUnlock(pScrn);
-#endif
-    return ret;
-}
-
-void
-i830DisableUnusedFunctions(ScrnInfoPtr pScrn)
-{
-    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int o, pipe;
-
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling unused functions\n");
-
-    for (o = 0; o < xf86_config->num_output; o++) 
-    {
-	xf86OutputPtr  output = xf86_config->output[o];
-	if (!output->crtc) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling output %s\n",
-		       output->name);
-	    (*output->funcs->dpms)(output, DPMSModeOff);
-	}
-    }
-
-    for (pipe = 0; pipe < xf86_config->num_crtc; pipe++) 
-    {
-	xf86CrtcPtr crtc = xf86_config->crtc[pipe];
-	I830CrtcPrivatePtr  intel_crtc = crtc->driver_private;
-	int		    pipe = intel_crtc->pipe;
-	char	    *pipe_name = pipe == 0 ? "A" : "B";
-
-	if (!crtc->enabled) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Disabling CRTC %s\n",
-		       pipe_name);
-	    crtc->funcs->dpms(crtc, DPMSModeOff);
-
-	    memset(&crtc->curMode, 0, sizeof(crtc->curMode));
-	}
-    }
-}
-
-/**
  * This function configures the screens in clone mode on
  * all active outputs using a mode similar to the specified mode.
  */
 Bool
-i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode)
+i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Rotation rotation)
 {
     xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
     Bool ok = TRUE;
@@ -1049,9 +899,9 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     if (crtc && crtc->enabled)
     {
-	ok = i830PipeSetMode(crtc,
-			     i830PipeFindClosestMode(crtc, pMode), 
-			     TRUE);
+	ok = xf86CrtcSetMode(crtc,
+			     i830PipeFindClosestMode(crtc, pMode),
+			     rotation);
 	if (!ok)
 	    goto done;
 	crtc->desiredMode = *pMode;
@@ -1061,7 +911,7 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 	       (int)(pMode->HDisplay * pMode->VDisplay *
 		     pMode->VRefresh / 1000000));
 
-    i830DisableUnusedFunctions(pScrn);
+    xf86DisableUnusedFunctions(pScrn);
 
     i830DescribeOutputConfiguration(pScrn);
 
@@ -1153,7 +1003,7 @@ i830GetLoadDetectPipe(xf86OutputPtr outp
 	return output->crtc;
 
     for (i = 0; i < xf86_config->num_crtc; i++)
-	if (!i830PipeInUse(xf86_config->crtc[i]))
+	if (!xf86CrtcInUse (xf86_config->crtc[i]))
 	    break;
 
     if (i == xf86_config->num_crtc)
@@ -1177,7 +1027,7 @@ i830ReleaseLoadDetectPipe(xf86OutputPtr 
     {
 	output->crtc = NULL;
 	intel_output->load_detect_temp = FALSE;
-	i830DisableUnusedFunctions(pScrn);
+	xf86DisableUnusedFunctions(pScrn);
     }
 }
 
@@ -1185,6 +1035,8 @@ static const xf86CrtcFuncsRec i830_crtc_
     .dpms = i830_crtc_dpms,
     .save = NULL, /* XXX */
     .restore = NULL, /* XXX */
+    .lock = i830_crtc_lock,
+    .unlock = i830_crtc_unlock,
     .mode_fixup = i830_crtc_mode_fixup,
     .mode_set = i830_crtc_mode_set,
     .gamma_set = i830_crtc_gamma_set,
diff --git a/src/i830_display.h b/src/i830_display.h
index 66ab17e..dc80055 100644
--- a/src/i830_display.h
+++ b/src/i830_display.h
@@ -30,16 +30,12 @@
 /* i830_display.c */
 DisplayModePtr
 i830PipeFindClosestMode(xf86CrtcPtr crtc, DisplayModePtr pMode);
-Bool i830PipeSetMode(xf86CrtcPtr crtc, DisplayModePtr pMode, 
-		     Bool plane_enable);
-void i830DisableUnusedFunctions(ScrnInfoPtr pScrn);
-Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode);
+Bool i830SetMode(ScrnInfoPtr pScrn, DisplayModePtr pMode, Rotation rotation);
 void i830PipeSetBase(xf86CrtcPtr crtc, int x, int y);
 void i830WaitForVblank(ScrnInfoPtr pScrn);
 void i830DescribeOutputConfiguration(ScrnInfoPtr pScrn);
 
 xf86CrtcPtr i830GetLoadDetectPipe(xf86OutputPtr output);
 void i830ReleaseLoadDetectPipe(xf86OutputPtr output);
-Bool i830PipeInUse(xf86CrtcPtr crtc);
 void i830_crtc_init(ScrnInfoPtr pScrn, int pipe);
 void i830_crtc_load_lut(xf86CrtcPtr crtc);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 2992798..daa5a3b 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3131,7 +3131,7 @@ I830EnterVT(int scrnIndex, int flags)
    ResetState(pScrn, FALSE);
    SetHWOperatingState(pScrn);
 
-   i830DisableUnusedFunctions(pScrn);
+   xf86DisableUnusedFunctions(pScrn);
 
    for (i = 0; i < xf86_config->num_crtc; i++)
    {
@@ -3140,9 +3140,12 @@ I830EnterVT(int scrnIndex, int flags)
       /* Mark that we'll need to re-set the mode for sure */
       memset(&crtc->curMode, 0, sizeof(crtc->curMode));
       if (!crtc->desiredMode.CrtcHDisplay)
+      {
 	 crtc->desiredMode = *i830PipeFindClosestMode (crtc, pScrn->currentMode);
+	 crtc->desiredRotation = RR_Rotate_0;
+      }
       
-      if (!i830PipeSetMode (crtc, &crtc->desiredMode, TRUE))
+      if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation))
 	 return FALSE;
    }
 
@@ -3223,45 +3226,11 @@ I830SwitchMode(int scrnIndex, DisplayMod
    ScrnInfoPtr pScrn = xf86Screens[scrnIndex];
    I830Ptr pI830 = I830PTR(pScrn);
    Bool ret = TRUE;
-   PixmapPtr pspix = (*pScrn->pScreen->GetScreenPixmap) (pScrn->pScreen);
 
    DPRINTF(PFX, "I830SwitchMode: mode == %p\n", mode);
 
-   /* Sync the engine before mode switch */
-   i830WaitSync(pScrn);
-
-   /* Check if our currentmode is about to change. We do this so if we
-    * are rotating, we don't need to call the mode setup again.
-    */
-   if (pI830->currentMode != mode) {
-      if (!i830SetMode(pScrn, mode))
-         ret = FALSE;
-   }
-
-   /* Kludge to detect Rotate or Vidmode switch. Not very elegant, but
-    * workable given the implementation currently. We only need to call
-    * the rotation function when we know that the framebuffer has been
-    * disabled by the EnableDisableFBAccess() function.
-    *
-    * The extra WindowTable check detects a rotation at startup.
-    */
-   if ( (!WindowTable[pScrn->scrnIndex] || pspix->devPrivate.ptr == NULL) &&
-         !pI830->DGAactive && (pScrn->PointerMoved == I830PointerMoved)) {
-      if (!I830Rotate(pScrn, mode))
-         ret = FALSE;
-   }
-
-   /* Either the original setmode or rotation failed, so restore the previous
-    * video mode here, as we'll have already re-instated the original rotation.
-    */
-   if (!ret) {
-      if (!i830SetMode(pScrn, pI830->currentMode)) {
-	 xf86DrvMsg(scrnIndex, X_INFO,
-		    "Failed to restore previous mode (SwitchMode)\n");
-      }
-   } else {
+   if (!i830SetMode(pScrn, mode, pI830->rotation))
       pI830->currentMode = mode;
-   }
 
    return ret;
 }
diff --git a/src/i830_lvds.c b/src/i830_lvds.c
index 18ac76b..8abd402 100644
--- a/src/i830_lvds.c
+++ b/src/i830_lvds.c
@@ -254,10 +254,10 @@ i830_lvds_get_modes(xf86OutputPtr output
     xf86MonPtr		    edid_mon;
     DisplayModePtr	    modes;
 
-    edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus);
-    i830_xf86OutputSetEDID (output, edid_mon);
+    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    xf86OutputSetEDID (output, edid_mon);
     
-    modes = i830_xf86OutputGetEDIDModes (output);
+    modes = xf86OutputGetEDIDModes (output);
     if (modes != NULL)
 	return modes;
 
diff --git a/src/i830_modes.c b/src/i830_modes.c
index b4e22c3..405dcc6 100644
--- a/src/i830_modes.c
+++ b/src/i830_modes.c
@@ -62,9 +62,9 @@ i830_ddc_get_modes (xf86OutputPtr output
     xf86MonPtr		    edid_mon;
     DisplayModePtr	    modes;
 
-    edid_mon = i830_xf86OutputGetEDID (output, intel_output->pDDCBus);
-    i830_xf86OutputSetEDID (output, edid_mon);
+    edid_mon = xf86OutputGetEDID (output, intel_output->pDDCBus);
+    xf86OutputSetEDID (output, edid_mon);
     
-    modes = i830_xf86OutputGetEDIDModes (output);
+    modes = xf86OutputGetEDIDModes (output);
     return modes;
 }
diff --git a/src/i830_randr.c b/src/i830_randr.c
index 533322b..d6df419 100644
--- a/src/i830_randr.c
+++ b/src/i830_randr.c
@@ -541,7 +541,7 @@ xf86RandR12CrtcNotify (RRCrtcPtr	randr_c
 	return FALSE;
     x = crtc->x;
     y = crtc->y;
-    rotation = RR_Rotate_0;
+    rotation = crtc->curRotation;
     numOutputs = 0;
     randr_mode = NULL;
     for (i = 0; i < config->num_output; i++)
@@ -638,7 +638,7 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 
 	if (mode)
 	{
-	    if (!i830PipeSetMode (crtc, mode, TRUE))
+	    if (!xf86CrtcSetMode (crtc, mode, rotation))
 	    {
 		crtc->enabled = save_enabled;
 		for (o = 0; o < config->num_output; o++)
@@ -651,7 +651,7 @@ xf86RandR12CrtcSet (ScreenPtr	pScreen,
 	    }
 	    crtc->desiredMode = *mode;
 	}
-	i830DisableUnusedFunctions (pScrn);
+	xf86DisableUnusedFunctions (pScrn);
 
 	i830DumpRegs(pScrn);
     }
diff --git a/src/i830_tv.c b/src/i830_tv.c
index 92e417e..a76cbff 100644
--- a/src/i830_tv.c
+++ b/src/i830_tv.c
@@ -1065,7 +1065,7 @@ i830_tv_detect(xf86OutputPtr output)
 	    /* we only need the pixel clock set correctly here */
 	    mode = reported_modes[0];
 	    xf86SetModeCrtc (&mode, INTERLACE_HALVE_V);
-	    i830PipeSetMode (crtc, &mode, FALSE);
+	    xf86CrtcSetMode (crtc, &mode, RR_Rotate_0);
 	}
 	i830_tv_detect_type (crtc, output);
 	i830ReleaseLoadDetectPipe (output);
diff --git a/src/i830_xf86Crtc.c b/src/i830_xf86Crtc.c
index ceb8f2e..5eb55e9 100644
--- a/src/i830_xf86Crtc.c
+++ b/src/i830_xf86Crtc.c
@@ -87,6 +87,8 @@ xf86CrtcCreate (ScrnInfoPtr		scrn,
 #ifdef RANDR_12_INTERFACE
     crtc->randr_crtc = NULL;
 #endif
+    crtc->curRotation = RR_Rotate_0;
+    crtc->desiredRotation = RR_Rotate_0;
     if (xf86_config->crtc)
 	crtcs = xrealloc (xf86_config->crtc,
 			  (xf86_config->num_crtc + 1) * sizeof (xf86CrtcPtr));
@@ -121,6 +123,122 @@ xf86CrtcDestroy (xf86CrtcPtr crtc)
     xfree (crtc);
 }
 
+
+/**
+ * Return whether any outputs are connected to the specified pipe
+ */
+
+Bool
+xf86CrtcInUse (xf86CrtcPtr crtc)
+{
+    ScrnInfoPtr		pScrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			o;
+    
+    for (o = 0; o < xf86_config->num_output; o++)
+	if (xf86_config->output[o]->crtc == crtc)
+	    return TRUE;
+    return FALSE;
+}
+
+/**
+ * Sets the given video mode on the given crtc
+ */
+Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+    int			i;
+    Bool		ret = FALSE;
+    Bool		didLock = FALSE;
+    DisplayModePtr	adjusted_mode;
+
+    adjusted_mode = xf86DuplicateMode(mode);
+
+    crtc->enabled = xf86CrtcInUse (crtc);
+    
+    if (!crtc->enabled)
+    {
+	/* XXX disable crtc? */
+	return TRUE;
+    }
+
+    didLock = crtc->funcs->lock (crtc);
+
+    /* Pass our mode to the outputs and the CRTC to give them a chance to
+     * adjust it according to limitations or output properties, and also
+     * a chance to reject the mode entirely.
+     */
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
+
+	if (output->crtc != crtc)
+	    continue;
+
+	if (!output->funcs->mode_fixup(output, mode, adjusted_mode)) {
+	    ret = FALSE;
+	    goto done;
+	}
+    }
+
+    if (!crtc->funcs->mode_fixup(crtc, mode, adjusted_mode)) {
+	ret = FALSE;
+	goto done;
+    }
+
+#if 0
+    if (!xf86CrtcRotate (crtc, mode, rotation))
+    {
+	ret = FALSE;
+	goto done;
+    }
+#endif
+
+    /* Disable the outputs and CRTCs before setting the mode. */
+    for (i = 0; i < xf86_config->num_output; i++) {
+	xf86OutputPtr output = xf86_config->output[i];
+
+	if (output->crtc != crtc)
+	    continue;
+
+	/* Disable the output as the first thing we do. */
+	output->funcs->dpms(output, DPMSModeOff);
+    }
+
+    crtc->funcs->dpms(crtc, DPMSModeOff);
+
+    /* Set up the DPLL and any output state that needs to adjust or depend
+     * on the DPLL.
+     */
+    crtc->funcs->mode_set(crtc, mode, adjusted_mode);
+    for (i = 0; i < xf86_config->num_output; i++) 
+    {
+	xf86OutputPtr output = xf86_config->output[i];
+	if (output->crtc == crtc)
+	    output->funcs->mode_set(output, mode, adjusted_mode);
+    }
+
+    /* Now, enable the clocks, plane, pipe, and outputs that we set up. */
+    crtc->funcs->dpms(crtc, DPMSModeOn);
+    for (i = 0; i < xf86_config->num_output; i++) 
+    {
+	xf86OutputPtr output = xf86_config->output[i];
+	if (output->crtc == crtc)
+	    output->funcs->dpms(output, DPMSModeOn);
+    }
+
+    crtc->curMode = *mode;
+
+    /* XXX free adjustedmode */
+    ret = TRUE;
+done:
+    if (didLock)
+	crtc->funcs->unlock (crtc);
+
+    return ret;
+}
+
 /*
  * Output functions
  */
@@ -362,14 +480,14 @@ xf86OutputHasPreferredMode (xf86OutputPt
 }
 
 static int
-xf86PickCrtcs (ScrnInfoPtr	pScrn,
+xf86PickCrtcs (ScrnInfoPtr	scrn,
 	       xf86CrtcPtr	*best_crtcs,
 	       DisplayModePtr	*modes,
 	       int		n,
 	       int		width,
 	       int		height)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int		    c, o, l;
     xf86OutputPtr   output;
     xf86CrtcPtr	    crtc;
@@ -388,7 +506,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
      */
     best_crtcs[n] = NULL;
     best_crtc = NULL;
-    best_score = xf86PickCrtcs (pScrn, best_crtcs, modes, n+1, width, height);
+    best_score = xf86PickCrtcs (scrn, best_crtcs, modes, n+1, width, height);
     if (modes[n] == NULL)
 	return best_score;
     
@@ -442,7 +560,7 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
 	}
 	crtcs[n] = crtc;
 	memcpy (crtcs, best_crtcs, n * sizeof (xf86CrtcPtr));
-	score = my_score + xf86PickCrtcs (pScrn, crtcs, modes, n+1, width, height);
+	score = my_score + xf86PickCrtcs (scrn, crtcs, modes, n+1, width, height);
 	if (score > best_score)
 	{
 	    best_crtc = crtc;
@@ -462,9 +580,9 @@ xf86PickCrtcs (ScrnInfoPtr	pScrn,
  */
 
 static void
-xf86DefaultScreenLimits (ScrnInfoPtr pScrn, int *widthp, int *heightp)
+xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int	    width = 0, height = 0;
     int	    o;
     int	    c;
@@ -513,9 +631,9 @@ xf86DefaultScreenLimits (ScrnInfoPtr pSc
 #define POSITION_UNSET	-100000
 
 static Bool
-xf86InitialOutputPositions (ScrnInfoPtr pScrn, DisplayModePtr *modes)
+xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o;
     int			min_x, min_y;
     
@@ -563,7 +681,7 @@ xf86InitialOutputPositions (ScrnInfoPtr 
 		}
 		else
 		{
-		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
 				"Output %s position not of form \"x y\"\n",
 				output->name);
 		    output->initial_x = output->initial_y = 0;
@@ -606,7 +724,7 @@ xf86InitialOutputPositions (ScrnInfoPtr 
 		}
 		if (!relative)
 		{
-		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
 				"Cannot position output %s relative to unknown output %s\n",
 				output->name, relative_name);
 		    output->initial_x = 0;
@@ -655,7 +773,7 @@ xf86InitialOutputPositions (ScrnInfoPtr 
 		xf86OutputPtr   output = config->output[o];
 		if (output->initial_x == POSITION_UNSET)
 		{
-		    xf86DrvMsg (pScrn->scrnIndex, X_ERROR,
+		    xf86DrvMsg (scrn->scrnIndex, X_ERROR,
 				"Output position loop. Moving %s to 0,0\n",
 				output->name);
 		    output->initial_x = output->initial_y = 0;
@@ -778,16 +896,16 @@ i830xf86SortModes (DisplayModePtr input)
 #define DEBUG_REPROBE 1
 
 void
-xf86ProbeOutputModes (ScrnInfoPtr pScrn, int maxX, int maxY)
+xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o;
 
     if (maxX == 0 || maxY == 0)
-	xf86RandR12GetOriginalVirtualSize (pScrn, &maxX, &maxY);
+	xf86RandR12GetOriginalVirtualSize (scrn, &maxX, &maxY);
 
     /* Elide duplicate modes before defaulting code uses them */
-    xf86PruneDuplicateMonitorModes (pScrn->monitor);
+    xf86PruneDuplicateMonitorModes (scrn->monitor);
     
     /* Probe the list of modes for each output. */
     for (o = 0; o < config->num_output; o++) 
@@ -837,7 +955,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 		mon_rec.nVrefresh++;
 		sync_source = sync_config;
 	    }
-	    config_modes = i830xf86GetMonitorModes (pScrn, conf_monitor);
+	    config_modes = xf86GetMonitorModes (scrn, conf_monitor);
 	}
 	
 	output_modes = (*output->funcs->get_modes) (output);
@@ -901,27 +1019,27 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	    mon_rec.vrefresh[0].hi = 62.0;
 	    mon_rec.nVrefresh = 1;
 	}
-	default_modes = i830xf86GetDefaultModes (output->interlaceAllowed,
-						 output->doubleScanAllowed);
+	default_modes = xf86GetDefaultModes (output->interlaceAllowed,
+					     output->doubleScanAllowed);
 	
 	if (sync_source == sync_config)
 	{
 	    /* 
 	     * Check output and config modes against sync range from config file
 	     */
-	    i830xf86ValidateModesSync (pScrn, output_modes, &mon_rec);
-	    i830xf86ValidateModesSync (pScrn, config_modes, &mon_rec);
+	    xf86ValidateModesSync (scrn, output_modes, &mon_rec);
+	    xf86ValidateModesSync (scrn, config_modes, &mon_rec);
 	}
 	/*
 	 * Check default modes against sync range
 	 */
-        i830xf86ValidateModesSync (pScrn, default_modes, &mon_rec);
+        xf86ValidateModesSync (scrn, default_modes, &mon_rec);
 	/*
 	 * Check default modes against monitor max clock
 	 */
 	if (max_clock)
-	    i830xf86ValidateModesClocks(pScrn, default_modes,
-					&min_clock, &max_clock, 1);
+	    xf86ValidateModesClocks(scrn, default_modes,
+				    &min_clock, &max_clock, 1);
 	
 	output->probed_modes = NULL;
 	output->probed_modes = xf86ModesAdd (output->probed_modes, config_modes);
@@ -932,7 +1050,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	 * Check all modes against max size
 	 */
 	if (maxX && maxY)
-	    i830xf86ValidateModesSize (pScrn, output->probed_modes,
+	    xf86ValidateModesSize (scrn, output->probed_modes,
 				       maxX, maxY, 0);
 	 
 	/*
@@ -942,7 +1060,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	    if (mode->status == MODE_OK)
 		mode->status = (*output->funcs->mode_valid)(output, mode);
 	
-	i830xf86PruneInvalidModes(pScrn, &output->probed_modes, TRUE);
+	xf86PruneInvalidModes(scrn, &output->probed_modes, TRUE);
 	
 	output->probed_modes = i830xf86SortModes (output->probed_modes);
 	
@@ -975,11 +1093,11 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	
 #ifdef DEBUG_REPROBE
 	if (output->probed_modes != NULL) {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	    xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		       "Printing probed modes for output %s\n",
 		       output->name);
 	} else {
-	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+	    xf86DrvMsg(scrn->scrnIndex, X_INFO,
 		       "No remaining probed modes for output %s\n",
 		       output->name);
 	}
@@ -993,7 +1111,7 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 	    xf86SetModeCrtc(mode, INTERLACE_HALVE_V);
 
 #ifdef DEBUG_REPROBE
-	    xf86PrintModeline(pScrn->scrnIndex, mode);
+	    xf86PrintModeline(scrn->scrnIndex, mode);
 #endif
 	}
     }
@@ -1006,12 +1124,12 @@ xf86ProbeOutputModes (ScrnInfoPtr pScrn,
 
 /* XXX where does this function belong? Here? */
 void
-xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y);
+xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr scrn, int *x, int *y);
 
 void
-xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
+xf86SetScrnInfoModes (ScrnInfoPtr scrn)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     xf86OutputPtr	output;
     xf86CrtcPtr		crtc;
     DisplayModePtr	last, mode;
@@ -1035,31 +1153,31 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
     }
     crtc = output->crtc;
 
-    /* Clear any existing modes from pScrn->modes */
-    while (pScrn->modes != NULL)
-	xf86DeleteMode(&pScrn->modes, pScrn->modes);
+    /* Clear any existing modes from scrn->modes */
+    while (scrn->modes != NULL)
+	xf86DeleteMode(&scrn->modes, scrn->modes);
 
-    /* Set pScrn->modes to the mode list for the 'compat' output */
-    pScrn->modes = xf86DuplicateModes(pScrn, output->probed_modes);
+    /* Set scrn->modes to the mode list for the 'compat' output */
+    scrn->modes = xf86DuplicateModes(scrn, output->probed_modes);
 
-    for (mode = pScrn->modes; mode; mode = mode->next)
+    for (mode = scrn->modes; mode; mode = mode->next)
 	if (xf86ModesEqual (mode, &crtc->desiredMode))
 	    break;
 
-    if (pScrn->modes != NULL) {
-	/* For some reason, pScrn->modes is circular, unlike the other mode
+    if (scrn->modes != NULL) {
+	/* For some reason, scrn->modes is circular, unlike the other mode
 	 * lists.  How great is that?
 	 */
-	for (last = pScrn->modes; last && last->next; last = last->next)
+	for (last = scrn->modes; last && last->next; last = last->next)
 	    ;
-	last->next = pScrn->modes;
-	pScrn->modes->prev = last;
+	last->next = scrn->modes;
+	scrn->modes->prev = last;
 	if (mode) {
-	    while (pScrn->modes != mode)
-		pScrn->modes = pScrn->modes->next;
+	    while (scrn->modes != mode)
+		scrn->modes = scrn->modes->next;
 	}
     }
-    pScrn->currentMode = pScrn->modes;
+    scrn->currentMode = scrn->modes;
 }
 
 /**
@@ -1070,9 +1188,9 @@ xf86SetScrnInfoModes (ScrnInfoPtr pScrn)
  */
 
 Bool
-xf86InitialConfiguration (ScrnInfoPtr	    pScrn)
+xf86InitialConfiguration (ScrnInfoPtr	    scrn)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			o, c;
     DisplayModePtr	target_mode = NULL;
     xf86CrtcPtr		*crtcs;
@@ -1081,16 +1199,16 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     int			width;
     int			height;
 
-    if (pScrn->display->virtualX)
-	width = pScrn->display->virtualX;
+    if (scrn->display->virtualX)
+	width = scrn->display->virtualX;
     else
 	width = config->maxWidth;
-    if (pScrn->display->virtualY)
-	height = pScrn->display->virtualY;
+    if (scrn->display->virtualY)
+	height = scrn->display->virtualY;
     else
 	height = config->maxHeight;
 
-    xf86ProbeOutputModes (pScrn, width, height);
+    xf86ProbeOutputModes (scrn, width, height);
 
     crtcs = xnfcalloc (config->num_output, sizeof (xf86CrtcPtr));
     modes = xnfcalloc (config->num_output, sizeof (DisplayModePtr));
@@ -1152,7 +1270,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     /*
      * Set the position of each output
      */
-    if (!xf86InitialOutputPositions (pScrn, modes))
+    if (!xf86InitialOutputPositions (scrn, modes))
     {
 	xfree (crtcs);
 	xfree (modes);
@@ -1162,7 +1280,7 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     /*
      * Assign CRTCs to fit output configuration
      */
-    if (!xf86PickCrtcs (pScrn, crtcs, modes, 0, width, height))
+    if (!xf86PickCrtcs (scrn, crtcs, modes, 0, width, height))
     {
 	xfree (crtcs);
 	xfree (modes);
@@ -1171,8 +1289,8 @@ xf86InitialConfiguration (ScrnInfoPtr	  
     
     /* XXX override xf86 common frame computation code */
     
-    pScrn->display->frameX0 = 0;
-    pScrn->display->frameY0 = 0;
+    scrn->display->frameX0 = 0;
+    scrn->display->frameY0 = 0;
     
     for (c = 0; c < config->num_crtc; c++)
     {
@@ -1201,24 +1319,24 @@ xf86InitialConfiguration (ScrnInfoPtr	  
 	}
     }
     
-    if (pScrn->display->virtualX == 0)
+    if (scrn->display->virtualX == 0)
     {
 	/*
 	 * Expand virtual size to cover potential mode switches
 	 */
-	xf86DefaultScreenLimits (pScrn, &width, &height);
+	xf86DefaultScreenLimits (scrn, &width, &height);
     
-	pScrn->display->virtualX = width;
-	pScrn->display->virtualY = height;
+	scrn->display->virtualX = width;
+	scrn->display->virtualY = height;
     }
 
-    if (width > pScrn->virtualX)
-	pScrn->virtualX = width;
-    if (height > pScrn->virtualY)
-	pScrn->virtualY = height;
+    if (width > scrn->virtualX)
+	scrn->virtualX = width;
+    if (height > scrn->virtualY)
+	scrn->virtualY = height;
     
-    /* Mirror output modes to pScrn mode list */
-    xf86SetScrnInfoModes (pScrn);
+    /* Mirror output modes to scrn mode list */
+    xf86SetScrnInfoModes (scrn);
     
     xfree (crtcs);
     xfree (modes);
@@ -1232,9 +1350,9 @@ xf86InitialConfiguration (ScrnInfoPtr	  
  * Otherwise, it will affect CRTCs before outputs.
  */
 void
-xf86DPMSSet(ScrnInfoPtr pScrn, int mode, int flags)
+xf86DPMSSet(ScrnInfoPtr scrn, int mode, int flags)
 {
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			i;
 
     if (mode == DPMSModeOff) {
@@ -1260,6 +1378,35 @@ xf86DPMSSet(ScrnInfoPtr pScrn, int mode,
     }
 }
 
+/**
+ * Disable all inactive crtcs and outputs
+ */
+void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn)
+{
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    int			o, c;
+
+    for (o = 0; o < xf86_config->num_output; o++) 
+    {
+	xf86OutputPtr  output = xf86_config->output[o];
+	if (!output->crtc) 
+	    (*output->funcs->dpms)(output, DPMSModeOff);
+    }
+
+    for (c = 0; c < xf86_config->num_crtc; c++) 
+    {
+	xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+	if (!crtc->enabled) 
+	{
+	    crtc->funcs->dpms(crtc, DPMSModeOff);
+	    memset(&crtc->curMode, 0, sizeof(crtc->curMode));
+	}
+    }
+}
+
+ 
 #ifdef RANDR_12_INTERFACE
 
 #define EDID_ATOM_NAME		"EDID_DATA"
@@ -1290,10 +1437,10 @@ xf86OutputSetEDIDProperty (xf86OutputPtr
  * Set the EDID information for the specified output
  */
 void
-i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon)
 {
-    ScrnInfoPtr		pScrn = output->scrn;
-    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(pScrn);
+    ScrnInfoPtr		scrn = output->scrn;
+    xf86CrtcConfigPtr	config = XF86_CRTC_CONFIG_PTR(scrn);
     int			i;
 #ifdef RANDR_12_INTERFACE
     int			size;
@@ -1305,12 +1452,12 @@ i830_xf86OutputSetEDID (xf86OutputPtr ou
     output->MonInfo = edid_mon;
 
     /* Debug info for now, at least */
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
+    xf86DrvMsg(scrn->scrnIndex, X_INFO, "EDID for output %s\n", output->name);
     xf86PrintEDID(edid_mon);
     
     /* Set the DDC properties for the 'compat' output */
     if (output == config->output[config->compat_output])
-        xf86SetDDCproperties(pScrn, edid_mon);
+        xf86SetDDCproperties(scrn, edid_mon);
 
 #ifdef RANDR_12_INTERFACE
     /* Set the RandR output properties */
@@ -1354,20 +1501,20 @@ i830_xf86OutputSetEDID (xf86OutputPtr ou
  * stored in 'output'
  */
 DisplayModePtr
-i830_xf86OutputGetEDIDModes (xf86OutputPtr output)
+xf86OutputGetEDIDModes (xf86OutputPtr output)
 {
-    ScrnInfoPtr	pScrn = output->scrn;
+    ScrnInfoPtr	scrn = output->scrn;
     xf86MonPtr	edid_mon = output->MonInfo;
 
     if (!edid_mon)
 	return NULL;
-    return xf86DDCGetModes(pScrn->scrnIndex, edid_mon);
+    return xf86DDCGetModes(scrn->scrnIndex, edid_mon);
 }
 
 xf86MonPtr
-i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
 {
-    ScrnInfoPtr	pScrn = output->scrn;
+    ScrnInfoPtr	scrn = output->scrn;
 
-    return xf86DoEDID_DDC2 (pScrn->scrnIndex, pDDCBus);
+    return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
 }
diff --git a/src/i830_xf86Crtc.h b/src/i830_xf86Crtc.h
index 8fea162..e72dda6 100644
--- a/src/i830_xf86Crtc.h
+++ b/src/i830_xf86Crtc.h
@@ -24,8 +24,10 @@
 
 #include <edid.h>
 #include "randrstr.h"
+#include "i830_xf86Rename.h"
 #include "i830_xf86Modes.h"
 #include "xf86Parser.h"
+#include "damage.h"
 
 /* Compat definitions for older X Servers. */
 #ifndef M_T_PREFERRED
@@ -70,6 +72,19 @@ typedef struct _xf86CrtcFuncs {
 
 
     /**
+     * Lock CRTC prior to mode setting, mostly for DRI.
+     * Returns whether unlock is needed
+     */
+    Bool
+    (*lock) (xf86CrtcPtr crtc);
+    
+    /**
+     * Unlock CRTC after mode setting, mostly for DRI
+     */
+    void
+    (*unlock) (xf86CrtcPtr crtc);
+    
+    /**
      * Callback to adjust the mode to be set in the CRTC.
      *
      * This allows a CRTC to adjust the clock or even the entire set of
@@ -95,6 +110,18 @@ typedef struct _xf86CrtcFuncs {
 		 int size);
 
     /**
+     * Create shadow pixmap for rotation support
+     */
+    PixmapPtr
+    (*shadow_create) (xf86CrtcPtr crtc, int width, int height);
+    
+    /**
+     * Destroy shadow pixmap
+     */
+    void
+    (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap);
+
+    /**
      * Clean up driver-specific bits of the crtc
      */
     void
@@ -135,6 +162,8 @@ struct _xf86Crtc {
      * during server startup
      */
     DisplayModeRec  curMode;
+    Rotation	    curRotation;
+    PixmapPtr	    rotatedPixmap;
     
     /**
      * Desired mode
@@ -145,6 +174,7 @@ struct _xf86Crtc {
      * on VT switch.
      */
     DisplayModeRec  desiredMode;
+    Rotation	    desiredRotation;
     
     /** crtc-specific functions */
     const xf86CrtcFuncsRec *funcs;
@@ -363,6 +393,9 @@ typedef struct _xf86CrtcConfig {
 
     int			minWidth, minHeight;
     int			maxWidth, maxHeight;
+    
+    /* For crtc-based rotation */
+    DamagePtr   rotationDamage;
 } xf86CrtcConfigRec, *xf86CrtcConfigPtr;
 
 extern int xf86CrtcConfigPrivateIndex;
@@ -411,6 +444,24 @@ xf86AllocCrtc (xf86OutputPtr		output);
 void
 xf86FreeCrtc (xf86CrtcPtr		crtc);
 
+/**
+ * Sets the given video mode on the given crtc
+ */
+Bool
+xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+
+/*
+ * Assign crtc rotation during mode set
+ */
+Bool
+xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation);
+
+/**
+ * Return whether any output is assigned to the crtc
+ */
+Bool
+xf86CrtcInUse (xf86CrtcPtr crtc);
+
 /*
  * Output functions
  */
@@ -437,20 +488,23 @@ xf86InitialConfiguration (ScrnInfoPtr pS
 void
 xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
     
+void
+xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
+
 /**
  * Set the EDID information for the specified output
  */
 void
-i830_xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
+xf86OutputSetEDID (xf86OutputPtr output, xf86MonPtr edid_mon);
 
 /**
  * Return the list of modes supported by the EDID information
  * stored in 'output'
  */
 DisplayModePtr
-i830_xf86OutputGetEDIDModes (xf86OutputPtr output);
+xf86OutputGetEDIDModes (xf86OutputPtr output);
 
 xf86MonPtr
-i830_xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
+xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
 
 #endif /* _XF86CRTC_H_ */
diff --git a/src/i830_xf86Modes.c b/src/i830_xf86Modes.c
index 482a332..f37eaeb 100644
--- a/src/i830_xf86Modes.c
+++ b/src/i830_xf86Modes.c
@@ -337,7 +337,7 @@ xf86PrintModeline(int scrnIndex,DisplayM
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			    int flags)
 {
     DisplayModePtr mode;
@@ -358,7 +358,7 @@ i830xf86ValidateModesFlags(ScrnInfoPtr p
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			  int maxX, int maxY, int maxPitch)
 {
     DisplayModePtr mode;
@@ -387,7 +387,7 @@ i830xf86ValidateModesSize(ScrnInfoPtr pS
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			  MonPtr mon)
 {
     DisplayModePtr mode;
@@ -434,7 +434,7 @@ i830xf86ValidateModesSync(ScrnInfoPtr pS
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
 			    int *min, int *max, int n_ranges)
 {
     DisplayModePtr mode;
@@ -468,7 +468,7 @@ i830xf86ValidateModesClocks(ScrnInfoPtr 
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
+xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList)
 {
     DisplayModePtr mode;
 
@@ -502,7 +502,7 @@ i830xf86ValidateModesUserConfig(ScrnInfo
  * This is not in xf86Modes.c, but would be part of the proposed new API.
  */
 void
-i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
 			  Bool verbose)
 {
     DisplayModePtr mode;
@@ -558,7 +558,7 @@ xf86ModesAdd(DisplayModePtr modes, Displ
  * Build a mode list from a list of config file modes
  */
 static DisplayModePtr
-i830xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
+xf86GetConfigModes (XF86ConfModeLinePtr conf_mode)
 {
     DisplayModePtr  head = NULL, prev = NULL, mode;
     
@@ -604,7 +604,7 @@ i830xf86GetConfigModes (XF86ConfModeLine
  * Build a mode list from a monitor configuration
  */
 DisplayModePtr
-i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
+xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor)
 {
     DisplayModePtr	    modes = NULL;
     XF86ConfModesLinkPtr    modes_link;
@@ -625,18 +625,18 @@ i830xf86GetMonitorModes (ScrnInfoPtr pSc
 						  xf86configptr->conf_modes_lst);
 	if (modes_link->ml_modes)
 	    modes = xf86ModesAdd (modes,
-				  i830xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
+				  xf86GetConfigModes (modes_link->ml_modes->mon_modeline_lst));
     }
 
     return xf86ModesAdd (modes,
-			 i830xf86GetConfigModes (conf_monitor->mon_modeline_lst));
+			 xf86GetConfigModes (conf_monitor->mon_modeline_lst));
 }
 
 /**
  * Build a mode list containing all of the default modes
  */
 DisplayModePtr
-i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
+xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed)
 {
     DisplayModePtr  head = NULL, prev = NULL, mode;
     int		    i;
diff --git a/src/i830_xf86Modes.h b/src/i830_xf86Modes.h
index a7d0839..d032199 100644
--- a/src/i830_xf86Modes.h
+++ b/src/i830_xf86Modes.h
@@ -29,67 +29,54 @@
 #define _I830_XF86MODES_H_
 #include "xorgVersion.h"
 #include "xf86Parser.h"
+#include "i830_xf86Rename.h"
 
-#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(7,2,99,2,0)
-double i830_xf86ModeHSync(DisplayModePtr mode);
-double i830_xf86ModeVRefresh(DisplayModePtr mode);
-DisplayModePtr i830_xf86DuplicateMode(DisplayModePtr pMode);
-DisplayModePtr i830_xf86DuplicateModes(ScrnInfoPtr pScrn,
+double xf86ModeHSync(DisplayModePtr mode);
+double xf86ModeVRefresh(DisplayModePtr mode);
+DisplayModePtr xf86DuplicateMode(DisplayModePtr pMode);
+DisplayModePtr xf86DuplicateModes(ScrnInfoPtr pScrn,
 				       DisplayModePtr modeList);
-void i830_xf86SetModeDefaultName(DisplayModePtr mode);
-void i830_xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
-Bool i830_xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
-void i830_xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
-DisplayModePtr i830_xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
+void xf86SetModeDefaultName(DisplayModePtr mode);
+void xf86SetModeCrtc(DisplayModePtr p, int adjustFlags);
+Bool xf86ModesEqual(DisplayModePtr pMode1, DisplayModePtr pMode2);
+void xf86PrintModeline(int scrnIndex,DisplayModePtr mode);
+DisplayModePtr xf86ModesAdd(DisplayModePtr modes, DisplayModePtr new);
 
-DisplayModePtr i830_xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
-DisplayModePtr i830_xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
-				Bool Reduced, Bool Interlaced);
-
-#define xf86ModeHSync i830_xf86ModeHSync
-#define xf86ModeVRefresh i830_xf86ModeVRefresh
-#define xf86DuplicateMode i830_xf86DuplicateMode
-#define xf86DuplicateModes i830_xf86DuplicateModes
-#define xf86SetModeDefaultName i830_xf86SetModeDefaultName
-#define xf86SetModeCrtc i830_xf86SetModeCrtc
-#define xf86ModesEqual i830_xf86ModesEqual
-#define xf86PrintModeline i830_xf86PrintModeline
-#define xf86ModesAdd i830_xf86ModesAdd
-#define xf86DDCGetModes i830_xf86DDCGetModes
-#define xf86CVTMode i830_xf86CVTMode
-#endif /* XORG_VERSION_CURRENT <= 7.2.99.2 */
+DisplayModePtr xf86DDCGetModes(int scrnIndex, xf86MonPtr DDC);
+DisplayModePtr xf86CVTMode(int HDisplay, int VDisplay, float VRefresh,
+			   Bool Reduced, Bool Interlaced);
 
 void
-i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int flags);
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		       int flags);
 
 void
-i830xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int *min, int *max, int n_ranges);
+xf86ValidateModesClocks(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+			int *min, int *max, int n_ranges);
 
 void
-i830xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			  int maxX, int maxY, int maxPitch);
+xf86ValidateModesSize(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		      int maxX, int maxY, int maxPitch);
 
 void
-i830xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			  MonPtr mon);
+xf86ValidateModesSync(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		      MonPtr mon);
 
 void
-i830xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
-			  Bool verbose);
+xf86PruneInvalidModes(ScrnInfoPtr pScrn, DisplayModePtr *modeList,
+		      Bool verbose);
 
 void
-i830xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
-			    int flags);
+xf86ValidateModesFlags(ScrnInfoPtr pScrn, DisplayModePtr modeList,
+		       int flags);
 
 void
-i830xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
+xf86ValidateModesUserConfig(ScrnInfoPtr pScrn, DisplayModePtr modeList);
 
 DisplayModePtr
-i830xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
+xf86GetMonitorModes (ScrnInfoPtr pScrn, XF86ConfMonitorPtr conf_monitor);
 
 DisplayModePtr
-i830xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
+xf86GetDefaultModes (Bool interlaceAllowed, Bool doubleScanAllowed);
 
 #endif /* _I830_XF86MODES_H_ */
diff --git a/src/i830_xf86Rename.h b/src/i830_xf86Rename.h
new file mode 100644
index 0000000..cf8de62
--- /dev/null
+++ b/src/i830_xf86Rename.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright © 2006 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.
+ */
+
+#ifndef _XF86RENAME_H_
+#define _XF86RENAME_H_
+
+#include "local_xf86Rename.h"
+
+#define xf86CrtcConfigInit XF86NAME(xf86CrtcConfigInit)
+#define xf86CrtcConfigPrivateIndex XF86NAME(xf86CrtcConfigPrivateIndex)
+#define xf86CrtcCreate XF86NAME(xf86CrtcCreate)
+#define xf86CrtcDestroy XF86NAME(xf86CrtcDestroy)
+#define xf86CrtcInUse XF86NAME(xf86CrtcInUse)
+#define xf86CrtcRotate XF86NAME(xf86CrtcRotate)
+#define xf86CrtcSetMode XF86NAME(xf86CrtcSetMode)
+#define xf86CrtcSetSizeRange XF86NAME(xf86CrtcSetSizeRange)
+#define xf86CVTMode XF86NAME(xf86CVTMode)
+#define xf86DisableUnusedFunctions XF86NAME(xf86DisableUnusedFunctions)
+#define xf86DPMSSet XF86NAME(xf86DPMSSet)
+#define xf86DuplicateMode XF86NAME(xf86DuplicateMode)
+#define xf86DuplicateModes XF86NAME(xf86DuplicateModes)
+#define xf86GetDefaultModes XF86NAME(xf86GetDefaultModes)
+#define xf86GetMonitorModes XF86NAME(xf86GetMonitorModes)
+#define xf86InitialConfiguration XF86NAME(xf86InitialConfiguration)
+#define xf86ModeHSync XF86NAME(xf86ModeHSync)
+#define xf86ModesAdd XF86NAME(xf86ModesAdd)
+#define xf86ModesEqual XF86NAME(xf86ModesEqual)
+#define xf86ModeVRefresh XF86NAME(xf86ModeVRefresh)
+#define xf86OutputCreate XF86NAME(xf86OutputCreate)
+#define xf86OutputDestroy XF86NAME(xf86OutputDestroy)
+#define xf86OutputGetEDID XF86NAME(xf86OutputGetEDID)
+#define xf86OutputGetEDIDModes XF86NAME(xf86OutputGetEDIDModes)
+#define xf86OutputRename XF86NAME(xf86OutputRename)
+#define xf86OutputSetEDID XF86NAME(xf86OutputSetEDID)
+#define xf86PrintModeline XF86NAME(xf86PrintModeline)
+#define xf86ProbeOutputModes XF86NAME(xf86ProbeOutputModes)
+#define xf86PruneInvalidModes XF86NAME(xf86PruneInvalidModes)
+#define xf86SetModeCrtc XF86NAME(xf86SetModeCrtc)
+#define xf86SetModeDefaultName XF86NAME(xf86SetModeDefaultName)
+#define xf86SetScrnInfoModes XF86NAME(xf86SetScrnInfoModes)
+#define xf86ValidateModesClocks XF86NAME(xf86ValidateModesClocks)
+#define xf86ValidateModesFlags XF86NAME(xf86ValidateModesFlags)
+#define xf86ValidateModesSize XF86NAME(xf86ValidateModesSize)
+#define xf86ValidateModesSync XF86NAME(xf86ValidateModesSync)
+#define xf86ValidateModesUserConfig XF86NAME(xf86ValidateModesUserConfig)
+
+#endif /* _XF86RENAME_H_ */
diff --git a/src/i830_xf86Rotate.c b/src/i830_xf86Rotate.c
new file mode 100644
index 0000000..12b2091
--- /dev/null
+++ b/src/i830_xf86Rotate.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright © 2006 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_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stddef.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "xf86.h"
+#include "xf86DDC.h"
+/*#include "i830.h" */
+#include "i830_xf86Crtc.h"
+#include "i830_xf86Modes.h"
+#include "i830_randr.h"
+#include "X11/extensions/render.h"
+#define DPMS_SERVER
+#include "X11/extensions/dpms.h"
+#include "X11/Xatom.h"
+
+static int
+mode_height (DisplayModePtr mode, Rotation rotation)
+{
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_180:
+	return mode->VDisplay;
+    case RR_Rotate_90:
+    case RR_Rotate_270:
+	return mode->HDisplay;
+    default:
+	return 0;
+    }
+}
+
+static int
+mode_width (DisplayModePtr mode, Rotation rotation)
+{
+    switch (rotation & 0xf) {
+    case RR_Rotate_0:
+    case RR_Rotate_180:
+	return mode->HDisplay;
+    case RR_Rotate_90:
+    case RR_Rotate_270:
+	return mode->VDisplay;
+    default:
+	return 0;
+    }
+}
+
+/* borrowed from composite extension, move to Render and publish? */
+
+static VisualPtr
+compGetWindowVisual (WindowPtr pWin)
+{
+    ScreenPtr	    pScreen = pWin->drawable.pScreen;
+    VisualID	    vid = wVisual (pWin);
+    int		    i;
+
+    for (i = 0; i < pScreen->numVisuals; i++)
+	if (pScreen->visuals[i].vid == vid)
+	    return &pScreen->visuals[i];
+    return 0;
+}
+
+static PictFormatPtr
+compWindowFormat (WindowPtr pWin)
+{
+    ScreenPtr	pScreen = pWin->drawable.pScreen;
+    
+    return PictureMatchVisual (pScreen, pWin->drawable.depth,
+			       compGetWindowVisual (pWin));
+}
+
+static void
+xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
+{
+    ScrnInfoPtr		scrn = crtc->scrn;
+    ScreenPtr		screen = scrn->pScreen;
+    PixmapPtr		src_pixmap = (*screen->GetScreenPixmap) (screen);
+    PixmapPtr		dst_pixmap = crtc->rotatedPixmap;
+    PictFormatPtr	format = compWindowFormat (WindowTable[screen->myNum]);
+    int			error;
+    PicturePtr		src, dst;
+    PictTransform	transform;
+    
+    src = CreatePicture (None,
+			 &src_pixmap->drawable,
+			 format,
+			 0L,
+			 NULL,
+			 serverClient,
+			 &error);
+    if (!src)
+	return;
+    dst = CreatePicture (None,
+			 &dst_pixmap->drawable,
+			 format,
+			 0L,
+			 NULL,
+			 serverClient,
+			 &error);
+    if (!dst)
+	return;
+    SetPictureClipRegion (src, 0, 0, region);
+    memset (&transform, '\0', sizeof (transform));
+    transform.matrix[2][2] = 1;
+    transform.matrix[0][2] = crtc->x;
+    transform.matrix[1][2] = crtc->y;
+    switch (crtc->curRotation & 0xf) {
+    case RR_Rotate_0:
+	transform.matrix[0][0] = 1;
+	transform.matrix[1][1] = 1;
+	break;
+    case RR_Rotate_90:
+	/* XXX probably wrong */
+	transform.matrix[0][1] = 1;
+	transform.matrix[1][0] = -1;
+	transform.matrix[1][2] += crtc->curMode.HDisplay;
+	break;
+    case RR_Rotate_180:
+	/* XXX probably wrong */
+	transform.matrix[0][0] = -1;
+	transform.matrix[1][1] = -1;
+	transform.matrix[0][2] += crtc->curMode.HDisplay;
+	transform.matrix[1][2] += crtc->curMode.VDisplay;
+	break;
+    case RR_Rotate_270:
+	/* XXX probably wrong */
+	transform.matrix[0][1] = -1;
+	transform.matrix[1][0] = 1;
+	transform.matrix[0][2] += crtc->curMode.VDisplay;
+	break;
+    }
+    /* handle reflection */
+    if (crtc->curRotation & RR_Reflect_X)
+    {
+	/* XXX figure this out */
+    }
+    if (crtc->curRotation & RR_Reflect_Y)
+    {
+	/* XXX figure this out too */
+    }
+    SetPictureTransform (src, &transform);
+    CompositePicture (PictOpSrc,
+		      src, NULL, dst,
+		      0, 0, 0, 0, 0, 0,
+		      dst_pixmap->drawable.width,
+		      dst_pixmap->drawable.height);
+    FreePicture (src, None);
+    FreePicture (dst, None);
+}
+
+static void
+xf86RotateRedisplay(ScreenPtr pScreen)
+{
+    ScrnInfoPtr		pScrn = xf86Screens[pScreen->myNum];
+    xf86CrtcConfigPtr   xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+    DamagePtr		damage = xf86_config->rotationDamage;
+    RegionPtr		region;
+
+    if (!damage)
+	return;
+    region = DamageRegion(damage);
+    if (REGION_NOTEMPTY(pScreen, region)) 
+    {
+	int		    c;
+	
+	for (c = 0; c < xf86_config->num_crtc; c++)
+	{
+	    xf86CrtcPtr	    crtc = xf86_config->crtc[c];
+
+	    if (crtc->curRotation != RR_Rotate_0)
+	    {
+		BoxRec	    box;
+		RegionRec   crtc_damage;
+
+		/* compute portion of damage that overlaps crtc */
+		box.x1 = crtc->x;
+		box.x2 = crtc->x + mode_width (&crtc->curMode, crtc->curRotation);
+		box.y1 = crtc->y;
+		box.y2 = crtc->y + mode_height (&crtc->curMode, crtc->curRotation);
+		REGION_INIT(pScreen, &crtc_damage, &box, 1);
+		REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
+		
+		/* update damaged region */
+		if (REGION_NOTEMPTY(pScreen, &crtc_damage))
+		    xf86RotateCrtcRedisplay (crtc, &crtc_damage);
+		
+		REGION_UNINIT (pScreen, &crtc_damage);
+	    }
+	}
+	DamageEmpty(damage);
+    }
+}
+
+static void
+xf86RotateBlockHandler(pointer data, OSTimePtr pTimeout, pointer pRead)
+{
+    ScreenPtr pScreen = (ScreenPtr) data;
+
+    xf86RotateRedisplay(pScreen);
+}
+
+static void
+xf86RotateWakeupHandler(pointer data, int i, pointer LastSelectMask)
+{
+}
+
+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)
+    {
+	/* Free memory from rotation */
+	if (crtc->rotatedPixmap)
+	{
+	    crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap);
+	    crtc->rotatedPixmap = NULL;
+	}
+
+	if (xf86_config->rotationDamage)
+	{
+	    /* Free damage structure */
+	    DamageDestroy (xf86_config->rotationDamage);
+	    xf86_config->rotationDamage = NULL;
+	    /* Free block/wakeup handler */
+	    RemoveBlockAndWakeupHandlers (xf86RotateBlockHandler,
+					  xf86RotateWakeupHandler,
+					  (pointer) pScreen);
+	}
+    }
+    else
+    {
+	int	    width = mode_width (mode, rotation);
+	int	    height = mode_height (mode, rotation);
+	PixmapPtr   shadow = crtc->rotatedPixmap;
+	int	    old_width = shadow ? shadow->drawable.width : 0;
+	int	    old_height = shadow ? shadow->drawable.height : 0;
+	
+	/* Allocate memory for rotation */
+	if (old_width != width || old_height != height)
+	{
+	    if (shadow)
+	    {
+		crtc->funcs->shadow_destroy (crtc, shadow);
+		crtc->rotatedPixmap = NULL;
+	    }
+	    shadow = crtc->funcs->shadow_create (crtc, width, height);
+	    if (!shadow)
+		goto bail1;
+	}
+	
+	if (!xf86_config->rotationDamage)
+	{
+	    /* Create damage structure */
+	    xf86_config->rotationDamage = DamageCreate (NULL, NULL,
+						DamageReportNone,
+						TRUE, pScreen, pScreen);
+	    if (!xf86_config->rotationDamage)
+		goto bail2;
+	    
+	    /* Hook damage to screen pixmap */
+	    DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+			    xf86_config->rotationDamage);
+	    
+	    /* Assign block/wakeup handler */
+	    if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler,
+						 xf86RotateWakeupHandler,
+						 (pointer) pScreen))
+	    {
+		goto bail3;
+	    }
+	}
+	if (0)
+	{
+bail3:
+	    DamageDestroy (xf86_config->rotationDamage);
+	    xf86_config->rotationDamage = NULL;
+	    
+bail2:
+	    if (shadow)
+	    {
+		crtc->funcs->shadow_destroy (crtc, shadow);
+		crtc->rotatedPixmap = NULL;
+	    }
+bail1:
+	    if (old_width && old_height)
+		crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
+								  old_width,
+								  old_height);
+	    return FALSE;
+	}
+    }
+    
+    /* All done */
+    crtc->curRotation = rotation;
+    return TRUE;
+}
diff --git a/src/local_xf86Rename.h b/src/local_xf86Rename.h
new file mode 100644
index 0000000..e1e788f
--- /dev/null
+++ b/src/local_xf86Rename.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright © 2006 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.
+ */
+
+#define XF86NAME(x) intel_##x



More information about the xorg-commit mailing list