diff options
Diffstat (limited to 'src/gallium/auxiliary')
23 files changed, 539 insertions, 91 deletions
diff --git a/src/gallium/auxiliary/Makefile b/src/gallium/auxiliary/Makefile index c672f32b7b2..38ce14df6b6 100644 --- a/src/gallium/auxiliary/Makefile +++ b/src/gallium/auxiliary/Makefile @@ -129,6 +129,7 @@ C_SOURCES = \ util/u_simple_shaders.c \ util/u_snprintf.c \ util/u_surface.c \ + util/u_surfaces.c \ util/u_texture.c \ util/u_tile.c \ util/u_transfer.c \ diff --git a/src/gallium/auxiliary/SConscript b/src/gallium/auxiliary/SConscript index 42f2cffc812..a9ec5d4e2cc 100644 --- a/src/gallium/auxiliary/SConscript +++ b/src/gallium/auxiliary/SConscript @@ -178,6 +178,7 @@ source = [ 'util/u_simple_shaders.c', 'util/u_snprintf.c', 'util/u_surface.c', + 'util/u_surfaces.c', 'util/u_texture.c', 'util/u_tile.c', 'util/u_transfer.c', diff --git a/src/gallium/auxiliary/draw/draw_context.c b/src/gallium/auxiliary/draw/draw_context.c index b6c558ba9b1..4196f01e0b2 100644 --- a/src/gallium/auxiliary/draw/draw_context.c +++ b/src/gallium/auxiliary/draw/draw_context.c @@ -31,22 +31,33 @@ */ +#include "pipe/p_context.h" #include "util/u_memory.h" #include "util/u_math.h" #include "draw_context.h" #include "draw_vs.h" #include "draw_gs.h" +#if HAVE_LLVM +#include "gallivm/lp_bld_init.h" +#endif -struct draw_context *draw_create( void ) +struct draw_context *draw_create( struct pipe_context *pipe ) { struct draw_context *draw = CALLOC_STRUCT( draw_context ); if (draw == NULL) goto fail; +#if HAVE_LLVM + assert(lp_build_engine); + draw->engine = lp_build_engine; +#endif + if (!draw_init(draw)) goto fail; + draw->pipe = pipe; + return draw; fail: @@ -92,10 +103,23 @@ boolean draw_init(struct draw_context *draw) void draw_destroy( struct draw_context *draw ) { + struct pipe_context *pipe; + int i, j; + if (!draw) return; + pipe = draw->pipe; + /* free any rasterizer CSOs that we may have created. + */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 2; j++) { + if (draw->rasterizer_no_cull[i][j]) { + pipe->delete_rasterizer_state(pipe, draw->rasterizer_no_cull[i][j]); + } + } + } /* Not so fast -- we're just borrowing this at the moment. * @@ -137,12 +161,17 @@ void draw_set_mrd(struct draw_context *draw, double mrd) * This causes the drawing pipeline to be rebuilt. */ void draw_set_rasterizer_state( struct draw_context *draw, - const struct pipe_rasterizer_state *raster ) + const struct pipe_rasterizer_state *raster, + void *rast_handle ) { - draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); + if (!draw->suspend_flushing) { + draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE ); - draw->rasterizer = raster; - draw->bypass_clipping = draw->driver.bypass_clipping; + draw->rasterizer = raster; + draw->rast_handle = rast_handle; + + draw->bypass_clipping = draw->driver.bypass_clipping; + } } @@ -499,3 +528,37 @@ draw_current_shader_position_output(const struct draw_context *draw) return draw->gs.position_output; return draw->vs.position_output; } + + +/** + * Return a pointer/handle for a driver/CSO rasterizer object which + * disabled culling, stippling, unfilled tris, etc. + * This is used by some pipeline stages (such as wide_point, aa_line + * and aa_point) which convert points/lines into triangles. In those + * cases we don't want to accidentally cull the triangles. + * + * \param scissor should the rasterizer state enable scissoring? + * \param flatshade should the rasterizer state use flat shading? + * \return rasterizer CSO handle + */ +void * +draw_get_rasterizer_no_cull( struct draw_context *draw, + boolean scissor, + boolean flatshade ) +{ + if (!draw->rasterizer_no_cull[scissor][flatshade]) { + /* create now */ + struct pipe_context *pipe = draw->pipe; + struct pipe_rasterizer_state rast; + + memset(&rast, 0, sizeof(rast)); + rast.scissor = scissor; + rast.flatshade = flatshade; + rast.front_winding = PIPE_WINDING_CCW; + rast.gl_rasterization_rules = draw->rasterizer->gl_rasterization_rules; + + draw->rasterizer_no_cull[scissor][flatshade] = + pipe->create_rasterizer_state(pipe, &rast); + } + return draw->rasterizer_no_cull[scissor][flatshade]; +} diff --git a/src/gallium/auxiliary/draw/draw_context.h b/src/gallium/auxiliary/draw/draw_context.h index cfa0ad88d0a..7b41bb48dd3 100644 --- a/src/gallium/auxiliary/draw/draw_context.h +++ b/src/gallium/auxiliary/draw/draw_context.h @@ -48,7 +48,7 @@ struct draw_geometry_shader; struct tgsi_sampler; -struct draw_context *draw_create( void ); +struct draw_context *draw_create( struct pipe_context *pipe ); void draw_destroy( struct draw_context *draw ); @@ -59,7 +59,8 @@ void draw_set_clip_state( struct draw_context *pipe, const struct pipe_clip_state *clip ); void draw_set_rasterizer_state( struct draw_context *draw, - const struct pipe_rasterizer_state *raster ); + const struct pipe_rasterizer_state *raster, + void *rast_handle ); void draw_set_rasterize_stage( struct draw_context *draw, struct draw_stage *stage ); @@ -198,11 +199,4 @@ boolean draw_need_pipeline(const struct draw_context *draw, const struct pipe_rasterizer_state *rasterizer, unsigned prim ); -#ifdef HAVE_LLVM -/******************************************************************************* - * LLVM integration - */ -struct draw_context *draw_create_with_llvm(void); -#endif - #endif /* DRAW_CONTEXT_H */ diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index a5403a49c35..9d110317698 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -10,7 +10,6 @@ #include "gallivm/lp_bld_debug.h" #include "gallivm/lp_bld_tgsi.h" #include "gallivm/lp_bld_printf.h" -#include "gallivm/lp_bld_init.h" #include "tgsi/tgsi_exec.h" @@ -196,7 +195,7 @@ draw_llvm_create(struct draw_context *draw) init_globals(llvm); -#if 1 +#if 0 LLVMDumpModule(llvm->module); #endif @@ -223,26 +222,6 @@ draw_llvm_prepare(struct draw_llvm *llvm, int num_inputs) return variant; } - -struct draw_context *draw_create_with_llvm(void) -{ - struct draw_context *draw = CALLOC_STRUCT( draw_context ); - if (draw == NULL) - goto fail; - - assert(lp_build_engine); - draw->engine = lp_build_engine; - - if (!draw_init(draw)) - goto fail; - - return draw; - -fail: - draw_destroy( draw ); - return NULL; -} - static void generate_vs(struct draw_llvm *llvm, LLVMBuilderRef builder, diff --git a/src/gallium/auxiliary/draw/draw_pipe_aaline.c b/src/gallium/auxiliary/draw/draw_pipe_aaline.c index e96dbecd262..4faf0a779ca 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aaline.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aaline.c @@ -113,11 +113,10 @@ struct aaline_stage void (*driver_bind_sampler_states)(struct pipe_context *, unsigned, void **); + void (*driver_set_sampler_views)(struct pipe_context *, unsigned, struct pipe_sampler_view **); - - struct pipe_context *pipe; }; @@ -342,6 +341,7 @@ aa_transform_inst(struct tgsi_transform_context *ctx, static boolean generate_aaline_fs(struct aaline_stage *aaline) { + struct pipe_context *pipe = aaline->stage.draw->pipe; const struct pipe_shader_state *orig_fs = &aaline->fs->state; struct pipe_shader_state aaline_fs; struct aa_transform_context transform; @@ -374,7 +374,7 @@ generate_aaline_fs(struct aaline_stage *aaline) aaline->fs->sampler_unit = transform.freeSampler; aaline->fs->aaline_fs - = aaline->driver_create_fs_state(aaline->pipe, &aaline_fs); + = aaline->driver_create_fs_state(pipe, &aaline_fs); if (aaline->fs->aaline_fs == NULL) goto fail; @@ -394,7 +394,7 @@ fail: static boolean aaline_create_texture(struct aaline_stage *aaline) { - struct pipe_context *pipe = aaline->pipe; + struct pipe_context *pipe = aaline->stage.draw->pipe; struct pipe_screen *screen = pipe->screen; struct pipe_resource texTemp; struct pipe_sampler_view viewTempl; @@ -486,7 +486,7 @@ static boolean aaline_create_sampler(struct aaline_stage *aaline) { struct pipe_sampler_state sampler; - struct pipe_context *pipe = aaline->pipe; + struct pipe_context *pipe = aaline->stage.draw->pipe; memset(&sampler, 0, sizeof(sampler)); sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; @@ -515,13 +515,14 @@ static boolean bind_aaline_fragment_shader(struct aaline_stage *aaline) { struct draw_context *draw = aaline->stage.draw; + struct pipe_context *pipe = draw->pipe; if (!aaline->fs->aaline_fs && !generate_aaline_fs(aaline)) return FALSE; draw->suspend_flushing = TRUE; - aaline->driver_bind_fs_state(aaline->pipe, aaline->fs->aaline_fs); + aaline->driver_bind_fs_state(pipe, aaline->fs->aaline_fs); draw->suspend_flushing = FALSE; return TRUE; @@ -661,8 +662,10 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header) { auto struct aaline_stage *aaline = aaline_stage(stage); struct draw_context *draw = stage->draw; - struct pipe_context *pipe = aaline->pipe; + struct pipe_context *pipe = draw->pipe; + const struct pipe_rasterizer_state *rast = draw->rasterizer; uint num_samplers; + void *r; assert(draw->rasterizer->line_smooth); @@ -701,6 +704,11 @@ aaline_first_line(struct draw_stage *stage, struct prim_header *header) draw->suspend_flushing = TRUE; aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler); aaline->driver_set_sampler_views(pipe, num_samplers, aaline->state.sampler_views); + + /* Disable triangle culling, stippling, unfilled mode etc. */ + r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade); + pipe->bind_rasterizer_state(pipe, r); + draw->suspend_flushing = FALSE; /* now really draw first line */ @@ -714,7 +722,7 @@ aaline_flush(struct draw_stage *stage, unsigned flags) { struct draw_context *draw = stage->draw; struct aaline_stage *aaline = aaline_stage(stage); - struct pipe_context *pipe = aaline->pipe; + struct pipe_context *pipe = draw->pipe; stage->line = aaline_first_line; stage->next->flush( stage->next, flags ); @@ -727,6 +735,12 @@ aaline_flush(struct draw_stage *stage, unsigned flags) aaline->driver_set_sampler_views(pipe, aaline->num_sampler_views, aaline->state.sampler_views); + + /* restore original rasterizer state */ + if (draw->rast_handle) { + pipe->bind_rasterizer_state(pipe, draw->rast_handle); + } + draw->suspend_flushing = FALSE; draw->extra_shader_outputs.slot = 0; @@ -744,6 +758,7 @@ static void aaline_destroy(struct draw_stage *stage) { struct aaline_stage *aaline = aaline_stage(stage); + struct pipe_context *pipe = stage->draw->pipe; uint i; for (i = 0; i < PIPE_MAX_SAMPLERS; i++) { @@ -751,7 +766,7 @@ aaline_destroy(struct draw_stage *stage) } if (aaline->sampler_cso) - aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso); + pipe->delete_sampler_state(pipe, aaline->sampler_cso); if (aaline->texture) pipe_resource_reference(&aaline->texture, NULL); @@ -814,13 +829,14 @@ aaline_create_fs_state(struct pipe_context *pipe, { struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); struct aaline_fragment_shader *aafs = CALLOC_STRUCT(aaline_fragment_shader); + if (aafs == NULL) return NULL; aafs->state = *fs; /* pass-through */ - aafs->driver_fs = aaline->driver_create_fs_state(aaline->pipe, fs); + aafs->driver_fs = aaline->driver_create_fs_state(pipe, fs); return aafs; } @@ -835,8 +851,7 @@ aaline_bind_fs_state(struct pipe_context *pipe, void *fs) /* save current */ aaline->fs = aafs; /* pass-through */ - aaline->driver_bind_fs_state(aaline->pipe, - (aafs ? aafs->driver_fs : NULL)); + aaline->driver_bind_fs_state(pipe, (aafs ? aafs->driver_fs : NULL)); } @@ -845,11 +860,12 @@ aaline_delete_fs_state(struct pipe_context *pipe, void *fs) { struct aaline_stage *aaline = aaline_stage_from_pipe(pipe); struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs; + /* pass-through */ - aaline->driver_delete_fs_state(aaline->pipe, aafs->driver_fs); + aaline->driver_delete_fs_state(pipe, aafs->driver_fs); if (aafs->aaline_fs) - aaline->driver_delete_fs_state(aaline->pipe, aafs->aaline_fs); + aaline->driver_delete_fs_state(pipe, aafs->aaline_fs); FREE(aafs); } @@ -866,7 +882,7 @@ aaline_bind_sampler_states(struct pipe_context *pipe, aaline->num_samplers = num; /* pass-through */ - aaline->driver_bind_sampler_states(aaline->pipe, num, sampler); + aaline->driver_bind_sampler_states(pipe, num, sampler); } @@ -888,7 +904,7 @@ aaline_set_sampler_views(struct pipe_context *pipe, aaline->num_sampler_views = num; /* pass-through */ - aaline->driver_set_sampler_views(aaline->pipe, num, views); + aaline->driver_set_sampler_views(pipe, num, views); } @@ -911,8 +927,6 @@ draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe) if (!aaline) goto fail; - aaline->pipe = pipe; - /* create special texture, sampler state */ if (!aaline_create_texture(aaline)) goto fail; diff --git a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c index 9f9fb4312c1..bba6f50c020 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_aapoint.c +++ b/src/gallium/auxiliary/draw/draw_pipe_aapoint.c @@ -107,8 +107,6 @@ struct aapoint_stage const struct pipe_shader_state *); void (*driver_bind_fs_state)(struct pipe_context *, void *); void (*driver_delete_fs_state)(struct pipe_context *, void *); - - struct pipe_context *pipe; }; @@ -499,6 +497,7 @@ generate_aapoint_fs(struct aapoint_stage *aapoint) struct pipe_shader_state aapoint_fs; struct aa_transform_context transform; const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS; + struct pipe_context *pipe = aapoint->stage.draw->pipe; aapoint_fs = *orig_fs; /* copy to init */ aapoint_fs.tokens = tgsi_alloc_tokens(newLen); @@ -527,7 +526,7 @@ generate_aapoint_fs(struct aapoint_stage *aapoint) #endif aapoint->fs->aapoint_fs - = aapoint->driver_create_fs_state(aapoint->pipe, &aapoint_fs); + = aapoint->driver_create_fs_state(pipe, &aapoint_fs); if (aapoint->fs->aapoint_fs == NULL) goto fail; @@ -549,13 +548,14 @@ static boolean bind_aapoint_fragment_shader(struct aapoint_stage *aapoint) { struct draw_context *draw = aapoint->stage.draw; + struct pipe_context *pipe = draw->pipe; if (!aapoint->fs->aapoint_fs && !generate_aapoint_fs(aapoint)) return FALSE; draw->suspend_flushing = TRUE; - aapoint->driver_bind_fs_state(aapoint->pipe, aapoint->fs->aapoint_fs); + aapoint->driver_bind_fs_state(pipe, aapoint->fs->aapoint_fs); draw->suspend_flushing = FALSE; return TRUE; @@ -679,6 +679,9 @@ aapoint_first_point(struct draw_stage *stage, struct prim_header *header) { auto struct aapoint_stage *aapoint = aapoint_stage(stage); struct draw_context *draw = stage->draw; + struct pipe_context *pipe = draw->pipe; + const struct pipe_rasterizer_state *rast = draw->rasterizer; + void *r; assert(draw->rasterizer->point_smooth); @@ -716,6 +719,14 @@ aapoint_first_point(struct draw_stage *stage, struct prim_header *header) } } + draw->suspend_flushing = TRUE; + + /* Disable triangle culling, stippling, unfilled mode etc. */ + r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade); + pipe->bind_rasterizer_state(pipe, r); + + draw->suspend_flushing = FALSE; + /* now really draw first point */ stage->point = aapoint_point; stage->point(stage, header); @@ -727,7 +738,7 @@ aapoint_flush(struct draw_stage *stage, unsigned flags) { struct draw_context *draw = stage->draw; struct aapoint_stage *aapoint = aapoint_stage(stage); - struct pipe_context *pipe = aapoint->pipe; + struct pipe_context *pipe = draw->pipe; stage->point = aapoint_first_point; stage->next->flush( stage->next, flags ); @@ -735,6 +746,12 @@ aapoint_flush(struct draw_stage *stage, unsigned flags) /* restore original frag shader */ draw->suspend_flushing = TRUE; aapoint->driver_bind_fs_state(pipe, aapoint->fs->driver_fs); + + /* restore original rasterizer state */ + if (draw->rast_handle) { + pipe->bind_rasterizer_state(pipe, draw->rast_handle); + } + draw->suspend_flushing = FALSE; draw->extra_shader_outputs.slot = 0; @@ -811,7 +828,7 @@ aapoint_create_fs_state(struct pipe_context *pipe, aafs->state = *fs; /* pass-through */ - aafs->driver_fs = aapoint->driver_create_fs_state(aapoint->pipe, fs); + aafs->driver_fs = aapoint->driver_create_fs_state(pipe, fs); return aafs; } @@ -825,7 +842,7 @@ aapoint_bind_fs_state(struct pipe_context *pipe, void *fs) /* save current */ aapoint->fs = aafs; /* pass-through */ - aapoint->driver_bind_fs_state(aapoint->pipe, + aapoint->driver_bind_fs_state(pipe, (aafs ? aafs->driver_fs : NULL)); } @@ -837,10 +854,10 @@ aapoint_delete_fs_state(struct pipe_context *pipe, void *fs) struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs; /* pass-through */ - aapoint->driver_delete_fs_state(aapoint->pipe, aafs->driver_fs); + aapoint->driver_delete_fs_state(pipe, aafs->driver_fs); if (aafs->aapoint_fs) - aapoint->driver_delete_fs_state(aapoint->pipe, aafs->aapoint_fs); + aapoint->driver_delete_fs_state(pipe, aafs->aapoint_fs); FREE(aafs); } @@ -857,8 +874,6 @@ draw_install_aapoint_stage(struct draw_context *draw, { struct aapoint_stage *aapoint; - pipe->draw = (void *) draw; - /* * Create / install AA point drawing / prim stage */ @@ -866,8 +881,6 @@ draw_install_aapoint_stage(struct draw_context *draw, if (aapoint == NULL) return FALSE; - aapoint->pipe = pipe; - /* save original driver functions */ aapoint->driver_create_fs_state = pipe->create_fs_state; aapoint->driver_bind_fs_state = pipe->bind_fs_state; diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_line.c b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c index 3073c870825..265a420d01e 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_line.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_line.c @@ -28,6 +28,7 @@ /* Authors: Keith Whitwell <[email protected]> */ +#include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_shader_tokens.h" #include "util/u_math.h" @@ -142,9 +143,40 @@ static void wideline_line( struct draw_stage *stage, } +static void wideline_first_line( struct draw_stage *stage, + struct prim_header *header ) +{ + struct draw_context *draw = stage->draw; + struct pipe_context *pipe = draw->pipe; + const struct pipe_rasterizer_state *rast = draw->rasterizer; + void *r; + + /* Disable triangle culling, stippling, unfilled mode etc. */ + r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade); + draw->suspend_flushing = TRUE; + pipe->bind_rasterizer_state(pipe, r); + draw->suspend_flushing = FALSE; + + stage->line = wideline_line; + + wideline_line(stage, header); +} + + static void wideline_flush( struct draw_stage *stage, unsigned flags ) { + struct draw_context *draw = stage->draw; + struct pipe_context *pipe = draw->pipe; + + stage->line = wideline_first_line; stage->next->flush( stage->next, flags ); + + /* restore original rasterizer state */ + if (draw->rast_handle) { + draw->suspend_flushing = TRUE; + pipe->bind_rasterizer_state(pipe, draw->rast_handle); + draw->suspend_flushing = FALSE; + } } @@ -171,7 +203,7 @@ struct draw_stage *draw_wide_line_stage( struct draw_context *draw ) wide->stage.name = "wide-line"; wide->stage.next = NULL; wide->stage.point = draw_pipe_passthrough_point; - wide->stage.line = wideline_line; + wide->stage.line = wideline_first_line; wide->stage.tri = draw_pipe_passthrough_tri; wide->stage.flush = wideline_flush; wide->stage.reset_stipple_counter = wideline_reset_stipple_counter; diff --git a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c index 6864b4015b3..30116f4925f 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_wide_point.c +++ b/src/gallium/auxiliary/draw/draw_pipe_wide_point.c @@ -52,6 +52,7 @@ */ +#include "pipe/p_context.h" #include "util/u_math.h" #include "util/u_memory.h" #include "pipe/p_defines.h" @@ -216,33 +217,42 @@ static void widepoint_first_point( struct draw_stage *stage, { struct widepoint_stage *wide = widepoint_stage(stage); struct draw_context *draw = stage->draw; + struct pipe_context *pipe = draw->pipe; + const struct pipe_rasterizer_state *rast = draw->rasterizer; + void *r; - wide->half_point_size = 0.5f * draw->rasterizer->point_size; + wide->half_point_size = 0.5f * rast->point_size; wide->xbias = 0.0; wide->ybias = 0.0; - if (draw->rasterizer->gl_rasterization_rules) { + if (rast->gl_rasterization_rules) { wide->xbias = 0.125; } + /* Disable triangle culling, stippling, unfilled mode etc. */ + r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade); + draw->suspend_flushing = TRUE; + pipe->bind_rasterizer_state(pipe, r); + draw->suspend_flushing = FALSE; + /* XXX we won't know the real size if it's computed by the vertex shader! */ - if ((draw->rasterizer->point_size > draw->pipeline.wide_point_threshold) || - (draw->rasterizer->sprite_coord_enable && draw->pipeline.point_sprite)) { + if ((rast->point_size > draw->pipeline.wide_point_threshold) || + (rast->sprite_coord_enable && draw->pipeline.point_sprite)) { stage->point = widepoint_point; } else { stage->point = draw_pipe_passthrough_point; } - if (draw->rasterizer->sprite_coord_enable) { + if (rast->sprite_coord_enable) { /* find vertex shader texcoord outputs */ const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i, j = 0; - wide->texcoord_mode = draw->rasterizer->sprite_coord_mode; + wide->texcoord_mode = rast->sprite_coord_mode; for (i = 0; i < vs->info.num_outputs; i++) { if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_GENERIC) { wide->texcoord_slot[j] = i; - wide->texcoord_enable[j] = (draw->rasterizer->sprite_coord_enable >> j) & 1; + wide->texcoord_enable[j] = (rast->sprite_coord_enable >> j) & 1; j++; } } @@ -262,7 +272,7 @@ static void widepoint_first_point( struct draw_stage *stage, } wide->psize_slot = -1; - if (draw->rasterizer->point_size_per_vertex) { + if (rast->point_size_per_vertex) { /* find PSIZ vertex output */ const struct draw_vertex_shader *vs = draw->vs.vertex_shader; uint i; @@ -280,9 +290,19 @@ static void widepoint_first_point( struct draw_stage *stage, static void widepoint_flush( struct draw_stage *stage, unsigned flags ) { + struct draw_context *draw = stage->draw; + struct pipe_context *pipe = draw->pipe; + stage->point = widepoint_first_point; stage->next->flush( stage->next, flags ); stage->draw->extra_shader_outputs.slot = 0; + + /* restore original rasterizer state */ + if (draw->rast_handle) { + draw->suspend_flushing = TRUE; + pipe->bind_rasterizer_state(pipe, draw->rast_handle); + draw->suspend_flushing = FALSE; + } } diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h index 33b0c196d4e..0b3c9e69bd5 100644 --- a/src/gallium/auxiliary/draw/draw_private.h +++ b/src/gallium/auxiliary/draw/draw_private.h @@ -86,6 +86,8 @@ struct vertex_header { */ struct draw_context { + struct pipe_context *pipe; + /** Drawing/primitive pipeline stages */ struct { struct draw_stage *first; /**< one of the following */ @@ -179,8 +181,14 @@ struct draw_context double mrd; /**< minimum resolvable depth value, for polygon offset */ - /* pipe state that we need: */ + /** Current rasterizer state given to us by the driver */ const struct pipe_rasterizer_state *rasterizer; + /** Driver CSO handle for the current rasterizer state */ + void *rast_handle; + + /** Rasterizer CSOs without culling/stipple/etc */ + void *rasterizer_no_cull[2][2]; + struct pipe_viewport_state viewport; boolean identity_viewport; @@ -244,6 +252,7 @@ struct draw_context #ifdef HAVE_LLVM LLVMExecutionEngineRef engine; + boolean use_llvm; #endif void *driver_private; }; @@ -357,5 +366,10 @@ void draw_do_flush( struct draw_context *draw, unsigned flags ); +void * +draw_get_rasterizer_no_cull( struct draw_context *draw, + boolean scissor, + boolean flatshade ); + #endif /* DRAW_PRIVATE_H */ diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c index aa1f7064a3a..b5876bb1bdb 100644 --- a/src/gallium/auxiliary/draw/draw_pt.c +++ b/src/gallium/auxiliary/draw/draw_pt.c @@ -142,7 +142,9 @@ boolean draw_pt_init( struct draw_context *draw ) return FALSE; #if HAVE_LLVM - draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit_llvm( draw ); + draw->use_llvm = debug_get_bool_option("DRAW_USE_LLVM", TRUE); + if (draw->use_llvm) + draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit_llvm( draw ); #else draw->pt.middle.general = NULL; #endif diff --git a/src/gallium/auxiliary/gallivm/lp_bld_pack.c b/src/gallium/auxiliary/gallivm/lp_bld_pack.c index 2daa8a3b582..186f8849b8d 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_pack.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_pack.c @@ -263,8 +263,6 @@ lp_build_pack2(LLVMBuilderRef builder, LLVMValueRef shuffle; LLVMValueRef res; - dst_vec_type = lp_build_vec_type(dst_type); - assert(!src_type.floating); assert(!dst_type.floating); assert(src_type.width == dst_type.width * 2); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample.h b/src/gallium/auxiliary/gallivm/lp_bld_sample.h index 8c1af95c506..e2873763857 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample.h +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample.h @@ -119,6 +119,11 @@ struct lp_sampler_dynamic_state unsigned unit); LLVMValueRef + (*img_stride)( struct lp_sampler_dynamic_state *state, + LLVMBuilderRef builder, + unsigned unit); + + LLVMValueRef (*data_ptr)( struct lp_sampler_dynamic_state *state, LLVMBuilderRef builder, unsigned unit); diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c index 767429ba060..c9b613e21c8 100644 --- a/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c +++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_soa.c @@ -1534,7 +1534,7 @@ lp_build_sample_general(struct lp_build_sample_context *bld, LLVMValueRef height_vec, LLVMValueRef depth_vec, LLVMValueRef row_stride_array, - LLVMValueRef img_stride_vec, + LLVMValueRef img_stride_array, LLVMValueRef data_array, LLVMValueRef *colors_out) { @@ -1602,8 +1602,9 @@ lp_build_sample_general(struct lp_build_sample_context *bld, row_stride0_vec = lp_build_get_level_stride_vec(bld, row_stride_array, ilevel0); if (dims == 3 || bld->static_state->target == PIPE_TEXTURE_CUBE) { - img_stride0_vec = lp_build_mul(&bld->int_coord_bld, - row_stride0_vec, height0_vec); + img_stride0_vec = lp_build_get_level_stride_vec(bld, + img_stride_array, + ilevel0); if (dims == 3) { depth0_vec = lp_build_minify(bld, depth_vec, ilevel0_vec); } @@ -1617,8 +1618,9 @@ lp_build_sample_general(struct lp_build_sample_context *bld, row_stride1_vec = lp_build_get_level_stride_vec(bld, row_stride_array, ilevel1); if (dims == 3 || bld->static_state->target == PIPE_TEXTURE_CUBE) { - img_stride1_vec = lp_build_mul(&bld->int_coord_bld, - row_stride1_vec, height1_vec); + img_stride1_vec = lp_build_get_level_stride_vec(bld, + img_stride_array, + ilevel1); if (dims ==3) { depth1_vec = lp_build_minify(bld, depth_vec, ilevel1_vec); } @@ -2002,7 +2004,7 @@ lp_build_sample_soa(LLVMBuilderRef builder, LLVMValueRef width, width_vec; LLVMValueRef height, height_vec; LLVMValueRef depth, depth_vec; - LLVMValueRef stride_array; + LLVMValueRef row_stride_array, img_stride_array; LLVMValueRef data_array; LLVMValueRef s; LLVMValueRef t; @@ -2033,7 +2035,8 @@ lp_build_sample_soa(LLVMBuilderRef builder, width = dynamic_state->width(dynamic_state, builder, unit); height = dynamic_state->height(dynamic_state, builder, unit); depth = dynamic_state->depth(dynamic_state, builder, unit); - stride_array = dynamic_state->row_stride(dynamic_state, builder, unit); + row_stride_array = dynamic_state->row_stride(dynamic_state, builder, unit); + img_stride_array = dynamic_state->img_stride(dynamic_state, builder, unit); data_array = dynamic_state->data_ptr(dynamic_state, builder, unit); /* Note that data_array is an array[level] of pointers to texture images */ @@ -2054,13 +2057,14 @@ lp_build_sample_soa(LLVMBuilderRef builder, is_simple_wrap_mode(static_state->wrap_t)) { /* special case */ lp_build_sample_2d_linear_aos(&bld, s, t, width_vec, height_vec, - stride_array, data_array, texel); + row_stride_array, data_array, texel); } else { lp_build_sample_general(&bld, unit, s, t, r, width, height, depth, width_vec, height_vec, depth_vec, - stride_array, NULL, data_array, + row_stride_array, img_stride_array, + data_array, texel); } diff --git a/src/gallium/auxiliary/tgsi/tgsi_exec.c b/src/gallium/auxiliary/tgsi/tgsi_exec.c index f853ea2820e..11045e4ba2f 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_exec.c +++ b/src/gallium/auxiliary/tgsi/tgsi_exec.c @@ -1796,6 +1796,12 @@ exec_declaration(struct tgsi_exec_machine *mach, last = decl->Range.Last; mask = decl->Declaration.UsageMask; + /* XXX we could remove this special-case code since + * mach->InterpCoefs[first].a0 should already have the + * front/back-face value. But we should first update the + * ureg code to emit the right UsageMask value (WRITEMASK_X). + * Then, we could remove the tgsi_exec_machine::Face field. + */ if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) { uint i; diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c index 3d0455de7ce..f725405ade1 100644 --- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c +++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c @@ -1158,7 +1158,7 @@ static void emit_decl_range( struct ureg_program *ureg, out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; out[0].decl.NrTokens = 2; out[0].decl.File = file; - out[0].decl.UsageMask = 0xf; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT; out[0].decl.Semantic = 0; @@ -1180,7 +1180,7 @@ emit_decl_range2D(struct ureg_program *ureg, out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION; out[0].decl.NrTokens = 3; out[0].decl.File = file; - out[0].decl.UsageMask = 0xf; + out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; out[0].decl.Interpolate = TGSI_INTERPOLATE_CONSTANT; out[0].decl.Dimension = 1; diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c index 7850f81e585..e45310b9bb7 100644 --- a/src/gallium/auxiliary/util/u_blit.c +++ b/src/gallium/auxiliary/util/u_blit.c @@ -374,6 +374,7 @@ util_blit_pixels_writemask(struct blit_state *ctx, texTemp.width0 = srcW; texTemp.height0 = srcH; texTemp.depth0 = 1; + texTemp.bind = PIPE_BIND_SAMPLER_VIEW; tex = screen->resource_create(screen, &texTemp); if (!tex) diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c index f3b42f7bf9c..956aedc8a15 100644 --- a/src/gallium/auxiliary/util/u_blitter.c +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -132,6 +132,7 @@ struct blitter_context *util_blitter_create(struct pipe_context *pipe) ctx->blitter.saved_fb_state.nr_cbufs = ~0; ctx->blitter.saved_num_sampler_views = ~0; ctx->blitter.saved_num_sampler_states = ~0; + ctx->blitter.saved_num_vertex_buffers = ~0; /* blend state objects */ memset(&blend, 0, sizeof(blend)); @@ -318,6 +319,13 @@ static void blitter_restore_CSOs(struct blitter_context_priv *ctx) ctx->blitter.saved_sampler_views); ctx->blitter.saved_num_sampler_views = ~0; } + + if (ctx->blitter.saved_num_vertex_buffers != ~0) { + pipe->set_vertex_buffers(pipe, + ctx->blitter.saved_num_vertex_buffers, + ctx->blitter.saved_vertex_buffers); + ctx->blitter.saved_num_vertex_buffers = ~0; + } } static void blitter_set_rectangle(struct blitter_context_priv *ctx, diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h index 2ad7201a29d..f6e3ce4874e 100644 --- a/src/gallium/auxiliary/util/u_blitter.h +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -57,6 +57,9 @@ struct blitter_context int saved_num_sampler_views; struct pipe_sampler_view *saved_sampler_views[PIPE_MAX_SAMPLERS]; + + int saved_num_vertex_buffers; + struct pipe_vertex_buffer saved_vertex_buffers[PIPE_MAX_ATTRIBS]; }; /** @@ -255,6 +258,19 @@ util_blitter_save_fragment_sampler_views(struct blitter_context *blitter, num_views * sizeof(struct pipe_sampler_view *)); } +static INLINE void +util_blitter_save_vertex_buffers(struct blitter_context *blitter, + int num_vertex_buffers, + struct pipe_vertex_buffer *vertex_buffers) +{ + assert(num_vertex_buffers <= Elements(blitter->saved_vertex_buffers)); + + blitter->saved_num_vertex_buffers = num_vertex_buffers; + memcpy(blitter->saved_vertex_buffers, + vertex_buffers, + num_vertex_buffers * sizeof(struct pipe_vertex_buffer)); +} + #ifdef __cplusplus } #endif diff --git a/src/gallium/auxiliary/util/u_dirty_surfaces.h b/src/gallium/auxiliary/util/u_dirty_surfaces.h new file mode 100644 index 00000000000..99f260bf967 --- /dev/null +++ b/src/gallium/auxiliary/util/u_dirty_surfaces.h @@ -0,0 +1,88 @@ +#ifndef U_DIRTY_SURFACES_H_ +#define U_DIRTY_SURFACES_H_ + +#include "util/u_double_list.h" +#include "util/u_math.h" + +typedef void (*util_dirty_surface_flush_t) (struct pipe_context *, struct pipe_surface *); + +struct util_dirty_surfaces +{ + struct list_head dirty_list; +}; + +struct util_dirty_surface +{ + struct pipe_surface base; + struct list_head dirty_list; +}; + +static INLINE void +util_dirty_surfaces_init(struct util_dirty_surfaces *ds) +{ + LIST_INITHEAD(&ds->dirty_list); +} + +static INLINE void +util_dirty_surfaces_use_for_sampling(struct pipe_context *pipe, struct util_dirty_surfaces *dss, util_dirty_surface_flush_t flush) +{ + struct list_head *p, *next; + for(p = dss->dirty_list.next; p != &dss->dirty_list; p = next) + { + struct util_dirty_surface *ds = LIST_ENTRY(struct util_dirty_surface, p, dirty_list); + next = p->next; + + flush(pipe, &ds->base); + } +} + +static INLINE void +util_dirty_surfaces_use_levels_for_sampling(struct pipe_context *pipe, struct util_dirty_surfaces *dss, unsigned first, unsigned last, util_dirty_surface_flush_t flush) +{ + struct list_head *p, *next; + if(first > last) + return; + for(p = dss->dirty_list.next; p != &dss->dirty_list; p = next) + { + struct util_dirty_surface *ds = LIST_ENTRY(struct util_dirty_surface, p, dirty_list); + next = p->next; + + if(ds->base.level >= first && ds->base.level <= last) + flush(pipe, &ds->base); + } +} + +static INLINE void +util_dirty_surfaces_use_for_sampling_with(struct pipe_context *pipe, struct util_dirty_surfaces *dss, struct pipe_sampler_view *psv, struct pipe_sampler_state *pss, util_dirty_surface_flush_t flush) +{ + if(!LIST_IS_EMPTY(&dss->dirty_list)) + util_dirty_surfaces_use_levels_for_sampling(pipe, dss, (unsigned)pss->min_lod + psv->first_level, MIN2((unsigned)ceilf(pss->max_lod) + psv->first_level, psv->last_level), flush); +} + +static INLINE void +util_dirty_surface_init(struct util_dirty_surface *ds) +{ + LIST_INITHEAD(&ds->dirty_list); +} + +static INLINE boolean +util_dirty_surface_is_dirty(struct util_dirty_surface *ds) +{ + return !LIST_IS_EMPTY(&ds->dirty_list); +} + +static INLINE void +util_dirty_surface_set_dirty(struct util_dirty_surfaces *dss, struct util_dirty_surface *ds) +{ + if(LIST_IS_EMPTY(&ds->dirty_list)) + LIST_ADDTAIL(&ds->dirty_list, &dss->dirty_list); +} + +static INLINE void +util_dirty_surface_set_clean(struct util_dirty_surfaces *dss, struct util_dirty_surface *ds) +{ + if(!LIST_IS_EMPTY(&ds->dirty_list)) + LIST_DELINIT(&ds->dirty_list); +} + +#endif diff --git a/src/gallium/auxiliary/util/u_inlines.h b/src/gallium/auxiliary/util/u_inlines.h index c2f4f05990b..089adcf3827 100644 --- a/src/gallium/auxiliary/util/u_inlines.h +++ b/src/gallium/auxiliary/util/u_inlines.h @@ -35,6 +35,7 @@ #include "util/u_debug.h" #include "util/u_atomic.h" #include "util/u_box.h" +#include "util/u_math.h" #ifdef __cplusplus @@ -121,6 +122,28 @@ pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_ *ptr = view; } +static INLINE void +pipe_surface_reset(struct pipe_surface* ps, struct pipe_resource *pt, + unsigned face, unsigned level, unsigned zslice, unsigned flags) +{ + pipe_resource_reference(&ps->texture, pt); + ps->format = pt->format; + ps->width = u_minify(pt->width0, level); + ps->height = u_minify(pt->height0, level); + ps->usage = flags; + ps->face = face; + ps->level = level; + ps->zslice = zslice; +} + +static INLINE void +pipe_surface_init(struct pipe_surface* ps, struct pipe_resource *pt, + unsigned face, unsigned level, unsigned zslice, unsigned flags) +{ + ps->texture = 0; + pipe_reference_init(&ps->reference, 1); + pipe_surface_reset(ps, pt, face, level, zslice, flags); +} /* * Convenience wrappers for screen buffer functions. diff --git a/src/gallium/auxiliary/util/u_surfaces.c b/src/gallium/auxiliary/util/u_surfaces.c new file mode 100644 index 00000000000..0be4609a207 --- /dev/null +++ b/src/gallium/auxiliary/util/u_surfaces.c @@ -0,0 +1,112 @@ +#include "u_surfaces.h" +#include "util/u_hash_table.h" +#include "util/u_inlines.h" +#include "util/u_memory.h" + +/* TODO: ouch, util_hash_table should do these by default when passed a null function pointer + * this indirect function call is quite bad + */ +static unsigned +hash(void *key) +{ + return (unsigned)key; +} + +static int +compare(void *key1, void *key2) +{ + return (unsigned)key1 - (unsigned)key2; +} + +struct pipe_surface * +util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) +{ + struct pipe_surface *ps; + void *key = NULL; + + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + { /* or 2D array */ + if(!us->u.table) + us->u.table = util_hash_table_create(hash, compare); + key = (void *)(((zslice + face) << 8) | level); + /* TODO: ouch, should have a get-reference function... + * also, shouldn't allocate a two-pointer structure for each item... */ + ps = util_hash_table_get(us->u.table, key); + } + else + { + if(!us->u.array) + us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *)); + ps = us->u.array[level]; + } + + if(ps) + { + p_atomic_inc(&ps->reference.count); + return ps; + } + + ps = (struct pipe_surface *)CALLOC(1, surface_struct_size); + if(!ps) + return NULL; + + pipe_surface_init(ps, pt, face, level, zslice, flags); + ps->offset = ~0; + + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + util_hash_table_set(us->u.table, key, ps); + else + us->u.array[level] = ps; + + return ps; +} + +void +util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps) +{ + struct pipe_resource *pt = ps->texture; + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + { /* or 2D array */ + void* key = (void*)(((ps->zslice + ps->face) << 8) | ps->level); + util_hash_table_remove(us->u.table, key); + } + else + us->u.array[ps->level] = 0; +} + +static enum pipe_error +util_surfaces_destroy_callback(void *key, void *value, void *data) +{ + void (*destroy_surface) (struct pipe_surface * ps) = data; + destroy_surface((struct pipe_surface *)value); + return PIPE_OK; +} + +void +util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *)) +{ + if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE) + { /* or 2D array */ + if(us->u.table) + { + util_hash_table_foreach(us->u.table, util_surfaces_destroy_callback, destroy_surface); + util_hash_table_destroy(us->u.table); + us->u.table = NULL; + } + } + else + { + if(us->u.array) + { + unsigned i; + for(i = 0; i < pt->last_level; ++i) + { + struct pipe_surface *ps = us->u.array[i]; + if(ps) + destroy_surface(ps); + } + free(us->u.array); + us->u.array = NULL; + } + } +} diff --git a/src/gallium/auxiliary/util/u_surfaces.h b/src/gallium/auxiliary/util/u_surfaces.h new file mode 100644 index 00000000000..6de5e7cc17e --- /dev/null +++ b/src/gallium/auxiliary/util/u_surfaces.h @@ -0,0 +1,54 @@ +#ifndef U_SURFACES_H_ +#define U_SURFACES_H_ + +#include "pipe/p_compiler.h" +#include "pipe/p_state.h" +#include "util/u_atomic.h" + +struct util_hash_table; + +struct util_surfaces +{ + union + { + struct util_hash_table *table; + struct pipe_surface **array; + } u; +}; + +struct pipe_surface *util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags); + +/* fast inline path for the very common case */ +static INLINE struct pipe_surface * +util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size, struct pipe_screen *pscreen, struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned flags) +{ + if(likely(pt->target == PIPE_TEXTURE_2D && us->u.array)) + { + struct pipe_surface *ps = us->u.array[level]; + if(ps) + { + p_atomic_inc(&ps->reference.count); + return ps; + } + } + + return util_surfaces_do_get(us, surface_struct_size, pscreen, pt, face, level, zslice, flags); +} + +void util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps); + +static INLINE void +util_surfaces_detach(struct util_surfaces *us, struct pipe_surface *ps) +{ + if(likely(ps->texture->target == PIPE_TEXTURE_2D)) + { + us->u.array[ps->level] = 0; + return; + } + + return util_surfaces_do_detach(us, ps); +} + +void util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *)); + +#endif |