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.
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 @@
};
+/**
+ * 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;
+};
-extern void lp_bin_new_data_block( struct data_block_list *list );
-extern void lp_bin_new_cmd_block( struct cmd_block_list *list );
+
+void lp_init_bins(struct lp_bins *bins);
+
+void lp_reset_bins(struct lp_bins *bins, unsigned tiles_x, unsigned tiles_y);
+
+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 @@
* 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 @@
/* 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 @@
* 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 @@
* 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 @@
/**
* 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 @@
}
+/**
+ * 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
* 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 @@
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 @@
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 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 @@
{
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 @@
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 @@
* 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 @@
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 @@
{
/* 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 @@
{
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: