llvmpipe: reorganize transfer usage

Move transfer creation and mapping to the "scene" object, and out of
the rasterizer.  The rasterizer operates on already-mapped
framebuffers only, and no longer needs a screen or context pointer.

The scene object has access to a pipe_context, and this reorg prepares
for moving transfer functionality from the screen to the context.
This commit is contained in:
Keith Whitwell
2010-03-02 14:41:35 +00:00
parent 8417528e3a
commit 5fe2ce28b6
8 changed files with 384 additions and 329 deletions
+1 -1
View File
@@ -183,7 +183,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
if (debug_get_bool_option( "LP_NO_RAST", FALSE ))
llvmpipe->no_rast = TRUE;
llvmpipe->setup = lp_setup_create( screen,
llvmpipe->setup = lp_setup_create( &llvmpipe->pipe,
llvmpipe->draw );
if (!llvmpipe->setup)
goto fail;
+94 -216
View File
@@ -42,114 +42,60 @@
#include "lp_scene.h"
/**
* Begin the rasterization phase.
* Map the framebuffer surfaces. Initialize the 'rast' state.
/* Begin rasterizing a scene:
*/
static boolean
lp_rast_begin( struct lp_rasterizer *rast,
const struct pipe_framebuffer_state *fb,
boolean write_color,
boolean write_zstencil )
struct lp_scene *scene )
{
struct pipe_screen *screen = rast->screen;
struct pipe_surface *cbuf, *zsbuf;
const struct pipe_framebuffer_state *fb = &scene->fb;
boolean write_color = fb->nr_cbufs != 0;
boolean write_zstencil = fb->zsbuf != NULL;
int i;
rast->curr_scene = scene;
LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
util_copy_framebuffer_state(&rast->state.fb, fb);
rast->state.nr_cbufs = scene->fb.nr_cbufs;
rast->state.write_zstencil = write_zstencil;
rast->state.write_color = write_color;
rast->check_for_clipped_tiles = (fb->width % TILE_SIZE != 0 ||
fb->height % TILE_SIZE != 0);
for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
cbuf = rast->state.fb.cbufs[i];
if (cbuf) {
rast->cbuf_transfer[i] = screen->get_tex_transfer(rast->screen,
cbuf->texture,
cbuf->face,
cbuf->level,
cbuf->zslice,
PIPE_TRANSFER_READ_WRITE,
0, 0,
cbuf->width,
cbuf->height);
if (!rast->cbuf_transfer[i])
goto fail;
rast->cbuf_map[i] = screen->transfer_map(rast->screen,
rast->cbuf_transfer[i]);
if (!rast->cbuf_map[i])
goto fail;
}
for (i = 0; i < rast->state.nr_cbufs; i++) {
rast->cbuf[i].map = scene->cbuf_map[i];
rast->cbuf[i].format = scene->cbuf_transfer[i]->texture->format;
rast->cbuf[i].width = scene->cbuf_transfer[i]->width;
rast->cbuf[i].height = scene->cbuf_transfer[i]->height;
rast->cbuf[i].stride = scene->cbuf_transfer[i]->stride;
}
zsbuf = rast->state.fb.zsbuf;
if (zsbuf) {
rast->zsbuf_transfer = screen->get_tex_transfer(rast->screen,
zsbuf->texture,
zsbuf->face,
zsbuf->level,
zsbuf->zslice,
PIPE_TRANSFER_READ_WRITE,
0, 0,
zsbuf->width,
zsbuf->height);
if (!rast->zsbuf_transfer)
goto fail;
rast->zsbuf_map = screen->transfer_map(rast->screen,
rast->zsbuf_transfer);
if (!rast->zsbuf_map)
goto fail;
if (write_zstencil) {
rast->zsbuf.map = scene->zsbuf_map;
rast->zsbuf.stride = scene->zsbuf_transfer->stride;
rast->zsbuf.blocksize =
util_format_get_blocksize(scene->zsbuf_transfer->texture->format);
}
lp_scene_bin_iter_begin( scene );
return TRUE;
fail:
/* Unmap and release transfers?
*/
return FALSE;
}
/**
* Finish the rasterization phase.
* Unmap framebuffer surfaces.
*/
static void
lp_rast_end( struct lp_rasterizer *rast )
{
struct pipe_screen *screen = rast->screen;
unsigned i;
int i;
for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
if (rast->cbuf_map[i])
screen->transfer_unmap(screen, rast->cbuf_transfer[i]);
lp_scene_reset( rast->curr_scene );
if (rast->cbuf_transfer[i])
screen->tex_transfer_destroy(rast->cbuf_transfer[i]);
for (i = 0; i < rast->state.nr_cbufs; i++)
rast->cbuf[i].map = NULL;
rast->cbuf_transfer[i] = NULL;
rast->cbuf_map[i] = NULL;
}
if (rast->zsbuf_map)
screen->transfer_unmap(screen, rast->zsbuf_transfer);
if (rast->zsbuf_transfer)
screen->tex_transfer_destroy(rast->zsbuf_transfer);
rast->zsbuf_transfer = NULL;
rast->zsbuf_map = NULL;
rast->zsbuf.map = NULL;
rast->curr_scene = NULL;
}
/**
* Begining rasterization of a tile.
* \param x window X position of the tile, in pixels
@@ -189,7 +135,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
clear_color[1] == clear_color[2] &&
clear_color[2] == clear_color[3]) {
/* clear to grayscale value {x, x, x, x} */
for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
for (i = 0; i < rast->state.nr_cbufs; i++) {
memset(color_tile[i], clear_color[0], TILE_SIZE * TILE_SIZE * 4);
}
}
@@ -200,7 +146,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
* works.
*/
const unsigned chunk = TILE_SIZE / 4;
for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
for (i = 0; i < rast->state.nr_cbufs; i++) {
uint8_t *c = color_tile[i];
unsigned j;
for (j = 0; j < 4 * TILE_SIZE; j++) {
@@ -232,17 +178,17 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
struct lp_rasterizer *rast = task->rast;
const unsigned tile_x = task->x;
const unsigned tile_y = task->y;
const unsigned height = TILE_SIZE/TILE_VECTOR_HEIGHT;
const unsigned width = TILE_SIZE*TILE_VECTOR_HEIGHT;
unsigned block_size = util_format_get_blocksize(rast->zsbuf_transfer->texture->format);
const unsigned height = TILE_SIZE / TILE_VECTOR_HEIGHT;
const unsigned width = TILE_SIZE * TILE_VECTOR_HEIGHT;
unsigned block_size = rast->zsbuf.blocksize;
uint8_t *dst;
unsigned dst_stride = rast->zsbuf_transfer->stride*TILE_VECTOR_HEIGHT;
unsigned dst_stride = rast->zsbuf.stride * TILE_VECTOR_HEIGHT;
unsigned i, j;
LP_DBG(DEBUG_RAST, "%s 0x%x\n", __FUNCTION__, arg.clear_zstencil);
assert(rast->zsbuf_map);
if (!rast->zsbuf_map)
assert(rast->zsbuf.map);
if (!rast->zsbuf.map)
return;
LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
@@ -278,8 +224,8 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
}
break;
default:
assert(0);
break;
assert(0);
break;
}
}
@@ -298,25 +244,16 @@ lp_rast_load_color(struct lp_rasterizer_task *task,
LP_DBG(DEBUG_RAST, "%s at %u, %u\n", __FUNCTION__, x, y);
for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
struct pipe_transfer *transfer = rast->cbuf_transfer[i];
int w = TILE_SIZE;
int h = TILE_SIZE;
if (x >= transfer->width || y >= transfer->height)
for (i = 0; i < rast->state.nr_cbufs; i++) {
if (x >= rast->cbuf[i].width || y >= rast->cbuf[i].height)
continue;
assert(w >= 0);
assert(h >= 0);
assert(w <= TILE_SIZE);
assert(h <= TILE_SIZE);
lp_tile_read_4ub(transfer->texture->format,
lp_tile_read_4ub(rast->cbuf[i].format,
task->tile.color[i],
rast->cbuf_map[i],
transfer->stride,
rast->cbuf[i].map,
rast->cbuf[i].stride,
x, y,
w, h);
TILE_SIZE, TILE_SIZE);
LP_COUNT(nr_color_tile_load);
}
@@ -366,7 +303,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
block_offset = ((y / 4) * (16 * 16) + (x / 4) * 16);
/* color buffer */
for (i = 0; i < rast->state.fb.nr_cbufs; i++)
for (i = 0; i < rast->state.nr_cbufs; i++)
color[i] = tile->color[i] + 4 * block_offset;
/* depth buffer */
@@ -423,7 +360,7 @@ void lp_rast_shade_quads( struct lp_rasterizer_task *task,
block_offset = ((iy / 4) * (16 * 16) + (ix / 4) * 16);
/* color buffer */
for (i = 0; i < rast->state.fb.nr_cbufs; i++)
for (i = 0; i < rast->state.nr_cbufs; i++)
color[i] = tile->color[i] + 4 * block_offset;
/* depth buffer */
@@ -516,51 +453,33 @@ lp_rast_store_color(struct lp_rasterizer_task *task)
const unsigned x = task->x, y = task->y;
unsigned i;
for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
struct pipe_transfer *transfer = rast->cbuf_transfer[i];
int w = TILE_SIZE;
int h = TILE_SIZE;
if (x >= transfer->width)
for (i = 0; i < rast->state.nr_cbufs; i++) {
if (x >= rast->cbuf[i].width)
continue;
if (y >= transfer->height)
if (y >= rast->cbuf[i].height)
continue;
LP_DBG(DEBUG_RAST, "%s [%u] %d,%d %dx%d\n", __FUNCTION__,
task->thread_index, x, y, w, h);
LP_DBG(DEBUG_RAST, "%s [%u] %d,%d\n", __FUNCTION__,
task->thread_index, x, y);
if (LP_DEBUG & DEBUG_SHOW_SUBTILES)
outline_subtiles(task->tile.color[i]);
else if (LP_DEBUG & DEBUG_SHOW_TILES)
outline_tile(task->tile.color[i]);
lp_tile_write_4ub(transfer->texture->format,
lp_tile_write_4ub(rast->cbuf[i].format,
task->tile.color[i],
rast->cbuf_map[i],
transfer->stride,
rast->cbuf[i].map,
rast->cbuf[i].stride,
x, y,
w, h);
TILE_SIZE, TILE_SIZE);
LP_COUNT(nr_color_tile_store);
}
}
/**
* Write the rasterizer's tiles to the framebuffer.
*/
static void
lp_rast_end_tile(struct lp_rasterizer_task *task)
{
struct lp_rasterizer *rast = task->rast;
LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
if (rast->state.write_color)
lp_rast_store_color(task);
}
/**
* Signal on a fence. This is called during bin execution/rasterization.
@@ -586,23 +505,6 @@ lp_rast_fence(struct lp_rasterizer_task *task,
}
/**
* When all the threads are done rasterizing a scene, one thread will
* call this function to reset the scene and put it onto the empty queue.
*/
static void
release_scene( struct lp_rasterizer *rast,
struct lp_scene *scene )
{
util_unreference_framebuffer_state( &scene->fb );
lp_scene_reset( scene );
assert(lp_scene_is_empty(scene));
lp_scene_enqueue( rast->empty_scenes, scene );
rast->curr_scene = NULL;
}
/**
@@ -620,7 +522,7 @@ rasterize_bin(struct lp_rasterizer_task *task,
struct cmd_block *block;
unsigned k;
lp_rast_start_tile( task, x, y );
lp_rast_start_tile( task, x * TILE_SIZE, y * TILE_SIZE );
/* simply execute each of the commands in the block list */
for (block = commands->head; block; block = block->next) {
@@ -629,7 +531,14 @@ rasterize_bin(struct lp_rasterizer_task *task,
}
}
lp_rast_end_tile( task );
/* Write the rasterizer's tiles to the framebuffer.
*/
if (task->rast->state.write_color)
lp_rast_store_color(task);
/* Free data for this bin.
*/
lp_scene_bin_reset( task->rast->curr_scene, x, y);
}
@@ -714,8 +623,7 @@ is_empty_bin( const struct cmd_bin *bin )
*/
static void
rasterize_scene(struct lp_rasterizer_task *task,
struct lp_scene *scene,
bool write_depth)
struct lp_scene *scene)
{
/* loop over scene bins, rasterize each */
#if 0
@@ -724,7 +632,7 @@ rasterize_scene(struct lp_rasterizer_task *task,
for (i = 0; i < scene->tiles_x; i++) {
for (j = 0; j < scene->tiles_y; j++) {
struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
rasterize_bin(task, bin, i * TILE_SIZE, j * TILE_SIZE);
rasterize_bin(task, bin, i, j);
}
}
}
@@ -736,7 +644,7 @@ rasterize_scene(struct lp_rasterizer_task *task,
assert(scene);
while ((bin = lp_scene_bin_iter_next(scene, &x, &y))) {
if (!is_empty_bin( bin ))
rasterize_bin(task, bin, x * TILE_SIZE, y * TILE_SIZE);
rasterize_bin(task, bin, x, y);
}
}
#endif
@@ -747,44 +655,20 @@ rasterize_scene(struct lp_rasterizer_task *task,
* Called by setup module when it has something for us to render.
*/
void
lp_rasterize_scene( struct lp_rasterizer *rast,
struct lp_scene *scene,
const struct pipe_framebuffer_state *fb,
bool write_depth )
lp_rast_queue_scene( struct lp_rasterizer *rast,
struct lp_scene *scene)
{
boolean debug = false;
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
if (debug) {
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));
}
}
}
/* save framebuffer state in the bin */
util_copy_framebuffer_state(&scene->fb, fb);
scene->write_depth = write_depth;
if (rast->num_threads == 0) {
/* no threading */
lp_rast_begin( rast, fb,
fb->nr_cbufs != 0, /* always write color if cbufs present */
fb->zsbuf != NULL && write_depth );
lp_rast_begin( rast, scene );
lp_scene_bin_iter_begin( scene );
rasterize_scene( &rast->tasks[0], scene, write_depth );
rasterize_scene( &rast->tasks[0], scene );
release_scene( rast, scene );
lp_rast_end( rast );
lp_scene_reset( scene );
rast->curr_scene = NULL;
}
else {
/* threaded rendering! */
@@ -796,14 +680,26 @@ lp_rasterize_scene( struct lp_rasterizer *rast,
for (i = 0; i < rast->num_threads; i++) {
pipe_semaphore_signal(&rast->tasks[i].work_ready);
}
}
LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
}
void
lp_rast_finish( struct lp_rasterizer *rast )
{
if (rast->num_threads == 0) {
/* nothing to do */
}
else {
int i;
/* wait for work to complete */
for (i = 0; i < rast->num_threads; i++) {
pipe_semaphore_wait(&rast->tasks[i].work_done);
}
}
LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
}
@@ -834,19 +730,8 @@ static PIPE_THREAD_ROUTINE( thread_func, init_data )
* - get next scene to rasterize
* - map the framebuffer surfaces
*/
const struct pipe_framebuffer_state *fb;
boolean write_depth;
rast->curr_scene = lp_scene_dequeue( rast->full_scenes, TRUE );
lp_scene_bin_iter_begin( rast->curr_scene );
fb = &rast->curr_scene->fb;
write_depth = rast->curr_scene->write_depth;
lp_rast_begin( rast, fb,
fb->nr_cbufs != 0,
fb->zsbuf != NULL && write_depth );
lp_rast_begin( rast,
lp_scene_dequeue( rast->full_scenes, TRUE ) );
}
/* Wait for all threads to get here so that threads[1+] don't
@@ -857,25 +742,23 @@ static PIPE_THREAD_ROUTINE( thread_func, init_data )
/* do work */
if (debug)
debug_printf("thread %d doing work\n", task->thread_index);
rasterize_scene(task,
rast->curr_scene,
rast->curr_scene->write_depth);
rast->curr_scene);
/* wait for all threads to finish with this scene */
pipe_barrier_wait( &rast->barrier );
/* XXX: shouldn't be necessary:
*/
if (task->thread_index == 0) {
/* thread[0]:
* - release the scene object
* - unmap the framebuffer surfaces
*/
release_scene( rast, rast->curr_scene );
lp_rast_end( rast );
}
/* signal done with work */
if (debug)
debug_printf("thread %d done working\n", task->thread_index);
pipe_semaphore_signal(&task->work_done);
}
@@ -918,7 +801,7 @@ create_rast_threads(struct lp_rasterizer *rast)
* processing them.
*/
struct lp_rasterizer *
lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
lp_rast_create( void )
{
struct lp_rasterizer *rast;
unsigned i, cbuf;
@@ -927,9 +810,6 @@ lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
if(!rast)
return NULL;
rast->screen = screen;
rast->empty_scenes = empty;
rast->full_scenes = lp_scene_queue_create();
for (i = 0; i < Elements(rast->tasks); i++) {
@@ -957,8 +837,6 @@ void lp_rast_destroy( struct lp_rasterizer *rast )
{
unsigned i, cbuf;
util_unreference_framebuffer_state(&rast->state.fb);
for (i = 0; i < Elements(rast->tasks); i++) {
for (cbuf = 0; cbuf < PIPE_MAX_COLOR_BUFS; cbuf++ )
align_free(rast->tasks[i].tile.color[cbuf]);
+11 -10
View File
@@ -43,10 +43,8 @@
struct lp_rasterizer;
struct lp_scene;
struct lp_scene_queue;
struct lp_fence;
struct cmd_bin;
struct pipe_screen;
/** For sub-pixel positioning */
#define FIXED_ORDER 4
@@ -129,18 +127,21 @@ struct lp_rast_triangle {
struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen,
struct lp_scene_queue *empty );
struct lp_rasterizer *
lp_rast_create( void );
void lp_rast_destroy( struct lp_rasterizer * );
void
lp_rast_destroy( struct lp_rasterizer * );
unsigned lp_rast_get_num_threads( struct lp_rasterizer * );
unsigned
lp_rast_get_num_threads( struct lp_rasterizer * );
void lp_rasterize_scene( struct lp_rasterizer *rast,
struct lp_scene *scene,
const struct pipe_framebuffer_state *fb,
bool write_depth );
void
lp_rast_queue_scene( struct lp_rasterizer *rast,
struct lp_scene *scene );
void
lp_rast_finish( struct lp_rasterizer *rast );
union lp_rast_cmd_arg {
+31 -19
View File
@@ -38,8 +38,6 @@
#define MAX_THREADS 8 /* XXX probably temporary here */
struct pipe_transfer;
struct pipe_screen;
struct lp_rasterizer;
@@ -82,20 +80,26 @@ struct lp_rasterizer_task
*/
struct lp_rasterizer
{
boolean clipped_tile;
boolean check_for_clipped_tiles;
boolean exit_flag;
/* Framebuffer stuff
*/
struct pipe_screen *screen;
struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS];
struct pipe_transfer *zsbuf_transfer;
void *cbuf_map[PIPE_MAX_COLOR_BUFS];
uint8_t *zsbuf_map;
struct {
void *map;
unsigned stride;
unsigned width;
unsigned height;
enum pipe_format format;
} cbuf[PIPE_MAX_COLOR_BUFS];
struct {
struct pipe_framebuffer_state fb;
uint8_t *map;
unsigned stride;
unsigned blocksize;
} zsbuf;
struct {
unsigned nr_cbufs;
boolean write_color;
boolean write_zstencil;
unsigned clear_color;
@@ -105,7 +109,14 @@ struct lp_rasterizer
/** The incoming queue of scenes ready to rasterize */
struct lp_scene_queue *full_scenes;
/** The outgoing queue of processed scenes to return to setup modulee */
/**
* The outgoing queue of processed scenes to return to setup module
*
* XXX: while scenes are per-context but the rasterizer is
* (potentially) shared, these empty scenes should be returned to
* the context which created them rather than retained here.
*/
struct lp_scene_queue *empty_scenes;
/** The scene currently being rasterized by the threads */
@@ -137,17 +148,18 @@ lp_rast_depth_pointer( struct lp_rasterizer *rast,
unsigned x, unsigned y )
{
void * depth;
assert((x % TILE_VECTOR_WIDTH) == 0);
assert((y % TILE_VECTOR_HEIGHT) == 0);
if(!rast->zsbuf_map)
if (!rast->zsbuf.map)
return NULL;
assert(rast->zsbuf_transfer);
depth = rast->zsbuf_map +
y*rast->zsbuf_transfer->stride +
TILE_VECTOR_HEIGHT*x*util_format_get_blocksize(rast->zsbuf_transfer->texture->format);
#ifdef DEBUG
depth = (rast->zsbuf.map +
rast->zsbuf.stride * y +
rast->zsbuf.blocksize * x * TILE_VECTOR_HEIGHT);
assert(lp_check_alignment(depth, 16));
#endif
return depth;
}
@@ -175,7 +187,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
block_offset = (iy / 4) * (16 * 16) + (ix / 4) * 16;
/* color buffer */
for (i = 0; i < rast->state.fb.nr_cbufs; i++)
for (i = 0; i < rast->state.nr_cbufs; i++)
color[i] = tile->color[i] + 4 * block_offset;
depth = lp_rast_depth_pointer(rast, x, y);
+204 -54
View File
@@ -29,37 +29,30 @@
#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)
{
struct lp_scene *scene = CALLOC_STRUCT(lp_scene);
if (scene)
lp_scene_init(scene);
return scene;
}
void
lp_scene_destroy(struct lp_scene *scene)
{
lp_scene_reset(scene);
lp_scene_free_bin_data(scene);
FREE(scene);
}
void
lp_scene_init(struct lp_scene *scene)
lp_scene_create( struct pipe_context *pipe,
struct lp_scene_queue *queue )
{
unsigned i, j;
for (i = 0; i < TILES_X; i++)
struct lp_scene *scene = CALLOC_STRUCT(lp_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);
@@ -67,6 +60,36 @@ lp_scene_init(struct lp_scene *scene)
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)
{
unsigned i, j;
lp_scene_reset(scene);
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);
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);
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 );
}
+26 -8
View File
@@ -39,6 +39,7 @@
#include "lp_tile_soa.h"
#include "lp_rast.h"
struct lp_scene_queue;
/* We're limited to 2K by 2K for 32bit fixed point rasterization.
* Will need a 64-bit version for larger framebuffers.
@@ -112,8 +113,14 @@ struct texture_ref {
* scenes:
*/
struct lp_scene {
struct cmd_bin tile[TILES_X][TILES_Y];
struct data_block_list data;
struct pipe_context *pipe;
struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS];
struct pipe_transfer *zsbuf_transfer;
/* Scene's buffers are mapped at the time the scene is enqueued:
*/
void *cbuf_map[PIPE_MAX_COLOR_BUFS];
uint8_t *zsbuf_map;
/** the framebuffer to render the scene into */
struct pipe_framebuffer_state fb;
@@ -131,25 +138,28 @@ struct lp_scene {
int curr_x, curr_y; /**< for iterating over bins */
pipe_mutex mutex;
/* Where to place this scene once it has been rasterized:
*/
struct lp_scene_queue *empty_queue;
struct cmd_bin tile[TILES_X][TILES_Y];
struct data_block_list data;
};
struct lp_scene *lp_scene_create(void);
struct lp_scene *lp_scene_create(struct pipe_context *pipe,
struct lp_scene_queue *empty_queue);
void lp_scene_destroy(struct lp_scene *scene);
void lp_scene_init(struct lp_scene *scene);
boolean lp_scene_is_empty(struct lp_scene *scene );
void lp_scene_reset(struct lp_scene *scene );
void lp_scene_free_bin_data(struct lp_scene *scene);
void lp_scene_set_framebuffer_size( struct lp_scene *scene,
unsigned width, unsigned height );
void lp_bin_new_data_block( struct data_block_list *list );
@@ -296,5 +306,13 @@ lp_scene_bin_iter_begin( struct lp_scene *scene );
struct cmd_bin *
lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y );
void
lp_scene_rasterize( struct lp_scene *scene,
struct lp_rasterizer *rast,
boolean write_depth );
void
lp_scene_begin_binning( struct lp_scene *scene,
struct pipe_framebuffer_state *fb );
#endif /* LP_BIN_H */
+16 -20
View File
@@ -66,11 +66,8 @@ lp_setup_get_current_scene(struct setup_context *setup)
assert(lp_scene_is_empty(setup->scene));
if(0)lp_scene_reset( setup->scene ); /* XXX temporary? */
lp_scene_set_framebuffer_size(setup->scene,
setup->fb.width,
setup->fb.height);
lp_scene_begin_binning(setup->scene,
&setup->fb );
}
return setup->scene;
}
@@ -135,13 +132,12 @@ static void reset_context( struct setup_context *setup )
/** Rasterize all scene's bins */
static void
lp_setup_rasterize_scene( struct setup_context *setup,
boolean write_depth )
boolean write_depth )
{
struct lp_scene *scene = lp_setup_get_current_scene(setup);
lp_rasterize_scene(setup->rast,
scene,
&setup->fb,
lp_scene_rasterize(scene,
setup->rast,
write_depth);
reset_context( setup );
@@ -246,19 +242,16 @@ void
lp_setup_bind_framebuffer( struct setup_context *setup,
const struct pipe_framebuffer_state *fb )
{
struct lp_scene *scene = lp_setup_get_current_scene(setup);
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
/* Flush any old scene.
*/
set_scene_state( setup, SETUP_FLUSHED );
/* re-get scene pointer, may have a new scene after flushing */
(void) scene;
scene = lp_setup_get_current_scene(setup);
/* Set new state. This will be picked up later when we next need a
* scene.
*/
util_copy_framebuffer_state(&setup->fb, fb);
lp_scene_set_framebuffer_size(scene, setup->fb.width, setup->fb.height);
}
@@ -683,7 +676,7 @@ lp_setup_destroy( struct setup_context *setup )
* it.
*/
struct setup_context *
lp_setup_create( struct pipe_screen *screen,
lp_setup_create( struct pipe_context *pipe,
struct draw_context *draw )
{
unsigned i;
@@ -698,7 +691,9 @@ lp_setup_create( struct pipe_screen *screen,
if (!setup->empty_scenes)
goto fail;
setup->rast = lp_rast_create( screen, setup->empty_scenes );
/* XXX: move this to the screen and share between contexts:
*/
setup->rast = lp_rast_create();
if (!setup->rast)
goto fail;
@@ -711,7 +706,8 @@ lp_setup_create( struct pipe_screen *screen,
/* create some empty scenes */
for (i = 0; i < MAX_SCENES; i++) {
setup->scenes[i] = lp_scene_create();
setup->scenes[i] = lp_scene_create( pipe, setup->empty_scenes );
lp_scene_enqueue(setup->empty_scenes, setup->scenes[i]);
}
+1 -1
View File
@@ -62,7 +62,7 @@ struct lp_fragment_shader;
struct lp_jit_context;
struct setup_context *
lp_setup_create( struct pipe_screen *screen,
lp_setup_create( struct pipe_context *pipe,
struct draw_context *draw );
void