i965g: add lots of error checks and early returns
authorKeith Whitwell <keithw@vmware.com>
Thu, 5 Nov 2009 13:57:05 +0000 (13:57 +0000)
committerKeith Whitwell <keithw@vmware.com>
Thu, 5 Nov 2009 14:01:37 +0000 (14:01 +0000)
Any allocation that may fail should be checked, and propogate the
error upwards.  At the highest level we will flush batch and retry.

This is an alternate strategy to what the original DRI driver did of
attempting to flush batch from the lowest levels (eg inside
BEGIN_BATCH).  The trouble with that strategy was that flushes could
occur at unexpected times, and additionally there was a need for a
wierd notification mechanism to propogate the 'lost context' state
back up to higher levels.

Propogating the errors directly gives us a lot of flexibility how to
deal with these states, at the expense of a lot more checking in the
code.

Will add some sanity checks later to make sure that out-of-memory
conditions are properly escalated and not lost halfway up the stack.

35 files changed:
src/gallium/drivers/i965/brw_batchbuffer.c
src/gallium/drivers/i965/brw_batchbuffer.h
src/gallium/drivers/i965/brw_cc.c
src/gallium/drivers/i965/brw_clip.c
src/gallium/drivers/i965/brw_clip_state.c
src/gallium/drivers/i965/brw_context.c
src/gallium/drivers/i965/brw_context.h
src/gallium/drivers/i965/brw_curbe.c
src/gallium/drivers/i965/brw_draw.c
src/gallium/drivers/i965/brw_draw_upload.c
src/gallium/drivers/i965/brw_eu.c
src/gallium/drivers/i965/brw_eu.h
src/gallium/drivers/i965/brw_gs.c
src/gallium/drivers/i965/brw_gs_state.c
src/gallium/drivers/i965/brw_pipe_query.c
src/gallium/drivers/i965/brw_pipe_shader.c
src/gallium/drivers/i965/brw_pipe_vertex.c
src/gallium/drivers/i965/brw_screen_buffers.c
src/gallium/drivers/i965/brw_screen_surface.c
src/gallium/drivers/i965/brw_screen_texture.c
src/gallium/drivers/i965/brw_sf.c
src/gallium/drivers/i965/brw_sf_state.c
src/gallium/drivers/i965/brw_state.h
src/gallium/drivers/i965/brw_state_cache.c
src/gallium/drivers/i965/brw_state_upload.c
src/gallium/drivers/i965/brw_vs.c
src/gallium/drivers/i965/brw_vs_state.c
src/gallium/drivers/i965/brw_vs_surface_state.c
src/gallium/drivers/i965/brw_winsys.h
src/gallium/drivers/i965/brw_wm.c
src/gallium/drivers/i965/brw_wm_constant_buffer.c
src/gallium/drivers/i965/brw_wm_sampler_state.c
src/gallium/drivers/i965/brw_wm_state.c
src/gallium/drivers/i965/brw_wm_surface_state.c
src/gallium/winsys/drm/i965/xlib/xlib_i965.c

index ca612e5ed0b86a7659471f017024c17fd8302135..e5f73bd6a318e97c00ecbb2acd64c8651d1b4ecb 100644 (file)
 #define USE_MALLOC_BUFFER 1
 #define ALWAYS_EMIT_MI_FLUSH 1
 
-void
+enum pipe_error
 brw_batchbuffer_reset(struct brw_batchbuffer *batch)
 {
-   if (batch->buf) {
-      batch->sws->bo_unreference(batch->buf);
-      batch->buf = NULL;
-   }
+   enum pipe_error ret;
 
-   batch->buf = batch->sws->bo_alloc(batch->sws,
-                                    BRW_BUFFER_TYPE_BATCH,
-                                    BRW_BATCH_SIZE, 4096);
+   ret = batch->sws->bo_alloc( batch->sws,
+                               BRW_BUFFER_TYPE_BATCH,
+                               BRW_BATCH_SIZE, 4096,
+                               &batch->buf );
+   if (ret)
+      return ret;
 
    if (batch->malloc_buffer)
       batch->map = batch->malloc_buffer;
@@ -59,6 +59,7 @@ brw_batchbuffer_reset(struct brw_batchbuffer *batch)
 
    batch->size = BRW_BATCH_SIZE;
    batch->ptr = batch->map;
+   return PIPE_OK;
 }
 
 struct brw_batchbuffer *
@@ -91,7 +92,7 @@ brw_batchbuffer_free(struct brw_batchbuffer *batch)
       batch->map = NULL;
    }
 
-   batch->sws->bo_unreference(batch->buf);
+   bo_reference(&batch->buf, NULL);
    FREE(batch);
 }
 
index 1f04826aea687f5568a2fc4f175533cb415682fb..288a9d275556b59144bfada8d2d8264a40c7629d 100644 (file)
@@ -65,7 +65,8 @@ void _brw_batchbuffer_flush(struct brw_batchbuffer *batch,
                              const char *file, int line);
 
 
-void brw_batchbuffer_reset(struct brw_batchbuffer *batch);
+enum pipe_error
+brw_batchbuffer_reset(struct brw_batchbuffer *batch);
 
 
 /* Unlike bmBufferData, this currently requires the buffer be mapped.
index 20967f01911cb6c2c877d9e0b0ce3b1f09f65d8a..8e25fe85854ba10126cc1210de2adf0c8d3612a6 100644 (file)
@@ -57,10 +57,11 @@ static void calc_sane_viewport( const struct pipe_viewport_state *vp,
    svp->far = 1;
 }
 
-static int prepare_cc_vp( struct brw_context *brw )
+static enum pipe_error prepare_cc_vp( struct brw_context *brw )
 {
    struct brw_cc_viewport ccv;
    struct sane_viewport svp;
+   enum pipe_error ret;
 
    memset(&ccv, 0, sizeof(ccv));
 
@@ -70,10 +71,12 @@ static int prepare_cc_vp( struct brw_context *brw )
    ccv.min_depth = svp.near;
    ccv.max_depth = svp.far;
 
-   brw->sws->bo_unreference(brw->cc.vp_bo);
-   brw->cc.vp_bo = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0 );
-
-   return 0;
+   ret = brw_cache_data( &brw->cache, BRW_CC_VP, &ccv, NULL, 0,
+                         &brw->cc.vp_bo );
+   if (ret)
+      return ret;
+                
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_cc_vp = {
@@ -123,11 +126,13 @@ cc_unit_populate_key(const struct brw_context *brw,
 /**
  * Creates the state cache entry for the given CC unit key.
  */
