galahad: do map/unmap counting for resources
[mesa.git] / src / gallium / drivers / i965 / brw_sf.c
index 013d839e37dd2c7e126ec8a0064073863ee1370d..5abf3848ab4e6d7865c505e5215845443cbb7946 100644 (file)
 #include "brw_context.h"
 #include "brw_pipe_rast.h"
 #include "brw_eu.h"
-#include "brw_util.h"
 #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;
@@ -62,83 +63,111 @@ static void compile_sf_prog( struct brw_context *brw,
    c.prog_data.urb_read_length = c.nr_attr_regs;
    c.prog_data.urb_entry_size = c.nr_setup_regs * 2;
 
-   
-   /* Which primitive?  Or all three? 
+   /* Special case when there are no attributes to setup.
+    *
+    * XXX: should be able to set nr_setup_attrs to nr_attrs-1 -- but
+    * breaks vp-tris.c
     */
-   switch (key->primitive) {
-   case SF_TRIANGLES:
-      c.nr_verts = 3;
-      brw_emit_tri_setup( &c, GL_TRUE );
-      break;
-   case SF_LINES:
-      c.nr_verts = 2;
-      brw_emit_line_setup( &c, GL_TRUE );
-      break;
-   case SF_POINTS:
-      c.nr_verts = 1;
-      if (key->do_point_sprite)
-         brw_emit_point_sprite_setup( &c, GL_TRUE );
-      else
-         brw_emit_point_setup( &c, GL_TRUE );
-      break;
-   case SF_UNFILLED_TRIS:
-      c.nr_verts = 3;
-      brw_emit_anyprim_setup( &c );
-      break;
-   default:
-      assert(0);
-      return;
+   if (c.nr_attrs - 1 == 0) {
+      c.nr_verts = 0;
+      brw_emit_null_setup( &c );
+   }
+   else {
+      /* Which primitive?  Or all three? 
+       */
+      switch (key->primitive) {
+      case SF_TRIANGLES:
+         c.nr_verts = 3;
+         brw_emit_tri_setup( &c, GL_TRUE );
+         break;
+      case SF_LINES:
+         c.nr_verts = 2;
+         brw_emit_line_setup( &c, GL_TRUE );
+         break;
+      case SF_POINTS:
+         c.nr_verts = 1;
+         if (key->do_point_sprite)
+            brw_emit_point_sprite_setup( &c, GL_TRUE );
+         else
+            brw_emit_point_setup( &c, GL_TRUE );
+         break;
+      case SF_UNFILLED_TRIS:
+         c.nr_verts = 3;
+         brw_emit_anyprim_setup( &c );
+         break;
+      default:
+         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->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)
 {
+   const struct brw_fs_signature *sig = &brw->curr.fragment_shader->signature;
+   const struct pipe_rasterizer_state *rast = &brw->curr.rast->templ;
    struct brw_sf_prog_key key;
+   enum pipe_error ret;
+   unsigned i;
 
    memset(&key, 0, sizeof(key));
 
    /* Populate the key, noting state dependencies:
     */
-   /* CACHE_NEW_VS_PROG */
-   key.nr_attrs = brw->curr.vertex_shader->info.file_max[TGSI_FILE_OUTPUT] + 1;
 
+   /* XXX: Add one to account for the position input.
+    */
+   /* PIPE_NEW_FRAGMENT_SIGNATURE */
+   key.nr_attrs = sig->nr_inputs + 1;
 
-   /* XXX: this is probably where the mapping between vertex shader
-    * outputs and fragment shader inputs should be handled.  Assume
-    * for now 1:1 correspondance.
-    *
-    * XXX: scan frag shader inputs to work out linear vs. perspective
-    * interpolation below.
-    *
-    * XXX: as long as we're hard-wiring, is eg. position required to
-    * be linear?
+
+   /* XXX: why is position required to be linear?  why do we care
+    * about it at all?
     */
-   key.linear_attrs = 0;
-   key.persp_attrs = (1 << key.nr_attrs) - 1;
+   key.linear_attrs = 1;        /* position -- but why? */
+
+   for (i = 0; i < sig->nr_inputs; i++) {
+      switch (sig->input[i].interp) {
+      case TGSI_INTERPOLATE_CONSTANT:
+         break;
+      case TGSI_INTERPOLATE_LINEAR:
+         key.linear_attrs |= 1 << (i+1);
+         break;
+      case TGSI_INTERPOLATE_PERSPECTIVE:
+         key.persp_attrs |= 1 << (i+1);
+         break;
+      }
+   }
 
    /* BRW_NEW_REDUCED_PRIMITIVE */
    switch (brw->reduced_primitive) {
    case PIPE_PRIM_TRIANGLES: 
       /* PIPE_NEW_RAST
        */
-      if (brw->curr.rast->templ.fill_cw != PIPE_POLYGON_MODE_FILL ||
-         brw->curr.rast->templ.fill_ccw != PIPE_POLYGON_MODE_FILL)
+      if (rast->fill_front != PIPE_POLYGON_MODE_FILL ||
+         rast->fill_back != PIPE_POLYGON_MODE_FILL)
         key.primitive = SF_UNFILLED_TRIS;
       else
         key.primitive = SF_TRIANGLES;
@@ -151,31 +180,34 @@ static int upload_sf_prog(struct brw_context *brw)
       break;
    }
 
-   key.do_point_sprite = brw->curr.rast->templ.point_sprite;
-   key.sprite_origin_lower_left = 0; /* XXX: ctx->Point.SpriteOrigin - fix rast state */
-   key.do_flat_shading = brw->curr.rast->templ.flatshade;
-   key.do_twoside_color = brw->curr.rast->templ.light_twoside;
+   key.do_point_sprite = rast->sprite_coord_enable ? 1 : 0;
+   key.sprite_origin_lower_left = (rast->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT);
+   key.point_coord_replace_attrs = rast->sprite_coord_enable;
+   key.do_flat_shading = rast->flatshade;
+   key.do_twoside_color = rast->light_twoside;
 
    if (key.do_twoside_color) {
-      key.frontface_ccw = (brw->curr.rast->templ.front_winding == 
-                          PIPE_WINDING_CCW);
+      key.frontface_ccw = rast->front_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;
+
+   ret = compile_sf_prog( brw, &key, &brw->sf.prog_bo );
+   if (ret)
+      return ret;
 
-   return 0;
+   return PIPE_OK;
 }
 
 
 const struct brw_tracked_state brw_sf_prog = {
    .dirty = {
-      .mesa  = (PIPE_NEW_RAST | PIPE_NEW_VERTEX_SHADER),
+      .mesa  = (PIPE_NEW_RAST | PIPE_NEW_FRAGMENT_SIGNATURE),
       .brw   = (BRW_NEW_REDUCED_PRIMITIVE),
       .cache = 0
    },