xf86-video-intel: 24 commits - configure.ac man/intel.man src/i830.h src/i830_accel.c src/i830_common.h src/i830_display.c src/i830_dri.c src/i830_dri.h src/i830_driver.c src/i830_memory.c src/i830_xaa.c

Michel Daenzer daenzer at kemper.freedesktop.org
Sat Mar 10 01:26:44 EET 2007


 configure.ac       |    5 
 man/intel.man      |   20 +++
 src/i830.h         |   12 ++
 src/i830_accel.c   |    3 
 src/i830_common.h  |    6 +
 src/i830_display.c |   52 ++++++++
 src/i830_dri.c     |  309 +++++++++++++++++++++++++++++++++++++++++++----------
 src/i830_dri.h     |    4 
 src/i830_driver.c  |   47 ++++++--
 src/i830_memory.c  |   47 +++++---
 src/i830_xaa.c     |    5 
 11 files changed, 428 insertions(+), 82 deletions(-)

New commits:
diff-tree 3c2d6e07bdf8daef6486b594aef0d22460eb2585 (from 7518b8959ee7598f3526365a83ea7e143a5d6a4e)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 23:49:46 2007 +0100

    Don't crash when the SAREA pointer is NULL.

diff --git a/src/i830_display.c b/src/i830_display.c
index 7855712..d230f74 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -395,6 +395,9 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
     if (pI830->directRenderingEnabled) {
 	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
 
+	if (!sPriv)
+	    return;
+
 	switch (pipe) {
 	case 0:
 	    sPriv->pipeA_x = x;
@@ -516,6 +519,9 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
 	Bool enabled = crtc->enabled && mode != DPMSModeOff;
 
+	if (!sPriv)
+	    return;
+
 	switch (pipe) {
 	case 0:
 	    sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0;
diff-tree 7518b8959ee7598f3526365a83ea7e143a5d6a4e (from 1991a90ae90b388c914985d20d6f8c3637856e9a)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 19:50:03 2007 +0100

    Revert change accidentally included in previous commit.

diff --git a/src/i830_exa.c b/src/i830_exa.c
index dfc8f99..bef8fae 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DEBUG_I830FALLBACK 1
 #endif
 
-#define ALWAYS_SYNC		0
+#define ALWAYS_SYNC		1
 
 #ifdef DEBUG_I830FALLBACK
 #define I830FALLBACK(s, arg...)				\
diff-tree 1991a90ae90b388c914985d20d6f8c3637856e9a (from aef161853033907c6916337cebe88c8f111dd542)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 19:47:13 2007 +0100

    Update SAREA pipe sizes in i830_crtc_dpms instead of i830PipeSetBase.
    
    This allows setting the size to 0 when a pipe gets disabled.

diff --git a/src/i830_display.c b/src/i830_display.c
index 8a2494f..7855712 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -399,14 +399,10 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	case 0:
 	    sPriv->pipeA_x = x;
 	    sPriv->pipeA_y = y;
-	    sPriv->pipeA_w = crtc->mode.HDisplay;
-	    sPriv->pipeA_h = crtc->mode.VDisplay;
 	    break;
 	case 1:
 	    sPriv->pipeB_x = x;
 	    sPriv->pipeB_y = y;
-	    sPriv->pipeB_w = crtc->mode.HDisplay;
-	    sPriv->pipeB_h = crtc->mode.VDisplay;
 	    break;
 	default:
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
@@ -514,6 +510,28 @@ i830_crtc_dpms(xf86CrtcPtr crtc, int mod
 	usleep(150);
 	break;
     }
+
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
+	Bool enabled = crtc->enabled && mode != DPMSModeOff;
+
+	switch (pipe) {
+	case 0:
+	    sPriv->pipeA_w = enabled ? crtc->mode.HDisplay : 0;
+	    sPriv->pipeA_h = enabled ? crtc->mode.VDisplay : 0;
+	    break;
+	case 1:
+	    sPriv->pipeB_w = enabled ? crtc->mode.HDisplay : 0;
+	    sPriv->pipeB_h = enabled ? crtc->mode.VDisplay : 0;
+	    break;
+	default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Can't update pipe %d in SAREA\n", pipe);
+	    break;
+	}
+    }
+#endif
 }
 
 static Bool
diff --git a/src/i830_exa.c b/src/i830_exa.c
index bef8fae..dfc8f99 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -42,7 +42,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #define DEBUG_I830FALLBACK 1
 #endif
 
-#define ALWAYS_SYNC		1
+#define ALWAYS_SYNC		0
 
 #ifdef DEBUG_I830FALLBACK
 #define I830FALLBACK(s, arg...)				\
diff-tree aef161853033907c6916337cebe88c8f111dd542 (from parents)
Merge: 1b54ee493fb96f944aa81e56fa6f00a8067f87fc 14ee9195d203192d3f613919f230b20b900ffdba
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 15:14:48 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip

diff-tree 1b54ee493fb96f944aa81e56fa6f00a8067f87fc (from parents)
Merge: e972265261c421268e4fb806e587378d0adec577 81722a21d232fa6cfb11fbe3d984abab50e89bcc
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Mar 9 15:13:50 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip
    
    Conflicts:
    
    	src/i830_dri.c

diff --cc src/i830_dri.c
index 9931acc,680a28e..5293574
@@@ -107,12 -107,7 +107,8 @@@
  static void I830DRITransitionTo3d(ScreenPtr pScreen);
  static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
  static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
 +static void I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num);
  
- #if 0
- static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
- #endif
- 
  extern void GlxSetVisualConfigs(int nconfigs,
  				__GLXvisualConfig * configs,
  				void **configprivs);
@@@ -1418,24 -1254,8 +1414,20 @@@
   * allocate and free 3d-specific memory on demand.
   */
  
- 
- 
- 
- 
 +/* Use the miext/shadow module to maintain a list of dirty rectangles.
 + * These are blitted to the back buffer to keep both buffers clean
 + * during page-flipping when the 3d application isn't fullscreen.
 + *
 + * Unlike most use of the shadow code, both buffers are in video
 + * memory.
 + *
 + * An alternative to this would be to organize for all on-screen
 + * drawing operations to be duplicated for the two buffers.  That
 + * might be faster, but seems like a lot more work...
 + */
 +
  static void
 -I830EnablePageFlip(ScreenPtr pScreen)
 +I830DRISetPfMask(ScreenPtr pScreen, int pfMask)
  {
     ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
diff-tree e972265261c421268e4fb806e587378d0adec577 (from 3c08bc7d6974a1a6cf5f9cb81898617032966c52)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 16:54:16 2007 +0100

    Fix build failure.
    
    Not sure how I missed this before... Thanks to Todd Merrill for reporting.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index bb9de1e..9931acc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -756,8 +756,9 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 		    "[drm] drmAddMap(third_handle) failed. Triple buffering "
 		    "inactive\n");
-	 i830_free_memory(pI830->third_buffer);
-	 sarea->third_handle = pI830->third_buffer = NULL;
+	 i830_free_memory(pScrn, pI830->third_buffer);
+	 pI830->third_buffer = NULL;
+	 sarea->third_handle = 0;
       } else
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
 		    (int)sarea->third_handle);
diff-tree 3c08bc7d6974a1a6cf5f9cb81898617032966c52 (from c25cfafbe1eb380b58b5fc16e94f5cc6f422f0cd)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 10:14:47 2007 +0100

    Fix some conditionals related to triple buffering.
    
    Guard code that dereferences pI830->third_buffer with tests for that instead of
    pI830->TripleBuffer. It could happen that we want to enable triple buffering
    but (temporarily) can't because the third buffer couldn't be allocated.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index d69ab3f..bb9de1e 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -748,18 +748,19 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n",
               (int)sarea->back_handle);
 