-static struct brw_winsys_buffer *
-cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key)
+static enum pipe_error
+cc_unit_create_from_key(struct brw_context *brw, 
+                        struct brw_cc_unit_key *key,
+                        struct brw_winsys_buffer **bo_out)
 {
    struct brw_cc_unit_state cc;
-   struct brw_winsys_buffer *bo;
+   enum pipe_error ret;
 
    memset(&cc, 0, sizeof(cc));
 
@@ -143,38 +148,48 @@ cc_unit_create_from_key(struct brw_context *brw, struct brw_cc_unit_key *key)
    cc.cc6 = key->cc6;
    cc.cc7 = key->cc7;
 
-   bo = brw_upload_cache(&brw->cache, BRW_CC_UNIT,
-                        key, sizeof(*key),
-                        &brw->cc.vp_bo, 1,
-                        &cc, sizeof(cc),
-                        NULL, NULL);
+   ret = brw_upload_cache(&brw->cache, BRW_CC_UNIT,
+                          key, sizeof(*key),
+                          &brw->cc.vp_bo, 1,
+                          &cc, sizeof(cc),
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
 
-   /* Emit CC viewport relocation */
-   brw->sws->bo_emit_reloc(bo,
-                          BRW_USAGE_STATE,
-                          0,
-                          offsetof(struct brw_cc_unit_state, cc4),
-                          brw->cc.vp_bo);
 
-   return bo;
+   /* 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;
+   enum pipe_error ret;
 
    cc_unit_populate_key(brw, &key);
 
-   brw->sws->bo_unreference(brw->cc.state_bo);
-   brw->cc.state_bo = brw_search_cache(&brw->cache, BRW_CC_UNIT,
-                                      &key, sizeof(key),
-                                      &brw->cc.vp_bo, 1,
-                                      NULL);
-
-   if (brw->cc.state_bo == NULL)
-      brw->cc.state_bo = cc_unit_create_from_key(brw, &key);
+   if (brw_search_cache(&brw->cache, BRW_CC_UNIT,
+                        &key, sizeof(key),
+                        &brw->cc.vp_bo, 1,
+                        NULL,
+                        &brw->cc.state_bo))
+      return PIPE_OK;
+
+   ret = cc_unit_create_from_key(brw, &key, 
+                                 &brw->cc.state_bo);
+   if (ret)
+      return ret;
    
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_cc_unit = {
index 1a52fa771bf5c608b6c7b1088c990c5b12d3d339..35e1d2fdbd033b982db34a5008493032bf0ba013 100644 (file)
 #define BACK_UNFILLED_BIT   0x2
 
 
-static void compile_clip_prog( struct brw_context *brw,
-                            struct brw_clip_prog_key *key )
+static enum pipe_error
+compile_clip_prog( struct brw_context *brw,
+                   struct brw_clip_prog_key *key,
+                   struct brw_winsys_buffer **bo_out )
 {
+   enum pipe_error ret;
    struct brw_clip_compile c;
    const GLuint *program;
    GLuint program_size;
@@ -123,31 +126,39 @@ static void compile_clip_prog( struct brw_context *brw,
       break;
    default:
       assert(0);
-      return;
+      return PIPE_ERROR_BAD_INPUT;
    }
 
         
 
    /* get the program
     */
-   program = brw_get_program(&c.func, &program_size);
+   ret = brw_get_program(&c.func, &program, &program_size);
+   if (ret)
+      return ret;
 
    /* Upload
     */
-   brw->sws->bo_unreference(brw->clip.prog_bo);
-   brw->clip.prog_bo = brw_upload_cache( &brw->cache,
-                                        BRW_CLIP_PROG,
-                                        &c.key, sizeof(c.key),
-                                        NULL, 0,
-                                        program, program_size,
-                                        &c.prog_data,
-                                        &brw->clip.prog_data );
+   ret = brw_upload_cache( &brw->cache,
+                           BRW_CLIP_PROG,
+                           &c.key, sizeof(c.key),
+                           NULL, 0,
+                           program, program_size,
+                           &c.prog_data,
+                           &brw->clip.prog_data,
+                           bo_out );
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 /* Calculate interpolants for triangle and line rasterization.
  */
-static int upload_clip_prog(struct brw_context *brw)
+static enum pipe_error
+upload_clip_prog(struct brw_context *brw)
 {
+   enum pipe_error ret;
    struct brw_clip_prog_key key;
 
    /* Populate the key, starting from the almost-complete version from
@@ -166,15 +177,22 @@ static int upload_clip_prog(struct brw_context *brw)
    /* PIPE_NEW_CLIP */
    key.nr_userclip = brw->curr.ucp.nr;
 
-   brw->sws->bo_unreference(brw->clip.prog_bo);
-   brw->clip.prog_bo = brw_search_cache(&brw->cache, BRW_CLIP_PROG,
-                                       &key, sizeof(key),
-                                       NULL, 0,
-                                       &brw->clip.prog_data);
-   if (brw->clip.prog_bo == NULL)
-      compile_clip_prog( brw, &key );
+   /* Already cached?
+    */
+   if (brw_search_cache(&brw->cache, BRW_CLIP_PROG,
+                        &key, sizeof(key),
+                        NULL, 0,
+                        &brw->clip.prog_data,
+                        &brw->clip.prog_bo))
+      return PIPE_OK;
+
+   /* Compile new program:
+    */
+   ret = compile_clip_prog( brw, &key, &brw->clip.prog_bo );
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 
index 6f8309fea925e0260b2393543cb46341505b2104..d4e3c43c61a371b431e14476ad4dddb73abf16d2 100644 (file)
@@ -72,12 +72,13 @@ clip_unit_populate_key(struct brw_context *brw, struct brw_clip_unit_key *key)
    key->depth_clamp = 0; // XXX: add this to gallium: ctx->Transform.DepthClamp;
 }
 
-static struct brw_winsys_buffer *
+static enum pipe_error
 clip_unit_create_from_key(struct brw_context *brw,
-                         struct brw_clip_unit_key *key)
+                          struct brw_clip_unit_key *key,
+                          struct brw_winsys_buffer **bo_out)
 {
    struct brw_clip_unit_state clip;
-   struct brw_winsys_buffer *bo;
+   enum pipe_error ret;
 
    memset(&clip, 0, sizeof(clip));
 
@@ -141,39 +142,50 @@ clip_unit_create_from_key(struct brw_context *brw,
    clip.viewport_ymin = -1;
    clip.viewport_ymax = 1;
 
-   bo = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT,
-                        key, sizeof(*key),
-                        &brw->clip.prog_bo, 1,
-                        &clip, sizeof(clip),
-                        NULL, NULL);
+   ret = brw_upload_cache(&brw->cache, BRW_CLIP_UNIT,
+                          key, sizeof(*key),
+                          &brw->clip.prog_bo, 1,
+                          &clip, sizeof(clip),
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
 
    /* Emit clip program relocation */
    assert(brw->clip.prog_bo);
-   brw->sws->bo_emit_reloc(bo,
-                          BRW_USAGE_STATE,
-                          clip.thread0.grf_reg_count << 1,
-                          offsetof(struct brw_clip_unit_state, thread0),
-                          brw->clip.prog_bo);
-
-   return 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;
+   enum pipe_error ret;
 
    clip_unit_populate_key(brw, &key);
 
-   brw->sws->bo_unreference(brw->clip.state_bo);
-   brw->clip.state_bo = brw_search_cache(&brw->cache, BRW_CLIP_UNIT,
-                                        &key, sizeof(key),
-                                        &brw->clip.prog_bo, 1,
-                                        NULL);
-   if (brw->clip.state_bo == NULL) {
-      brw->clip.state_bo = clip_unit_create_from_key(brw, &key);
-   }
+   if (brw_search_cache(&brw->cache, BRW_CLIP_UNIT,
+                        &key, sizeof(key),
+                        &brw->clip.prog_bo, 1,
+                        NULL,
+                        &brw->clip.state_bo))
+      return PIPE_OK;
+      
+   /* Create new:
+    */
+   ret = clip_unit_create_from_key(brw, &key, 
+                                   &brw->clip.state_bo);
+   if (ret)
+      return ret;
    
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_clip_unit = {
index aaf7d1834ea1423efaa89574438af16981b465c0..2cee7a7a3cf9f3a6aac2f8a55f11307ba0fcaec2 100644 (file)
@@ -72,29 +72,33 @@ static void brw_destroy_context( struct pipe_context *pipe )
    brw->curr.fb.nr_cbufs = 0;
    pipe_surface_reference(&brw->curr.fb.zsbuf, NULL);
 
-   brw->sws->bo_unreference(brw->curbe.curbe_bo);
-   brw->sws->bo_unreference(brw->vs.prog_bo);
-   brw->sws->bo_unreference(brw->vs.state_bo);
-   brw->sws->bo_unreference(brw->vs.bind_bo);
-   brw->sws->bo_unreference(brw->gs.prog_bo);
-   brw->sws->bo_unreference(brw->gs.state_bo);
-   brw->sws->bo_unreference(brw->clip.prog_bo);
-   brw->sws->bo_unreference(brw->clip.state_bo);
-   brw->sws->bo_unreference(brw->clip.vp_bo);
-   brw->sws->bo_unreference(brw->sf.prog_bo);
-   brw->sws->bo_unreference(brw->sf.state_bo);
-   brw->sws->bo_unreference(brw->sf.vp_bo);
+   bo_reference(&brw->curbe.curbe_bo, NULL);
+   bo_reference(&brw->vs.prog_bo, NULL);
+   bo_reference(&brw->vs.state_bo, NULL);
+   bo_reference(&brw->vs.bind_bo, NULL);
+   bo_reference(&brw->gs.prog_bo, NULL);
+   bo_reference(&brw->gs.state_bo, NULL);
+   bo_reference(&brw->clip.prog_bo, NULL);
+   bo_reference(&brw->clip.state_bo, NULL);
+   bo_reference(&brw->clip.vp_bo, NULL);
+   bo_reference(&brw->sf.prog_bo, NULL);
+   bo_reference(&brw->sf.state_bo, NULL);
+   bo_reference(&brw->sf.vp_bo, NULL);
+
    for (i = 0; i < BRW_MAX_TEX_UNIT; i++)
-      brw->sws->bo_unreference(brw->wm.sdc_bo[i]);
-   brw->sws->bo_unreference(brw->wm.bind_bo);
+      bo_reference(&brw->wm.sdc_bo[i], NULL);
+
+   bo_reference(&brw->wm.bind_bo, NULL);
+
    for (i = 0; i < BRW_WM_MAX_SURF; i++)
-      brw->sws->bo_unreference(brw->wm.surf_bo[i]);
-   brw->sws->bo_unreference(brw->wm.sampler_bo);
-   brw->sws->bo_unreference(brw->wm.prog_bo);
-   brw->sws->bo_unreference(brw->wm.state_bo);
-   brw->sws->bo_unreference(brw->cc.prog_bo);
-   brw->sws->bo_unreference(brw->cc.state_bo);
-   brw->sws->bo_unreference(brw->cc.vp_bo);
+      bo_reference(&brw->wm.surf_bo[i], NULL);
+
+   bo_reference(&brw->wm.sampler_bo, NULL);
+   bo_reference(&brw->wm.prog_bo, NULL);
+   bo_reference(&brw->wm.state_bo, NULL);
+   bo_reference(&brw->cc.prog_bo, NULL);
+   bo_reference(&brw->cc.state_bo, NULL);
+   bo_reference(&brw->cc.vp_bo, NULL);
 }
 
 
index 09d34615c745c679a32a1f487d6a502219d15f83..580251d2f12c4e1188e4997cff48d779cf0fd1b2 100644 (file)
@@ -744,7 +744,7 @@ struct brw_context
  * brw_queryobj.c
  */
 void brw_init_query(struct brw_context *brw);
-void brw_prepare_query_begin(struct brw_context *brw);
+enum pipe_error brw_prepare_query_begin(struct brw_context *brw);
 void brw_emit_query_begin(struct brw_context *brw);
 void brw_emit_query_end(struct brw_context *brw);
 
index 1e2e232204e73efbad34a9ebd86795e187d047f7..ca7774a7cc29006bcb7d870bb4536877f9701107 100644 (file)
@@ -160,10 +160,11 @@ static GLfloat fixed_plane[6][4] = {
  * cache mechanism, but maybe would benefit from a comparison against
  * the current uploaded set of constants.
  */
-static int prepare_curbe_buffer(struct brw_context *brw)
+static enum pipe_error prepare_curbe_buffer(struct brw_context *brw)
 {
    const GLuint sz = brw->curbe.total_size;
    const GLuint bufsz = sz * 16 * sizeof(GLfloat);
+   enum pipe_error ret;
    GLfloat *buf;
    GLuint i;
 
@@ -267,17 +268,20 @@ static int prepare_curbe_buffer(struct brw_context *brw)
          (brw->curbe.need_new_bo ||
           brw->curbe.curbe_next_offset + bufsz > brw->curbe.curbe_bo->size))
       {
-        brw->sws->bo_unreference(brw->curbe.curbe_bo);
-        brw->curbe.curbe_bo = NULL;
+        bo_reference(&brw->curbe.curbe_bo, NULL);
       }
 
       if (brw->curbe.curbe_bo == NULL) {
         /* Allocate a single page for CURBE entries for this batchbuffer.
          * They're generally around 64b.
          */
-        brw->curbe.curbe_bo = brw->sws->bo_alloc(brw->sws, 
-                                                 BRW_BUFFER_TYPE_CURBE,
-                                                 4096, 1 << 6);
+        ret = brw->sws->bo_alloc(brw->sws, 
+                                  BRW_BUFFER_TYPE_CURBE,
+                                  4096, 1 << 6,
+                                  &brw->curbe.curbe_bo);
+         if (ret)
+            return ret;
+
         brw->curbe.curbe_next_offset = 0;
       }
 
@@ -313,7 +317,7 @@ static int prepare_curbe_buffer(struct brw_context *brw)
    return 0;
 }
 
-static int emit_curbe_buffer(struct brw_context *brw)
+static enum pipe_error emit_curbe_buffer(struct brw_context *brw)
 {
    GLuint sz = brw->curbe.total_size;
 
index 6d6b1c7c5c3ef94a22ab108e15eebfd9282b1207..88cb31ad5460c9b1086f0065f52a0387d7f220a5 100644 (file)
@@ -280,6 +280,5 @@ void brw_draw_cleanup( struct brw_context *brw )
    u_upload_destroy( brw->vb.upload_vertex );
    u_upload_destroy( brw->vb.upload_index );
 
-   brw->sws->bo_unreference(brw->ib.bo);
-   brw->ib.bo = NULL;
+   bo_reference(&brw->ib.bo, NULL);
 }
index 4fa7d549ebd6d66a903a5e1f42054f0cf3ab4c22..188605a0c12217bd2a8857bbec861d514c0b5594 100644 (file)
@@ -251,9 +251,8 @@ static int brw_prepare_vertices(struct brw_context *brw)
       brw->vb.vb[i].vertex_count = (vb->stride == 0 ?
                                    1 :
                                    (bo->size - offset) / vb->stride);
-      brw->sws->bo_unreference(brw->vb.vb[i].bo);
-      brw->vb.vb[i].bo = bo;
-      brw->sws->bo_reference(brw->vb.vb[i].bo);
+
+      bo_reference( &brw->vb.vb[i].bo,  bo );
 
       /* Don't need to retain this reference.  We have a reference on
        * the underlying winsys buffer:
@@ -417,6 +416,7 @@ const struct brw_tracked_state brw_vertices = {
 static int brw_prepare_indices(struct brw_context *brw)
 {
    struct pipe_buffer *index_buffer = brw->curr.index_buffer;
+   struct pipe_buffer *upload_buf = NULL;
    struct brw_winsys_buffer *bo = NULL;
    GLuint offset;
    GLuint index_size;
@@ -438,7 +438,6 @@ static int brw_prepare_indices(struct brw_context *brw)
    /* Turn userbuffer into a proper hardware buffer?
     */
    if (brw_buffer_is_user_buffer(index_buffer)) {
-      struct pipe_buffer *upload_buf;
 
       ret = u_upload_buffer( brw->vb.upload_index,
                             0,
@@ -450,8 +449,6 @@ static int brw_prepare_indices(struct brw_context *brw)
         return ret;
 
       bo = brw_buffer(upload_buf)->bo;
-      brw->sws->bo_reference(bo);
-      pipe_buffer_reference( &upload_buf, NULL );
 
       /* XXX: annotate the userbuffer with the upload information so
        * that successive calls don't get re-uploaded.
@@ -459,8 +456,6 @@ static int brw_prepare_indices(struct brw_context *brw)
    }
    else {
       bo = brw_buffer(index_buffer)->bo;
-      brw->sws->bo_reference(bo);
-      
       ib_size = bo->size;
       offset = 0;
    }
@@ -486,15 +481,12 @@ static int brw_prepare_indices(struct brw_context *brw)
    if (brw->ib.bo != bo ||
        brw->ib.size != ib_size)
    {
-      brw->sws->bo_unreference(brw->ib.bo);
-      brw->ib.bo = bo;
+      bo_reference(&brw->ib.bo, bo);
       brw->ib.size = ib_size;
       brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;
    }
-   else {
-      brw->sws->bo_unreference(bo);
-   }
 
+   pipe_buffer_reference( &upload_buf, NULL );
    brw_add_validated_bo(brw, brw->ib.bo);
    return 0;
 }
index de43b14512d785bc59abbb148e3bfb75603a4601..a8fcb5f97eb511dbda564fc266e52195a285d28a 100644 (file)
@@ -118,16 +118,23 @@ void brw_init_compile( struct brw_context *brw, struct brw_compile *p )
 }
 
 
-const GLuint *brw_get_program( struct brw_compile *p,
-                              GLuint *sz )
+enum pipe_error brw_get_program( struct brw_compile *p,
+                                 const GLuint **data,
+                                 GLuint *sz )
 {
    GLuint i;
 
    for (i = 0; i < 8; i++)
       brw_NOP(p);
 
+   /* Is the generated program malformed for some reason?
+    */
+   if (p->error)
+      return PIPE_ERROR_BAD_INPUT;
+
    *sz = p->nr_insn * sizeof(struct brw_instruction);
-   return (const GLuint *)p->store;
+   *data = (const GLuint *)p->store;
+   return PIPE_OK;
 }
 
 
index 7bddc3859ca240a1b79dd7dde6f95460320c8d95..565f4ef1c59e9a12a8857b22ce980bf1c80beb01 100644 (file)
@@ -34,6 +34,7 @@
 #define BRW_EU_H
 
 #include "util/u_debug.h"
+#include "pipe/p_error.h"
 
 #include "brw_structs.h"
 #include "brw_defines.h"
@@ -132,6 +133,8 @@ struct brw_compile {
 
    struct brw_eu_label *first_label;  /**< linked list of labels */
    struct brw_eu_call *first_call;    /**< linked list of CALs */
+
+   boolean error;
 };
 
 
@@ -772,7 +775,10 @@ void brw_set_predicate_control( struct brw_compile *p, GLuint pc );
 void brw_set_conditionalmod( struct brw_compile *p, GLuint conditional );
 
 void brw_init_compile( struct brw_context *, struct brw_compile *p );
-const GLuint *brw_get_program( struct brw_compile *p, GLuint *sz );
+
+enum pipe_error brw_get_program( struct brw_compile *p, 
+                                 const GLuint **program,
+                                 GLuint *sz );
 
 
 /* Helpers for regular instructions:
index 693d8bfdf8dd7254444e766c907f99b89e501f7c..ce77be24f608a7454019823e0de2b0b5aca34a48 100644 (file)
 
 
 
-static void compile_gs_prog( struct brw_context *brw,
-                            struct brw_gs_prog_key *key )
+static enum pipe_error compile_gs_prog( struct brw_context *brw,
+                                        struct brw_gs_prog_key *key,
+                                        struct brw_winsys_buffer **bo_out )
 {
    struct brw_gs_compile c;
+   enum pipe_error ret;
    const GLuint *program;
    GLuint program_size;
 
@@ -57,9 +59,9 @@ static void compile_gs_prog( struct brw_context *brw,
    c.nr_attrs = c.key.nr_attrs;
 
    if (BRW_IS_IGDNG(brw))
-       c.nr_regs = (c.nr_attrs + 1) / 2 + 3;  /* are vertices packed, or reg-aligned? */
+      c.nr_regs = (c.nr_attrs + 1) / 2 + 3;  /* are vertices packed, or reg-aligned? */
    else
-       c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
+      c.nr_regs = (c.nr_attrs + 1) / 2 + 1;  /* are vertices packed, or reg-aligned? */
 
    c.nr_bytes = c.nr_regs * REG_SIZE;
 
@@ -93,40 +95,47 @@ static void compile_gs_prog( struct brw_context *brw,
       if (key->hint_gs_always)
         brw_gs_lines( &c );
       else {
-        return;
+        return PIPE_OK;
       }
       break;
    case PIPE_PRIM_TRIANGLES:
       if (key->hint_gs_always)
         brw_gs_tris( &c );
       else {
-        return;
+        return PIPE_OK;
       }
       break;
    case PIPE_PRIM_POINTS:
       if (key->hint_gs_always)
         brw_gs_points( &c );
       else {
-        return;
+        return PIPE_OK;
       }
-      break;      
+      break;
    default:
-      return;
+      assert(0);
+      return PIPE_ERROR_BAD_INPUT;
    }
 
    /* get the program
     */
-   program = brw_get_program(&c.func, &program_size);
+   ret = brw_get_program(&c.func, &program, &program_size);
+   if (ret)
+      return ret;
 
    /* Upload
     */
-   brw->sws->bo_unreference(brw->gs.prog_bo);
-   brw->gs.prog_bo = brw_upload_cache( &brw->cache, BRW_GS_PROG,
-                                      &c.key, sizeof(c.key),
-                                      NULL, 0,
-                                      program, program_size,
-                                      &c.prog_data,
-                                      &brw->gs.prog_data );
+   ret = brw_upload_cache( &brw->cache, BRW_GS_PROG,
+                           &c.key, sizeof(c.key),
+                           NULL, 0,
+                           program, program_size,
+                           &c.prog_data,
+                           &brw->gs.prog_data,
+                           bo_out );
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 static const unsigned gs_prim[PIPE_PRIM_MAX] = {  
@@ -166,6 +175,8 @@ static void populate_key( struct brw_context *brw,
 static int prepare_gs_prog(struct brw_context *brw)
 {
    struct brw_gs_prog_key key;
+   enum pipe_error ret;
+
    /* Populate the key:
     */
    populate_key(brw, &key);
@@ -175,17 +186,21 @@ static int prepare_gs_prog(struct brw_context *brw)
       brw->gs.prog_active = key.need_gs_prog;
    }
 
-   if (brw->gs.prog_active) {
-      brw->sws->bo_unreference(brw->gs.prog_bo);
-      brw->gs.prog_bo = brw_search_cache(&brw->cache, BRW_GS_PROG,
-                                        &key, sizeof(key),
-                                        NULL, 0,
-                                        &brw->gs.prog_data);
-      if (brw->gs.prog_bo == NULL)
-        compile_gs_prog( brw, &key );
-   }
+   if (!brw->gs.prog_active)
+      return PIPE_OK;
+
+   if (brw_search_cache(&brw->cache, BRW_GS_PROG,
+                        &key, sizeof(key),
+                        NULL, 0,
+                        &brw->gs.prog_data,
+                        &brw->gs.prog_bo))
+      return PIPE_OK;
+
+   ret = compile_gs_prog( brw, &key, &brw->gs.prog_bo );
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 
index f27f886a651b78b7ef1c9374050ce50fda39d46f..18a66da538ed89bdcb92d75ecb0adb556015828b 100644 (file)
@@ -69,11 +69,13 @@ gs_unit_populate_key(struct brw_context *brw, struct brw_gs_unit_key *key)
    key->urb_size = brw->urb.vsize;
 }
 
-static struct brw_winsys_buffer *
-gs_unit_create_from_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_buffer **bo_out)
 {
    struct brw_gs_unit_state gs;
-   struct brw_winsys_buffer *bo;
+   enum pipe_error ret;
 
    memset(&gs, 0, sizeof(gs));
 
@@ -104,40 +106,46 @@ gs_unit_create_from_key(struct brw_context *brw, struct brw_gs_unit_key *key)
    if (BRW_DEBUG & DEBUG_STATS)
       gs.thread4.stats_enable = 1;
 
-   bo = brw_upload_cache(&brw->cache, BRW_GS_UNIT,
-                        key, sizeof(*key),
-                        &brw->gs.prog_bo, 1,
-                        &gs, sizeof(gs),
-                        NULL, NULL);
+   ret = brw_upload_cache(&brw->cache, BRW_GS_UNIT,
+                          key, sizeof(*key),
+                          &brw->gs.prog_bo, 1,
+                          &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,
+      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 bo;
+   return PIPE_OK;
 }
 
-static int prepare_gs_unit(struct brw_context *brw)
+static enum pipe_error prepare_gs_unit(struct brw_context *brw)
 {
    struct brw_gs_unit_key key;
+   enum pipe_error ret;
 
    gs_unit_populate_key(brw, &key);
 
-   brw->sws->bo_unreference(brw->gs.state_bo);
-   brw->gs.state_bo = brw_search_cache(&brw->cache, BRW_GS_UNIT,
-                                      &key, sizeof(key),
-                                      &brw->gs.prog_bo, 1,
-                                      NULL);
-   if (brw->gs.state_bo == NULL) {
-      brw->gs.state_bo = gs_unit_create_from_key(brw, &key);
-   }
+   if (brw_search_cache(&brw->cache, BRW_GS_UNIT,
+                        &key, sizeof(key),
+                        &brw->gs.prog_bo, 1,
+                        NULL,
+                        &brw->gs.state_bo))
+      return PIPE_OK;
+
+   ret = gs_unit_create_from_key(brw, &key, &brw->gs.state_bo);
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_gs_unit = {
index 3370ebd2626f5611c8c323a624286c5e9a6f27d5..6a0117378795e2eb1de8cc8051ae109e93f60c5b 100644 (file)
@@ -72,8 +72,7 @@ brw_query_get_result(struct pipe_context *pipe,
       }
 
       brw->sws->bo_unmap(query->bo);
-      brw->sws->bo_unreference(query->bo);
-      query->bo = NULL;
+      bo_reference(&query->bo, NULL);
    }
 
    *result = query->result;
@@ -100,10 +99,9 @@ brw_query_create(struct pipe_context *pipe, unsigned type )
 static void
 brw_query_destroy(struct pipe_context *pipe, struct pipe_query *q)
 {
-   struct brw_context *brw = brw_context(pipe);
    struct brw_query_object *query = (struct brw_query_object *)q;
 
-   brw->sws->bo_unreference(query->bo);
+   bo_reference(&query->bo, NULL);
    FREE(query);
 }
 
@@ -114,9 +112,8 @@ brw_query_begin(struct pipe_context *pipe, struct pipe_query *q)
    struct brw_query_object *query = (struct brw_query_object *)q;
 
    /* Reset our driver's tracking of query state. */
-   brw->sws->bo_unreference(query->bo);
+   bo_reference(&query->bo, NULL);
    query->result = 0;
-   query->bo = NULL;
    query->first_index = -1;
    query->last_index = -1;
 
@@ -139,8 +136,7 @@ brw_query_end(struct pipe_context *pipe, struct pipe_query *q)
       brw_emit_query_end(brw);
       brw_context_flush( brw );
 
-      brw->sws->bo_unreference(brw->query.bo);
-      brw->query.bo = NULL;
+      bo_reference(&brw->query.bo, NULL);
    }
 
    remove_from_list(query);
@@ -153,24 +149,30 @@ brw_query_end(struct pipe_context *pipe, struct pipe_query *q)
  */
 
 /** Called to set up the query BO and account for its aperture space */
-void
+enum pipe_error
 brw_prepare_query_begin(struct brw_context *brw)
 {
+   enum pipe_error ret;
+
    /* Skip if we're not doing any queries. */
    if (is_empty_list(&brw->query.active_head))
-      return;
+      return PIPE_OK;
 
    /* Get a new query BO if we're going to need it. */
    if (brw->query.bo == NULL ||
        brw->query.index * 2 + 1 >= 4096 / sizeof(uint64_t)) {
-      brw->sws->bo_unreference(brw->query.bo);
-      brw->query.bo = NULL;
 
-      brw->query.bo = brw->sws->bo_alloc(brw->sws, BRW_BUFFER_TYPE_QUERY, 4096, 1);
+      ret = brw->sws->bo_alloc(brw->sws, BRW_BUFFER_TYPE_QUERY, 4096, 1,
+                               &brw->query.bo);
+      if (ret)
+         return ret;
+
       brw->query.index = 0;
    }
 
    brw_add_validated_bo(brw, brw->query.bo);
+
+   return PIPE_OK;
 }
 
 /** Called just before primitive drawing to get a beginning PS_DEPTH_COUNT. */
@@ -213,8 +215,7 @@ brw_emit_query_begin(struct brw_context *brw)
                                  FALSE,
                                  &tmp );
 
-        brw->sws->bo_reference(brw->query.bo);
-        query->bo = brw->query.bo;
+        bo_reference( &query->bo, brw->query.bo );
         query->first_index = brw->query.index;
       }
       query->last_index = brw->query.index;
index 2833f2bce02a7b542f5852209e142f4b88f70424..662c43c3e5f2ab20d5f3c90de636a39c16e74cbd 100644 (file)
@@ -146,10 +146,9 @@ fail:
 
 static void brw_delete_fs_state( struct pipe_context *pipe, void *prog )
 {
-   struct brw_context *brw = brw_context(pipe);
    struct brw_fragment_shader *fs = (struct brw_fragment_shader *)prog;
 
-   brw->sws->bo_unreference(fs->const_buffer);
+   bo_reference(&fs->const_buffer, NULL);
    FREE( (void *)fs->tokens );
    FREE( fs );
 }
index 97e9a236883d76daa5cc24154696b1c4e37a2c93..73bba5b0881c7b75ffe03e047bfa9b44a98274a3 100644 (file)
@@ -56,7 +56,7 @@ brw_pipe_vertex_cleanup( struct brw_context *brw )
     */
 #if 0
    for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
-      brw->sws->bo_unreference(brw->vb.inputs[i].bo);
+      bo_reference(&brw->vb.inputs[i].bo, NULL);
       brw->vb.inputs[i].bo = NULL;
    }
 #endif
index ba54740225cd538710181d3f4d729e0b13a99ea1..7ae386ffb34a03b2098e049b7dfc4ce1fbbf47d8 100644 (file)
@@ -43,15 +43,11 @@ brw_buffer_unmap( struct pipe_screen *screen,
 static void
 brw_buffer_destroy( struct pipe_buffer *buffer )
 {
-   struct brw_screen *bscreen = brw_screen( buffer->screen );
-   struct brw_winsys_screen *sws = bscreen->sws;
    struct brw_buffer *buf = brw_buffer( buffer );
 
    assert(!p_atomic_read(&buffer->reference.count));
 
-   if (buf->bo)
-      sws->bo_unreference(buf->bo);
-   
+   bo_reference(&buf->bo, NULL);
    FREE(buf);
 }
 
@@ -66,6 +62,7 @@ brw_buffer_create(struct pipe_screen *screen,
    struct brw_winsys_screen *sws = bscreen->sws;
    struct brw_buffer *buf;
    unsigned buffer_type;
+   enum pipe_error ret;
    
    buf = CALLOC_STRUCT(brw_buffer);
    if (!buf)
@@ -101,10 +98,11 @@ brw_buffer_create(struct pipe_screen *screen,
       break;
    }
    
-   buf->bo = sws->bo_alloc( sws,
-                            buffer_type,
-                            size,
-                            alignment );
+   ret = sws->bo_alloc( sws, buffer_type,
+                        size, alignment,
+                        &buf->bo );
+   if (ret != PIPE_OK)
+      return NULL;
       
    return &buf->base; 
 }
index 1c408e9f2e5d37ae211057747c126e02d5a39be6..21a7382873ffce617e7614984c1a86d5965e2d44 100644 (file)
@@ -150,9 +150,7 @@ static struct brw_surface *create_in_place_view( struct brw_screen *brw_screen,
    surface->pitch = tex->pitch;
    surface->tiling = tex->tiling;
 
-   surface->bo = tex->bo;
-   brw_screen->sws->bo_reference(surface->bo);
-
+   bo_reference( &surface->bo, tex->bo );
    pipe_texture_reference( &surface->base.texture, &tex->base );
 
    surface->ss.ss0.surface_format = tex->ss.ss0.surface_format;
@@ -244,11 +242,10 @@ static struct pipe_surface *brw_get_tex_surface(struct pipe_screen *screen,
 static void brw_tex_surface_destroy( struct pipe_surface *surf )
 {
    struct brw_surface *surface = brw_surface(surf);
-   struct brw_screen *screen = brw_screen(surf->texture->screen);
 
    /* Unreference texture, shared buffer:
     */
-   screen->sws->bo_unreference(surface->bo);
+   bo_reference(&surface->bo, NULL);
    pipe_texture_reference( &surface->base.texture, NULL );
 
 
index ba6dc7dfdee2aacf0865a25339b27b3e5a768b80..355abf0b898d5b078d9491bc9a58f590873aa768 100644 (file)
@@ -187,6 +187,7 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen,
    struct brw_screen *bscreen = brw_screen(screen);
    struct brw_texture *tex;
    enum brw_buffer_type buffer_type;
+   enum pipe_error ret;
    
    tex = CALLOC_STRUCT(brw_texture);
    if (tex == NULL)
@@ -235,10 +236,13 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen,
       buffer_type = BRW_BUFFER_TYPE_TEXTURE;
    }
 
-   tex->bo = bscreen->sws->bo_alloc( bscreen->sws,
-                                     buffer_type,
-                                     tex->pitch * tex->total_height * tex->cpp,
-                                     64 );
+   ret = bscreen->sws->bo_alloc( bscreen->sws,
+                                 buffer_type,
+                                 tex->pitch * tex->total_height * tex->cpp,
+                                 64,
+                                 &tex->bo );
+   if (ret)
+      goto fail;
 
    tex->ss.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
    tex->ss.ss0.surface_type = translate_tex_target(tex->base.target);
@@ -289,7 +293,7 @@ static struct pipe_texture *brw_texture_create( struct pipe_screen *screen,
    return &tex->base;
 
 fail:
-   bscreen->sws->bo_unreference(tex->bo);
+   bo_reference(&tex->bo, NULL);
    FREE(tex);
    return NULL;
 }
@@ -306,7 +310,8 @@ static struct pipe_texture *brw_texture_blanket(struct pipe_screen *screen,
 
 static void brw_texture_destroy(struct pipe_texture *pt)
 {
-   //bscreen->sws->bo_unreference(tex->bo);
+   struct brw_texture *tex = brw_texture(pt);
+   bo_reference(&tex->bo, NULL);
    FREE(pt);
 }
 
index 013d839e37dd2c7e126ec8a0064073863ee1370d..24d1015bbd507300916407acc2a17157fdc49896 100644 (file)
 #include "brw_sf.h"
 #include "brw_state.h"
 
-static void compile_sf_prog( struct brw_context *brw,
-                            struct brw_sf_prog_key *key )
+static enum pipe_error compile_sf_prog( struct brw_context *brw,
+                                        struct brw_sf_prog_key *key,
+                                        struct brw_winsys_buffer **bo_out )
 {
+   enum pipe_error ret;
    struct brw_sf_compile c;
    const GLuint *program;
    GLuint program_size;
@@ -87,28 +89,35 @@ static void compile_sf_prog( struct brw_context *brw,
       break;
    default:
       assert(0);
-      return;
+      return PIPE_ERROR_BAD_INPUT;
    }
 
    /* get the program
     */
-   program = brw_get_program(&c.func, &program_size);
+   ret = brw_get_program(&c.func, &program, &program_size);
+   if (ret)
+      return ret;
 
    /* Upload
     */
-   brw->sws->bo_unreference(brw->sf.prog_bo);
-   brw->sf.prog_bo = brw_upload_cache( &brw->cache, BRW_SF_PROG,
-                                      &c.key, sizeof(c.key),
-                                      NULL, 0,
-                                      program, program_size,
-                                      &c.prog_data,
-                                      &brw->sf.prog_data );
+   ret = brw_upload_cache( &brw->cache, BRW_SF_PROG,
+                           &c.key, sizeof(c.key),
+                           NULL, 0,
+                           program, program_size,
+                           &c.prog_data,
+                           &brw->sf.prog_data,
+                           bo_out);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 /* Calculate interpolants for triangle and line rasterization.
  */
-static int upload_sf_prog(struct brw_context *brw)
+static enum pipe_error upload_sf_prog(struct brw_context *brw)
 {
+   enum pipe_error ret;
    struct brw_sf_prog_key key;
 
    memset(&key, 0, sizeof(key));
@@ -161,15 +170,18 @@ static int upload_sf_prog(struct brw_context *brw)
                           PIPE_WINDING_CCW);
    }
 
-   brw->sws->bo_unreference(brw->sf.prog_bo);
-   brw->sf.prog_bo = brw_search_cache(&brw->cache, BRW_SF_PROG,
-                                     &key, sizeof(key),
-                                     NULL, 0,
-                                     &brw->sf.prog_data);
-   if (brw->sf.prog_bo == NULL)
-      compile_sf_prog( brw, &key );
+   if (brw_search_cache(&brw->cache, BRW_SF_PROG,
+                        &key, sizeof(key),
+                        NULL, 0,
+                        &brw->sf.prog_data,
+                        &brw->sf.prog_bo))
+      return PIPE_OK;
 
-   return 0;
+   ret = compile_sf_prog( brw, &key, &brw->sf.prog_bo );
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
index 31343ff24597abff7c7ee76597a52fa73d297e3e..f030f26c19f37746e1928db87505479be3381ab6 100644 (file)
 #include "brw_debug.h"
 #include "brw_pipe_rast.h"
 
-static int upload_sf_vp(struct brw_context *brw)
+static enum pipe_error upload_sf_vp(struct brw_context *brw)
 {
    const struct pipe_viewport_state *vp = &brw->curr.vp;
    const struct pipe_scissor_state *scissor = &brw->curr.scissor;
    struct brw_sf_viewport sfv;
+   enum pipe_error ret;
 
    memset(&sfv, 0, sizeof(sfv));
 
@@ -61,10 +62,12 @@ static int upload_sf_vp(struct brw_context *brw)
    sfv.scissor.ymin = scissor->miny;
    sfv.scissor.ymax = scissor->maxy; /* -1 ?? */
 
-   brw->sws->bo_unreference(brw->sf.vp_bo);
-   brw->sf.vp_bo = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0 );
+   ret = brw_cache_data( &brw->cache, BRW_SF_VP, &sfv, NULL, 0,
+                         &brw->sf.vp_bo );
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_sf_vp = {
@@ -128,12 +131,13 @@ sf_unit_populate_key(struct brw_context *brw, struct brw_sf_unit_key *key)
                           rast->point_size_max);
 }
 
-static struct brw_winsys_buffer *
+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)
+                       struct brw_winsys_buffer **reloc_bufs,
+                        struct brw_winsys_buffer **bo_out)
 {
    struct brw_sf_unit_state sf;
-   struct brw_winsys_buffer *bo;
+   enum pipe_error ret;
    int chipset_max_threads;
    memset(&sf, 0, sizeof(sf));
 
@@ -273,51 +277,65 @@ sf_unit_create_from_key(struct brw_context *brw, struct brw_sf_unit_key *key,
       sf.sf6.dest_org_hbias = 0x0;
    }
 
-   bo = brw_upload_cache(&brw->cache, BRW_SF_UNIT,
-                        key, sizeof(*key),
-                        reloc_bufs, 2,
-                        &sf, sizeof(sf),
-                        NULL, NULL);
+   ret = brw_upload_cache(&brw->cache, BRW_SF_UNIT,
+                          key, sizeof(*key),
+                          reloc_bufs, 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 */
-   brw->sws->bo_emit_reloc(bo,
-                          BRW_USAGE_STATE,
-                          sf.thread0.grf_reg_count << 1,
-                          offsetof(struct brw_sf_unit_state, thread0),
-                          brw->sf.prog_bo);
+   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 */
-   brw->sws->bo_emit_reloc(bo,
-                          BRW_USAGE_STATE,
-                          sf.sf5.front_winding | (sf.sf5.viewport_transform << 1),
-                          offsetof(struct brw_sf_unit_state, sf5),
-                          brw->sf.vp_bo);
 
-   return bo;
+   /* 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;
 }
 
-static int upload_sf_unit( struct brw_context *brw )
+static enum pipe_error upload_sf_unit( struct brw_context *brw )
 {
    struct brw_sf_unit_key key;
    struct brw_winsys_buffer *reloc_bufs[2];
+   enum pipe_error ret;
 
    sf_unit_populate_key(brw, &key);
 
    reloc_bufs[0] = brw->sf.prog_bo;
    reloc_bufs[1] = brw->sf.vp_bo;
 
-   brw->sws->bo_unreference(brw->sf.state_bo);
-   brw->sf.state_bo = brw_search_cache(&brw->cache, BRW_SF_UNIT,
-                                      &key, sizeof(key),
-                                      reloc_bufs, 2,
-                                      NULL);
-   if (brw->sf.state_bo == NULL) {
-      brw->sf.state_bo = sf_unit_create_from_key(brw, &key, reloc_bufs);
-   }
-   return 0;
+   if (brw_search_cache(&brw->cache, BRW_SF_UNIT,
+                        &key, sizeof(key),
+                        reloc_bufs, 2,
+                        NULL,
+                        &brw->sf.state_bo))
+      return PIPE_OK;
+
+
+   ret = sf_unit_create_from_key(brw, &key, reloc_bufs,
+                                 &brw->sf.state_bo);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_sf_unit = {
index 94d2cb6f829f9a52a40130a33afca1aaf7686283..e219a1d87014968402617b4229b80e16f0070fbd 100644 (file)
@@ -44,8 +44,8 @@ brw_add_validated_bo(struct brw_context *brw, struct brw_winsys_buffer *bo)
    assert(brw->state.validated_bo_count < Elements(brw->state.validated_bos));
 
    if (bo != NULL) {
-      brw->sws->bo_reference(bo);
-      brw->state.validated_bos[brw->state.validated_bo_count++] = bo;
+      bo_reference( &brw->state.validated_bos[brw->state.validated_bo_count++],
+                    bo );
    }
 }
 
@@ -106,37 +106,42 @@ void brw_destroy_state(struct brw_context *brw);
 /***********************************************************************
  * brw_state_cache.c
  */
-struct brw_winsys_buffer *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_buffer *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_buffer *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,
-                         const void *data,
-                         GLuint data_sz,
-                         const void *aux,
-                         void *aux_return );
-
-struct brw_winsys_buffer *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,
-                         void *aux_return);
+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_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_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,
+                                  const void *data,
+                                  GLuint data_sz,
+                                  const void *aux,
+                                  void *aux_return ,
+                                  struct brw_winsys_buffer **bo_out);
+
+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,
+                          void *aux_return,
+                          struct brw_winsys_buffer **bo_out);
+
 void brw_state_cache_check_size( struct brw_context *brw );
 
 void brw_init_caches( struct brw_context *brw );
index cbd1f02d77d4df3e05945e1e47a47f9f40e7b709..f8369d31ec12fc6493f46977ed1359a4758c8360 100644 (file)
@@ -109,9 +109,8 @@ update_cache_last(struct brw_cache *cache, enum brw_cache_id cache_id,
    if (bo == cache->last_bo[cache_id])
       return; /* no change */
 
-   cache->sws->bo_unreference(cache->last_bo[cache_id]);
-   cache->last_bo[cache_id] = bo;
-   cache->sws->bo_reference(cache->last_bo[cache_id]);
+   bo_reference( &cache->last_bo[cache_id],  bo );
+
    cache->brw->state.dirty.cache |= 1 << cache_id;
 }
 
@@ -174,14 +173,15 @@ rehash(struct brw_cache *cache)
 /**
  * Returns the buffer object matching cache_id and key, or NULL.
  */
-struct brw_winsys_buffer *
+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,
-                 void *aux_return)
+                 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);
@@ -189,20 +189,20 @@ brw_search_cache(struct brw_cache *cache,
    item = search_cache(cache, cache_id, hash, key, key_size,
                       reloc_bufs, nr_reloc_bufs);
 
-   if (item == NULL)
-      return NULL;
-
-   if (aux_return)
-      *(void **)aux_return = (void *)((char *)item->key + item->key_size);
-
-   update_cache_last(cache, cache_id, item->bo);
-
-   cache->sws->bo_reference(item->bo);
-   return item->bo;
+   if (item) {
+      if (aux_return)
+         *(void **)aux_return = (void *)((char *)item->key + item->key_size);
+      
+      update_cache_last(cache, cache_id, item->bo);
+      bo_reference(bo_out, item->bo);
+      return TRUE;
+   }
+   
+   return FALSE;      
 }
 
 
