Mesa (i965g-restart): i965g: pass relocation information in an array with bo_subdata

Keith Whitwell keithw at kemper.freedesktop.org
Fri Nov 6 07:36:05 UTC 2009


Module: Mesa
Branch: i965g-restart
Commit: 4c196ed7a8e06933d11b96ac520afa39252fc5c7
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4c196ed7a8e06933d11b96ac520afa39252fc5c7

Author: Keith Whitwell <keithw at vmware.com>
Date:   Thu Nov  5 22:43:36 2009 +0000

i965g: pass relocation information in an array with bo_subdata

Makes it easier to dump as we get all of the information
about the upload in a single hit.

Opens the window to simplification in the driver if these
relocation arrays can be maintained statically rather than
being recreated whenever we check for a new upload.

Still needs some cleanup to avoid uglyness introduced with the
delta values.

---

 src/gallium/drivers/i965/brw_cc.c                 |   27 ++++----
 src/gallium/drivers/i965/brw_clip_state.c         |   35 ++++++----
 src/gallium/drivers/i965/brw_context.h            |    4 +-
 src/gallium/drivers/i965/brw_curbe.c              |    3 +-
 src/gallium/drivers/i965/brw_gs_state.c           |   36 ++++++----
 src/gallium/drivers/i965/brw_sf_state.c           |   73 +++++++++----------
 src/gallium/drivers/i965/brw_state.h              |   16 ++--
 src/gallium/drivers/i965/brw_state_cache.c        |   81 +++++++++++----------
 src/gallium/drivers/i965/brw_vs_state.c           |   28 ++++---
 src/gallium/drivers/i965/brw_vs_surface_state.c   |   69 +++++++-----------
 src/gallium/drivers/i965/brw_winsys.h             |   28 +++++++-
 src/gallium/drivers/i965/brw_wm_constant_buffer.c |   25 +++----
 src/gallium/drivers/i965/brw_wm_sampler_state.c   |   27 ++++----
 src/gallium/drivers/i965/brw_wm_state.c           |   61 ++++++++--------
 src/gallium/drivers/i965/brw_wm_surface_state.c   |   70 +++++++++----------
 src/gallium/winsys/drm/i965/xlib/xlib_i965.c      |   31 +++++++--
 16 files changed, 327 insertions(+), 287 deletions(-)