-   if (pI830->TripleBuffer) {
+   if (pI830->third_buffer) {
       if (drmAddMap(pI830->drmSubFD,
 		    (drm_handle_t)(sarea->third_offset + pI830->LinearAddr),
 		    sarea->third_size, DRM_AGP, 0,
 		    (drmAddress) &sarea->third_handle) < 0) {
-	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
-		   "[drm] drmAddMap(third_handle) failed. Disabling DRI\n");
-	DRICloseScreen(pScreen);
-	return FALSE;
-      }
-      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
-		 (int)sarea->third_handle);
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "[drm] drmAddMap(third_handle) failed. Triple buffering "
+		    "inactive\n");
+	 i830_free_memory(pI830->third_buffer);
+	 sarea->third_handle = pI830->third_buffer = NULL;
+      } else
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
+		    (int)sarea->third_handle);
    }
 
    if (drmAddMap(pI830->drmSubFD,
@@ -1103,7 +1104,7 @@ I830DRIRefreshArea (ScrnInfoPtr pScrn, i
 
    I830DRIDoRefreshArea(pScrn, num, pbox, pI830->back_buffer->offset);
 
-   if (pI830->TripleBuffer) {
+   if (pI830->third_buffer) {
       I830DRIDoRefreshArea(pScrn, num, pbox, pI830->third_buffer->offset);
    }
 
@@ -1207,7 +1208,7 @@ I830DRIInitBuffers(WindowPtr pWin, Regio
       I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
 				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
 
-      if (I830PTR(pScrn)->TripleBuffer) {
+      if (I830PTR(pScrn)->third_buffer) {
 	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
 	 I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
 				     pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
@@ -1386,7 +1387,7 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
 
       I830SelectBuffer(pScrn, I830_SELECT_BACK);
       I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
-      if (pI830->TripleBuffer) {
+      if (pI830->third_buffer) {
 	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
 	 I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
       }
@@ -1582,8 +1583,13 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->height = pScreen->height;
    sarea->back_offset = pI830->back_buffer->offset;
    sarea->back_size = pI830->back_buffer->size;
-   sarea->third_offset = pI830->third_buffer->offset;
-   sarea->third_size = pI830->third_buffer->size;
+   if (pI830->third_buffer != NULL) {
+      sarea->third_offset = pI830->third_buffer->offset;
+      sarea->third_size = pI830->third_buffer->size;
+   } else {
+      sarea->third_offset = 0;
+      sarea->third_size = 0;
+   }
    sarea->depth_offset = pI830->depth_buffer->offset;
    sarea->depth_size = pI830->depth_buffer->size;
    if (pI830->textures != NULL) {
diff-tree c25cfafbe1eb380b58b5fc16e94f5cc6f422f0cd (from e787d7b698d320a7c45df35d58c5113413561fe2)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 10:00:12 2007 +0100

    Unify allocation of back buffers.

diff --git a/src/i830_memory.c b/src/i830_memory.c
index 17cad73..54cd6be 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1064,7 +1064,8 @@ myLog2(unsigned int n)
 }
 
 static Bool
-i830_allocate_backbuffer(ScrnInfoPtr pScrn)
+i830_allocate_backbuffer(ScrnInfoPtr pScrn, i830_memory **buffer,
+			 unsigned int *tiled, const char *name)
 {
     I830Ptr pI830 = I830PTR(pScrn);
     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
@@ -1080,69 +1081,23 @@ i830_allocate_backbuffer(ScrnInfoPtr pSc
     if (!pI830->disableTiling && IsTileable(pScrn, pitch))
     {
 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
-	pI830->back_buffer =
-	    i830_allocate_memory_tiled(pScrn, "back buffer",
-				       size, pitch, GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS,
-				       TILING_XMAJOR);
-	pI830->back_tiled = FENCE_XMAJOR;
+	*buffer = i830_allocate_memory_tiled(pScrn, name, size, pitch,
+					     GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
+					     TILING_XMAJOR);
+	*tiled = FENCE_XMAJOR;
     }
 
     /* Otherwise, just allocate it linear */
-    if (pI830->back_buffer == NULL) {
+    if (*buffer == NULL) {
 	size = ROUND_TO_PAGE(pitch * height);
-	pI830->back_buffer = i830_allocate_memory(pScrn, "back buffer",
-						  size, GTT_PAGE_SIZE,
-						  ALIGN_BOTH_ENDS);
-	pI830->back_tiled = FENCE_LINEAR;
+	*buffer = i830_allocate_memory(pScrn, name, size, GTT_PAGE_SIZE,
+				       ALIGN_BOTH_ENDS);
+	*tiled = FENCE_LINEAR;
     }
 
-    if (pI830->back_buffer == NULL) {
+    if (*buffer == NULL) {
 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Failed to allocate back buffer space.\n");
-	return FALSE;
-    }
-
-    return TRUE;
-}
-
-static Bool
-i830_allocate_thirdbuffer(ScrnInfoPtr pScrn)
-{
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
-    unsigned long size;
-    int height;
-
-    if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
-	height = pScrn->virtualY;
-    else
-	height = pScrn->virtualX;
-
-    /* Try to allocate on the best tile-friendly boundaries. */
-    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
-    {
-	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
-	pI830->third_buffer =
-	    i830_allocate_memory_tiled(pScrn, "third buffer",
-				       size, pitch, GTT_PAGE_SIZE,
-				       ALIGN_BOTH_ENDS,
-				       TILING_XMAJOR);
-	pI830->third_tiled = FENCE_XMAJOR;
-    }
-
-    /* Otherwise, just allocate it linear */
-    if (pI830->third_buffer == NULL) {
-	size = ROUND_TO_PAGE(pitch * height);
-	pI830->third_buffer = i830_allocate_memory(pScrn, "third buffer",
-						   size, GTT_PAGE_SIZE,
-						   ALIGN_BOTH_ENDS);
-	pI830->third_tiled = FENCE_LINEAR;
-    }
-
-    if (pI830->third_buffer == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Failed to allocate third buffer space.\n");
+		   "Failed to allocate %s space.\n", name);
 	return FALSE;
     }
 
@@ -1246,10 +1201,14 @@ i830_allocate_3d_memory(ScrnInfoPtr pScr
 
     DPRINTF(PFX, "i830_allocate_3d_memory\n");
 
-    if (!i830_allocate_backbuffer(pScrn))
+    if (!i830_allocate_backbuffer(pScrn, &pI830->back_buffer,
+				  &pI830->back_tiled, "back buffer"))
 	return FALSE;
 
-    if (pI830->TripleBuffer && !i830_allocate_thirdbuffer(pScrn)) {
+    if (pI830->TripleBuffer && !i830_allocate_backbuffer(pScrn,
+							 &pI830->third_buffer,
+							 &pI830->third_tiled,
+							 "third buffer")) {
        xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		  "Failed to allocate third buffer, triple buffering "
 		  "inactive\n");
diff-tree e787d7b698d320a7c45df35d58c5113413561fe2 (from 6c299aea8e87e72c68c96c03594706c976601ede)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 09:35:42 2007 +0100

    Remove warnings about potential artifacts with page flipping and mixed 2D/3D.
    
    The artifacts only seemed to occur when EXA was falling back to software for
    the front buffer.

diff --git a/man/intel.man b/man/intel.man
index 05a91f7..32aa7c1 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -161,9 +161,9 @@ Default: 32768.
 .TP
 .BI "Option \*qPageFlip\*q \*q" boolean \*q
 Enable support for page flipping. This should improve 3D performance at the
-potential cost of worse performance or artifacts with mixed 2D/3D. Also note
-that this gives no benefit without corresponding support in the Mesa 3D driver
-and may not give the full benefit without triple buffering (see
+potential cost of worse performance with mixed 2D/3D. Also note that this gives
+no benefit without corresponding support in the Mesa 3D driver and may not give
+the full benefit without triple buffering (see
 .B "Option \*qTripleBuffer\*q"
 ).
 Default for i810: The option is not used.
diff-tree 6c299aea8e87e72c68c96c03594706c976601ede (from parents)
Merge: 330815251dee808754b328cd2fd60db39f2460eb 4042b27f01fdb94e7fc0d4e991e054fff88479ea
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Mar 6 09:28:52 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip
    
    Conflicts:
    
    	src/i830_display.c
    	src/i830_driver.c

diff --cc src/i830_driver.c
index 8379b6b,0977511..0de4d0d
@@@ -272,9 -272,10 +272,11 @@@
     OPTION_COLOR_KEY,
     OPTION_CHECKDEVICES,
     OPTION_LINEARALLOC,
+ #ifdef XF86DRI_MM
     OPTION_INTELTEXPOOL,
 -   OPTION_INTELMMSIZE
 +   OPTION_INTELMMSIZE,
+ #endif
 +   OPTION_TRIPLEBUFFER,
  } I830Opts;
  
  static OptionInfoRec I830Options[] = {
@@@ -291,9 -292,10 +293,11 @@@
     {OPTION_VIDEO_KEY,	"VideoKey",	OPTV_INTEGER,	{0},	FALSE},
     {OPTION_CHECKDEVICES, "CheckDevices",OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
+ #ifdef XF86DRI_MM
     {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
     {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
+ #endif
 +   {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,	{0},	FALSE},
     {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
  };
  /* *INDENT-ON* */
diff-tree 330815251dee808754b328cd2fd60db39f2460eb (from parents)
Merge: 50ba1fff886a7f51b178ac6d3a1ba79a3014b214 015027034e970f1e3bb6ab239f7e0119235e404f
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 5 13:05:20 2007 +0100

    Merge remote branch 'origin/master' into i830-pageflip
    
    Conflicts:
    
    	src/i830.h
    	src/i830_dri.c
    	src/i830_dri.h
    	src/i830_driver.c
    	src/i830_memory.c
    	src/i830_xaa.c

diff --cc src/i830.h
index e26556f,08d9e3e..c704372
@@@ -291,12 -295,13 +298,14 @@@
     CreateScreenResourcesProcPtr    CreateScreenResources;
     int *used3D;
  
-    I830MemRange ContextMem;
+    i830_memory *logical_context;
  #ifdef XF86DRI
-    I830MemRange BackBuffer;
-    I830MemRange ThirdBuffer;
-    I830MemRange DepthBuffer;
-    I830MemRange TexMem;
+    i830_memory *back_buffer;
++   i830_memory *third_buffer;
+    i830_memory *depth_buffer;
+    i830_memory *textures;		/**< Compatibility texture memory */
+    i830_memory *memory_manager;		/**< DRI memory manager aperture */
+ 
     int TexGranularity;
     int drmMinor;
     Bool have3DWindows;
diff --cc src/i830_accel.c
index c76c748,49a9c13..045b3b6
@@@ -226,13 -226,10 +226,13 @@@
     switch (buffer) {
  #ifdef XF86DRI
     case I830_SELECT_BACK:
-       pI830->bufferOffset = pI830->BackBuffer.Start;
+       pI830->bufferOffset = pI830->back_buffer->offset;
        break;
 +   case I830_SELECT_THIRD:
-       pI830->bufferOffset = pI830->ThirdBuffer.Start;
++      pI830->bufferOffset = pI830->third_buffer->offset;
 +      break;
     case I830_SELECT_DEPTH:
-       pI830->bufferOffset = pI830->DepthBuffer.Start;
+       pI830->bufferOffset = pI830->depth_buffer->offset;
        break;
  #endif
     default:
diff --cc src/i830_display.c
index 04159e7,d0b21a9..f5a2faa
@@@ -358,34 -387,9 +387,34 @@@
          OUTREG(dspsurf, Start);
  	(void) INREG(dspsurf);
      } else {
- 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
+ 	OUTREG(dspbase, Start + Offset);
  	(void) INREG(dspbase);
      }
 +
 +#ifdef XF86DRI
 +    if (pI830->directRenderingEnabled) {
 +	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
 +
 +	switch (pipe) {
 +	case 0:
 +	    sPriv->pipeA_x = x;
 +	    sPriv->pipeA_y = y;
 +	    sPriv->pipeA_w = crtc->mode.HDisplay;
 +	    sPriv->pipeA_h = crtc->mode.VDisplay;
 +	    break;
 +	case 1:
 +	    sPriv->pipeB_x = x;
 +	    sPriv->pipeB_y = y;
 +	    sPriv->pipeB_w = crtc->mode.HDisplay;
 +	    sPriv->pipeB_h = crtc->mode.VDisplay;
 +	    break;
 +	default:
 +	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 +		       "Can't update pipe %d in SAREA\n", pipe);
 +	    break;
 +	}
 +    }
 +#endif
  }
  
  /**
diff --cc src/i830_dri.c
index dba1a07,f81251a..d69ab3f
@@@ -1059,61 -1022,6 +1056,61 @@@
     }
  }
  
 +#ifdef DAMAGE
 +/* This should be done *before* XAA syncs,
 + * Otherwise will have to sync again???
 + */
 +static void
 +I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, CARD32 dst)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
 +
 +   if (pScrn->bitsPerPixel == 32) {
 +      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
 +	     XY_SRC_COPY_BLT_WRITE_RGB);
 +      br13 |= 3 << 24;
 +   } else {
 +      cmd = (XY_SRC_COPY_BLT_CMD);
 +      br13 |= 1 << 24;
 +   }
 +
 +   for (i = 0 ; i < num ; i++, pbox++) {
 +      BEGIN_LP_RING(8);
 +      OUT_RING(cmd);
 +      OUT_RING(br13);
 +      OUT_RING((pbox->y1 << 16) | pbox->x1);
 +      OUT_RING((pbox->y2 << 16) | pbox->x2);
 +      OUT_RING(dst);
 +      OUT_RING((pbox->y1 << 16) | pbox->x1);
 +      OUT_RING(br13 & 0xffff);
-       OUT_RING(pI830->FrontBuffer.Start);
++      OUT_RING(pI830->front_buffer->offset);
 +      ADVANCE_LP_RING();
 +   }
 +}
 +
 +static void
 +I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
 +{
 +   I830Ptr pI830 = I830PTR(pScrn);
 +   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
 +
 +   /* Don't want to do this when no 3d is active and pages are
 +    * right-way-round :
 +    */
 +   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
 +      return;
 +
-    I830DRIDoRefreshArea(pScrn, num, pbox, pI830->BackBuffer.Start);
++   I830DRIDoRefreshArea(pScrn, num, pbox, pI830->back_buffer->offset);
 +
 +   if (pI830->TripleBuffer) {
-       I830DRIDoRefreshArea(pScrn, num, pbox, pI830->ThirdBuffer.Start);
++      I830DRIDoRefreshArea(pScrn, num, pbox, pI830->third_buffer->offset);
 +   }
 +
 +   DamageEmpty(pI830->pDamage);
 +}
 +#endif
 +
  static void
  I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
  		   DRIContextType oldContextType, void *oldContext,
@@@ -1582,14 -1458,17 +1580,19 @@@
  
     sarea->width = pScreen->width;
     sarea->height = pScreen->height;
-    sarea->back_offset = pI830->BackBuffer.Start;
-    sarea->back_size = pI830->BackBuffer.Size;
-    sarea->third_offset = pI830->ThirdBuffer.Start;
-    sarea->third_size = pI830->ThirdBuffer.Size;
-    sarea->depth_offset = pI830->DepthBuffer.Start;
-    sarea->depth_size = pI830->DepthBuffer.Size;
-    sarea->tex_offset = pI830->TexMem.Start;
-    sarea->tex_size = pI830->TexMem.Size;
+    sarea->back_offset = pI830->back_buffer->offset;
+    sarea->back_size = pI830->back_buffer->size;
++   sarea->third_offset = pI830->third_buffer->offset;
++   sarea->third_size = pI830->third_buffer->size;
+    sarea->depth_offset = pI830->depth_buffer->offset;
+    sarea->depth_size = pI830->depth_buffer->size;
+    if (pI830->textures != NULL) {
+       sarea->tex_offset = pI830->textures->offset;
+       sarea->tex_size = pI830->textures->size;
+    } else {
+       sarea->tex_offset = 0;
+       sarea->tex_size = 0;
+    }
     sarea->log_tex_granularity = pI830->TexGranularity;
     sarea->pitch = pScrn->displayWidth;
     sarea->virtualX = pScrn->virtualX;
diff --cc src/i830_driver.c
index c950149,ac4e38c..8379b6b
@@@ -854,11 -837,9 +839,8 @@@
     char *s;
     pointer pVBEModule = NULL;
     const char *chipname;
 -   Bool enable;
     int num_pipe;
     int max_width, max_height;
- #ifdef XF86DRI
-    unsigned long savedMMSize;
- #endif
  
     if (pScrn->numEntities != 1)
        return FALSE;
@@@ -2490,7 -2136,250 +2147,254 @@@
     pI830 = I830PTR(pScrn);
     hwp = VGAHWPTR(pScrn);
  
-    pScrn->displayWidth = pI830->displayWidth;
+    pScrn->displayWidth = (pScrn->virtualX + 63) & ~63;
+ 
+    /*
+     * The "VideoRam" config file parameter specifies the maximum amount of
+     * memory that will be used/allocated.  When not present, we allow the
+     * driver to allocate as much memory as it wishes to satisfy its
+     * allocations, but if agpgart support isn't available, it gets limited
+     * to the amount of pre-allocated ("stolen") memory.
+     *
+     * Note that in using this value for allocator initialization, we're
+     * limiting aperture allocation to the VideoRam option, rather than limiting
+     * actual memory allocation, so alignment and things will cause less than
+     * VideoRam to be actually used.
+     */
+    if (pI830->pEnt->device->videoRam == 0) {
+       from = X_DEFAULT;
+       pScrn->videoRam = pI830->FbMapSize / KB(1);
+    } else {
+       from = X_CONFIG;
+       pScrn->videoRam = pI830->pEnt->device->videoRam;
+    }
+ 
+    /* Limit videoRam to how much we might be able to allocate from AGP */
+    sys_mem = I830CheckAvailableMemory(pScrn);
+    if (sys_mem == -1) {
+       if (pScrn->videoRam > pI830->stolen_size / KB(1)) {
+ 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		    "/dev/agpgart is either not available, or no memory "
+ 		    "is available\nfor allocation.  "
+ 		    "Using pre-allocated memory only.\n");
+ 	 pScrn->videoRam = pI830->stolen_size / KB(1);
+       }
+       pI830->StolenOnly = TRUE;
+    } else {
+       if (sys_mem + (pI830->stolen_size / 1024) < pScrn->videoRam) {
+ 	 pScrn->videoRam = sys_mem + (pI830->stolen_size / 1024);
+ 	 from = X_PROBED;
+ 	 if (sys_mem + (pI830->stolen_size / 1024) <
+ 	     pI830->pEnt->device->videoRam)
+ 	 {
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		       "VideoRAM reduced to %d kByte "
+ 		       "(limited to available sysmem)\n", pScrn->videoRam);
+ 	 }
+       }
+    }
+ 
+    /* Limit video RAM to the actual aperture size */
+    if (pScrn->videoRam > pI830->FbMapSize / 1024) {
+       pScrn->videoRam = pI830->FbMapSize / 1024;
+       if (pI830->FbMapSize / 1024 < pI830->pEnt->device->videoRam) {
+ 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		    "VideoRam reduced to %d kByte (limited to aperture "
+ 		    "size)\n",
+ 		    pScrn->videoRam);
+       }
+    }
+ 
+    /* Make sure it's on a page boundary */
+    if (pScrn->videoRam & 3) {
+       xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "VideoRam reduced to %d KB "
+ 		 "(page aligned - was %d KB)\n",
+ 		 pScrn->videoRam & ~3, pScrn->videoRam);
+       pScrn->videoRam &= ~3;
+    }
+ 
+    /* Set up our video memory allocator for the chosen videoRam */
+    if (!i830_allocator_init(pScrn, 0, pScrn->videoRam * KB(1))) {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ 		 "Couldn't initialize video memory allocator\n");
+       PreInitCleanup(pScrn);
+       return FALSE;
+    }
+ 
+    xf86DrvMsg(pScrn->scrnIndex,
+ 	      pI830->pEnt->device->videoRam ? X_CONFIG : X_DEFAULT,
+ 	      "VideoRam: %d KB\n", pScrn->videoRam);
+ 
+    if (xf86GetOptValInteger(pI830->Options, OPTION_CACHE_LINES,
+ 			    &(pI830->CacheLines))) {
+       xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "Requested %d cache lines\n",
+ 		 pI830->CacheLines);
+    } else {
+       pI830->CacheLines = -1;
+    }
+ 
+    pI830->disableTiling = FALSE;
+ 
+    if (I830IsPrimary(pScrn)) {
+       /* Alloc our pointers for the primary head */
+       if (!pI830->LpRing)
+          pI830->LpRing = xcalloc(1, sizeof(I830RingBuffer));
+       if (!pI830->overlayOn)
+          pI830->overlayOn = xalloc(sizeof(Bool));
+       if (!pI830->used3D)
+          pI830->used3D = xalloc(sizeof(int));
+       if (!pI830->LpRing || !pI830->overlayOn || !pI830->used3D) {
+          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ 		 "Could not allocate primary data structures.\n");
+          return FALSE;
+       }
+       *pI830->overlayOn = FALSE;
+       if (pI830->entityPrivate)
+          pI830->entityPrivate->XvInUse = -1;
+    } else {
+       /* Make our second head point to the first heads structures */
+       pI8301 = I830PTR(pI830->entityPrivate->pScrn_1);
+       pI830->LpRing = pI8301->LpRing;
+       pI830->overlay_regs = pI8301->overlay_regs;
+       pI830->overlayOn = pI8301->overlayOn;
+       pI830->used3D = pI8301->used3D;
+    }
+ 
+ #if defined(XF86DRI)
+    /*
+     * If DRI is potentially usable, check if there is enough memory available
+     * for it, and if there's also enough to allow tiling to be enabled.
+     */
+ 
+    if (!I830CheckDRIAvailable(pScrn)) {
+       pI830->directRenderingDisabled = TRUE;
+       pI830->mmSize = 0;
+    }
+ 
+    if (!pI830->directRenderingDisabled) {
+       int savedDisplayWidth = pScrn->displayWidth;
+       Bool tiled = FALSE;
+ 
+ #ifdef I830_XV
+       /*
+        * Set this so that the overlay allocation is factored in when
+        * appropriate.
+        */
+       pI830->XvEnabled = !pI830->XvDisabled;
+ #endif
+ 
+       if (IS_I965G(pI830)) {
+ 	 int tile_pixels = 512 / pI830->cpp;
+ 	 pScrn->displayWidth = (pScrn->displayWidth + tile_pixels - 1) &
+ 	    ~(tile_pixels - 1);
+ 	 tiled = TRUE;
+       } else {
+ 	 /* Good pitches to allow tiling.  Don't care about pitches < 1024
+ 	  * pixels.
+ 	  */
+ 	 static const int pitches[] = {
+ 	    1024,
+ 	    2048,
+ 	    4096,
+ 	    8192,
+ 	    0
+ 	 };
+ 
+ 	 for (i = 0; pitches[i] != 0; i++) {
+ 	    if (pitches[i] >= pScrn->displayWidth) {
+ 	       pScrn->displayWidth = pitches[i];
+ 	       tiled = TRUE;
+ 	       break;
+ 	    }
+ 	 }
+       }
+ 
+       /* Attempt several rounds of allocation to get 2d and 3d memory to fit:
+        *
+        * 0: tiled, large memory manager
+        * 1: tiled, small memory manager
+        * 2: untiled, large
+        * 3: untiled, small
+        */
+ 
+       pI830->disableTiling = FALSE;
+       savedMMSize = pI830->mmSize;
+       for (i = 0; i < 4; i++) {
+ 	 if (!tiled && i < 2)
+ 	    continue;
+ 
+ 	 if (i >= 2) {
+ 	    /* For further allocations, disable tiling */
+ 	    pI830->disableTiling = TRUE;
+ 	    pScrn->displayWidth = savedDisplayWidth;
++	    if (pI830->allowPageFlip)
++	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++			  "Couldn't allocate tiled memory, page flipping "
++			  "disabled\n");
+ 	    pI830->allowPageFlip = FALSE;
+ 	 }
+ 
+ 	 if (i & 1) {
+ 	    /* For this allocation, switch to a smaller DRI memory manager
+ 	     * size.
+ 	     */
+ 	    pI830->mmSize = I830_MM_MINPAGES * GTT_PAGE_SIZE;
+ 	 } else {
+ 	    pI830->mmSize = savedMMSize;
+ 	 }
+ 
+ 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 		    "Attempting memory allocation with %s buffers and \n"
+ 		    "\t       %s DRI memory manager reservation:\n",
+ 		    (i & 2) ? "untiled" : "tiled",
+ 		    (i & 1) ? "small" : "large");
+ 
+ 	 if (i830_allocate_2d_memory(pScrn) &&
+ 	     i830_allocate_3d_memory(pScrn))
+ 	 {
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Success.\n");
+ 	    if (pScrn->displayWidth != savedDisplayWidth) {
+ 	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ 			  "Increasing the scanline pitch to allow tiling mode "
+ 			  "(%d -> %d).\n",
+ 			  savedDisplayWidth, pScrn->displayWidth);
+ 	    }
+ 	    allocation_done = TRUE;
+ 	    break;
+ 	 }
+ 
+ 	 i830_reset_allocations(pScrn);
+       }
+ 
+       if (i == 4) {
+ 	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		    "Not enough video memory.  Disabling DRI.\n");
+ 	 pI830->mmSize = 0;
+ 	 pI830->directRenderingDisabled = TRUE;
+       }
+    } else
+ #endif
+       pI830->disableTiling = TRUE; /* no DRI - so disableTiling */
+ 
+    if (!allocation_done) {
+       if (!i830_allocate_2d_memory(pScrn)) {
+ 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ 		    "Couldn't allocate video memory\n");
+ 	 return FALSE;
+       }
+       allocation_done = TRUE;
+    }
+ 
+    i830_describe_allocations(pScrn, 1, "");
+ 
+    if (!IS_I965G(pI830) && pScrn->displayWidth > 2048) {
+       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ 		 "Cannot support DRI with frame buffer width > 2048.\n");
+       pI830->disableTiling = TRUE;
+       pI830->directRenderingDisabled = TRUE;
+    }
+ 
+    pScrn->displayWidth = pScrn->displayWidth;
  
  #ifdef HAS_MTRR_SUPPORT
     {
@@@ -2663,30 -2512,9 +2527,12 @@@
     pI830->directRenderingEnabled = FALSE;
  #endif
  
-    /*
-     * After the 3D allocations have been done, see if there's any free space
-     * that can be added to the framebuffer allocation.
-     */
-    if (I830IsPrimary(pScrn)) {
-       I830Allocate2DMemory(pScrn, 0);
- 
-       DPRINTF(PFX, "assert(if(!I830DoPoolAllocation(pScrn, pI830->StolenPool)))\n");
-       if (!I830DoPoolAllocation(pScrn, &(pI830->StolenPool)))
-          return FALSE;
- 
-       DPRINTF(PFX, "assert( if(!I830FixupOffsets(pScrn)) )\n");
-       if (!I830FixupOffsets(pScrn))
-          return FALSE;
-    }
- 
  #ifdef XF86DRI
-    if (pI830->directRenderingEnabled) {
-       I830SetupMemoryTiling(pScrn);
+    if (pI830->directRenderingEnabled)
        pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
-    }
 +
 +   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n",
 +	      pI830->allowPageFlip ? "en" : "dis");
  #endif
  
     DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
diff --cc src/i830_memory.c
index a952b70,5cddf17..f5cffba
@@@ -62,259 -107,514 +107,521 @@@
  #include "i830.h"
  #include "i810_reg.h"
  
- static int nextTile = 0;
- static unsigned int tileGeneration = -1;
+ #define ALIGN(i,m)    (((i) + (m) - 1) & ~((m) - 1))
+ 
+ enum tile_format {
+     TILING_NONE,
+     TILING_XMAJOR,
+     TILING_YMAJOR
+ };
+ 
+ static void i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
+ 			   unsigned int pitch, unsigned int size,
+ 			   enum tile_format tile_format);
  
+ /**
+  * Returns the fence size for a tiled area of the given size.
+  */
  static unsigned long
- GetBestTileAlignment(unsigned long size)
+ i830_get_fence_size(ScrnInfoPtr pScrn, unsigned long size)
  {
-    unsigned long i;
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned long i;
+     unsigned long start;
+ 
+     if (IS_I965G(pI830)) {
+ 	/* The 965 can have fences at any page boundary. */
+ 	return ALIGN(size, GTT_PAGE_SIZE);
+     } else {
+ 	/* Align the size to a power of two greater than the smallest fence
+ 	 * size.
+ 	 */
+ 	if (IS_I9XX(pI830))
+ 	    start = MB(1);
+ 	else
+ 	    start = KB(512);
  
-    for (i = KB(512); i < size; i <<= 1)
-       ;
+ 	for (i = start; i < size; i <<= 1)
+ 	    ;
  
-    if (i > MB(64))
-       i = MB(64);
+ 	return i;
+     }
+ }
+ 
+ static Bool
+ i830_bind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+ 
+     if (mem == NULL || mem->key == -1 || mem->bound || !pI830->gtt_acquired)
+ 	return TRUE;
  
