summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/llvmpipe/lp_setup.c
diff options
context:
space:
mode:
authorKeith Whitwell <keithw@vmware.com>2009-10-08 15:44:29 +0100
committerKeith Whitwell <keithw@vmware.com>2009-10-08 15:46:29 +0100
commit931210424bc46b2c13919f0ac3e0ef781eff207e (patch)
tree26dc9949ca2bd6b5270784c3f699a5304e7f0cc7 /src/gallium/drivers/llvmpipe/lp_setup.c
parentd614ced756f2cca64ec83b122da4cd028c08c0eb (diff)
llvmpipe: wip me harder
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_setup.c')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_setup.c343
1 files changed, 278 insertions, 65 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index ac9bfad3f2..514366b71f 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -26,124 +26,337 @@
**************************************************************************/
/**
- * \brief Primitive rasterization/rendering (points, lines)
+ * Tiling engine.
*
- * \author Keith Whitwell <keith@tungstengraphics.com>
- * \author Brian Paul
+ * Builds per-tile display lists and executes them on calls to
+ * lp_setup_flush().
*/
-#include "lp_context.h"
-#include "lp_quad.h"
#include "lp_setup.h"
-#include "lp_state.h"
-#include "draw/draw_context.h"
-#include "draw/draw_private.h"
-#include "draw/draw_vertex.h"
-#include "pipe/p_shader_tokens.h"
-#include "pipe/p_thread.h"
#include "util/u_math.h"
#include "util/u_memory.h"
+void lp_setup_new_cmd_block( struct cmd_block_list *list )
+{
+ struct cmd_block *block = MALLOC_STRUCT(cmd_block);
+ list->tail->next = block;
+ list->tail = block;
+ block->next = NULL;
+ block->count = 0;
+}
-#define DEBUG_VERTS 0
+void lp_setup_new_data_block( struct data_block_list *list )
+{
+ struct data_block *block = MALLOC_STRUCT(data_block);
+ list->tail->next = block;
+ list->tail = block;
+ block->next = NULL;
+ block->used = 0;
+}
+static void reset_context( struct setup_context *setup )
+{
+ for (i = 0; i < setup->tiles_x; i++) {
+ for (j = 0; j < setup->tiles_y; j++) {
+ struct cmd_block_list *list = scene->tile[i][j];
+ struct cmd_block *block;
+ struct cmd_block *tmp;
+
+ for (block = list->first; block != list->tail; block = tmp) {
+ tmp = block->next;
+ FREE(block);
+ }
+
+ list->first = list->tail;
+ }
+ }
-void
-llvmpipe_setup_flush()
+ {
+ struct data_block_list *list = &scene->data;
+ struct data_block *block, *tmp;
+
+ for (block = list->first; block != list->tail; block = tmp) {
+ tmp = block->next;
+ FREE(block);
+ }
+
+ list->first = list->tail;
+ }
+}
+
+
+
+
+/* Add a command to all active bins.
+ */
+static void bin_everywhere( struct setup_context *setup,
+ bin_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++)
+ bin_cmd( setup, &setup->tile[i][j], cmd, arg );
}
-void
-llvmpipe_setup_bind_framebuffer()
+
+static void
+rasterize_bins( struct setup_context *setup,
+ struct lp_rast *rast,
+ boolean write_depth )
{
+ lp_rast_bind_color( rast,
+ scene->fb.color,
+ TRUE ); /* WRITE */
+
+ lp_rast_bind_depth( rast,
+ scene->fb.depth,
+ write_depth ); /* WRITE */
+
+ for (i = 0; i < scene->tiles_x; i++) {
+ for (j = 0; j < scene->tiles_y; j++) {
+
+ lp_rast_start_tile( rast,
+ i * TILESIZE,
+ j * TILESIZE );
+
+ for (block = scene->tile[i][j].first; block; block = block->next) {
+ for (k = 0; k < block->nr_cmds; k++) {
+ block->cmd[k].func( rast, block->cmd[k].arg );
+ }
+ }
+
+ lp_rast_finish_tile( rast );
+ }
+ }
+
+ lp_setup_free_data( setup );
}
-void
-llvmpipe_setup_clear()
+
+
+static void
+begin_binning( struct setup_context *setup )
{
+ if (setup->fb.color) {
+ if (setup->fb.clear_color)
+ bin_everywhere( setup,
+ lp_rast_clear_color,
+ &setup->clear_data );
+ else
+ bin_everywhere( setup,
+ lp_rast_load_color,
+ NULL );
+ }
+
+ if (setup->fb.zstencil) {
+ if (setup->fb.clear_zstencil)
+ bin_everywhere( setup,
+ lp_rast_clear_zstencil,
+ &setup->clear_data );
+ else
+ bin_everywhere( setup,
+ lp_rast_load_zstencil,
+ NULL );
+ }
}
-/* Stubs for lines & points for now:
+/* This basically bins and then flushes any outstanding full-screen
+ * clears.
+ *
+ * TODO: fast path for fullscreen clears and no triangles.
*/
-void
-llvmpipe_setup_point(struct setup_context *setup,
- const float (*v0)[4])
+static void
+execute_clears( struct setup_context *setup )
{
+ begin_binning( setup );
+ rasterize_bins( setup );
}
+
+static void
+set_state( struct setup_context *setup,
+ unsigned new_state )
+{
+ unsigned old_state = setup->state;
+
+ if (old_state == new_state)
+ return;
+
+ switch (new_state) {
+ case SETUP_ACTIVE:
+ if (old_state == SETUP_FLUSHED)
+ setup_begin_binning( setup );
+ break;
+
+ case SETUP_CLEARED:
+ if (old_state == SETUP_ACTIVE) {
+ assert(0);
+ return;
+ }
+ break;
+
+ case SETUP_FLUSHED:
+ if (old_state == SETUP_CLEAR)
+ execute_clears( setup );
+ else
+ rasterize_bins( setup );
+ break;
+ }
+
+ setup->state = new_state;
+}
+
+
void
-llvmpipe_setup_line(struct setup_context *setup,
- const float (*v0)[4],
- const float (*v1)[4])
+lp_setup_flush( struct setup_context *setup,
+ unsigned flags )
{
+ set_state( setup, SETUP_FLUSHED );
}
-/* Called after statechange, before emitting primitives. If binning
- * is active, this function should store relevant state in the binning
- * context.
- *
- * That includes:
- * - current fragment shader function
- * - bound constant buffer contents
- * - bound textures
- * - blend color
- * - etc.
- *
- * Basically everything needed at some point in the future to
- * rasterize triangles for the current state.
- *
- * Additionally this will set up the state needed for the rasterizer
- * to process and bin incoming triangles. That would include such
- * things as:
- * - cull mode
- * - ???
- * - etc.
- *
- */
-void setup_prepare( struct setup_context *setup )
+void
+lp_setup_bind_framebuffer( struct setup_context *setup,
+ struct pipe_surface *color,
+ struct pipe_surface *zstencil )
{
- struct llvmpipe_context *lp = setup->llvmpipe;
+ unsigned width, height;
- if (lp->dirty) {
- llvmpipe_update_derived(lp);
- }
+ set_state( setup, SETUP_FLUSHED );
+
+ pipe_surface_reference( &setup->fb.color, color );
+ pipe_surface_reference( &setup->fb.zstencil, zstencil );
+
+ width = MAX2( color->width, zstencil->width );
+ height = MAX2( color->height, zstencil->height );
+
+ setup->tiles_x = align( width, TILESIZE ) / TILESIZE;
+ setup->tiles_y = align( height, TILESIZE ) / TILESIZE;
+}
+
+void
+lp_setup_clear( struct setup_context *setup,
+ const float *clear_color,
+ double clear_depth,
+ unsigned clear_stencil,
+ unsigned flags )
+{
+ if (setup->state == SETUP_ACTIVE) {
+ struct lp_rast_clear_info *clear_info;
+ unsigned i, j;
+
+ clear_info = alloc_clear_info( setup );
- lp->quad.first->begin( lp->quad.first );
+ if (flags & PIPE_CLEAR_COLOR) {
+ pack_color( setup,
+ clear_info->color,
+ clear_color );
+ bin_everywhere(setup, lp_rast_clear_color, clear_info );
+ }
- if (lp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
- lp->rasterizer->fill_cw == PIPE_POLYGON_MODE_FILL &&
- lp->rasterizer->fill_ccw == PIPE_POLYGON_MODE_FILL) {
- /* we'll do culling */
- setup->winding = lp->rasterizer->cull_mode;
+ if (flags & PIPE_CLEAR_DEPTH_STENCIL) {
+ pack_depth_stencil( setup,
+ clear_info->depth,
+ clear_depth,
+ clear_stencil );
+
+ bin_everywhere(setup, lp_rast_clear_zstencil, clear_info );
+ }
}
else {
- /* 'draw' will do culling */
- setup->winding = PIPE_WINDING_NONE;
+ set_state( setup, SETUP_CLEARED );
+ setup->clear.flags |= flags;
+
+ if (flags & PIPE_CLEAR_COLOR) {
+ memcpy(setup->clear.color, color, sizeof setup->clear.color);
+ }
+
+ if (flags & PIPE_CLEAR_DEPTH_STENCIL) {
+ setup->clear.depth = clear_depth;
+ setup->clear.stencil = clear_stencil;
+ }
}
+}
+
+
+void
+lp_setup_set_fs_inputs( struct setup_context *setup,
+ const enum lp_interp *interp,
+ unsigned nr )
+{
+ memcpy( setup->interp, interp, nr * sizeof interp[0] );
+}
- setup_prepare_tri( setup->llvmpipe );
+
+static void
+first_triangle( struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4])
+{
+ set_state( setup, STATE_ACTIVE );
+ setup_choose_triangle( setup, v0, v1, v2 );
+}
+
+
+
+/* Stubs for lines & points for now:
+ */
+void
+lp_setup_point(struct setup_context *setup,
+ const float (*v0)[4])
+{
+ setup->point( setup, v0 );
}
+void
+lp_setup_line(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4])
+{
+ setup->line( setup, v0, v1 );
+}
+
+void
+lp_setup_triangle(struct setup_context *setup,
+ const float (*v0)[4],
+ const float (*v1)[4],
+ const float (*v2)[4])
+{
+ setup->triangle( setup, v0, v1, v2 );
+}
void setup_destroy_context( struct setup_context *setup )
{
+ lp_rast_destroy( setup->rast );
FREE( setup );
}
/**
- * Create a new primitive setup/render stage.
+ * Create a new primitive tiling engine. Currently also creates a
+ * rasterizer to use with it.
*/
-struct setup_context *setup_create_context( struct llvmpipe_context *llvmpipe )
+struct setup_context *setup_create_context( void )
{
struct setup_context *setup = CALLOC_STRUCT(setup_context);
- unsigned i;
- setup->llvmpipe = llvmpipe;
+ setup->rast = lp_rast_create( void );
+ if (!setup->rast)
+ goto fail;
+
+ for (i = 0; i < TILES_X; i++)
+ for (j = 0; j < TILES_Y; j++)
+ setup->tile[i][j].first =
+ setup->tile[i][j].next = CALLOC_STRUCT(cmd_block);
return setup;
+
+fail:
+ FREE(setup);
+ return NULL;
}