diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index d5fe6e93699..8f37a28e875 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -237,9 +237,10 @@ void lp_rast_set_state( struct lp_rasterizer *rast, { const struct lp_rast_state *state = arg.set_state; - RAST_DEBUG("%s\n", __FUNCTION__); + RAST_DEBUG("%s %p\n", __FUNCTION__, (void *) state); - /* XXX to do */ + /* just set the current state pointer for this rasterizer */ + rast->current_state = state; } @@ -279,7 +280,7 @@ void lp_rast_shade_quads( struct lp_rasterizer *rast, unsigned mask) { #if 1 - const struct lp_rast_state *state = inputs->state; + const struct lp_rast_state *state = rast->current_state; struct lp_rast_tile *tile = &rast->tile; void *color; void *depth; @@ -287,6 +288,8 @@ void lp_rast_shade_quads( struct lp_rasterizer *rast, unsigned ix, iy; int block_offset; + assert(state); + /* Sanity checks */ assert(x % TILE_VECTOR_WIDTH == 0); assert(y % TILE_VECTOR_HEIGHT == 0); diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h index 435993d44d2..e9a1fa49add 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.h +++ b/src/gallium/drivers/llvmpipe/lp_rast.h @@ -55,18 +55,13 @@ struct lp_rast_state { }; -/* Coefficients necessary to run the shader at a given location: + +/** + * Coefficients necessary to run the shader at a given location. + * First coefficient is position. + * These pointers point into the bin data buffer. */ struct lp_rast_shader_inputs { - - /* Current rasterizer state: - */ - const struct lp_rast_state *state; - - /* Attribute interpolation: - * First coefficient is position. - * These pointers point into the bin data buffer. - */ float (*a0)[4]; float (*dadx)[4]; float (*dady)[4]; diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h index 4c0dfe2282d..98111edff72 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h +++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h @@ -86,6 +86,8 @@ struct lp_rasterizer unsigned y; unsigned mask; } blocks[256]; + + const struct lp_rast_state *current_state; }; diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index fc7f4f6778e..11a9fd2637c 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -155,6 +155,34 @@ static void reset_context( struct setup_context *setup ) } +/** + * Return last command in the bin + */ +static lp_rast_cmd +lp_get_last_command( const struct cmd_bin *bin ) +{ + const struct cmd_block *tail = bin->commands.tail; + const unsigned i = tail->count; + if (i > 0) + return tail->cmd[i - 1]; + else + return NULL; +} + + +/** + * Replace the arg of the last command in the bin. + */ +static void +lp_replace_last_command_arg( struct cmd_bin *bin, + const union lp_rast_cmd_arg arg ) +{ + struct cmd_block *tail = bin->commands.tail; + const unsigned i = tail->count; + assert(i > 0); + tail->arg[i - 1] = arg; +} + /* Add a command to all active bins. @@ -170,6 +198,32 @@ static void bin_everywhere( struct setup_context *setup, } +/** + * Put a state-change command into all bins. + * If we find that the last command in a bin was also a state-change + * command, we can simply replace that one with the new one. + */ +static void +bin_state_command( struct setup_context *setup, + lp_rast_cmd cmd, + const union lp_rast_cmd_arg arg ) +{ + 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]; + lp_rast_cmd last_cmd = lp_get_last_command(bin); + if (last_cmd == cmd) { + lp_replace_last_command_arg(bin, arg); + } + else { + bin_command( bin, cmd, arg ); + } + } + } +} + + /** Rasterize commands for a single bin */ static void rasterize_bin( struct lp_rasterizer *rast, @@ -234,31 +288,6 @@ begin_binning( struct setup_context *setup ) { SETUP_DEBUG("%s\n", __FUNCTION__); - if (!setup->fb.cbuf && !setup->fb.zsbuf) { - setup->fb.width = 0; - setup->fb.height = 0; - } - else if (!setup->fb.zsbuf) { - setup->fb.width = setup->fb.cbuf->width; - setup->fb.height = setup->fb.cbuf->height; - } - else if (!setup->fb.cbuf) { - setup->fb.width = setup->fb.zsbuf->width; - setup->fb.height = setup->fb.zsbuf->height; - } - else { - /* XXX: not sure what we're really supposed to do for - * mis-matched color & depth buffer sizes. - */ - setup->fb.width = MIN2(setup->fb.cbuf->width, - setup->fb.zsbuf->width); - setup->fb.height = MIN2(setup->fb.cbuf->height, - setup->fb.zsbuf->height); - } - - setup->tiles_x = align(setup->fb.width, TILE_SIZE) / TILE_SIZE; - setup->tiles_y = align(setup->fb.height, TILE_SIZE) / TILE_SIZE; - if (setup->fb.cbuf) { if (setup->clear.flags & PIPE_CLEAR_COLOR) bin_everywhere( setup, @@ -352,8 +381,34 @@ lp_setup_bind_framebuffer( struct setup_context *setup, pipe_surface_reference( &setup->fb.cbuf, color ); pipe_surface_reference( &setup->fb.zsbuf, zstencil ); + + if (!setup->fb.cbuf && !setup->fb.zsbuf) { + setup->fb.width = 0; + setup->fb.height = 0; + } + else if (!setup->fb.zsbuf) { + setup->fb.width = setup->fb.cbuf->width; + setup->fb.height = setup->fb.cbuf->height; + } + else if (!setup->fb.cbuf) { + setup->fb.width = setup->fb.zsbuf->width; + setup->fb.height = setup->fb.zsbuf->height; + } + else { + /* XXX: not sure what we're really supposed to do for + * mis-matched color & depth buffer sizes. + */ + setup->fb.width = MIN2(setup->fb.cbuf->width, + setup->fb.zsbuf->width); + setup->fb.height = MIN2(setup->fb.cbuf->height, + setup->fb.zsbuf->height); + } + + setup->tiles_x = align(setup->fb.width, TILE_SIZE) / TILE_SIZE; + setup->tiles_y = align(setup->fb.height, TILE_SIZE) / TILE_SIZE; } + void lp_setup_clear( struct setup_context *setup, const float *color, @@ -608,12 +663,10 @@ lp_setup_update_shader_state( struct setup_context *setup ) sizeof setup->fs.current); setup->fs.stored = stored; -#if 0 /* put the state-set command into all bins */ - bin_everywhere( setup, - lp_rast_set_state, - *setup->fs.stored ); -#endif + bin_state_command( setup, + lp_rast_set_state, + lp_rast_arg_state(setup->fs.stored) ); } } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h index 1715048f760..7c7c34f3f76 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_context.h +++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h @@ -76,10 +76,14 @@ struct cmd_block_list { */ struct cmd_bin { struct cmd_block_list commands; - struct lp_rast_state *curr_state; }; +/** + * This stores bulk data which is shared by all bins. + * Examples include triangle data and state data. The commands in + * the per-tile bins will point to chunks of data in this structure. + */ struct data_block_list { struct data_block *head; struct data_block *tail; @@ -241,5 +245,4 @@ static INLINE void bin_command( struct cmd_bin *bin, } - #endif diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index 74ed0a9e8fb..48733a599b7 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -295,8 +295,6 @@ do_triangle_ccw(struct setup_context *setup, return; } - tri->inputs.state = setup->fs.stored; - /* */ tri->oneoverarea = ((float)FIXED_ONE) / (float)area;