i915: Remove state batch emit support.
[mesa.git] / src / mesa / drivers / dri / i915 / intel_batchbuffer.c
index 323d0b22122f2f016c90f1b17c9d1f26df7e4c69..1857fea28dd85a46852401e917f60a2b46db7733 100644 (file)
@@ -1,6 +1,6 @@
 /**************************************************************************
  * 
- * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
  * All Rights Reserved.
  * 
  * Permission is hereby granted, free of charge, to any person obtaining a
  * 
  **************************************************************************/
 
-
-#include <stdio.h>
-#include <errno.h>
-
-#include "mtypes.h"
-#include "context.h"
-#include "enums.h"
-
-#include "intel_reg.h"
-#include "intel_batchbuffer.h"
 #include "intel_context.h"
+#include "intel_batchbuffer.h"
+#include "intel_buffer_objects.h"
+#include "intel_reg.h"
+#include "intel_bufmgr.h"
+#include "intel_buffers.h"
 
+static void
+intel_batchbuffer_reset(struct intel_context *intel);
 
-
-
-/* ================================================================
- * Performance monitoring functions
- */
-
-static void intel_fill_box( intelContextPtr intel,
-                           GLshort x, GLshort y,
-                           GLshort w, GLshort h,
-                           GLubyte r, GLubyte g, GLubyte b )
+void
+intel_batchbuffer_init(struct intel_context *intel)
 {
-   x += intel->drawX;
-   y += intel->drawY;
-
-   if (x >= 0 && y >= 0 &&
-       x+w < intel->intelScreen->width &&
-       y+h < intel->intelScreen->height)
-      intelEmitFillBlitLocked( intel, 
-                              intel->intelScreen->cpp,
-                              intel->intelScreen->back.pitch,
-                              intel->intelScreen->back.offset,
-                              x, y, w, h,
-                              INTEL_PACKCOLOR(intel->intelScreen->fbFormat,
-                                              r,g,b,0xff));
+   intel_batchbuffer_reset(intel);
+
+   intel->batch.cpu_map = malloc(intel->maxBatchSize);
+   intel->batch.map = intel->batch.cpu_map;
 }
 
