diff options
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_scene.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_scene.c | 248 |
1 files changed, 199 insertions, 49 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c index cba0e212985..72492c0f0ca 100644 --- a/src/gallium/drivers/llvmpipe/lp_scene.c +++ b/src/gallium/drivers/llvmpipe/lp_scene.c @@ -29,44 +29,67 @@ #include "util/u_memory.h" #include "util/u_inlines.h" #include "util/u_simple_list.h" +#include "util/u_surface.h" #include "lp_scene.h" +#include "lp_scene_queue.h" +#include "lp_debug.h" struct lp_scene * -lp_scene_create(void) +lp_scene_create( struct pipe_context *pipe, + struct lp_scene_queue *queue ) { + unsigned i, j; struct lp_scene *scene = CALLOC_STRUCT(lp_scene); - if (scene) - lp_scene_init(scene); + if (!scene) + return NULL; + + scene->pipe = pipe; + scene->empty_queue = queue; + + for (i = 0; i < TILES_X; i++) { + for (j = 0; j < TILES_Y; j++) { + struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); + bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block); + } + } + + scene->data.head = + scene->data.tail = CALLOC_STRUCT(data_block); + + make_empty_list(&scene->textures); + + pipe_mutex_init(scene->mutex); + return scene; } +/** + * Free all data associated with the given scene, and free(scene). + */ void lp_scene_destroy(struct lp_scene *scene) { - lp_scene_reset(scene); - lp_scene_free_bin_data(scene); - FREE(scene); -} + unsigned i, j; + lp_scene_reset(scene); -void -lp_scene_init(struct lp_scene *scene) -{ - unsigned i, j; for (i = 0; i < TILES_X; i++) for (j = 0; j < TILES_Y; j++) { struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); - bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block); + assert(bin->commands.head == bin->commands.tail); + FREE(bin->commands.head); + bin->commands.head = NULL; + bin->commands.tail = NULL; } - scene->data.head = - scene->data.tail = CALLOC_STRUCT(data_block); + FREE(scene->data.head); + scene->data.head = NULL; - make_empty_list(&scene->textures); + pipe_mutex_destroy(scene->mutex); - pipe_mutex_init(scene->mutex); + FREE(scene); } @@ -92,6 +115,9 @@ lp_scene_is_empty(struct lp_scene *scene ) } +/* Free data for one particular bin. May be called from the + * rasterizer thread(s). + */ void lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y) { @@ -115,7 +141,8 @@ lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y) /** - * Set scene to empty state. + * Free all the temporary data in a scene. May be called from the + * rasterizer thread(s). */ void lp_scene_reset(struct lp_scene *scene ) @@ -162,40 +189,8 @@ lp_scene_reset(struct lp_scene *scene ) } -/** - * Free all data associated with the given bin, but don't free(scene). - */ -void -lp_scene_free_bin_data(struct lp_scene *scene) -{ - unsigned i, j; - - for (i = 0; i < TILES_X; i++) - for (j = 0; j < TILES_Y; j++) { - struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); - /* lp_reset_scene() 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(scene->data.head); - scene->data.head = NULL; - - pipe_mutex_destroy(scene->mutex); -} - -void -lp_scene_set_framebuffer_size( struct lp_scene *scene, - unsigned width, unsigned height ) -{ - assert(lp_scene_is_empty(scene)); - scene->tiles_x = align(width, TILE_SIZE) / TILE_SIZE; - scene->tiles_y = align(height, TILE_SIZE) / TILE_SIZE; -} void @@ -393,3 +388,158 @@ end: pipe_mutex_unlock(scene->mutex); return bin; } + + +/** + * Prepare this scene for the rasterizer. + * Map the framebuffer surfaces. Initialize the 'rast' state. + */ +static boolean +lp_scene_map_buffers( struct lp_scene *scene ) +{ + struct pipe_screen *screen = scene->pipe->screen; + struct pipe_surface *cbuf, *zsbuf; + int i; + + LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__); + + + /* Map all color buffers + */ + for (i = 0; i < scene->fb.nr_cbufs; i++) { + cbuf = scene->fb.cbufs[i]; + if (cbuf) { + scene->cbuf_transfer[i] = screen->get_tex_transfer(screen, + cbuf->texture, + cbuf->face, + cbuf->level, + cbuf->zslice, + PIPE_TRANSFER_READ_WRITE, + 0, 0, + cbuf->width, + cbuf->height); + if (!scene->cbuf_transfer[i]) + goto fail; + + scene->cbuf_map[i] = screen->transfer_map(screen, + scene->cbuf_transfer[i]); + if (!scene->cbuf_map[i]) + goto fail; + } + } + + /* Map the zsbuffer + */ + zsbuf = scene->fb.zsbuf; + if (zsbuf) { + scene->zsbuf_transfer = screen->get_tex_transfer(screen, + zsbuf->texture, + zsbuf->face, + zsbuf->level, + zsbuf->zslice, + PIPE_TRANSFER_READ_WRITE, + 0, 0, + zsbuf->width, + zsbuf->height); + if (!scene->zsbuf_transfer) + goto fail; + + scene->zsbuf_map = screen->transfer_map(screen, + scene->zsbuf_transfer); + if (!scene->zsbuf_map) + goto fail; + } + + return TRUE; + +fail: + /* Unmap and release transfers? + */ + return FALSE; +} + + + +/** + * Called after rasterizer as finished rasterizing a scene. + * + * We want to call this from the pipe_context's current thread to + * avoid having to have mutexes on the transfer functions. + */ +static void +lp_scene_unmap_buffers( struct lp_scene *scene ) +{ + struct pipe_screen *screen = scene->pipe->screen; + unsigned i; + + for (i = 0; i < scene->fb.nr_cbufs; i++) { + if (scene->cbuf_map[i]) + screen->transfer_unmap(screen, scene->cbuf_transfer[i]); + + if (scene->cbuf_transfer[i]) + screen->tex_transfer_destroy(scene->cbuf_transfer[i]); + + scene->cbuf_transfer[i] = NULL; + scene->cbuf_map[i] = NULL; + } + + if (scene->zsbuf_map) + screen->transfer_unmap(screen, scene->zsbuf_transfer); + + if (scene->zsbuf_transfer) + screen->tex_transfer_destroy(scene->zsbuf_transfer); + + scene->zsbuf_transfer = NULL; + scene->zsbuf_map = NULL; + + util_unreference_framebuffer_state( &scene->fb ); +} + + +void lp_scene_begin_binning( struct lp_scene *scene, + struct pipe_framebuffer_state *fb ) +{ + assert(lp_scene_is_empty(scene)); + + util_copy_framebuffer_state(&scene->fb, fb); + + scene->tiles_x = align(fb->width, TILE_SIZE) / TILE_SIZE; + scene->tiles_y = align(fb->height, TILE_SIZE) / TILE_SIZE; +} + + +void lp_scene_rasterize( struct lp_scene *scene, + struct lp_rasterizer *rast, + boolean write_depth ) +{ + if (0) { + unsigned x, y; + debug_printf("rasterize scene:\n"); + debug_printf(" data size: %u\n", lp_scene_data_size(scene)); + for (y = 0; y < scene->tiles_y; y++) { + for (x = 0; x < scene->tiles_x; x++) { + debug_printf(" bin %u, %u size: %u\n", x, y, + lp_scene_bin_size(scene, x, y)); + } + } + } + + + scene->write_depth = (scene->fb.zsbuf != NULL && + write_depth); + + lp_scene_map_buffers( scene ); + + /* Enqueue the scene for rasterization, then immediately wait for + * it to finish. + */ + lp_rast_queue_scene( rast, scene ); + + /* Currently just wait for the rasterizer to finish. Some + * threading interactions need to be worked out, particularly once + * transfers become per-context: + */ + lp_rast_finish( rast ); + lp_scene_unmap_buffers( scene ); + lp_scene_enqueue( scene->empty_queue, scene ); +} |