xf86-video-intel: Branch 'drm-gem' - 6 commits - src/i810_reg.h src/i830_accel.c src/i830_batchbuffer.c src/i830_batchbuffer.h src/i830_dri.c src/i830_driver.c src/i830_exa.c src/i830.h src/i830_memory.c src/i830_render.c src/i830_ring.h src/i915_3d.h src/i915_render.c src/i915_video.c src/Makefile.am

Eric Anholt anholt at kemper.freedesktop.org
Tue Jun 10 23:18:54 PDT 2008


 src/Makefile.am        |    2 
 src/i810_reg.h         |    7 ++
 src/i830.h             |   33 ++++++---
 src/i830_accel.c       |   53 ++++++++++-----
 src/i830_batchbuffer.c |  165 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/i830_batchbuffer.h |  119 +++++++++++++++++++++++++++++++++++
 src/i830_dri.c         |   67 +++++++++++--------
 src/i830_driver.c      |  151 +++++++++++++++++++++++++++++++++++---------
 src/i830_exa.c         |   18 +----
 src/i830_memory.c      |   19 ++++-
 src/i830_render.c      |   10 +-
 src/i830_ring.h        |    5 -
 src/i915_3d.h          |   10 +-
 src/i915_render.c      |   16 ++--
 src/i915_video.c       |    2 
 15 files changed, 551 insertions(+), 126 deletions(-)

New commits:
commit 339f00e340c3a9c8ac8f17147e37906494ef370b
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Jun 10 16:14:06 2008 -0700

    [gem] Don't set up the ring in GEM mode, as that'll be handled by the kernel.

diff --git a/src/i830_accel.c b/src/i830_accel.c
index a71ea47..c3cd08e 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -54,12 +54,15 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  *
  */
 
+#include <errno.h>
+
 #include "xf86.h"
 #include "xaarop.h"
 #include "i830.h"
 #include "i810_reg.h"
 #include "i830_debug.h"
 #include "i830_ring.h"
+#include "i915_drm.h"
 
 unsigned long
 intel_get_pixmap_offset(PixmapPtr pPix)
@@ -190,7 +193,35 @@ I830Sync(ScrnInfoPtr pScrn)
 
    intel_batch_flush(pScrn);
 
-   i830_wait_ring_idle(pScrn);
+   if (pI830->directRenderingEnabled) {
+       struct drm_i915_irq_emit emit;
+       struct drm_i915_irq_wait wait;
+       int ret;
+
+       /* Most of the uses of I830Sync while using GEM should actually be
+	* using set_domain on a specific buffer.  We're not there yet, so fake
+	* it up using irq_emit/wait.  It's still better than spinning on
+	* register reads for idle.
+	*/
+       emit.irq_seq = &wait.irq_seq;
+       ret = drmCommandWrite(pI830->drmSubFD, DRM_I830_IRQ_EMIT, &emit,
+			    sizeof(emit));
+       if (ret != 0)
+	   FatalError("Failure to emit IRQ: %s\n", strerror(-ret));
+
+       do {
+	   ret = drmCommandWrite(pI830->drmSubFD, DRM_I830_IRQ_WAIT, &wait,
+				 sizeof(wait));
+       } while (ret == -EINTR);
+
+       if (ret != 0)
+	   FatalError("Failure to wait for IRQ: %s\n", strerror(-ret));
+
+       if (!pI830->memory_manager)
+	   i830_refresh_ring(pScrn);
+   } else {
+       i830_wait_ring_idle(pScrn);
+   }
 
    pI830->nextColorExpandBuf = 0;
 }
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 416f4d0..2f53d2f 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -115,8 +115,6 @@ intel_batch_flush(ScrnInfoPtr pScrn)
 				  exec, sizeof(*exec));
 	if (ret != 0)
 	    FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
