i965: relAddr local var (to make debug/test a little easier)
[mesa.git] / src / mesa / drivers / dri / i915 / i830_vtbl.c
index be4fdff7d6d8af4a1098ecab80b3d72533020c03..3bf02de61f8d29263a43cf9697a360271650535b 100644 (file)
  * 
  **************************************************************************/
 
+#include "glapi/glapi.h"
+#include "main/texformat.h"
 
 #include "i830_context.h"
 #include "i830_reg.h"
 #include "intel_batchbuffer.h"
 #include "intel_regions.h"
+#include "intel_tris.h"
+#include "intel_fbo.h"
 #include "tnl/t_context.h"
 #include "tnl/t_vertex.h"
 
@@ -295,7 +299,7 @@ i830_emit_invarient_state(struct intel_context *intel)
 {
    BATCH_LOCALS;
 
-   BEGIN_BATCH(40, IGNORE_CLIPRECTS);
+   BEGIN_BATCH(30, IGNORE_CLIPRECTS);
 
    OUT_BATCH(_3DSTATE_DFLT_DIFFUSE_CMD);
    OUT_BATCH(0);
@@ -414,38 +418,62 @@ get_state_size(struct i830_hw_state *state)
 /* Push the state into the sarea and/or texture memory.
  */
 static void
-i830_do_emit_state(struct intel_context *intel)
+i830_emit_state(struct intel_context *intel)
 {
    struct i830_context *i830 = i830_context(&intel->ctx);
    struct i830_hw_state *state = i830->current;
-   int i;
+   int i, count;
    GLuint dirty;
+   dri_bo *aper_array[3 + I830_TEX_UNITS];
+   int aper_count;
+   GET_CURRENT_CONTEXT(ctx);
    BATCH_LOCALS;
 
    /* We don't hold the lock at this point, so want to make sure that
-    * there won't be a buffer wrap.  
+    * there won't be a buffer wrap between the state emits and the primitive
+    * emit header.
     *
     * It might be better to talk about explicit places where
     * scheduling is allowed, rather than assume that it is whenever a
     * batchbuffer fills up.
-    */
-   intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
-
-   /* Workaround.  There are cases I haven't been able to track down
-    * where we aren't emitting a full state at the start of a new
-    * batchbuffer.  This code spots that we are on a new batchbuffer
-    * and forces a full state emit no matter what.  
     *
-    * In the normal case state->emitted is already zero, this code is
-    * another set of checks to make sure it really is.
+    * Set the space as LOOP_CLIPRECTS now, since that's what our primitives
+    * will be emitted under.
     */
-   if (intel->batch->id != intel->last_state_batch_id ||
-       intel->batch->map == intel->batch->ptr) 
-   {
-      state->emitted = 0;
-      intel_batchbuffer_require_space(intel->batch, get_state_size(state), 0);
+   intel_batchbuffer_require_space(intel->batch,
+                                  get_state_size(state) + INTEL_PRIM_EMIT_SIZE,
+                                  LOOP_CLIPRECTS);
+   count = 0;
+ again:
+   aper_count = 0;
+   dirty = get_dirty(state);
+
+   aper_array[aper_count++] = intel->batch->buf;
+   if (dirty & I830_UPLOAD_BUFFERS) {
+      aper_array[aper_count++] = state->draw_region->buffer;
+      if (state->depth_region)
+         aper_array[aper_count++] = state->depth_region->buffer;
    }
 
+   for (i = 0; i < I830_TEX_UNITS; i++)
+     if (dirty & I830_UPLOAD_TEX(i)) {
+       if (state->tex_buffer[i]) {
+          aper_array[aper_count++] = state->tex_buffer[i];
+       }
+     }
+
+   if (dri_bufmgr_check_aperture_space(aper_array, aper_count)) {
+       if (count == 0) {
+          count++;
+          intel_batchbuffer_flush(intel->batch);
+          goto again;
+       } else {
+          _mesa_error(ctx, GL_OUT_OF_MEMORY, "i830 emit state");
+          assert(0);
+       }
+   }
+
+
    /* Do this here as we may have flushed the batchbuffer above,
     * causing more state to be dirty!
     */
@@ -453,11 +481,6 @@ i830_do_emit_state(struct intel_context *intel)
    state->emitted |= dirty;
    assert(get_dirty(state) == 0);
 
-   if (intel->batch->id != intel->last_state_batch_id) {
-      assert(dirty & I830_UPLOAD_CTX);
-      intel->last_state_batch_id = intel->batch->id;
-   }
-
    if (dirty & I830_UPLOAD_INVARIENT) {
       DBG("I830_UPLOAD_INVARIENT:\n");
       i830_emit_invarient_state(intel);
@@ -470,19 +493,28 @@ i830_do_emit_state(struct intel_context *intel)
    }
 
    if (dirty & I830_UPLOAD_BUFFERS) {
+      GLuint count = 9; 
+
       DBG("I830_UPLOAD_BUFFERS:\n");
-      BEGIN_BATCH(I830_DEST_SETUP_SIZE + 2, IGNORE_CLIPRECTS);
+
+      if (state->depth_region)
+          count += 3;
+
+      if (intel->constant_cliprect)
+          count += 6;
+
+      BEGIN_BATCH(count, IGNORE_CLIPRECTS);
       OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR0]);
       OUT_BATCH(state->Buffer[I830_DESTREG_CBUFADDR1]);
       OUT_RELOC(state->draw_region->buffer,
-                DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+               I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                 state->draw_region->draw_offset);
 
       if (state->depth_region) {
          OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR0]);
          OUT_BATCH(state->Buffer[I830_DESTREG_DBUFADDR1]);
          OUT_RELOC(state->depth_region->buffer,
-                   DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
+                  I915_GEM_DOMAIN_RENDER, I915_GEM_DOMAIN_RENDER,
                    state->depth_region->draw_offset);
       }
 