-static void intel_draw_performance_boxes( intelContextPtr intel )
+static void
+intel_batchbuffer_reset(struct intel_context *intel)
 {
-   /* Purple box for page flipping
-    */
-   if ( intel->perf_boxes & I830_BOX_FLIP ) 
-      intel_fill_box( intel, 4, 4, 8, 8, 255, 0, 255 );
-
-   /* Red box if we have to wait for idle at any point
-    */
-   if ( intel->perf_boxes & I830_BOX_WAIT ) 
-      intel_fill_box( intel, 16, 4, 8, 8, 255, 0, 0 );
-
-   /* Blue box: lost context?
-    */
-   if ( intel->perf_boxes & I830_BOX_LOST_CONTEXT ) 
-      intel_fill_box( intel, 28, 4, 8, 8, 0, 0, 255 );
-
-   /* Yellow box for texture swaps
-    */
-   if ( intel->perf_boxes & I830_BOX_TEXTURE_LOAD ) 
-      intel_fill_box( intel, 40, 4, 8, 8, 255, 255, 0 );
-
-   /* Green box if hardware never idles (as far as we can tell)
-    */
-   if ( !(intel->perf_boxes & I830_BOX_RING_EMPTY) ) 
-      intel_fill_box( intel, 64, 4, 8, 8, 0, 255, 0 );
-
-
-   /* Draw bars indicating number of buffers allocated 
-    * (not a great measure, easily confused)
-    */
-#if 0
-   if (intel->dma_used) {
-      int bar = intel->dma_used / 10240;
-      if (bar > 100) bar = 100;
-      if (bar < 1) bar = 1;
-      intel_fill_box( intel, 4, 16, bar, 4, 196, 128, 128 );
-      intel->dma_used = 0;
+   if (intel->batch.last_bo != NULL) {
+      drm_intel_bo_unreference(intel->batch.last_bo);
+      intel->batch.last_bo = NULL;
    }
-#endif
-
-   intel->perf_boxes = 0;
-}
-
-
+   intel->batch.last_bo = intel->batch.bo;
 
+   intel->batch.bo = drm_intel_bo_alloc(intel->bufmgr, "batchbuffer",
+                                       intel->maxBatchSize, 4096);
 
-
-
-static int bad_prim_vertex_nr( int primitive, int nr )
-{
-   switch (primitive & PRIM3D_MASK) {
-   case PRIM3D_POINTLIST:
-      return nr < 1;
-   case PRIM3D_LINELIST:
-      return (nr & 1) || nr == 0;
-   case PRIM3D_LINESTRIP:
-      return nr < 2;
-   case PRIM3D_TRILIST:
-   case PRIM3D_RECTLIST:
-      return nr % 3 || nr == 0;
-   case PRIM3D_POLY:
-   case PRIM3D_TRIFAN:
-   case PRIM3D_TRISTRIP:
-   case PRIM3D_TRISTRIP_RVRSE:
-      return nr < 3;
-   default:
-      return 1;
-   }   
+   intel->batch.reserved_space = BATCH_RESERVED;
+   intel->batch.used = 0;
 }
 
-static void intel_flush_inline_primitive( GLcontext *ctx )
+void
+intel_batchbuffer_free(struct intel_context *intel)
 {
-   intelContextPtr intel = INTEL_CONTEXT( ctx );
-   GLuint used = intel->batch.ptr - intel->prim.start_ptr;
-   GLuint vertcount;
-
-   assert(intel->prim.primitive != ~0);
-
-   if (1) {
-      /* Check vertex size against the vertex we're specifying to
-       * hardware.  If it's wrong, ditch the primitive.
-       */ 
-      if (!intel->vtbl.check_vertex_size( intel, intel->vertex_size )) 
-        goto do_discard;
-
-      vertcount = (used - 4)/ (intel->vertex_size * 4);
-
-      if (!vertcount)
-        goto do_discard;
-      
-      if (vertcount * intel->vertex_size * 4 != used - 4) {
-        fprintf(stderr, "vertex size confusion %d %d\n", used, 
-                intel->vertex_size * vertcount * 4);
-        goto do_discard;
-      }
-
-      if (bad_prim_vertex_nr( intel->prim.primitive, vertcount )) {
-        fprintf(stderr, "bad_prim_vertex_nr %x %d\n", intel->prim.primitive,
-                vertcount);
-        goto do_discard;
-      }
-   }
-
-   if (used < 8)
-      goto do_discard;
-
-   *(int *)intel->prim.start_ptr = (_3DPRIMITIVE | 
-                                   intel->prim.primitive |
-                                   (used/4-2));
-
-   goto finished;
-   
- do_discard:
-   intel->batch.ptr -= used;
-   intel->batch.space += used;
-   assert(intel->batch.space >= 0);
-
- finished:
-   intel->prim.primitive = ~0;
-   intel->prim.start_ptr = 0;
-   intel->prim.flush = 0;
+   free(intel->batch.cpu_map);
+   drm_intel_bo_unreference(intel->batch.last_bo);
+   drm_intel_bo_unreference(intel->batch.bo);
 }
 
-
-/* Emit a primitive referencing vertices in a vertex buffer.
- */
-void intelStartInlinePrimitive( intelContextPtr intel, GLuint prim )
+static void
+do_batch_dump(struct intel_context *intel)
 {
-   BATCH_LOCALS;
-
-   if (0)
-      fprintf(stderr, "%s %x\n", __FUNCTION__, prim);
+   struct drm_intel_decode *decode;
+   struct intel_batchbuffer *batch = &intel->batch;
+   int ret;
 
+   decode = drm_intel_decode_context_alloc(intel->intelScreen->deviceID);
+   if (!decode)
+      return;
 
-   /* Finish any in-progress primitive:
-    */
-   INTEL_FIREVERTICES( intel );
-   
-   /* Emit outstanding state:
-    */
-   intel->vtbl.emit_state( intel );
-   
-   /* Make sure there is some space in this buffer:
-    */
-   if (intel->vertex_size * 10 * sizeof(GLuint) >= intel->batch.space) {
-      intelFlushBatch(intel, GL_TRUE); 
-      intel->vtbl.emit_state( intel );
+   ret = drm_intel_bo_map(batch->bo, false);
+   if (ret == 0) {
+      drm_intel_decode_set_batch_pointer(decode,
+                                        batch->bo->virtual,
+                                        batch->bo->offset,
+                                        batch->used);
+   } else {
+      fprintf(stderr,
+             "WARNING: failed to map batchbuffer (%s), "
+             "dumping uploaded data instead.\n", strerror(ret));
+
+      drm_intel_decode_set_batch_pointer(decode,
+                                        batch->map,
+                                        batch->bo->offset,
+                                        batch->used);
    }
 
-#if 1
-   if (((int)intel->batch.ptr) & 0x4) {
-      BEGIN_BATCH(1);
-      OUT_BATCH(0);
-      ADVANCE_BATCH();
-   }
-#endif
+   drm_intel_decode(decode);
 
-   /* Emit a slot which will be filled with the inline primitive
-    * command later.
-    */
-   BEGIN_BATCH(2);
-   OUT_BATCH( 0 );
+   drm_intel_decode_context_free(decode);
 
-   intel->prim.start_ptr = batch_ptr;
-   intel->prim.primitive = prim;
-   intel->prim.flush = intel_flush_inline_primitive;
-   intel->batch.contains_geometry = 1;
+   if (ret == 0) {
+      drm_intel_bo_unmap(batch->bo);
 
-   OUT_BATCH( 0 );
-   ADVANCE_BATCH();
+      if (intel->vtbl.debug_batch != NULL)
+        intel->vtbl.debug_batch(intel);
+   }
 }
 
-
-void intelRestartInlinePrimitive( intelContextPtr intel )
+/* TODO: Push this whole function into bufmgr.
+ */
+static int
+do_flush_locked(struct intel_context *intel)
 {
-   GLuint prim = intel->prim.primitive;
+   struct intel_batchbuffer *batch = &intel->batch;
+   int ret = 0;
 
-   intel_flush_inline_primitive( &intel->ctx );
-   if (1) intelFlushBatch(intel, GL_TRUE); /* GL_TRUE - is critical */
-   intelStartInlinePrimitive( intel, prim );
-}
+   ret = drm_intel_bo_subdata(batch->bo, 0, 4*batch->used, batch->map);
 
+   if (!intel->intelScreen->no_hw) {
+      if (ret == 0) {
+         if (unlikely(INTEL_DEBUG & DEBUG_AUB) && intel->vtbl.annotate_aub)
+            intel->vtbl.annotate_aub(intel);
+         ret = drm_intel_bo_mrb_exec(batch->bo, 4 * batch->used, NULL, 0, 0,
+                                     I915_EXEC_RENDER);
+      }
+   }
 
+   if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
+      do_batch_dump(intel);
 
-void intelWrapInlinePrimitive( intelContextPtr intel )
-{
-   GLuint prim = intel->prim.primitive;
+   if (ret != 0) {
+      fprintf(stderr, "intel_do_flush_locked failed: %s\n", strerror(-ret));
+      exit(1);
+   }
+   intel->vtbl.new_batch(intel);
 
-   if (0)
-      fprintf(stderr, "%s\n", __FUNCTION__);
-   intel_flush_inline_primitive( &intel->ctx );
-   intelFlushBatch(intel, GL_TRUE);
-   intelStartInlinePrimitive( intel, prim );
+   return ret;
 }
 
-
-/* Emit a primitive with space for inline vertices.
- */
-GLuint *intelEmitInlinePrimitiveLocked(intelContextPtr intel, 
-                                      int primitive,
-                                      int dwords,
-                                      int vertex_size )
+int
+_intel_batchbuffer_flush(struct intel_context *intel,
+                        const char *file, int line)
 {
-   GLuint *tmp = 0;
-   BATCH_LOCALS;
+   int ret;
 
-   if (0)
-      fprintf(stderr, "%s 0x%x %d\n", __FUNCTION__, primitive, dwords);
+   if (intel->batch.used == 0)
+      return 0;
 
-   /* Emit outstanding state:
-    */
-   intel->vtbl.emit_state( intel );
-
-   if ((1+dwords)*4 >= intel->batch.space) {
-      intelFlushBatch(intel, GL_TRUE); 
-      intel->vtbl.emit_state( intel );
+   if (intel->first_post_swapbuffers_batch == NULL) {
+      intel->first_post_swapbuffers_batch = intel->batch.bo;
+      drm_intel_bo_reference(intel->first_post_swapbuffers_batch);
    }
 
+   if (unlikely(INTEL_DEBUG & DEBUG_BATCH))
+      fprintf(stderr, "%s:%d: Batchbuffer flush with %db used\n", file, line,
+             4*intel->batch.used);
 
-   if (1) {
-      int used = dwords * 4;
-      int vertcount;
-
-      /* Check vertex size against the vertex we're specifying to
-       * hardware.  If it's wrong, ditch the primitive.
-       */ 
-      if (!intel->vtbl.check_vertex_size( intel, vertex_size )) 
-        goto do_discard;
+   intel->batch.reserved_space = 0;
 
-      vertcount = dwords / vertex_size;
-      
-      if (dwords % vertex_size) {
-        fprintf(stderr, "did not request a whole number of vertices\n");
-        goto do_discard;
-      }
+   if (intel->vtbl.finish_batch)
+      intel->vtbl.finish_batch(intel);
 
-      if (bad_prim_vertex_nr( primitive, vertcount )) {
-        fprintf(stderr, "bad_prim_vertex_nr %x %d\n", primitive, vertcount);
-        goto do_discard;
-      }
-
-      if (used < 8)
-        goto do_discard;
+   /* Mark the end of the buffer. */
+   intel_batchbuffer_emit_dword(intel, MI_BATCH_BUFFER_END);
+   if (intel->batch.used & 1) {
+      /* Round batchbuffer usage to 2 DWORDs. */
+      intel_batchbuffer_emit_dword(intel, MI_NOOP);
    }
 
-   /* Emit 3D_PRIMITIVE commands:
-    */
-   BEGIN_BATCH(1 + dwords);
-   OUT_BATCH( _3DPRIMITIVE | 
-             primitive |
-             (dwords-1) );
-
-   tmp = (GLuint *)batch_ptr;
-   batch_ptr += dwords * 4;
-
-   ADVANCE_BATCH();
-
-   intel->batch.contains_geometry = 1;
-
- do_discard:
-   return tmp;
-}
+   intel_upload_finish(intel);
 
+   /* Check that we didn't just wrap our batchbuffer at a bad time. */
+   assert(!intel->no_batch_wrap);
 
+   ret = do_flush_locked(intel);
 
-/*
- * Copy the back buffer to the front buffer. 
- */
-void intelCopyBuffer( const __DRIdrawablePrivate *dPriv ) 
-{
-   intelContextPtr intel;
-
-   if (0)
-      fprintf(stderr, "%s\n", __FUNCTION__);
-
-   assert(dPriv);
-   assert(dPriv->driContextPriv);
-   assert(dPriv->driContextPriv->driverPrivate);
-
-   intel = (intelContextPtr) dPriv->driContextPriv->driverPrivate;
-
-   intelFlush( &intel->ctx );
-   LOCK_HARDWARE( intel );
-   {
-      const intelScreenPrivate *intelScreen = intel->intelScreen;
-      const __DRIdrawablePrivate *dPriv = intel->driDrawable;
-      const int nbox = dPriv->numClipRects;
-      const drm_clip_rect_t *pbox = dPriv->pClipRects;
-      const int cpp = intelScreen->cpp;
-      const int pitch = intelScreen->front.pitch; /* in bytes */
-      int i;
-      GLuint CMD, BR13;
-      BATCH_LOCALS;
-
-      switch(cpp) {
-      case 2: 
-        BR13 = (pitch) | (0xCC << 16) | (1<<24);
-        CMD = XY_SRC_COPY_BLT_CMD;
-        break;
-      case 4:
-        BR13 = (pitch) | (0xCC << 16) | (1<<24) | (1<<25);
-        CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-               XY_SRC_COPY_BLT_WRITE_RGB);
-        break;
-      default:
-        BR13 = (pitch) | (0xCC << 16) | (1<<24);
-        CMD = XY_SRC_COPY_BLT_CMD;
-        break;
-      }
-   
-      if (0) 
-        intel_draw_performance_boxes( intel );
-
-      for (i = 0 ; i < nbox; i++, pbox++) 
-      {
-        if (pbox->x1 > pbox->x2 ||
-            pbox->y1 > pbox->y2 ||
-            pbox->x2 > intelScreen->width ||
-            pbox->y2 > intelScreen->height) {
-            _mesa_warning(&intel->ctx, "Bad cliprect in intelCopyBuffer()");
-           continue;
-         }
-
-        BEGIN_BATCH( 8);
-        OUT_BATCH( CMD );
-        OUT_BATCH( BR13 );
-        OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
-        OUT_BATCH( (pbox->y2 << 16) | pbox->x2 );
-
-        if (intel->sarea->pf_current_page == 0) 
-           OUT_BATCH( intelScreen->front.offset );
-        else
-           OUT_BATCH( intelScreen->back.offset );                      
-
-        OUT_BATCH( (pbox->y1 << 16) | pbox->x1 );
-        OUT_BATCH( BR13 & 0xffff );
-
-        if (intel->sarea->pf_current_page == 0) 
-           OUT_BATCH( intelScreen->back.offset );                      
-        else
-           OUT_BATCH( intelScreen->front.offset );
-
-        ADVANCE_BATCH();
-      }
+   if (unlikely(INTEL_DEBUG & DEBUG_SYNC)) {
+      fprintf(stderr, "waiting for idle\n");
+      drm_intel_bo_wait_rendering(intel->batch.bo);
    }
-   intelFlushBatchLocked( intel, GL_TRUE, GL_TRUE, GL_TRUE );
-   UNLOCK_HARDWARE( intel );
-}
-
-
 
+   /* Reset the buffer:
+    */
+   intel_batchbuffer_reset(intel);
 
-void intelEmitFillBlitLocked( intelContextPtr intel,
-                             GLuint cpp,
-                             GLshort dst_pitch,  /* in bytes */
-                             GLuint dst_offset,
-                             GLshort x, GLshort y, 
-                             GLshort w, GLshort h,
-                             GLuint color )
-{
-   GLuint BR13, CMD;
-   BATCH_LOCALS;
-
-   switch(cpp) {
-   case 1: 
-   case 2: 
-   case 3: 
-      BR13 = dst_pitch | (0xF0 << 16) | (1<<24);
-      CMD = XY_COLOR_BLT_CMD;
-      break;
-   case 4:
-      BR13 = dst_pitch | (0xF0 << 16) | (1<<24) | (1<<25);
-      CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
-            XY_COLOR_BLT_WRITE_RGB);
-      break;
-   default:
-      return;
-   }
-
-   BEGIN_BATCH( 6);
-   OUT_BATCH( CMD );
-   OUT_BATCH( BR13 );
-   OUT_BATCH( (y << 16) | x );
-   OUT_BATCH( ((y+h) << 16) | (x+w) );
-   OUT_BATCH( dst_offset );
-   OUT_BATCH( color );
-   ADVANCE_BATCH();
+   return ret;
 }
 
 
-/* Copy BitBlt
+/*  This is the only way buffers get added to the validate list.
  */
-void intelEmitCopyBlitLocked( intelContextPtr intel,
-                             GLuint cpp,
-                             GLshort src_pitch,
-                             GLuint  src_offset,
-                             GLshort dst_pitch,
-                             GLuint  dst_offset,
-                             GLshort src_x, GLshort src_y,
-                             GLshort dst_x, GLshort dst_y,
-                             GLshort w, GLshort h )
+bool
+intel_batchbuffer_emit_reloc(struct intel_context *intel,
+                             drm_intel_bo *buffer,
+                             uint32_t read_domains, uint32_t write_domain,
+                            uint32_t delta)
 {
-   GLuint CMD, BR13;
-   int dst_y2 = dst_y + h;
-   int dst_x2 = dst_x + w;
-   BATCH_LOCALS;
-
-   src_pitch *= cpp;
-   dst_pitch *= cpp;
-
-   switch(cpp) {
-   case 1: 
-   case 2: 
-   case 3: 
-      BR13 = dst_pitch | (0xCC << 16) | (1<<24);
-      CMD = XY_SRC_COPY_BLT_CMD;
-      break;
-   case 4:
-      BR13 = dst_pitch | (0xCC << 16) | (1<<24) | (1<<25);
-      CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-            XY_SRC_COPY_BLT_WRITE_RGB);
-      break;
-   default:
-      return;
-   }
-
-   if (dst_y2 < dst_y ||
-       dst_x2 < dst_x) {
-      return;
-   }
+   int ret;
+
+   ret = drm_intel_bo_emit_reloc(intel->batch.bo, 4*intel->batch.used,
+                                buffer, delta,
+                                read_domains, write_domain);
+   assert(ret == 0);
+   (void)ret;
+
+   /*
+    * Using the old buffer offset, write in what the right data would be, in case
+    * the buffer doesn't move and we can short-circuit the relocation processing
+    * in the kernel
+    */
+   intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
 
-   BEGIN_BATCH( 12);
-   OUT_BATCH( CMD );
-   OUT_BATCH( BR13 );
-   OUT_BATCH( (dst_y << 16) | dst_x );
-   OUT_BATCH( (dst_y2 << 16) | dst_x2 );
-   OUT_BATCH( dst_offset );    
-   OUT_BATCH( (src_y << 16) | src_x );
-   OUT_BATCH( src_pitch );
-   OUT_BATCH( src_offset ); 
-   ADVANCE_BATCH();
+   return true;
 }
 
-
-
-void intelClearWithBlit(GLcontext *ctx, GLbitfield flags, GLboolean all,
-                     GLint cx1, GLint cy1, GLint cw, GLint ch)
+bool
+intel_batchbuffer_emit_reloc_fenced(struct intel_context *intel,
+                                   drm_intel_bo *buffer,
+                                   uint32_t read_domains,
+                                   uint32_t write_domain,
+                                   uint32_t delta)
 {
-   intelContextPtr intel = INTEL_CONTEXT( ctx );
-   intelScreenPrivate *intelScreen = intel->intelScreen;
-   GLuint clear_depth, clear_color;
-   GLint cx, cy;
-   GLint pitch;
-   GLint cpp = intelScreen->cpp;
-   GLint i;
-   GLuint BR13, CMD, D_CMD;
-   BATCH_LOCALS;
-
-   intelFlush( &intel->ctx );
-   LOCK_HARDWARE( intel );
-
-   pitch = intelScreen->front.pitch;
-
-   clear_color = intel->ClearColor;
-   clear_depth = 0;
-
-   if (flags & BUFFER_BIT_DEPTH) {
-      clear_depth = (GLuint)(ctx->Depth.Clear * intel->ClearDepth);
-   }
-
-   if (flags & BUFFER_BIT_STENCIL) {
-      clear_depth |= (ctx->Stencil.Clear & 0xff) << 24;
-   }
-
-   switch(cpp) {
-   case 2: 
-      BR13 = (0xF0 << 16) | (pitch) | (1<<24);
-      D_CMD = CMD = XY_COLOR_BLT_CMD;
-      break;
-   case 4:
-      BR13 = (0xF0 << 16) | (pitch) | (1<<24) | (1<<25);
-      CMD = (XY_COLOR_BLT_CMD |
-            XY_COLOR_BLT_WRITE_ALPHA | 
-            XY_COLOR_BLT_WRITE_RGB);
-      D_CMD = XY_COLOR_BLT_CMD;
-      if (flags & BUFFER_BIT_DEPTH) D_CMD |= XY_COLOR_BLT_WRITE_RGB;
-      if (flags & BUFFER_BIT_STENCIL) D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
-      break;
-   default:
-      BR13 = (0xF0 << 16) | (pitch) | (1<<24);
-      D_CMD = CMD = XY_COLOR_BLT_CMD;
-      break;
-   }
-
-   {
-      /* flip top to bottom */
-      cy = intel->driDrawable->h-cy1-ch;
-      cx = cx1 + intel->drawX;
-      cy += intel->drawY;
-
-      /* adjust for page flipping */
-      if ( intel->sarea->pf_current_page == 1 ) {
-        GLuint tmp = flags;
-
-        flags &= ~(BUFFER_BIT_FRONT_LEFT | BUFFER_BIT_BACK_LEFT);
-        if ( tmp & BUFFER_BIT_FRONT_LEFT ) flags |= BUFFER_BIT_BACK_LEFT;
-        if ( tmp & BUFFER_BIT_BACK_LEFT )  flags |= BUFFER_BIT_FRONT_LEFT;
-      }
+   int ret;
+
+   ret = drm_intel_bo_emit_reloc_fence(intel->batch.bo, 4*intel->batch.used,
+                                      buffer, delta,
+                                      read_domains, write_domain);
+   assert(ret == 0);
+   (void)ret;
+
+   /*
+    * Using the old buffer offset, write in what the right data would
+    * be, in case the buffer doesn't move and we can short-circuit the
+    * relocation processing in the kernel
+    */
+   intel_batchbuffer_emit_dword(intel, buffer->offset + delta);
 
-      for (i = 0 ; i < intel->numClipRects ; i++) 
-      {         
-        drm_clip_rect_t *box = &intel->pClipRects[i];   
-        drm_clip_rect_t b;
-
-        if (!all) {
-           GLint x = box[i].x1;
-           GLint y = box[i].y1;
-           GLint w = box[i].x2 - x;
-           GLint h = box[i].y2 - y;
-
-           if (x < cx) w -= cx - x, x = cx; 
-           if (y < cy) h -= cy - y, y = cy;
-           if (x + w > cx + cw) w = cx + cw - x;
-           if (y + h > cy + ch) h = cy + ch - y;
-           if (w <= 0) continue;
-           if (h <= 0) continue;
-
-           b.x1 = x;
-           b.y1 = y;
-           b.x2 = x + w;
-           b.y2 = y + h;      
-        } else {
-           b = *box;
-        }
-
-
-        if (b.x1 > b.x2 ||
-            b.y1 > b.y2 ||
-            b.x2 > intelScreen->width ||
-            b.y2 > intelScreen->height)
-           continue;
-
-        if ( flags & BUFFER_BIT_FRONT_LEFT ) {     
-           BEGIN_BATCH( 6);        
-           OUT_BATCH( CMD );
-           OUT_BATCH( BR13 );
-           OUT_BATCH( (b.y1 << 16) | b.x1 );
-           OUT_BATCH( (b.y2 << 16) | b.x2 );
-           OUT_BATCH( intelScreen->front.offset );
-           OUT_BATCH( clear_color );
-           ADVANCE_BATCH();
-        }
-
-        if ( flags & BUFFER_BIT_BACK_LEFT ) {
-           BEGIN_BATCH( 6); 
-           OUT_BATCH( CMD );
-           OUT_BATCH( BR13 );
-           OUT_BATCH( (b.y1 << 16) | b.x1 );
-           OUT_BATCH( (b.y2 << 16) | b.x2 );
-           OUT_BATCH( intelScreen->back.offset );
-           OUT_BATCH( clear_color );
-           ADVANCE_BATCH();
-        }
-
-        if ( flags & (BUFFER_BIT_STENCIL | BUFFER_BIT_DEPTH) ) {
-           BEGIN_BATCH( 6);
-           OUT_BATCH( D_CMD );
-           OUT_BATCH( BR13 );
-           OUT_BATCH( (b.y1 << 16) | b.x1 );
-           OUT_BATCH( (b.y2 << 16) | b.x2 );
-           OUT_BATCH( intelScreen->depth.offset );
-           OUT_BATCH( clear_depth );
-           ADVANCE_BATCH();
-        }      
-      }
-   }
-   intelFlushBatchLocked( intel, GL_TRUE, GL_FALSE, GL_TRUE );
-   UNLOCK_HARDWARE( intel );
+   return true;
 }
 
-
-
-
-void intelDestroyBatchBuffer( GLcontext *ctx )
+void
+intel_batchbuffer_data(struct intel_context *intel,
+                       const void *data, GLuint bytes)
 {
-   intelContextPtr intel = INTEL_CONTEXT(ctx);
-
-   if (intel->alloc.offset) {
-      intelFreeAGP( intel, intel->alloc.ptr );
-      intel->alloc.ptr = NULL;
-      intel->alloc.offset = 0;
-   }
-   else if (intel->alloc.ptr) {
-      free(intel->alloc.ptr);
-      intel->alloc.ptr = NULL;
-   }
-
-   memset(&intel->batch, 0, sizeof(intel->batch));
+   assert((bytes & 3) == 0);
+   intel_batchbuffer_require_space(intel, bytes);
+   __memcpy(intel->batch.map + intel->batch.used, data, bytes);
+   intel->batch.used += bytes >> 2;
 }
 
-
-void intelInitBatchBuffer( GLcontext *ctx )
+/* Emit a pipelined flush to either flush render and texture cache for
+ * reading from a FBO-drawn texture, or flush so that frontbuffer
+ * render appears on the screen in DRI1.
+ *
+ * This is also used for the always_flush_cache driconf debug option.
+ */
+void
+intel_batchbuffer_emit_mi_flush(struct intel_context *intel)
 {
-   intelContextPtr intel = INTEL_CONTEXT(ctx);
-
-   /* This path isn't really safe with rotate:
-    */
-   if (getenv("INTEL_BATCH") && intel->intelScreen->allow_batchbuffer) {      
-      switch (intel->intelScreen->deviceID) {
-      case PCI_CHIP_I865_G:
-        /* HW bug?  Seems to crash if batchbuffer crosses 4k boundary.
-         */
-        intel->alloc.size = 8 * 1024; 
-        break;
-      default:
-        /* This is the smallest amount of memory the kernel deals with.
-         * We'd ideally like to make this smaller.
-         */
-        intel->alloc.size = 1 << intel->intelScreen->logTextureGranularity;
-        break;
-      }
-
-      /* KW: temporary - this make crashes & lockups more frequent, so
-       * leave in until they are solved.
-       */
-      intel->alloc.size = 8 * 1024; 
-
-      intel->alloc.ptr = intelAllocateAGP( intel, intel->alloc.size );
-      if (intel->alloc.ptr)
-        intel->alloc.offset = 
-           intelAgpOffsetFromVirtual( intel, intel->alloc.ptr );
-      else
-         intel->alloc.offset = 0; /* OK? */
-   }
-
-   /* The default is now to use a local buffer and pass that to the
-    * kernel.  This is also a fallback if allocation fails on the
-    * above path:
-    */
-   if (!intel->alloc.ptr) {
-      intel->alloc.size = 8 * 1024;
-      intel->alloc.ptr = malloc( intel->alloc.size );
-      intel->alloc.offset = 0;
-   }
-
-   assert(intel->alloc.ptr);
+   BEGIN_BATCH(1);
+   OUT_BATCH(MI_FLUSH);
+   ADVANCE_BATCH();
 }