Mesa (lp-binning): llvmpipe: reorganization of binning data structions and funtions

Brian Paul brianp at kemper.freedesktop.org
Fri Dec 4 15:02:57 PST 2009


Module: Mesa
Branch: lp-binning
Commit: 01b1900084152dbacd4025a31ced25f75666ce59
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=01b1900084152dbacd4025a31ced25f75666ce59

Author: Brian Paul <brianp at vmware.com>
Date:   Fri Dec  4 15:31:09 2009 -0700

llvmpipe: reorganization of binning data structions and funtions

New lp_bins struct contains all bin information.
More move bin-related code into lp_bin.[ch]
Use new/updated bin-access functions to hide implementation details.
The result is more/cleaner separation between the setup and rast components.
This will make double-buffering of the bins easier, etc.

---

 src/gallium/drivers/llvmpipe/lp_bin.c           |   78 +++++++++++++++++++
 src/gallium/drivers/llvmpipe/lp_bin.h           |   61 +++++++++++++--
 src/gallium/drivers/llvmpipe/lp_rast.c          |   51 +++++++++++--
 src/gallium/drivers/llvmpipe/lp_rast.h          |   21 ++----
 src/gallium/drivers/llvmpipe/lp_setup.c         |   93 +++-------------------
 src/gallium/drivers/llvmpipe/lp_setup_context.h |   17 +----
 src/gallium/drivers/llvmpipe/lp_setup_tri.c     |   26 +++---
 7 files changed, 209 insertions(+), 138 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_bin.c b/src/gallium/drivers/llvmpipe/lp_bin.c
index f43cdcb..1f05416 100644
--- a/src/gallium/drivers/llvmpipe/lp_bin.c
+++ b/src/gallium/drivers/llvmpipe/lp_bin.c
@@ -30,6 +30,84 @@
 
 
 void
