X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_setup.c;h=61b968c49f5e88c750741bf7fc0129f13aacc38a;hb=a1acbff299c444913418e65da473745cd901a2db;hp=030a19ef3011a50607c36c1129e0b7368375844a;hpb=1928c965b1fb76987cbc834111bd1d1e1f2cda51;p=mesa.git diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index 030a19ef301..61b968c49f5 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -34,32 +34,42 @@ #include "pipe/p_defines.h" #include "pipe/p_inlines.h" -#include "util/u_math.h" #include "util/u_memory.h" #include "util/u_pack_color.h" -#include "lp_state.h" +#include "util/u_surface.h" +#include "lp_scene.h" +#include "lp_scene_queue.h" #include "lp_buffer.h" #include "lp_texture.h" +#include "lp_debug.h" +#include "lp_fence.h" +#include "lp_rast.h" #include "lp_setup_context.h" -static void set_state( struct setup_context *, unsigned ); +#include "draw/draw_context.h" +#include "draw/draw_vbuf.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; -} -void lp_setup_new_data_block( struct data_block_list *list ) +/** XXX temporary value, temporary here */ +#define MAX_SCENES 2 + + +static void set_scene_state( struct setup_context *, unsigned ); + + +struct lp_scene * +lp_setup_get_current_scene(struct setup_context *setup) { - struct data_block *block = MALLOC_STRUCT(data_block); - list->tail->next = block; - list->tail = block; - block->next = NULL; - block->used = 0; + if (!setup->scene) { + /* wait for a free/empty bin */ + setup->scene = lp_scene_dequeue(setup->empty_scenes); + if(0)lp_scene_reset( setup->scene ); /* XXX temporary? */ + + lp_scene_set_framebuffer_size(setup->scene, + setup->fb.width, + setup->fb.height); + } + return setup->scene; } @@ -69,7 +79,7 @@ first_triangle( struct setup_context *setup, const float (*v1)[4], const float (*v2)[4]) { - set_state( setup, SETUP_ACTIVE ); + set_scene_state( setup, SETUP_ACTIVE ); lp_setup_choose_triangle( setup ); setup->triangle( setup, v0, v1, v2 ); } @@ -79,7 +89,7 @@ first_line( struct setup_context *setup, const float (*v0)[4], const float (*v1)[4]) { - set_state( setup, SETUP_ACTIVE ); + set_scene_state( setup, SETUP_ACTIVE ); lp_setup_choose_line( setup ); setup->line( setup, v0, v1 ); } @@ -88,45 +98,23 @@ static void first_point( struct setup_context *setup, const float (*v0)[4]) { - set_state( setup, SETUP_ACTIVE ); + set_scene_state( setup, SETUP_ACTIVE ); lp_setup_choose_point( setup ); setup->point( setup, v0 ); } static void reset_context( struct setup_context *setup ) { - unsigned i, j; + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - /* Free 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]; - struct cmd_block *block; - struct cmd_block *tmp; - - for (block = list->head; block != list->tail; block = tmp) { - tmp = block->next; - FREE(block); - } - - list->head = list->tail; - } - } - - /* Free binned data: - */ - { - struct data_block_list *list = &setup->data; - struct data_block *block, *tmp; + /* Reset derived state */ + setup->constants.stored_size = 0; + setup->constants.stored_data = NULL; + setup->fs.stored = NULL; + setup->dirty = ~0; - for (block = list->head; block != list->tail; block = tmp) { - tmp = block->next; - FREE(block); - } - - list->head = list->tail; - } + /* no current bin */ + setup->scene = NULL; /* Reset some state: */ @@ -141,65 +129,21 @@ static void reset_context( struct setup_context *setup ) } - - -/* Add a command to all active bins. - */ -static void bin_everywhere( 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++) - bin_command( &setup->tile[i][j], cmd, arg ); -} - - +/** Rasterize all scene's bins */ static void -rasterize_bins( struct setup_context *setup, - boolean write_depth ) +lp_setup_rasterize_scene( struct setup_context *setup, + boolean write_depth ) { - struct lp_rasterizer *rast = setup->rast; - struct cmd_block *block; - unsigned i,j,k; - - if (setup->state != SETUP_ACTIVE) { - /* this can happen, not a big deal */ - debug_printf("%s called when not binning\n", __FUNCTION__); - return; - } + struct lp_scene *scene = lp_setup_get_current_scene(setup); - lp_rast_begin( rast, - setup->fb.width, - setup->fb.height ); - - lp_rast_bind_color( rast, - setup->fb.cbuf, - setup->fb.cbuf != NULL ); - - lp_rast_bind_zstencil( rast, - setup->fb.zsbuf, - setup->fb.zsbuf != NULL && write_depth ); - - for (i = 0; i < setup->tiles_x; i++) { - for (j = 0; j < setup->tiles_y; j++) { - - lp_rast_start_tile( rast, - i * TILESIZE, - j * TILESIZE ); - - for (block = setup->tile[i][j].head; block; block = block->next) { - for (k = 0; k < block->count; k++) { - block->cmd[k]( rast, block->arg[k] ); - } - } - - lp_rast_end_tile( rast ); - } - } + lp_rasterize_scene(setup->rast, + scene, + &setup->fb, + write_depth); reset_context( setup ); + + LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__); } @@ -207,48 +151,35 @@ rasterize_bins( struct setup_context *setup, static void begin_binning( struct setup_context *setup ) { - 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); - } + struct lp_scene *scene = lp_setup_get_current_scene(setup); - setup->tiles_x = align(setup->fb.width, TILESIZE); - setup->tiles_y = align(setup->fb.height, TILESIZE); + LP_DBG(DEBUG_SETUP, "%s color: %s depth: %s\n", __FUNCTION__, + (setup->clear.flags & PIPE_CLEAR_COLOR) ? "clear": "load", + (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) ? "clear": "load"); - if (setup->fb.cbuf) { + if (setup->fb.nr_cbufs) { if (setup->clear.flags & PIPE_CLEAR_COLOR) - bin_everywhere( setup, - lp_rast_clear_color, - setup->clear.color ); + lp_scene_bin_everywhere( scene, + lp_rast_clear_color, + setup->clear.color ); else - bin_everywhere( setup, lp_rast_load_color, lp_rast_arg_null() ); + lp_scene_bin_everywhere( scene, + lp_rast_load_color, + lp_rast_arg_null() ); } if (setup->fb.zsbuf) { if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) - bin_everywhere( setup, - lp_rast_clear_zstencil, - setup->clear.zstencil ); + lp_scene_bin_everywhere( scene, + lp_rast_clear_zstencil, + setup->clear.zstencil ); else - bin_everywhere( setup, lp_rast_load_zstencil, lp_rast_arg_null() ); + lp_scene_bin_everywhere( scene, + lp_rast_load_zstencil, + lp_rast_arg_null() ); } + + LP_DBG(DEBUG_SETUP, "%s done\n", __FUNCTION__); } @@ -260,13 +191,15 @@ begin_binning( struct setup_context *setup ) static void execute_clears( struct setup_context *setup ) { + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + begin_binning( setup ); - rasterize_bins( setup, TRUE ); + lp_setup_rasterize_scene( setup, TRUE ); } static void -set_state( struct setup_context *setup, +set_scene_state( struct setup_context *setup, unsigned new_state ) { unsigned old_state = setup->state; @@ -274,10 +207,11 @@ set_state( struct setup_context *setup, if (old_state == new_state) return; + LP_DBG(DEBUG_SETUP, "%s old %d new %d\n", __FUNCTION__, old_state, new_state); + switch (new_state) { case SETUP_ACTIVE: - if (old_state == SETUP_FLUSHED) - begin_binning( setup ); + begin_binning( setup ); break; case SETUP_CLEARED: @@ -291,7 +225,7 @@ set_state( struct setup_context *setup, if (old_state == SETUP_CLEARED) execute_clears( setup ); else - rasterize_bins( setup, TRUE ); + lp_setup_rasterize_scene( setup, TRUE ); break; } @@ -303,29 +237,28 @@ void lp_setup_flush( struct setup_context *setup, unsigned flags ) { - set_state( setup, SETUP_FLUSHED ); + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + + set_scene_state( setup, SETUP_FLUSHED ); } void lp_setup_bind_framebuffer( struct setup_context *setup, - struct pipe_surface *color, - struct pipe_surface *zstencil ) + const struct pipe_framebuffer_state *fb ) { - unsigned width, height; + struct lp_scene *scene = lp_setup_get_current_scene(setup); - set_state( setup, SETUP_FLUSHED ); + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - pipe_surface_reference( &setup->fb.cbuf, color ); - pipe_surface_reference( &setup->fb.zsbuf, zstencil ); + set_scene_state( setup, SETUP_FLUSHED ); - width = MAX2( color->width, zstencil->width ); - height = MAX2( color->height, zstencil->height ); + util_copy_framebuffer_state(&setup->fb, fb); - setup->tiles_x = align( width, TILESIZE ) / TILESIZE; - setup->tiles_y = align( height, TILESIZE ) / TILESIZE; + lp_scene_set_framebuffer_size(scene, setup->fb.width, setup->fb.height); } + void lp_setup_clear( struct setup_context *setup, const float *color, @@ -333,10 +266,15 @@ lp_setup_clear( struct setup_context *setup, unsigned stencil, unsigned flags ) { + struct lp_scene *scene = lp_setup_get_current_scene(setup); + unsigned i; + + LP_DBG(DEBUG_SETUP, "%s state %d\n", __FUNCTION__, setup->state); + + if (flags & PIPE_CLEAR_COLOR) { - util_pack_color(color, - setup->fb.cbuf->format, - &setup->clear.color.clear_color ); + for (i = 0; i < 4; ++i) + setup->clear.color.clear_color[i] = float_to_ubyte(color[i]); } if (flags & PIPE_CLEAR_DEPTHSTENCIL) { @@ -347,20 +285,21 @@ lp_setup_clear( struct setup_context *setup, } if (setup->state == SETUP_ACTIVE) { - /* Add the clear to existing bins. In the unusual case where - * both color and depth-stencilare being cleared, we could - * discard the currently binned scene and start again, but I - * don't see that as being a common usage. + /* Add the clear to existing scene. In the unusual case where + * both color and depth-stencil are being cleared when there's + * already been some rendering, we could discard the currently + * binned scene and start again, but I don't see that as being + * a common usage. */ if (flags & PIPE_CLEAR_COLOR) - bin_everywhere( setup, - lp_rast_clear_color, - setup->clear.color ); + lp_scene_bin_everywhere( scene, + lp_rast_clear_color, + setup->clear.color ); if (setup->clear.flags & PIPE_CLEAR_DEPTHSTENCIL) - bin_everywhere( setup, - lp_rast_clear_zstencil, - setup->clear.zstencil ); + lp_scene_bin_everywhere( scene, + lp_rast_clear_zstencil, + setup->clear.zstencil ); } else { /* Put ourselves into the 'pre-clear' state, specifically to try @@ -368,19 +307,43 @@ lp_setup_clear( struct setup_context *setup, * buffers which the app or state-tracker might issue * separately. */ - set_state( setup, SETUP_CLEARED ); + set_scene_state( setup, SETUP_CLEARED ); setup->clear.flags |= flags; } } +/** + * Emit a fence. + */ +struct pipe_fence_handle * +lp_setup_fence( struct setup_context *setup ) +{ + struct lp_scene *scene = lp_setup_get_current_scene(setup); + const unsigned rank = lp_scene_get_num_bins( scene ); /* xxx */ + struct lp_fence *fence = lp_fence_create(rank); + + LP_DBG(DEBUG_SETUP, "%s rank %u\n", __FUNCTION__, rank); + + set_scene_state( setup, SETUP_ACTIVE ); + + /* insert the fence into all command bins */ + lp_scene_bin_everywhere( scene, + lp_rast_fence, + lp_rast_arg_fence(fence) ); + + return (struct pipe_fence_handle *) fence; +} + void lp_setup_set_triangle_state( struct setup_context *setup, unsigned cull_mode, boolean ccw_is_frontface) { + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + setup->ccw_is_frontface = ccw_is_frontface; setup->cullmode = cull_mode; setup->triangle = first_triangle; @@ -393,33 +356,34 @@ lp_setup_set_fs_inputs( struct setup_context *setup, const struct lp_shader_input *input, unsigned nr ) { + LP_DBG(DEBUG_SETUP, "%s %p %u\n", __FUNCTION__, (void *) input, nr); + memcpy( setup->fs.input, input, nr * sizeof input[0] ); setup->fs.nr_inputs = nr; } void -lp_setup_set_fs( struct setup_context *setup, - struct lp_fragment_shader *fs ) +lp_setup_set_fs_function( struct setup_context *setup, + lp_jit_frag_func jit_function, + boolean opaque ) { + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) jit_function); /* FIXME: reference count */ - setup->fs.jit_function = fs->current->jit_function; + setup->fs.current.jit_function = jit_function; + setup->fs.current.opaque = opaque; + setup->dirty |= LP_SETUP_NEW_FS; } void lp_setup_set_fs_constants(struct setup_context *setup, struct pipe_buffer *buffer) { - const void *data = buffer ? llvmpipe_buffer(buffer)->data : NULL; - struct pipe_buffer *dummy; - - /* FIXME: hold on to the reference */ - dummy = NULL; - pipe_buffer_reference(&dummy, buffer); + LP_DBG(DEBUG_SETUP, "%s %p\n", __FUNCTION__, (void *) buffer); - setup->fs.jit_context.constants = data; + pipe_buffer_reference(&setup->constants.current, buffer); - setup->fs.jit_context_dirty = TRUE; + setup->dirty |= LP_SETUP_NEW_CONSTANTS; } @@ -427,9 +391,11 @@ void lp_setup_set_alpha_ref_value( struct setup_context *setup, float alpha_ref_value ) { - if(setup->fs.jit_context.alpha_ref_value != alpha_ref_value) { - setup->fs.jit_context.alpha_ref_value = alpha_ref_value; - setup->fs.jit_context_dirty = TRUE; + LP_DBG(DEBUG_SETUP, "%s %f\n", __FUNCTION__, alpha_ref_value); + + if(setup->fs.current.jit_context.alpha_ref_value != alpha_ref_value) { + setup->fs.current.jit_context.alpha_ref_value = alpha_ref_value; + setup->dirty |= LP_SETUP_NEW_FS; } } @@ -437,20 +403,35 @@ void lp_setup_set_blend_color( struct setup_context *setup, const struct pipe_blend_color *blend_color ) { - unsigned i, j; + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); - if(!setup->fs.jit_context.blend_color) - setup->fs.jit_context.blend_color = align_malloc(4 * 16, 16); + assert(blend_color); - for (i = 0; i < 4; ++i) { - uint8_t c = float_to_ubyte(blend_color->color[i]); - for (j = 0; j < 16; ++j) - setup->fs.jit_context.blend_color[i*4 + j] = c; + if(memcmp(&setup->blend_color.current, blend_color, sizeof *blend_color) != 0) { + memcpy(&setup->blend_color.current, blend_color, sizeof *blend_color); + setup->dirty |= LP_SETUP_NEW_BLEND_COLOR; } +} - setup->fs.jit_context_dirty = TRUE; + +void +lp_setup_set_flatshade_first( struct setup_context *setup, + boolean flatshade_first ) +{ + setup->flatshade_first = flatshade_first; } + +void +lp_setup_set_vertex_info( struct setup_context *setup, + struct vertex_info *vertex_info ) +{ + /* XXX: just silently holding onto the pointer: + */ + setup->vertex_info = vertex_info; +} + + void lp_setup_set_sampler_textures( struct setup_context *setup, unsigned num, struct pipe_texture **texture) @@ -458,6 +439,9 @@ lp_setup_set_sampler_textures( struct setup_context *setup, struct pipe_texture *dummy; unsigned i; + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); + + assert(num <= PIPE_MAX_SAMPLERS); for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { @@ -469,9 +453,10 @@ lp_setup_set_sampler_textures( struct setup_context *setup, if(tex) { struct llvmpipe_texture *lp_tex = llvmpipe_texture(tex); - struct lp_jit_texture *jit_tex = &setup->fs.jit_context.textures[i]; - jit_tex->width = tex->width[0]; - jit_tex->height = tex->height[0]; + struct lp_jit_texture *jit_tex; + jit_tex = &setup->fs.current.jit_context.textures[i]; + jit_tex->width = tex->width0; + jit_tex->height = tex->height0; jit_tex->stride = lp_tex->stride[0]; if(!lp_tex->dt) jit_tex->data = lp_tex->data; @@ -481,7 +466,7 @@ lp_setup_set_sampler_textures( struct setup_context *setup, } } - setup->fs.jit_context_dirty = TRUE; + setup->dirty |= LP_SETUP_NEW_FS; } boolean @@ -493,71 +478,182 @@ lp_setup_is_texture_referenced( struct setup_context *setup, } -/* Stubs for lines & points for now: - */ void -lp_setup_point(struct setup_context *setup, - const float (*v0)[4]) +lp_setup_update_state( struct setup_context *setup ) { - setup->point( setup, v0 ); -} + struct lp_scene *scene = lp_setup_get_current_scene(setup); -void -lp_setup_line(struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4]) -{ - setup->line( setup, v0, v1 ); -} + LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__); -void -lp_setup_tri(struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4]) -{ - setup->triangle( setup, v0, v1, v2 ); + assert(setup->fs.current.jit_function); + + if(setup->dirty & LP_SETUP_NEW_BLEND_COLOR) { + uint8_t *stored; + unsigned i, j; + + stored = lp_scene_alloc_aligned(scene, 4 * 16, 16); + + /* smear each blend color component across 16 ubyte elements */ + for (i = 0; i < 4; ++i) { + uint8_t c = float_to_ubyte(setup->blend_color.current.color[i]); + for (j = 0; j < 16; ++j) + stored[i*16 + j] = c; + } + + setup->blend_color.stored = stored; + + setup->fs.current.jit_context.blend_color = setup->blend_color.stored; + setup->dirty |= LP_SETUP_NEW_FS; + } + + + if(setup->dirty & LP_SETUP_NEW_CONSTANTS) { + struct pipe_buffer *buffer = setup->constants.current; + + if(buffer) { + unsigned current_size = buffer->size; + const void *current_data = llvmpipe_buffer(buffer)->data; + + /* TODO: copy only the actually used constants? */ + + if(setup->constants.stored_size != current_size || + !setup->constants.stored_data || + memcmp(setup->constants.stored_data, + current_data, + current_size) != 0) { + void *stored; + + stored = lp_scene_alloc(scene, current_size); + if(stored) { + memcpy(stored, + current_data, + current_size); + setup->constants.stored_size = current_size; + setup->constants.stored_data = stored; + } + } + } + else { + setup->constants.stored_size = 0; + setup->constants.stored_data = NULL; + } + + setup->fs.current.jit_context.constants = setup->constants.stored_data; + setup->dirty |= LP_SETUP_NEW_FS; + } + + + if(setup->dirty & LP_SETUP_NEW_FS) { + if(!setup->fs.stored || + memcmp(setup->fs.stored, + &setup->fs.current, + sizeof setup->fs.current) != 0) { + /* The fs state that's been stored in the scene is different from + * the new, current state. So allocate a new lp_rast_state object + * and append it to the bin's setup data buffer. + */ + struct lp_rast_state *stored = + (struct lp_rast_state *) lp_scene_alloc(scene, sizeof *stored); + if(stored) { + memcpy(stored, + &setup->fs.current, + sizeof setup->fs.current); + setup->fs.stored = stored; + + /* put the state-set command into all bins */ + lp_scene_bin_state_command( scene, + lp_rast_set_state, + lp_rast_arg_state(setup->fs.stored) ); + } + } + } + + setup->dirty = 0; + + assert(setup->fs.stored); } + +/* Only caller is lp_setup_vbuf_destroy() + */ void lp_setup_destroy( struct setup_context *setup ) { - unsigned i, j; - reset_context( setup ); - for (i = 0; i < TILES_X; i++) - for (j = 0; j < TILES_Y; j++) - FREE(setup->tile[i][j].head); + pipe_buffer_reference(&setup->constants.current, NULL); + + /* free the scenes in the 'empty' queue */ + while (lp_scene_queue_count(setup->empty_scenes) > 0) { + struct lp_scene *scene = lp_scene_dequeue(setup->empty_scenes); + if (!scene) + break; + lp_scene_destroy(scene); + } lp_rast_destroy( setup->rast ); + FREE( setup ); } /** - * Create a new primitive tiling engine. Currently also creates a - * rasterizer to use with it. + * Create a new primitive tiling engine. Plug it into the backend of + * the draw module. Currently also creates a rasterizer to use with + * it. */ struct setup_context * -lp_setup_create( void ) +lp_setup_create( struct pipe_screen *screen, + struct draw_context *draw ) { + unsigned i; struct setup_context *setup = CALLOC_STRUCT(setup_context); - unsigned i, j; - setup->rast = lp_rast_create(); + if (!setup) + return NULL; + + lp_setup_init_vbuf(setup); + + setup->empty_scenes = lp_scene_queue_create(); + if (!setup->empty_scenes) + goto fail; + + setup->rast = lp_rast_create( screen, setup->empty_scenes ); if (!setup->rast) goto fail; - for (i = 0; i < TILES_X; i++) - for (j = 0; j < TILES_Y; j++) - setup->tile[i][j].head = - setup->tile[i][j].tail = CALLOC_STRUCT(cmd_block); + setup->vbuf = draw_vbuf_stage(draw, &setup->base); + if (!setup->vbuf) + goto fail; + + draw_set_rasterize_stage(draw, setup->vbuf); + draw_set_render(draw, &setup->base); + + /* create some empty scenes */ + for (i = 0; i < MAX_SCENES; i++) { + struct lp_scene *scene = lp_scene_create(); + lp_scene_enqueue(setup->empty_scenes, scene); + } + + setup->triangle = first_triangle; + setup->line = first_line; + setup->point = first_point; + + setup->dirty = ~0; return setup; fail: + if (setup->rast) + lp_rast_destroy( setup->rast ); + + if (setup->vbuf) + ; + + if (setup->empty_scenes) + lp_scene_queue_destroy(setup->empty_scenes); + FREE(setup); return NULL; }