-    return i;
+     if (xf86BindGARTMemory(pScrn->scrnIndex, mem->key, mem->agp_offset)) {
+ 	mem->bound = TRUE;
+ 	return TRUE;
+     } else {
+ 	return FALSE;
+     }
+ 
+     return TRUE;
  }
  
- /*
-  * Allocate memory from the given pool.  Grow the pool if needed and if
-  * possible.
+ static Bool
+ i830_unbind_memory(ScrnInfoPtr pScrn, i830_memory *mem)
+ {
+     if (mem == NULL || mem->key == -1 || !mem->bound)
+ 	return TRUE;
+ 
+     if (xf86UnbindGARTMemory(pScrn->scrnIndex, mem->key)) {
+ 	mem->bound = FALSE;
+ 	return TRUE;
+     } else {
+ 	return FALSE;
+     }
+ }
+ 
+ void
+ i830_free_memory(ScrnInfoPtr pScrn, i830_memory *mem)
+ {
+     if (mem == NULL)
+ 	return;
+ 
+     i830_unbind_memory(pScrn, mem);
+ 
+     /* Disconnect from the list of allocations */
+     if (mem->prev != NULL)
+ 	mem->prev->next = mem->next;
+     if (mem->next != NULL)
+ 	mem->next->prev = mem->prev;
+ 
+     /* Free any AGP memory. */
+     i830_unbind_memory(pScrn, mem);
+ 
+     if (mem->key != -1) {
+ 	xf86DeallocateGARTMemory(pScrn->scrnIndex, mem->key);
+ 	mem->key = -1;
+     }
+ 
+     xfree(mem->name);
+     xfree(mem);
+ }
+ 
+ /* Resets the state of the aperture allocator, freeing all memory that had
+  * been allocated.
   */
- static unsigned long
- AllocFromPool(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
- 	      long size, unsigned long alignment, int flags)
+ void
+ i830_reset_allocations(ScrnInfoPtr pScrn)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
-    long needed, start, end;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
- 
-    if (!result || !pool || !size)
-       return 0;
- 
-    /* Calculate how much space is needed. */
-    if (alignment <= GTT_PAGE_SIZE)
-       needed = size;
-    else {
-       if (flags & ALLOCATE_AT_BOTTOM) {
- 	 start = ROUND_TO(pool->Free.Start, alignment);
- 	 if (flags & ALIGN_BOTH_ENDS)
- 	    end = ROUND_TO(start + size, alignment);
- 	 else
- 	    end = start + size;
- 	 needed = end - pool->Free.Start;
-       } else {				/* allocate at top */
- 	 if (flags & ALIGN_BOTH_ENDS)
- 	    end = ROUND_DOWN_TO(pool->Free.End, alignment);
- 	 else
- 	    end = pool->Free.End;
- 
- 	 start = ROUND_DOWN_TO(end - size, alignment);
- 	 needed = end - start;
-       }
-    }
-    if (needed > pool->Free.Size) {
-       long extra;
-       /* See if the pool can be grown. */
-       if (pI830->StolenOnly && !dryrun)
- 	 return 0;
-       extra = needed - pool->Free.Size;
-       extra = ROUND_TO_PAGE(extra);
-       if (extra > pI830->FreeMemory) {
- 	 if (dryrun)
- 	    pI830->FreeMemory = extra;
- 	 else
- 	    return 0;
-       }
- 
-       if (!dryrun && ((long)extra > pI830->MemoryAperture.Size))
- 	 return 0;
- 
-       pool->Free.Size += extra;
-       pool->Free.End += extra;
-       pool->Total.Size += extra;
-       pool->Total.End += extra;
-       pI830->FreeMemory -= extra;
-       pI830->MemoryAperture.Start += extra;
-       pI830->MemoryAperture.Size -= extra;
-    }
-    if (flags & ALLOCATE_AT_BOTTOM) {
-       result->Start = ROUND_TO(pool->Free.Start, alignment);
-       pool->Free.Start += needed;
-       result->End = pool->Free.Start;
-    } else {
-       result->Start = ROUND_DOWN_TO(pool->Free.End - size, alignment);
-       pool->Free.End -= needed;
-       result->End = result->Start + needed;
-    }
-    pool->Free.Size = pool->Free.End - pool->Free.Start;
-    result->Size = result->End - result->Start;
-    result->Pool = pool;
-    result->Alignment = alignment;
-    return needed;
+     I830Ptr pI830 = I830PTR(pScrn);
+     xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+     int i;
+ 
+     /* While there is any memory between the start and end markers, free it. */
+     while (pI830->memory_list->next->next != NULL)
+ 	i830_free_memory(pScrn, pI830->memory_list->next);
+ 
+     /* Null out the pointers for all the allocations we just freed.  This is
+      * kind of gross, but at least it's just one place now.
+      */
+     for (i = 0; i < xf86_config->num_crtc; i++) {
+ 	I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
+ 
+ 	intel_crtc->cursor_mem = NULL;
+ 	intel_crtc->cursor_mem_argb = NULL;
+     }
+ 
+     pI830->front_buffer = NULL;
+     pI830->front_buffer_2 = NULL;
+     pI830->xaa_scratch = NULL;
+     pI830->xaa_scratch_2 = NULL;
+     pI830->exa_offscreen = NULL;
+     pI830->exa_965_state = NULL;
+     pI830->overlay_regs = NULL;
+     pI830->xaa_linear = NULL;
+     pI830->logical_context = NULL;
+     pI830->back_buffer = NULL;
++    pI830->third_buffer = NULL;
+     pI830->depth_buffer = NULL;
+     pI830->textures = NULL;
+     pI830->memory_manager = NULL;
+     pI830->LpRing->mem = NULL;
+ 
+     /* Reset the fence register allocation. */
+     pI830->next_fence = 0;
+     memset(pI830->fence, 0, sizeof(pI830->fence));
  }
  
- static unsigned long
- AllocFromAGP(ScrnInfoPtr pScrn, I830MemRange *result, long size,
- 	     unsigned long alignment, int flags)
+ void
+ i830_free_3d_memory(ScrnInfoPtr pScrn)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+ 
+     i830_free_memory(pScrn, pI830->back_buffer);
+     pI830->back_buffer = NULL;
++    i830_free_memory(pScrn, pI830->third_buffer);
++    pI830->third_buffer = NULL;
+     i830_free_memory(pScrn, pI830->depth_buffer);
+     pI830->depth_buffer = NULL;
+     i830_free_memory(pScrn, pI830->textures);
+     pI830->textures = NULL;
+     i830_free_memory(pScrn, pI830->memory_manager);
+     pI830->memory_manager = NULL;
+ }
+ 
+ /**
+  * Initialize's the driver's video memory allocator to allocate in the
+  * given range.
+  */
+ Bool
+ i830_allocator_init(ScrnInfoPtr pScrn, unsigned long offset,
+ 		    unsigned long size)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long start, end;
-    unsigned long newApStart, newApEnd;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
- 
-    if (!result || !size)
-       return 0;
- 
-    if ((flags & ALLOCATE_AT_BOTTOM) && pI830->StolenMemory.Size != 0) {
-       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		 "AllocFromAGP(): can't allocate from "
- 		 "bottom when there is stolen memory\n");
-       return 0;
-    }
- 
-    if (size > pI830->FreeMemory) {
-       if (dryrun)
- 	 pI830->FreeMemory = size;
-       else
- 	 return 0;
-    }
- 
-    /* Calculate offset */
-    if (flags & ALLOCATE_AT_BOTTOM) {
-       start = ROUND_TO(pI830->MemoryAperture.Start, alignment);
-       if (flags & ALIGN_BOTH_ENDS)
- 	 end = ROUND_TO(start + size, alignment);
-       else
- 	 end = start + size;
-       newApStart = end;
-       newApEnd = pI830->MemoryAperture.End;
-    } else {
-       if (flags & ALIGN_BOTH_ENDS)
- 	 end = ROUND_DOWN_TO(pI830->MemoryAperture.End, alignment);
-       else
- 	 end = pI830->MemoryAperture.End;
-       start = ROUND_DOWN_TO(end - size, alignment);
-       newApStart = pI830->MemoryAperture.Start;
-       newApEnd = start;
-    }
- 
-    if (!dryrun) {
-       if (newApStart > newApEnd)
- 	 return 0;
- 
-       if (flags & NEED_PHYSICAL_ADDR) 
- 	 result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
- 					      &(result->Physical));
-       else 
- 	 result->Key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
- 
-       if (result->Key == -1)
- 	 return 0;
-    }
- 
-    pI830->allocatedMemory += size;
-    pI830->MemoryAperture.Start = newApStart;
-    pI830->MemoryAperture.End = newApEnd;
-    pI830->MemoryAperture.Size = newApEnd - newApStart;
-    pI830->FreeMemory -= size;
-    result->Start = start;
-    result->End = start + size;
-    result->Size = size;
-    result->Offset = start;
-    result->Alignment = alignment;
-    result->Pool = NULL;
+     I830Ptr pI830 = I830PTR(pScrn);
+     i830_memory *start, *end;
+ 
+     start = xcalloc(1, sizeof(*start));
+     if (start == NULL)
+ 	return FALSE;
+     start->name = xstrdup("start marker");
+     if (start->name == NULL) {
+ 	xfree(start);
+ 	return FALSE;
+     }
+     end = xcalloc(1, sizeof(*end));
+     if (end == NULL) {
+ 	xfree(start->name);
+ 	xfree(start);
+ 	return FALSE;
+     }
+     end->name = xstrdup("end marker");
+     if (end->name == NULL) {
+ 	xfree(start->name);
+ 	xfree(start);
+ 	xfree(end);
+ 	return FALSE;
+     }
+ 
+     start->key = -1;
+     start->offset = offset;
+     start->end = start->offset;
+     start->size = 0;
+     start->next = end;
+     end->key = -1;
+     end->offset = offset + size;
+     end->end = end->offset;
+     end->size = 0;
+     end->prev = start;
+ 
+     pI830->memory_list = start;
+ 
+     return TRUE;
+ }
+ 
+ /* Allocate aperture space for the given size and alignment, and returns the
+  * memory allocation.
+  *
+  * Allocations are a minimum of a page, and will be at least page-aligned.
+  */
+ static i830_memory *
+ i830_allocate_aperture(ScrnInfoPtr pScrn, const char *name,
+ 		       long size, unsigned long alignment, int flags)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+     i830_memory *mem, *scan;
+ 
+     mem = xcalloc(1, sizeof(*mem));
+     if (mem == NULL)
+ 	return NULL;
+ 
+     /* No memory allocated to back the region */
+     mem->key = -1;
+ 
+     mem->name = xstrdup(name);
+     if (mem->name == NULL) {
+ 	xfree(mem);
+ 	return NULL;
+     }
+     /* Only allocate page-sized increments. */
+     size = ALIGN(size, GTT_PAGE_SIZE);
+     mem->size = size;
+ 
+     if (alignment < GTT_PAGE_SIZE)
+ 	alignment = GTT_PAGE_SIZE;
+ 
+     for (scan = pI830->memory_list; scan->next != NULL; scan = scan->next) {
+ 	mem->offset = scan->end;
+ 	/* For allocations requiring physical addresses, we have to use AGP
+ 	 * memory, so move the allocation up out of stolen memory.
+ 	 */
+ 	if ((flags & NEED_PHYSICAL_ADDR) && mem->offset < pI830->stolen_size)
+ 	    mem->offset = pI830->stolen_size;
+ 	mem->offset = ROUND_TO(mem->offset, alignment);
+ 
+ 	mem->end = mem->offset + size;
+ 	if (flags & ALIGN_BOTH_ENDS)
+ 	    mem->end = ROUND_TO(mem->end, alignment);
+ 	if (mem->end <= scan->next->offset)
+ 	    break;
+     }
+     if (scan->next == NULL) {
+ 	/* Reached the end of the list, and didn't find space */
+ 	xfree(mem->name);
+ 	xfree(mem);
+ 	return NULL;
+     }
+     /* Insert new allocation into the list */
+     mem->prev = scan;
+     mem->next = scan->next;
+     scan->next = mem;
+     mem->next->prev = scan;
+ 
+     return mem;
+ }
+ 
+ /**
+  * Allocates the AGP memory necessary for the part of a memory allocation not
+  * already covered by the stolen memory.
+  *
+  * The memory is automatically bound if we have the VT.
+  */
+ static Bool
+ i830_allocate_agp_memory(ScrnInfoPtr pScrn, i830_memory *mem, int flags)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned long size;
+ 
+     if (mem->key != -1)
+ 	return TRUE;
+ 
+     if (mem->offset + mem->size <= pI830->stolen_size &&
+ 	!(flags & NEED_PHYSICAL_ADDR))
+     {
+ 	return TRUE;
+     }
+ 
+     if (mem->offset < pI830->stolen_size)
+ 	mem->agp_offset = pI830->stolen_size;
+     else
+ 	mem->agp_offset = mem->offset;
+ 
+     size = mem->size - (mem->agp_offset - mem->offset);
+ 
+     if (flags & NEED_PHYSICAL_ADDR)
+ 	mem->key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 2,
+ 					  &mem->bus_addr);
+     else
+ 	mem->key = xf86AllocateGARTMemory(pScrn->scrnIndex, size, 0, NULL);
+     if (mem->key == -1 || ((flags & NEED_PHYSICAL_ADDR) && mem->bus_addr == 0))
+     {
+ 	return FALSE;
+     }
+ 
+     if (!i830_bind_memory(pScrn, mem)) {
+ 	return FALSE;
+     }
+ 
+     return TRUE;
+ }
+ 
+ 
+ /* Allocates video memory at the given size and alignment.
+  *
+  * The memory will be bound automatically when the driver is in control of the
+  * VT.
+  */
+ static i830_memory *
+ i830_allocate_memory(ScrnInfoPtr pScrn, const char *name,
+ 		     unsigned long size, unsigned long alignment, int flags)
+ {
+     i830_memory *mem;
+ 
+     mem = i830_allocate_aperture(pScrn, name, size, alignment, flags);
+     if (mem == NULL)
+ 	return NULL;
+ 
+     if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
+ 	i830_free_memory(pScrn, mem);
+ 	return NULL;
+     }
+ 
+     return mem;
+ }
+ 
+ /* Allocate a tiled region with the given size and pitch.
+  *
+  * As is, we might miss out on tiling some allocations on older hardware with
+  * large framebuffer size and a small aperture size, where the first
+  * allocations use a large alignment even though we've got fences to spare, and
+  * the later allocations can't find enough aperture space left.  We could do
+  * some search across all allocation options to fix this, probably, but that
+  * would be another rewrite.
+  */
+ static i830_memory *
+ i830_allocate_memory_tiled(ScrnInfoPtr pScrn, const char *name,
+ 			   unsigned long size, unsigned long pitch,
+ 			   unsigned long alignment, int flags,
+ 			   enum tile_format tile_format)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned long aper_size;
+     unsigned long aper_align;
+     i830_memory *mem;
+     int fence_divide, i;
+ 
+     if (tile_format == TILING_NONE)
+ 	return i830_allocate_memory(pScrn, name, size, alignment, flags);
+ 
+     /* Only allocate page-sized increments. */
+     size = ALIGN(size, GTT_PAGE_SIZE);
+ 
+     /* Check for maximum tiled region size */
+     if (IS_I9XX(pI830)) {
+ 	if (size > MB(128))
+ 	    return NULL;
+     } else {
+ 	if (size > MB(64))
+ 	    return NULL;
+     }
  
-    return size;
+     aper_size = i830_get_fence_size(pScrn, size);
+     if (IS_I965G(pI830)) {
+ 	aper_align = GTT_PAGE_SIZE;
+     } else {
+ 	/* The offset has to be aligned to at least the size of the fence
+ 	 * region.
+ 	 */
+ 	aper_align = aper_size;
+     }
+     if (aper_align < alignment)
+ 	aper_align = alignment;
+ 
+     fence_divide = 1;
+     mem = i830_allocate_aperture(pScrn, name, aper_size, aper_align, flags);
+     if (mem == NULL && !IS_I965G(pI830)) {
+ 	/* For the older hardware with stricter fencing limits, if we
+ 	 * couldn't allocate with the large alignment, try relaxing the
+ 	 * alignment requirements and using more fences to cover the area.
+ 	 */
+ 	for (fence_divide = 2; fence_divide <= 4 && mem == NULL;
+ 	     fence_divide *= 2)
+ 	{
+ 	    /* Check that it's not too small for fencing. */
+ 	    if (i830_get_fence_size(pScrn, aper_align / fence_divide) !=
+ 		aper_align / fence_divide)
+ 	    {
+ 		break;
+ 	    }
+ 
+ 	    mem = i830_allocate_aperture(pScrn, name, aper_size,
+ 					 aper_align / fence_divide, flags);
+ 	}
+     }
+ 
+     if (mem == NULL)
+ 	return NULL;
+ 
+     /* Make sure we've got enough free fence regs.  It's pretty hard to run
+      * out, luckily, with 8 even on older hardware and us only tiling
+      * front/back/depth buffers.
+      */
+     if (pI830->next_fence + fence_divide >
+ 	(IS_I965G(pI830) ? FENCE_NEW_NR : FENCE_NR))
+     {
+ 	i830_free_memory(pScrn, mem);
+ 	return NULL;
+     }
+ 
+     /* Allocate any necessary AGP memory to back this allocation */
+     if (!i830_allocate_agp_memory(pScrn, mem, flags)) {
+ 	i830_free_memory(pScrn, mem);
+ 	return NULL;
+     }
+ 
+     /* Set up the fence registers. */
+     for (i = 0; i < fence_divide; i++) {
+ 	i830_set_fence(pScrn, pI830->next_fence++,
+ 		       mem->offset + mem->size * i / fence_divide, pitch,
+ 		       mem->size / fence_divide, tile_format);
+     }
+ 
+     mem->size = size;
+ 
+     return mem;
+ }
+ 
+ static void
+ i830_describe_tiling(ScrnInfoPtr pScrn, int verbosity, const char *prefix,
+ 		     i830_memory *mem, unsigned int tiling_mode)
+ {
+     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		   "%s%s is %stiled\n", prefix, mem->name,
+ 		   (tiling_mode == FENCE_LINEAR) ? "not " : "");
  }
  
  void
