[Intel-gfx] [PATCH] intel: Don't keep intel->pClipRects, and instead just calculate it when needed.

Eric Anholt eric at anholt.net
Mon Oct 20 05:09:37 CEST 2008


This avoids issues with dereferencing stale cliprects around intel_draw_buffer
time.  Additionally, take advantage of cliprects staying constant for FBOs and
DRI2, and emit cliprects in the batchbuffer instead of having to flush batch
each time they change.
---
 src/mesa/drivers/dri/i915/i830_context.h       |    8 +-
 src/mesa/drivers/dri/i915/i830_vtbl.c          |   36 +++++-
 src/mesa/drivers/dri/i915/i915_context.h       |    8 +-
 src/mesa/drivers/dri/i915/i915_vtbl.c          |   37 +++++-
 src/mesa/drivers/dri/i915/intel_tris.c         |    7 +-
 src/mesa/drivers/dri/i965/brw_draw.c           |   33 +++--
 src/mesa/drivers/dri/i965/brw_misc_state.c     |   27 ++++
 src/mesa/drivers/dri/i965/brw_state.h          |    1 +
 src/mesa/drivers/dri/i965/brw_state_upload.c   |    1 +
 src/mesa/drivers/dri/intel/intel_batchbuffer.c |   30 +++--
 src/mesa/drivers/dri/intel/intel_blit.c        |   16 ++-
 src/mesa/drivers/dri/intel/intel_buffers.c     |  173 ++++++------------------
 src/mesa/drivers/dri/intel/intel_buffers.h     |    7 +
 src/mesa/drivers/dri/intel/intel_context.c     |   35 -----
 src/mesa/drivers/dri/intel/intel_context.h     |   18 ++-
 src/mesa/drivers/dri/intel/intel_reg.h         |    5 +
 src/mesa/drivers/dri/intel/intel_span.c        |  141 ++++++++-----------
 17 files changed, 282 insertions(+), 301 deletions(-)

diff --git a/src/mesa/drivers/dri/i915/i830_context.h b/src/mesa/drivers/dri/i915/i830_context.h
index a298c14..1bdb320 100644
--- a/src/mesa/drivers/dri/i915/i830_context.h
+++ b/src/mesa/drivers/dri/i915/i830_context.h
@@ -57,7 +57,13 @@
 #define I830_DESTREG_SR0 7
 #define I830_DESTREG_SR1 8
 #define I830_DESTREG_SR2 9
-#define I830_DEST_SETUP_SIZE 10
+#define I830_DESTREG_DRAWRECT0 10
+#define I830_DESTREG_DRAWRECT1 11
+#define I830_DESTREG_DRAWRECT2 12
+#define I830_DESTREG_DRAWRECT3 13
+#define I830_DESTREG_DRAWRECT4 14
+#define I830_DESTREG_DRAWRECT5 15
+#define I830_DEST_SETUP_SIZE 16
 
 #define I830_CTXREG_STATE1		0
 #define I830_CTXREG_STATE2		1
diff --git a/src/mesa/drivers/dri/i915/i830_vtbl.c b/src/mesa/drivers/dri/i915/i830_vtbl.c
index 773a8b4..124fb82 100644
--- a/src/mesa/drivers/dri/i915/i830_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i830_vtbl.c
@@ -426,6 +426,7 @@ i830_emit_state(struct intel_context *intel)
    BATCH_LOCALS;
    dri_bo *aper_array[3 + I830_TEX_UNITS];
    int aper_count;
+   enum cliprect_mode clip_mode;
 
    /* We don't hold the lock at this point, so want to make sure that
     * there won't be a buffer wrap between the state emits and the primitive
@@ -435,12 +436,13 @@ i830_emit_state(struct intel_context *intel)
     * scheduling is allowed, rather than assume that it is whenever a
     * batchbuffer fills up.
     *
-    * Set the space as LOOP_CLIPRECTS now, since that's what our primitives
-    * will be emitted under.
+    * Set the space under {NO_,}LOOP_CLIPRECTS according to how the primitives
+    * will be emitted.
     */
+   clip_mode = intel->constant_cliprect ? NO_LOOP_CLIPRECTS: LOOP_CLIPRECTS;
    intel_batchbuffer_require_space(intel->batch,
 				   get_state_size(state) + INTEL_PRIM_EMIT_SIZE,
-				   LOOP_CLIPRECTS);
+				   clip_mode);
    count = 0;
  again:
    aper_count = 0;
@@ -512,6 +514,15 @@ i830_emit_state(struct intel_context *intel)
       OUT_BATCH(state->Buffer[I830_DESTREG_SR0]);
       OUT_BATCH(state->Buffer[I830_DESTREG_SR1]);
       OUT_BATCH(state->Buffer[I830_DESTREG_SR2]);
+
+      if (intel->constant_cliprect) {
+	 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT0]);
+	 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT1]);
+	 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT2]);
+	 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT3]);
+	 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT4]);
+	 OUT_BATCH(state->Buffer[I830_DESTREG_DRAWRECT5]);
+      }
       ADVANCE_BATCH();
    }
    
@@ -591,6 +602,7 @@ i830_state_draw_region(struct intel_context *intel,
 		       struct intel_region *depth_region)
 {
    struct i830_context *i830 = i830_context(&intel->ctx);
+   GLcontext *ctx = &intel->ctx;
    GLuint value;
 
    ASSERT(state == &i830->state || state == &i830->meta);
@@ -643,6 +655,24 @@ i830_state_draw_region(struct intel_context *intel,
    }
    state->Buffer[I830_DESTREG_DV1] = value;
 
+   if (intel->constant_cliprect) {
+      state->Buffer[I830_DESTREG_DRAWRECT0] = _3DSTATE_DRAWRECT_INFO;
+      state->Buffer[I830_DESTREG_DRAWRECT1] = 0;
+      state->Buffer[I830_DESTREG_DRAWRECT2] = 0; /* xmin, ymin */
+      state->Buffer[I830_DESTREG_DRAWRECT3] =
+	 (ctx->DrawBuffer->Width & 0xffff) |
+	 (ctx->DrawBuffer->Height << 16);
+      state->Buffer[I830_DESTREG_DRAWRECT4] = 0; /* xoff, yoff */
+      state->Buffer[I830_DESTREG_DRAWRECT5] = 0;
+   } else {
+      state->Buffer[I830_DESTREG_DRAWRECT0] = MI_NOOP;
+      state->Buffer[I830_DESTREG_DRAWRECT1] = MI_NOOP;
+      state->Buffer[I830_DESTREG_DRAWRECT2] = MI_NOOP;
+      state->Buffer[I830_DESTREG_DRAWRECT3] = MI_NOOP;
+      state->Buffer[I830_DESTREG_DRAWRECT4] = MI_NOOP;
+      state->Buffer[I830_DESTREG_DRAWRECT5] = MI_NOOP;
+   }
+
    I830_STATECHANGE(i830, I830_UPLOAD_BUFFERS);
 
 
diff --git a/src/mesa/drivers/dri/i915/i915_context.h b/src/mesa/drivers/dri/i915/i915_context.h
index a2376e5..87bbf5f 100644
--- a/src/mesa/drivers/dri/i915/i915_context.h
+++ b/src/mesa/drivers/dri/i915/i915_context.h
@@ -65,7 +65,13 @@
 #define I915_DESTREG_SR0 9
 #define I915_DESTREG_SR1 10
 #define I915_DESTREG_SR2 11
-#define I915_DEST_SETUP_SIZE 12
+#define I915_DESTREG_DRAWRECT0 12
+#define I915_DESTREG_DRAWRECT1 13
+#define I915_DESTREG_DRAWRECT2 14
+#define I915_DESTREG_DRAWRECT3 15
+#define I915_DESTREG_DRAWRECT4 16
+#define I915_DESTREG_DRAWRECT5 17
+#define I915_DEST_SETUP_SIZE 18
 
 #define I915_CTXREG_STATE4		0
 #define I915_CTXREG_LI	        	1
diff --git a/src/mesa/drivers/dri/i915/i915_vtbl.c b/src/mesa/drivers/dri/i915/i915_vtbl.c
index 7431a9c..87b80b5 100644
--- a/src/mesa/drivers/dri/i915/i915_vtbl.c
+++ b/src/mesa/drivers/dri/i915/i915_vtbl.c
@@ -302,6 +302,7 @@ i915_emit_state(struct intel_context *intel)
    dri_bo *aper_array[3 + I915_TEX_UNITS];
    GET_CURRENT_CONTEXT(ctx);
    BATCH_LOCALS;
+   enum cliprect_mode clip_mode;
 
    /* We don't hold the lock at this point, so want to make sure that
     * there won't be a buffer wrap between the state emits and the primitive
@@ -311,12 +312,13 @@ i915_emit_state(struct intel_context *intel)
     * scheduling is allowed, rather than assume that it is whenever a
     * batchbuffer fills up.
     *
-    * Set the space as LOOP_CLIPRECTS now, since that's what our primitives
-    * will be emitted under.
+    * Set the space under {NO_,}LOOP_CLIPRECTS according to how the primitives
+    * will be emitted.
     */
+   clip_mode = intel->constant_cliprect ? NO_LOOP_CLIPRECTS: LOOP_CLIPRECTS;
    intel_batchbuffer_require_space(intel->batch,
 				   get_state_size(state) + INTEL_PRIM_EMIT_SIZE,
-				   LOOP_CLIPRECTS);
+				   clip_mode);
    count = 0;
  again:
    aper_count = 0;
@@ -399,6 +401,16 @@ i915_emit_state(struct intel_context *intel)
       OUT_BATCH(state->Buffer[I915_DESTREG_SR0]);
       OUT_BATCH(state->Buffer[I915_DESTREG_SR1]);
       OUT_BATCH(state->Buffer[I915_DESTREG_SR2]);
+
+      if (intel->constant_cliprect) {
+	 OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT0]);
+	 OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT1]);
+	 OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT2]);
+	 OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT3]);
+	 OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT4]);
+	 OUT_BATCH(state->Buffer[I915_DESTREG_DRAWRECT5]);
+      }
+
       ADVANCE_BATCH();
    }
 
@@ -521,6 +533,7 @@ i915_state_draw_region(struct intel_context *intel,
                        struct intel_region *depth_region)
 {
    struct i915_context *i915 = i915_context(&intel->ctx);
+   GLcontext *ctx = &intel->ctx;
    GLuint value;
 
    ASSERT(state == &i915->state || state == &i915->meta);
@@ -573,6 +586,24 @@ i915_state_draw_region(struct intel_context *intel,
    }
    state->Buffer[I915_DESTREG_DV1] = value;
 
+   if (intel->constant_cliprect) {
+      state->Buffer[I915_DESTREG_DRAWRECT0] = _3DSTATE_DRAWRECT_INFO;
+      state->Buffer[I915_DESTREG_DRAWRECT1] = 0;
+      state->Buffer[I915_DESTREG_DRAWRECT2] = 0; /* xmin, ymin */
+      state->Buffer[I915_DESTREG_DRAWRECT3] =
+	 (ctx->DrawBuffer->Width & 0xffff) |
+	 (ctx->DrawBuffer->Height << 16);
+      state->Buffer[I915_DESTREG_DRAWRECT4] = 0; /* xoff, yoff */
+      state->Buffer[I915_DESTREG_DRAWRECT5] = 0;
+   } else {
+      state->Buffer[I915_DESTREG_DRAWRECT0] = MI_NOOP;
+      state->Buffer[I915_DESTREG_DRAWRECT1] = MI_NOOP;
+      state->Buffer[I915_DESTREG_DRAWRECT2] = MI_NOOP;
+      state->Buffer[I915_DESTREG_DRAWRECT3] = MI_NOOP;
+      state->Buffer[I915_DESTREG_DRAWRECT4] = MI_NOOP;
+      state->Buffer[I915_DESTREG_DRAWRECT5] = MI_NOOP;
+   }
+
    I915_STATECHANGE(i915, I915_UPLOAD_BUFFERS);
 }
 
diff --git a/src/mesa/drivers/dri/i915/intel_tris.c b/src/mesa/drivers/dri/i915/intel_tris.c
index 0621003..7b22ca2 100644
--- a/src/mesa/drivers/dri/i915/intel_tris.c
+++ b/src/mesa/drivers/dri/i915/intel_tris.c
@@ -110,6 +110,9 @@ void intel_flush_prim(struct intel_context *intel)
    dri_bo *aper_array[2];
    dri_bo *vb_bo;
    unsigned int offset, count;
+   enum cliprect_mode clip_mode;
+
+   clip_mode = intel->constant_cliprect ? NO_LOOP_CLIPRECTS : LOOP_CLIPRECTS;
 
    /* Must be called after an intel_start_prim. */
    assert(intel->prim.primitive != ~0);
@@ -160,7 +163,7 @@ void intel_flush_prim(struct intel_context *intel)
 #endif
 
    if (IS_9XX(intel->intelScreen->deviceID)) {
-      BEGIN_BATCH(5, LOOP_CLIPRECTS);
+      BEGIN_BATCH(5, clip_mode);
       OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
 		I1_LOAD_S(0) | I1_LOAD_S(1) | 1);
       assert((offset & !S0_VB_OFFSET_MASK) == 0);