-struct brw_winsys_buffer *
+enum pipe_error
 brw_upload_cache( struct brw_cache *cache,
                  enum brw_cache_id cache_id,
                  const void *key,
@@ -212,14 +212,15 @@ brw_upload_cache( struct brw_cache *cache,
                  const void *data,
                  GLuint data_size,
                  const void *aux,
-                 void *aux_return )
+                 void *aux_return,
+                  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 aux_size = cache->aux_size[cache_id];
+   enum pipe_error ret;
    void *tmp;
-   struct brw_winsys_buffer *bo;
    int i;
 
    /* Create the buffer object to contain the data.  For now, use a
@@ -227,9 +228,12 @@ brw_upload_cache( struct brw_cache *cache,
     * may want to take advantage of hardware distinctions between
     * these various entities.
     */
-   bo = cache->sws->bo_alloc(cache->sws,
-                             cache->buffer_type,
-                            data_size, 1 << 6);
+   ret = cache->sws->bo_alloc(cache->sws,
+                              cache->buffer_type,
+                              data_size, 1 << 6, 
+                              bo_out);
+   if (ret)
+      return ret;
 
 
    /* Set up the memory containing the key, aux_data, and reloc_bufs */
@@ -240,7 +244,7 @@ brw_upload_cache( struct brw_cache *cache,
    memcpy((char *)tmp + key_size + aux_size, reloc_bufs, relocs_size);
    for (i = 0; i < nr_reloc_bufs; i++) {
       if (reloc_bufs[i] != NULL)
-        cache->sws->bo_reference(reloc_bufs[i]);
+         p_atomic_inc(&reloc_bufs[i]->reference.count);
    }
 
    item->cache_id = cache_id;
@@ -249,9 +253,7 @@ brw_upload_cache( struct brw_cache *cache,
    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->bo = bo;
-   cache->sws->bo_reference(bo);
+   bo_reference( &item->bo, *bo_out );
    item->data_size = data_size;
 
    if (cache->n_items > cache->size * 1.5)
@@ -273,28 +275,28 @@ brw_upload_cache( struct brw_cache *cache,
                   data_size, cache_id);
 
    /* Copy data to the buffer */
-   cache->sws->bo_subdata(bo, 
+   cache->sws->bo_subdata(item->bo, 
                           cache_id,
                           0, data_size, data);
 
-   update_cache_last(cache, cache_id, bo);
+   update_cache_last(cache, cache_id, item->bo);
 
-   return bo;
+   return PIPE_OK;
 }
 
 
 /**
  * This doesn't really work with aux data.  Use search/upload instead
  */
-struct brw_winsys_buffer *
+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)
+                 GLuint nr_reloc_bufs,
+                  struct brw_winsys_buffer **bo_out)
 {
-   struct brw_winsys_buffer *bo;
    struct brw_cache_item *item;
    GLuint hash = hash_key(data, data_size, reloc_bufs, nr_reloc_bufs);
 
@@ -302,17 +304,17 @@ brw_cache_data_sz(struct brw_cache *cache,
                       reloc_bufs, nr_reloc_bufs);
    if (item) {
       update_cache_last(cache, cache_id, item->bo);
-      cache->sws->bo_reference(item->bo);
-      return item->bo;
-   }
 
-   bo = brw_upload_cache(cache, cache_id,
-                        data, data_size,
-                        reloc_bufs, nr_reloc_bufs,
-                        data, data_size,
-                        NULL, NULL);
+      bo_reference(bo_out, item->bo);
+      return PIPE_OK;
+   }
 
-   return bo;
+   return brw_upload_cache(cache, cache_id,
+                           data, data_size,
+                           reloc_bufs, nr_reloc_bufs,
+                           data, data_size,
+                           NULL, NULL,
+                           bo_out);
 }
 
 