- I830FreeVidMem(ScrnInfoPtr pScrn, I830MemRange *range)
+ i830_describe_allocations(ScrnInfoPtr pScrn, int verbosity, const char *prefix)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
+     I830Ptr pI830 = I830PTR(pScrn);
+     i830_memory *mem;
  
-    if (!range || range->Size == 0)
-       return;
+     if (pI830->memory_list == NULL) {
+ 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		       "%sMemory allocator not initialized\n", prefix);
+ 	return;
+     }
+ 
+     if (pI830->memory_list->next->next == NULL) {
+ 	xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		       "%sNo memory allocations\n", prefix);
+ 	return;
+     }
  
-    if (range->Key != -1)
-       xf86DeallocateGARTMemory(pScrn->scrnIndex, range->Key);
- 
-    if (range->Pool) {
-       /* 
-        * This code essentially resets what I830DoPoolAllocation() did.
-        * And if things are freed in the wrong order this can break wildly!
-        * USE CAUTION when changing anything here...
-        */
-       I830MemPool *Pool = range->Pool;
-       Pool->Total.End = pI830->StolenMemory.End;
- 
-       if (pI830->StolenOnly)
-          Pool->Free.End += range->Size;
-       else
-          Pool->Free.End = Pool->Total.End;
- 
-       if (Pool->Free.End < Pool->Free.Start) {
-          Pool->Free.End = Pool->Free.Start;
-       }
- 
-       Pool->Free.Size = Pool->Free.End - Pool->Free.Start;
-       Pool->Total.Size = Pool->Total.End - Pool->Total.Start;
- 
-       if (!pI830->StolenOnly) {
-          pI830->FreeMemory -= Pool->Free.Size;
-          pI830->MemoryAperture.Start -= (range->Size - Pool->Free.Size);
-          pI830->MemoryAperture.Size += (range->Size - Pool->Free.Size);
-       }
-    } else {
-       if (range->Alignment == GTT_PAGE_SIZE)
-          pI830->MemoryAperture.End = range->End;
-       else
-          pI830->MemoryAperture.End = range->End - range->Size + range->Alignment;
-       pI830->MemoryAperture.Size = pI830->MemoryAperture.End - pI830->MemoryAperture.Start;
-    }
- 
-    if (!pI830->StolenOnly)
-       pI830->FreeMemory += range->Size;
-    pI830->allocatedMemory -= range->Size;
- }
- 
- unsigned long
- I830AllocVidMem(ScrnInfoPtr pScrn, I830MemRange *result, I830MemPool *pool,
- 		long size, unsigned long alignment, int flags)
- {
-    I830Ptr pI830 = I830PTR(pScrn);
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
- 
-    if (!result)
-       return 0;
- 
-    /* Make sure these are initialised. */
-    result->Size = 0;
-    result->Key = -1;
- 
-    if (!size) {
-       return 0;
-    }
- 
-    switch (flags & FROM_MASK) {
-    case FROM_POOL_ONLY:
-       return AllocFromPool(pScrn, result, pool, size, alignment, flags);
-    case FROM_NEW_ONLY:
-       if (!dryrun && (pI830->StolenOnly || (pI830->FreeMemory <= 0)))
- 	 return 0;
-       return AllocFromAGP(pScrn, result, size, alignment, flags);
-    case FROM_ANYWHERE:
-       if ((!(flags & ALLOCATE_AT_BOTTOM) && (pI830->FreeMemory >= size)) ||
- 	  (flags & NEED_PHYSICAL_ADDR))
- 	 return AllocFromAGP(pScrn, result, size, alignment, flags);
-       else
- 	 return AllocFromPool(pScrn, result, pool, size, alignment, flags);
-    default:
-       /* Shouldn't happen. */
-       return 0;
-    }
+     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		   "%sMemory allocation layout:\n", prefix);
+ 
+     for (mem = pI830->memory_list->next; mem->next != NULL; mem = mem->next) {
+ 
+ 	if (mem->offset >= pI830->stolen_size &&
+ 	    mem->prev->offset < pI830->stolen_size)
+ 	{
+ 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 			   "%s0x%08lx:            end of stolen memory\n",
+ 			   prefix, pI830->stolen_size);
+ 	}
+ 
+ 	if (mem->bus_addr == 0) {
+ 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 			   "%s0x%08lx-0x%08lx: %s (%ld kB)\n", prefix,
+ 			   mem->offset, mem->end - 1, mem->name,
+ 			   mem->size / 1024);
+ 	} else {
+ 	    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 			   "%s0x%08lx-0x%08lx: %s (%ld kB, 0x%08lx physical)\n",
+ 			   prefix,
+ 			   mem->offset, mem->end - 1, mem->name,
+ 			   mem->size / 1024, mem->bus_addr);
+ 	}
+     }
+     xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+ 		   "%s0x%08lx:            end of aperture\n",
+ 		   prefix, pI830->FbMapSize);
+ 
+     if (pI830->front_buffer != NULL) {
+ 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->front_buffer,
+ 			     pI830->front_tiled);
+     }
+     if (pI830->back_buffer != NULL) {
+ 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->back_buffer,
+ 			     pI830->back_tiled);
+     }
++    if (pI830->third_buffer != NULL) {
++	i830_describe_tiling(pScrn, verbosity, prefix, pI830->third_buffer,
++			     pI830->third_tiled);
++    }
+     if (pI830->depth_buffer != NULL) {
+ 	i830_describe_tiling(pScrn, verbosity, prefix, pI830->depth_buffer,
+ 			     pI830->depth_tiled);
+     }
  }
  
  static Bool
@@@ -1045,567 -1042,293 +1049,344 @@@
  static unsigned int
  myLog2(unsigned int n)
  {
-    unsigned int log2 = 1;
+     unsigned int log2 = 1;
  
-    while (n > 1) {
-       n >>= 1;
-       log2++;
-    }
-    return log2;
+     while (n > 1) {
+ 	n >>= 1;
+ 	log2++;
+     }
+     return log2;
  }
  
- Bool
- I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags)
+ static Bool
+ i830_allocate_backbuffer(ScrnInfoPtr pScrn)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced, align = 0;
-    Bool tileable;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-    int lines;
-    int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
- 
-    /* Back Buffer */
-    memset(&(pI830->BackBuffer), 0, sizeof(pI830->BackBuffer));
-    pI830->BackBuffer.Key = -1;
-    tileable = !(flags & ALLOC_NO_TILING) &&
- 	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-    if (tileable) {
-       /* Make the height a multiple of the tile height (16) */
-       lines = (height + 15) / 16 * 16;
-    } else {
-       lines = height;
-    }
- 
-    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-    /*
-     * Try to allocate on the best tile-friendly boundaries.
-     */
-    alloced = 0;
-    if (tileable) {
-       align = GetBestTileAlignment(size);
-       for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
- 	 alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
- 				   &(pI830->StolenPool), size, align,
- 				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
- 				   ALIGN_BOTH_ENDS);
- 	 if (alloced >= size)
- 	    break;
-       }
-    }
-    if (alloced < size) {
-       /* Give up on trying to tile */
-       tileable = FALSE;
-       size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-       align = GTT_PAGE_SIZE;
-       alloced = I830AllocVidMem(pScrn, &(pI830->BackBuffer),
- 				&(pI830->StolenPool), size, align,
- 				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-    }
-    if (alloced < size) {
-       if (!dryrun) {
- 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		    "Failed to allocate back buffer space.\n");
-       }
-       return FALSE;
-    }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
- 		  "%sAllocated %ld kB for the back buffer at 0x%lx.\n", s,
- 		  alloced / 1024, pI830->BackBuffer.Start);
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
+     unsigned long size;
+     int height;
+ 
+     if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
+ 	height = pScrn->virtualY;
+     else
+ 	height = pScrn->virtualX;
+ 
+     /* Try to allocate on the best tile-friendly boundaries. */
+     if (!pI830->disableTiling && IsTileable(pScrn, pitch))
+     {
+ 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
+ 	pI830->back_buffer =
+ 	    i830_allocate_memory_tiled(pScrn, "back buffer",
+ 				       size, pitch, GTT_PAGE_SIZE,
+ 				       ALIGN_BOTH_ENDS,
+ 				       TILING_XMAJOR);
+ 	pI830->back_tiled = FENCE_XMAJOR;
+     }
+ 
+     /* Otherwise, just allocate it linear */
+     if (pI830->back_buffer == NULL) {
+ 	size = ROUND_TO_PAGE(pitch * height);
+ 	pI830->back_buffer = i830_allocate_memory(pScrn, "back buffer",
+ 						  size, GTT_PAGE_SIZE,
+ 						  ALIGN_BOTH_ENDS);
+ 	pI830->back_tiled = FENCE_LINEAR;
+     }
  
-    return TRUE;
+     if (pI830->back_buffer == NULL) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "Failed to allocate back buffer space.\n");
+ 	return FALSE;
+     }
+ 
+     return TRUE;
  }
  
- Bool
- I830AllocateThirdBuffer(ScrnInfoPtr pScrn, const int flags)
+ static Bool
++i830_allocate_thirdbuffer(ScrnInfoPtr pScrn)
 +{
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced, align = 0;
-    Bool tileable;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-    int lines;
-    int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
- 
-    /* Third Buffer */
-    memset(&(pI830->ThirdBuffer), 0, sizeof(pI830->ThirdBuffer));
-    pI830->ThirdBuffer.Key = -1;
-    tileable = !(flags & ALLOC_NO_TILING) &&
- 	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-    if (tileable) {
-       /* Make the height a multiple of the tile height (16) */
-       lines = (height + 15) / 16 * 16;
-    } else {
-       lines = height;
-    }
- 
-    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-    /*
-     * Try to allocate on the best tile-friendly boundaries.
-     */
-    alloced = 0;
-    if (tileable) {
-       align = GetBestTileAlignment(size);
-       for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
- 	 alloced = I830AllocVidMem(pScrn, &(pI830->ThirdBuffer),
- 				   &(pI830->StolenPool), size, align,
- 				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
- 				   ALIGN_BOTH_ENDS);
- 	 if (alloced >= size)
- 	    break;
-       }
-    }
-    if (alloced < size) {
-       /* Give up on trying to tile */
-       tileable = FALSE;
-       size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-       align = GTT_PAGE_SIZE;
-       alloced = I830AllocVidMem(pScrn, &(pI830->ThirdBuffer),
- 				&(pI830->StolenPool), size, align,
- 				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-    }
-    if (alloced < size) {
-       if (!dryrun) {
- 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		    "Failed to allocate third buffer space.\n");
-       }
-       return FALSE;
-    }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
- 		  "%sAllocated %ld kB for the third buffer at 0x%lx.\n", s,
- 		  alloced / 1024, pI830->ThirdBuffer.Start);
++    I830Ptr pI830 = I830PTR(pScrn);
++    unsigned int pitch = pScrn->displayWidth * pI830->cpp;
++    unsigned long size;
++    int height;
++
++    if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
++	height = pScrn->virtualY;
++    else
++	height = pScrn->virtualX;
++
++    /* Try to allocate on the best tile-friendly boundaries. */
++    if (!pI830->disableTiling && IsTileable(pScrn, pitch))
++    {
++	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
++	pI830->third_buffer =
++	    i830_allocate_memory_tiled(pScrn, "third buffer",
++				       size, pitch, GTT_PAGE_SIZE,
++				       ALIGN_BOTH_ENDS,
++				       TILING_XMAJOR);
++	pI830->third_tiled = FENCE_XMAJOR;
++    }
++
++    /* Otherwise, just allocate it linear */
++    if (pI830->third_buffer == NULL) {
++	size = ROUND_TO_PAGE(pitch * height);
++	pI830->third_buffer = i830_allocate_memory(pScrn, "third buffer",
++						   size, GTT_PAGE_SIZE,
++						   ALIGN_BOTH_ENDS);
++	pI830->third_tiled = FENCE_LINEAR;
++    }
 +
-    return TRUE;
++    if (pI830->third_buffer == NULL) {
++	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		   "Failed to allocate third buffer space.\n");
++	return FALSE;
++    }
++
++    return TRUE;
 +}
 +
- Bool
- I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags)
++static Bool
+ i830_allocate_depthbuffer(ScrnInfoPtr pScrn)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced, align = 0;
-    Bool tileable;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
-    int lines;
-    int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
- 
-    /* Depth Buffer -- same size as the back buffer */
-    memset(&(pI830->DepthBuffer), 0, sizeof(pI830->DepthBuffer));
-    pI830->DepthBuffer.Key = -1;
-    tileable = !(flags & ALLOC_NO_TILING) &&
- 	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-    if (tileable) {
-       /* Make the height a multiple of the tile height (16) */
-       lines = (height + 15) / 16 * 16;
-    } else {
-       lines = height;
-    }
- 
-    size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
-    /*
-     * Try to allocate on the best tile-friendly boundaries.
-     */
-    alloced = 0;
-    if (tileable) {
-       align = GetBestTileAlignment(size);
-       for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
- 	 alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
- 				   &(pI830->StolenPool), size, align,
- 				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
- 				   ALIGN_BOTH_ENDS);
- 	 if (alloced >= size)
- 	    break;
-       }
-    }
-    if (alloced < size) {
-       /* Give up on trying to tile */
-       tileable = FALSE;
-       size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
-       align = GTT_PAGE_SIZE;
-       alloced = I830AllocVidMem(pScrn, &(pI830->DepthBuffer),
- 				&(pI830->StolenPool), size, align,
- 				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-    }
-    if (alloced < size) {
-       if (!dryrun) {
- 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		    "Failed to allocate depth buffer space.\n");
-       }
-       return FALSE;
-    }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
- 		  "%sAllocated %ld kB for the depth buffer at 0x%lx.\n", s,
- 		  alloced / 1024, pI830->DepthBuffer.Start);
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned long size;
+     unsigned int pitch = pScrn->displayWidth * pI830->cpp;
+     int height;
+ 
+     /* XXX: this rotation stuff is bogus */
+     if (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180))
+ 	height = pScrn->virtualY;
+     else
+ 	height = pScrn->virtualX;
+ 
+     /* First try allocating it tiled */
+     if (!pI830->disableTiling && IsTileable(pScrn, pitch))
+     {
+ 	size = ROUND_TO_PAGE(pitch * ALIGN(height, 16));
+ 
+ 	pI830->depth_buffer =
+ 	    i830_allocate_memory_tiled(pScrn, "depth buffer", size, pitch,
+ 				       GTT_PAGE_SIZE, ALIGN_BOTH_ENDS,
+ 				       TILING_YMAJOR);
+ 	pI830->depth_tiled = FENCE_YMAJOR;
+     }
+ 
+     /* Otherwise, allocate it linear. */
+     if (pI830->depth_buffer == NULL) {
+ 	size = ROUND_TO_PAGE(pitch * height);
+ 	pI830->depth_buffer =
+ 	    i830_allocate_memory(pScrn, "depth buffer", size, GTT_PAGE_SIZE,
+ 				 0);
+ 	pI830->depth_tiled = FENCE_LINEAR;
+     }
  
-    return TRUE;
+     if (pI830->depth_buffer == NULL) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "Failed to allocate depth buffer space.\n");
+ 	return FALSE;
+     }
+ 
+     return TRUE;
  }
  
- Bool
- I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags)
+ static Bool
+ i830_allocate_texture_memory(ScrnInfoPtr pScrn)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced;
-    int i;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
- 
-    /* Allocate the remaining space for textures. */
-    memset(&(pI830->TexMem), 0, sizeof(pI830->TexMem));
-    pI830->TexMem.Key = -1;
- 
-    if (pI830->mmModeFlags & I830_KERNEL_TEX) {
- 
-       if (dryrun && pI830->pEnt->device->videoRam == 0) {
- 	 /* If we're laying out a default-sized allocation, then don't be
- 	  * too greedy and just ask for 32MB.
- 	  */
- 	 size = MB(32);
-       } else {
- 	 size = GetFreeSpace(pScrn);
-       }
-       if (dryrun && (size < MB(1)))
- 	 size = MB(1);
-       i = myLog2(size / I830_NR_TEX_REGIONS);
-       if (i < I830_LOG_MIN_TEX_REGION_SIZE)
- 	 i = I830_LOG_MIN_TEX_REGION_SIZE;
-       pI830->TexGranularity = i;
-       /* Truncate size */
-       size >>= i;
-       size <<= i;
-       if (size < KB(512)) {
- 	 if (!dryrun) {
+     I830Ptr pI830 = I830PTR(pScrn);
+     unsigned long size;
+     int i;
+ 
+     if (pI830->mmModeFlags & I830_KERNEL_MM) {
+ 	pI830->memory_manager =
+ 	    i830_allocate_aperture(pScrn, "DRI memory manager",
+ 				   pI830->mmSize * KB(1), GTT_PAGE_SIZE,
+ 				   ALIGN_BOTH_ENDS);
+ 	/* XXX: try memory manager size backoff here? */
+ 	if (pI830->memory_manager == NULL)
+ 	    return FALSE;
+     }
+ 
+     if (pI830->mmModeFlags & I830_KERNEL_TEX) {
+ 	/* XXX: auto-sizing */
+ 	size = MB(32);
+ 	i = myLog2(size / I830_NR_TEX_REGIONS);
+ 	if (i < I830_LOG_MIN_TEX_REGION_SIZE)
+ 	    i = I830_LOG_MIN_TEX_REGION_SIZE;
+ 	pI830->TexGranularity = i;
+ 	/* Truncate size */
+ 	size >>= i;
+ 	size <<= i;
+ 	if (size < KB(512)) {
  	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		       "Less than 512 kBytes for texture space (real %ld kBytes).\n", 
+ 		       "Less than 512 kBytes for texture space (real %ld"
+ 		       "kBytes).\n",
  		       size / 1024);
- 	 }
- 	 return FALSE;
-       }
-       alloced = I830AllocVidMem(pScrn, &(pI830->TexMem),
- 				&(pI830->StolenPool), size, GTT_PAGE_SIZE,
- 				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-       if (alloced < size) {
- 	 if (!dryrun) {
- 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ 	    return FALSE;
+ 	}
+ 	pI830->textures = i830_allocate_memory(pScrn, "textures", size,
+ 					       GTT_PAGE_SIZE, 0);
+ 	if (pI830->textures == NULL) {
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
  		       "Failed to allocate texture space.\n");
- 	 }
- 	 return FALSE;
-       }
-       xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
- 		     "%sAllocated %ld kB for textures at 0x%lx\n", s,
- 		     alloced / 1024, pI830->TexMem.Start);
-    }
+ 	    return FALSE;
+ 	}
+     }
  