-
-	i830_refresh_ring(pScrn);
     } else {
 	dri_process_relocs(pI830->batch_bo);
 
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 8ec51fc..5a53670 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -175,22 +175,31 @@ I830InitDma(ScrnInfoPtr pScrn)
    memset(&info, 0, sizeof(drmI830Init));
    info.func = I830_INIT_DMA;
 
-   info.ring_start = ring->mem->offset + pI830->LinearAddr;
-   info.ring_end = ring->mem->end + pI830->LinearAddr;
-   info.ring_size = ring->mem->size;
+   /* Initialize fields that are used in the absence of GEM */
+   if (!pI830->memory_manager) {
+       info.ring_start = ring->mem->offset + pI830->LinearAddr;
+       info.ring_end = ring->mem->end + pI830->LinearAddr;
+       info.ring_size = ring->mem->size;
+
+       /* Not used as of the middle of GEM development. */
+       info.mmio_offset = (unsigned int)pI830DRI->regs;
+
+       /* Not used as of before GEM development */
+       info.front_offset = pI830->front_buffer->offset;
+       info.back_offset = pI830->back_buffer->offset;
+       info.depth_offset = pI830->depth_buffer->offset;
+       info.pitch = pScrn->displayWidth;
+       info.back_pitch = pScrn->displayWidth;
+       info.depth_pitch = pScrn->displayWidth;
+       info.w = pScrn->virtualX;
+       info.h = pScrn->virtualY;
+   }
 
-   info.mmio_offset = (unsigned int)pI830DRI->regs;
 
    info.sarea_priv_offset = sizeof(XF86DRISAREARec);
 
-   info.front_offset = pI830->front_buffer->offset;
-   info.back_offset = pI830->back_buffer->offset;
-   info.depth_offset = pI830->depth_buffer->offset;
-   info.w = pScrn->virtualX;
-   info.h = pScrn->virtualY;
-   info.pitch = pScrn->displayWidth;
-   info.back_pitch = pScrn->displayWidth;
-   info.depth_pitch = pScrn->displayWidth;
+   /* This should probably have been moved alongside offset/pitch in the sarea.
+    */
    info.cpp = pI830->cpp;
 
    if (drmCommandWrite(pI830->drmSubFD, DRM_I830_INIT,
@@ -799,17 +808,20 @@ I830DRIDoMappings(ScreenPtr pScreen)
    xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] Registers = 0x%08x\n",
 	      (int)pI830DRI->regs);
 
-   if (drmAddMap(pI830->drmSubFD,
-		 (drm_handle_t)pI830->LpRing->mem->offset + pI830->LinearAddr,
-		 pI830->LpRing->mem->size, DRM_AGP, 0,
-		 (drmAddress) &pI830->ring_map) < 0) {
-      xf86DrvMsg(pScreen->myNum, X_ERROR,
-		 "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
-      DRICloseScreen(pScreen);
-      return FALSE;
+   if (!pI830->memory_manager) {
+       if (drmAddMap(pI830->drmSubFD,
+		     (drm_handle_t)pI830->LpRing->mem->offset +
+		     pI830->LinearAddr,
+		     pI830->LpRing->mem->size, DRM_AGP, 0,
+		     (drmAddress) &pI830->ring_map) < 0) {
+	   xf86DrvMsg(pScreen->myNum, X_ERROR,
+		      "[drm] drmAddMap(ring_map) failed. Disabling DRI\n");
+	   DRICloseScreen(pScreen);
+	   return FALSE;
+       }
+       xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n",
+		  (int)pI830->ring_map);
    }
-   xf86DrvMsg(pScreen->myNum, X_INFO, "[drm] ring buffer = 0x%08x\n",
-	      (int)pI830->ring_map);
 
    if (!I830InitDma(pScrn)) {
       DRICloseScreen(pScreen);
@@ -960,6 +972,7 @@ I830DRICloseScreen(ScreenPtr pScreen)
       xfree(pI830->pVisualConfigs);
    if (pI830->pVisualConfigsPriv)
       xfree(pI830->pVisualConfigsPriv);
+   pI830->directRenderingEnabled = FALSE;
 }
 
 static Bool
@@ -1065,7 +1078,8 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
       if (!pScrn->vtSema)
      	 return;
       pI830->LockHeld = 1;
-      i830_refresh_ring(pScrn);
+      if (!pI830->memory_manager)
+	  i830_refresh_ring(pScrn);
 
 #ifdef DAMAGE
       if (!pI830->pDamage && pI830->allowPageFlip) {
@@ -1763,7 +1777,8 @@ I830DRILock(ScrnInfoPtr pScrn)
    if (pI830->directRenderingEnabled && !pI830->LockHeld) {
       DRILock(screenInfo.screens[pScrn->scrnIndex], 0);
       pI830->LockHeld = 1;
-      i830_refresh_ring(pScrn);
+      if (!pI830->memory_manager)
+	  i830_refresh_ring(pScrn);
       return TRUE;
    }
    else
diff --git a/src/i830_driver.c b/src/i830_driver.c
index bce00af..e7994df 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -211,6 +211,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <sys/ioctl.h>
 #ifdef XF86DRI_MM
 #include "xf86mm.h"
+#include "i915_drm.h"
 #endif
 #endif
 
@@ -3005,7 +3006,7 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 #endif
 
    if (!pI830->noAccel) {
-      if (pI830->LpRing->mem->size == 0) {
+      if (pI830->memory_manager == NULL && pI830->LpRing->mem->size == 0) {
 	  xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
 		     "Disabling acceleration because the ring buffer "
 		      "allocation failed.\n");
@@ -3357,7 +3358,8 @@ I830LeaveVT(int scrnIndex, int flags)
       intel_bufmgr_fake_evict_all(pI830->bufmgr);
    intel_batch_teardown(pScrn);
 
-   i830_stop_ring(pScrn, TRUE);
+   if (!pI830->memory_manager)
+      i830_stop_ring(pScrn, TRUE);
 
    if (pI830->debug_modes) {
       i830CompareRegsToSnapshot(pScrn, "After LeaveVT");
@@ -3367,15 +3369,16 @@ I830LeaveVT(int scrnIndex, int flags)
    if (I830IsPrimary(pScrn))
       i830_unbind_all_memory(pScrn);
 
-   /* Tell the kernel to evict all buffer objects and block new buffer
-    * allocations until we relese the lock.
-    */
 #ifdef XF86DRI_MM
-   if (pI830->directRenderingOpen) {
-      /* XXX:
-      if (pI830->memory_manager != NULL && pScrn->vtSema) {
-	 drmMMLock(pI830->drmSubFD, DRM_BO_MEM_TT, 1, 0);
-      }*/
+   if (pI830->memory_manager) {
+      int ret;
+
+      /* Tell the kernel to evict all buffer objects and block GTT usage while
+       * we're no longer in control of the chip.
+       */
+      ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_LEAVEVT);
+      if (ret != 0)
+	 FatalError("DRM_I915_LEAVEVT failed: %s\n", strerror(ret));
    }
 #endif /* XF86DRI_MM */
 
@@ -3409,15 +3412,15 @@ I830EnterVT(int scrnIndex, int flags)
    pI830->leaving = FALSE;
 
 #ifdef XF86DRI_MM
-   if (pI830->directRenderingEnabled) {
-      /* Unlock the memory manager first of all so that we can pin our
-       * buffer objects
+   if (pI830->memory_manager) {
+      int ret;
+
+      /* Tell the kernel that we're back in control and ready for GTT
+       * usage.
        */
-      /*
-      if (pI830->memory_manager != NULL && pScrn->vtSema) {
-	 drmMMUnlock(pI830->drmSubFD, DRM_BO_MEM_TT, 1);
-      }
-      */
+      ret = drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_ENTERVT);
+      if (ret != 0)
+	 FatalError("DRM_I915_ENTERVT failed: %s\n", strerror(ret));
    }
 #endif /* XF86DRI_MM */
 
@@ -3440,8 +3443,11 @@ I830EnterVT(int scrnIndex, int flags)
 		 "Existing errors found in hardware state.\n");
    }
 
-   i830_stop_ring(pScrn, FALSE);
-   i830_start_ring(pScrn);
+   /* Re-set up the ring. */
+   if (!pI830->memory_manager) {
+      i830_stop_ring(pScrn, FALSE);
+      i830_start_ring(pScrn);
+   }
    if (!pI830->SWCursor)
       I830InitHWCursor(pScrn);
 
@@ -3504,7 +3510,8 @@ I830EnterVT(int scrnIndex, int flags)
 
 	 I830DRIResume(screenInfo.screens[scrnIndex]);
 
-	 i830_refresh_ring(pScrn);
+	 if (!pI830->memory_manager)
+	    i830_refresh_ring(pScrn);
 	 I830Sync(pScrn);
 
 	 sarea->texAge++;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index db99d97..3613167 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -996,7 +996,7 @@ i830_allocate_ringbuffer(ScrnInfoPtr pScrn)
 {
     I830Ptr pI830 = I830PTR(pScrn);
 
-    if (pI830->noAccel || pI830->LpRing->mem != NULL)
+    if (pI830->noAccel || pI830->memory_manager || pI830->LpRing->mem != NULL)
 	return TRUE;
 
     /* We don't have any mechanism in the DRM yet to alert it that we've moved
@@ -1632,8 +1632,10 @@ i830_allocate_texture_memory(ScrnInfoPtr pScrn)
 		       size / 1024);
 	    return FALSE;
 	}
-	/* The offset must stay constant currently because we don't ever update
-	 * the DRI maps after screen init.
+	/* Now that the DRM uses the sarea to get the offsets of the buffers,
+	 * and we update the classic DRM mappings and the sarea contents on
+	 * changes, the NEED_LIFETIME_FIXED is no longer true and should be
+	 * made conditional on DRM version.
 	 */
 	pI830->textures = i830_allocate_memory(pScrn, "classic textures", size,
 					       GTT_PAGE_SIZE,
commit e930c0dc5b5f98d256a4167ed70ba813c88924d2
Author: Eric Anholt <eric at anholt.net>
Date:   Sat Jun 7 13:57:59 2008 -0700

    Use bufmgr_gem when available instead of the fake bufmgr.
    
    This is a bit unstable still sometimes.

diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 976a405..416f4d0 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -98,36 +98,59 @@ intel_batch_flush(ScrnInfoPtr pScrn)
     dri_bo_unmap(pI830->batch_bo);
     pI830->batch_ptr = NULL;
 
-    dri_process_relocs(pI830->batch_bo);
-
-    if (pI830->directRenderingEnabled) {
-	struct drm_i915_batchbuffer batch;
+    if (pI830->memory_manager) {
+	struct drm_i915_gem_execbuffer *exec;
 	int ret;
 
-	batch.start = pI830->batch_bo->offset;
-	batch.used = pI830->batch_used;
-	batch.cliprects = NULL;
-	batch.num_cliprects = 0;
-	batch.DR1 = 0;
-	batch.DR4 = 0xffffffff;
+	exec = dri_process_relocs(pI830->batch_bo);
+
+	exec->batch_start_offset = 0;
+	exec->batch_len = pI830->batch_used;
+	exec->cliprects_ptr = 0;
+	exec->num_cliprects = 0;
+	exec->DR1 = 0;
+	exec->DR4 = 0xffffffff;
 
-	ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_BATCHBUFFER,
-			      &batch, sizeof(batch));
+	ret = drmCommandWriteRead(pI830->drmSubFD, DRM_I915_GEM_EXECBUFFER,
+				  exec, sizeof(*exec));
 	if (ret != 0)
 	    FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
+
+	i830_refresh_ring(pScrn);
     } else {
-	if (!IS_I830(pI830) && !IS_845G(pI830)) {
-	    BEGIN_LP_RING(2);
-	    OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-	    OUT_RING(pI830->batch_bo->offset);
-	    ADVANCE_LP_RING();
+	dri_process_relocs(pI830->batch_bo);
+
+	if (pI830->directRenderingEnabled) {
+	    struct drm_i915_batchbuffer batch;
+	    int ret;
+
+	    batch.start = pI830->batch_bo->offset;
+	    batch.used = pI830->batch_used;
+	    batch.cliprects = NULL;
+	    batch.num_cliprects = 0;
+	    batch.DR1 = 0;
+	    batch.DR4 = 0xffffffff;
+
+	    ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_BATCHBUFFER,
+				  &batch, sizeof(batch));
+	    if (ret != 0)
+		FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
+
+	    i830_refresh_ring(pScrn);
 	} else {
-	    BEGIN_LP_RING(4);
-	    OUT_RING(MI_BATCH_BUFFER);
-	    OUT_RING(pI830->batch_bo->offset);
-	    OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
-	    OUT_RING(MI_NOOP);
-	    ADVANCE_LP_RING();
+	    if (!IS_I830(pI830) && !IS_845G(pI830)) {
+		BEGIN_LP_RING(2);
+		OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+		OUT_RING(pI830->batch_bo->offset);
+		ADVANCE_LP_RING();
+	    } else {
+		BEGIN_LP_RING(4);
+		OUT_RING(MI_BATCH_BUFFER);
+		OUT_RING(pI830->batch_bo->offset);
+		OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
+		OUT_RING(MI_NOOP);
+		ADVANCE_LP_RING();
+	    }
 	}
     }
 
diff --git a/src/i830_driver.c b/src/i830_driver.c
index cb9644e..bce00af 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2750,13 +2750,25 @@ i830_init_bufmgr(ScrnInfoPtr pScrn)
    I830Ptr pI830 = I830PTR(pScrn);
 
    assert(pI830->FbBase != NULL);
-   pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
-					  pI830->FbBase +
-					  pI830->fake_bufmgr_mem->offset,
-					  pI830->fake_bufmgr_mem->size,
-					  i830_fake_fence_emit,
-					  i830_fake_fence_wait,
-					  pScrn);
+   if (pI830->memory_manager) {
+      int batch_size;
+
+      batch_size = 4096 * 4;
+
+      /* The 865 has issues with larger-than-page-sized batch buffers. */
+      if (IS_I865G(pI830))
+	 batch_size = 4096;
+
+      pI830->bufmgr = intel_bufmgr_gem_init(pI830->drmSubFD, batch_size);
+   } else {
+      pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
+					     pI830->FbBase +
+					     pI830->fake_bufmgr_mem->offset,
+					     pI830->fake_bufmgr_mem->size,
+					     i830_fake_fence_emit,
+					     i830_fake_fence_wait,
+					     pScrn);
+   }
 }
 
 
@@ -3338,7 +3350,11 @@ I830LeaveVT(int scrnIndex, int flags)
 
    RestoreHWState(pScrn);
 
-   intel_bufmgr_fake_evict_all(pI830->bufmgr);
+   /* Evict everything from the bufmgr, as we're about to lose ownership of
+    * the graphics memory.
+    */
+   if (!pI830->memory_manager)
+      intel_bufmgr_fake_evict_all(pI830->bufmgr);
    intel_batch_teardown(pScrn);
 
    i830_stop_ring(pScrn, TRUE);
diff --git a/src/i830_memory.c b/src/i830_memory.c
index 57e4f2e..db99d97 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -1375,12 +1375,14 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 	return FALSE;
     }
 
-    pI830->fake_bufmgr_mem = i830_allocate_memory(pScrn, "fake bufmgr",
-						  MB(1), GTT_PAGE_SIZE, 0);
-    if (pI830->fake_bufmgr_mem == NULL) {
-	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
-		   "Failed to allocate fake bufmgr space.\n");
-	return FALSE;
+    if (pI830->memory_manager == NULL) {
+	pI830->fake_bufmgr_mem = i830_allocate_memory(pScrn, "fake bufmgr",
+						      MB(1), GTT_PAGE_SIZE, 0);
+	if (pI830->fake_bufmgr_mem == NULL) {
+	    xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		       "Failed to allocate fake bufmgr space.\n");
+	    return FALSE;
+	}
     }
 
     /* even in XAA, 965G needs state mem buffer for rendering */