diff --git a/src/gallium/drivers/i965/brw_cc.c b/src/gallium/drivers/i965/brw_cc.c
index 78d8392..94e2c99 100644
--- a/src/gallium/drivers/i965/brw_cc.c
+++ b/src/gallium/drivers/i965/brw_cc.c
@@ -129,6 +129,7 @@ cc_unit_populate_key(const struct brw_context *brw,
 static enum pipe_error
 cc_unit_create_from_key(struct brw_context *brw, 
                         struct brw_cc_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_cc_unit_state cc;
@@ -141,50 +142,48 @@ cc_unit_create_from_key(struct brw_context *brw,
    cc.cc2 = key->cc2;
    cc.cc3 = key->cc3;
 
-   /* CACHE_NEW_CC_VP */
    cc.cc4.cc_viewport_state_offset = 0;
 
    cc.cc5 = key->cc5;
    cc.cc6 = key->cc6;
    cc.cc7 = key->cc7;
-
+   
    ret = brw_upload_cache(&brw->cache, BRW_CC_UNIT,
                           key, sizeof(*key),
-                          &brw->cc.vp_bo, 1,
+                          reloc, Elements(reloc),
                           &cc, sizeof(cc),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-
-   /* Emit CC viewport relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 0,
-                                 offsetof(struct brw_cc_unit_state, cc4),
-                                 brw->cc.vp_bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
 static int prepare_cc_unit( struct brw_context *brw )
 {
    struct brw_cc_unit_key key;
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
    cc_unit_populate_key(brw, &key);
 
+   /* CACHE_NEW_CC_VP */
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              0,
+              offsetof(struct brw_cc_unit_state, cc4),
+              brw->cc.vp_bo);
+
    if (brw_search_cache(&brw->cache, BRW_CC_UNIT,
                         &key, sizeof(key),
-                        &brw->cc.vp_bo, 1,
+                        reloc, 1,
                         NULL,
                         &brw->cc.state_bo))
       return PIPE_OK;
 
    ret = cc_unit_create_from_key(brw, &key, 
+                                 reloc,
                                  &brw->cc.state_bo);
    if (ret)
       return ret;
diff --git a/src/gallium/drivers/i965/brw_clip_state.c b/src/gallium/drivers/i965/brw_clip_state.c
index 157e6ed..3f2b970 100644
--- a/src/gallium/drivers/i965/brw_clip_state.c
+++ b/src/gallium/drivers/i965/brw_clip_state.c
@@ -75,6 +75,7 @@ clip_unit_populate_key(struct brw_context *brw, struct brw_clip_unit_key *key)
 static enum pipe_error
 clip_unit_create_from_key(struct brw_context *brw,
                           struct brw_clip_unit_key *key,
+                          struct brw_winsys_reloc *reloc,
                           struct brw_winsys_buffer **bo_out)
 {
    struct brw_clip_unit_state clip;
@@ -82,7 +83,6 @@ clip_unit_create_from_key(struct brw_context *brw,
 
    memset(&clip, 0, sizeof(clip));
 
-   clip.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
    /* reloc */
    clip.thread0.kernel_start_pointer = 0;
 
@@ -144,36 +144,44 @@ clip_unit_create_from_key(struct brw_context *brw,
 
    ret = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT,
                           key, sizeof(*key),
-                          &brw->clip.prog_bo, 1,
+                          reloc, 1,
                           &clip, sizeof(clip),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* Emit clip program relocation */
-   assert(brw->clip.prog_bo);
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 clip.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_clip_unit_state, thread0),
-                                 brw->clip.prog_bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
 static int upload_clip_unit( struct brw_context *brw )
 {
    struct brw_clip_unit_key key;
+   struct brw_winsys_reloc reloc[1];
+   unsigned grf_reg_count;
    enum pipe_error ret;
 
    clip_unit_populate_key(brw, &key);
 
+   grf_reg_count = align(key.total_grf, 16) / 16 - 1;
+
+   /* clip program relocation
+    *
+    * XXX: these reloc structs are long lived and only need to be
+    * updated when the bound BO changes.  Hopefully the stuff mixed in
+    * in the delta's is non-orthogonal.
+    */
+   assert(brw->clip.prog_bo);
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              grf_reg_count << 1,
+              offsetof(struct brw_clip_unit_state, thread0),
+              brw->clip.prog_bo);
+
+
    if (brw_search_cache(&brw->cache, BRW_CLIP_UNIT,
                         &key, sizeof(key),
-                        &brw->clip.prog_bo, 1,
+                        reloc, 1,
                         NULL,
                         &brw->clip.state_bo))
       return PIPE_OK;
@@ -181,6 +189,7 @@ static int upload_clip_unit( struct brw_context *brw )
    /* Create new:
     */
    ret = clip_unit_create_from_key(brw, &key, 
+                                   reloc,
                                    &brw->clip.state_bo);
    if (ret)
       return ret;
diff --git a/src/gallium/drivers/i965/brw_context.h b/src/gallium/drivers/i965/brw_context.h
index 177fe21..67fad0d 100644
--- a/src/gallium/drivers/i965/brw_context.h
+++ b/src/gallium/drivers/i965/brw_context.h
@@ -383,8 +383,8 @@ struct brw_cache_item {
    GLuint hash;
    GLuint key_size;		/* for variable-sized keys */
    const void *key;
-   struct brw_winsys_buffer **reloc_bufs;
-   GLuint nr_reloc_bufs;
+   struct brw_winsys_reloc *relocs;
+   GLuint nr_relocs;
 
    struct brw_winsys_buffer *bo;
    GLuint data_size;
diff --git a/src/gallium/drivers/i965/brw_curbe.c b/src/gallium/drivers/i965/brw_curbe.c
index ca7774a..0a5cfcc 100644
--- a/src/gallium/drivers/i965/brw_curbe.c
+++ b/src/gallium/drivers/i965/brw_curbe.c
@@ -295,7 +295,8 @@ static enum pipe_error prepare_curbe_buffer(struct brw_context *brw)
 			   brw->curbe.curbe_offset,
                            BRW_DATA_OTHER,
 			   bufsz,
-			   buf);
+			   buf,
+                           NULL, 0);
    }
 
    brw_add_validated_bo(brw, brw->curbe.curbe_bo);
diff --git a/src/gallium/drivers/i965/brw_gs_state.c b/src/gallium/drivers/i965/brw_gs_state.c
index 36a99fd..1b0de17 100644
--- a/src/gallium/drivers/i965/brw_gs_state.c
+++ b/src/gallium/drivers/i965/brw_gs_state.c
@@ -72,15 +72,18 @@ gs_unit_populate_key(struct brw_context *brw, struct brw_gs_unit_key *key)
 static enum pipe_error
 gs_unit_create_from_key(struct brw_context *brw, 
                         struct brw_gs_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
+                        unsigned nr_reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_gs_unit_state gs;
    enum pipe_error ret;
 
+
    memset(&gs, 0, sizeof(gs));
 
+   /* maybe-reloc: populate the background */
    gs.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
-   /* reloc */
    gs.thread0.kernel_start_pointer = 0;
 
    gs.thread1.floating_point_mode = BRW_FLOATING_POINT_NON_IEEE_754;
@@ -108,22 +111,13 @@ gs_unit_create_from_key(struct brw_context *brw,
 
    ret = brw_upload_cache(&brw->cache, BRW_GS_UNIT,
                           key, sizeof(*key),
-                          &brw->gs.prog_bo, 1,
+                          reloc, nr_reloc,
                           &gs, sizeof(gs),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   if (key->prog_active) {
-      /* Emit GS program relocation */
-      brw->sws->bo_emit_reloc(*bo_out,
-			      BRW_USAGE_STATE,
-			      gs.thread0.grf_reg_count << 1,
-			      offsetof(struct brw_gs_unit_state, thread0),
-			      brw->gs.prog_bo);
-   }
-
    return PIPE_OK;
 }
 
@@ -131,17 +125,33 @@ static enum pipe_error prepare_gs_unit(struct brw_context *brw)
 {
    struct brw_gs_unit_key key;
    enum pipe_error ret;
+   struct brw_winsys_reloc reloc[1];
+   unsigned nr_reloc = 0;
+   unsigned grf_reg_count;
 
    gs_unit_populate_key(brw, &key);
 
+   grf_reg_count = (align(key.total_grf, 16) / 16 - 1);
+
+   /* GS program relocation */
+   if (key.prog_active) {
+      make_reloc(&reloc[nr_reloc++],
+                 BRW_USAGE_STATE,
+                 grf_reg_count << 1,
+                 offsetof(struct brw_gs_unit_state, thread0),
+                 brw->gs.prog_bo);
+   }
+
    if (brw_search_cache(&brw->cache, BRW_GS_UNIT,
                         &key, sizeof(key),
-                        &brw->gs.prog_bo, 1,
+                        reloc, nr_reloc,
                         NULL,
                         &brw->gs.state_bo))
       return PIPE_OK;
 
-   ret = gs_unit_create_from_key(brw, &key, &brw->gs.state_bo);
+   ret = gs_unit_create_from_key(brw, &key,
+                                 reloc, nr_reloc,
+                                 &brw->gs.state_bo);
    if (ret)
       return ret;
 
diff --git a/src/gallium/drivers/i965/brw_sf_state.c b/src/gallium/drivers/i965/brw_sf_state.c
index 689483b..a911482 100644
--- a/src/gallium/drivers/i965/brw_sf_state.c
+++ b/src/gallium/drivers/i965/brw_sf_state.c
@@ -132,8 +132,9 @@ sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key)
 }
 
 static enum pipe_error
-sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
-			struct brw_winsys_buffer **reloc_bufs,
+sf_unit_create_from_key(struct brw_context *brw,
+                        struct brw_sf_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_sf_unit_state sf;
@@ -141,7 +142,8 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
    int chipset_max_threads;
    memset(&sf, 0, sizeof(sf));
 
-   sf.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
+
+   sf.thread0.grf_reg_count = 0;
    /* reloc */
    sf.thread0.kernel_start_pointer = 0;
 
@@ -177,18 +179,10 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
 
    /* CACHE_NEW_SF_VP */
    /* reloc */
-   sf.sf5.sf_viewport_state_offset = 0;
-
-   sf.sf5.viewport_transform = 1;
 
    if (key->scissor)
       sf.sf6.scissor = 1;
 
-   if (key->front_face == PIPE_WINDING_CCW)
-      sf.sf5.front_winding = BRW_FRONTWINDING_CCW;
-   else
-      sf.sf5.front_winding = BRW_FRONTWINDING_CW;
-
    switch (key->cull_mode) {
    case PIPE_WINDING_CCW:
    case PIPE_WINDING_CW:
@@ -281,34 +275,13 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
 
    ret = brw_upload_cache(&brw->cache, BRW_SF_UNIT,
                           key, sizeof(*key),
-                          reloc_bufs, 2,
+                          reloc, 2,
                           &sf, sizeof(sf),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* STATE_PREFETCH command description describes this state as being
-    * something loaded through the GPE (L2 ISC), so it's INSTRUCTION domain.
-    */
-   /* Emit SF program relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 sf.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_sf_unit_state, thread0),
-                                 brw->sf.prog_bo);
-   if (ret)
-      return ret;
-
-
-   /* Emit SF viewport relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 sf.sf5.front_winding | (sf.sf5.viewport_transform << 1),
-                                 offsetof(struct brw_sf_unit_state, sf5),
-                                 brw->sf.vp_bo);
-   if (ret)
-      return ret;
    
    return PIPE_OK;
 }
@@ -316,23 +289,47 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
 static enum pipe_error upload_sf_unit( struct brw_context *brw )
 {
    struct brw_sf_unit_key key;
-   struct brw_winsys_buffer *reloc_bufs[2];
+   struct brw_winsys_reloc reloc[2];
+   unsigned total_grf;
+   unsigned viewport_transform;
+   unsigned front_winding;
    enum pipe_error ret;
 
    sf_unit_populate_key(brw, &key);
+   
+   /* XXX: cut this crap and pre calculate the key:
+    */
+   total_grf = (align(key.total_grf, 16) / 16 - 1);
+   viewport_transform = 1;
+   front_winding = (key.front_face == PIPE_WINDING_CCW ?
+                    BRW_FRONTWINDING_CCW :
+                    BRW_FRONTWINDING_CW);
+
+   /* Emit SF program relocation */
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              total_grf << 1,
+              offsetof(struct brw_sf_unit_state, thread0),
+              brw->sf.prog_bo);
+
+   /* Emit SF viewport relocation */
+   make_reloc(&reloc[1],
+              BRW_USAGE_STATE,
+              front_winding | (viewport_transform << 1),
+              offsetof(struct brw_sf_unit_state, sf5),
+              brw->sf.vp_bo);
 
-   reloc_bufs[0] = brw->sf.prog_bo;
-   reloc_bufs[1] = brw->sf.vp_bo;
 
    if (brw_search_cache(&brw->cache, BRW_SF_UNIT,
                         &key, sizeof(key),
-                        reloc_bufs, 2,
+                        reloc, 2,
                         NULL,
                         &brw->sf.state_bo))
       return PIPE_OK;
 
 
-   ret = sf_unit_create_from_key(brw, &key, reloc_bufs,
+   ret = sf_unit_create_from_key(brw, &key,
+                                 reloc,
                                  &brw->sf.state_bo);
    if (ret)
       return ret;
diff --git a/src/gallium/drivers/i965/brw_state.h b/src/gallium/drivers/i965/brw_state.h
index e219a1d..97710ab 100644
--- a/src/gallium/drivers/i965/brw_state.h
+++ b/src/gallium/drivers/i965/brw_state.h
@@ -109,24 +109,24 @@ void brw_destroy_state(struct brw_context *brw);
 enum pipe_error brw_cache_data(struct brw_cache *cache,
                                enum brw_cache_id cache_id,
                                const void *data,
-                               struct brw_winsys_buffer **reloc_bufs,
-                               GLuint nr_reloc_bufs,
+                               struct brw_winsys_reloc *relocs,
+                               GLuint nr_relocs,
                                struct brw_winsys_buffer **bo_out );
 
 enum pipe_error brw_cache_data_sz(struct brw_cache *cache,
                                   enum brw_cache_id cache_id,
                                   const void *data,
                                   GLuint data_size,
-                                  struct brw_winsys_buffer **reloc_bufs,
-                                  GLuint nr_reloc_bufs,
+                                  struct brw_winsys_reloc *relocs,
+                                  GLuint nr_relocs,
                                   struct brw_winsys_buffer **bo_out);
 
 enum pipe_error brw_upload_cache( struct brw_cache *cache,
                                   enum brw_cache_id cache_id,
                                   const void *key,
                                   GLuint key_sz,
-                                  struct brw_winsys_buffer **reloc_bufs,
-                                  GLuint nr_reloc_bufs,
+                                  struct brw_winsys_reloc *relocs,
+                                  GLuint nr_relocs,
                                   const void *data,
                                   GLuint data_sz,
                                   const void *aux,
@@ -137,8 +137,8 @@ boolean brw_search_cache( struct brw_cache *cache,
                           enum brw_cache_id cache_id,
                           const void *key,
                           GLuint key_size,
-                          struct brw_winsys_buffer **reloc_bufs,
-                          GLuint nr_reloc_bufs,
+                          struct brw_winsys_reloc *relocs,
+                          GLuint nr_relocs,
                           void *aux_return,
                           struct brw_winsys_buffer **bo_out);
 
diff --git a/src/gallium/drivers/i965/brw_state_cache.c b/src/gallium/drivers/i965/brw_state_cache.c
index f8369d3..16b643c 100644
--- a/src/gallium/drivers/i965/brw_state_cache.c
+++ b/src/gallium/drivers/i965/brw_state_cache.c
@@ -47,7 +47,7 @@
  * a safe point (unlock) we throw out all of the cache data and let it
  * regenerate for the next rendering operation.
  *
- * The reloc_buf pointers need to be included as key data, otherwise the
+ * The reloc structs need to be included as key data, otherwise the
  * non-unique values stuffed in the offset in key data through
  * brw_cache_data() may result in successful probe for state buffers
  * even when the buffer being referenced doesn't match.  The result would be
@@ -73,7 +73,7 @@
 
 static GLuint
 hash_key(const void *key, GLuint key_size,
-         struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs)
+         struct brw_winsys_reloc *relocs, GLuint nr_relocs)
 {
    GLuint *ikey = (GLuint *)key;
    GLuint hash = 0, i;
@@ -88,8 +88,8 @@ hash_key(const void *key, GLuint key_size,
    }
 
    /* Include the BO pointers as key data as well */
-   ikey = (GLuint *)reloc_bufs;
-   key_size = nr_reloc_bufs * sizeof(struct brw_winsys_buffer *);
+   ikey = (GLuint *)relocs;
+   key_size = nr_relocs * sizeof(struct brw_winsys_reloc);
    for (i = 0; i < key_size/4; i++) {
       hash ^= ikey[i];
       hash = (hash << 5) | (hash >> 27);
@@ -118,7 +118,7 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
 static struct brw_cache_item *
 search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
 	     GLuint hash, const void *key, GLuint key_size,
-	     struct brw_winsys_buffer **reloc_bufs, GLuint nr_reloc_bufs)
+	     struct brw_winsys_reloc *relocs, GLuint nr_relocs)
 {
    struct brw_cache_item *c;
 
@@ -137,9 +137,8 @@ search_cache(struct brw_cache *cache, enum brw_cache_id cache_id,
 	  c->hash == hash &&
 	  c->key_size == key_size &&
 	  memcmp(c->key, key, key_size) == 0 &&
-	  c->nr_reloc_bufs == nr_reloc_bufs &&
-	  memcmp(c->reloc_bufs, reloc_bufs,
-		 nr_reloc_bufs * sizeof(struct brw_winsys_buffer *)) == 0)
+	  c->nr_relocs == nr_relocs &&
+	  memcmp(c->relocs, relocs, nr_relocs * sizeof *relocs) == 0)
 	 return c;
    }
 
@@ -178,16 +177,16 @@ brw_search_cache(struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *key,
                  GLuint key_size,
-                 struct brw_winsys_buffer **reloc_bufs, 
-		 GLuint nr_reloc_bufs,
+                 struct brw_winsys_reloc *relocs, 
+		 GLuint nr_relocs,
                  void *aux_return,
                  struct brw_winsys_buffer **bo_out)
 {
    struct brw_cache_item *item;
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
+   GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
 
    item = search_cache(cache, cache_id, hash, key, key_size,
-		       reloc_bufs, nr_reloc_bufs);
+		       relocs, nr_relocs);
 
    if (item) {
       if (aux_return)
@@ -207,8 +206,8 @@ brw_upload_cache( struct brw_cache *cache,
 		  enum brw_cache_id cache_id,
 		  const void *key,
 		  GLuint key_size,
-		  struct brw_winsys_buffer **reloc_bufs,
-		  GLuint nr_reloc_bufs,
+		  struct brw_winsys_reloc *relocs,
+		  GLuint nr_relocs,
 		  const void *data,
 		  GLuint data_size,
 		  const void *aux,
@@ -216,8 +215,8 @@ brw_upload_cache( struct brw_cache *cache,
                   struct brw_winsys_buffer **bo_out)
 {
    struct brw_cache_item *item = CALLOC_STRUCT(brw_cache_item);
-   GLuint hash = hash_key(key, key_size, reloc_bufs, nr_reloc_bufs);
-   GLuint relocs_size = nr_reloc_bufs * sizeof(struct brw_winsys_buffer *);
+   GLuint hash = hash_key(key, key_size, relocs, nr_relocs);
+   GLuint relocs_size = nr_relocs * sizeof relocs[0];
    GLuint aux_size = cache->aux_size[cache_id];
    enum pipe_error ret;
    void *tmp;
@@ -236,23 +235,22 @@ brw_upload_cache( struct brw_cache *cache,
       return ret;
 
 
-   /* Set up the memory containing the key, aux_data, and reloc_bufs */
+   /* Set up the memory containing the key, aux_data, and relocs */
    tmp = MALLOC(key_size + aux_size + relocs_size);
 
    memcpy(tmp, key, key_size);
    memcpy((char *)tmp + key_size, aux, cache->aux_size[cache_id]);
-   memcpy((char *)tmp + key_size + aux_size, reloc_bufs, relocs_size);
-   for (i = 0; i < nr_reloc_bufs; i++) {
-      if (reloc_bufs[i] != NULL)
-         p_atomic_inc(&reloc_bufs[i]->reference.count);
+   memcpy((char *)tmp + key_size + aux_size, relocs, relocs_size);
+   for (i = 0; i < nr_relocs; i++) {
+      p_atomic_inc(&relocs[i].bo->reference.count);
    }
 
    item->cache_id = cache_id;
    item->key = tmp;
    item->hash = hash;
    item->key_size = key_size;
-   item->reloc_bufs = (struct brw_winsys_buffer **)((char *)tmp + key_size + aux_size);
-   item->nr_reloc_bufs = nr_reloc_bufs;
+   item->relocs = (struct brw_winsys_reloc *)((char *)tmp + key_size + aux_size);
+   item->nr_relocs = nr_relocs;
    bo_reference( &item->bo, *bo_out );
    item->data_size = data_size;
 
@@ -275,9 +273,12 @@ brw_upload_cache( struct brw_cache *cache,
 		   data_size, cache_id);
 
    /* Copy data to the buffer */
-   cache->sws->bo_subdata(item->bo, 
-                          cache_id,
-                          0, data_size, data);
+   ret = cache->sws->bo_subdata(item->bo, 
+                                cache_id,
+                                0, data_size, data,
+                                relocs, nr_relocs);
+   if (ret)
+      return ret;
 
    update_cache_last(cache, cache_id, item->bo);
 
@@ -293,15 +294,15 @@ brw_cache_data_sz(struct brw_cache *cache,
 		  enum brw_cache_id cache_id,
 		  const void *data,
 		  GLuint data_size,
-		  struct brw_winsys_buffer **reloc_bufs,
-		  GLuint nr_reloc_bufs,
+		  struct brw_winsys_reloc *relocs,
+		  GLuint nr_relocs,
                   struct brw_winsys_buffer **bo_out)
 {
    struct brw_cache_item *item;
-   GLuint hash = hash_key(data, data_size, reloc_bufs, nr_reloc_bufs);
+   GLuint hash = hash_key(data, data_size, relocs, nr_relocs);
 
    item = search_cache(cache, cache_id, hash, data, data_size,
-		       reloc_bufs, nr_reloc_bufs);
+		       relocs, nr_relocs);
    if (item) {
       update_cache_last(cache, cache_id, item->bo);
 
@@ -311,7 +312,7 @@ brw_cache_data_sz(struct brw_cache *cache,
 
    return brw_upload_cache(cache, cache_id,
                            data, data_size,
-                           reloc_bufs, nr_reloc_bufs,
+                           relocs, nr_relocs,
                            data, data_size,
                            NULL, NULL,
                            bo_out);
@@ -321,20 +322,22 @@ brw_cache_data_sz(struct brw_cache *cache,
 /**
  * Wrapper around brw_cache_data_sz using the cache_id's canonical key size.
  *
- * If nr_reloc_bufs is nonzero, brw_search_cache()/brw_upload_cache() would be
+ * If nr_relocs is nonzero, brw_search_cache()/brw_upload_cache() would be
  * better to use, as the potentially changing offsets in the data-used-as-key
  * will result in excessive cache misses.
+ * 
+ * XXX: above is no longer true -- can we remove some code?
  */
 enum pipe_error
 brw_cache_data(struct brw_cache *cache,
 	       enum brw_cache_id cache_id,
 	       const void *data,
-	       struct brw_winsys_buffer **reloc_bufs,
-	       GLuint nr_reloc_bufs,
+	       struct brw_winsys_reloc *relocs,
+	       GLuint nr_relocs,
                struct brw_winsys_buffer **bo_out)
 {
    return brw_cache_data_sz(cache, cache_id, data, cache->key_size[cache_id],
-			    reloc_bufs, nr_reloc_bufs, bo_out);
+			    relocs, nr_relocs, bo_out);
 }
 
 
@@ -510,8 +513,8 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
 
 	 next = c->next;
 
-	 for (j = 0; j < c->nr_reloc_bufs; j++)
-	    bo_reference(&c->reloc_bufs[j], NULL);
+	 for (j = 0; j < c->nr_relocs; j++)
+	    bo_reference(&c->relocs[j].bo, NULL);
 
 	 bo_reference(&c->bo, NULL);
 	 FREE((void *)c->key);
@@ -555,8 +558,8 @@ brw_state_cache_bo_delete(struct brw_cache *cache, struct brw_winsys_buffer *bo)
 
 	    *prev = c->next;
 
-	    for (j = 0; j < c->nr_reloc_bufs; j++)
-	       bo_reference(&c->reloc_bufs[j], NULL);
+	    for (j = 0; j < c->nr_relocs; j++)
+	       bo_reference(&c->relocs[j].bo, NULL);
 
 	    bo_reference(&c->bo, NULL);
 
diff --git a/src/gallium/drivers/i965/brw_vs_state.c b/src/gallium/drivers/i965/brw_vs_state.c
index a5b30eb..0b44f39 100644
--- a/src/gallium/drivers/i965/brw_vs_state.c
+++ b/src/gallium/drivers/i965/brw_vs_state.c
@@ -81,6 +81,7 @@ vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key)
 static enum pipe_error
 vs_unit_create_from_key(struct brw_context *brw, 
                         struct brw_vs_unit_key *key,
+                        struct brw_winsys_reloc *reloc,
                         struct brw_winsys_buffer **bo_out)
 {
    enum pipe_error ret;
@@ -145,22 +146,13 @@ vs_unit_create_from_key(struct brw_context *brw,
 
    ret = brw_upload_cache(&brw->cache, BRW_VS_UNIT,
                           key, sizeof(*key),
-                          &brw->vs.prog_bo, 1,
+                          reloc, Elements(reloc),
                           &vs, sizeof(vs),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* Emit VS program relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 vs.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_vs_unit_state, thread0),
-                                 brw->vs.prog_bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
@@ -168,17 +160,29 @@ static int prepare_vs_unit(struct brw_context *brw)
 {
    struct brw_vs_unit_key key;
    enum pipe_error ret;
+   struct brw_winsys_reloc reloc[1];
+   unsigned grf_reg_count;
 
    vs_unit_populate_key(brw, &key);
 
+   grf_reg_count = (align(key.total_grf, 16) / 16 - 1);
+
+   /* Emit VS program relocation */
+   make_reloc(&reloc[0],
+              BRW_USAGE_STATE,
+              grf_reg_count << 1,
+              offsetof(struct brw_vs_unit_state, thread0),
+              brw->vs.prog_bo);
+
+
    if (brw_search_cache(&brw->cache, BRW_VS_UNIT,
                         &key, sizeof(key),
-                        &brw->vs.prog_bo, 1,
+                        reloc, 1,
                         NULL,
                         &brw->vs.state_bo))
       return PIPE_OK;
 
-   ret = vs_unit_create_from_key(brw, &key, &brw->vs.state_bo);
+   ret = vs_unit_create_from_key(brw, &key, reloc, &brw->vs.state_bo);
    if (ret)
       return ret;
 
diff --git a/src/gallium/drivers/i965/brw_vs_surface_state.c b/src/gallium/drivers/i965/brw_vs_surface_state.c
index b12df0e..aaf2a44 100644
--- a/src/gallium/drivers/i965/brw_vs_surface_state.c
+++ b/src/gallium/drivers/i965/brw_vs_surface_state.c
@@ -65,7 +65,8 @@ brw_vs_update_constant_buffer(struct brw_context *brw)
 				     size, 64);
 
    /* _NEW_PROGRAM_CONSTANTS */
-   dri_bo_subdata(const_buffer, 0, size, params->ParameterValues);
+   brw->sws->bo_subdata(const_buffer, 0, size, params->ParameterValues,
+                        NULL, 0);
 
    return const_buffer;
 }
@@ -145,51 +146,31 @@ brw_vs_get_binding_table(struct brw_context *brw,
                          struct brw_winsys_buffer **bo_out)
 {
 #if 0
-   if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
-                        NULL, 0,
-                        brw->vs.surf_bo, BRW_VS_MAX_SURF,
-                        NULL,
-                        bo_out))
-   {
-      return PIPE_OK;
-   }
-   else {
-      GLuint data_size = BRW_VS_MAX_SURF * sizeof(GLuint);
-      uint32_t *data = malloc(data_size);
-      int i;
-
-      for (i = 0; i < BRW_VS_MAX_SURF; i++)
-         if (brw->vs.surf_bo[i])
-            data[i] = brw->vs.surf_bo[i]->offset;
-         else
-            data[i] = 0;
-
-      ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
-                              NULL, 0,
-                              brw->vs.surf_bo, BRW_VS_MAX_SURF,
-                              data, data_size,
-                              NULL, NULL,
-                              bo_out);
-      if (ret)
-         return ret;
-
-      /* Emit binding table relocations to surface state */
-      for (i = 0; i < BRW_VS_MAX_SURF; i++) {
-	 if (brw->vs.surf_bo[i] != NULL) {
-	    /* The presumed offsets were set in the data values for
-	     * brw_upload_cache.
-	     */
-	    ret = sws->bo_emit_reloc(*bo_out, i * 4,
-                                     brw->vs.surf_bo[i], 0,
-                                     BRW_USAGE_STATE);
-            if (ret)
-               return ret;
-	 }
-      }
+   static GLuint data[BRW_VS_MAX_SURF]; /* always zero */
+   struct brw_winsys_reloc reloc[BRW_VS_MAX_SURF];
+   int i;
 
-      FREE(data);
-      return PIPE_OK;
+   /* Emit binding table relocations to surface state */
+   for (i = 0; i < BRW_VS_MAX_SURF; i++) {
+      make_reloc(&reloc[i],
+                 BRW_USAGE_STATE,
+                 0,
+                 i * 4,
+                 brw->vs.surf_bo[i]);
    }
+   
+   ret = brw_cache_data( &brw->surface_cache, 
+                         BRW_SS_SURF_BIND,
+                         NULL, 0,
+                         reloc, Elements(reloc),
+                         data, sizeof data,
+                         NULL, NULL,
+                         bo_out);
+   if (ret)
+      return ret;
+
+   FREE(data);
+   return PIPE_OK;
 #else
    return PIPE_OK;
 #endif
diff --git a/src/gallium/drivers/i965/brw_winsys.h b/src/gallium/drivers/i965/brw_winsys.h
index e72b928..2da660a 100644
--- a/src/gallium/drivers/i965/brw_winsys.h
+++ b/src/gallium/drivers/i965/brw_winsys.h
@@ -111,6 +111,30 @@ enum brw_buffer_data_type {
 };
 
 
+/* Relocations to be applied with subdata in a call to sws->bo_subdata, below.
+ *
+ * Effectively this encodes:
+ *
+ *    (unsigned *)(subdata + offset) = bo->offset + delta
+ */
+struct brw_winsys_reloc {
+   enum brw_buffer_usage usage; /* debug only */
+   unsigned delta;
+   unsigned offset;
+   struct brw_winsys_buffer *bo;
+};
+
+static INLINE void make_reloc( struct brw_winsys_reloc *reloc,
+                               enum brw_buffer_usage usage,
+                               unsigned delta,
+                               unsigned offset,
+                               struct brw_winsys_buffer *bo)
+{
+   reloc->usage = usage;
+   reloc->delta = delta;
+   reloc->offset = offset;
+   reloc->bo = bo;              /* Note - note taking a reference yet */
+}
 
 
 
@@ -151,7 +175,9 @@ struct brw_winsys_screen {
                                  enum brw_buffer_data_type data_type,
                                  size_t offset,
                                  size_t size,
-                                 const void *data);
+                                 const void *data,
+                                 const struct brw_winsys_reloc *reloc,
+                                 unsigned nr_reloc );
 
    boolean (*bo_is_busy)(struct brw_winsys_buffer *buffer);
    boolean (*bo_references)(struct brw_winsys_buffer *a,
diff --git a/src/gallium/drivers/i965/brw_wm_constant_buffer.c b/src/gallium/drivers/i965/brw_wm_constant_buffer.c
index 1456826..6434c6a 100644
--- a/src/gallium/drivers/i965/brw_wm_constant_buffer.c
+++ b/src/gallium/drivers/i965/brw_wm_constant_buffer.c
@@ -13,16 +13,24 @@ brw_create_constant_surface( struct brw_context *brw,
 {
    const GLint w = key->width - 1;
    struct brw_winsys_buffer *bo;
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
+      /* Emit relocation to surface contents */
+   make_reloc(&reloc[0],
+              BRW_USAGE_SAMPLER,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              key->bo);
+
+   
    memset(&surf, 0, sizeof(surf));
 
    surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
    surf.ss0.surface_type = BRW_SURFACE_BUFFER;
    surf.ss0.surface_format = BRW_SURFACEFORMAT_R32G32B32A32_FLOAT;
 
-   assert(key->bo);
-   surf.ss1.base_addr = key->bo->offset; /* reloc */
+   surf.ss1.base_addr = 0; /* reloc */
 
    surf.ss2.width = w & 0x7f;            /* bits 6:0 of size or width */
    surf.ss2.height = (w >> 7) & 0x1fff;  /* bits 19:7 of size or width */
@@ -32,24 +40,13 @@ brw_create_constant_surface( struct brw_context *brw,
  
    ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
                           key, sizeof(*key),
-                          &key->bo, key->bo ? 1 : 0,
+                          reloc, Elements(reloc),
                           &surf, sizeof(surf),
                           NULL, NULL,
                           &bo_out);
    if (ret)
       return ret;
 
-   if (key->bo) {
-      /* Emit relocation to surface contents */
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_SAMPLER,
-                                    0,
-                                    offsetof(struct brw_surface_state, ss1),
-                                    key->bo);
-      if (ret)
-         return ret;
-   }
-
    return PIPE_OK;
 }
 
diff --git a/src/gallium/drivers/i965/brw_wm_sampler_state.c b/src/gallium/drivers/i965/brw_wm_sampler_state.c
index 174836b..4e99ac7 100644
--- a/src/gallium/drivers/i965/brw_wm_sampler_state.c
+++ b/src/gallium/drivers/i965/brw_wm_sampler_state.c
@@ -165,6 +165,7 @@ brw_wm_sampler_update_default_colors(struct brw_context *brw)
 static int upload_wm_samplers( struct brw_context *brw )
 {
    struct wm_sampler_key key;
+   struct brw_winsys_reloc reloc[BRW_MAX_TEX_UNIT];
    enum pipe_error ret;
    int i;
 
@@ -181,9 +182,20 @@ static int upload_wm_samplers( struct brw_context *brw )
       return PIPE_OK;
    }
 
+   /* Emit SDC relocations */
+   for (i = 0; i < key.sampler_count; i++) {
+      make_reloc( &reloc[i],
+                  BRW_USAGE_SAMPLER,
+                  0,
+                  i * sizeof(struct brw_sampler_state) +
+                  offsetof(struct brw_sampler_state, ss2),
+                  brw->wm.sdc_bo[i]);
+   }
+
+
    if (brw_search_cache(&brw->cache, BRW_SAMPLER,
                         &key, sizeof(key),
-                        brw->wm.sdc_bo, key.sampler_count,
+                        reloc, key.sampler_count,
                         NULL,
                         &brw->wm.sampler_bo))
       return PIPE_OK;
@@ -193,24 +205,13 @@ static int upload_wm_samplers( struct brw_context *brw )
     */
    ret = brw_upload_cache(&brw->cache, BRW_SAMPLER,
                           &key, sizeof(key),
-                          brw->wm.sdc_bo, key.sampler_count,
+                          reloc, key.sampler_count,
                           &key.sampler, sizeof(key.sampler),
                           NULL, NULL,
                           &brw->wm.sampler_bo);
    if (ret)
       return ret;
 
-   /* Emit SDC relocations */
-   for (i = 0; i < key.sampler_count; i++) {
-      ret = brw->sws->bo_emit_reloc(brw->wm.sampler_bo,
-                                    BRW_USAGE_SAMPLER,
-                                    0,
-                                    i * sizeof(struct brw_sampler_state) +
-                                    offsetof(struct brw_sampler_state, ss2),
-                                    brw->wm.sdc_bo[i]);
-      if (ret)
-         return ret;
-   }
 
    return 0;
 }
diff --git a/src/gallium/drivers/i965/brw_wm_state.c b/src/gallium/drivers/i965/brw_wm_state.c
index 56789ce..d8e8823 100644
--- a/src/gallium/drivers/i965/brw_wm_state.c
+++ b/src/gallium/drivers/i965/brw_wm_state.c
@@ -144,8 +144,36 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
                         struct brw_winsys_buffer **bo_out)
 {
    struct brw_wm_unit_state wm;
+   struct brw_winsys_reloc reloc[3];
+   unsigned nr_reloc = 0;
    enum pipe_error ret;
 
+   /* Emit WM program relocation */
+   make_reloc(&reloc[nr_reloc++],
+              BRW_USAGE_STATE,
+              wm.thread0.grf_reg_count << 1,
+              offsetof(struct brw_wm_unit_state, thread0),
+              brw->wm.prog_bo);
+
+   /* Emit scratch space relocation */
+   if (key->total_scratch != 0) {
+      make_reloc(&reloc[nr_reloc++],
+                 BRW_USAGE_SCRATCH,
+                 wm.thread2.per_thread_scratch_space,
+                 offsetof(struct brw_wm_unit_state, thread2),
+                 brw->wm.scratch_bo);
+   }
+
+   /* Emit sampler state relocation */
+   if (key->sampler_count != 0) {
+      make_reloc(&reloc[nr_reloc++],
+                 BRW_USAGE_STATE,
+                 wm.wm4.stats_enable | (wm.wm4.sampler_count << 2),
+                 offsetof(struct brw_wm_unit_state, wm4),
+                 brw->wm.sampler_bo);
+   }
+
+
    memset(&wm, 0, sizeof(wm));
 
    wm.thread0.grf_reg_count = align(key->total_grf, 16) / 16 - 1;
@@ -220,44 +248,13 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
 
    ret = brw_upload_cache(&brw->cache, BRW_WM_UNIT,
                           key, sizeof(*key),
-                          reloc_bufs, 3,
+                          reloc, nr_reloc,
                           &wm, sizeof(wm),
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-   /* Emit WM program relocation */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_STATE,
-                                 wm.thread0.grf_reg_count << 1,
-                                 offsetof(struct brw_wm_unit_state, thread0),
-                                 brw->wm.prog_bo);
-   if (ret)
-      return ret;
-
-   /* Emit scratch space relocation */
-   if (key->total_scratch != 0) {
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_SCRATCH,
-                                    wm.thread2.per_thread_scratch_space,
-                                    offsetof(struct brw_wm_unit_state, thread2),
-                                    brw->wm.scratch_bo);
-      if (ret)
-         return ret;
-   }
-
-   /* Emit sampler state relocation */
-   if (key->sampler_count != 0) {
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_STATE,
-                                    wm.wm4.stats_enable | (wm.wm4.sampler_count << 2),
-                                    offsetof(struct brw_wm_unit_state, wm4),
-                                    brw->wm.sampler_bo);
-      if (ret)
-         return ret;
-   }
-
    return PIPE_OK;
 }
 
diff --git a/src/gallium/drivers/i965/brw_wm_surface_state.c b/src/gallium/drivers/i965/brw_wm_surface_state.c
index ed365b0..f882331 100644
--- a/src/gallium/drivers/i965/brw_wm_surface_state.c
+++ b/src/gallium/drivers/i965/brw_wm_surface_state.c
@@ -45,33 +45,32 @@ brw_update_texture_surface( struct brw_context *brw,
 			    struct brw_texture *tex,
                             struct brw_winsys_buffer **bo_out)
 {
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
+   /* Emit relocation to surface contents */
+   make_reloc(&reloc[0],
+              BRW_USAGE_SAMPLER,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              tex->bo);
+
    if (brw_search_cache(&brw->surface_cache,
                         BRW_SS_SURFACE,
                         &tex->ss, sizeof tex->ss,
-                        &tex->bo, 1,
+                        reloc, Elements(reloc),
                         NULL,
                         bo_out))
       return PIPE_OK;
 
    ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
                           &tex->ss, sizeof tex->ss,
-                          &tex->bo, 1,
+                          reloc, Elements(reloc),
                           &tex->ss, sizeof tex->ss,
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
-      
-   /* Emit relocation to surface contents */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_SAMPLER,
-                                 0,
-                                 offsetof(struct brw_surface_state, ss1),
-                                 tex->bo);
-   if (ret)
-      return ret;
 
    return PIPE_OK;
 }
@@ -95,8 +94,17 @@ brw_update_render_surface(struct brw_context *brw,
 {
    struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0;
    struct brw_surface_state ss;
+   struct brw_winsys_reloc reloc[1];
    enum pipe_error ret;
 
+   /* XXX: we will only be rendering to this surface:
+    */
+   make_reloc(&reloc[0],
+              BRW_USAGE_RENDER_TARGET,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              surface->bo);
+
    /* Surfaces are potentially shared between contexts, so can't
     * scribble the in-place ss0 value in the surface.
     */
@@ -111,7 +119,7 @@ brw_update_render_surface(struct brw_context *brw,
    if (brw_search_cache(&brw->surface_cache,
                         BRW_SS_SURFACE,
                         &ss, sizeof(ss),
-                        &surface->bo, 1,
+                        reloc, Elements(reloc),
                         NULL,
                         bo_out))
       return PIPE_OK;
@@ -119,23 +127,13 @@ brw_update_render_surface(struct brw_context *brw,
    ret = brw_upload_cache(&brw->surface_cache,
                           BRW_SS_SURFACE,
                           &ss, sizeof ss,
-                          &surface->bo, 1,
+                          reloc, Elements(reloc),
                           &ss, sizeof ss,
                           NULL, NULL,
                           bo_out);
    if (ret)
       return ret;
 
-      /* XXX: we will only be rendering to this surface:
-       */
-   ret = brw->sws->bo_emit_reloc(*bo_out,
-                                 BRW_USAGE_RENDER_TARGET,
-                                 0,
-                                 offsetof(struct brw_surface_state, ss1),
-                                 surface->bo);
-   if (ret)
-      return ret;
-
    return PIPE_OK;
 }
 
@@ -149,6 +147,7 @@ brw_wm_get_binding_table(struct brw_context *brw,
                          struct brw_winsys_buffer **bo_out )
 {
    enum pipe_error ret;
+   struct brw_winsys_reloc reloc[BRW_WM_MAX_SURF];
    uint32_t data[BRW_WM_MAX_SURF];
    GLuint data_size = brw->wm.nr_surfaces * sizeof data[0];
    int i;
@@ -156,13 +155,21 @@ brw_wm_get_binding_table(struct brw_context *brw,
    assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
    assert(brw->wm.nr_surfaces > 0);
 
+   /* Emit binding table relocations to surface state */
+   for (i = 0; i < brw->wm.nr_surfaces; i++) {
+      make_reloc(&reloc[i],
+                 BRW_USAGE_STATE,
+                 0,
+                 i * sizeof(GLuint),
+                 brw->wm.surf_bo[i]);
+   }
+
    /* Note there is no key for this search beyond the values in the
     * relocation array:
     */
    if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
                         NULL, 0,
-                        brw->wm.surf_bo,
-                        brw->wm.nr_surfaces,
+                        reloc, brw->wm.nr_surfaces,
                         NULL,
                         bo_out))
       return PIPE_OK;
@@ -175,24 +182,13 @@ brw_wm_get_binding_table(struct brw_context *brw,
 
    ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
                            NULL, 0,
-                           brw->wm.surf_bo, brw->wm.nr_surfaces,
+                           reloc, brw->wm.nr_surfaces,
                            data, data_size,
                            NULL, NULL,
                            bo_out);
    if (ret)
       return ret;
 
-   /* Emit binding table relocations to surface state */
-   for (i = 0; i < brw->wm.nr_surfaces; i++) {
-      ret = brw->sws->bo_emit_reloc(*bo_out,
-                                    BRW_USAGE_STATE,
-                                    0,
-                                    i * sizeof(GLuint),
-                                    brw->wm.surf_bo[i]);
-      if (ret)
-         return ret;
-   }
-
    return PIPE_OK;
 }
 
diff --git a/src/gallium/winsys/drm/i965/xlib/xlib_i965.c b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c
index ab5df56..ce6d859 100644
--- a/src/gallium/winsys/drm/i965/xlib/xlib_i965.c
+++ b/src/gallium/winsys/drm/i965/xlib/xlib_i965.c
@@ -47,6 +47,10 @@
 
 #define MAX_VRAM (128*1024*1024)
 
+#define MAX_DUMPS 128
+
+
+
 extern int brw_disasm (FILE *file, 
                        const struct brw_instruction *inst,
                        unsigned count );
@@ -294,21 +298,36 @@ xlib_brw_bo_subdata(struct brw_winsys_buffer *buffer,
                     enum brw_buffer_data_type data_type,
                     size_t offset,
                     size_t size,
-                    const void *data)
+                    const void *data,
+                    const struct brw_winsys_reloc *reloc,
+                    unsigned nr_relocs)
 {
    struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
    struct xlib_brw_winsys *xbw = xlib_brw_winsys(buffer->sws);
+   unsigned i;
 
-   debug_printf("%s buf %p off %d sz %d %s\n", 
+   debug_printf("%s buf %p off %d sz %d %s relocs: %d\n", 
                 __FUNCTION__, 
-                (void *)buffer, offset, size, data_types[data_type]);
-
-   if (1)
-      dump_data( xbw, data_type, data, size );
+                (void *)buffer, offset, size, 
+                data_types[data_type],
+                nr_relocs);
 
    assert(buf->base.size >= offset + size);
    memcpy(buf->virtual + offset, data, size);
 
+   /* Apply the relocations:
+    */
+   for (i = 0; i < nr_relocs; i++) {
+      debug_printf("\treloc[%d] usage %s off %d value %x+%x\n", 
+                   i, usages[reloc[i].usage], reloc[i].offset,
+                   xlib_brw_buffer(reloc[i].bo)->offset, reloc[i].delta);
+
+      *(unsigned *)(buf->virtual + offset + reloc[i].offset) = 
+         xlib_brw_buffer(reloc[i].bo)->offset + reloc[i].delta;
+   }
+
+   if (1)
+      dump_data( xbw, data_type, buf->virtual + offset, size );
 
    return 0;
 }




More information about the mesa-commit mailing list