-    return TRUE;
+     return TRUE;
  }
  
  Bool
- I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags)
+ i830_allocate_3d_memory(ScrnInfoPtr pScrn)
  {
-    I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long size, alloced;
-    Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
-    int verbosity = dryrun ? 4 : 1;
-    const char *s = dryrun ? "[dryrun] " : "";
- 
-    DPRINTF(PFX, "I830Allocate3DMemory\n");
- 
-    /* Space for logical context.  32k is fine for right now. */
-    memset(&(pI830->ContextMem), 0, sizeof(pI830->ContextMem));
-    pI830->ContextMem.Key = -1;
-    size = KB(32);
-    alloced = I830AllocVidMem(pScrn, &(pI830->ContextMem),
- 			     &(pI830->StolenPool), size, GTT_PAGE_SIZE,
- 			     flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
-    if (alloced < size) {
-       if (!dryrun) {
- 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		    "Failed to allocate logical context space.\n");
-       }
-       return FALSE;
-    }
-    xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
- 		  "%sAllocated %ld kB for the logical context at 0x%lx.\n", s,
- 		  alloced / 1024, pI830->ContextMem.Start);
- 
-    if (!I830AllocateBackBuffer(pScrn, flags))
-       return FALSE;
- 
-    if (pI830->TripleBuffer && !I830AllocateThirdBuffer(pScrn, flags))
-       return FALSE;
- 
-    if (!I830AllocateDepthBuffer(pScrn, flags))
-       return FALSE;
++    I830Ptr pI830 = I830PTR(pScrn);
 +
-    if (!I830AllocateTextureMemory(pScrn, flags))
-       return FALSE;
+     DPRINTF(PFX, "i830_allocate_3d_memory\n");
  
-    return TRUE;
- }
- #endif
+     if (!i830_allocate_backbuffer(pScrn))
+ 	return FALSE;
  
- /* Allocate pool space that isn't pre-allocated */
- Bool
- I830DoPoolAllocation(ScrnInfoPtr pScrn, I830MemPool *pool)
- {
-    I830Ptr pI830 = I830PTR(pScrn);
++    if (pI830->TripleBuffer && !i830_allocate_thirdbuffer(pScrn)) {
++       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
++		  "Failed to allocate third buffer, triple buffering "
++		  "inactive\n");
++    }
 +
-    DPRINTF(PFX, "I830DoPoolAllocation\n");
+     if (!i830_allocate_depthbuffer(pScrn))
+ 	return FALSE;
  
-    if (!pool)
-       return FALSE;
+     if (!i830_allocate_texture_memory(pScrn))
+ 	return FALSE;
  
-    /*
-     * Sanity check: there shouldn't be an allocation required when
-     * there is only stolen memory.
-     */
-    if (pI830->StolenOnly && (pool->Total.Size > pool->Fixed.Size)) {
-       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- 		 "I830DoPoolAllocation(): pool size is greater than the "
- 		 "preallocated size,\n\t"
- 		 "and there is no allocatable memory.\n");
-       return FALSE;
-    }
- 
-    if (pool->Total.Size > pool->Fixed.Size) {
-       pool->Allocated.Size = pool->Total.Size - pool->Fixed.Size;
-       pool->Allocated.Key = xf86AllocateGARTMemory(pScrn->scrnIndex, 
- 				   pool->Allocated.Size, 0, NULL);
-       if (pool->Allocated.Key == -1) {
- 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Pool allocation failed\n");
- 	 return FALSE;
-       }
-       pool->Allocated.Start = pool->Fixed.End;
-       pool->Allocated.End = pool->Total.Size;
-       pool->Allocated.Offset = pool->Allocated.Start;
-    } else
-       pool->Allocated.Key = -1;
-    return TRUE;
+     return TRUE;
  }
+ #endif
  
- static unsigned long topOfMem = 0;
- 
- /*
-  * These modify the way memory is positioned within the aperture.
-  *
-  * By default, memory allocated from the bottom or specifically within
-  * the pool at the bottom gets allocated from the "stolen pool", which is
-  * actually the stolen memory plus any extra allocated to make it a larger
-  * contiguous region.  Memory allocated from the AGP is allocated top-down
-  * from the end of the aperture space.  Memory allocated "from top" defaults
-  * to AGP if there is enough "free space".  The total allocation (stolen +
-  * extra) doesn't exceed the orignal pScrn->videoRam amount (this isn't true
-  * when memory allocated from AGP gets moved into the pool by one of the
-  * following options.
-  *
-  * XXX Write a better description.
+ #ifdef XF86DRI
+ /**
+  * Sets up a fence area for the hardware.
   *
+  * The fences control automatic tiled address swizzling for CPU access of the
+  * framebuffer.
   */
- #define PACK_RANGES 0
- #define POOL_RANGES 0
+ static void
+ i830_set_fence(ScrnInfoPtr pScrn, int nr, unsigned int offset,
+ 	       unsigned int pitch, unsigned int size,
+ 	       enum tile_format tile_format)
+ {
+     I830Ptr pI830 = I830PTR(pScrn);
+     CARD32 val;
+     CARD32 fence_mask = 0;
+     unsigned int fence_pitch;
  
- Bool
- I830FixOffset(ScrnInfoPtr pScrn, I830MemRange *mem)
- {
- #if POOL_RANGES
-    I830Ptr pI830 = I830PTR(pScrn);
- #endif
+     DPRINTF(PFX, "i830_set_fence(): %d, 0x%08x, %d, %d kByte\n",
+ 	    nr, offset, pitch, size / 1024);
  
-    if (!mem)
-       return FALSE;
+     assert(tile_format != TILING_NONE);
  
-    if (mem->Pool && mem->Key == -1 && mem->Start < 0) {
-       mem->Start = mem->Pool->Total.End + mem->Start;
-       mem->End = mem->Start + mem->Size;
-    }
- #if PACK_RANGES
-    /*
-     * Map AGP-allocated areas at the top of the stolen area, resulting in
-     * a contiguous region in the aperture.  Normally most AGP-allocated areas
-     * will be at the top of the aperture, making alignment requirements
-     * easier to achieve.  This optin is primarily for debugging purposes,
-     * and using this option can break any special alignment requirements.
-     */
-    if (!mem->Pool && mem->Start != 0 && mem->Key != -1 && mem->Physical == 0 &&
- 	mem->Offset != 0) {
-       long diff;
-       if (mem->Offset != mem->Start)
- 	 ErrorF("mem %p, Offset != Start\n", mem);
-       diff = mem->Offset - topOfMem;
-       mem->Start -= diff;
-       mem->End -= diff;
-       mem->Offset -= diff;
-       topOfMem += mem->Size;
-    }
- #elif POOL_RANGES
-    /*
-     * Move AGP-allocated regions (that don't need a physical address) into
-     * the pre-allocated pool when there's enough space to do so.  Note: the
-     * AGP-allocated areas aren't freed.  This option is primarily for
-     * debugging purposes, and using it can break any special alignment
-     * requirements.
-     */
-    if (!mem->Pool && mem->Start >= pI830->StolenPool.Free.End &&
-        mem->Key != -1 && mem->Physical == 0 && mem->Offset != 0 &&
-        pI830->StolenPool.Free.Size >= mem->Size) {
-       long diff;
-       if (mem->Offset != mem->Start)
- 	 ErrorF("mem %p, Offset != Start\n", mem);
-       diff = mem->Offset - pI830->StolenPool.Free.Start;
-       mem->Start -= diff;
-       mem->End -= diff;
-       mem->Offset -= diff;
-       mem->Key = -1;
-       pI830->StolenPool.Free.Start += mem->Size;
-       pI830->StolenPool.Free.Size -= mem->Size;
-    }
- #endif
-    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- 	      "%p: Memory at offset 0x%08lx, size %ld kBytes\n", (void *)mem,
- 	      mem->Start, mem->Size / 1024);
-    return TRUE;
- }
+     if (IS_I965G(pI830)) {
+ 	if (nr < 0 || nr >= FENCE_NEW_NR) {
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		       "i830_set_fence(): fence %d out of range\n",nr);
+ 	    return;
+ 	}
+ 
+ 	switch (tile_format) {
+ 	case TILING_XMAJOR:
+             pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1;
+ 	    pI830->fence[nr] |= I965_FENCE_X_MAJOR;
+             break;
+ 	case TILING_YMAJOR:
+             /* YMajor can be 128B aligned but the current code dictates
+              * otherwise. This isn't a problem apart from memory waste.
+              * FIXME */
+             pI830->fence[nr] = (((pitch / 128) - 1) << 2) | offset | 1;
+ 	    pI830->fence[nr] |= I965_FENCE_Y_MAJOR;
+             break;
+ 	case TILING_NONE:
+             break;
+ 	}
  
- Bool
- I830FixupOffsets(ScrnInfoPtr pScrn)
- {
-    I830Ptr pI830 = I830PTR(pScrn);
-    xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
-    int i;
- 
-    DPRINTF(PFX, "I830FixupOffsets\n");
- 
-    topOfMem = pI830->StolenPool.Total.End;
-    if (pI830->entityPrivate && pI830->entityPrivate->pScrn_2)
-       I830FixOffset(pScrn, &(pI830->FrontBuffer2));
-    I830FixOffset(pScrn, &(pI830->FrontBuffer));
- 
-    for (i = 0; i < xf86_config->num_crtc; i++) {
-       I830CrtcPrivatePtr intel_crtc = xf86_config->crtc[i]->driver_private;
- 
-       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)
-       I830FixOffset(pScrn, &(pI830->Scratch2));
- #ifdef I830_XV
-    if (pI830->XvEnabled) {
-       I830FixOffset(pScrn, pI830->OverlayMem);
-       if (pI830->LinearAlloc)
-          I830FixOffset(pScrn, &(pI830->LinearMem));
-    }
- #endif
- #ifdef XF86DRI
-    if (pI830->directRenderingEnabled) {
-       I830FixOffset(pScrn, &(pI830->ContextMem));
-       I830FixOffset(pScrn, &(pI830->BackBuffer));
-       I830FixOffset(pScrn, &(pI830->ThirdBuffer));
-       I830FixOffset(pScrn, &(pI830->DepthBuffer));
-       if (pI830->mmModeFlags & I830_KERNEL_TEX) {
- 	 I830FixOffset(pScrn, &(pI830->TexMem));
-       }
-    }
- #endif
- #ifdef I830_USE_EXA
-    if (pI830->useEXA) {
-        I830FixOffset(pScrn, &(pI830->Offscreen));
-        if (IS_I965G(pI830))
-            I830FixOffset(pScrn, &(pI830->EXAStateMem));
+ 	/* The end marker is the address of the last page in the allocation. */
+ 	pI830->fence[FENCE_NEW_NR + nr] = offset + size - 4096;
+ 	return;
      }
- #endif
-    return TRUE;
- }
  
- #ifdef XF86DRI
- /* Tiled memory is good... really, really good...
-  *
-  * Need to make it less likely that we miss out on this - probably
-  * need to move the frontbuffer away from the 'guarenteed' alignment
-  * of the first memory segment, or perhaps allocate a discontigous
-  * framebuffer to get more alignment 'sweet spots'.
-  */
- static void
- SetFence(ScrnInfoPtr pScrn, int nr, unsigned int start, unsigned int pitch,
-          unsigned int size)
- {
-    I830Ptr pI830 = I830PTR(pScrn);
-    I830RegPtr i830Reg = &pI830->ModeReg;
-    CARD32 val;
-    CARD32 fence_mask = 0;
-    unsigned int fence_pitch;
- 
-    DPRINTF(PFX, "SetFence: %d, 0x%08x, %d, %d kByte\n",
- 	   nr, start, pitch, size / 1024);
- 
-    if (nr < 0 || nr > 7) {
-       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- 		 "SetFence: fence %d out of range\n",nr);
-       return;
-    }
+     if (nr < 0 || nr >= FENCE_NR) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "i830_set_fence(): fence %d out of range\n",nr);
+ 	return;
+     }
  
-    i830Reg->Fence[nr] = 0;
+     pI830->fence[nr] = 0;
  
-    if (IS_I9XX(pI830))
+     if (IS_I9XX(pI830))
     	fence_mask = ~I915G_FENCE_START_MASK;
-    else
+     else
     	fence_mask = ~I830_FENCE_START_MASK;
  
-    if (start & fence_mask) {
-       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- 		 "SetFence: %d: start (0x%08x) is not %s aligned\n",
- 		 nr, start, (IS_I9XX(pI830)) ? "1MB" : "512k");
-       return;
-    }
- 
-    if (start % size) {
-       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- 		 "SetFence: %d: start (0x%08x) is not size (%dk) aligned\n",
- 		 nr, start, size / 1024);
-       return;
-    }
- 
-    if (pitch & 127) {
-       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- 		 "SetFence: %d: pitch (%d) not a multiple of 128 bytes\n",
- 		 nr, pitch);
-       return;
-    }
+     if (offset & fence_mask) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "i830_set_fence(): %d: offset (0x%08x) is not %s aligned\n",
+ 		   nr, offset, (IS_I9XX(pI830)) ? "1MB" : "512k");
+ 	return;
+     }
+ 
+     if (offset % size) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "i830_set_fence(): %d: offset (0x%08x) is not size (%dk) "
+ 		   "aligned\n",
+ 		   nr, offset, size / 1024);
+ 	return;
+     }
+ 
+     if (pitch & 127) {
+ 	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ 		   "i830_set_fence(): %d: pitch (%d) not a multiple of 128 "
+ 		   "bytes\n",
+ 		   nr, pitch);
+ 	return;
+     }
+ 
+     val = offset | FENCE_VALID;
  
-    val = (start | FENCE_X_MAJOR | FENCE_VALID);
+     switch (tile_format) {
+     case TILING_XMAJOR:
+ 	val |= FENCE_X_MAJOR;
+ 	break;
+     case TILING_YMAJOR:
+ 	val |= FENCE_Y_MAJOR;
+ 	break;
+     case TILING_NONE:
+ 	break;
+     }
  
-    if (IS_I9XX(pI830)) {
+     if (IS_I9XX(pI830)) {
     	switch (size) {
- 	   case MB(1):
-       		val |= I915G_FENCE_SIZE_1M;
-       		break;
-    	   case MB(2):
-       		val |= I915G_FENCE_SIZE_2M;
-       		break;
-    	   case MB(4):
-       		val |= I915G_FENCE_SIZE_4M;
-       		break;
-    	   case MB(8):
-       		val |= I915G_FENCE_SIZE_8M;
-       		break;
-    	   case MB(16):
-       		val |= I915G_FENCE_SIZE_16M;
-       		break;
-    	   case MB(32):
-       		val |= I915G_FENCE_SIZE_32M;
-       		break;
-    	   case MB(64):
-       		val |= I915G_FENCE_SIZE_64M;
-       		break;
-    	   default:
-       		xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
- 		 "SetFence: %d: illegal size (%d kByte)\n", nr, size / 1024);
-       		return;
+ 	case MB(1):
+ 	    val |= I915G_FENCE_SIZE_1M;
+ 	    break;
+ 	case MB(2):
+ 	    val |= I915G_FENCE_SIZE_2M;
+ 	    break;
+ 	case MB(4):
+ 	    val |= I915G_FENCE_SIZE_4M;
+ 	    break;
+ 	case MB(8):
+ 	    val |= I915G_FENCE_SIZE_8M;
+ 	    break;
+ 	case MB(16):
+ 	    val |= I915G_FENCE_SIZE_16M;
+ 	    break;
+ 	case MB(32):
+ 	    val |= I915G_FENCE_SIZE_32M;
+ 	    break;
+ 	case MB(64):
+ 	    val |= I915G_FENCE_SIZE_64M;
+ 	    break;
+ 	default:
+ 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ 		       "i830_set_fence(): %d: illegal size (%d kByte)\n",
+ 		       nr, size / 1024);
+ 	    return;
     	}
      } else {
     	switch (size) {
diff --cc src/i830_xaa.c
index 9b11973,9ecf706..46ea7ec
@@@ -279,13 -279,17 +279,22 @@@
     if (IS_I965G(pI830)) {
        if (pI830->bufferOffset == pScrn->fbOffset && pI830->front_tiled == FENCE_XMAJOR)
           tiled = 1;
-       if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR)
+       if (pI830->back_buffer != NULL &&
+ 	  pI830->bufferOffset == pI830->back_buffer->offset &&
+ 	  pI830->back_tiled == FENCE_XMAJOR) {
           tiled = 1;
-       if (pI830->bufferOffset == pI830->ThirdBuffer.Start && pI830->third_tiled == FENCE_XMAJOR)
+       }
++      if (pI830->third_buffer != NULL &&
++	  pI830->bufferOffset == pI830->third_buffer->offset &&
++	  pI830->third_tiled == FENCE_XMAJOR) {
 +         tiled = 1;
++      }
        /* not really supported as it's always YMajor tiled */
-       if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR)
+       if (pI830->depth_buffer != NULL &&
+ 	  pI830->bufferOffset == pI830->depth_buffer->offset &&
+ 	  pI830->depth_tiled == FENCE_XMAJOR) {
           tiled = 1;
+       }
     }
  
     return tiled;
diff-tree 50ba1fff886a7f51b178ac6d3a1ba79a3014b214 (from 36cad3fcb65e3dcd88e58e301cd60adb121cb96b)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Mon Mar 5 10:22:07 2007 +0100

    Be more verbose when page flipping can't be enabled for various reasons.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index e546066..dba1a07 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1146,7 +1146,7 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 	 if (pI830->pDamage == NULL) {
 	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
                        "No screen damage record, page flipping disabled\n");
-            pI830->allowPageFlip = 0;
+            pI830->allowPageFlip = FALSE;
 	 } else {
 	    DamageRegister(&pPix->drawable, pI830->pDamage);
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 9bd7029..c950149 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -853,7 +853,6 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    int i;
    char *s;
    pointer pVBEModule = NULL;
-   Bool enable;
    const char *chipname;
    int num_pipe;
    int max_width, max_height;
@@ -1479,14 +1478,14 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 	      pI830->colorKey);
 #endif
 