commit ecf19e1cda60a938d41413075ae6e00f24e0ec1a
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 6 15:27:44 2008 -0700

    Change most usage of pixmap offsets to using a reloc macro.
    
    This is based on airlied's RING->BATCH commit.  The 965 code still needs to
    be fixed up for relocations.

diff --git a/src/i830.h b/src/i830.h
index 403cd63..96843f0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -690,6 +690,9 @@ typedef struct _I830Rec {
 #define I830_SELECT_DEPTH	2
 #define I830_SELECT_THIRD	3
 
+unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
+unsigned long intel_get_pixmap_pitch(PixmapPtr pPix);
+
 /* Batchbuffer support macros and functions */
 #include "i830_batchbuffer.h"
 
@@ -764,8 +767,6 @@ extern Bool I830DRISetHWS(ScrnInfoPtr pScrn);
 extern Bool I830DRIInstIrqHandler(ScrnInfoPtr pScrn);
 #endif
 
-unsigned long intel_get_pixmap_offset(PixmapPtr pPix);
-unsigned long intel_get_pixmap_pitch(PixmapPtr pPix);
 extern Bool I830AccelInit(ScreenPtr pScreen);
 extern void I830SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir,
 					   int ydir, int rop,
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
index 9179326..2b898c2 100644
--- a/src/i830_batchbuffer.h
+++ b/src/i830_batchbuffer.h
@@ -59,8 +59,21 @@ intel_batch_emit_dword(I830Ptr pI830, uint32_t dword)
     pI830->batch_used += 4;
 }
 
+static inline void
+intel_batch_emit_reloc_pixmap(I830Ptr pI830, PixmapPtr pPixmap, uint32_t delta)
+{
+    assert(pI830->batch_ptr != NULL);
+    assert(intel_batch_space(pI830) >= 4);
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) =
+	intel_get_pixmap_offset(pPixmap) + delta;
+    pI830->batch_used += 4;
+}
+
 #define OUT_BATCH(dword) intel_batch_emit_dword(pI830, dword)
 