@@ -492,6 +524,16 @@ i830_do_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) {
+        assert(state->Buffer[I830_DESTREG_DRAWRECT0] != MI_NOOP);
+        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();
    }
    
@@ -509,7 +551,7 @@ i830_do_emit_state(struct intel_context *intel)
 
          if (state->tex_buffer[i]) {
             OUT_RELOC(state->tex_buffer[i],
-                      DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
+                     I915_GEM_DOMAIN_SAMPLER, 0,
                       state->tex_offset[i] | TM0S0_USE_FENCE);
          }
         else if (state == &i830->meta) {
@@ -526,6 +568,8 @@ i830_do_emit_state(struct intel_context *intel)
          OUT_BATCH(state->Tex[i][I830_TEXREG_TM0S4]);
          OUT_BATCH(state->Tex[i][I830_TEXREG_MCS]);
          OUT_BATCH(state->Tex[i][I830_TEXREG_CUBE]);
+
+         ADVANCE_BATCH();
       }
 
       if (dirty & I830_UPLOAD_TEXBLEND(i)) {
@@ -537,27 +581,6 @@ i830_do_emit_state(struct intel_context *intel)
 
    intel->batch->dirty_state &= ~dirty;
    assert(get_dirty(state) == 0);
-}
-
-static void
-i830_emit_state(struct intel_context *intel)
-{
-   struct i830_context *i830 = i830_context(&intel->ctx);
-
-   i830_do_emit_state( intel );
-
-   /* Second chance - catch batchbuffer wrap in the middle of state
-    * emit.  This shouldn't happen but it has been observed in
-    * testing.
-    */
-   if (get_dirty( i830->current )) {
-      /* Force a full re-emit if this happens.
-       */
-      i830->current->emitted = 0;
-      i830_do_emit_state( intel );
-   }
-
-   assert(get_dirty(i830->current) == 0);
    assert((intel->batch->dirty_state & (1<<1)) == 0);
 }
 