-   pI830->allowPageFlip = FALSE;
-   enable = xf86ReturnOptValBool(pI830->Options, OPTION_PAGEFLIP, FALSE);
 #ifdef XF86DRI
-   if (!pI830->directRenderingDisabled) {
-      pI830->allowPageFlip = enable;
-      xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "page flipping %s\n",
-		 enable ? "enabled" : "disabled");
-   }
+   pI830->allowPageFlip = FALSE;
+   from = (!pI830->directRenderingDisabled &&
+	   xf86GetOptValBool(pI830->Options, OPTION_PAGEFLIP,
+			     &pI830->allowPageFlip)) ? X_CONFIG : X_DEFAULT;
+
+   xf86DrvMsg(pScrn->scrnIndex, from, "Will%s try to enable page flipping\n",
+	      pI830->allowPageFlip ? "" : " not");
 #endif
 
 #ifdef XF86DRI
@@ -1676,6 +1675,9 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
 			     -pI830->MemoryAperture.Size / 1024);
 	       }
 	       pScrn->displayWidth = savedDisplayWidth;
+	       if (pI830->allowPageFlip)
+		  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			     "Can't enable page flipping due to the above\n");
 	       pI830->allowPageFlip = FALSE;
 	    } else if (pScrn->displayWidth != savedDisplayWidth) {
 	       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -2682,6 +2684,9 @@ I830ScreenInit(int scrnIndex, ScreenPtr 
       I830SetupMemoryTiling(pScrn);
       pI830->directRenderingEnabled = I830DRIDoMappings(pScreen);
    }
+
+   xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Page Flipping %sabled\n",
+	      pI830->allowPageFlip ? "en" : "dis");
 #endif
 
    DPRINTF(PFX, "assert( if(!I830MapMem(pScrn)) )\n");
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 2d1cca9..a952b70 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1762,6 +1762,9 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		 "I830SetupMemoryTiling: Not tileable 0x%x\n",
 		 pScrn->displayWidth * pI830->cpp);
+      if (pI830->allowPageFlip)
+	 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		    "Can't enable page flipping due to the above\n");
       pI830->allowPageFlip = FALSE;
       return;
    }
@@ -1778,14 +1781,20 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 		       "Activating tiled memory for the front buffer\n");
             pI830->front_tiled = FENCE_XMAJOR;
 	 } else {
-	    pI830->allowPageFlip = FALSE;
 	    xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		       "MakeTiles failed for the front buffer\n");
+	    if (pI830->allowPageFlip)
+	       xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+			  "Can't enable page flipping due to the above\n");
+	    pI830->allowPageFlip = FALSE;
 	 }
       } else {
-	 pI830->allowPageFlip = FALSE;
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		 "Alignment bad for the front buffer\n");
+	 if (pI830->allowPageFlip)
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Can't enable page flipping due to the above\n");
+	 pI830->allowPageFlip = FALSE;
       }
    }
 
@@ -1803,6 +1812,9 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       } else {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		    "MakeTiles failed for the back buffer.\n");
+	 if (pI830->allowPageFlip)
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Can't enable page flipping due to the above\n");
 	 pI830->allowPageFlip = FALSE;
       }
    }
@@ -1815,6 +1827,9 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       } else {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
 		    "MakeTiles failed for the third buffer.\n");
+	 if (pI830->allowPageFlip)
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Can't enable page flipping due to the above\n");
 	 pI830->allowPageFlip = FALSE;
       }
    }
diff-tree 36cad3fcb65e3dcd88e58e301cd60adb121cb96b (from b5316fb2623e9630cbd58020e0a7c95bf354c587)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 28 17:52:42 2007 +0100

    Update vblank pipe setup when setting a mode.

diff --git a/src/i830_display.c b/src/i830_display.c
index 258897e..04159e7 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -864,6 +864,9 @@ i830_crtc_mode_set(xf86CrtcPtr crtc, Dis
     OUTREG(dspcntr_reg, dspcntr);
     /* Flush the plane changes */
     i830PipeSetBase(crtc, x, y);
+#ifdef XF86DRI
+   I830DRISetVBlankInterrupt (pScrn, TRUE);
+#endif
     
     i830WaitForVblank(pScrn);
 }