+#define OUT_RELOC_PIXMAP(pPixmap, delta)	\
+	intel_batch_emit_reloc_pixmap(pI830, pPixmap, delta)
+
 union intfloat {
 	float f;
 	unsigned int ui;
diff --git a/src/i830_exa.c b/src/i830_exa.c
index 2c807c5..75ccd74 100644
--- a/src/i830_exa.c
+++ b/src/i830_exa.c
@@ -162,7 +162,7 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long offset, pitch;
+    unsigned long pitch;
 
     if (!EXA_PM_IS_SOLID(&pPixmap->drawable, planemask))
 	I830FALLBACK("planemask is not solid");
@@ -172,11 +172,8 @@ I830EXAPrepareSolid(PixmapPtr pPixmap, int alu, Pixel planemask, Pixel fg)
 
     i830_exa_check_pitch_2d(pPixmap);
 
-    offset = exaGetPixmapOffset(pPixmap);
     pitch = exaGetPixmapPitch(pPixmap);
 
-    if (offset % pI830->EXADriverPtr->pixmapOffsetAlign != 0)
-	I830FALLBACK("pixmap offset not aligned");
     if (pitch % pI830->EXADriverPtr->pixmapPitchAlign != 0)
 	I830FALLBACK("pixmap pitch not aligned");
 
@@ -202,10 +199,9 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPixmap->drawable.pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    unsigned long offset, pitch;
+    unsigned long pitch;
     uint32_t cmd;
 
-    offset = exaGetPixmapOffset(pPixmap);
     pitch = exaGetPixmapPitch(pPixmap);
 
     {
@@ -227,7 +223,7 @@ I830EXASolid(PixmapPtr pPixmap, int x1, int y1, int x2, int y2)
 	OUT_BATCH(pI830->BR[13] | pitch);
 	OUT_BATCH((y1 << 16) | (x1 & 0xffff));
 	OUT_BATCH((y2 << 16) | (x2 & 0xffff));
-	OUT_BATCH(offset);
+	OUT_RELOC_PIXMAP(pPixmap, 0);
 	OUT_BATCH(pI830->BR[16]);
 	ADVANCE_BATCH();
     }
@@ -285,14 +281,12 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
     I830Ptr pI830 = I830PTR(pScrn);
     uint32_t cmd;
     int dst_x2, dst_y2;
-    unsigned int dst_off, dst_pitch, src_off, src_pitch;
+    unsigned int dst_pitch, src_pitch;
 
     dst_x2 = dst_x1 + w;
     dst_y2 = dst_y1 + h;
 
-    dst_off = exaGetPixmapOffset(pDstPixmap);
     dst_pitch = exaGetPixmapPitch(pDstPixmap);
-    src_off = exaGetPixmapOffset(pI830->pSrcPixmap);
     src_pitch = exaGetPixmapPitch(pI830->pSrcPixmap);
 
     {
@@ -322,10 +316,10 @@ I830EXACopy(PixmapPtr pDstPixmap, int src_x1, int src_y1, int dst_x1,
 	OUT_BATCH(pI830->BR[13] | dst_pitch);
 	OUT_BATCH((dst_y1 << 16) | (dst_x1 & 0xffff));
 	OUT_BATCH((dst_y2 << 16) | (dst_x2 & 0xffff));
-	OUT_BATCH(dst_off);
+	OUT_RELOC_PIXMAP(pDstPixmap, 0);
 	OUT_BATCH((src_y1 << 16) | (src_x1 & 0xffff));
 	OUT_BATCH(src_pitch);
-	OUT_BATCH(src_off);
+	OUT_RELOC_PIXMAP(pI830->pSrcPixmap, 0);
 
 	ADVANCE_BATCH();
     }
diff --git a/src/i830_render.c b/src/i830_render.c
index 3a959e8..d5cab3f 100644
--- a/src/i830_render.c
+++ b/src/i830_render.c
@@ -275,10 +275,9 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 
     ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t format, offset, pitch, filter;
+    uint32_t format, pitch, filter;
     uint32_t wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
 
-    offset = intel_get_pixmap_offset(pPix);
     pitch = intel_get_pixmap_pitch(pPix);
     pI830->scale_units[unit][0] = pPix->drawable.width;
     pI830->scale_units[unit][1] = pPix->drawable.height;
@@ -314,7 +313,7 @@ i830_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 
 	BEGIN_BATCH(10);
 	OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_2 | LOAD_TEXTURE_MAP(unit) | 4);
-	OUT_BATCH((offset & TM0S0_ADDRESS_MASK) | TM0S0_USE_FENCE);
+	OUT_RELOC_PIXMAP(pPix, TM0S0_USE_FENCE);
 	OUT_BATCH(((pPix->drawable.height - 1) << TM0S1_HEIGHT_SHIFT) |
 		  ((pPix->drawable.width - 1) << TM0S1_WIDTH_SHIFT) | format);
 	OUT_BATCH((pitch/4 - 1) << TM0S2_PITCH_SHIFT | TM0S2_MAP_2D);
@@ -394,7 +393,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t dst_format, dst_offset, dst_pitch;
+    uint32_t dst_format, dst_pitch;
     Bool is_affine_src, is_affine_mask;
     Bool is_nearest = FALSE;
 
@@ -408,7 +407,6 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 
     if (!i830_get_dest_format(pDstPicture, &dst_format))
 	return FALSE;
-    dst_offset = intel_get_pixmap_offset(pDst);
     dst_pitch = intel_get_pixmap_pitch(pDst);
 
     if (!i830_texture_setup(pSrcPicture, pSrc, 0))
@@ -446,7 +444,7 @@ i830_prepare_composite(int op, PicturePtr pSrcPicture,
 	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
 	OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE |
 		  BUF_3D_PITCH(dst_pitch));
-	OUT_BATCH(BUF_3D_ADDR(dst_offset));
+	OUT_RELOC_PIXMAP(pDst, 0);
 	OUT_BATCH(MI_NOOP);
 
 	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
diff --git a/src/i915_render.c b/src/i915_render.c
index 4a02cf5..54197bf 100644
--- a/src/i915_render.c
+++ b/src/i915_render.c
@@ -250,11 +250,10 @@ i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
 {
     ScrnInfoPtr pScrn = xf86Screens[pPict->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t format, offset, pitch, filter;
+    uint32_t format, pitch, filter;
     int w, h, i;
     uint32_t wrap_mode = TEXCOORDMODE_CLAMP_BORDER;
 
-    offset = intel_get_pixmap_offset(pPix);
     pitch = intel_get_pixmap_pitch(pPix);
     w = pPict->pDrawable->width;
     h = pPict->pDrawable->height;
@@ -288,7 +287,7 @@ i915_texture_setup(PicturePtr pPict, PixmapPtr pPix, int unit)
         I830FALLBACK("Bad filter 0x%x\n", pPict->filter);
     }
 
-    pI830->mapstate[unit * 3 + 0] = offset;
+    pI830->mapstate[unit * 3 + 0] = 0; /* offset filled in at emit time */
     pI830->mapstate[unit * 3 + 1] = format |
 	MS3_USE_FENCE_REGS |
 	((pPix->drawable.height - 1) << MS3_HEIGHT_SHIFT) |
@@ -316,7 +315,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 {
     ScrnInfoPtr pScrn = xf86Screens[pSrcPicture->pDrawable->pScreen->myNum];
     I830Ptr pI830 = I830PTR(pScrn);
-    uint32_t dst_format, dst_offset, dst_pitch;
+    uint32_t dst_format, dst_pitch;
     uint32_t blendctl;
     int out_reg = FS_OC;
     FS_LOCALS(20);
@@ -333,7 +332,6 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 
     if (!i915_get_dest_format(pDstPicture, &dst_format))
 	return FALSE;
-    dst_offset = intel_get_pixmap_offset(pDst);
     dst_pitch = intel_get_pixmap_pitch(pDst);
 
     if (!i915_texture_setup(pSrcPicture, pSrc, 0))
@@ -362,7 +360,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	BEGIN_BATCH(10);
 	OUT_BATCH(_3DSTATE_MAP_STATE | 3);
 	OUT_BATCH(0x00000001); /* map 0 */
-	OUT_BATCH(pI830->mapstate[0]);
+	OUT_RELOC_PIXMAP(pSrc, 0);
 	OUT_BATCH(pI830->mapstate[1]);
 	OUT_BATCH(pI830->mapstate[2]);
 
@@ -376,10 +374,10 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	BEGIN_BATCH(16);
 	OUT_BATCH(_3DSTATE_MAP_STATE | 6);
 	OUT_BATCH(0x00000003); /* map 0,1 */
-	OUT_BATCH(pI830->mapstate[0]);
+	OUT_RELOC_PIXMAP(pSrc, 0);
 	OUT_BATCH(pI830->mapstate[1]);
 	OUT_BATCH(pI830->mapstate[2]);
-	OUT_BATCH(pI830->mapstate[3]);
+	OUT_RELOC_PIXMAP(pMask, 0);
 	OUT_BATCH(pI830->mapstate[4]);
 	OUT_BATCH(pI830->mapstate[5]);
 
@@ -400,7 +398,7 @@ i915_prepare_composite(int op, PicturePtr pSrcPicture,
 	OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
 	OUT_BATCH(BUF_3D_ID_COLOR_BACK| BUF_3D_USE_FENCE|
 		  BUF_3D_PITCH(dst_pitch));
-	OUT_BATCH(BUF_3D_ADDR(dst_offset));
+	OUT_RELOC_PIXMAP(pDst, 0);
 
 	OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
 	OUT_BATCH(dst_format);
diff --git a/src/i915_video.c b/src/i915_video.c
index aeb3729..e27854e 100644
--- a/src/i915_video.c
+++ b/src/i915_video.c
@@ -130,7 +130,7 @@ I915DisplayVideoTextured(ScrnInfoPtr pScrn, I830PortPrivPtr pPriv, int id,
    OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
    OUT_BATCH(BUF_3D_ID_COLOR_BACK | BUF_3D_USE_FENCE |
 	     BUF_3D_PITCH(intel_get_pixmap_pitch(pPixmap)));
-   OUT_BATCH(BUF_3D_ADDR(intel_get_pixmap_offset(pPixmap)));
+   OUT_RELOC_PIXMAP(pPixmap, 0);
    ADVANCE_BATCH();
 
    if (!planar) {
commit bade7d7d2505a10a8a7d24b084aff9742e2d6d64
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 6 14:03:25 2008 -0700

    Use the DRM for submitting batchbuffers when available.
    
    There are some concerns with this, as the DRM will be setting the nonsecure
    flag on the batchbuffer, and the server may be submitting some secure-only
    commands.  It appears to work on the 915GM test system currently.

diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 82758a2..976a405 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -100,18 +100,35 @@ intel_batch_flush(ScrnInfoPtr pScrn)
 
     dri_process_relocs(pI830->batch_bo);
 
-    if (!IS_I830(pI830) && !IS_845G(pI830)) {
-	BEGIN_LP_RING(2);
-	OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-	OUT_RING(pI830->batch_bo->offset);
-	ADVANCE_LP_RING();
+    if (pI830->directRenderingEnabled) {
+	struct drm_i915_batchbuffer batch;
+	int ret;
+
+	batch.start = pI830->batch_bo->offset;
+	batch.used = pI830->batch_used;
+	batch.cliprects = NULL;
+	batch.num_cliprects = 0;
+	batch.DR1 = 0;
+	batch.DR4 = 0xffffffff;
+
+	ret = drmCommandWrite(pI830->drmSubFD, DRM_I915_BATCHBUFFER,
+			      &batch, sizeof(batch));
+	if (ret != 0)
+	    FatalError("Failed to submit batchbuffer: %s\n", strerror(errno));
     } else {
-	BEGIN_LP_RING(4);
-	OUT_RING(MI_BATCH_BUFFER);
-	OUT_RING(pI830->batch_bo->offset);
-	OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
-	OUT_RING(MI_NOOP);
-	ADVANCE_LP_RING();
+	if (!IS_I830(pI830) && !IS_845G(pI830)) {
+	    BEGIN_LP_RING(2);
+	    OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+	    OUT_RING(pI830->batch_bo->offset);
+	    ADVANCE_LP_RING();
+	} else {
+	    BEGIN_LP_RING(4);
+	    OUT_RING(MI_BATCH_BUFFER);
+	    OUT_RING(pI830->batch_bo->offset);
+	    OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
+	    OUT_RING(MI_NOOP);
+	    ADVANCE_LP_RING();
+	}
     }
 
     dri_post_submit(pI830->batch_bo);
commit 6e94affcc2240e668bcf1aa41f3c8b19929d144b
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Jun 6 14:01:05 2008 -0700

    Avoid needless flush emits in the blockhandler.
    
    The EmitFlush in i830_dri.c was added as a pageflipping workaround, and was
    noted to not even be sufficient then.  There's no reason for it to be there,
    so it's removed.  After that, we just have to not emit an MI_FLUSH if we
    already had, and cursor movement no longer bashes memory manager.

diff --git a/src/i830.h b/src/i830.h
index ccf91a0..403cd63 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -463,6 +463,8 @@ typedef struct _I830Rec {
 #endif
 #endif
 
+   Bool need_mi_flush;
+
    Bool NeedRingBufferLow;
    Bool allowPageFlip;
    Bool TripleBuffer;
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
index 19d642d..82758a2 100644
--- a/src/i830_batchbuffer.c
+++ b/src/i830_batchbuffer.c
@@ -32,10 +32,12 @@
 
 #include <assert.h>
 #include <stdlib.h>
+#include <errno.h>
 
 #include "xf86.h"
 #include "i830.h"
 #include "i830_ring.h"
+#include "i915_drm.h"
 
 static void
 intel_next_batch(ScrnInfoPtr pScrn)
@@ -116,4 +118,10 @@ intel_batch_flush(ScrnInfoPtr pScrn)
 
     dri_bo_unreference(pI830->batch_bo);
     intel_next_batch(pScrn);
+
+    /* Mark that we need to flush whatever potential rendering we've done in the
+     * blockhandler.  We could set this less often, but it's probably not worth
+     * the work.
+     */
+    pI830->need_mi_flush = TRUE;
 }
diff --git a/src/i830_dri.c b/src/i830_dri.c
index 95e1e72..8ec51fc 100644
--- a/src/i830_dri.c
+++ b/src/i830_dri.c
@@ -1067,8 +1067,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
       pI830->LockHeld = 1;
       i830_refresh_ring(pScrn);
 
-      I830EmitFlush(pScrn);
-
 #ifdef DAMAGE
       if (!pI830->pDamage && pI830->allowPageFlip) {
 	 PixmapPtr pPix  = pScreen->GetScreenPixmap(pScreen);
@@ -1122,8 +1120,6 @@ I830DRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
       }
 #endif
 
-      I830EmitFlush(pScrn);
-
 #ifdef DAMAGE
       /* Try flipping back to the front page if necessary */
       if (sPriv && !sPriv->pf_enabled && sPriv->pf_current_page != 0) {
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 3a9d425..cb9644e 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -2496,17 +2496,17 @@ I830BlockHandler(int i,
     if (pScrn->vtSema && !pI830->noAccel) {
        /* Emit a flush of the rendering cache, or on the 965 and beyond
 	* rendering results may not hit the framebuffer until significantly
-	* later.  In the direct rendering case this is already done just
-	* after the page flipping updates, so there's no need to duplicate
-	* the effort here.
+	* later.
 	*/
-       if (!pI830->noAccel && !pI830->directRenderingEnabled)
+       if (!pI830->noAccel && pI830->need_mi_flush)
 	  I830EmitFlush(pScrn);
 
        /* Flush the batch, so that any rendering is executed in a timely
 	* fashion.
 	*/
        intel_batch_flush(pScrn);
+
+       pI830->need_mi_flush = FALSE;
     }
 
     /*
commit b2216e7bc2f1a35f9fc1794bad83208cd5c583d1
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Jun 4 16:31:16 2008 -0700

    Use batchbuffers instead of ring emits for general commands.
    
    The batchbuffers are managed using libdrm and bufmgr_fake, and dispatched from
    the ring from userland.

diff --git a/src/Makefile.am b/src/Makefile.am
index 0784c06..7ab1f08 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -89,6 +89,8 @@ intel_drv_la_SOURCES = \
          i830_accel.c \
          i830_bios.c \
          i830_bios.h \
+         i830_batchbuffer.c \
+         i830_batchbuffer.h \
          i830_common.h \
 	 i830_crt.c \
          i830_cursor.c \
diff --git a/src/i810_reg.h b/src/i810_reg.h
index d8e0cb2..6a82c19 100644
--- a/src/i810_reg.h
+++ b/src/i810_reg.h
@@ -2379,6 +2379,13 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 #define STATE3D_COLOR_FACTOR	((0x3<<29)|(0x1d<<24)|(0x01<<16))
 
+/* Batch */
+#define MI_BATCH_BUFFER		((0x30 << 23) | 1)
+#define MI_BATCH_BUFFER_START	(0x31 << 23)
+#define MI_BATCH_BUFFER_END	(0xA << 23)
+#define MI_BATCH_NON_SECURE		(1)
+#define MI_BATCH_NON_SECURE_I965	(1 << 8)
+
 /* STATE3D_FOG_MODE stuff */
 #define ENABLE_FOG_SOURCE	(1<<27)
 #define ENABLE_FOG_CONST	(1<<24)
diff --git a/src/i830.h b/src/i830.h
index 9cce5bc..ccf91a0 100644
--- a/src/i830.h
+++ b/src/i830.h
@@ -81,6 +81,8 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "damage.h"
 #endif
 #endif
+#include "dri_bufmgr.h"
+#include "intel_bufmgr.h"
 
 #ifdef I830_USE_EXA
 #include "exa.h"
@@ -95,7 +97,6 @@ Bool I830XAAInit(ScreenPtr pScreen);
 typedef struct _I830OutputRec I830OutputRec, *I830OutputPtr;
 
 #include "common.h"
-#include "i830_ring.h"
 #include "i830_sdvo.h"
 #include "i2c_vid.h"
 
@@ -401,6 +402,8 @@ typedef struct _I830Rec {
    i830_memory *exa_offscreen;
    i830_memory *gen4_render_state_mem;
 #endif
+   i830_memory *fake_bufmgr_mem;
+
    /* Regions allocated either from the above pools, or from agpgart. */
    I830RingBuffer *LpRing;
 
@@ -411,6 +414,17 @@ typedef struct _I830Rec {
    /** Offset in the ring for the next DWORD emit */
    uint32_t ring_next;
 
+   dri_bufmgr *bufmgr;
+
+   uint8_t *batch_ptr;
+   /** Byte offset in batch_ptr for the next dword to be emitted. */
+   unsigned int batch_used;
+   /** Position in batch_ptr at the start of the current BEGIN_BATCH */
+   unsigned int batch_emit_start;
+   /** Number of bytes to be emitted in the current BEGIN_BATCH. */
+   uint32_t batch_emitting;
+   dri_bo *batch_bo;
+
 #ifdef I830_XV
    /* For Xvideo */
    i830_memory *overlay_regs;
@@ -674,6 +688,9 @@ typedef struct _I830Rec {
 #define I830_SELECT_DEPTH	2
 #define I830_SELECT_THIRD	3
 
+/* Batchbuffer support macros and functions */
+#include "i830_batchbuffer.h"
+
 /* I830 specific functions */
 extern int I830WaitLpRing(ScrnInfoPtr pScrn, int n, int timeout_millis);
 extern void I830SetPIOAccess(I830Ptr pI830);
@@ -898,13 +915,6 @@ Bool i830_pixmap_tiled(PixmapPtr p);
     if (pitch > KB(8)) I830FALLBACK("pitch exceeds 3d limit 8K\n");\
 } while(0)
 
-/* Batchbuffer compatibility handling */
-#define BEGIN_BATCH(n) BEGIN_LP_RING(n)
-#define ENSURE_BATCH(n)
-#define OUT_BATCH(d) OUT_RING(d)
-#define OUT_BATCH_F(x) OUT_RING_F(x)
-#define ADVANCE_BATCH() ADVANCE_LP_RING()
-
 extern const int I830PatternROP[16];
 extern const int I830CopyROP[16];
 
diff --git a/src/i830_accel.c b/src/i830_accel.c
index 7784c62..a71ea47 100644
--- a/src/i830_accel.c
+++ b/src/i830_accel.c
@@ -59,6 +59,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include "i830.h"
 #include "i810_reg.h"
 #include "i830_debug.h"
+#include "i830_ring.h"
 
 unsigned long
 intel_get_pixmap_offset(PixmapPtr pPix)
@@ -168,7 +169,6 @@ void
 I830Sync(ScrnInfoPtr pScrn)
 {
    I830Ptr pI830 = I830PTR(pScrn);
-   int flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE;
 
    if (I810_DEBUG & (DEBUG_VERBOSE_ACCEL | DEBUG_VERBOSE_SYNC))
       ErrorF("I830Sync\n");
@@ -186,24 +186,12 @@ I830Sync(ScrnInfoPtr pScrn)
 
    if (pI830->entityPrivate && !pI830->entityPrivate->RingRunning) return;
 
-   if (IS_I965G(pI830))
-      flags = 0;
+   I830EmitFlush(pScrn);
 
-   /* Send a flush instruction and then wait till the ring is empty.
-    * This is stronger than waiting for the blitter to finish as it also
-    * flushes the internal graphics caches.
-    */
-   
-   {
-      BEGIN_BATCH(2);
-      OUT_BATCH(MI_FLUSH | flags);
-      OUT_BATCH(MI_NOOP);		/* pad to quadword */
-      ADVANCE_BATCH();
-   }
+   intel_batch_flush(pScrn);
 
    i830_wait_ring_idle(pScrn);
 
-   pI830->LpRing->space = pI830->LpRing->mem->size - 8;
    pI830->nextColorExpandBuf = 0;
 }
 
diff --git a/src/i830_batchbuffer.c b/src/i830_batchbuffer.c
new file mode 100644
index 0000000..19d642d
--- /dev/null
+++ b/src/i830_batchbuffer.c
@@ -0,0 +1,119 @@
+/* -*- c-basic-offset: 4 -*- */
+/*
+ * Copyright © 2006 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ *    Eric Anholt <eric at anholt.net>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "xf86.h"
+#include "i830.h"
+#include "i830_ring.h"
+
+static void
+intel_next_batch(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    /* The 865 has issues with larger-than-page-sized batch buffers. */
+    if (IS_I865G(pI830))
+	pI830->batch_bo = dri_bo_alloc(pI830->bufmgr, "batch", 4096, 4096);
+    else
+	pI830->batch_bo = dri_bo_alloc(pI830->bufmgr, "batch", 4096 * 4, 4096);
+
+    dri_bo_map(pI830->batch_bo, 1);
+    pI830->batch_used = 0;
+    pI830->batch_ptr = pI830->batch_bo->virtual;
+}
+
+void
+intel_batch_init(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    pI830->batch_emit_start = 0;
+    pI830->batch_emitting = 0;
+
+    intel_next_batch(pScrn);
+}
+
+void
+intel_batch_teardown(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pI830->batch_ptr != NULL) {
+	dri_bo_unmap(pI830->batch_bo);
+	pI830->batch_ptr = NULL;
+    }
+}
+
+void
+intel_batch_flush(ScrnInfoPtr pScrn)
+{
+    I830Ptr pI830 = I830PTR(pScrn);
+
+    if (pI830->batch_used == 0)
+	return;
+
+    /* Emit a padding dword if we aren't going to be quad-word aligned. */
+    if ((pI830->batch_used & 4) == 0) {
+	*(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = MI_NOOP;
+	pI830->batch_used += 4;
+    }
+
+    /* Mark the end of the batchbuffer. */
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = MI_BATCH_BUFFER_END;
+    pI830->batch_used += 4;
+
+    dri_bo_unmap(pI830->batch_bo);
+    pI830->batch_ptr = NULL;
+
+    dri_process_relocs(pI830->batch_bo);
+
+    if (!IS_I830(pI830) && !IS_845G(pI830)) {
+	BEGIN_LP_RING(2);
+	OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
+	OUT_RING(pI830->batch_bo->offset);
+	ADVANCE_LP_RING();
+    } else {
+	BEGIN_LP_RING(4);
+	OUT_RING(MI_BATCH_BUFFER);
+	OUT_RING(pI830->batch_bo->offset);
+	OUT_RING(pI830->batch_bo->offset + pI830->batch_used - 4);
+	OUT_RING(MI_NOOP);
+	ADVANCE_LP_RING();
+    }
+
+    dri_post_submit(pI830->batch_bo);
+
+    dri_bo_unreference(pI830->batch_bo);
+    intel_next_batch(pScrn);
+}
diff --git a/src/i830_batchbuffer.h b/src/i830_batchbuffer.h
new file mode 100644
index 0000000..9179326
--- /dev/null
+++ b/src/i830_batchbuffer.h
@@ -0,0 +1,106 @@
+/**************************************************************************
+
+Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
+Copyright © 2002 David Dawes
+
+All Rights Reserved.
+
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sub license, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice (including the
+next paragraph) shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR
+ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+**************************************************************************/
+
+#ifndef _INTEL_BATCHBUFFER_H
+#define _INTEL_BATCHBUFFER_H
+
+#define BATCH_RESERVED		16
+
+void intel_batch_init(ScrnInfoPtr pScrn);
+void intel_batch_teardown(ScrnInfoPtr pScrn);
+void intel_batch_flush(ScrnInfoPtr pScrn);
+
+static inline int
+intel_batch_space(I830Ptr pI830)
+{
+    return (pI830->batch_bo->size - BATCH_RESERVED) - (pI830->batch_used);
+}
+
+static inline void
+intel_batch_require_space(ScrnInfoPtr pScrn, I830Ptr pI830, GLuint sz)
+{
+    assert(sz < pI830->batch_bo->size - 8);
+    if (intel_batch_space(pI830) < sz)
+	intel_batch_flush(pScrn);
+}
+
+static inline void
+intel_batch_emit_dword(I830Ptr pI830, uint32_t dword)
+{
+    assert(pI830->batch_ptr != NULL);
+    assert(intel_batch_space(pI830) >= 4);
+    *(uint32_t *)(pI830->batch_ptr + pI830->batch_used) = dword;
+    pI830->batch_used += 4;
+}
+
+#define OUT_BATCH(dword) intel_batch_emit_dword(pI830, dword)
+
+union intfloat {
+	float f;
+	unsigned int ui;
+};
+
+#define OUT_BATCH_F(x) do {			\
+	union intfloat tmp;			\
+	tmp.f = (float)(x);			\
+	OUT_BATCH(tmp.ui);			\
+} while(0)
+
+#define BEGIN_BATCH(n)							\
+do {									\
+    if (pI830->batch_emitting != 0)					\
+	FatalError("%s: BEGIN_BATCH called without closing "		\
+		   "ADVANCE_BATCH\n", __FUNCTION__);			\
+    pI830->batch_emitting = (n) * 4;					\
+    intel_batch_require_space(pScrn, pI830, pI830->batch_emitting);	\
+    pI830->batch_emit_start = pI830->batch_used;			\
+} while (0)
+
+#define ADVANCE_BATCH() do {						\
+    if (pI830->batch_emitting == 0)					\
+	FatalError("%s: ADVANCE_BATCH called with no matching "		\
+		   "BEGIN_BATCH\n", __FUNCTION__);			\
+    if (pI830->batch_used > pI830->batch_emit_start + pI830->batch_emitting) \
+	FatalError("%s: ADVANCE_BATCH: exceeded allocation %d/%d\n ",	\
+		   __FUNCTION__,					\
+		   pI830->batch_used - pI830->batch_emit_start,		\
+		   pI830->batch_emitting);				\
+    if (pI830->batch_used < pI830->batch_emit_start + pI830->batch_emitting) \
+	FatalError("%s: ADVANCE_BATCH: under-used allocation %d/%d\n ", \
+		   __FUNCTION__,					\
+		   pI830->batch_used - pI830->batch_emit_start,		\
+		   pI830->batch_emitting);				\
+    if ((pI830->batch_emitting > 8) && (I810_DEBUG & DEBUG_ALWAYS_SYNC)) { \
+	/* Note: not actually syncing, just flushing each batch. */	\
+	intel_batch_flush(pScrn);					\
+    }									\
+    pI830->batch_emitting = 0;						\
+} while (0)
+
+#endif /* _INTEL_BATCHBUFFER_H */
diff --git a/src/i830_driver.c b/src/i830_driver.c
index 35df0c7..3a9d425 100644
--- a/src/i830_driver.c
+++ b/src/i830_driver.c
@@ -1838,7 +1838,7 @@ i830_stop_ring(ScrnInfoPtr pScrn, Bool flush)
       temp = INREG(LP_RING + RING_LEN);
       if (temp & RING_VALID) {
 	 i830_refresh_ring(pScrn);
-	 I830Sync(pScrn);
+	 i830_wait_ring_idle(pScrn);
       }
 
       OUTREG(LP_RING + RING_LEN, 0);
@@ -2493,14 +2493,21 @@ I830BlockHandler(int i,
     pI830->BlockHandler = pScreen->BlockHandler;
     pScreen->BlockHandler = I830BlockHandler;
 
-    /* Emit a flush of the rendering cache, or on the 965 and beyond
-     * rendering results may not hit the framebuffer until significantly
-     * later.  In the direct rendering case this is already done just
-     * after the page flipping updates, so there's no need to duplicate
-     * the effort here.
-     */
-    if (pScrn->vtSema && !pI830->noAccel && !pI830->directRenderingEnabled)
-	I830EmitFlush(pScrn);
+    if (pScrn->vtSema && !pI830->noAccel) {
+       /* Emit a flush of the rendering cache, or on the 965 and beyond
+	* rendering results may not hit the framebuffer until significantly
+	* later.  In the direct rendering case this is already done just
+	* after the page flipping updates, so there's no need to duplicate
+	* the effort here.
+	*/
+       if (!pI830->noAccel && !pI830->directRenderingEnabled)
+	  I830EmitFlush(pScrn);
+
+       /* Flush the batch, so that any rendering is executed in a timely
+	* fashion.
+	*/
+       intel_batch_flush(pScrn);
+    }
 
     /*
      * Check for FIFO underruns at block time (which amounts to just
@@ -2704,6 +2711,55 @@ i830_memory_init(ScrnInfoPtr pScrn)
     return FALSE;
 }
 
+/**
+ * Returns a cookie to be waited on.  This is just a stub implementation, and
+ * should be hooked up to the emit/wait irq functions when available (DRI
+ * enabled).
+ */
+static unsigned int
+i830_fake_fence_emit(void *priv)
+{
+   static unsigned int fence = 0;
+
+   /* Match DRM in not using half the range. The fake bufmgr relies on this. */
+   if (++fence >= 0x8000000)
+      fence = 1;
+
+   return fence;
+}
+
+/**
+ * Waits on a cookie representing a request to be passed.
+ *
+ * Stub implementation that should be replaced with DRM functions when
+ * available.
+ */
+static int
+i830_fake_fence_wait(void *priv, unsigned int fence)
+{
+   ScrnInfoPtr pScrn = priv;
+
+   i830_wait_ring_idle(pScrn);
+
+   return 0;
+}
+
+static void
+i830_init_bufmgr(ScrnInfoPtr pScrn)
+{
+   I830Ptr pI830 = I830PTR(pScrn);
+
+   assert(pI830->FbBase != NULL);
+   pI830->bufmgr = intel_bufmgr_fake_init(pI830->fake_bufmgr_mem->offset,
+					  pI830->FbBase +
+					  pI830->fake_bufmgr_mem->offset,
+					  pI830->fake_bufmgr_mem->size,
+					  i830_fake_fence_emit,
+					  i830_fake_fence_wait,
+					  pScrn);
+}
+
+
 static Bool
 I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
 {
@@ -3033,6 +3089,8 @@ I830ScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
    pI830->xoffset = (pScrn->fbOffset / pI830->cpp) % pScrn->displayWidth;
    pI830->yoffset = (pScrn->fbOffset / pI830->cpp) / pScrn->displayWidth;
 
+   i830_init_bufmgr(pScrn);
+
    vgaHWSetMmioFuncs(hwp, pI830->MMIOBase, 0);
    vgaHWGetIOBase(hwp);
    DPRINTF(PFX, "assert( if(!vgaHWMapMem(pScrn)) )\n");
@@ -3276,8 +3334,13 @@ I830LeaveVT(int scrnIndex, int flags)
 
    xf86_hide_cursors (pScrn);
 
+   I830Sync(pScrn);
+
    RestoreHWState(pScrn);
 
+   intel_bufmgr_fake_evict_all(pI830->bufmgr);
+   intel_batch_teardown(pScrn);
+
    i830_stop_ring(pScrn, TRUE);
 
    if (pI830->debug_modes) {
@@ -3351,6 +3414,8 @@ I830EnterVT(int scrnIndex, int flags)
    /* Update the screen pixmap in case the buffer moved */
    i830_update_front_offset(pScrn);
 
+   intel_batch_init(pScrn);
+
    if (IS_I965G(pI830))
       gen4_render_state_init(pScrn);
 
@@ -3478,6 +3543,9 @@ I830CloseScreen(int scrnIndex, ScreenPtr pScreen)
       I830LeaveVT(scrnIndex, 0);
    }
 
+   dri_bufmgr_destroy(pI830->bufmgr);
+   pI830->bufmgr = NULL;
+
    if (pI830->devicesTimer)
       TimerCancel(pI830->devicesTimer);
    pI830->devicesTimer = NULL;
diff --git a/src/i830_memory.c b/src/i830_memory.c
index dc48967..57e4f2e 100644
--- a/src/i830_memory.c
+++ b/src/i830_memory.c
@@ -350,6 +350,7 @@ i830_reset_allocations(ScrnInfoPtr pScrn)
     pI830->textures = NULL;
 #endif
     pI830->LpRing->mem = NULL;
+    pI830->fake_bufmgr_mem = NULL;
 }
 
 void
@@ -1374,6 +1375,14 @@ i830_allocate_2d_memory(ScrnInfoPtr pScrn)
 	return FALSE;
     }
 
+    pI830->fake_bufmgr_mem = i830_allocate_memory(pScrn, "fake bufmgr",
+						  MB(1), GTT_PAGE_SIZE, 0);
+    if (pI830->fake_bufmgr_mem == NULL) {
+	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+		   "Failed to allocate fake bufmgr space.\n");
+	return FALSE;
+    }
+
     /* even in XAA, 965G needs state mem buffer for rendering */
     if (IS_I965G(pI830) && !pI830->noAccel &&
 	pI830->gen4_render_state_mem == NULL)
diff --git a/src/i830_ring.h b/src/i830_ring.h
index c2078fb..c296d41 100644
--- a/src/i830_ring.h
+++ b/src/i830_ring.h
@@ -42,11 +42,6 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     pI830->ring_next &= pI830->LpRing->tail_mask;			\
 } while (0)
 
-union intfloat {
-	float f;
-	unsigned int ui;
-};
-
 #define OUT_RING_F(x) do {			\
 	union intfloat tmp;			\
 	tmp.f = (float)(x);			\
diff --git a/src/i915_3d.h b/src/i915_3d.h
index 1a0bd45..d3330e5 100644
--- a/src/i915_3d.h
+++ b/src/i915_3d.h
@@ -446,12 +446,12 @@ do {									\
 #define FS_END()							\
 do {									\
     int _i, _pad = (_cur_shader_commands & 0x1) ? 0 : 1;		\
-    BEGIN_LP_RING(_cur_shader_commands * 3 + 1 + _pad);			\
-    OUT_RING(_3DSTATE_PIXEL_SHADER_PROGRAM |				\
+    BEGIN_BATCH(_cur_shader_commands * 3 + 1 + _pad);			\
+    OUT_BATCH(_3DSTATE_PIXEL_SHADER_PROGRAM |				\
 	     (_cur_shader_commands * 3 - 1));				\
     for (_i = 0; _i < _cur_shader_commands * 3; _i++)			\
-	OUT_RING(_shader_buf[_i]);					\
+	OUT_BATCH(_shader_buf[_i]);					\
     if (_pad != 0)							\
-	OUT_RING(MI_NOOP);						\
-    ADVANCE_LP_RING();							\
+	OUT_BATCH(MI_NOOP);						\
+    ADVANCE_BATCH();							\
 } while (0);


More information about the xorg-commit mailing list