@@ -323,15 +325,16 @@ brw_cache_data_sz(struct brw_cache *cache,
  * better to use, as the potentially changing offsets in the data-used-as-key
  * will result in excessive cache misses.
  */
-struct brw_winsys_buffer *
+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)
+              GLuint nr_reloc_bufs,
+               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);
+                           reloc_bufs, nr_reloc_bufs, bo_out);
 }
 
 
@@ -506,11 +509,13 @@ brw_clear_cache(struct brw_context *brw, struct brw_cache *cache)
         int j;
 
         next = c->next;
+
         for (j = 0; j < c->nr_reloc_bufs; j++)
-           brw->sws->bo_unreference(c->reloc_bufs[j]);
-        brw->sws->bo_unreference(c->bo);
-        free((void *)c->key);
-        free(c);
+           bo_reference(&c->reloc_bufs[j], NULL);
+
+        bo_reference(&c->bo, NULL);
+        FREE((void *)c->key);
+        FREE(c);
       }
       cache->items[i] = NULL;
    }
@@ -551,10 +556,12 @@ 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++)
-              cache->sws->bo_unreference(c->reloc_bufs[j]);
-           cache->sws->bo_unreference(c->bo);
-           free((void *)c->key);
-           free(c);
+              bo_reference(&c->reloc_bufs[j], NULL);
+
+           bo_reference(&c->bo, NULL);
+
+           FREE((void *)c->key);
+           FREE(c);
            cache->n_items--;
         } else {
            prev = &c->next;
@@ -590,10 +597,10 @@ brw_destroy_cache(struct brw_context *brw, struct brw_cache *cache)
 
    brw_clear_cache(brw, cache);
    for (i = 0; i < BRW_MAX_CACHE; i++) {
-      brw->sws->bo_unreference(cache->last_bo[i]);
-      free(cache->name[i]);
+      bo_reference(&cache->last_bo[i], NULL);
+      FREE(cache->name[i]);
    }
-   free(cache->items);
+   FREE(cache->items);
    cache->items = NULL;
    cache->size = 0;
 }