@@ -567,6 +590,13 @@ i830_destroy_context(struct intel_context *intel)
    GLuint i;
    struct i830_context *i830 = i830_context(&intel->ctx);
 
+   intel_region_release(&i830->state.draw_region);
+   intel_region_release(&i830->state.depth_region);
+   intel_region_release(&i830->meta.draw_region);
+   intel_region_release(&i830->meta.depth_region);
+   intel_region_release(&i830->initial.draw_region);
+   intel_region_release(&i830->initial.depth_region);
+
    for (i = 0; i < I830_TEX_UNITS; i++) {
       if (i830->state.tex_buffer[i] != NULL) {
         dri_bo_unreference(i830->state.tex_buffer[i]);
@@ -585,6 +615,9 @@ 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;
+   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+   struct intel_renderbuffer *irb = intel_renderbuffer(rb);
    GLuint value;
 
    ASSERT(state == &i830->state || state == &i830->meta);
@@ -622,13 +655,27 @@ i830_state_draw_region(struct intel_context *intel,
     */
    value = (DSTORG_HORT_BIAS(0x8) |     /* .5 */
             DSTORG_VERT_BIAS(0x8) | DEPTH_IS_Z);    /* .5 */
-            
-   if (color_region && color_region->cpp == 4) {
-      value |= DV_PF_8888;
-   }
-   else {
-      value |= DV_PF_565;
+
+   if (irb != NULL) {
+      switch (irb->texformat->MesaFormat) {
+      case MESA_FORMAT_ARGB8888:
+        value |= DV_PF_8888;
+        break;
+      case MESA_FORMAT_RGB565:
+        value |= DV_PF_565;
+        break;
+      case MESA_FORMAT_ARGB1555:
+        value |= DV_PF_1555;
+        break;
+      case MESA_FORMAT_ARGB4444:
+        value |= DV_PF_4444;
+        break;
+      default:
+        _mesa_problem(ctx, "Bad renderbuffer format: %d\n",
+                      irb->texformat->MesaFormat);
+      }
    }
+
    if (depth_region && depth_region->cpp == 4) {
       value |= DEPTH_FRMT_24_FIXED_8_OTHER;
    }
@@ -637,6 +684,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);
 
 
@@ -645,11 +710,12 @@ i830_state_draw_region(struct intel_context *intel,
 
 static void
 i830_set_draw_region(struct intel_context *intel,
-                     struct intel_region *color_region,
-                     struct intel_region *depth_region)
+                     struct intel_region *color_regions[],
+                     struct intel_region *depth_region,
+                    GLuint num_regions)
 {
    struct i830_context *i830 = i830_context(&intel->ctx);
-   i830_state_draw_region(intel, &i830->state, color_region, depth_region);
+   i830_state_draw_region(intel, &i830->state, color_regions[0], depth_region);
 }
 
 #if 0
@@ -679,6 +745,9 @@ i830_new_batch(struct intel_context *intel)
 {
    struct i830_context *i830 = i830_context(&intel->ctx);
    i830->state.emitted = 0;
+
+   /* Check that we didn't just wrap our batchbuffer at a bad time. */
+   assert(!intel->no_batch_wrap);
 }
 
 
@@ -698,6 +767,11 @@ i830_assert_not_dirty( struct intel_context *intel )
    assert(!get_dirty(state));
 }
 
+static void
+i830_note_unlock( struct intel_context *intel )
+{
+    /* nothing */
+}
 
 void
 i830InitVtbl(struct i830_context *i830)
@@ -713,4 +787,6 @@ i830InitVtbl(struct i830_context *i830)
    i830->intel.vtbl.render_start = i830_render_start;
    i830->intel.vtbl.render_prevalidate = i830_render_prevalidate;
    i830->intel.vtbl.assert_not_dirty = i830_assert_not_dirty;
+   i830->intel.vtbl.note_unlock = i830_note_unlock; 
+   i830->intel.vtbl.finish_batch = intel_finish_vb;
 }