@@ -1041,9 +1044,6 @@ i830SetMode(ScrnInfoPtr pScrn, DisplayMo
 
     i830DescribeOutputConfiguration(pScrn);
 
-#ifdef XF86DRI
-   I830DRISetVBlankInterrupt (pScrn, TRUE);
-#endif
 done:
     i830DumpRegs (pScrn);
     i830_sdvo_dump(pScrn);
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3c8ec1a..9bd7029 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3085,10 +3085,6 @@ I830EnterVT(int scrnIndex, int flags)
    i830DumpRegs (pScrn);
    i830DescribeOutputConfiguration(pScrn);
 
-#ifdef XF86DRI
-   I830DRISetVBlankInterrupt (pScrn, TRUE);
-#endif
-
    ResetState(pScrn, TRUE);
    SetHWOperatingState(pScrn);
 
diff-tree b5316fb2623e9630cbd58020e0a7c95bf354c587 (from f5ab9e0ad3a65c972861dd53be6e33e1aac13191)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 28 17:50:56 2007 +0100

    I830DRIClipNotify: Fix initialization of crtcBox[1].[xy]2.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index afc7de0..e546066 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1523,8 +1523,8 @@ I830DRIClipNotify(ScreenPtr pScreen, Win
       crtcBox[0].y2 = crtcBox[0].y1 + sPriv->pipeA_h;
       crtcBox[1].x1 = sPriv->pipeB_x;
       crtcBox[1].y1 = sPriv->pipeB_y;
-      crtcBox[1].x2 = crtcBox[0].x1 + sPriv->pipeB_w;
-      crtcBox[1].y2 = crtcBox[0].y1 + sPriv->pipeB_h;
+      crtcBox[1].x2 = crtcBox[1].x1 + sPriv->pipeB_w;
+      crtcBox[1].y2 = crtcBox[1].y1 + sPriv->pipeB_h;
 
       for (i = 0; i < 2; i++) {
 	 for (j = 0; j < num; j++) {
diff-tree f5ab9e0ad3a65c972861dd53be6e33e1aac13191 (from 8cce74f195e5ef6ce5599ecd52f35bcfcb0d7913)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Feb 22 18:57:23 2007 +0100

    I830DRISwapContext: Some cleanups.
    
    Also call I830EmitFlush() when entering/leaving the server context. Doesn't
    seem to help for artifacts with page flipping and mixed 2D/3D unfortunately.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 6c91cdc..afc7de0 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1135,6 +1135,8 @@ I830DRISwapContext(ScreenPtr pScreen, DR
       pI830->LockHeld = 1;
       I830RefreshRing(pScrn);
 
+      I830EmitFlush(pScrn);
+
 #ifdef DAMAGE
       if (!pI830->pDamage && pI830->allowPageFlip) {
 	 PixmapPtr pPix  = pScreen->GetScreenPixmap(pScreen);
@@ -1159,10 +1161,12 @@ I830DRISwapContext(ScreenPtr pScreen, DR
    } else if (syncType == DRI_2D_SYNC &&
 	      oldContextType == DRI_NO_CONTEXT &&
 	      newContextType == DRI_2D_CONTEXT) {
-      pI830->LockHeld = 0;
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (out)\n");
 
+      if (!pScrn->vtSema)
+     	 return;
+
 #ifdef DAMAGE
       if (pI830->pDamage) {
 	 RegionPtr pDamageReg = DamageRegion(pI830->pDamage);
@@ -1181,6 +1185,10 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 	 }
       }
 #endif
+
+      I830EmitFlush(pScrn);
+
+      pI830->LockHeld = 0;
    } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
       ErrorF("i830DRISwapContext (other)\n");
 }
diff-tree 8cce74f195e5ef6ce5599ecd52f35bcfcb0d7913 (from f346549183a407a4bff6521ec2450dacb97442e9)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Feb 22 18:27:59 2007 +0100

    Do not sync DRI windows between pages when possible.

diff --git a/src/i830.h b/src/i830.h
index bbbb4a8..e26556f 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -310,6 +310,7 @@ typedef struct _I830Rec {
 
 #ifdef DAMAGE
    DamagePtr pDamage;
+   RegionRec driRegion;
 #endif
 #endif
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 65736cd..6c91cdc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -980,6 +980,10 @@ I830DRICloseScreen(ScreenPtr pScreen)
 
    DPRINTF(PFX, "I830DRICloseScreen\n");
 
+#ifdef DAMAGE
+   REGION_UNINIT(pScreen, &pI830->driRegion);
+#endif
+
    if (pI830DRI->irq) {
        drmCtlUninstHandler(pI830->drmSubFD);
        pI830DRI->irq = 0;
@@ -1164,10 +1168,16 @@ I830DRISwapContext(ScreenPtr pScreen, DR
 	 RegionPtr pDamageReg = DamageRegion(pI830->pDamage);
 
 	 if (pDamageReg) {
-	    int nrects = REGION_NUM_RECTS(pDamageReg);
+	    RegionRec region;
+	    int nrects;
 
-	    if (nrects)
-	       I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(pDamageReg));
+	    REGION_NULL(pScreen, &region);
+	    REGION_SUBTRACT(pScreen, &region, pDamageReg, &pI830->driRegion);
+
+	    if ((nrects = REGION_NUM_RECTS(&region)))
+	       I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(&region));
+
+	    REGION_UNINIT(pScreen, &region);
 	 }
       }
 #endif
@@ -1486,8 +1496,13 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
 static void
 I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
    unsigned pfMask = 0;
 
+   REGION_UNINIT(pScreen, &pI830->driRegion);
+   REGION_NULL(pScreen, &pI830->driRegion);
+
    if (num > 0) {
       drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
       BoxRec crtcBox[2];
@@ -1505,15 +1520,24 @@ I830DRIClipNotify(ScreenPtr pScreen, Win
 
       for (i = 0; i < 2; i++) {
 	 for (j = 0; j < num; j++) {
-	    if (ppWin[j] && RECT_IN_REGION(pScreen, &ppWin[j]->clipList,
-					   &crtcBox[i]) != rgnOUT)
-	       numvisible[i]++;
+	    WindowPtr pWin = ppWin[j];
+
+	    if (pWin) {
+	       if (RECT_IN_REGION(pScreen, &pWin->clipList, &crtcBox[i]) !=
+		   rgnOUT)
+		  numvisible[i]++;
+
+	       if (i == 0)
+		  REGION_UNION(pScreen, &pI830->driRegion, &pWin->clipList,
+			       &pI830->driRegion);
+	    }
 	 }
 
 	 if (numvisible[i] == 1)
 	    pfMask |= 1 << i;
       }
-   }
+   } else
+      REGION_NULL(pScreen, &pI830->driRegion);
 
    I830DRISetPfMask(pScreen, pfMask);
 }
diff-tree f346549183a407a4bff6521ec2450dacb97442e9 (from 0bee64f4bc7581de7ab28ca438581d215e85c610)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 21 09:19:54 2007 +0100

    intel.man: Fix typo.

diff --git a/man/intel.man b/man/intel.man
index 503b52a..05a91f7 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -170,7 +170,7 @@ Default for i810: The option is not used
 Default for i830 and above: Disabled.
 .TP
 .BI "Option \*qTripleBuffer\*q \*q" boolean \*q
-Enable support for triple flipping. This should improve 3D performance at the
+Enable support for triple buffering. This should improve 3D performance at the
 potential cost of worse performance with mixed 2D/3D. Also note that this gives
 no benefit without corresponding support in the Mesa 3D driver and may not give
 any benefit without page flipping either (see
diff-tree 0bee64f4bc7581de7ab28ca438581d215e85c610 (from 2212baa8454abb4c7948c3f2e20e337f831d1b86)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Feb 20 19:09:37 2007 +0100

    Add support for triple buffering using a third static buffer.
    
    Need to bump the DRI DDX version minor for the added SAREA fields.

diff --git a/man/intel.man b/man/intel.man
index 3f4cff8..503b52a 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -162,9 +162,22 @@ Default: 32768.
 .BI "Option \*qPageFlip\*q \*q" boolean \*q
 Enable support for page flipping. This should improve 3D performance at the
 potential cost of worse performance or artifacts with mixed 2D/3D. Also note
-that this gives no benefit without corresponding support in the Mesa 3D driver.
+that this gives no benefit without corresponding support in the Mesa 3D driver
+and may not give the full benefit without triple buffering (see
+.B "Option \*qTripleBuffer\*q"
+).
 Default for i810: The option is not used.
-Default for i9xx: Disabled.
+Default for i830 and above: Disabled.
+.TP
+.BI "Option \*qTripleBuffer\*q \*q" boolean \*q
+Enable support for triple flipping. This should improve 3D performance at the
+potential cost of worse performance with mixed 2D/3D. Also note that this gives
+no benefit without corresponding support in the Mesa 3D driver and may not give
+any benefit without page flipping either (see
+.B "Option \*qPageFlip\*q"
+).
+Default for i810: The option is not used.
+Default for i830 and above: Disabled.
 .TP
 .BI "Option \*qAccelMethod\*q \*q" string \*q
 Choose acceleration architecture, either "XAA" or "EXA".  XAA is the old
diff --git a/src/i830.h b/src/i830.h
index 78381fb..bbbb4a8 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -294,6 +294,7 @@ typedef struct _I830Rec {
    I830MemRange ContextMem;
 #ifdef XF86DRI
    I830MemRange BackBuffer;
+   I830MemRange ThirdBuffer;
    I830MemRange DepthBuffer;
    I830MemRange TexMem;
    int TexGranularity;
@@ -304,6 +305,7 @@ typedef struct _I830Rec {
 
    unsigned int front_tiled;
    unsigned int back_tiled;
+   unsigned int third_tiled;
    unsigned int depth_tiled;
 
 #ifdef DAMAGE
@@ -313,6 +315,7 @@ typedef struct _I830Rec {
 
    Bool NeedRingBufferLow;
    Bool allowPageFlip;
+   Bool TripleBuffer;
    Bool disableTiling;
 
    int backPitch;
@@ -511,6 +514,7 @@ typedef struct _I830Rec {
 #define I830_SELECT_FRONT	0
 #define I830_SELECT_BACK	1
 #define I830_SELECT_DEPTH	2
+#define I830_SELECT_THIRD	3
 
 /* I830 specific functions */
 extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
@@ -539,6 +543,7 @@ extern void i830_crtc_dpms_video(xf86Crt
 #ifdef XF86DRI
 extern Bool I830Allocate3DMemory(ScrnInfoPtr pScrn, const int flags);
 extern Bool I830AllocateBackBuffer(ScrnInfoPtr pScrn, const int flags);
+extern Bool I830AllocateThirdBuffer(ScrnInfoPtr pScrn, const int flags);
 extern Bool I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags);
 extern Bool I830AllocateTextureMemory(ScrnInfoPtr pScrn, const int flags);
 extern void I830SetupMemoryTiling(ScrnInfoPtr pScrn);
diff --git a/src/i830_accel.c b/src/i830_accel.c
index db3168a..c76c748 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -228,6 +228,9 @@ I830SelectBuffer(ScrnInfoPtr pScrn, int 
    case I830_SELECT_BACK:
       pI830->bufferOffset = pI830->BackBuffer.Start;
       break;
+   case I830_SELECT_THIRD:
+      pI830->bufferOffset = pI830->ThirdBuffer.Start;
+      break;
    case I830_SELECT_DEPTH:
       pI830->bufferOffset = pI830->DepthBuffer.Start;
       break;
diff --git a/src/i830_common.h b/src/i830_common.h
index 79455b6..f853ccd 100644
--- a/src/i830_common.h
+++ b/src/i830_common.h
@@ -130,6 +130,12 @@ typedef struct {
 	int pipeB_y;
 	int pipeB_w;
 	int pipeB_h;
+
+	/* Triple buffering */
+	drm_handle_t third_handle;
+	int third_offset;
+	int third_size;
+	unsigned int third_tiled;
 } drmI830Sarea;
 
 /* Flags for perf_boxes
diff --git a/src/i830_dri.c b/src/i830_dri.c
index d655183..65736cd 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -751,6 +751,20 @@ I830DRIMapScreenRegions(ScrnInfoPtr pScr
    xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Back Buffer = 0x%08x\n",
               (int)sarea->back_handle);
 
+   if (pI830->TripleBuffer) {
+      if (drmAddMap(pI830->drmSubFD,
+		    (drm_handle_t)(sarea->third_offset + pI830->LinearAddr),
+		    sarea->third_size, DRM_AGP, 0,
+		    (drmAddress) &sarea->third_handle) < 0) {
+	xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		   "[drm] drmAddMap(third_handle) failed. Disabling DRI\n");
+	DRICloseScreen(pScreen);
+	return FALSE;
+      }
+      xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Third Buffer = 0x%08x\n",
+		 (int)sarea->third_handle);
+   }
+
    if (drmAddMap(pI830->drmSubFD,
                  (drm_handle_t)sarea->depth_offset + pI830->LinearAddr,
                  sarea->depth_size, DRM_AGP, 0,
@@ -794,6 +808,10 @@ I830DRIUnmapScreenRegions(ScrnInfoPtr pS
       drmRmMap(pI830->drmSubFD, sarea->back_handle);
       sarea->back_handle = 0;
    }
+   if (sarea->third_handle) {
+      drmRmMap(pI830->drmSubFD, sarea->third_handle);
+      sarea->third_handle = 0;
+   }
    if (sarea->depth_handle) {
       drmRmMap(pI830->drmSubFD, sarea->depth_handle);
       sarea->depth_handle = 0;
@@ -870,6 +888,7 @@ I830DRIDoMappings(ScreenPtr pScreen)
    /* init to zero to be safe */
    sarea->front_handle = 0;
    sarea->back_handle = 0;
+   sarea->third_handle = 0;
    sarea->depth_handle = 0;
    sarea->tex_handle = 0;
 
@@ -1041,17 +1060,10 @@ I830DRIFinishScreenInit(ScreenPtr pScree
  * Otherwise will have to sync again???
  */
 static void
-I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+I830DRIDoRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox, CARD32 dst)
 {
    I830Ptr pI830 = I830PTR(pScrn);
    int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
-   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
-
-   /* Don't want to do this when no 3d is active and pages are
-    * right-way-round :
-    */
-   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
-      return;
 
    if (pScrn->bitsPerPixel == 32) {
       cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
@@ -1068,12 +1080,31 @@ I830DRIRefreshArea (ScrnInfoPtr pScrn, i
       OUT_RING(br13);
       OUT_RING((pbox->y1 << 16) | pbox->x1);
       OUT_RING((pbox->y2 << 16) | pbox->x2);
-      OUT_RING(pI830->BackBuffer.Start);
+      OUT_RING(dst);
       OUT_RING((pbox->y1 << 16) | pbox->x1);
       OUT_RING(br13 & 0xffff);
       OUT_RING(pI830->FrontBuffer.Start);
       ADVANCE_LP_RING();
    }
+}
+
+static void
+I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+   /* Don't want to do this when no 3d is active and pages are
+    * right-way-round :
+    */
+   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
+      return;
+
+   I830DRIDoRefreshArea(pScrn, num, pbox, pI830->BackBuffer.Start);
+
+   if (pI830->TripleBuffer) {
+      I830DRIDoRefreshArea(pScrn, num, pbox, pI830->ThirdBuffer.Start);
+   }
 
    DamageEmpty(pI830->pDamage);
 }
@@ -1160,6 +1191,13 @@ I830DRIInitBuffers(WindowPtr pWin, Regio
       I830SelectBuffer(pScrn, I830_SELECT_BACK);
       I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
 				  pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+
+      if (I830PTR(pScrn)->TripleBuffer) {
+	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
+	 I830SubsequentSolidFillRect(pScrn, pbox->x1, pbox->y1,
+				     pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+      }
+
       pbox++;
    }
 
@@ -1333,6 +1371,10 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
 
       I830SelectBuffer(pScrn, I830_SELECT_BACK);
       I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+      if (pI830->TripleBuffer) {
+	 I830SelectBuffer(pScrn, I830_SELECT_THIRD);
+	 I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
+      }
       if (!IS_I965G(pI830)) {
          I830SelectBuffer(pScrn, I830_SELECT_DEPTH);
          I830SubsequentScreenToScreenCopy(pScrn, x1, y1, destx, desty, w, h);
@@ -1492,6 +1534,7 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
 
    sarea->front_tiled = pI830->front_tiled;
    sarea->back_tiled = pI830->back_tiled;
+   sarea->third_tiled = pI830->third_tiled;
    sarea->depth_tiled = pI830->depth_tiled;
    sarea->rotated_tiled = FALSE;
 
@@ -1509,6 +1552,8 @@ I830UpdateDRIBuffers(ScrnInfoPtr pScrn, 
    sarea->height = pScreen->height;
    sarea->back_offset = pI830->BackBuffer.Start;
    sarea->back_size = pI830->BackBuffer.Size;
+   sarea->third_offset = pI830->ThirdBuffer.Start;
+   sarea->third_size = pI830->ThirdBuffer.Size;
    sarea->depth_offset = pI830->DepthBuffer.Start;
    sarea->depth_size = pI830->DepthBuffer.Size;
    sarea->tex_offset = pI830->TexMem.Start;
diff --git a/src/i830_dri.h b/src/i830_dri.h
index a140497..a2cf78e 100644
--- a/src/i830_dri.h
+++ b/src/i830_dri.h
@@ -9,8 +9,8 @@
 #define I830_MAX_DRAWABLES 256
 
 #define I830_MAJOR_VERSION 1
-#define I830_MINOR_VERSION 7
-#define I830_PATCHLEVEL 2
+#define I830_MINOR_VERSION 8
+#define I830_PATCHLEVEL 0
 
 #define I830_REG_SIZE 0x80000
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index d1f83e5..3c8ec1a 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -273,7 +273,8 @@ typedef enum {
    OPTION_CHECKDEVICES,
    OPTION_LINEARALLOC,
    OPTION_INTELTEXPOOL,
-   OPTION_INTELMMSIZE
+   OPTION_INTELMMSIZE,
+   OPTION_TRIPLEBUFFER,
 } I830Opts;
 
 static OptionInfoRec I830Options[] = {
@@ -292,6 +293,7 @@ static OptionInfoRec I830Options[] = {
    {OPTION_LINEARALLOC, "LinearAlloc",  OPTV_INTEGER,   {0},    FALSE},
    {OPTION_INTELTEXPOOL,"Legacy3D",     OPTV_BOOLEAN,	{0},	FALSE},
    {OPTION_INTELMMSIZE, "AperTexSize",  OPTV_INTEGER,	{0},	FALSE},
+   {OPTION_TRIPLEBUFFER, "TripleBuffer", OPTV_BOOLEAN,	{0},	FALSE},
    {-1,			NULL,		OPTV_NONE,	{0},	FALSE}
 };
 /* *INDENT-ON* */
@@ -1487,6 +1489,16 @@ I830PreInit(ScrnInfoPtr pScrn, int flags
    }
 #endif
 
+#ifdef XF86DRI
+   pI830->TripleBuffer = FALSE;
+   from =  (!pI830->directRenderingDisabled &&
+	    xf86GetOptValBool(pI830->Options, OPTION_TRIPLEBUFFER,
+			      &pI830->TripleBuffer)) ? X_CONFIG : X_DEFAULT;
+
+   xf86DrvMsg(pScrn->scrnIndex, from, "Triple buffering %sabled\n",
+	      pI830->TripleBuffer ? "en" : "dis");
+#endif
+
    /*
     * If the driver can do gamma correction, it should call xf86SetGamma() here.
     */
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 29d9d31..2d1cca9 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1118,6 +1118,69 @@ I830AllocateBackBuffer(ScrnInfoPtr pScrn
 }
 
 Bool
+I830AllocateThirdBuffer(ScrnInfoPtr pScrn, const int flags)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   unsigned long size, alloced, align = 0;
+   Bool tileable;
+   Bool dryrun = ((flags & ALLOCATE_DRY_RUN) != 0);
+   int verbosity = dryrun ? 4 : 1;
+   const char *s = dryrun ? "[dryrun] " : "";
+   int lines;
+   int height = (pI830->rotation & (RR_Rotate_0 | RR_Rotate_180)) ? pScrn->virtualY : pScrn->virtualX;
+
+   /* Third Buffer */
+   memset(&(pI830->ThirdBuffer), 0, sizeof(pI830->ThirdBuffer));
+   pI830->ThirdBuffer.Key = -1;
+   tileable = !(flags & ALLOC_NO_TILING) &&
+	      IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
+   if (tileable) {
+      /* Make the height a multiple of the tile height (16) */
+      lines = (height + 15) / 16 * 16;
+   } else {
+      lines = height;
+   }
+
+   size = ROUND_TO_PAGE(pScrn->displayWidth * lines * pI830->cpp);
+   /*
+    * Try to allocate on the best tile-friendly boundaries.
+    */
+   alloced = 0;
+   if (tileable) {
+      align = GetBestTileAlignment(size);
+      for (align = GetBestTileAlignment(size); align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
+	 alloced = I830AllocVidMem(pScrn, &(pI830->ThirdBuffer),
+				   &(pI830->StolenPool), size, align,
+				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+				   ALIGN_BOTH_ENDS);
+	 if (alloced >= size)
+	    break;
+      }
+   }
+   if (alloced < size) {
+      /* Give up on trying to tile */
+      tileable = FALSE;
+      size = ROUND_TO_PAGE(pScrn->displayWidth * height * pI830->cpp);
+      align = GTT_PAGE_SIZE;
+      alloced = I830AllocVidMem(pScrn, &(pI830->ThirdBuffer),
+				&(pI830->StolenPool), size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_TOP);
+   }
+   if (alloced < size) {
+      if (!dryrun) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		    "Failed to allocate third buffer space.\n");
+      }
+      return FALSE;
+   }
+   xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, verbosity,
+		  "%sAllocated %ld kB for the third buffer at 0x%lx.\n", s,
+		  alloced / 1024, pI830->ThirdBuffer.Start);
+
+   return TRUE;
+}
+
+Bool
 I830AllocateDepthBuffer(ScrnInfoPtr pScrn, const int flags)
 {
    I830Ptr pI830 = I830PTR(pScrn);
@@ -1271,6 +1334,9 @@ I830Allocate3DMemory(ScrnInfoPtr pScrn, 
    if (!I830AllocateBackBuffer(pScrn, flags))
       return FALSE;
 
+   if (pI830->TripleBuffer && !I830AllocateThirdBuffer(pScrn, flags))
+      return FALSE;
+
    if (!I830AllocateDepthBuffer(pScrn, flags))
       return FALSE;
 
@@ -1439,6 +1505,7 @@ I830FixupOffsets(ScrnInfoPtr pScrn)
    if (pI830->directRenderingEnabled) {
       I830FixOffset(pScrn, &(pI830->ContextMem));
       I830FixOffset(pScrn, &(pI830->BackBuffer));
+      I830FixOffset(pScrn, &(pI830->ThirdBuffer));
       I830FixOffset(pScrn, &(pI830->DepthBuffer));
       if (pI830->mmModeFlags & I830_KERNEL_TEX) {
 	 I830FixOffset(pScrn, &(pI830->TexMem));
@@ -1701,6 +1768,7 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
 
    pI830->front_tiled = FENCE_LINEAR;
    pI830->back_tiled = FENCE_LINEAR;
+   pI830->third_tiled = FENCE_LINEAR;
    pI830->depth_tiled = FENCE_LINEAR;
 
    if (pI830->allowPageFlip) {
@@ -1739,6 +1807,18 @@ I830SetupMemoryTiling(ScrnInfoPtr pScrn)
       }
    }
 
+   if (pI830->ThirdBuffer.Alignment >= KB(512)) {
+      if (MakeTiles(pScrn, &(pI830->ThirdBuffer), FENCE_XMAJOR)) {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "Activating tiled memory for the third buffer.\n");
+         pI830->third_tiled = FENCE_XMAJOR;
+      } else {
+	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+		    "MakeTiles failed for the third buffer.\n");
+	 pI830->allowPageFlip = FALSE;
+      }
+   }
+
    if (pI830->DepthBuffer.Alignment >= KB(512)) {
       if (MakeTiles(pScrn, &(pI830->DepthBuffer), FENCE_YMAJOR)) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
@@ -1825,6 +1905,8 @@ I830BindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
 	 if (!BindMemRange(pScrn, &(pI830->BackBuffer)))
 	    return FALSE;
+	 if (pI830->TripleBuffer && !BindMemRange(pScrn, &(pI830->ThirdBuffer)))
+	    return FALSE;
 	 if (!BindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
 	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
@@ -1919,6 +2001,8 @@ I830UnbindAGPMemory(ScrnInfoPtr pScrn)
 	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &(pI830->BackBuffer)))
 	    return FALSE;
+	 if (pI830->TripleBuffer && !UnbindMemRange(pScrn, &(pI830->ThirdBuffer)))
+	    return FALSE;
 	 if (!UnbindMemRange(pScrn, &(pI830->DepthBuffer)))
 	    return FALSE;
 	 if ((pI830->mmModeFlags & I830_KERNEL_TEX) && 
diff --git a/src/i830_xaa.c b/src/i830_xaa.c
index 5ef5d3c..9b11973 100644
--- a/src/i830_xaa.c
+++ b/src/i830_xaa.c
@@ -281,6 +281,8 @@ CheckTiling(ScrnInfoPtr pScrn)
          tiled = 1;
       if (pI830->bufferOffset == pI830->BackBuffer.Start && pI830->back_tiled == FENCE_XMAJOR)
          tiled = 1;
+      if (pI830->bufferOffset == pI830->ThirdBuffer.Start && pI830->third_tiled == FENCE_XMAJOR)
+         tiled = 1;
       /* not really supported as it's always YMajor tiled */
       if (pI830->bufferOffset == pI830->DepthBuffer.Start && pI830->depth_tiled == FENCE_XMAJOR)
          tiled = 1;
diff-tree 2212baa8454abb4c7948c3f2e20e337f831d1b86 (from fac8f2eb49de22abd853ca75f3c985d4d94e3633)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Feb 20 18:39:13 2007 +0100

    Don't mark page flipping as active when it really isn't.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index b368c99..d655183 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1382,8 +1382,11 @@ I830DRISetPfMask(ScreenPtr pScreen, int 
    I830Ptr pI830 = I830PTR(pScrn);
    drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
 
-   pSAREAPriv->pf_enabled = pI830->allowPageFlip;
-   pSAREAPriv->pf_active = pfMask;
+   if (pI830->allowPageFlip && pfMask) {
+      pSAREAPriv->pf_enabled = pI830->allowPageFlip;
+      pSAREAPriv->pf_active = pfMask;
+   } else
+      pSAREAPriv->pf_enabled = pSAREAPriv->pf_active = 0;
 }
 
 static void
diff-tree fac8f2eb49de22abd853ca75f3c985d4d94e3633 (from 55c7b017ed718107b9b11467030addf225728b84)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Tue Feb 20 18:38:40 2007 +0100

    Document Option "PageFlip".

diff --git a/man/intel.man b/man/intel.man
index b932632..3f4cff8 100644
--- a/man/intel.man
+++ b/man/intel.man
@@ -159,6 +159,13 @@ atctivate the legacy texture pool (see 
 gain some performance by increasing this value.
 Default: 32768.
 .TP
+.BI "Option \*qPageFlip\*q \*q" boolean \*q
+Enable support for page flipping. This should improve 3D performance at the
+potential cost of worse performance or artifacts with mixed 2D/3D. Also note
+that this gives no benefit without corresponding support in the Mesa 3D driver.
+Default for i810: The option is not used.
+Default for i9xx: Disabled.
+.TP
 .BI "Option \*qAccelMethod\*q \*q" string \*q
 Choose acceleration architecture, either "XAA" or "EXA".  XAA is the old
 (but stable) XFree86 based acceleration architecture.  EXA is a newer and
diff-tree 55c7b017ed718107b9b11467030addf225728b84 (from 3bd8edb95fcbbb49e97a1a2bdd5c8eae4f83d3a8)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 14 16:45:22 2007 +0100

    Use new DRI ClipNotify hook to track page flipping per CRTC when available.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 05171d3..b368c99 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -107,6 +107,7 @@ static void I830DRITransitionTo2d(Screen
 static void I830DRITransitionTo3d(ScreenPtr pScreen);
 static void I830DRITransitionMultiToSingle3d(ScreenPtr pScreen);
 static void I830DRITransitionSingleToMulti3d(ScreenPtr pScreen);
+static void I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num);
 
 #if 0
 static void I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf);
@@ -551,10 +552,31 @@ I830DRIScreenInit(ScreenPtr pScreen)
    pDRIInfo->InitBuffers = I830DRIInitBuffers;
    pDRIInfo->MoveBuffers = I830DRIMoveBuffers;
    pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
-   pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
-   pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
-   pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
-   pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
+
+#if DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1
+   {
+      int major, minor, patch;
+
+      DRIQueryVersion(&major, &minor, &patch);
+
+      if (minor >= 1)
+#endif
+#if DRIINFO_MAJOR_VERSION > 5 || \
+    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
+	 pDRIInfo->ClipNotify = I830DRIClipNotify;
+#endif
+   }
+
+#if DRIINFO_MAJOR_VERSION > 5 || \
+    (DRIINFO_MAJOR_VERSION == 5 && DRIINFO_MINOR_VERSION >= 1)
+   if (!pDRIInfo->ClipNotify)
+#endif
+   {
+      pDRIInfo->TransitionTo2d = I830DRITransitionTo2d;
+      pDRIInfo->TransitionTo3d = I830DRITransitionTo3d;
+      pDRIInfo->TransitionSingleToMulti3D = I830DRITransitionSingleToMulti3d;
+      pDRIInfo->TransitionMultiToSingle3D = I830DRITransitionMultiToSingle3d;
+   }
 
    /* do driver-independent DRI screen initialization here */
    if (!DRIScreenInit(pScreen, pDRIInfo, &pI830->drmSubFD)) {
@@ -1354,41 +1376,35 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
  */
 
 static void
-I830EnablePageFlip(ScreenPtr pScreen)
+I830DRISetPfMask(ScreenPtr pScreen, int pfMask)
 {
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
    drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
 
    pSAREAPriv->pf_enabled = pI830->allowPageFlip;
-   pSAREAPriv->pf_active = pI830->allowPageFlip;
+   pSAREAPriv->pf_active = pfMask;
 }
 
 static void
-I830DisablePageFlip(ScreenPtr pScreen)
-{
-   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
-
-   pSAREAPriv->pf_active = 0;
-}
-
-
-static void
 I830DRITransitionSingleToMulti3d(ScreenPtr pScreen)
 {
    /* Tell the clients not to pageflip.  How?
     *   -- Field in sarea, plus bumping the window counters.
     *   -- DRM needs to cope with Front-to-Back swapbuffers.
     */
-   I830DisablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, 0);
 }
 
 static void
 I830DRITransitionMultiToSingle3d(ScreenPtr pScreen)
 {
+   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+   I830Ptr pI830 = I830PTR(pScrn);
+
    /* Let the remaining 3d app start page flipping again.
     */
-   I830EnablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
 }
 
 static void
@@ -1397,7 +1413,7 @@ I830DRITransitionTo3d(ScreenPtr pScreen)
    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
    I830Ptr pI830 = I830PTR(pScrn);
 
-   I830EnablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, pI830->allowPageFlip ? 0x3 : 0);
    pI830->have3DWindows = 1;
 }
 
@@ -1417,11 +1433,46 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
       xf86DrvMsg(pScreen->myNum, X_WARNING,
 		 "[dri] %s: kernel failed to unflip buffers.\n", __func__);
 
-   I830DisablePageFlip(pScreen);
+   I830DRISetPfMask(pScreen, 0);
 
    pI830->have3DWindows = 0;
 }
 
+static void
+I830DRIClipNotify(ScreenPtr pScreen, WindowPtr *ppWin, int num)
+{
+   unsigned pfMask = 0;
+
+   if (num > 0) {
+      drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScreen);
+      BoxRec crtcBox[2];
+      unsigned numvisible[2] = { 0, 0 };
+      int i, j;
+
+      crtcBox[0].x1 = sPriv->pipeA_x;
+      crtcBox[0].y1 = sPriv->pipeA_y;
+      crtcBox[0].x2 = crtcBox[0].x1 + sPriv->pipeA_w;
+      crtcBox[0].y2 = crtcBox[0].y1 + sPriv->pipeA_h;
+      crtcBox[1].x1 = sPriv->pipeB_x;
+      crtcBox[1].y1 = sPriv->pipeB_y;
+      crtcBox[1].x2 = crtcBox[0].x1 + sPriv->pipeB_w;
+      crtcBox[1].y2 = crtcBox[0].y1 + sPriv->pipeB_h;
+
+      for (i = 0; i < 2; i++) {
+	 for (j = 0; j < num; j++) {
+	    if (ppWin[j] && RECT_IN_REGION(pScreen, &ppWin[j]->clipList,
+					   &crtcBox[i]) != rgnOUT)
+	       numvisible[i]++;
+	 }
+
+	 if (numvisible[i] == 1)
+	    pfMask |= 1 << i;
+      }
+   }
+
+   I830DRISetPfMask(pScreen, pfMask);
+}
+
 
 /**
  * Update the SAREA fields with the most recent values.
diff-tree 3bd8edb95fcbbb49e97a1a2bdd5c8eae4f83d3a8 (from 1d22bad33b634aaf61976907cb2ceeec8a9ebe4d)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Fri Feb 2 17:41:18 2007 +0100

    Revive i830 page flipping support.
    
    Use the damage layer directly instead of via shadowfb.

diff --git a/configure.ac b/configure.ac
index d45185a..219fbe6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -94,6 +94,8 @@ if test "$DRI" != no; then
                       [have_sarea_h="yes"], [have_sarea_h="no"])
         AC_CHECK_FILE([${sdkdir}/dristruct.h],
                       [have_dristruct_h="yes"], [have_dristruct_h="no"])
+	AC_CHECK_FILE([${sdkdir}/damage.h],
+                      [have_damage_h="yes"], [have_damage_h="no"])
 fi
 
 AC_MSG_CHECKING([whether to include DRI support])
@@ -127,6 +129,9 @@ if test "$DRI" = yes; then
 	if test "x$DRI_MM" = xyes; then
 		AC_DEFINE(XF86DRI_MM,1,[Extended DRI memory management])
 	fi
+	if test "$have_damage_h" = yes; then
+		AC_DEFINE(DAMAGE,1,[Use Damage extension])
+	fi
 fi
 
 AM_CONDITIONAL(VIDEO_DEBUG, test x$VIDEO_DEBUG = xyes)
diff --git a/src/i830.h b/src/i830.h
index 96972eb..78381fb 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -68,6 +68,9 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN
 #include "dri.h"
 #include "GL/glxint.h"
 #include "i830_dri.h"
+#ifdef DAMAGE
+#include "damage.h"
+#endif
 #endif
 
 #ifdef I830_USE_EXA
@@ -302,6 +305,10 @@ typedef struct _I830Rec {
    unsigned int front_tiled;
    unsigned int back_tiled;
    unsigned int depth_tiled;
+
+#ifdef DAMAGE
+   DamagePtr pDamage;
+#endif
 #endif
 
    Bool NeedRingBufferLow;
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 3531bf5..05171d3 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -984,17 +984,6 @@ I830DRIFinishScreenInit(ScreenPtr pScree
 
    DPRINTF(PFX, "I830DRIFinishScreenInit\n");
 
-   /* Have shadow run only while there is 3d active.
-    */
-#if 0
-   if (pI830->allowPageFlip && pI830->drmMinor >= 1) {
-      shadowAdd(pScreen, 0, I830DRIShadowUpdate, 0, 0, 0);
-   }
-   else
-#endif
-      pI830->allowPageFlip = 0;
-
-
    if (!DRIFinishScreenInit(pScreen))
       return FALSE;
 
@@ -1025,6 +1014,49 @@ I830DRIFinishScreenInit(ScreenPtr pScree
    }
 }
 
+#ifdef DAMAGE
+/* This should be done *before* XAA syncs,
+ * Otherwise will have to sync again???
+ */
+static void
+I830DRIRefreshArea (ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+   int i, cmd, br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
+   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScrn->pScreen);
+
+   /* Don't want to do this when no 3d is active and pages are
+    * right-way-round :
+    */
+   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
+      return;
+
+   if (pScrn->bitsPerPixel == 32) {
+      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
+	     XY_SRC_COPY_BLT_WRITE_RGB);
+      br13 |= 3 << 24;
+   } else {
+      cmd = (XY_SRC_COPY_BLT_CMD);
+      br13 |= 1 << 24;
+   }
+
+   for (i = 0 ; i < num ; i++, pbox++) {
+      BEGIN_LP_RING(8);
+      OUT_RING(cmd);
+      OUT_RING(br13);
+      OUT_RING((pbox->y1 << 16) | pbox->x1);
+      OUT_RING((pbox->y2 << 16) | pbox->x2);
+      OUT_RING(pI830->BackBuffer.Start);
+      OUT_RING((pbox->y1 << 16) | pbox->x1);
+      OUT_RING(br13 & 0xffff);
+      OUT_RING(pI830->FrontBuffer.Start);
+      ADVANCE_LP_RING();
+   }
+
+   DamageEmpty(pI830->pDamage);
+}
+#endif
+
 static void
 I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
 		   DRIContextType oldContextType, void *oldContext,
@@ -1045,12 +1077,47 @@ I830DRISwapContext(ScreenPtr pScreen, DR
      	 return;
       pI830->LockHeld = 1;
       I830RefreshRing(pScrn);
+
+#ifdef DAMAGE
+      if (!pI830->pDamage && pI830->allowPageFlip) {
+	 PixmapPtr pPix  = pScreen->GetScreenPixmap(pScreen);
+	 pI830->pDamage = DamageCreate(NULL, NULL, DamageReportNone, TRUE,
+				       pScreen, pPix);
+
+	 if (pI830->pDamage == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+                       "No screen damage record, page flipping disabled\n");
+            pI830->allowPageFlip = 0;
+	 } else {
+	    DamageRegister(&pPix->drawable, pI830->pDamage);
+
+	    DamageDamageRegion(&pPix->drawable,
+			       &WindowTable[pScreen->myNum]->winSize);
+
+            xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+                       "Damage tracking initialized for page flipping\n");
+	 }
+    }
+#endif
    } else if (syncType == DRI_2D_SYNC &&
 	      oldContextType == DRI_NO_CONTEXT &&
 	      newContextType == DRI_2D_CONTEXT) {
       pI830->LockHeld = 0;
       if (I810_DEBUG & DEBUG_VERBOSE_DRI)
 	 ErrorF("i830DRISwapContext (out)\n");
+
+#ifdef DAMAGE
+      if (pI830->pDamage) {
+	 RegionPtr pDamageReg = DamageRegion(pI830->pDamage);
+
+	 if (pDamageReg) {
+	    int nrects = REGION_NUM_RECTS(pDamageReg);
+
+	    if (nrects)
+	       I830DRIRefreshArea(pScrn, nrects, REGION_RECTS(pDamageReg));
+	 }
+      }
+#endif
    } else if (I810_DEBUG & DEBUG_VERBOSE_DRI)
       ErrorF("i830DRISwapContext (other)\n");
 }
@@ -1286,54 +1353,6 @@ I830DRIMoveBuffers(WindowPtr pParent, DD
  * might be faster, but seems like a lot more work...
  */
 
-
-#if 0
-/* This should be done *before* XAA syncs,
- * Otherwise will have to sync again???
- */
-static void
-I830DRIShadowUpdate (ScreenPtr pScreen, shadowBufPtr pBuf)
-{
-   ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
-   I830Ptr pI830 = I830PTR(pScrn);
-   RegionPtr damage = &pBuf->damage;
-   int i, num =  REGION_NUM_RECTS(damage);
-   BoxPtr pbox = REGION_RECTS(damage);
-   drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
-   int cmd, br13;
-
-   /* Don't want to do this when no 3d is active and pages are
-    * right-way-round :
-    */
-   if (!pSAREAPriv->pf_active && pSAREAPriv->pf_current_page == 0)
-      return;
-
-   br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
-
-   if (pScrn->bitsPerPixel == 32) {
-      cmd = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-	     XY_SRC_COPY_BLT_WRITE_RGB);
-      br13 |= 3 << 24;
-   } else {
-      cmd = (XY_SRC_COPY_BLT_CMD);
-      br13 |= 1 << 24;
-   }
-
-   for (i = 0 ; i < num ; i++, pbox++) {
-      BEGIN_LP_RING(8);
-      OUT_RING(cmd);
-      OUT_RING(br13);
-      OUT_RING((pbox->y1 << 16) | pbox->x1);
-      OUT_RING((pbox->y2 << 16) | pbox->x2);
-      OUT_RING(pI830->BackBuffer.Start);
-      OUT_RING((pbox->y1 << 16) | pbox->x1);
-      OUT_RING(br13 & 0xffff);
-      OUT_RING(pI830->FrontBuffer.Start);
-      ADVANCE_LP_RING();
-   }
-}
-#endif
-
 static void
 I830EnablePageFlip(ScreenPtr pScreen)
 {
@@ -1342,32 +1361,7 @@ I830EnablePageFlip(ScreenPtr pScreen)
    drmI830Sarea *pSAREAPriv = DRIGetSAREAPrivate(pScreen);
 
    pSAREAPriv->pf_enabled = pI830->allowPageFlip;
-   pSAREAPriv->pf_active = 0;
-
-   if (pI830->allowPageFlip) {
-      int br13 = (pScrn->displayWidth * pI830->cpp) | (0xcc << 16);
-
-      BEGIN_LP_RING(8);
-      if (pScrn->bitsPerPixel == 32) {
-	 OUT_RING(XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-		  XY_SRC_COPY_BLT_WRITE_RGB);
-	 br13 |= 3 << 24;
-      } else {
-	 OUT_RING(XY_SRC_COPY_BLT_CMD);
-	 br13 |= 1 << 24;
-      }
-
-      OUT_RING(br13);
-      OUT_RING(0);
-      OUT_RING((pScrn->virtualY << 16) | pScrn->virtualX);
-      OUT_RING(pI830->BackBuffer.Start);
-      OUT_RING(0);
-      OUT_RING(br13 & 0xffff);
-      OUT_RING(pI830->FrontBuffer.Start);
-      ADVANCE_LP_RING();
-
-      pSAREAPriv->pf_active = 1;
-   }
+   pSAREAPriv->pf_active = pI830->allowPageFlip;
 }
 
 static void
@@ -1419,14 +1413,13 @@ I830DRITransitionTo2d(ScreenPtr pScreen)
    if (sPriv->pf_current_page == 1)
       drmCommandNone(pI830->drmSubFD, DRM_I830_FLIP);
 
-   /* Shut down shadowing if we've made it back to the front page:
-    */
-   if (sPriv->pf_current_page == 0) {
-      I830DisablePageFlip(pScreen);
-   }
+   if (sPriv->pf_current_page == 1)
+      xf86DrvMsg(pScreen->myNum, X_WARNING,
+		 "[dri] %s: kernel failed to unflip buffers.\n", __func__);
 
-   pI830->have3DWindows = 0;
+   I830DisablePageFlip(pScreen);
 
+   pI830->have3DWindows = 0;
 }
 
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index cb3dd87..d1f83e5 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -3168,6 +3168,15 @@ I830CloseScreen(int scrnIndex, ScreenPtr
    pI830->closing = TRUE;
 #ifdef XF86DRI
    if (pI830->directRenderingOpen) {
+#ifdef DAMAGE
+      if (pI830->pDamage) {
+	 PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
+
+	 DamageUnregister(&pPix->drawable, pI830->pDamage);
+	 DamageDestroy(pI830->pDamage);
+	 pI830->pDamage = NULL;
+      }
+#endif
 #ifdef XF86DRI_MM
       if (pI830->mmModeFlags & I830_KERNEL_MM) {
 #ifndef XSERVER_LIBDRM_MM
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 6ceb05b..29d9d31 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -515,7 +515,7 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
    int verbosity = dryrun ? 4 : 1;
    const char *s = dryrun ? "[dryrun] " : "";
    Bool tileable;
-   int align, alignflags;
+   int align;
    long size, alloced, fb_height;
 
    /* Clear everything first. */
@@ -586,16 +586,6 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 
    tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
       IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
-   if (tileable) {
-      if (IS_I9XX(pI830))
-	 align = MB(1);
-      else
-	 align = KB(512);
-      alignflags = ALIGN_BOTH_ENDS;
-   } else {
-      align = KB(64);
-      alignflags = 0;
-   }
 
    size = lineSize * (fb_height + cacheLines);
    size = ROUND_TO_PAGE(size);
@@ -603,10 +593,26 @@ I830AllocateFramebuffer(ScrnInfoPtr pScr
 		  "%sInitial %sframebuffer allocation size: %ld kByte\n",
 		  s, secondary ? "secondary " : "",
 		  size / 1024);
-   alloced = I830AllocVidMem(pScrn, FrontBuffer,
-			     StolenPool, size, align,
-			     flags | alignflags |
-			     FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+
+   if (tileable) {
+      align = GetBestTileAlignment(size);
+
+      for (align = GetBestTileAlignment(size);
+	   align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
+	 alloced = I830AllocVidMem(pScrn, FrontBuffer, StolenPool, size, align,
+				   flags | FROM_ANYWHERE | ALLOCATE_AT_TOP |
+				   ALIGN_BOTH_ENDS);
+	 if (alloced >= size)
+	    break;
+      }
+   } else {
+      align = KB(64);
+
+      alloced = I830AllocVidMem(pScrn, FrontBuffer,
+				StolenPool, size, align,
+				flags | FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+   }
+
    if (alloced < size) {
       if (!dryrun) {
 	 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate "
@@ -718,7 +724,7 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
    int verbosity = dryrun ? 4 : 1;
    const char *s = dryrun ? "[dryrun] " : "";
    Bool tileable;
-   int align, alignflags, i;
+   int align, i;
 
    DPRINTF(PFX, "I830Allocate2DMemory: inital is %s\n",
 	   BOOLTOSTRING(flags & ALLOC_INITIAL));
@@ -877,20 +883,26 @@ I830Allocate2DMemory(ScrnInfoPtr pScrn, 
 	 pI830->FbMemBox.y2 = maxFb / lineSize;
 	 tileable = !(flags & ALLOC_NO_TILING) && pI830->allowPageFlip &&
 		 IsTileable(pScrn, pScrn->displayWidth * pI830->cpp);
+
 	 if (tileable) {
-            if (IS_I9XX(pI830))
-               align = MB(1);
-            else
-	       align = KB(512);
-	    alignflags = ALIGN_BOTH_ENDS;
+	    align = GetBestTileAlignment(size);
+
+	    for (align = GetBestTileAlignment(size);
+		 align >= (IS_I9XX(pI830) ? MB(1) : KB(512)); align >>= 1) {
+	       alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
+					 &(pI830->StolenPool), size, align,
+					 flags | FROM_ANYWHERE |
+					 ALLOCATE_AT_TOP | ALIGN_BOTH_ENDS);
+	       if (alloced >= size)
+		  break;
+	    }
 	 } else {
-	    align = KB(64);
-	    alignflags = 0;
+	    alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
+				      &(pI830->StolenPool), maxFb, align,
+				      flags |
+				      FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
 	 }
-	 alloced = I830AllocVidMem(pScrn, &(pI830->FrontBuffer),
-				   &(pI830->StolenPool), maxFb, align,
-				   flags | alignflags |
-				   FROM_ANYWHERE | ALLOCATE_AT_BOTTOM);
+
 	 if (alloced < maxFb) {
 	    if (!dryrun) {
 	       xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
diff-tree 1d22bad33b634aaf61976907cb2ceeec8a9ebe4d (from 0df490938af10d3a748221e2fb5467b0f244f9eb)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Wed Feb 14 12:57:12 2007 +0100

    Update SAREA pipe fields in i830PipeSetBase.

diff --git a/src/i830_display.c b/src/i830_display.c
index 345eea9..258897e 100644
--- a/src/i830_display.c
+++ b/src/i830_display.c
@@ -361,6 +361,31 @@ i830PipeSetBase(xf86CrtcPtr crtc, int x,
 	OUTREG(dspbase, Start + ((y * pScrn->displayWidth + x) * pI830->cpp));
 	(void) INREG(dspbase);
     }
+
+#ifdef XF86DRI
+    if (pI830->directRenderingEnabled) {
+	drmI830Sarea *sPriv = (drmI830Sarea *) DRIGetSAREAPrivate(pScrn->pScreen);
+
+	switch (pipe) {
+	case 0:
+	    sPriv->pipeA_x = x;
+	    sPriv->pipeA_y = y;
+	    sPriv->pipeA_w = crtc->mode.HDisplay;
+	    sPriv->pipeA_h = crtc->mode.VDisplay;
+	    break;
+	case 1:
+	    sPriv->pipeB_x = x;
+	    sPriv->pipeB_y = y;
+	    sPriv->pipeB_w = crtc->mode.HDisplay;
+	    sPriv->pipeB_h = crtc->mode.VDisplay;
+	    break;
+	default:
+	    xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+		       "Can't update pipe %d in SAREA\n", pipe);
+	    break;
+	}
+    }
+#endif
 }
 
 /**
diff-tree 0df490938af10d3a748221e2fb5467b0f244f9eb (from 1623b47c4863f5362587cdac855e3e11c109b007)
Author: Michel Dänzer <michel at tungstengraphics.com>
Date:   Thu Dec 21 11:27:28 2006 +0100

    If the DRM can handle it, enable vertical blank interrupts for both pipes.

diff --git a/src/i830_dri.c b/src/i830_dri.c
index 70e7e49..3531bf5 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1497,7 +1497,10 @@ I830DRISetVBlankInterrupt (ScrnInfoPtr p
     if (pI830->directRenderingEnabled && pI830->drmMinor >= 5) {
 	if (on) {
 	    if (xf86_config->num_crtc > 1 && xf86_config->crtc[1]->enabled)
-		pipe.pipe = DRM_I830_VBLANK_PIPE_B;
+		if (pI830->drmMinor >= 6)
+		    pipe.pipe = DRM_I830_VBLANK_PIPE_A | DRM_I830_VBLANK_PIPE_B;
+		else
+		    pipe.pipe = DRM_I830_VBLANK_PIPE_B;
 	    else
 		pipe.pipe = DRM_I830_VBLANK_PIPE_A;
 	} else {



More information about the xorg-commit mailing list