index a71af4d2b91d01878e099c32977a8415edbda443..fdcdd59129f5e5504b8a99616f205e26502802e3 100644 (file)
@@ -140,8 +140,7 @@ brw_clear_validated_bos(struct brw_context *brw)
 
    /* Clear the last round of validated bos */
    for (i = 0; i < brw->state.validated_bo_count; i++) {
-      brw->sws->bo_unreference(brw->state.validated_bos[i]);
-      brw->state.validated_bos[i] = NULL;
+      bo_reference(&brw->state.validated_bos[i], NULL);
    }
    brw->state.validated_bo_count = 0;
 }
index 26a28114d98012ff6b95b9456d442f010ba2a370..966940ceacb7370cd23cf383cd4589df3d045b00 100644 (file)
 
 
 
-static void do_vs_prog( struct brw_context *brw, 
-                       struct brw_vertex_shader *vp,
-                       struct brw_vs_prog_key *key )
+static enum pipe_error do_vs_prog( struct brw_context *brw, 
+                                   struct brw_vertex_shader *vp,
+                                   struct brw_vs_prog_key *key,
+                                   struct brw_winsys_buffer **bo_out)
 {
+   enum pipe_error ret;
    GLuint program_size;
    const GLuint *program;
    struct brw_vs_compile c;
@@ -66,22 +68,29 @@ static void do_vs_prog( struct brw_context *brw,
 
    /* get the program
     */
-   program = brw_get_program(&c.func, &program_size);
-
-   brw->sws->bo_unreference(brw->vs.prog_bo);
-   brw->vs.prog_bo = brw_upload_cache( &brw->cache, BRW_VS_PROG,
-                                      &c.key, sizeof(c.key),
-                                      NULL, 0,
-                                      program, program_size,
-                                      &c.prog_data,
-                                      &brw->vs.prog_data );
+   ret = brw_get_program(&c.func, &program, &program_size);
+   if (ret)
+      return ret;
+
+   ret = brw_upload_cache( &brw->cache, BRW_VS_PROG,
+                           &c.key, sizeof(c.key),
+                           NULL, 0,
+                           program, program_size,
+                           &c.prog_data,
+                           &brw->vs.prog_data,
+                           bo_out);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
-static int brw_upload_vs_prog(struct brw_context *brw)
+static enum pipe_error brw_upload_vs_prog(struct brw_context *brw)
 {
    struct brw_vs_prog_key key;
    struct brw_vertex_shader *vp = brw->curr.vertex_shader;
+   enum pipe_error ret;
 
    memset(&key, 0, sizeof(key));
 
@@ -95,15 +104,18 @@ static int brw_upload_vs_prog(struct brw_context *brw)
 
    /* Make an early check for the key.
     */
-   brw->sws->bo_unreference(brw->vs.prog_bo);
-   brw->vs.prog_bo = brw_search_cache(&brw->cache, BRW_VS_PROG,
-                                     &key, sizeof(key),
-                                     NULL, 0,
-                                     &brw->vs.prog_data);
-   if (brw->vs.prog_bo == NULL)
-      do_vs_prog(brw, vp, &key);
-
-   return 0;
+   if (brw_search_cache(&brw->cache, BRW_VS_PROG,
+                        &key, sizeof(key),
+                        NULL, 0,
+                        &brw->vs.prog_data,
+                        &brw->vs.prog_bo))
+      return PIPE_OK;
+
+   ret = do_vs_prog(brw, vp, &key, &brw->vs.prog_bo);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
index 26d5d005faaf7cdd8c8f63b18cf473c1a0dd2d63..22a4d7f01b9f7c664130c80ec16f40b71aed7628 100644 (file)
@@ -78,11 +78,13 @@ vs_unit_populate_key(struct brw_context *brw, struct brw_vs_unit_key *key)
    }
 }
 
-static struct brw_winsys_buffer *
-vs_unit_create_from_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_buffer **bo_out)
 {
+   enum pipe_error ret;
    struct brw_vs_unit_state vs;
-   struct brw_winsys_buffer *bo;
    int chipset_max_threads;
 
    memset(&vs, 0, sizeof(vs));
@@ -141,38 +143,46 @@ vs_unit_create_from_key(struct brw_context *brw, struct brw_vs_unit_key *key)
     */
    vs.vs6.vs_enable = 1;
 
-   bo = brw_upload_cache(&brw->cache, BRW_VS_UNIT,
-                        key, sizeof(*key),
-                        &brw->vs.prog_bo, 1,
-                        &vs, sizeof(vs),
-                        NULL, NULL);
+   ret = brw_upload_cache(&brw->cache, BRW_VS_UNIT,
+                          key, sizeof(*key),
+                          &brw->vs.prog_bo, 1,
+                          &vs, sizeof(vs),
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
 
    /* Emit VS program relocation */
-   brw->sws->bo_emit_reloc(bo,
-                          BRW_USAGE_STATE,
-                          vs.thread0.grf_reg_count << 1,
-                          offsetof(struct brw_vs_unit_state, thread0),
-                          brw->vs.prog_bo);
-
-   return bo;
+   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;
 }
 
 static int prepare_vs_unit(struct brw_context *brw)
 {
    struct brw_vs_unit_key key;
+   enum pipe_error ret;
 
    vs_unit_populate_key(brw, &key);
 
-   brw->sws->bo_unreference(brw->vs.state_bo);
-   brw->vs.state_bo = brw_search_cache(&brw->cache, BRW_VS_UNIT,
-                                      &key, sizeof(key),
-                                      &brw->vs.prog_bo, 1,
-                                      NULL);
-   if (brw->vs.state_bo == NULL) {
-      brw->vs.state_bo = vs_unit_create_from_key(brw, &key);
-   }
+   if (brw_search_cache(&brw->cache, BRW_VS_UNIT,
+                        &key, sizeof(key),
+                        &brw->vs.prog_bo, 1,
+                        NULL,
+                        &brw->vs.state_bo))
+      return PIPE_OK;
+
+   ret = vs_unit_create_from_key(brw, &key, &brw->vs.state_bo);
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_vs_unit = {
index 32fb9b2a8b98f2fb5728df295c5e46e9f2958ca4..b12df0ec03887f694f0ed6a1858e19c1718c3264 100644 (file)
@@ -83,22 +83,23 @@ brw_update_vs_constant_surface( struct brw_context *brw,
 {
    struct brw_surface_key key;
    struct pipe_buffer *cb = brw->curr.vs_constants;
+   enum pipe_error ret;
 
    assert(surf == 0);
 
    /* If we're in this state update atom, we need to update VS constants, so
     * free the old buffer and create a new one for the new contents.
     */
-   brw->sws->bo_unreference(vp->const_buffer);
-   vp->const_buffer = brw_vs_update_constant_buffer(brw);
+   ret = brw_vs_update_constant_buffer(brw, &vp->const_buffer);
+   if (ret)
+      return ret;
 
    /* If there's no constant buffer, then no surface BO is needed to point at
     * it.
     */
-   if (vp->const_buffer == 0) {
-      drm_intel_bo_unreference(brw->vs.surf_bo[surf]);
-      brw->vs.surf_bo[surf] = NULL;
-      return;
+   if (vp->const_buffer == NULL) {
+      bo_reference(brw->vs.surf_bo[surf], NULL);
+      return PIPE_OK;
    }
 
    memset(&key, 0, sizeof(key));
@@ -118,15 +119,20 @@ brw_update_vs_constant_surface( struct brw_context *brw,
           key.width, key.height, key.depth, key.cpp, key.pitch);
    */
 
-   drm_intel_bo_unreference(brw->vs.surf_bo[surf]);
-   brw->vs.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
-                                            BRW_SS_SURFACE,
-                                            &key, sizeof(key),
-                                            &key.bo, key.bo ? 1 : 0,
-                                            NULL);
-   if (brw->vs.surf_bo[surf] == NULL) {
-      brw->vs.surf_bo[surf] = brw_create_constant_surface(brw, &key);
-   }
+   if (brw_search_cache(&brw->surface_cache,
+                        BRW_SS_SURFACE,
+                        &key, sizeof(key),
+                        &key.bo, key.bo ? 1 : 0,
+                        NULL,
+                        &brw->vs.surf_bo[surf]))
+      return PIPE_OK;
+
+   ret = brw_create_constant_surface(brw, &key
+                                     &brw->vs.surf_bo[surf]);
+   if (ret)
+      return ret;
+   
+   return PIPE_OK;
 }
 #endif
 
@@ -134,18 +140,20 @@ brw_update_vs_constant_surface( struct brw_context *brw,
 /**
  * Constructs the binding table for the VS surface state.
  */
-static struct brw_winsys_buffer *
-brw_vs_get_binding_table(struct brw_context *brw)
+static enum pipe_error
+brw_vs_get_binding_table(struct brw_context *brw,
+                         struct brw_winsys_buffer **bo_out)
 {
 #if 0
-   struct brw_winsys_buffer *bind_bo;
-
-   bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
-                             NULL, 0,
-                             brw->vs.surf_bo, BRW_VS_MAX_SURF,
-                             NULL);
-
-   if (bind_bo == NULL) {
+   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;
@@ -156,11 +164,14 @@ brw_vs_get_binding_table(struct brw_context *brw)
          else
             data[i] = 0;
 
-      bind_bo = 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);
+      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++) {
@@ -168,18 +179,19 @@ brw_vs_get_binding_table(struct brw_context *brw)
            /* The presumed offsets were set in the data values for
             * brw_upload_cache.
             */
-           drm_intel_bo_emit_reloc(bind_bo, i * 4,
-                                   brw->vs.surf_bo[i], 0,
-                                   BRW_USAGE_STATE);
+           ret = sws->bo_emit_reloc(*bo_out, i * 4,
+                                     brw->vs.surf_bo[i], 0,
+                                     BRW_USAGE_STATE);
+            if (ret)
+               return ret;
         }
       }
 
-      free(data);
+      FREE(data);
+      return PIPE_OK;
    }
-
-   return bind_bo;
 #else
-   return NULL;
+   return PIPE_OK;
 #endif
 }
 
@@ -190,8 +202,10 @@ brw_vs_get_binding_table(struct brw_context *brw)
  * to be updated, and produces BRW_NEW_NR_VS_SURFACES for the VS unit and
  * CACHE_NEW_SURF_BIND for the binding table upload.
  */
-static int prepare_vs_surfaces(struct brw_context *brw )
+static enum pipe_error prepare_vs_surfaces(struct brw_context *brw )
 {
+   enum pipe_error ret;
+
 #if 0
    int i;
    int nr_surfaces = 0;
@@ -215,11 +229,12 @@ static int prepare_vs_surfaces(struct brw_context *brw )
     * just slightly increases our working set size.
     */
    if (brw->vs.nr_surfaces != 0) {
-      brw->sws->bo_unreference(brw->vs.bind_bo);
-      brw->vs.bind_bo = brw_vs_get_binding_table(brw);
+      ret = brw_vs_get_binding_table(brw, &brw->vs.bind_bo);
+      if (ret)
+         return ret;
    }
 
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_vs_surfaces = {
index d941fbcebee87735a1e45eb2eb424aef8da276f1..f61c541ad1517ef50e9210f0b2d0108ea9709710 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "pipe/p_compiler.h"
 #include "pipe/p_error.h"
+#include "pipe/p_refcnt.h"
 
 struct brw_winsys;
 struct pipe_fence_handle;
@@ -36,10 +37,13 @@ struct pipe_fence_handle;
  */
 #define BRW_BATCH_SIZE (32*1024)
 
+struct brw_winsys_screen;
 
 /* Need a tiny bit of information inside the abstract buffer struct:
  */
 struct brw_winsys_buffer {
+   struct pipe_reference reference;
+   struct brw_winsys_screen *sws;
    unsigned *offset;
    unsigned size;
 };
@@ -105,6 +109,10 @@ enum brw_buffer_data_type {
    BRW_DATA_MAX
 };
 
+
+
+
+
 struct brw_winsys_screen {
 
 
@@ -116,33 +124,33 @@ struct brw_winsys_screen {
    /**
     * Create a buffer.
     */
-   struct brw_winsys_buffer *(*bo_alloc)( struct brw_winsys_screen *sws,
-                                         enum brw_buffer_type type,
-                                         unsigned size,
-                                         unsigned alignment );
+   enum pipe_error (*bo_alloc)( struct brw_winsys_screen *sws,
+                                enum brw_buffer_type type,
+                                unsigned size,
+                                unsigned alignment,
+                                struct brw_winsys_buffer **bo_out );
 
-   /* Reference and unreference buffers:
+   /* Destroy a buffer when our refcount goes to zero:
     */
-   void (*bo_reference)( struct brw_winsys_buffer *buffer );
-   void (*bo_unreference)( struct brw_winsys_buffer *buffer );
+   void (*bo_destroy)( struct brw_winsys_buffer *buffer );
 
    /* delta -- added to b2->offset, and written into buffer
     * offset -- location above value is written to within buffer
     */
-   int (*bo_emit_reloc)( struct brw_winsys_buffer *buffer,
-                        enum brw_buffer_usage usage,
-                        unsigned delta,
-                        unsigned offset,
-                        struct brw_winsys_buffer *b2);
+   enum pipe_error (*bo_emit_reloc)( struct brw_winsys_buffer *buffer,
+                                     enum brw_buffer_usage usage,
+                                     unsigned delta,
+                                     unsigned offset,
+                                     struct brw_winsys_buffer *b2);
 
-   int (*bo_exec)( struct brw_winsys_buffer *buffer,
-                  unsigned bytes_used );
+   enum pipe_error (*bo_exec)( struct brw_winsys_buffer *buffer,
+                               unsigned bytes_used );
 
-   int (*bo_subdata)(struct brw_winsys_buffer *buffer,
-                     enum brw_buffer_data_type data_type,
-                     size_t offset,
-                     size_t size,
-                     const void *data);
+   enum pipe_error (*bo_subdata)(struct brw_winsys_buffer *buffer,
+                                 enum brw_buffer_data_type data_type,
+                                 size_t offset,
+                                 size_t size,
+                                 const void *data);
 
    boolean (*bo_is_busy)(struct brw_winsys_buffer *buffer);
    boolean (*bo_references)(struct brw_winsys_buffer *a,
@@ -175,6 +183,16 @@ struct brw_winsys_screen {
 };
 
 
+static INLINE void
+bo_reference(struct brw_winsys_buffer **ptr, struct brw_winsys_buffer *buf)
+{
+   struct brw_winsys_buffer *old_buf = *ptr;
+
+   if (pipe_reference((struct pipe_reference **)ptr, &buf->reference))
+      old_buf->sws->bo_destroy(old_buf);
+}
+
+
 /**
  * Create brw pipe_screen.
  */
index 815ae8c51aabbd32cbddb8cc9879d85918565d6e..93f90bf32981d60d57c435db559d8668cb1031cf 100644 (file)
@@ -137,30 +137,26 @@ brw_wm_linear_shader_emit(struct brw_context *brw, struct brw_wm_compile *c)
  * Depending on the instructions used (i.e. flow control instructions)
  * we'll use one of two code generators.
  */
-static int do_wm_prog( struct brw_context *brw,
-                       struct brw_fragment_shader *fp, 
-                       struct brw_wm_prog_key *key)
+static enum pipe_error do_wm_prog( struct brw_context *brw,
+                                   struct brw_fragment_shader *fp, 
+                                   struct brw_wm_prog_key *key,
+                                   struct brw_winsys_buffer **bo_out)
 {
+   enum pipe_error ret;
    struct brw_wm_compile *c;
    const GLuint *program;
    GLuint program_size;
 
-   c = brw->wm.compile_data;
-   if (c == NULL) {
-      brw->wm.compile_data = calloc(1, sizeof(*brw->wm.compile_data));
-      c = brw->wm.compile_data;
-      if (c == NULL) {
-         /* Ouch - big out of memory problem.  Can't continue
-          * without triggering a segfault, no way to signal,
-          * so just return.
-          */
+   if (brw->wm.compile_data == NULL) {
+      brw->wm.compile_data = MALLOC(sizeof(*brw->wm.compile_data));
+      if (!brw->wm.compile_data) 
          return PIPE_ERROR_OUT_OF_MEMORY;
-      }
-   } else {
-      memset(c, 0, sizeof(*brw->wm.compile_data));
    }
-   memcpy(&c->key, key, sizeof(*key));
 
+   c = brw->wm.compile_data;
+   memset(c, 0, sizeof *c);
+
+   c->key = *key;
    c->fp = fp;
    c->env_param = NULL; /*brw->intel.ctx.FragmentProgram.Parameters;*/
 
@@ -190,17 +186,21 @@ static int do_wm_prog( struct brw_context *brw,
 
    /* get the program
     */
-   program = brw_get_program(&c->func, &program_size);
-
-   brw->sws->bo_unreference(brw->wm.prog_bo);
-   brw->wm.prog_bo = brw_upload_cache( &brw->cache, BRW_WM_PROG,
-                                      &c->key, sizeof(c->key),
-                                      NULL, 0,
-                                      program, program_size,
-                                      &c->prog_data,
-                                      &brw->wm.prog_data );
-
-   return 0;
+   ret = brw_get_program(&c->func, &program, &program_size);
+   if (ret)
+      return ret;
+
+   ret = brw_upload_cache( &brw->cache, BRW_WM_PROG,
+                           &c->key, sizeof(c->key),
+                           NULL, 0,
+                           program, program_size,
+                           &c->prog_data,
+                           &brw->wm.prog_data,
+                           bo_out );
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
@@ -267,24 +267,28 @@ static void brw_wm_populate_key( struct brw_context *brw,
 }
 
 
-static int brw_prepare_wm_prog(struct brw_context *brw)
+static enum pipe_error brw_prepare_wm_prog(struct brw_context *brw)
 {
    struct brw_wm_prog_key key;
    struct brw_fragment_shader *fs = brw->curr.fragment_shader;
+   enum pipe_error ret;
      
    brw_wm_populate_key(brw, &key);
 
    /* Make an early check for the key.
     */
-   brw->sws->bo_unreference(brw->wm.prog_bo);
-   brw->wm.prog_bo = brw_search_cache(&brw->cache, BRW_WM_PROG,
-                                     &key, sizeof(key),
-                                     NULL, 0,
-                                     &brw->wm.prog_data);
-   if (brw->wm.prog_bo == NULL)
-      return do_wm_prog(brw, fs, &key);
-
-   return 0;
+   if (brw_search_cache(&brw->cache, BRW_WM_PROG,
+                        &key, sizeof(key),
+                        NULL, 0,
+                        &brw->wm.prog_data,
+                        &brw->wm.prog_bo))
+      return PIPE_OK;
+
+   ret = do_wm_prog(brw, fs, &key, &brw->wm.prog_bo);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
index 50ecef29a41b4e60ed72f22d72b7ac0077570427..14568265dd03a991ae772e183e3f40685cd4f6be 100644 (file)
@@ -6,12 +6,14 @@
  * Create the constant buffer surface.  Vertex/fragment shader constants will be
  * read from this buffer with Data Port Read instructions/messages.
  */
-struct brw_winsys_buffer *
+enum pipe_error
 brw_create_constant_surface( struct brw_context *brw,
-                             struct brw_surface_key *key )
+                             struct brw_surface_key *key,
+                             struct brw_winsys_buffer **bo_out )
 {
    const GLint w = key->width - 1;
    struct brw_winsys_buffer *bo;
+   enum pipe_error ret;
 
    memset(&surf, 0, sizeof(surf));
 
@@ -28,22 +30,27 @@ brw_create_constant_surface( struct brw_context *brw,
    surf.ss3.pitch = (key->pitch * key->cpp) - 1; /* ignored?? */
    brw_set_surface_tiling(&surf, key->tiling); /* tiling now allowed */
  
-   bo = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
-                        key, sizeof(*key),
-                        &key->bo, key->bo ? 1 : 0,
-                        &surf, sizeof(surf),
-                        NULL, NULL);
+   ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
+                          key, sizeof(*key),
+                          &key->bo, key->bo ? 1 : 0,
+                          &surf, sizeof(surf),
+                          NULL, NULL,
+                          &bo_out);
+   if (ret)
+      return ret;
 
    if (key->bo) {
       /* Emit relocation to surface contents */
-      brw->sws->bo_emit_reloc(bo,
-                             BRW_USAGE_SAMPLER,
-                             0,
-                             offsetof(struct brw_surface_state, ss1),
-                             key->bo);
+      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 bo;
+   return PIPE_OK;
 }
 
 
@@ -52,7 +59,7 @@ brw_create_constant_surface( struct brw_context *brw,
  * Update the surface state for a WM constant buffer.
  * The constant buffer will be (re)allocated here if needed.
  */
-static void
+static enum pipe_error
 brw_update_wm_constant_surface( struct brw_context *brw,
                                 GLuint surf)
 {
@@ -60,20 +67,21 @@ brw_update_wm_constant_surface( struct brw_context *brw,
    struct brw_fragment_shader *fp = brw->curr.fragment_shader;
    struct pipe_buffer *cbuf = brw->curr.fragment_constants;
    int pitch = cbuf->size / (4 * sizeof(float));
+   enum pipe_error ret;
 
    /* If we're in this state update atom, we need to update WM constants, so
     * free the old buffer and create a new one for the new contents.
     */
-   brw->sws->bo_unreference(fp->const_buffer);
-   fp->const_buffer = brw_wm_update_constant_buffer(brw);
+   ret = brw_wm_update_constant_buffer(brw, &fp->const_buffer);
+   if (ret)
+      return ret;
 
    /* If there's no constant buffer, then no surface BO is needed to point at
     * it.
     */
    if (cbuf == NULL) {
-      drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
-      brw->wm.surf_bo[surf] = NULL;
-      return;
+      bo_reference(&brw->wm.surf_bo[surf], NULL);
+      return PIPE_OK;
    }
 
    memset(&key, 0, sizeof(key));
@@ -97,16 +105,20 @@ brw_update_wm_constant_surface( struct brw_context *brw,
           key.width, key.height, key.depth, key.cpp, key.pitch);
    */
 
-   brw->sws->bo_unreference(brw->wm.surf_bo[surf]);
-   brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
-                                            BRW_SS_SURFACE,
-                                            &key, sizeof(key),
-                                            &key.bo, 1,
-                                            NULL);
-   if (brw->wm.surf_bo[surf] == NULL) {
-      brw->wm.surf_bo[surf] = brw_create_constant_surface(brw, &key);
-   }
+   if (brw_search_cache(&brw->surface_cache,
+                        BRW_SS_SURFACE,
+                        &key, sizeof(key),
+                        &key.bo, 1,
+                        NULL,
+                        &brw->wm.surf_bo[surf]))
+      return PIPE_OK;
+
+   ret = brw_create_constant_surface(brw, &key, &brw->wm.surf_bo[surf]);
+   if (ret)
+      return ret;
+
    brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
+   return PIPE_OK;
 }
 
 /**
@@ -117,28 +129,33 @@ brw_update_wm_constant_surface( struct brw_context *brw,
  * BRW_NEW_WM_SURFACES to get picked up by brw_prepare_wm_surfaces for
  * inclusion in the binding table.
  */
-static void prepare_wm_constant_surface(struct brw_context *brw )
+static enum pipe_error prepare_wm_constant_surface(struct brw_context *brw )
 {
    struct brw_fragment_program *fp =
       (struct brw_fragment_program *) brw->fragment_program;
    GLuint surf = SURF_INDEX_FRAG_CONST_BUFFER;
 
-   drm_intel_bo_unreference(fp->const_buffer);
-   fp->const_buffer = brw_wm_update_constant_buffer(brw);
+   ret = brw_wm_update_constant_buffer(brw,
+                                       &fp->const_buffer);
+   if (ret)
+      return ret;
 
    /* If there's no constant buffer, then no surface BO is needed to point at
     * it.
     */
    if (fp->const_buffer == 0) {
       if (brw->wm.surf_bo[surf] != NULL) {
-        drm_intel_bo_unreference(brw->wm.surf_bo[surf]);
-        brw->wm.surf_bo[surf] = NULL;
+        bo_reference(&brw->wm.surf_bo[surf], NULL);
         brw->state.dirty.brw |= BRW_NEW_WM_SURFACES;
       }
-      return;
+      return PIPE_OK;
    }
 
-   brw_update_wm_constant_surface(ctx, surf);
+   ret = brw_update_wm_constant_surface(ctx, surf);
+   if (ret)
+      return ret;
+
+   return PIPE_OK
 }
 
 const struct brw_tracked_state brw_wm_constant_surface = {
index 2fddb4ad8974635f78c3ce63ff79142dc9da6afe..2861aa979fefa21553cb57947efcba59ed3853ee 100644 (file)
 
 
 
-static struct brw_winsys_buffer *
+static enum pipe_error
 upload_default_color( struct brw_context *brw,
-                     const GLfloat *color )
+                     const GLfloat *color,
+                      struct brw_winsys_buffer **bo_out )
 {
    struct brw_sampler_default_color sdc;
+   enum pipe_error ret;
 
    COPY_4V(sdc.color, color); 
    
-   return brw_cache_data( &brw->cache, BRW_SAMPLER_DEFAULT_COLOR, &sdc,
-                         NULL, 0 );
+   ret = brw_cache_data( &brw->cache, BRW_SAMPLER_DEFAULT_COLOR, &sdc,
+                         NULL, 0, bo_out );
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
@@ -111,9 +117,10 @@ brw_wm_sampler_populate_key(struct brw_context *brw,
 }
 
 
-static void
+static enum pipe_error
 brw_wm_sampler_update_default_colors(struct brw_context *brw)
 {
+   enum pipe_error ret;
    int nr = MIN2(brw->curr.num_textures,
                 brw->curr.num_samplers);
    int i;
@@ -121,8 +128,7 @@ brw_wm_sampler_update_default_colors(struct brw_context *brw)
    for (i = 0; i < nr; i++) {
       const struct brw_texture *tex = brw_texture(brw->curr.texture[i]);
       const struct brw_sampler *sampler = brw->curr.sampler[i];
-
-      brw->sws->bo_unreference(brw->wm.sdc_bo[i]);
+      const float *bc;
 
       if (pf_is_depth_or_stencil(tex->base.format)) {
         float bordercolor[4] = {
@@ -131,15 +137,25 @@ brw_wm_sampler_update_default_colors(struct brw_context *brw)
            sampler->border_color[0],
            sampler->border_color[0]
         };
-        /* GL specs that border color for depth textures is taken from the
-         * R channel, while the hardware uses A.  Spam R into all the
-         * channels for safety.
-         */
-        brw->wm.sdc_bo[i] = upload_default_color(brw, bordercolor);
-      } else {
-        brw->wm.sdc_bo[i] = upload_default_color(brw, sampler->border_color);
+         
+         bc = bordercolor;
+      }
+      else {
+         bc = sampler->border_color;
       }
+
+      /* GL specs that border color for depth textures is taken from the
+       * R channel, while the hardware uses A.  Spam R into all the
+       * channels for safety.
+       */
+      ret = upload_default_color(brw, 
+                                 bc,
+                                 &brw->wm.sdc_bo[i]);
+      if (ret) 
+         return ret;
    }
+
+   return PIPE_OK;
 }
 
 
@@ -149,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;
+   enum pipe_error ret;
    int i;
 
    brw_wm_sampler_update_default_colors(brw);
@@ -159,35 +176,40 @@ static int upload_wm_samplers( struct brw_context *brw )
       brw->state.dirty.cache |= CACHE_NEW_SAMPLER;
    }
 
-   brw->sws->bo_unreference(brw->wm.sampler_bo);
-   brw->wm.sampler_bo = NULL;
-   if (brw->wm.sampler_count == 0)
-      return 0;
+   if (brw->wm.sampler_count == 0) {
+      bo_reference(&brw->wm.sampler_bo, NULL);
+      return PIPE_OK;
+   }
 
-   brw->wm.sampler_bo = brw_search_cache(&brw->cache, BRW_SAMPLER,
-                                        &key, sizeof(key),
-                                        brw->wm.sdc_bo, key.sampler_count,
-                                        NULL);
+   if (brw_search_cache(&brw->cache, BRW_SAMPLER,
+                        &key, sizeof(key),
+                        brw->wm.sdc_bo, key.sampler_count,
+                        NULL,
+                        &brw->wm.sampler_bo))
+      return PIPE_OK;
 
    /* If we didnt find it in the cache, compute the state and put it in the
     * cache.
     */
-   if (brw->wm.sampler_bo == NULL) {
-      brw->wm.sampler_bo = brw_upload_cache(&brw->cache, BRW_SAMPLER,
-                                           &key, sizeof(key),
-                                           brw->wm.sdc_bo, key.sampler_count,
-                                           &key.sampler, sizeof(key.sampler),
-                                           NULL, NULL);
-
-      /* Emit SDC relocations */
-      for (i = 0; i < key.sampler_count; i++) {
-        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]);
-      }
+   ret = brw_upload_cache(&brw->cache, BRW_SAMPLER,
+                          &key, sizeof(key),
+                          brw->wm.sdc_bo, 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;
index ccbb647bcd01881eb635bb9ae3905d3d6042e52a..86dc10540d776568a9641d72f7c83014a12e2c52 100644 (file)
@@ -138,12 +138,13 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
 /**
  * Setup wm hardware state.  See page 225 of Volume 2
  */
-static struct brw_winsys_buffer *
+static enum pipe_error
 wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
-                       struct brw_winsys_buffer **reloc_bufs)
+                       struct brw_winsys_buffer **reloc_bufs,
+                        struct brw_winsys_buffer **bo_out)
 {
    struct brw_wm_unit_state wm;
-   struct brw_winsys_buffer *bo;
+   enum pipe_error ret;
 
    memset(&wm, 0, sizeof(wm));
 
@@ -222,45 +223,56 @@ wm_unit_create_from_key(struct brw_context *brw, struct brw_wm_unit_key *key,
    if (BRW_DEBUG & DEBUG_STATS || key->stats_wm)
       wm.wm4.stats_enable = 1;
 
-   bo = brw_upload_cache(&brw->cache, BRW_WM_UNIT,
-                        key, sizeof(*key),
-                        reloc_bufs, 3,
-                        &wm, sizeof(wm),
-                        NULL, NULL);
+   ret = brw_upload_cache(&brw->cache, BRW_WM_UNIT,
+                          key, sizeof(*key),
+                          reloc_bufs, 3,
+                          &wm, sizeof(wm),
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
 
    /* Emit WM program relocation */
-   brw->sws->bo_emit_reloc(bo,
-                          BRW_USAGE_STATE,
-                          wm.thread0.grf_reg_count << 1,
-                          offsetof(struct brw_wm_unit_state, thread0),
-                          brw->wm.prog_bo);
+   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) {
-      brw->sws->bo_emit_reloc(bo,
-                             BRW_USAGE_SCRATCH,
-                             wm.thread2.per_thread_scratch_space,
-                             offsetof(struct brw_wm_unit_state, thread2),
-                             brw->wm.scratch_bo);
+      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) {
-      brw->sws->bo_emit_reloc(bo,
-                             BRW_USAGE_STATE,
-                             wm.wm4.stats_enable | (wm.wm4.sampler_count << 2),
-                             offsetof(struct brw_wm_unit_state, wm4),
-                             brw->wm.sampler_bo);
+      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 bo;
+   return PIPE_OK;
 }
 
 
-static int upload_wm_unit( struct brw_context *brw )
+static enum pipe_error upload_wm_unit( struct brw_context *brw )
 {
    struct brw_wm_unit_key key;
    struct brw_winsys_buffer *reloc_bufs[3];
+   enum pipe_error ret;
+
    wm_unit_populate_key(brw, &key);
 
    /* Allocate the necessary scratch space if we haven't already.  Don't
@@ -271,15 +283,19 @@ static int upload_wm_unit( struct brw_context *brw )
    if (key.total_scratch) {
       GLuint total = key.total_scratch * key.max_threads;
 
-      if (brw->wm.scratch_bo && total > brw->wm.scratch_bo->size) {
-        brw->sws->bo_unreference(brw->wm.scratch_bo);
-        brw->wm.scratch_bo = NULL;
-      }
+      /* Do we need a new buffer:
+       */
+      if (brw->wm.scratch_bo && total > brw->wm.scratch_bo->size) 
+        bo_reference(&brw->wm.scratch_bo, NULL);
+
       if (brw->wm.scratch_bo == NULL) {
-        brw->wm.scratch_bo = brw->sws->bo_alloc(brw->sws,
-                                                BRW_BUFFER_TYPE_SHADER_SCRATCH,
-                                                total,
-                                                4096);
+        ret = brw->sws->bo_alloc(brw->sws,
+                                  BRW_BUFFER_TYPE_SHADER_SCRATCH,
+                                  total,
+                                  4096,
+                                  &brw->wm.scratch_bo);
+         if (ret)
+            return ret;
       }
    }
 
@@ -287,16 +303,19 @@ static int upload_wm_unit( struct brw_context *brw )
    reloc_bufs[1] = brw->wm.scratch_bo;
    reloc_bufs[2] = brw->wm.sampler_bo;
 
-   brw->sws->bo_unreference(brw->wm.state_bo);
-   brw->wm.state_bo = brw_search_cache(&brw->cache, BRW_WM_UNIT,
-                                      &key, sizeof(key),
-                                      reloc_bufs, 3,
-                                      NULL);
-   if (brw->wm.state_bo == NULL) {
-      brw->wm.state_bo = wm_unit_create_from_key(brw, &key, reloc_bufs);
-   }
+   if (brw_search_cache(&brw->cache, BRW_WM_UNIT,
+                        &key, sizeof(key),
+                        reloc_bufs, 3,
+                        NULL,
+                        &brw->wm.state_bo))
+      return PIPE_OK;
+
+   ret = wm_unit_create_from_key(brw, &key, reloc_bufs,
+                                 &brw->wm.state_bo);
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_wm_unit = {
index b055dde20cf1ceee29f56f53e92b4b2aa3f48d3e..e5d03299677c03a0a709f3e9d9f8c2366d5c3f59 100644 (file)
 
 
 
-static void
+static enum pipe_error
 brw_update_texture_surface( struct brw_context *brw,
                            struct brw_texture *tex,
-                           GLuint surf )
+                            struct brw_winsys_buffer **bo_out)
 {
-   brw->wm.surf_bo[surf] = brw_search_cache(&brw->surface_cache,
-                                            BRW_SS_SURFACE,
-                                            &tex->ss, sizeof tex->ss,
-                                            &tex->bo, 1,
-                                            NULL);
-
-   if (brw->wm.surf_bo[surf] == NULL) {
-      brw->wm.surf_bo[surf] = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
-                                              &tex->ss, sizeof tex->ss,
-                                              &tex->bo, 1,
-                                              &tex->ss, sizeof tex->ss,
-                                              NULL, NULL);
+   enum pipe_error ret;
+
+   if (brw_search_cache(&brw->surface_cache,
+                        BRW_SS_SURFACE,
+                        &tex->ss, sizeof tex->ss,
+                        &tex->bo, 1,
+                        NULL,
+                        bo_out))
+      return PIPE_OK;
+
+   ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
+                          &tex->ss, sizeof tex->ss,
+                          &tex->bo, 1,
+                          &tex->ss, sizeof tex->ss,
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
       
-      /* Emit relocation to surface contents */
-      brw->sws->bo_emit_reloc(brw->wm.surf_bo[surf],
-                             BRW_USAGE_SAMPLER,
-                             0,
-                             offsetof(struct brw_surface_state, ss1),
-                             tex->bo);
-   }
+   /* 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;
 }
 
 
@@ -79,13 +88,14 @@ brw_update_texture_surface( struct brw_context *brw,
  * While it is only used for the front/back buffer currently, it should be
  * usable for further buffers when doing ARB_draw_buffer support.
  */
-static void
-brw_update_renderbuffer_surface(struct brw_context *brw,
-                               struct brw_surface *surface,
-                               unsigned int unit)
+static enum pipe_error
+brw_update_render_surface(struct brw_context *brw,
+                          struct brw_surface *surface,
+                          struct brw_winsys_buffer **bo_out)
 {
    struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0;
    struct brw_surface_state ss;
+   enum pipe_error ret;
 
    /* Surfaces are potentially shared between contexts, so can't
     * scribble the in-place ss0 value in the surface.
@@ -98,30 +108,35 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
    ss.ss0.writedisable_red   = blend_ss0.writedisable_red;
    ss.ss0.writedisable_alpha = blend_ss0.writedisable_alpha;
 
-   brw->sws->bo_unreference(brw->wm.surf_bo[unit]);
-   brw->wm.surf_bo[unit] = brw_search_cache(&brw->surface_cache,
-                                           BRW_SS_SURFACE,
-                                           &ss, sizeof(ss),
-                                           &surface->bo, 1,
-                                           NULL);
-
-   if (brw->wm.surf_bo[unit] == NULL) {
-
-      brw->wm.surf_bo[unit] = brw_upload_cache(&brw->surface_cache,
-                                               BRW_SS_SURFACE,
-                                               &ss, sizeof ss,
-                                              &surface->bo, 1,
-                                              &ss, sizeof ss,
-                                              NULL, NULL);
+   if (brw_search_cache(&brw->surface_cache,
+                        BRW_SS_SURFACE,
+                        &ss, sizeof(ss),
+                        &surface->bo, 1,
+                        NULL,
+                        bo_out))
+      return PIPE_OK;
+       
+   ret = brw_upload_cache(&brw->surface_cache,
+                          BRW_SS_SURFACE,
+                          &ss, sizeof ss,
+                          &surface->bo, 1,
+                          &ss, sizeof ss,
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
 
       /* XXX: we will only be rendering to this surface:
        */
-      brw->sws->bo_emit_reloc(brw->wm.surf_bo[unit],
-                             BRW_USAGE_RENDER_TARGET,
-                             ss.ss1.base_addr - surface->bo->offset[0], /* XXX */
-                             offsetof(struct brw_surface_state, ss1),
-                             surface->bo);
-   }
+   ret = brw->sws->bo_emit_reloc(*bo_out,
+                                 BRW_USAGE_RENDER_TARGET,
+                                 ss.ss1.base_addr - surface->bo->offset[0], /* XXX */
+                                 offsetof(struct brw_surface_state, ss1),
+                                 surface->bo);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
@@ -129,60 +144,60 @@ brw_update_renderbuffer_surface(struct brw_context *brw,
  * Constructs the binding table for the WM surface state, which maps unit
  * numbers to surface state objects.
  */
-static struct brw_winsys_buffer *
-brw_wm_get_binding_table(struct brw_context *brw)
+static enum pipe_error
+brw_wm_get_binding_table(struct brw_context *brw,
+                         struct brw_winsys_buffer **bo_out )
 {
-   struct brw_winsys_buffer *bind_bo;
+   enum pipe_error ret;
+   uint32_t data[BRW_WM_MAX_SURF];
+   GLuint data_size = brw->wm.nr_surfaces * sizeof data[0];
+   int i;
 
    assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
+   assert(brw->wm.nr_surfaces > 0);
 
    /* Note there is no key for this search beyond the values in the
     * relocation array:
     */
-   bind_bo = brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
-                             NULL, 0,
-                             brw->wm.surf_bo, brw->wm.nr_surfaces,
-                             NULL);
-
-   if (bind_bo == NULL) {
-      uint32_t data[BRW_WM_MAX_SURF];
-      GLuint data_size = brw->wm.nr_surfaces * sizeof data[0];
-      int i;
-
-      for (i = 0; i < brw->wm.nr_surfaces; i++)
-        data[i] = brw->wm.surf_bo[i]->offset[0];
-
-      bind_bo = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
-                                 NULL, 0,
-                                 brw->wm.surf_bo, brw->wm.nr_surfaces,
-                                 data, data_size,
-                                 NULL, NULL);
-
-      /* Emit binding table relocations to surface state */
-      for (i = 0; i < brw->wm.nr_surfaces; i++) {
-        brw->sws->bo_emit_reloc(bind_bo,
-                                BRW_USAGE_STATE,
-                                0,
-                                i * sizeof(GLuint),
-                                brw->wm.surf_bo[i]);
-      }
+   if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
+                        NULL, 0,
+                        brw->wm.surf_bo,
+                        brw->wm.nr_surfaces,
+                        NULL,
+                        bo_out))
+      return PIPE_OK;
+
+   for (i = 0; i < brw->wm.nr_surfaces; i++)
+      data[i] = brw->wm.surf_bo[i]->offset[0];
+
+   ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
+                           NULL, 0,
+                           brw->wm.surf_bo, 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 bind_bo;
+   return PIPE_OK;
 }
 
-static int prepare_wm_surfaces(struct brw_context *brw )
+static enum pipe_error prepare_wm_surfaces(struct brw_context *brw )
 {
-   GLuint i;
+   enum pipe_error ret;
    int nr_surfaces = 0;
-
-   /* Unreference old buffers
-    */
-   for (i = 0; i < brw->wm.nr_surfaces; i++) {
-      brw->sws->bo_unreference(brw->wm.surf_bo[i]);
-      brw->wm.surf_bo[i] = NULL;
-   }
-
+   GLuint i;
 
    /* PIPE_NEW_COLOR_BUFFERS | PIPE_NEW_BLEND
     *
@@ -192,38 +207,51 @@ static int prepare_wm_surfaces(struct brw_context *brw )
     * XXX: no color buffer case
     */
    for (i = 0; i < brw->curr.fb.nr_cbufs; i++) {
-      brw_update_renderbuffer_surface(brw, 
-                                     brw_surface(brw->curr.fb.cbufs[i]), 
-                                     nr_surfaces++);
+      ret = brw_update_render_surface(brw, 
+                                      brw_surface(brw->curr.fb.cbufs[i]), 
+                                      &brw->wm.surf_bo[nr_surfaces++]);
+      if (ret)
+         return ret;
    }
 
    /* PIPE_NEW_TEXTURE 
     */
    for (i = 0; i < brw->curr.num_textures; i++) {
-      brw_update_texture_surface(brw, 
-                                brw_texture(brw->curr.texture[i]),
-                                nr_surfaces++);
+      ret = brw_update_texture_surface(brw, 
+                                       brw_texture(brw->curr.texture[i]),
+                                       &brw->wm.surf_bo[nr_surfaces++]);
+      if (ret)
+         return ret;
    }
 
    /* PIPE_NEW_FRAGMENT_CONSTANTS
     */
 #if 0
    if (brw->curr.fragment_constants) {
-      brw_update_fragment_constant_surface(brw, 
-                                          brw->curr.fragment_constants, 
-                                          nr_surfaces++);
+      ret = brw_update_fragment_constant_surface(brw, 
+                                                 brw->curr.fragment_constants, 
+                                                 &brw->wm.surf_bo[nr_surfaces++]);
+      if (ret)
+         return ret;
    }
 #endif
 
    if (brw->wm.nr_surfaces != nr_surfaces) {
+
+      /* Unreference any left-over old buffers
+       */
+      for (i = nr_surfaces; i < brw->wm.nr_surfaces; i++)
+         bo_reference(&brw->wm.surf_bo[i], NULL);
+
       brw->wm.nr_surfaces = nr_surfaces;
       brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
    }
 
-   brw->sws->bo_unreference(brw->wm.bind_bo);
-   brw->wm.bind_bo = brw_wm_get_binding_table(brw);
+   ret = brw_wm_get_binding_table(brw, &brw->wm.bind_bo);
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_wm_surfaces = {
index b1edca818a1126c3c6e03c08d01abcf34f7a89e9..fc465d7c1434fe8adcfda39808d1c416be333cd1 100644 (file)
@@ -134,11 +134,12 @@ const char *data_types[BRW_DATA_MAX] =
 };
 
 
-static struct brw_winsys_buffer *
+static enum pipe_error
 xlib_brw_bo_alloc( struct brw_winsys_screen *sws,
-                     enum brw_buffer_type type,
-                     unsigned size,
-                     unsigned alignment )
+                   enum brw_buffer_type type,
+                   unsigned size,
+                   unsigned alignment,
+                   struct brw_winsys_buffer **bo_out )
 {
    struct xlib_brw_winsys *xbw = xlib_brw_winsys(sws);
    struct xlib_brw_buffer *buf;
@@ -148,12 +149,13 @@ xlib_brw_bo_alloc( struct brw_winsys_screen *sws,
 
    buf = CALLOC_STRUCT(xlib_brw_buffer);
    if (!buf)
-      return NULL;
+      return PIPE_ERROR_OUT_OF_MEMORY;
+
+   pipe_reference_init(&buf->base.reference, 1);
 
    buf->offset = align(xbw->offset, alignment);
    buf->type = type;
    buf->virtual = MALLOC(size);
-   buf->cheesy_refcount = 1;
    buf->base.offset = &buf->offset; /* hmm, cheesy */
    buf->base.size = size;
 
@@ -161,36 +163,25 @@ xlib_brw_bo_alloc( struct brw_winsys_screen *sws,
    if (xbw->offset > MAX_VRAM)
       goto err;
 
-   return &buf->base;
+   /* XXX: possibly rentrant call to bo_destroy:
+    */
+   bo_reference(bo_out, &buf->base);
+   return PIPE_OK;
 
 err:
    assert(0);
+   FREE(buf->virtual);
    FREE(buf);
-   return NULL;
-}
-
-static void 
-xlib_brw_bo_reference( struct brw_winsys_buffer *buffer )
-{
-   struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
-
-   buf->cheesy_refcount++;
+   return PIPE_ERROR_OUT_OF_MEMORY;
 }
 
 static void 
-xlib_brw_bo_unreference( struct brw_winsys_buffer *buffer )
+xlib_brw_bo_destroy( struct brw_winsys_buffer *buffer )
 {
    struct xlib_brw_buffer *buf = xlib_brw_buffer(buffer);
 
-   /* As a special favor in this call only, buffer is allowed to be
-    * NULL:
-    */
-   if (buffer == NULL)
-      return;
-
-   if (--buf->cheesy_refcount == 0) {
-      FREE(buffer);
-   }
+   FREE(buf->virtual);
+   FREE(buf);
 }
 
 static int 
@@ -378,8 +369,7 @@ xlib_create_brw_winsys_screen( void )
 
    ws->base.destroy              = xlib_brw_winsys_destroy;
    ws->base.bo_alloc             = xlib_brw_bo_alloc;
-   ws->base.bo_reference         = xlib_brw_bo_reference;
-   ws->base.bo_unreference       = xlib_brw_bo_unreference;
+   ws->base.bo_destroy           = xlib_brw_bo_destroy;
    ws->base.bo_emit_reloc        = xlib_brw_bo_emit_reloc;
    ws->base.bo_exec              = xlib_brw_bo_exec;
    ws->base.bo_subdata           = xlib_brw_bo_subdata;