@@ -178,7 +181,7 @@ void intel_flush_prim(struct intel_context *intel)
    } else {
       struct i830_context *i830 = i830_context(&intel->ctx);
 
-      BEGIN_BATCH(5, LOOP_CLIPRECTS);
+      BEGIN_BATCH(5, clip_mode);
       OUT_BATCH(_3DSTATE_LOAD_STATE_IMMEDIATE_1 |
 		I1_LOAD_S(0) | I1_LOAD_S(2) | 1);
       /* S0 */
diff --git a/src/mesa/drivers/dri/i965/brw_draw.c b/src/mesa/drivers/dri/i965/brw_draw.c
index 6c71b4a..7e868e3 100644
--- a/src/mesa/drivers/dri/i965/brw_draw.c
+++ b/src/mesa/drivers/dri/i965/brw_draw.c
@@ -126,6 +126,7 @@ static void brw_emit_prim( struct brw_context *brw,
 			   const struct _mesa_prim *prim )
 
 {
+   struct intel_context *intel = &brw->intel;
    struct brw_3d_primitive prim_packet;
 
    if (INTEL_DEBUG & DEBUG_PRIMS)
@@ -147,8 +148,11 @@ static void brw_emit_prim( struct brw_context *brw,
    /* Can't wrap here, since we rely on the validated state. */
    brw->no_batch_wrap = GL_TRUE;
    if (prim_packet.verts_per_instance) {
-      intel_batchbuffer_data( brw->intel.batch, &prim_packet,
-			      sizeof(prim_packet), LOOP_CLIPRECTS);
+      enum cliprect_mode clip_mode;
+
+      clip_mode = intel->constant_cliprect ? NO_LOOP_CLIPRECTS : LOOP_CLIPRECTS;
+      intel_batchbuffer_data(brw->intel.batch, &prim_packet,
+			     sizeof(prim_packet), clip_mode);
    }
    brw->no_batch_wrap = GL_FALSE;
 }
@@ -257,6 +261,7 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
    struct brw_context *brw = brw_context(ctx);
    GLboolean retval = GL_FALSE;
    GLuint i;
+   enum cliprect_mode clip_mode;
 
    if (ctx->NewState)
       _mesa_update_state( ctx );
@@ -282,24 +287,22 @@ static GLboolean brw_try_draw_prims( GLcontext *ctx,
 
    LOCK_HARDWARE(intel);
 
-   if (brw->intel.numClipRects == 0) {
+   if (!intel->constant_cliprect && intel->driDrawable->numClipRects == 0) {
       UNLOCK_HARDWARE(intel);
       return GL_TRUE;
    }
 
+   clip_mode = intel->constant_cliprect ? NO_LOOP_CLIPRECTS : LOOP_CLIPRECTS;
+   /* Flush the batch if it's approaching full, so that we don't wrap while
+    * we've got validated state that needs to be in the same batch as the
+    * primitives.  This fraction is just a guess (minimal full state plus
+    * a primitive is around 512 bytes), and would be better if we had
+    * an upper bound of how much we might emit in a single
+    * brw_try_draw_prims().
+    */
+   intel_batchbuffer_require_space(intel->batch, intel->batch->size / 4,
+				   clip_mode);
    {
-      /* Flush the batch if it's approaching full, so that we don't wrap while
-       * we've got validated state that needs to be in the same batch as the
-       * primitives.  This fraction is just a guess (minimal full state plus
-       * a primitive is around 512 bytes), and would be better if we had
-       * an upper bound of how much we might emit in a single
-       * brw_try_draw_prims().
-       */
-      if (intel->batch->ptr - intel->batch->map > intel->batch->size * 3 / 4
-	/* brw_emit_prim may change the cliprect_mode to LOOP_CLIPRECTS */
-	  || intel->batch->cliprect_mode != LOOP_CLIPRECTS)
-	      intel_batchbuffer_flush(intel->batch);
-
       /* Set the first primitive early, ahead of validate_state:
        */
       brw_set_prim(brw, prim[0].mode);
diff --git a/src/mesa/drivers/dri/i965/brw_misc_state.c b/src/mesa/drivers/dri/i965/brw_misc_state.c
index 487c638..4fce79a 100644
--- a/src/mesa/drivers/dri/i965/brw_misc_state.c
+++ b/src/mesa/drivers/dri/i965/brw_misc_state.c
@@ -71,6 +71,33 @@ const struct brw_tracked_state brw_blend_constant_color = {
    .emit = upload_blend_constant_color
 };
 
+/* Constant single cliprect for framebuffer object or DRI2 drawing */
+static void upload_drawing_rect(struct brw_context *brw)
+{
+   struct intel_context *intel = &brw->intel;
+   GLcontext *ctx = &intel->ctx;
+
+   if (!intel->constant_cliprect)
+      return;
+
+   BEGIN_BATCH(4, NO_LOOP_CLIPRECTS);
+   OUT_BATCH(_3DSTATE_DRAWRECT_INFO_I965);
+   OUT_BATCH(0); /* xmin, ymin */
+   OUT_BATCH(((ctx->DrawBuffer->Width - 1) & 0xffff) |
+	    ((ctx->DrawBuffer->Height - 1) << 16));
+   OUT_BATCH(0);
+   ADVANCE_BATCH();
+}
+
+const struct brw_tracked_state brw_drawing_rect = {
+   .dirty = {
+      .mesa = _NEW_BUFFERS,
+      .brw = 0,
+      .cache = 0
+   },
+   .emit = upload_drawing_rect
+};
+
 /**
  * Upload the binding table pointers, which point each stage's array of surface
  * state pointers.
diff --git a/src/mesa/drivers/dri/i965/brw_state.h b/src/mesa/drivers/dri/i965/brw_state.h
index 4c04036..a27ef1f 100644
--- a/src/mesa/drivers/dri/i965/brw_state.h
+++ b/src/mesa/drivers/dri/i965/brw_state.h
@@ -79,6 +79,7 @@ const struct brw_tracked_state brw_pipe_control;
 const struct brw_tracked_state brw_clear_surface_cache;
 const struct brw_tracked_state brw_clear_batch_cache;
 
+const struct brw_tracked_state brw_drawing_rect;
 const struct brw_tracked_state brw_indices;
 const struct brw_tracked_state brw_vertices;
 
diff --git a/src/mesa/drivers/dri/i965/brw_state_upload.c b/src/mesa/drivers/dri/i965/brw_state_upload.c
index b6a5284..db0b896 100644
--- a/src/mesa/drivers/dri/i965/brw_state_upload.c
+++ b/src/mesa/drivers/dri/i965/brw_state_upload.c
@@ -99,6 +99,7 @@ const struct brw_tracked_state *atoms[] =
    &brw_psp_urb_cbs,
 #endif
 
+   &brw_drawing_rect,
    &brw_indices,
    &brw_vertices,
 
diff --git a/src/mesa/drivers/dri/intel/intel_batchbuffer.c b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
index 7dbc646..c9b88b0 100644
--- a/src/mesa/drivers/dri/intel/intel_batchbuffer.c
+++ b/src/mesa/drivers/dri/intel/intel_batchbuffer.c
@@ -30,6 +30,7 @@
 #include "intel_decode.h"
 #include "intel_reg.h"
 #include "intel_bufmgr.h"
+#include "intel_buffers.h"
 
 /* Relocations in kernel space:
  *    - pass dma buffer seperately
@@ -133,6 +134,9 @@ do_flush_locked(struct intel_batchbuffer *batch,
 {
    struct intel_context *intel = batch->intel;
    int ret = 0;
+   unsigned int num_cliprects = 0;
+   struct drm_clip_rect *cliprects = NULL;
+   int x_off = 0, y_off = 0;
 
    if (batch->buffer)
       dri_bo_subdata (batch->buf, 0, used, batch->buffer);
@@ -142,23 +146,21 @@ do_flush_locked(struct intel_batchbuffer *batch,
    batch->map = NULL;
    batch->ptr = NULL;
 
-   /* Throw away non-effective packets.  Won't work once we have
-    * hardware contexts which would preserve statechanges beyond a
-    * single buffer.
-    */
 
-   if (!(intel->numClipRects == 0 &&
-	 batch->cliprect_mode == LOOP_CLIPRECTS) || intel->no_hw) {
-      dri_bo_exec(batch->buf, used,
-		  intel->pClipRects,
-		  batch->cliprect_mode != LOOP_CLIPRECTS ?
-		  0 : intel->numClipRects,
-		  (((GLuint) intel->drawX) & 0xffff) |
-		  (((GLuint) intel->drawY) << 16));
+   if (batch->cliprect_mode == LOOP_CLIPRECTS) {
+      intel_get_cliprects(intel, &cliprects, &num_cliprects, &x_off, &y_off);
+   }
+   /* Dispatch the batchbuffer, if it has some effect (nonzero cliprects).
+    * Can't short-circuit like this once we have hardware contexts, but we
+    * should always be in DRI2 mode by then anyway.
+    */
+   if ((batch->cliprect_mode != LOOP_CLIPRECTS ||
+	num_cliprects != 0) && !intel->no_hw) {
+      dri_bo_exec(batch->buf, used, cliprects, num_cliprects,
+		  (x_off & 0xffff) | (y_off << 16));
    }
 
-   if (intel->numClipRects == 0 &&
-       batch->cliprect_mode == LOOP_CLIPRECTS) {
+   if (batch->cliprect_mode == LOOP_CLIPRECTS && num_cliprects == 0) {
       if (allow_unlock) {
 	 /* If we are not doing any actual user-visible rendering,
 	  * do a sched_yield to keep the app from pegging the cpu while
diff --git a/src/mesa/drivers/dri/intel/intel_blit.c b/src/mesa/drivers/dri/intel/intel_blit.c
index 2917401..0430f93 100644
--- a/src/mesa/drivers/dri/intel/intel_blit.c
+++ b/src/mesa/drivers/dri/intel/intel_blit.c
@@ -393,6 +393,9 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
    struct gl_framebuffer *fb = ctx->DrawBuffer;
    GLuint clear_depth;
    GLbitfield skipBuffers = 0;
+   unsigned int num_cliprects;
+   struct drm_clip_rect *cliprects;
+   int x_off, y_off;
    BATCH_LOCALS;
 
    /*
@@ -417,7 +420,8 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
    intelFlush(&intel->ctx);
    LOCK_HARDWARE(intel);
 
-   if (intel->numClipRects) {
+   intel_get_cliprects(intel, &cliprects, &num_cliprects, &x_off, &y_off);
+   if (num_cliprects) {
       GLint cx, cy, cw, ch;
       drm_clip_rect_t clear;
       int i;
@@ -432,15 +436,15 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
          /* clearing a window */
 
          /* flip top to bottom */
-         clear.x1 = cx + intel->drawX;
+         clear.x1 = cx + x_off;
          clear.y1 = intel->driDrawable->y + intel->driDrawable->h - cy - ch;
          clear.x2 = clear.x1 + cw;
          clear.y2 = clear.y1 + ch;
       }
       else {
          /* clearing FBO */
-         assert(intel->numClipRects == 1);
-         assert(intel->pClipRects == &intel->fboRect);
+         assert(num_cliprects == 1);
+         assert(cliprects == &intel->fboRect);
          clear.x1 = cx;
          clear.y1 = cy;
          clear.x2 = clear.x1 + cw;
@@ -448,8 +452,8 @@ intelClearWithBlit(GLcontext *ctx, GLbitfield mask)
          /* no change to mask */
       }
 
-      for (i = 0; i < intel->numClipRects; i++) {
-         const drm_clip_rect_t *box = &intel->pClipRects[i];
+      for (i = 0; i < num_cliprects; i++) {
+         const drm_clip_rect_t *box = &cliprects[i];
          drm_clip_rect_t b;
          GLuint buf;
          GLuint clearMask = mask;      /* use copy, since we modify it below */
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.c b/src/mesa/drivers/dri/intel/intel_buffers.c
index f5eaf76..f8f009c 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.c
+++ b/src/mesa/drivers/dri/intel/intel_buffers.c
@@ -123,99 +123,40 @@ intel_readbuf_region(struct intel_context *intel)
       return NULL;
 }
 
-
-
-/**
- * Update the following fields for rendering to a user-created FBO:
- *   intel->numClipRects
- *   intel->pClipRects
- *   intel->drawX
- *   intel->drawY
- */
-static void
-intelSetRenderbufferClipRects(struct intel_context *intel)
-{
-   /* If the batch contents require looping over cliprects, flush them before
-    * we go changing which cliprects get referenced when that happens.
-    */
-   if (intel->batch->cliprect_mode == LOOP_CLIPRECTS &&
-       (intel->fboRect.x2 != intel->ctx.DrawBuffer->Width ||
-	intel->fboRect.x2 != intel->ctx.DrawBuffer->Height))
-      intel_batchbuffer_flush(intel->batch);
-
-   assert(intel->ctx.DrawBuffer->Width > 0);
-   assert(intel->ctx.DrawBuffer->Height > 0);
-   intel->fboRect.x1 = 0;
-   intel->fboRect.y1 = 0;
-   intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
-   intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
-   intel->numClipRects = 1;
-   intel->pClipRects = &intel->fboRect;
-   intel->drawX = 0;
-   intel->drawY = 0;
-}
-
-
-/**
- * As above, but for rendering to front buffer of a window.
- * \sa intelSetRenderbufferClipRects
- */
-static void
-intelSetFrontClipRects(struct intel_context *intel)
-{
-   __DRIdrawablePrivate *dPriv = intel->driDrawable;
-
-   if (!dPriv)
-      return;
-
-   /* If the batch contents require looping over cliprects, flush them before
-    * we go changing which cliprects get referenced when that happens.
-    */
-   if (intel->batch->cliprect_mode == LOOP_CLIPRECTS &&
-       intel->pClipRects != dPriv->pClipRects)
-      intel_batchbuffer_flush(intel->batch);
-   intel->numClipRects = dPriv->numClipRects;
-   intel->pClipRects = dPriv->pClipRects;
-   intel->drawX = dPriv->x;
-   intel->drawY = dPriv->y;
-}
-
-
-/**
- * As above, but for rendering to back buffer of a window.
- */
-static void
-intelSetBackClipRects(struct intel_context *intel)
+void
+intel_get_cliprects(struct intel_context *intel,
+		    struct drm_clip_rect **cliprects,
+		    unsigned int *num_cliprects,
+		    int *x_off, int *y_off)
 {
    __DRIdrawablePrivate *dPriv = intel->driDrawable;
-   struct intel_framebuffer *intel_fb;
-
-   if (!dPriv)
-      return;
-
-   intel_fb = dPriv->driverPrivate;
+   struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
 
-   if (intel_fb->pf_active || dPriv->numBackClipRects == 0) {
+   if (intel->constant_cliprect) {
+      /* FBO or DRI2 rendering, which can just use the fb's size. */
+      intel->fboRect.x1 = 0;
+      intel->fboRect.y1 = 0;
+      intel->fboRect.x2 = intel->ctx.DrawBuffer->Width;
+      intel->fboRect.y2 = intel->ctx.DrawBuffer->Height;
+
+      *cliprects = &intel->fboRect;
+      *num_cliprects = 1;
+      *x_off = 0;
+      *y_off = 0;
+   } else if (intel->front_cliprects ||
+       intel_fb->pf_active || dPriv->numBackClipRects == 0) {
       /* use the front clip rects */
-      if (intel->batch->cliprect_mode == LOOP_CLIPRECTS &&
-	  intel->pClipRects != dPriv->pClipRects)
-	 intel_batchbuffer_flush(intel->batch);
-
-      intel->numClipRects = dPriv->numClipRects;
-      intel->pClipRects = dPriv->pClipRects;
-      intel->drawX = dPriv->x;
-      intel->drawY = dPriv->y;
+      *cliprects = dPriv->pClipRects;
+      *num_cliprects = dPriv->numClipRects;
+      *x_off = dPriv->x;
+      *y_off = dPriv->y;
    }
    else {
       /* use the back clip rects */
-      if (intel->batch->cliprect_mode == LOOP_CLIPRECTS &&
-	  intel->pClipRects != dPriv->pBackClipRects)
-	 intel_batchbuffer_flush(intel->batch);
-
-      intel->numClipRects = dPriv->numBackClipRects;
-      intel->pClipRects = dPriv->pBackClipRects;
-      intel->drawX = dPriv->backX;
-      intel->drawY = dPriv->backY;
+      *num_cliprects = dPriv->numBackClipRects;
+      *cliprects = dPriv->pBackClipRects;
+      *x_off = dPriv->backX;
+      *y_off = dPriv->backY;
    }
 }
 
@@ -300,29 +241,6 @@ intelWindowMoved(struct intel_context *intel)
    __DRIdrawablePrivate *dPriv = intel->driDrawable;
    struct intel_framebuffer *intel_fb = dPriv->driverPrivate;
 
-   if (!intel->ctx.DrawBuffer) {
-      /* when would this happen? -BP */
-      intelSetFrontClipRects(intel);
-   }
-   else if (intel->ctx.DrawBuffer->Name != 0) {
-      /* drawing to user-created FBO - do nothing */
-      /* Cliprects would be set from intelDrawBuffer() */
-   }
-   else {
-      /* drawing to a window */
-      switch (intel_fb->Base._ColorDrawBufferIndexes[0]) {
-      case BUFFER_FRONT_LEFT:
-         intelSetFrontClipRects(intel);
-         break;
-      case BUFFER_BACK_LEFT:
-         intelSetBackClipRects(intel);
-         break;
-      default:
-         intelSetFrontClipRects(intel);
-      }
-	
-   }
-
    if (!intel->intelScreen->driScrnPriv->dri2.enabled &&
        intel->intelScreen->driScrnPriv->ddx_version.minor >= 7) {
       volatile struct drm_i915_sarea *sarea = intel->sarea;
@@ -894,7 +812,6 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
    struct intel_context *intel = intel_context(ctx);
    struct intel_region *colorRegions[MAX_DRAW_BUFFERS], *depthRegion = NULL;
    struct intel_renderbuffer *irbDepth = NULL, *irbStencil = NULL;
-   int front = 0;               /* drawing to front color buffer? */
 
    if (!fb) {
       /* this can happen during the initial context initialization */
@@ -927,52 +844,44 @@ intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb)
     */
    if (fb->_NumColorDrawBuffers == 0) {
       /* writing to 0  */
-      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_TRUE);
       colorRegions[0] = NULL;
-
-      if (fb->Name != 0)
-	 intelSetRenderbufferClipRects(intel);
+      intel->constant_cliprect = GL_TRUE;
    } else if (fb->_NumColorDrawBuffers > 1) {
        int i;
        struct intel_renderbuffer *irb;
-       FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
 
-       if (fb->Name != 0)
-           intelSetRenderbufferClipRects(intel);
        for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
            irb = intel_renderbuffer(fb->_ColorDrawBuffers[i]);
-           colorRegions[i] = (irb && irb->region) ? irb->region : NULL;
+           colorRegions[i] = irb ? irb->region : NULL;
        }
+       intel->constant_cliprect = GL_TRUE;
    }
    else {
-      /* draw to exactly one color buffer */
-      /*_mesa_debug(ctx, "Hardware rendering\n");*/
-      FALLBACK(intel, INTEL_FALLBACK_DRAW_BUFFER, GL_FALSE);
-      if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
-         front = 1;
-      }
-
-      /*
-       * Get the intel_renderbuffer for the colorbuffer we're drawing into.
-       * And set up cliprects.
+      /* Get the intel_renderbuffer for the single colorbuffer we're drawing
+       * into, and set up cliprects if it's .
        */
       if (fb->Name == 0) {
+	 intel->constant_cliprect = intel->driScreen->dri2.enabled;
 	 /* drawing to window system buffer */
-	 if (front) {
-	    intelSetFrontClipRects(intel);
+	 if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
+	    if (!intel->constant_cliprect && !intel->front_cliprects)
+	       intel_batchbuffer_flush(intel->batch);
+	    intel->front_cliprects = GL_TRUE;
 	    colorRegions[0] = intel_get_rb_region(fb, BUFFER_FRONT_LEFT);
 	 }
 	 else {
-	    intelSetBackClipRects(intel);
+	    if (!intel->constant_cliprect && intel->front_cliprects)
+	       intel_batchbuffer_flush(intel->batch);
+	    intel->front_cliprects = GL_FALSE;
 	    colorRegions[0]= intel_get_rb_region(fb, BUFFER_BACK_LEFT);
 	 }
       }
       else {
 	 /* drawing to user-created FBO */
 	 struct intel_renderbuffer *irb;
-	 intelSetRenderbufferClipRects(intel);
 	 irb = intel_renderbuffer(fb->_ColorDrawBuffers[0]);
 	 colorRegions[0] = (irb && irb->region) ? irb->region : NULL;
+	 intel->constant_cliprect = GL_TRUE;
       }
    }
 
diff --git a/src/mesa/drivers/dri/intel/intel_buffers.h b/src/mesa/drivers/dri/intel/intel_buffers.h
index a669a85..e5afb37 100644
--- a/src/mesa/drivers/dri/intel/intel_buffers.h
+++ b/src/mesa/drivers/dri/intel/intel_buffers.h
@@ -29,6 +29,8 @@
 #ifndef INTEL_BUFFERS_H
 #define INTEL_BUFFERS_H
 
+#include "dri_util.h"
+#include "drm.h"
 
 struct intel_context;
 struct intel_framebuffer;
@@ -53,4 +55,9 @@ extern void intel_draw_buffer(GLcontext * ctx, struct gl_framebuffer *fb);
 
 extern void intelInitBufferFuncs(struct dd_function_table *functions);
 
+void intel_get_cliprects(struct intel_context *intel,
+			 struct drm_clip_rect **cliprects,
+			 unsigned int *num_cliprects,
+			 int *x_off, int *y_off);
+
 #endif /* INTEL_BUFFERS_H */
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 2b3a9b9..9ac18e6 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -588,9 +588,6 @@ intelInitContext(struct intel_context *intel,
    intel->driFd = sPriv->fd;
    intel->driHwLock = sPriv->lock;
 
-   intel->width = intelScreen->width;
-   intel->height = intelScreen->height;
-
    driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
                        intel->driScreen->myNum,
 		       IS_965(intelScreen->deviceID) ? "i965" : "i915");
@@ -932,38 +929,6 @@ intelContendedLock(struct intel_context *intel, GLuint flags)
 		 sarea->ctxOwner, intel->hHWContext);
    }
 
-   if (sarea->width != intel->width || sarea->height != intel->height) {
-       int numClipRects = intel->numClipRects;
-
-       /*
-	* FIXME: Really only need to do this when drawing to a
-	* common back- or front buffer.
-	*/
-
-       /*
-	* This will essentially drop the outstanding batchbuffer on
-	* the floor.
-	*/
-       intel->numClipRects = 0;
-
-       if (intel->Fallback)
-	   _swrast_flush(&intel->ctx);
-
-       if (!IS_965(intel->intelScreen->deviceID))
-	   INTEL_FIREVERTICES(intel);
-
-       if (intel->batch->map != intel->batch->ptr)
-	   intel_batchbuffer_flush(intel->batch);
-
-       intel->numClipRects = numClipRects;
-
-       /* force window update */
-       intel->lastStamp = 0;
-
-       intel->width = sarea->width;
-       intel->height = sarea->height;
-   }
-
    /* Drawable changed?
     */
    if (dPriv && intel->lastStamp != dPriv->lastStamp) {
diff --git a/src/mesa/drivers/dri/intel/intel_context.h b/src/mesa/drivers/dri/intel/intel_context.h
index 554159a..3938af4 100644
--- a/src/mesa/drivers/dri/intel/intel_context.h
+++ b/src/mesa/drivers/dri/intel/intel_context.h
@@ -235,10 +235,18 @@ struct intel_context
 
    /* These refer to the current drawing buffer:
     */
-   int drawX, drawY;            /**< origin of drawing area within region */
-   GLuint numClipRects;         /**< cliprects for drawing */
-   drm_clip_rect_t *pClipRects;
    struct gl_texture_object *frame_buffer_texobj;
+   /**
+    * Set to true if a single constant cliprect should be used in the
+    * batchbuffer.  Otherwise, cliprects must be calculated at batchbuffer
+    * flush time while the lock is held.
+    */
+   GLboolean constant_cliprect;
+   /**
+    * In !constant_cliprect mode, set to true if the front cliprects should be
+    * used instead of back.
+    */
+   GLboolean front_cliprects;
    drm_clip_rect_t fboRect;     /**< cliprect for FBO rendering */
 
    int perf_boxes;
@@ -271,10 +279,6 @@ struct intel_context
     */
    driOptionCache optionCache;
 
-   /* Last seen width/height of the screen */
-   int width;
-   int height;
-
    int64_t swap_ust;
    int64_t swap_missed_ust;
 
diff --git a/src/mesa/drivers/dri/intel/intel_reg.h b/src/mesa/drivers/dri/intel/intel_reg.h
index c21f408..81a7386 100644
--- a/src/mesa/drivers/dri/intel/intel_reg.h
+++ b/src/mesa/drivers/dri/intel/intel_reg.h
@@ -29,6 +29,8 @@
 #define CMD_2D				(0x2 << 29)
 #define CMD_3D				(0x3 << 29)
 
+#define MI_NOOP				(CMD_MI | 0)
+
 #define MI_BATCH_BUFFER_END		(CMD_MI | 0xA << 23)
 
 #define MI_FLUSH			(CMD_MI | (4 << 23))
@@ -44,6 +46,9 @@
 #define _3DSTATE_LOAD_STATE_IMMEDIATE_1   (CMD_3D | (0x1d<<24) | (0x04<<16))
 #define I1_LOAD_S(n)                      (1<<(4+n))
 
+#define _3DSTATE_DRAWRECT_INFO		(CMD_3D | (0x1d<<24) | (0x80<<16) | 0x3)
+#define _3DSTATE_DRAWRECT_INFO_I965	(CMD_3D | (3 << 27) | (1 << 24) | 0x2)
+
 /** @{
  *
  * PIPE_CONTROL operation, a combination MI_FLUSH and register write with
diff --git a/src/mesa/drivers/dri/intel/intel_span.c b/src/mesa/drivers/dri/intel/intel_span.c
index 8e2b445..8f4e681 100644
--- a/src/mesa/drivers/dri/intel/intel_span.c
+++ b/src/mesa/drivers/dri/intel/intel_span.c
@@ -30,6 +30,7 @@
 #include "main/mtypes.h"
 #include "main/colormac.h"
 
+#include "intel_buffers.h"
 #include "intel_fbo.h"
 #include "intel_screen.h"
 #include "intel_span.h"
@@ -131,12 +132,8 @@ pwrite_8(struct intel_renderbuffer *irb, uint32_t offset, uint8_t val)
 }
 
 static uint32_t no_tile_swizzle(struct intel_renderbuffer *irb,
-				struct intel_context *intel,
 				int x, int y)
 {
-	x += intel->drawX;
-	y += intel->drawY;
-
 	return (y * irb->region->pitch + x) * irb->region->cpp;
 }
 
@@ -145,7 +142,6 @@ static uint32_t no_tile_swizzle(struct intel_renderbuffer *irb,
  */
 
 static uint32_t x_tile_swizzle(struct intel_renderbuffer *irb,
-			       struct intel_context *intel,
 			       int x, int y)
 {
 	int	tile_stride;
@@ -155,9 +151,6 @@ static uint32_t x_tile_swizzle(struct intel_renderbuffer *irb,
 	int	tile_off, tile_base;
 	
 	tile_stride = (irb->pfPitch * irb->region->cpp) << 3;
-	
-	x += intel->drawX;
-	y += intel->drawY;
 
 	xbyte = x * irb->region->cpp;
 
@@ -204,7 +197,6 @@ static uint32_t x_tile_swizzle(struct intel_renderbuffer *irb,
 }
 
 static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
-			       struct intel_context *intel,
 			       int x, int y)
 {
 	int	tile_stride;
@@ -214,9 +206,6 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 	int	tile_off, tile_base;
 	
 	tile_stride = (irb->pfPitch * irb->region->cpp) << 5;
-	
-	x += intel->drawX;
-	y += intel->drawY;
 
 	xbyte = x * irb->region->cpp;
 
@@ -268,8 +257,12 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);		\
    const GLint yScale = irb->RenderToTexture ? 1 : -1;			\
    const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;	\
+   unsigned int num_cliprects;						\
+   struct drm_clip_rect *cliprects;					\
+   int x_off, y_off;							\
    GLuint p;								\
-   (void) p;
+   (void) p;								\
+   intel_get_cliprects(intel, &cliprects, &num_cliprects, &x_off, &y_off);
 
 /* XXX FBO: this is identical to the macro in spantmp2.h except we get
  * the cliprect info from the context, not the driDrawable.
@@ -277,12 +270,12 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
  */
 #define HW_CLIPLOOP()							\
    do {									\
-      int _nc = intel->numClipRects;					\
+      int _nc = num_cliprects;						\
       while ( _nc-- ) {							\
-	 int minx = intel->pClipRects[_nc].x1 - intel->drawX;		\
-	 int miny = intel->pClipRects[_nc].y1 - intel->drawY;		\
-	 int maxx = intel->pClipRects[_nc].x2 - intel->drawX;		\
-	 int maxy = intel->pClipRects[_nc].y2 - intel->drawY;
+	 int minx = cliprects[_nc].x1 - x_off;				\
+	 int miny = cliprects[_nc].y1 - y_off;				\
+	 int maxx = cliprects[_nc].x2 - x_off;				\
+	 int maxy = cliprects[_nc].y2 - y_off;
 	
 #if 0
       }}
@@ -295,6 +288,11 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define HW_UNLOCK()
 
+/* Convenience macros to avoid typing the swizzle argument over and over */
+#define NO_TILE(_X, _Y) no_tile_swizzle(irb, (_X) + x_off, (_Y) + y_off)
+#define X_TILE(_X, _Y) x_tile_swizzle(irb, (_X) + x_off, (_Y) + y_off)
+#define Y_TILE(_X, _Y) y_tile_swizzle(irb, (_X) + x_off, (_Y) + y_off)
+
 /* 16 bit, RGB565 color spanline and pixel functions
  */
 #define SPANTMP_PIXEL_FMT GL_RGB
@@ -302,8 +300,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel##x##_RGB565
 #define TAG2(x,y) intel##x##_RGB565##y
-#define GET_VALUE(X, Y) pread_16(irb, no_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_16(irb, no_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_16(irb, NO_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_16(irb, NO_TILE(X, Y), V)
 #include "spantmp2.h"
 
 /* 32 bit, ARGB8888 color spanline and pixel functions
@@ -313,8 +311,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel##x##_ARGB8888
 #define TAG2(x,y) intel##x##_ARGB8888##y
-#define GET_VALUE(X, Y) pread_32(irb, no_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_32(irb, no_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_32(irb, NO_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_32(irb, NO_TILE(X, Y), V)
 #include "spantmp2.h"
 
 /* 32 bit, xRGB8888 color spanline and pixel functions
@@ -324,8 +322,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel##x##_xRGB8888
 #define TAG2(x,y) intel##x##_xRGB8888##y
-#define GET_VALUE(X, Y) pread_xrgb8888(irb, no_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, no_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_xrgb8888(irb, NO_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, NO_TILE(X, Y), V)
 #include "spantmp2.h"
 
 /* 16 bit RGB565 color tile spanline and pixel functions
@@ -336,8 +334,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel_XTile_##x##_RGB565
 #define TAG2(x,y) intel_XTile_##x##_RGB565##y
-#define GET_VALUE(X, Y) pread_16(irb, x_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_16(irb, x_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_16(irb, X_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_16(irb, X_TILE(X, Y), V)
 #include "spantmp2.h"
 
 #define SPANTMP_PIXEL_FMT GL_RGB
@@ -345,8 +343,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel_YTile_##x##_RGB565
 #define TAG2(x,y) intel_YTile_##x##_RGB565##y
-#define GET_VALUE(X, Y) pread_16(irb, y_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_16(irb, y_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_16(irb, Y_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_16(irb, Y_TILE(X, Y), V)
 #include "spantmp2.h"
 
 /* 32 bit ARGB888 color tile spanline and pixel functions
@@ -357,8 +355,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel_XTile_##x##_ARGB8888
 #define TAG2(x,y) intel_XTile_##x##_ARGB8888##y
-#define GET_VALUE(X, Y) pread_32(irb, x_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_32(irb, x_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_32(irb, X_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_32(irb, X_TILE(X, Y), V)
 #include "spantmp2.h"
 
 #define SPANTMP_PIXEL_FMT GL_BGRA
@@ -366,8 +364,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel_YTile_##x##_ARGB8888
 #define TAG2(x,y) intel_YTile_##x##_ARGB8888##y
-#define GET_VALUE(X, Y) pread_32(irb, y_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_32(irb, y_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_32(irb, Y_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_32(irb, Y_TILE(X, Y), V)
 #include "spantmp2.h"
 
 /* 32 bit xRGB888 color tile spanline and pixel functions
@@ -378,8 +376,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel_XTile_##x##_xRGB8888
 #define TAG2(x,y) intel_XTile_##x##_xRGB8888##y
-#define GET_VALUE(X, Y) pread_xrgb8888(irb, x_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, x_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_xrgb8888(irb, X_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, X_TILE(X, Y), V)
 #include "spantmp2.h"
 
 #define SPANTMP_PIXEL_FMT GL_BGRA
@@ -387,15 +385,19 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 #define TAG(x)    intel_YTile_##x##_xRGB8888
 #define TAG2(x,y) intel_YTile_##x##_xRGB8888##y
-#define GET_VALUE(X, Y) pread_xrgb8888(irb, y_tile_swizzle(irb, intel, X, Y))
-#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, y_tile_swizzle(irb, intel, X, Y), V)
+#define GET_VALUE(X, Y) pread_xrgb8888(irb, Y_TILE(X, Y))
+#define PUT_VALUE(X, Y, V) pwrite_xrgb8888(irb, Y_TILE(X, Y), V)
 #include "spantmp2.h"
 
 #define LOCAL_DEPTH_VARS						\
    struct intel_context *intel = intel_context(ctx);			\
    struct intel_renderbuffer *irb = intel_renderbuffer(rb);		\
    const GLint yScale = irb->RenderToTexture ? 1 : -1;			\
-   const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1;
+   const GLint yBias = irb->RenderToTexture ? 0 : irb->Base.Height - 1; \
+   unsigned int num_cliprects;						\
+   struct drm_clip_rect *cliprects;					\
+   int x_off, y_off;							\
+   intel_get_cliprects(intel, &cliprects, &num_cliprects, &x_off, &y_off);
 
 
 #define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
@@ -404,10 +406,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
  ** 16-bit depthbuffer functions.
  **/
 #define VALUE_TYPE GLushort
-#define WRITE_DEPTH(_x, _y, d) \
-   pwrite_16(irb, no_tile_swizzle(irb, intel, _x, _y), d)
-#define READ_DEPTH(d, _x, _y) \
-   d = pread_16(irb, no_tile_swizzle(irb, intel, _x, _y))
+#define WRITE_DEPTH(_x, _y, d) pwrite_16(irb, NO_TILE(_x, _y), d)
+#define READ_DEPTH(d, _x, _y) d = pread_16(irb, NO_TILE(_x, _y))
 #define TAG(x) intel##x##_z16
 #include "depthtmp.h"
 
@@ -416,10 +416,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
  ** 16-bit x tile depthbuffer functions.
  **/
 #define VALUE_TYPE GLushort
-#define WRITE_DEPTH(_x, _y, d) \
-   pwrite_16(irb, x_tile_swizzle(irb, intel, _x, _y), d)
-#define READ_DEPTH(d, _x, _y) \
-   d = pread_16(irb, x_tile_swizzle(irb, intel, _x, _y))
+#define WRITE_DEPTH(_x, _y, d) pwrite_16(irb, X_TILE(_x, _y), d)
+#define READ_DEPTH(d, _x, _y) d = pread_16(irb, X_TILE(_x, _y))
 #define TAG(x) intel_XTile_##x##_z16
 #include "depthtmp.h"
 
@@ -427,10 +425,8 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
  ** 16-bit y tile depthbuffer functions.
  **/
 #define VALUE_TYPE GLushort
-#define WRITE_DEPTH(_x, _y, d) \
-   pwrite_16(irb, y_tile_swizzle(irb, intel, _x, _y), d)
-#define READ_DEPTH(d, _x, _y) \
-   d = pread_16(irb, y_tile_swizzle(irb, intel, _x, _y))
+#define WRITE_DEPTH(_x, _y, d) pwrite_16(irb, Y_TILE(_x, _y), d)
+#define READ_DEPTH(d, _x, _y) d = pread_16(irb, Y_TILE(_x, _y))
 #define TAG(x) intel_YTile_##x##_z16
 #include "depthtmp.h"
 
@@ -445,12 +441,11 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 /* Change ZZZS -> SZZZ */
 #define WRITE_DEPTH(_x, _y, d)					\
-   pwrite_32(irb, no_tile_swizzle(irb, intel, _x, _y),		\
-	     ((d) >> 8) | ((d) << 24))
+   pwrite_32(irb, NO_TILE(_x, _y), ((d) >> 8) | ((d) << 24))
 
 /* Change SZZZ -> ZZZS */
 #define READ_DEPTH( d, _x, _y ) {				\
-   GLuint tmp = pread_32(irb, no_tile_swizzle(irb, intel, _x, _y));	\
+   GLuint tmp = pread_32(irb, NO_TILE(_x, _y));			\
    d = (tmp << 8) | (tmp >> 24);				\
 }
 
@@ -468,12 +463,11 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 /* Change ZZZS -> SZZZ */
 #define WRITE_DEPTH(_x, _y, d)					\
-   pwrite_32(irb, x_tile_swizzle(irb, intel, _x, _y),		\
-	     ((d) >> 8) | ((d) << 24))				\
+   pwrite_32(irb, X_TILE(_x, _y), ((d) >> 8) | ((d) << 24))
 
 /* Change SZZZ -> ZZZS */
 #define READ_DEPTH( d, _x, _y ) {				\
-   GLuint tmp = pread_32(irb, x_tile_swizzle(irb, intel, _x, _y));	\
+   GLuint tmp = pread_32(irb, X_TILE(_x, _y));		\
    d = (tmp << 8) | (tmp >> 24);				\
 }
 
@@ -490,12 +484,11 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 
 /* Change ZZZS -> SZZZ */
 #define WRITE_DEPTH(_x, _y, d)					\
-   pwrite_32(irb, y_tile_swizzle(irb, intel, _x, _y),		\
-	     ((d) >> 8) | ((d) << 24))
+   pwrite_32(irb, Y_TILE(_x, _y), ((d) >> 8) | ((d) << 24))
 
 /* Change SZZZ -> ZZZS */
 #define READ_DEPTH( d, _x, _y ) {				\
-   GLuint tmp = pread_32(irb, y_tile_swizzle(irb, intel, _x, _y));	\
+   GLuint tmp = pread_32(irb, Y_TILE(_x, _y));			\
    d = (tmp << 8) | (tmp >> 24);				\
 }
 
@@ -506,36 +499,24 @@ static uint32_t y_tile_swizzle(struct intel_renderbuffer *irb,
 /**
  ** 8-bit stencil function (XXX FBO: This is obsolete)
  **/
-#define WRITE_STENCIL(_x, _y, d)				\
-   pwrite_8(irb, no_tile_swizzle(irb, intel, _x, _y) + 3, d)
-
-#define READ_STENCIL(d, _x, _y)					\
-   d = pread_8(irb, no_tile_swizzle(irb, intel, _x, _y) + 3);
-
+#define WRITE_STENCIL(_x, _y, d) pwrite_8(irb, NO_TILE(_x, _y) + 3, d)
+#define READ_STENCIL(d, _x, _y) d = pread_8(irb, NO_TILE(_x, _y) + 3);
 #define TAG(x) intel##x##_z24_s8
 #include "stenciltmp.h"
 
 /**
  ** 8-bit x-tile stencil function (XXX FBO: This is obsolete)
  **/
-#define WRITE_STENCIL(_x, _y, d)				\
-   pwrite_8(irb, x_tile_swizzle(irb, intel, _x, _y) + 3, d)
-
-#define READ_STENCIL(d, _x, _y)					\
-   d = pread_8(irb, x_tile_swizzle(irb, intel, _x, _y) + 3);
-
+#define WRITE_STENCIL(_x, _y, d) pwrite_8(irb, X_TILE(_x, _y) + 3, d)
+#define READ_STENCIL(d, _x, _y) d = pread_8(irb, X_TILE(_x, _y) + 3);
 #define TAG(x) intel_XTile_##x##_z24_s8
 #include "stenciltmp.h"
 
 /**
  ** 8-bit y-tile stencil function (XXX FBO: This is obsolete)
  **/
-#define WRITE_STENCIL(_x, _y, d)				\
-   pwrite_8(irb, y_tile_swizzle(irb, intel, _x, _y) + 3, d)
-
-#define READ_STENCIL(d, _x, _y)					\
-   d = pread_8(irb, y_tile_swizzle(irb, intel, _x, _y) + 3)
-
+#define WRITE_STENCIL(_x, _y, d) pwrite_8(irb, Y_TILE(_x, _y) + 3, d)
+#define READ_STENCIL(d, _x, _y) d = pread_8(irb, Y_TILE(_x, _y) + 3)
 #define TAG(x) intel_YTile_##x##_z24_s8
 #include "stenciltmp.h"
 
@@ -602,14 +583,10 @@ intel_map_unmap_buffers(struct intel_context *intel, GLboolean map)
       if (tex) {
          /* render to texture */
          ASSERT(att->Renderbuffer);
-         if (map) {
-            struct gl_texture_image *texImg;
-            texImg = tex->Image[att->CubeMapFace][att->TextureLevel];
+         if (map)
             intel_tex_map_images(intel, intel_texture_object(tex));
-         }
-         else {
+         else
             intel_tex_unmap_images(intel, intel_texture_object(tex));
-         }
       }
    }
 
-- 
1.5.6.5




More information about the Intel-gfx mailing list