+lp_init_bins(struct lp_bins *bins)
+{
+   unsigned i, j;
+   for (i = 0; i < TILES_X; i++)
+      for (j = 0; j < TILES_Y; j++) {
+         struct cmd_bin *bin = lp_get_bin(bins, i, j);
+         bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block);
+      }
+
+   bins->data.head =
+      bins->data.tail = CALLOC_STRUCT(data_block);
+}
+
+
+void
+lp_reset_bins(struct lp_bins *bins, unsigned tiles_x, unsigned tiles_y)
+{
+   unsigned i, j;
+
+   /* Free all but last binner command lists:
+    */
+   for (i = 0; i < tiles_x; i++) {
+      for (j = 0; j < tiles_y; j++) {
+         struct cmd_bin *bin = lp_get_bin(bins, i, j);
+         struct cmd_block_list *list = &bin->commands;
+         struct cmd_block *block;
+         struct cmd_block *tmp;
+         
+         for (block = list->head; block != list->tail; block = tmp) {
+            tmp = block->next;
+            FREE(block);
+         }
+         
+         assert(list->tail->next == NULL);
+         list->head = list->tail;
+         list->head->count = 0;
+      }
+   }
+
+   /* Free all but last binned data block:
+    */
+   {
+      struct data_block_list *list = &bins->data;
+      struct data_block *block, *tmp;
+
+      for (block = list->head; block != list->tail; block = tmp) {
+         tmp = block->next;
+         FREE(block);
+      }
+         
+      assert(list->tail->next == NULL);
+      list->head = list->tail;
+      list->head->used = 0;
+   }
+}
+
+
+void
+lp_free_bin_data(struct lp_bins *bins)
+{
+   unsigned i, j;
+
+   for (i = 0; i < TILES_X; i++)
+      for (j = 0; j < TILES_Y; j++) {
+         struct cmd_bin *bin = lp_get_bin(bins, i, j);
+         /* lp_reset_bins() should have been already called */
+         assert(bin->commands.head == bin->commands.tail);
+         FREE(bin->commands.head);
+         bin->commands.head = NULL;
+         bin->commands.tail = NULL;
+      }
+
+   FREE(bins->data.head);
+   bins->data.head = NULL;
+}
+
+
+void
 lp_bin_new_cmd_block( struct cmd_block_list *list )
 {
    struct cmd_block *block = MALLOC_STRUCT(cmd_block);
diff --git a/src/gallium/drivers/llvmpipe/lp_bin.h b/src/gallium/drivers/llvmpipe/lp_bin.h
index fa25d78..4d12b93 100644
--- a/src/gallium/drivers/llvmpipe/lp_bin.h
+++ b/src/gallium/drivers/llvmpipe/lp_bin.h
@@ -35,9 +35,19 @@
 #ifndef LP_BIN_H
 #define LP_BIN_H
 
+#include "lp_tile_soa.h"
 #include "lp_rast.h"
 
 
+/* We're limited to 2K by 2K for 32bit fixed point rasterization.
+ * Will need a 64-bit version for larger framebuffers.
+ */
+#define MAXHEIGHT 2048
+#define MAXWIDTH 2048
+#define TILES_X (MAXWIDTH / TILE_SIZE)
+#define TILES_Y (MAXHEIGHT / TILE_SIZE)
+
+
 #define CMD_BLOCK_MAX 128
 #define DATA_BLOCK_SIZE (16 * 1024 - sizeof(unsigned) - sizeof(void *))
    
@@ -84,19 +94,40 @@ struct data_block_list {
 };
 
 
+/**
+ * All bins and bin data are contained here.
+ * Per-bin data goes into the 'tile' bins.
+ * Shared bin data goes into the 'data' buffer.
+ * When there are multiple threads, will want to double-buffer the
+ * bin arrays:
+ */
+struct lp_bins {
+   struct cmd_bin tile[TILES_X][TILES_Y];
+   struct data_block_list data;
+};
+
+
+
+void lp_init_bins(struct lp_bins *bins);
 
-extern void lp_bin_new_data_block( struct data_block_list *list );
+void lp_reset_bins(struct lp_bins *bins, unsigned tiles_x, unsigned tiles_y);
 
-extern void lp_bin_new_cmd_block( struct cmd_block_list *list );
+void lp_free_bin_data(struct lp_bins *bins);
+
+void lp_bin_new_data_block( struct data_block_list *list );
+
+void lp_bin_new_cmd_block( struct cmd_block_list *list );
 
 
 /**
- * Allocate space for a command/data in the given block list.
+ * Allocate space for a command/data in the bin's data buffer.
  * Grow the block list if needed.
  */
 static INLINE void *
-lp_bin_alloc( struct data_block_list *list, unsigned size)
+lp_bin_alloc( struct lp_bins *bins, unsigned size)
 {
+   struct data_block_list *list = &bins->data;
+
    if (list->tail->used + size > DATA_BLOCK_SIZE) {
       lp_bin_new_data_block( list );
    }
@@ -114,9 +145,11 @@ lp_bin_alloc( struct data_block_list *list, unsigned size)
  * As above, but with specific alignment.
  */
 static INLINE void *
-lp_bin_alloc_aligned( struct data_block_list *list, unsigned size,
+lp_bin_alloc_aligned( struct lp_bins *bins, unsigned size,
                       unsigned alignment )
 {
+   struct data_block_list *list = &bins->data;
+
    if (list->tail->used + size + alignment - 1 > DATA_BLOCK_SIZE) {
       lp_bin_new_data_block( list );
    }
@@ -134,20 +167,32 @@ lp_bin_alloc_aligned( struct data_block_list *list, unsigned size,
 /* Put back data if we decide not to use it, eg. culled triangles.
  */
 static INLINE void
-lp_bin_putback_data( struct data_block_list *list, unsigned size)
+lp_bin_putback_data( struct lp_bins *bins, unsigned size)
 {
+   struct data_block_list *list = &bins->data;
    assert(list->tail->used >= size);
    list->tail->used -= size;
 }
 
 
-/* Add a command to a given bin.
+/** Return pointer to a particular tile's bin. */
+static INLINE struct cmd_bin *
+lp_get_bin(struct lp_bins *bins, unsigned x, unsigned y)
+{
+   return &bins->tile[x][y];
+}
+
+
+
+/* Add a command to bin[x][y].
  */
 static INLINE void
-lp_bin_command( struct cmd_bin *bin,
+lp_bin_command( struct lp_bins *bins,
+                unsigned x, unsigned y,
                 lp_rast_cmd cmd,
                 union lp_rast_cmd_arg arg )
 {
+   struct cmd_bin *bin = lp_get_bin(bins, x, y);
    struct cmd_block_list *list = &bin->commands;
 
    if (list->tail->count == CMD_BLOCK_MAX) {
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index a466aec..87e3bfc 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -56,7 +56,8 @@ struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen )
  * Begin the rasterization phase.
  * Map the framebuffer surfaces.  Initialize the 'rast' state.
  */
-boolean lp_rast_begin( struct lp_rasterizer *rast,
+static boolean
+lp_rast_begin( struct lp_rasterizer *rast,
                        struct pipe_surface *cbuf,
                        struct pipe_surface *zsbuf,
                        boolean write_color,
@@ -121,7 +122,8 @@ boolean lp_rast_begin( struct lp_rasterizer *rast,
  * Finish the rasterization phase.
  * Unmap framebuffer surfaces.
  */
-void lp_rast_end( struct lp_rasterizer *rast )
+static void
+lp_rast_end( struct lp_rasterizer *rast )
 {
    struct pipe_screen *screen = rast->screen;
 
@@ -469,12 +471,13 @@ lp_rast_end_tile( struct lp_rasterizer *rast )
 
 /**
  * Rasterize commands for a single bin.
+ * \param x, y  position of the bin's tile in the framebuffer
  * Must be called between lp_rast_begin() and lp_rast_end().
  */
-void
-lp_rasterize_bin( struct lp_rasterizer *rast,
-                  const struct cmd_bin *bin,
-                  int x, int y)
+static void
+rasterize_bin( struct lp_rasterizer *rast,
+               const struct cmd_bin *bin,
+               int x, int y)
 {
    const struct cmd_block_list *commands = &bin->commands;
    struct cmd_block *block;
@@ -493,6 +496,42 @@ lp_rasterize_bin( struct lp_rasterizer *rast,
 }
 
 
+/**
+ * Rasterize/execute all bins.
+ */
+void
+lp_rasterize_bins( struct lp_rasterizer *rast,
+                   struct lp_bins *bins,
+                   unsigned tiles_x, unsigned tiles_y,
+                   const struct pipe_framebuffer_state *fb,
+                   bool write_depth )
+{
+   unsigned i, j;
+
+   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
+
+   lp_rast_begin( rast,
+                  fb->cbufs[0], 
+                  fb->zsbuf,
+                  fb->cbufs[0] != NULL,
+                  fb->zsbuf != NULL && write_depth,
+                  fb->width,
+                  fb->height );
+                       
+   /* loop over tile bins, rasterize each */
+   for (i = 0; i < tiles_x; i++) {
+      for (j = 0; j < tiles_y; j++) {
+         struct cmd_bin *bin = lp_get_bin(bins, i, j);
+         rasterize_bin( rast, bin, i * TILE_SIZE, j * TILE_SIZE );
+      }
+   }
+
+   lp_rast_end( rast );
+
+   LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
+}
+
+
 
 /* Shutdown:
  */
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index 3d2388b..e623eaf 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -47,6 +47,7 @@
  * individual function calls like this.
  */
 struct lp_rasterizer;
+struct lp_bins;
 struct cmd_bin;
 struct pipe_screen;
 
@@ -133,22 +134,12 @@ struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen );
 
 void lp_rast_destroy( struct lp_rasterizer * );
 
+void lp_rasterize_bins( struct lp_rasterizer *rast,
+                        struct lp_bins *bins,
+                        unsigned tiles_x, unsigned tiles_y,
+                        const struct pipe_framebuffer_state *fb,
+                        bool write_depth );
 
-boolean lp_rast_begin( struct lp_rasterizer *rast,
-                       struct pipe_surface *cbuf,
-                       struct pipe_surface *zsbuf,
-                       boolean write_color,
-                       boolean write_zstencil,
-                       unsigned width,
-                       unsigned height );
-
-void
-lp_rasterize_bin( struct lp_rasterizer *rast,
-                  const struct cmd_bin *bin,
-                  int x, int y);
-
-
-void lp_rast_end( struct lp_rasterizer * );
 
 
 union lp_rast_cmd_arg {
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 47d2ac8..efaf5ac 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -80,8 +80,6 @@ first_point( struct setup_context *setup,
 
 static void reset_context( struct setup_context *setup )
 {
-   unsigned i, j;
-
    LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 
    /* Reset derived state */
@@ -90,40 +88,7 @@ static void reset_context( struct setup_context *setup )
    setup->fs.stored = NULL;
    setup->dirty = ~0;
 
-   /* Free all but last binner command lists:
-    */
-   for (i = 0; i < setup->tiles_x; i++) {
-      for (j = 0; j < setup->tiles_y; j++) {
-         struct cmd_block_list *list = &setup->tile[i][j].commands;
-         struct cmd_block *block;
-         struct cmd_block *tmp;
-         
-         for (block = list->head; block != list->tail; block = tmp) {
-            tmp = block->next;
-            FREE(block);
-         }
-         
-         assert(list->tail->next == NULL);
-         list->head = list->tail;
-         list->head->count = 0;
-      }
-   }
-
-   /* Free all but last binned data block:
-    */
-   {
-      struct data_block_list *list = &setup->data;
-      struct data_block *block, *tmp;
-
-      for (block = list->head; block != list->tail; block = tmp) {
-         tmp = block->next;
-         FREE(block);
-      }
-         
-      assert(list->tail->next == NULL);
-      list->head = list->tail;
-      list->head->used = 0;
-   }
+   lp_reset_bins(&setup->bins, setup->tiles_x, setup->tiles_y);
 
    /* Reset some state:
     */
@@ -177,7 +142,7 @@ static void bin_everywhere( struct setup_context *setup,
    unsigned i, j;
    for (i = 0; i < setup->tiles_x; i++)
       for (j = 0; j < setup->tiles_y; j++)
-         lp_bin_command( &setup->tile[i][j], cmd, arg );
+         lp_bin_command( &setup->bins, i, j, cmd, arg );
 }
 
 
@@ -194,13 +159,13 @@ bin_state_command( struct setup_context *setup,
    unsigned i, j;
    for (i = 0; i < setup->tiles_x; i++) {
       for (j = 0; j < setup->tiles_y; j++) {
-         struct cmd_bin *bin = &setup->tile[i][j];
+         struct cmd_bin *bin = &setup->bins.tile[i][j];
          lp_rast_cmd last_cmd = lp_get_last_command(bin);
          if (last_cmd == cmd) {
             lp_replace_last_command_arg(bin, arg);
          }
          else {
-            lp_bin_command( bin, cmd, arg );
+            lp_bin_command( &setup->bins, i, j, cmd, arg );
          }
       }
    }
@@ -212,29 +177,10 @@ static void
 rasterize_bins( struct setup_context *setup,
                 boolean write_depth )
 {
-   struct lp_rasterizer *rast = setup->rast;
-   unsigned i, j;
-
-   LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
-
-   lp_rast_begin( rast,
-                  setup->fb->cbufs[0], 
-                  setup->fb->zsbuf,
-                  setup->fb->cbufs[0] != NULL,
-                  setup->fb->zsbuf != NULL && write_depth,
-                  setup->fb->width,
-                  setup->fb->height );
-                       
-   /* loop over tile bins, rasterize each */
-   for (i = 0; i < setup->tiles_x; i++) {
-      for (j = 0; j < setup->tiles_y; j++) {
-         lp_rasterize_bin( rast, &setup->tile[i][j], 
-                           i * TILE_SIZE,
-                           j * TILE_SIZE );
-      }
-   }
-
-   lp_rast_end( rast );
+   lp_rasterize_bins(setup->rast,
+                     &setup->bins, setup->tiles_x, setup->tiles_y,
+                     setup->fb,
+                     write_depth);
 
    reset_context( setup );
 
@@ -559,7 +505,7 @@ lp_setup_update_shader_state( struct setup_context *setup )
       uint8_t *stored;
       unsigned i, j;
 
-      stored = lp_bin_alloc_aligned(&setup->data, 4 * 16, 16);
+      stored = lp_bin_alloc_aligned(&setup->bins, 4 * 16, 16);
 
       /* smear each blend color component across 16 ubyte elements */
       for (i = 0; i < 4; ++i) {
@@ -591,7 +537,7 @@ lp_setup_update_shader_state( struct setup_context *setup )
                    current_size) != 0) {
             void *stored;
 
-            stored = lp_bin_alloc(&setup->data, current_size);
+            stored = lp_bin_alloc(&setup->bins, current_size);
             if(stored) {
                memcpy(stored,
                       current_data,
@@ -621,7 +567,7 @@ lp_setup_update_shader_state( struct setup_context *setup )
           * and append it to the bin's setup data buffer.
           */
          struct lp_rast_state *stored =
-            (struct lp_rast_state *) lp_bin_alloc(&setup->data, sizeof *stored);
+            (struct lp_rast_state *) lp_bin_alloc(&setup->bins, sizeof *stored);
          if(stored) {
             memcpy(stored,
                    &setup->fs.current,
@@ -677,17 +623,11 @@ lp_setup_tri(struct setup_context *setup,
 void 
 lp_setup_destroy( struct setup_context *setup )
 {
-   unsigned i, j;
-
    reset_context( setup );
 
    pipe_buffer_reference(&setup->constants.current, NULL);
 
-   for (i = 0; i < TILES_X; i++)
-      for (j = 0; j < TILES_Y; j++)
-         FREE(setup->tile[i][j].commands.head);
-
-   FREE(setup->data.head);
+   lp_free_bin_data(&setup->bins);
 
    lp_rast_destroy( setup->rast );
    FREE( setup );
@@ -702,19 +642,12 @@ struct setup_context *
 lp_setup_create( struct pipe_screen *screen )
 {
    struct setup_context *setup = CALLOC_STRUCT(setup_context);
-   unsigned i, j;
 
    setup->rast = lp_rast_create( screen );
    if (!setup->rast) 
       goto fail;
 
-   for (i = 0; i < TILES_X; i++)
-      for (j = 0; j < TILES_Y; j++)
-         setup->tile[i][j].commands.head = 
-            setup->tile[i][j].commands.tail = CALLOC_STRUCT(cmd_block);
-
-   setup->data.head =
-      setup->data.tail = CALLOC_STRUCT(data_block);
+   lp_init_bins(&setup->bins);
 
    setup->triangle = first_triangle;
    setup->line     = first_line;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index dc12eb7..8478bb9 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -40,14 +40,6 @@
 #include "lp_tile_soa.h"        /* for TILE_SIZE */
 #include "lp_bin.h"
 
-/* We're limited to 2K by 2K for 32bit fixed point rasterization.
- * Will need a 64-bit version for larger framebuffers.
- */
-#define MAXHEIGHT 2048
-#define MAXWIDTH 2048
-#define TILES_X (MAXWIDTH / TILE_SIZE)
-#define TILES_Y (MAXHEIGHT / TILE_SIZE)
-
 
 #define LP_SETUP_NEW_FS          0x01
 #define LP_SETUP_NEW_CONSTANTS   0x02
@@ -63,14 +55,7 @@ struct setup_context {
 
    struct lp_rasterizer *rast;
 
-   /**
-    * Per-bin data goes into the 'tile' bins.
-    * Shared bin data goes into the 'data' buffer.
-    * When there are multiple threads, will want to double-buffer the
-    * bin arrays:
-    */
-   struct cmd_bin tile[TILES_X][TILES_Y];
-   struct data_block_list data;
+   struct lp_bins bins;
 
    /* size of framebuffer, in tiles */
    unsigned tiles_x;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
index 5e53b40..b8f7984 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c
@@ -185,9 +185,9 @@ static void setup_tri_coefficients( struct setup_context *setup,
    {
       unsigned bytes;
       bytes = (setup->fs.nr_inputs + 1) * 4 * sizeof(float);
-      tri->inputs.a0   = lp_bin_alloc_aligned( &setup->data, bytes, 16 );
-      tri->inputs.dadx = lp_bin_alloc_aligned( &setup->data, bytes, 16 );
-      tri->inputs.dady = lp_bin_alloc_aligned( &setup->data, bytes, 16 );
+      tri->inputs.a0   = lp_bin_alloc_aligned( &setup->bins, bytes, 16 );
+      tri->inputs.dadx = lp_bin_alloc_aligned( &setup->bins, bytes, 16 );
+      tri->inputs.dady = lp_bin_alloc_aligned( &setup->bins, bytes, 16 );
    }
 
    /* The internal position input is in slot zero:
@@ -263,7 +263,7 @@ do_triangle_ccw(struct setup_context *setup,
    const int y2 = subpixel_snap(v2[0][1]);
    const int y3 = subpixel_snap(v3[0][1]);
 
-   struct lp_rast_triangle *tri = lp_bin_alloc( &setup->data, sizeof *tri );
+   struct lp_rast_triangle *tri = lp_bin_alloc( &setup->bins, sizeof *tri );
    float area, oneoverarea;
    int minx, maxx, miny, maxy;
 
@@ -283,7 +283,7 @@ do_triangle_ccw(struct setup_context *setup,
     * XXX: subject to overflow??
     */
    if (area <= 0) {
-      lp_bin_putback_data( &setup->data, sizeof *tri );
+      lp_bin_putback_data( &setup->bins, sizeof *tri );
       return;
    }
 
@@ -295,7 +295,7 @@ do_triangle_ccw(struct setup_context *setup,
    
    if (tri->miny == tri->maxy || 
        tri->minx == tri->maxx) {
-      lp_bin_putback_data( &setup->data, sizeof *tri );
+      lp_bin_putback_data( &setup->bins, sizeof *tri );
       return;
    }
 
@@ -405,7 +405,7 @@ do_triangle_ccw(struct setup_context *setup,
    {
       /* Triangle is contained in a single tile:
        */
-      lp_bin_command( &setup->tile[minx][miny], lp_rast_triangle, 
+      lp_bin_command( &setup->bins, minx, miny, lp_rast_triangle, 
                    lp_rast_arg_triangle(tri) );
    }
    else 
@@ -464,17 +464,17 @@ do_triangle_ccw(struct setup_context *setup,
 	    {
 	       in = 1;
                /* triangle covers the whole tile- shade whole tile */
-               lp_bin_command( &setup->tile[x][y],
-                            lp_rast_shade_tile,
-                            lp_rast_arg_inputs(&tri->inputs) );
+               lp_bin_command( &setup->bins, x, y,
+                               lp_rast_shade_tile,
+                               lp_rast_arg_inputs(&tri->inputs) );
 	    }
 	    else 
 	    { 
 	       in = 1;
                /* shade partial tile */
-               lp_bin_command( &setup->tile[x][y], 
-                            lp_rast_triangle, 
-                            lp_rast_arg_triangle(tri) );
+               lp_bin_command( &setup->bins, x, y,
+                               lp_rast_triangle, 
+                               lp_rast_arg_triangle(tri) );
 	    }
 
 	    /* Iterate cx values across the region:



More information about the mesa-commit mailing list