Merge branch '7.8'
[mesa.git] / src / gallium / drivers / i965 / brw_wm_surface_state.c
index 6c29db045fc1272bc204dba5a39dabd4031f5c47..0d80a0114af62316bcdcbe2325af586c65a887ae 100644 (file)
 #include "brw_batchbuffer.h"
 #include "brw_context.h"
 #include "brw_state.h"
-#include "brw_defines.h"
-#include "brw_screen.h"
+#include "brw_resource.h"
 
 
 
 
-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);
-      
-      /* 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);
-   }
+   struct brw_winsys_reloc reloc[1];
+   enum pipe_error ret;
+
+   /* Emit relocation to surface contents */
+   make_reloc(&reloc[0],
+              BRW_USAGE_SAMPLER,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              tex->bo);
+
+   if (brw_search_cache(&brw->surface_cache,
+                        BRW_SS_SURFACE,
+                        &tex->ss, sizeof tex->ss,
+                        reloc, Elements(reloc),
+                        NULL,
+                        bo_out))
+      return PIPE_OK;
+
+   ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
+                          &tex->ss, sizeof tex->ss,
+                          reloc, Elements(reloc),
+                          &tex->ss, sizeof tex->ss,
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
@@ -79,13 +86,23 @@ 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;
+   struct brw_winsys_reloc reloc[1];
+   enum pipe_error ret;
+
+   /* XXX: we will only be rendering to this surface:
+    */
+   make_reloc(&reloc[0],
+              BRW_USAGE_RENDER_TARGET,
+              0,
+              offsetof(struct brw_surface_state, ss1),
+              surface->bo);
 
    /* Surfaces are potentially shared between contexts, so can't
     * scribble the in-place ss0 value in the surface.
@@ -98,30 +115,25 @@ 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);
-
-      /* 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);
-   }
+   if (brw_search_cache(&brw->surface_cache,
+                        BRW_SS_SURFACE,
+                        &ss, sizeof(ss),
+                        reloc, Elements(reloc),
+                        NULL,
+                        bo_out))
+      return PIPE_OK;
+       
+   ret = brw_upload_cache(&brw->surface_cache,
+                          BRW_SS_SURFACE,
+                          &ss, sizeof ss,
+                          reloc, Elements(reloc),
+                          &ss, sizeof ss,
+                          NULL, NULL,
+                          bo_out);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 
@@ -129,60 +141,65 @@ 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;
+   struct brw_winsys_reloc reloc[BRW_WM_MAX_SURF];
+   uint32_t data[BRW_WM_MAX_SURF];
+   GLuint nr_relocs = 0;
+   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:
+   /* Emit binding table relocations to surface state 
     */
-   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]);
+   for (i = 0; i < brw->wm.nr_surfaces; i++) {
+      if (brw->wm.surf_bo[i]) {
+         make_reloc(&reloc[nr_relocs++],
+                    BRW_USAGE_STATE,
+                    0,
+                    i * sizeof(GLuint),
+                    brw->wm.surf_bo[i]);
       }
    }
 
-   return bind_bo;
+   /* Note there is no key for this search beyond the values in the
+    * relocation array:
+    */
+   if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
+                        NULL, 0,
+                        reloc, nr_relocs,
+                        NULL,
+                        bo_out))
+      return PIPE_OK;
+
+   /* Upload zero data, will all be overwitten with relocation
+    * offsets:
+    */
+   for (i = 0; i < brw->wm.nr_surfaces; i++)
+      data[i] = 0;
+
+   ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
+                           NULL, 0,
+                           reloc, nr_relocs,
+                           data, data_size,
+                           NULL, NULL,
+                           bo_out);
+   if (ret)
+      return ret;
+
+   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 +209,71 @@ 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[BTI_COLOR_BUF(i)]);
+      if (ret)
+         return ret;
+      
+      nr_surfaces = BTI_COLOR_BUF(i) + 1;
    }
 
-   /* 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++);
-   }
+
 
    /* 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[BTI_FRAGMENT_CONSTANTS]);
+
+      if (ret)
+         return ret;
+
+      nr_surfaces = BTI_FRAGMENT_CONSTANTS + 1;
+   }
+   else {
+      bo_reference(&brw->wm.surf_bo[SURF_FRAG_CONSTANTS], NULL);      
    }
 #endif
 
-   brw->sws->bo_unreference(brw->wm.bind_bo);
-   brw->wm.bind_bo = brw_wm_get_binding_table(brw);
+
+   /* PIPE_NEW_TEXTURE 
+    */
+   for (i = 0; i < brw->curr.num_fragment_sampler_views; i++) {
+      ret = brw_update_texture_surface(brw, 
+                                       brw_texture(brw->curr.fragment_sampler_views[i]->texture),
+                                       &brw->wm.surf_bo[BTI_TEXTURE(i)]);
+      if (ret)
+         return ret;
+
+      nr_surfaces = BTI_TEXTURE(i) + 1;
+   }
+
+   /* Clear any inactive entries:
+    */
+   for (i = brw->curr.fb.nr_cbufs; i < BRW_MAX_DRAW_BUFFERS; i++) 
+      bo_reference(&brw->wm.surf_bo[BTI_COLOR_BUF(i)], NULL);
+
+   if (!brw->curr.fragment_constants)
+      bo_reference(&brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS], NULL);      
+
+   /* XXX: no pipe_max_textures define?? */
+   for (i = brw->curr.num_fragment_sampler_views; i < PIPE_MAX_SAMPLERS; i++)
+      bo_reference(&brw->wm.surf_bo[BTI_TEXTURE(i)], NULL);
 
    if (brw->wm.nr_surfaces != nr_surfaces) {
       brw->wm.nr_surfaces = nr_surfaces;
       brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
    }
 
-   return 0;
+   ret = brw_wm_get_binding_table(brw, &brw->wm.bind_bo);
+   if (ret)
+      return ret;
+
+   return PIPE_OK;
 }
 
 const struct brw_tracked_state brw_wm_surfaces = {