diff options
Diffstat (limited to 'src/gallium')
78 files changed, 1080 insertions, 380 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 diff --git a/src/gallium/drivers/i915/i915_context.c b/src/gallium/drivers/i915/i915_context.c index beddc139964..2af9bdac956 100644 --- a/src/gallium/drivers/i915/i915_context.c +++ b/src/gallium/drivers/i915/i915_context.c @@ -175,7 +175,7 @@ i915_create_context(struct pipe_screen *screen, void *priv) /* * Create drawing context and plug our rendering stage into it. */ - i915->draw = draw_create(); + i915->draw = draw_create(&i915->base); assert(i915->draw); if (!debug_get_bool_option("I915_NO_VBUF", FALSE)) { draw_set_rasterize_stage(i915->draw, i915_draw_vbuf_stage(i915)); diff --git a/src/gallium/drivers/i915/i915_resource_buffer.c b/src/gallium/drivers/i915/i915_resource_buffer.c index d2f8afeee7c..0744cc926ae 100644 --- a/src/gallium/drivers/i915/i915_resource_buffer.c +++ b/src/gallium/drivers/i915/i915_resource_buffer.c @@ -33,7 +33,6 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "util/u_inlines.h" -#include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" diff --git a/src/gallium/drivers/i915/i915_state.c b/src/gallium/drivers/i915/i915_state.c index 397647204b4..f883883852a 100644 --- a/src/gallium/drivers/i915/i915_state.c +++ b/src/gallium/drivers/i915/i915_state.c @@ -737,7 +737,8 @@ static void i915_bind_rasterizer_state( struct pipe_context *pipe, /* pass-through to draw module */ draw_set_rasterizer_state(i915->draw, - (i915->rasterizer ? i915->rasterizer->templ : NULL)); + (i915->rasterizer ? i915->rasterizer->templ : NULL), + raster); i915->dirty |= I915_NEW_RASTERIZER; } diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c index 868e112ba3f..f7cf06d8d46 100644 --- a/src/gallium/drivers/llvmpipe/lp_context.c +++ b/src/gallium/drivers/llvmpipe/lp_context.c @@ -45,10 +45,6 @@ #include "lp_query.h" #include "lp_setup.h" - -#define USE_DRAW_LLVM 0 - - static void llvmpipe_destroy( struct pipe_context *pipe ) { struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); @@ -162,11 +158,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv ) /* * Create drawing context and plug our rendering stage into it. */ -#if USE_DRAW_LLVM - llvmpipe->draw = draw_create_with_llvm(); -#else - llvmpipe->draw = draw_create(); -#endif + llvmpipe->draw = draw_create(&llvmpipe->pipe); if (!llvmpipe->draw) goto fail; diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c index 7e8a117cc82..8690941a507 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.c +++ b/src/gallium/drivers/llvmpipe/lp_jit.c @@ -51,7 +51,7 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) /* struct lp_jit_texture */ { - LLVMTypeRef elem_types[6]; + LLVMTypeRef elem_types[LP_JIT_TEXTURE_NUM_FIELDS]; elem_types[LP_JIT_TEXTURE_WIDTH] = LLVMInt32Type(); elem_types[LP_JIT_TEXTURE_HEIGHT] = LLVMInt32Type(); @@ -59,6 +59,8 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) elem_types[LP_JIT_TEXTURE_LAST_LEVEL] = LLVMInt32Type(); elem_types[LP_JIT_TEXTURE_ROW_STRIDE] = LLVMArrayType(LLVMInt32Type(), LP_MAX_TEXTURE_LEVELS); + elem_types[LP_JIT_TEXTURE_IMG_STRIDE] = + LLVMArrayType(LLVMInt32Type(), LP_MAX_TEXTURE_LEVELS); elem_types[LP_JIT_TEXTURE_DATA] = LLVMArrayType(LLVMPointerType(LLVMInt8Type(), 0), LP_MAX_TEXTURE_LEVELS); @@ -80,6 +82,9 @@ lp_jit_init_globals(struct llvmpipe_screen *screen) LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, row_stride, screen->target, texture_type, LP_JIT_TEXTURE_ROW_STRIDE); + LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, img_stride, + screen->target, texture_type, + LP_JIT_TEXTURE_IMG_STRIDE); LP_CHECK_MEMBER_OFFSET(struct lp_jit_texture, data, screen->target, texture_type, LP_JIT_TEXTURE_DATA); diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h index 3790a71eab4..5d0268c68c4 100644 --- a/src/gallium/drivers/llvmpipe/lp_jit.h +++ b/src/gallium/drivers/llvmpipe/lp_jit.h @@ -52,6 +52,7 @@ struct lp_jit_texture uint32_t depth; uint32_t last_level; uint32_t row_stride[LP_MAX_TEXTURE_LEVELS]; + uint32_t img_stride[LP_MAX_TEXTURE_LEVELS]; const void *data[LP_MAX_TEXTURE_LEVELS]; }; @@ -62,7 +63,9 @@ enum { LP_JIT_TEXTURE_DEPTH, LP_JIT_TEXTURE_LAST_LEVEL, LP_JIT_TEXTURE_ROW_STRIDE, - LP_JIT_TEXTURE_DATA + LP_JIT_TEXTURE_IMG_STRIDE, + LP_JIT_TEXTURE_DATA, + LP_JIT_TEXTURE_NUM_FIELDS /* number of fields above */ }; diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c index 4574f411456..527103c75cf 100644 --- a/src/gallium/drivers/llvmpipe/lp_rast.c +++ b/src/gallium/drivers/llvmpipe/lp_rast.c @@ -162,7 +162,7 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, assert(cbuf); lpt = llvmpipe_resource(cbuf->texture); task->color_tiles[buf] = llvmpipe_get_texture_tile(lpt, - cbuf->face, + cbuf->face + cbuf->zslice, cbuf->level, usage, x, y); @@ -184,7 +184,7 @@ lp_rast_tile_begin(struct lp_rasterizer_task *task, * and update the tile's layout info. */ (void) llvmpipe_get_texture_tile(lpt, - zsbuf->face, + zsbuf->face + zsbuf->zslice, zsbuf->level, usage, x, y); @@ -344,7 +344,7 @@ lp_rast_load_color(struct lp_rasterizer_task *task, assert(cbuf); lpt = llvmpipe_texture(cbuf->texture); task->color_tiles[buf] = llvmpipe_get_texture_tile(lpt, - cbuf->face, + cbuf->face + cbuf->zslice, cbuf->level, usage, task->x, task->y); diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c index ffbc7fc4ea0..6be13c60a57 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup.c +++ b/src/gallium/drivers/llvmpipe/lp_setup.c @@ -526,15 +526,11 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, /* regular texture - setup array of mipmap level pointers */ int j; for (j = 0; j <= tex->last_level; j++) { -#if 0 jit_tex->data[j] = - (ubyte *) lp_tex->data + lp_tex->level_offset[j]; -#else - jit_tex->data[j] = - llvmpipe_get_texture_image(lp_tex, 0, j, LP_TEX_USAGE_READ, - LP_TEX_LAYOUT_LINEAR); -#endif - jit_tex->row_stride[j] = lp_tex->stride[j]; + llvmpipe_get_texture_image_all(lp_tex, j, LP_TEX_USAGE_READ, + LP_TEX_LAYOUT_LINEAR); + jit_tex->row_stride[j] = lp_tex->row_stride[j]; + jit_tex->img_stride[j] = lp_tex->img_stride[j]; } } else { @@ -547,7 +543,8 @@ lp_setup_set_fragment_sampler_views(struct lp_setup_context *setup, struct sw_winsys *winsys = screen->winsys; jit_tex->data[0] = winsys->displaytarget_map(winsys, lp_tex->dt, PIPE_TRANSFER_READ); - jit_tex->row_stride[0] = lp_tex->stride[0]; + jit_tex->row_stride[0] = lp_tex->row_stride[0]; + jit_tex->img_stride[0] = lp_tex->img_stride[0]; assert(jit_tex->data[0]); } } diff --git a/src/gallium/drivers/llvmpipe/lp_setup_tri.c b/src/gallium/drivers/llvmpipe/lp_setup_tri.c index 25e6b3edfb3..a95053444bf 100644 --- a/src/gallium/drivers/llvmpipe/lp_setup_tri.c +++ b/src/gallium/drivers/llvmpipe/lp_setup_tri.c @@ -601,6 +601,9 @@ do_triangle_ccw(struct lp_setup_context *setup, } +/** + * Draw triangle if it's CW, cull otherwise. + */ static void triangle_cw( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], @@ -610,6 +613,9 @@ static void triangle_cw( struct lp_setup_context *setup, } +/** + * Draw triangle if it's CCW, cull otherwise. + */ static void triangle_ccw( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], @@ -619,6 +625,10 @@ static void triangle_ccw( struct lp_setup_context *setup, } + +/** + * Draw triangle whether it's CW or CCW. + */ static void triangle_both( struct lp_setup_context *setup, const float (*v0)[4], const float (*v1)[4], diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c index 6aa1e581bb3..18f28289e36 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_fs.c +++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c @@ -37,7 +37,7 @@ * - early depth test * - fragment shader * - alpha test - * - depth/stencil test (stencil TBI) + * - depth/stencil test * - blending * * This file has only the glue to assemble the fragment pipeline. The actual diff --git a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c index 6df3ef25b0e..47f65fe72d1 100644 --- a/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c +++ b/src/gallium/drivers/llvmpipe/lp_state_rasterizer.c @@ -38,19 +38,26 @@ void * llvmpipe_create_rasterizer_state(struct pipe_context *pipe, const struct pipe_rasterizer_state *rast) { + /* We do nothing special with rasterizer state. + * The CSO handle is just a pointer to a pipe_rasterizer_state object. + */ return mem_dup(rast, sizeof(*rast)); } -void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, - void *rasterizer) + + +void +llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, void *handle) { struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe); + const struct pipe_rasterizer_state *rasterizer = + (const struct pipe_rasterizer_state *) handle; if (llvmpipe->rasterizer == rasterizer) return; /* pass-through to draw module */ - draw_set_rasterizer_state(llvmpipe->draw, rasterizer); + draw_set_rasterizer_state(llvmpipe->draw, rasterizer, handle); llvmpipe->rasterizer = rasterizer; @@ -69,6 +76,7 @@ void llvmpipe_bind_rasterizer_state(struct pipe_context *pipe, llvmpipe->dirty |= LP_NEW_RASTERIZER; } + void llvmpipe_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer) { diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c index 4fee40fd099..1a116989d4c 100644 --- a/src/gallium/drivers/llvmpipe/lp_surface.c +++ b/src/gallium/drivers/llvmpipe/lp_surface.c @@ -135,10 +135,11 @@ lp_surface_copy(struct pipe_context *pipe, LP_TEX_LAYOUT_LINEAR); util_copy_rect(dst_linear_ptr, format, - dst_tex->stride[dst->level], + llvmpipe_resource_stride(&dst_tex->base, dst->level), dstx, dsty, width, height, - src_linear_ptr, src_tex->stride[src->level], + src_linear_ptr, + llvmpipe_resource_stride(&src_tex->base, src->level), srcx, srcy); } } diff --git a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c index 4715cfe4f62..74b7393e4ec 100644 --- a/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c +++ b/src/gallium/drivers/llvmpipe/lp_tex_sample_llvm.c @@ -148,6 +148,7 @@ LP_LLVM_TEXTURE_MEMBER(height, LP_JIT_TEXTURE_HEIGHT, TRUE) LP_LLVM_TEXTURE_MEMBER(depth, LP_JIT_TEXTURE_DEPTH, TRUE) LP_LLVM_TEXTURE_MEMBER(last_level, LP_JIT_TEXTURE_LAST_LEVEL, TRUE) LP_LLVM_TEXTURE_MEMBER(row_stride, LP_JIT_TEXTURE_ROW_STRIDE, FALSE) +LP_LLVM_TEXTURE_MEMBER(img_stride, LP_JIT_TEXTURE_IMG_STRIDE, FALSE) LP_LLVM_TEXTURE_MEMBER(data_ptr, LP_JIT_TEXTURE_DATA, FALSE) @@ -205,6 +206,7 @@ lp_llvm_sampler_soa_create(const struct lp_sampler_static_state *static_state, sampler->dynamic_state.base.depth = lp_llvm_texture_depth; sampler->dynamic_state.base.last_level = lp_llvm_texture_last_level; sampler->dynamic_state.base.row_stride = lp_llvm_texture_row_stride; + sampler->dynamic_state.base.img_stride = lp_llvm_texture_img_stride; sampler->dynamic_state.base.data_ptr = lp_llvm_texture_data_ptr; sampler->dynamic_state.static_state = static_state; sampler->dynamic_state.context_ptr = context_ptr; diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 2267fcb29ca..45739e94cb0 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -72,16 +72,16 @@ resource_is_texture(const struct pipe_resource *resource) * The number of elements is width_in_tiles * height_in_tiles. */ static enum lp_texture_layout * -alloc_layout_array(unsigned width, unsigned height) +alloc_layout_array(unsigned num_slices, unsigned width, unsigned height) { const unsigned tx = align(width, TILE_SIZE) / TILE_SIZE; const unsigned ty = align(height, TILE_SIZE) / TILE_SIZE; - assert(tx * ty > 0); + assert(num_slices * tx * ty > 0); assert(LP_TEX_LAYOUT_NONE == 0); /* calloc'ing LP_TEX_LAYOUT_NONE here */ return (enum lp_texture_layout *) - calloc(tx * ty, sizeof(enum lp_texture_layout)); + calloc(num_slices * tx * ty, sizeof(enum lp_texture_layout)); } @@ -98,30 +98,41 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; + unsigned depth = pt->depth0; assert(LP_MAX_TEXTURE_2D_LEVELS <= LP_MAX_TEXTURE_LEVELS); assert(LP_MAX_TEXTURE_3D_LEVELS <= LP_MAX_TEXTURE_LEVELS); for (level = 0; level <= pt->last_level; level++) { - const unsigned num_faces = lpr->base.target == PIPE_TEXTURE_CUBE ? 6 : 1; - unsigned nblocksx, face; + const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; + const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; + unsigned nblocksx, num_slices; + + if (lpr->base.target == PIPE_TEXTURE_CUBE) + num_slices = 6; + else if (lpr->base.target == PIPE_TEXTURE_3D) + num_slices = depth; + else + num_slices = 1; /* Allocate storage for whole quads. This is particularly important * for depth surfaces, which are currently stored in a swizzled format. */ nblocksx = util_format_get_nblocksx(pt->format, align(width, TILE_SIZE)); - lpr->stride[level] = + lpr->row_stride[level] = align(nblocksx * util_format_get_blocksize(pt->format), 16); - lpr->tiles_per_row[level] = align(width, TILE_SIZE) / TILE_SIZE; + lpr->img_stride[level] = lpr->row_stride[level] * align(height, TILE_SIZE); - for (face = 0; face < num_faces; face++) { - lpr->layout[face][level] = alloc_layout_array(width, height); - } + lpr->tiles_per_row[level] = width_t; + lpr->tiles_per_image[level] = width_t * height_t; + lpr->num_slices_faces[level] = num_slices; + lpr->layout[level] = alloc_layout_array(num_slices, width, height); width = u_minify(width, 1); height = u_minify(height, 1); + depth = u_minify(depth, 1); } return TRUE; @@ -138,19 +149,24 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, /* Round up the surface size to a multiple of the tile size to * avoid tile clipping. */ - unsigned width = align(lpr->base.width0, TILE_SIZE); - unsigned height = align(lpr->base.height0, TILE_SIZE); + const unsigned width = align(lpr->base.width0, TILE_SIZE); + const unsigned height = align(lpr->base.height0, TILE_SIZE); + const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; + const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; - lpr->tiles_per_row[0] = align(width, TILE_SIZE) / TILE_SIZE; + lpr->tiles_per_row[0] = width_t; + lpr->tiles_per_image[0] = width_t * height_t; + lpr->num_slices_faces[0] = 1; + lpr->img_stride[0] = 0; - lpr->layout[0][0] = alloc_layout_array(width, height); + lpr->layout[0] = alloc_layout_array(1, width, height); lpr->dt = winsys->displaytarget_create(winsys, lpr->base.bind, lpr->base.format, width, height, 16, - &lpr->stride[0] ); + &lpr->row_stride[0] ); return lpr->dt != NULL; } @@ -178,14 +194,14 @@ llvmpipe_resource_create(struct pipe_screen *_screen, /* displayable surface */ if (!llvmpipe_displaytarget_layout(screen, lpr)) goto fail; - assert(lpr->layout[0][0][0] == LP_TEX_LAYOUT_NONE); + assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE); } else if (lpr->base.bind & (PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL)) { /* texture map */ if (!llvmpipe_texture_layout(screen, lpr)) goto fail; - assert(lpr->layout[0][0][0] == LP_TEX_LAYOUT_NONE); + assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE); } else { /* other data (vertex buffer, const buffer, etc) */ @@ -201,7 +217,7 @@ llvmpipe_resource_create(struct pipe_screen *_screen, } if (resource_is_texture(&lpr->base)) { - assert(lpr->layout[0][0]); + assert(lpr->layout[0]); } lpr->id = id_counter++; @@ -228,8 +244,7 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen, } else if (resource_is_texture(pt)) { /* regular texture */ - const uint num_faces = pt->target == PIPE_TEXTURE_CUBE ? 6 : 1; - uint level, face; + uint level; /* free linear image data */ for (level = 0; level < Elements(lpr->linear); level++) { @@ -249,10 +264,8 @@ llvmpipe_resource_destroy(struct pipe_screen *pscreen, /* free layout flag arrays */ for (level = 0; level < Elements(lpr->tiled); level++) { - for (face = 0; face < num_faces; face++) { - free(lpr->layout[face][level]); - lpr->layout[face][level] = NULL; - } + free(lpr->layout[level]); + lpr->layout[level] = NULL; } } else if (!lpr->userBuffer) { @@ -312,36 +325,24 @@ llvmpipe_resource_map(struct pipe_resource *resource, /* install this linear image in texture data structure */ lpr->linear[level].data = map; - map = llvmpipe_get_texture_image(lpr, face, level, tex_usage, layout); + map = llvmpipe_get_texture_image(lpr, face + zslice, level, + tex_usage, layout); assert(map); return map; } else if (resource_is_texture(resource)) { /* regular texture */ - const unsigned tex_height = u_minify(resource->height0, level); - const unsigned nblocksy = - util_format_get_nblocksy(resource->format, tex_height); - const unsigned stride = lpr->stride[level]; - unsigned offset = 0; - - if (resource->target == PIPE_TEXTURE_CUBE) { - /* XXX incorrect - offset = face * nblocksy * stride; - */ - } - else if (resource->target == PIPE_TEXTURE_3D) { - offset = zslice * nblocksy * stride; - } - else { + if (resource->target != PIPE_TEXTURE_CUBE) { assert(face == 0); + } + if (resource->target != PIPE_TEXTURE_3D) { assert(zslice == 0); - offset = 0; } - map = llvmpipe_get_texture_image(lpr, face, level, tex_usage, layout); + map = llvmpipe_get_texture_image(lpr, face + zslice, level, + tex_usage, layout); assert(map); - map += offset; return map; } else { @@ -371,7 +372,7 @@ llvmpipe_resource_unmap(struct pipe_resource *resource, assert(zslice == 0); /* make sure linear image is up to date */ - (void) llvmpipe_get_texture_image(lpr, 0, 0, + (void) llvmpipe_get_texture_image(lpr, face + zslice, level, LP_TEX_USAGE_READ, LP_TEX_LAYOUT_LINEAR); @@ -411,7 +412,7 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen, lpr->dt = winsys->displaytarget_from_handle(winsys, template, whandle, - &lpr->stride[0]); + &lpr->row_stride[0]); if (!lpr->dt) goto fail; @@ -498,7 +499,7 @@ llvmpipe_get_transfer(struct pipe_context *pipe, pipe_resource_reference(&pt->resource, resource); pt->box = *box; pt->sr = sr; - pt->stride = lprex->stride[sr.level]; + pt->stride = lprex->row_stride[sr.level]; pt->usage = usage; return pt; @@ -659,37 +660,49 @@ llvmpipe_user_buffer_create(struct pipe_screen *screen, /** * Compute size (in bytes) need to store a texture image / mipmap level, - * for just one cube face. + * for just one cube face or one 3D texture slice */ static unsigned tex_image_face_size(const struct llvmpipe_resource *lpr, unsigned level, enum lp_texture_layout layout) { - /* for tiled layout, force a 32bpp format */ - enum pipe_format format = layout == LP_TEX_LAYOUT_TILED - ? PIPE_FORMAT_B8G8R8A8_UNORM : lpr->base.format; + const unsigned width = u_minify(lpr->base.width0, level); const unsigned height = u_minify(lpr->base.height0, level); - const unsigned depth = u_minify(lpr->base.depth0, level); - const unsigned nblocksy = - util_format_get_nblocksy(format, align(height, TILE_SIZE)); - const unsigned buffer_size = - nblocksy * lpr->stride[level] * - (lpr->base.target == PIPE_TEXTURE_3D ? depth : 1); - return buffer_size; + + assert(layout == LP_TEX_LAYOUT_TILED || + layout == LP_TEX_LAYOUT_LINEAR); + + if (layout == LP_TEX_LAYOUT_TILED) { + /* for tiled layout, force a 32bpp format */ + const enum pipe_format format = PIPE_FORMAT_B8G8R8A8_UNORM; + const unsigned block_size = util_format_get_blocksize(format); + const unsigned nblocksy = + util_format_get_nblocksy(format, align(height, TILE_SIZE)); + const unsigned nblocksx = + util_format_get_nblocksx(format, align(width, TILE_SIZE)); + const unsigned buffer_size = block_size * nblocksy * nblocksx; + return buffer_size; + } + else { + const enum pipe_format format = lpr->base.format; + const unsigned nblocksy = + util_format_get_nblocksy(format, align(height, TILE_SIZE)); + const unsigned buffer_size = nblocksy * lpr->row_stride[level]; + return buffer_size; + } } /** * Compute size (in bytes) need to store a texture image / mipmap level, - * including all cube faces. + * including all cube faces or 3D image slices */ static unsigned tex_image_size(const struct llvmpipe_resource *lpr, unsigned level, enum lp_texture_layout layout) { const unsigned buf_size = tex_image_face_size(lpr, level, layout); - const unsigned num_faces = lpr->base.target == PIPE_TEXTURE_CUBE ? 6 : 1; - return buf_size * num_faces; + return buf_size * lpr->num_slices_faces[level]; } @@ -780,15 +793,64 @@ llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr, } +static INLINE enum lp_texture_layout +llvmpipe_get_texture_tile_layout(const struct llvmpipe_resource *lpr, + unsigned face_slice, unsigned level, + unsigned x, unsigned y) +{ + uint i; + assert(resource_is_texture(&lpr->base)); + assert(x < lpr->tiles_per_row[level]); + i = face_slice * lpr->tiles_per_image[level] + + y * lpr->tiles_per_row[level] + x; + return lpr->layout[level][i]; +} + + +static INLINE void +llvmpipe_set_texture_tile_layout(struct llvmpipe_resource *lpr, + unsigned face_slice, unsigned level, + unsigned x, unsigned y, + enum lp_texture_layout layout) +{ + uint i; + assert(resource_is_texture(&lpr->base)); + assert(x < lpr->tiles_per_row[level]); + i = face_slice * lpr->tiles_per_image[level] + + y * lpr->tiles_per_row[level] + x; + lpr->layout[level][i] = layout; +} + + +/** + * Set the layout mode for all tiles in a particular image. + */ +static INLINE void +llvmpipe_set_texture_image_layout(struct llvmpipe_resource *lpr, + unsigned face_slice, unsigned level, + unsigned width_t, unsigned height_t, + enum lp_texture_layout layout) +{ + const unsigned start = face_slice * lpr->tiles_per_image[level]; + unsigned i; + + for (i = 0; i < width_t * height_t; i++) { + lpr->layout[level][start + i] = layout; + } +} + /** - * Return pointer to texture image data (either linear or tiled layout). + * Return pointer to texture image data (either linear or tiled layout) + * for a particular cube face or 3D texture slice. + * + * \param face_slice the cube face or 3D slice of interest * \param usage one of LP_TEX_USAGE_READ/WRITE_ALL/READ_WRITE - * \param layout either LP_TEX_LAYOUT_LINEAR or LP_TEX_LAYOUT_TILED + * \param layout either LP_TEX_LAYOUT_LINEAR or _TILED or _NONE */ void * llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, - unsigned face, unsigned level, + unsigned face_slice, unsigned level, enum lp_texture_usage usage, enum lp_texture_layout layout) { @@ -807,6 +869,7 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE; const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE; enum lp_texture_layout other_layout; + boolean only_allocate; assert(layout == LP_TEX_LAYOUT_NONE || layout == LP_TEX_LAYOUT_TILED || @@ -816,6 +879,15 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, usage == LP_TEX_USAGE_READ_WRITE || usage == LP_TEX_USAGE_WRITE_ALL); + /* check for the special case of layout == LP_TEX_LAYOUT_NONE */ + if (layout == LP_TEX_LAYOUT_NONE) { + only_allocate = TRUE; + layout = LP_TEX_LAYOUT_TILED; + } + else { + only_allocate = FALSE; + } + if (lpr->dt) { assert(lpr->linear[level].data); } @@ -842,30 +914,39 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, target_data = target_img->data; } - if (face > 0) { - unsigned offset = face * tex_image_face_size(lpr, level, layout); + if (face_slice > 0) { + unsigned target_offset, other_offset; + + target_offset = face_slice * tex_image_face_size(lpr, level, layout); + other_offset = face_slice * tex_image_face_size(lpr, level, other_layout); if (target_data) { - target_data = (uint8_t *) target_data + offset; + target_data = (uint8_t *) target_data + target_offset; } if (other_data) { - other_data = (uint8_t *) other_data + offset; + other_data = (uint8_t *) other_data + other_offset; } } - if (layout == LP_TEX_LAYOUT_NONE) { - /* just allocating memory */ + if (only_allocate) { + /* Just allocating tiled memory. Don't initialize it from the + * linear data if it exists. + */ + llvmpipe_set_texture_image_layout(lpr, face_slice, level, + width_t, height_t, layout); + return target_data; } if (other_data) { /* may need to convert other data to the requested layout */ enum lp_texture_layout new_layout; - unsigned x, y, i = 0; + unsigned x, y; /* loop over all image tiles, doing layout conversion where needed */ for (y = 0; y < height_t; y++) { for (x = 0; x < width_t; x++) { - enum lp_texture_layout cur_layout = lpr->layout[face][level][i]; + enum lp_texture_layout cur_layout = + llvmpipe_get_texture_tile_layout(lpr, face_slice, level, x, y); boolean convert; layout_logic(cur_layout, layout, usage, &new_layout, &convert); @@ -876,28 +957,26 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE, lpr->base.format, - lpr->stride[level]); + lpr->row_stride[level]); } else { lp_tiled_to_linear(other_data, target_data, x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE, lpr->base.format, - lpr->stride[level]); + lpr->row_stride[level]); } } - lpr->layout[face][level][i] = new_layout; - i++; + llvmpipe_set_texture_tile_layout(lpr, face_slice, level, x, y, + new_layout); } } } else { /* no other data */ - unsigned i; - for (i = 0; i < width_t * height_t; i++) { - lpr->layout[face][level][i] = layout; - } + llvmpipe_set_texture_image_layout(lpr, face_slice, level, + width_t, height_t, layout); } assert(target_data); @@ -906,33 +985,33 @@ llvmpipe_get_texture_image(struct llvmpipe_resource *lpr, } -static INLINE enum lp_texture_layout -llvmpipe_get_texture_tile_layout(const struct llvmpipe_resource *lpr, - unsigned face, unsigned level, - unsigned x, unsigned y) +/** + * Return pointer to start of a texture image (1D, 2D, 3D, CUBE). + * All cube faces and 3D slices will be converted to the requested + * layout if needed. + * This is typically used when we're about to sample from a texture. + */ +void * +llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr, + unsigned level, + enum lp_texture_usage usage, + enum lp_texture_layout layout) { - uint i; - assert(resource_is_texture(&lpr->base)); - assert(x < lpr->tiles_per_row[level]); - i = y * lpr->tiles_per_row[level] + x; - return lpr->layout[face][level][i]; -} + const int slices = lpr->num_slices_faces[level]; + int slice; + void *map; + assert(slices > 0); -static INLINE void -llvmpipe_set_texture_tile_layout(struct llvmpipe_resource *lpr, - unsigned face, unsigned level, - unsigned x, unsigned y, - enum lp_texture_layout layout) -{ - uint i; - assert(resource_is_texture(&lpr->base)); - assert(x < lpr->tiles_per_row[level]); - i = y * lpr->tiles_per_row[level] + x; - lpr->layout[face][level][i] = layout; + for (slice = slices - 1; slice >= 0; slice--) { + map = llvmpipe_get_texture_image(lpr, slice, level, usage, layout); + } + + return map; } + /** * Get pointer to a linear image where the tile at (x,y) is known to be * in linear layout. @@ -941,7 +1020,7 @@ llvmpipe_set_texture_tile_layout(struct llvmpipe_resource *lpr, */ ubyte * llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, - unsigned face, unsigned level, + unsigned face_slice, unsigned level, enum lp_texture_usage usage, unsigned x, unsigned y) { @@ -961,7 +1040,7 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, linear_img->data = align_malloc(buffer_size, 16); } - cur_layout = llvmpipe_get_texture_tile_layout(lpr, face, level, tx, ty); + cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty); layout_logic(cur_layout, LP_TEX_LAYOUT_LINEAR, usage, &new_layout, &convert); @@ -969,15 +1048,15 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, if (convert) { lp_tiled_to_linear(tiled_img->data, linear_img->data, x, y, TILE_SIZE, TILE_SIZE, lpr->base.format, - lpr->stride[level]); + lpr->row_stride[level]); } if (new_layout != cur_layout) - llvmpipe_set_texture_tile_layout(lpr, face, level, tx, ty, new_layout); + llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout); - if (face > 0) { + if (face_slice > 0) { unsigned offset - = face * tex_image_face_size(lpr, level, LP_TEX_LAYOUT_LINEAR); + = face_slice * tex_image_face_size(lpr, level, LP_TEX_LAYOUT_LINEAR); return (ubyte *) linear_img->data + offset; } else { @@ -992,7 +1071,7 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, */ ubyte * llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, - unsigned face, unsigned level, + unsigned face_slice, unsigned level, enum lp_texture_usage usage, unsigned x, unsigned y) { @@ -1012,21 +1091,21 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, tiled_img->data = align_malloc(buffer_size, 16); } - cur_layout = llvmpipe_get_texture_tile_layout(lpr, face, level, tx, ty); + cur_layout = llvmpipe_get_texture_tile_layout(lpr, face_slice, level, tx, ty); layout_logic(cur_layout, LP_TEX_LAYOUT_TILED, usage, &new_layout, &convert); if (convert) { lp_linear_to_tiled(linear_img->data, tiled_img->data, x, y, TILE_SIZE, TILE_SIZE, lpr->base.format, - lpr->stride[level]); + lpr->row_stride[level]); } if (new_layout != cur_layout) - llvmpipe_set_texture_tile_layout(lpr, face, level, tx, ty, new_layout); + llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty, new_layout); /* compute, return address of the 64x64 tile */ { - unsigned tiles_per_row, tile_offset, face_offset; + unsigned tiles_per_row, tile_offset, face_slice_offset; tiles_per_row = align(width, TILE_SIZE) / TILE_SIZE; @@ -1037,11 +1116,11 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, assert(tiled_img->data); - face_offset = (face > 0) - ? (face * tex_image_face_size(lpr, level, LP_TEX_LAYOUT_TILED)) + face_slice_offset = (face_slice > 0) + ? (face_slice * tex_image_face_size(lpr, level, LP_TEX_LAYOUT_TILED)) : 0; - return (ubyte *) tiled_img->data + face_offset + tile_offset; + return (ubyte *) tiled_img->data + face_slice_offset + tile_offset; } } diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h index 134666db6f6..5862f979da6 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.h +++ b/src/gallium/drivers/llvmpipe/lp_texture.h @@ -92,8 +92,13 @@ struct llvmpipe_resource struct pipe_resource base; /** Row stride in bytes */ - unsigned stride[LP_MAX_TEXTURE_LEVELS]; + unsigned row_stride[LP_MAX_TEXTURE_LEVELS]; + /** Image stride (for cube maps or 3D textures) in bytes */ + unsigned img_stride[LP_MAX_TEXTURE_LEVELS]; unsigned tiles_per_row[LP_MAX_TEXTURE_LEVELS]; + unsigned tiles_per_image[LP_MAX_TEXTURE_LEVELS]; + /** Number of 3D slices or cube faces per level */ + unsigned num_slices_faces[LP_MAX_TEXTURE_LEVELS]; /** * Display target, for textures with the PIPE_BIND_DISPLAY_TARGET @@ -112,8 +117,8 @@ struct llvmpipe_resource */ void *data; - /** per-tile layout info */ - enum lp_texture_layout *layout[PIPE_TEX_FACE_MAX][LP_MAX_TEXTURE_LEVELS]; + /** array [level][face or slice][tile_y][tile_x] of layout values) */ + enum lp_texture_layout *layout[LP_MAX_TEXTURE_LEVELS]; boolean userBuffer; /** Is this a user-space buffer? */ unsigned timestamp; @@ -161,13 +166,13 @@ llvmpipe_resource_stride(struct pipe_resource *resource, { struct llvmpipe_resource *lpr = llvmpipe_resource(resource); assert(level < LP_MAX_TEXTURE_2D_LEVELS); - return lpr->stride[level]; + return lpr->row_stride[level]; } void * llvmpipe_resource_map(struct pipe_resource *resource, - unsigned face, + unsigned face_slice, unsigned level, unsigned zslice, enum lp_texture_usage tex_usage, @@ -175,7 +180,7 @@ llvmpipe_resource_map(struct pipe_resource *resource, void llvmpipe_resource_unmap(struct pipe_resource *resource, - unsigned face, + unsigned face_slice, unsigned level, unsigned zslice); @@ -186,25 +191,30 @@ llvmpipe_resource_data(struct pipe_resource *resource); void * llvmpipe_get_texture_image_address(struct llvmpipe_resource *lpr, - unsigned face, unsigned level, + unsigned face_slice, unsigned level, enum lp_texture_layout layout); void * llvmpipe_get_texture_image(struct llvmpipe_resource *resource, - unsigned face, unsigned level, + unsigned face_slice, unsigned level, enum lp_texture_usage usage, enum lp_texture_layout layout); +void * +llvmpipe_get_texture_image_all(struct llvmpipe_resource *lpr, + unsigned level, + enum lp_texture_usage usage, + enum lp_texture_layout layout); ubyte * llvmpipe_get_texture_tile_linear(struct llvmpipe_resource *lpr, - unsigned face, unsigned level, + unsigned face_slice, unsigned level, enum lp_texture_usage usage, unsigned x, unsigned y); ubyte * llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr, - unsigned face, unsigned level, + unsigned face_slice, unsigned level, enum lp_texture_usage usage, unsigned x, unsigned y); diff --git a/src/gallium/drivers/nouveau/nouveau_screen.h b/src/gallium/drivers/nouveau/nouveau_screen.h index 747fd15acdd..8eacdff0358 100644 --- a/src/gallium/drivers/nouveau/nouveau_screen.h +++ b/src/gallium/drivers/nouveau/nouveau_screen.h @@ -1,6 +1,8 @@ #ifndef __NOUVEAU_SCREEN_H__ #define __NOUVEAU_SCREEN_H__ +#include "pipe/p_screen.h" + struct nouveau_screen { struct pipe_screen base; struct nouveau_device *device; diff --git a/src/gallium/drivers/nv50/nv50_context.c b/src/gallium/drivers/nv50/nv50_context.c index f543b3c504d..915a9254025 100644 --- a/src/gallium/drivers/nv50/nv50_context.c +++ b/src/gallium/drivers/nv50/nv50_context.c @@ -97,7 +97,7 @@ nv50_create(struct pipe_screen *pscreen, void *priv) nv50_init_query_functions(nv50); nv50_init_resource_functions(&nv50->pipe); - nv50->draw = draw_create(); + nv50->draw = draw_create(&nv50->pipe); assert(nv50->draw); draw_set_rasterize_stage(nv50->draw, nv50_draw_render_stage(nv50)); diff --git a/src/gallium/drivers/nv50/nv50_screen.h b/src/gallium/drivers/nv50/nv50_screen.h index 092333a3b10..40ebbee72e2 100644 --- a/src/gallium/drivers/nv50/nv50_screen.h +++ b/src/gallium/drivers/nv50/nv50_screen.h @@ -2,7 +2,8 @@ #define __NV50_SCREEN_H__ #include "nouveau/nouveau_screen.h" -#include "nv50_context.h" + +struct nv50_context; struct nv50_screen { struct nouveau_screen base; diff --git a/src/gallium/drivers/nvfx/nv04_surface_2d.c b/src/gallium/drivers/nvfx/nv04_surface_2d.c index a1507bbb3ca..4ed574227d6 100644 --- a/src/gallium/drivers/nvfx/nv04_surface_2d.c +++ b/src/gallium/drivers/nvfx/nv04_surface_2d.c @@ -497,6 +497,9 @@ struct nv04_surface* nv04_surface_wrap_for_render(struct pipe_screen *pscreen, struct nv04_surface_2d* eng2d, struct nv04_surface* ns) { + struct pipe_resource templ; + struct pipe_resource* temp_tex; + struct nv04_surface* temp_ns; int temp_flags; temp_flags = (ns->base.usage | @@ -506,7 +509,6 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, ns->base.usage = (PIPE_BIND_BLIT_SOURCE | PIPE_BIND_BLIT_DESTINATION); - struct pipe_resource templ; memset(&templ, 0, sizeof(templ)); templ.format = ns->base.texture->format; templ.target = PIPE_TEXTURE_2D; @@ -520,8 +522,8 @@ nv04_surface_wrap_for_render(struct pipe_screen *pscreen, templ.bind = ns->base.texture->bind | PIPE_BIND_RENDER_TARGET; - struct pipe_resource* temp_tex = pscreen->resource_create(pscreen, &templ); - struct nv04_surface* temp_ns = (struct nv04_surface*)pscreen->get_tex_surface(pscreen, temp_tex, 0, 0, 0, temp_flags); + temp_tex = pscreen->resource_create(pscreen, &templ); + temp_ns = (struct nv04_surface*)pscreen->get_tex_surface(pscreen, temp_tex, 0, 0, 0, temp_flags); temp_ns->backing = ns; if(ns->base.usage & PIPE_BIND_BLIT_SOURCE) diff --git a/src/gallium/drivers/nvfx/nv04_surface_2d.h b/src/gallium/drivers/nvfx/nv04_surface_2d.h index b2b237b9dfa..2123c3ed08b 100644 --- a/src/gallium/drivers/nvfx/nv04_surface_2d.h +++ b/src/gallium/drivers/nvfx/nv04_surface_2d.h @@ -1,6 +1,10 @@ #ifndef __NV04_SURFACE_2D_H__ #define __NV04_SURFACE_2D_H__ +#include "pipe/p_state.h" + +struct nouveau_screen; + struct nv04_surface { struct pipe_surface base; unsigned pitch; diff --git a/src/gallium/drivers/nvfx/nvfx_context.c b/src/gallium/drivers/nvfx/nvfx_context.c index 1faa0af31fb..6d2dc4d5bf6 100644 --- a/src/gallium/drivers/nvfx/nvfx_context.c +++ b/src/gallium/drivers/nvfx/nvfx_context.c @@ -70,7 +70,7 @@ nvfx_create(struct pipe_screen *pscreen, void *priv) nvfx_init_resource_functions(&nvfx->pipe); /* Create, configure, and install fallback swtnl path */ - nvfx->draw = draw_create(); + nvfx->draw = draw_create(&nvfx->pipe); draw_wide_point_threshold(nvfx->draw, 9999999.0); draw_wide_line_threshold(nvfx->draw, 9999999.0); draw_enable_line_stipple(nvfx->draw, FALSE); diff --git a/src/gallium/drivers/nvfx/nvfx_fragprog.c b/src/gallium/drivers/nvfx/nvfx_fragprog.c index aaa30bd60e3..6772d9bd516 100644 --- a/src/gallium/drivers/nvfx/nvfx_fragprog.c +++ b/src/gallium/drivers/nvfx/nvfx_fragprog.c @@ -846,6 +846,8 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx) if (!fp->translated) { + const int min_size = 4096; + nvfx_fragprog_translate(nvfx, fp); if (!fp->translated) { static unsigned dummy[8] = {1, 0, 0, 0, 1, 0, 0, 0}; @@ -866,7 +868,6 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx) fp->prog_size = (fp->insn_len * 4 + 63) & ~63; - int min_size = 4096; if(fp->prog_size >= min_size) fp->progs_per_bo = 1; else @@ -874,10 +875,15 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx) fp->bo_prog_idx = fp->progs_per_bo - 1; } - if (nvfx->dirty & NVFX_NEW_FRAGCONST) + /* we must update constants even on "just" fragprog changes, because + we don't check whether the current constant buffer matches the latest + one bound to this fragment program */ + if (nvfx->dirty & (NVFX_NEW_FRAGCONST | NVFX_NEW_FRAGPROG)) update = TRUE; if(update) { + int offset; + ++fp->bo_prog_idx; if(fp->bo_prog_idx >= fp->progs_per_bo) { @@ -888,6 +894,8 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx) else { struct nvfx_fragment_program_bo* fpbo = os_malloc_aligned(sizeof(struct nvfx_fragment_program) + fp->prog_size * fp->progs_per_bo, 16); + char *map, *buf; + if(fp->fpbo) { fpbo->next = fp->fpbo->next; @@ -900,8 +908,8 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx) nouveau_bo_new(nvfx->screen->base.device, NOUVEAU_BO_VRAM | NOUVEAU_BO_MAP, 64, fp->prog_size * fp->progs_per_bo, &fpbo->bo); nouveau_bo_map(fpbo->bo, NOUVEAU_BO_NOSYNC); - char* map = fpbo->bo->map; - char* buf = fpbo->insn; + map = fpbo->bo->map; + buf = fpbo->insn; for(int i = 0; i < fp->progs_per_bo; ++i) { memcpy(buf, fp->insn, fp->insn_len * 4); @@ -913,7 +921,7 @@ nvfx_fragprog_validate(struct nvfx_context *nvfx) fp->bo_prog_idx = 0; } - int offset = fp->bo_prog_idx * fp->prog_size; + offset = fp->bo_prog_idx * fp->prog_size; if(nvfx->constbuf[PIPE_SHADER_FRAGMENT]) { struct pipe_resource* constbuf = nvfx->constbuf[PIPE_SHADER_FRAGMENT]; diff --git a/src/gallium/drivers/nvfx/nvfx_fragtex.c b/src/gallium/drivers/nvfx/nvfx_fragtex.c index f5f6b0c0cbd..0b4a434fecc 100644 --- a/src/gallium/drivers/nvfx/nvfx_fragtex.c +++ b/src/gallium/drivers/nvfx/nvfx_fragtex.c @@ -40,11 +40,14 @@ nvfx_fragtex_relocate(struct nvfx_context *nvfx) samplers = nvfx->hw_samplers; while (samplers) { + struct nvfx_miptree* mt; + struct nouveau_bo *bo; + unit = ffs(samplers) - 1; samplers &= ~(1 << unit); - struct nvfx_miptree* mt = (struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture; - struct nouveau_bo *bo = mt->base.bo; + mt = (struct nvfx_miptree*)nvfx->fragment_sampler_views[unit]->texture; + bo = mt->base.bo; MARK_RING(chan, 3, 3); OUT_RELOC(chan, bo, RING_3D(NV34TCL_TX_OFFSET(unit), 2), tex_flags | NOUVEAU_BO_DUMMY, 0, 0); diff --git a/src/gallium/drivers/nvfx/nvfx_screen.c b/src/gallium/drivers/nvfx/nvfx_screen.c index 04b456d4087..9f03ab1833b 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.c +++ b/src/gallium/drivers/nvfx/nvfx_screen.c @@ -316,6 +316,7 @@ nvfx_screen_get_vertex_buffer_flags(struct nvfx_screen* screen) struct pipe_screen * nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) { + static const unsigned query_sizes[] = {(4096 - 4 * 32) / 32, 3 * 1024 / 32, 2 * 1024 / 32, 1024 / 32}; struct nvfx_screen *screen = CALLOC_STRUCT(nvfx_screen); struct nouveau_channel *chan; struct pipe_screen *pscreen; @@ -401,7 +402,6 @@ nvfx_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev) } /* Query objects */ - unsigned query_sizes[] = {(4096 - 4 * 32) / 32, 3 * 1024 / 32, 2 * 1024 / 32, 1024 / 32}; for(i = 0; i < sizeof(query_sizes) / sizeof(query_sizes[0]); ++i) { ret = nouveau_notifier_alloc(chan, 0xbeef0302, query_sizes[i], &screen->query); diff --git a/src/gallium/drivers/nvfx/nvfx_screen.h b/src/gallium/drivers/nvfx/nvfx_screen.h index 127d8919af4..5e1c3945aef 100644 --- a/src/gallium/drivers/nvfx/nvfx_screen.h +++ b/src/gallium/drivers/nvfx/nvfx_screen.h @@ -4,7 +4,8 @@ #include "util/u_double_list.h" #include "nouveau/nouveau_screen.h" #include "nv04_surface_2d.h" -#include "nvfx_context.h" + +struct nvfx_context; struct nvfx_screen { struct nouveau_screen base; diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c index 4137849bf0b..f91ae19ecd3 100644 --- a/src/gallium/drivers/nvfx/nvfx_state_emit.c +++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c @@ -159,7 +159,8 @@ nvfx_state_validate_swtnl(struct nvfx_context *nvfx) draw_bind_vertex_shader(draw, nvfx->vertprog->draw); if (nvfx->draw_dirty & NVFX_NEW_RAST) - draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe); + draw_set_rasterizer_state(draw, &nvfx->rasterizer->pipe, + nvfx->rasterizer); if (nvfx->draw_dirty & NVFX_NEW_UCP) draw_set_clip_state(draw, &nvfx->clip); diff --git a/src/gallium/drivers/nvfx/nvfx_vbo.c b/src/gallium/drivers/nvfx/nvfx_vbo.c index d441d032d9d..4d7b7f181d8 100644 --- a/src/gallium/drivers/nvfx/nvfx_vbo.c +++ b/src/gallium/drivers/nvfx/nvfx_vbo.c @@ -122,11 +122,12 @@ nvfx_vbo_static_attrib(struct nvfx_context *nvfx, struct pipe_transfer *transfer; struct nouveau_channel* chan = nvfx->screen->base.channel; void *map; + float *v; map = pipe_buffer_map(&nvfx->pipe, vb->buffer, PIPE_TRANSFER_READ, &transfer); - map += vb->buffer_offset + ve->src_offset; + map = (uint8_t *) map + vb->buffer_offset + ve->src_offset; - float *v = map; + v = map; switch (ncomp) { case 4: @@ -173,11 +174,11 @@ nvfx_draw_arrays(struct pipe_context *pipe, } while (count) { - unsigned vc, nr; + unsigned vc, nr, avail; nvfx_state_emit(nvfx); - unsigned avail = AVAIL_RING(chan); + avail = AVAIL_RING(chan); avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */ vc = nouveau_vbuf_split(avail, 6, 256, @@ -229,11 +230,11 @@ nvfx_draw_elements_u08(struct nvfx_context *nvfx, void *ib, while (count) { uint8_t *elts = (uint8_t *)ib + start; - unsigned vc, push, restart = 0; + unsigned vc, push, restart = 0, avail; nvfx_state_emit(nvfx); - unsigned avail = AVAIL_RING(chan); + avail = AVAIL_RING(chan); avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */ vc = nouveau_vbuf_split(avail, 6, 2, @@ -282,11 +283,11 @@ nvfx_draw_elements_u16(struct nvfx_context *nvfx, void *ib, while (count) { uint16_t *elts = (uint16_t *)ib + start; - unsigned vc, push, restart = 0; + unsigned vc, push, restart = 0, avail; nvfx_state_emit(nvfx); - unsigned avail = AVAIL_RING(chan); + avail = AVAIL_RING(chan); avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */ vc = nouveau_vbuf_split(avail, 6, 2, @@ -335,11 +336,11 @@ nvfx_draw_elements_u32(struct nvfx_context *nvfx, void *ib, while (count) { uint32_t *elts = (uint32_t *)ib + start; - unsigned vc, push, restart = 0; + unsigned vc, push, restart = 0, avail; nvfx_state_emit(nvfx); - unsigned avail = AVAIL_RING(chan); + avail = AVAIL_RING(chan); avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */ vc = nouveau_vbuf_split(avail, 5, 1, @@ -416,11 +417,11 @@ nvfx_draw_elements_vbo(struct pipe_context *pipe, unsigned restart = 0; while (count) { - unsigned nr, vc; + unsigned nr, vc, avail; nvfx_state_emit(nvfx); - unsigned avail = AVAIL_RING(chan); + avail = AVAIL_RING(chan); avail -= 16 + (avail >> 10); /* for the BEGIN_RING_NIs, conservatively assuming one every 1024, plus 16 for safety */ vc = nouveau_vbuf_split(avail, 6, 256, diff --git a/src/gallium/drivers/r300/r300_blit.c b/src/gallium/drivers/r300/r300_blit.c index e84b79ae902..e15c71eef65 100644 --- a/src/gallium/drivers/r300/r300_blit.c +++ b/src/gallium/drivers/r300/r300_blit.c @@ -37,6 +37,9 @@ static void r300_blitter_save_states(struct r300_context* r300) util_blitter_save_viewport(r300->blitter, &r300->viewport); util_blitter_save_clip(r300->blitter, &r300->clip); util_blitter_save_vertex_elements(r300->blitter, r300->velems); + /* XXX this crashes the driver + util_blitter_save_vertex_buffers(r300->blitter, r300->vertex_buffer_count, + r300->vertex_buffer); */ } /* Clear currently bound buffers. */ diff --git a/src/gallium/drivers/r300/r300_chipset.c b/src/gallium/drivers/r300/r300_chipset.c index 9b2163e44cc..928a310bd81 100644 --- a/src/gallium/drivers/r300/r300_chipset.c +++ b/src/gallium/drivers/r300/r300_chipset.c @@ -108,6 +108,7 @@ void r300_parse_chipset(struct r300_capabilities* caps) case 0x3150: case 0x3152: case 0x3154: + case 0x3155: case 0x3E50: case 0x3E54: caps->family = CHIP_FAMILY_RV380; @@ -370,4 +371,6 @@ void r300_parse_chipset(struct r300_capabilities* caps) fprintf(stderr, "r300: Warning: Unknown chipset 0x%x\n", caps->pci_id); } + + caps->is_rv350 = caps->family >= CHIP_FAMILY_RV350; } diff --git a/src/gallium/drivers/r300/r300_chipset.h b/src/gallium/drivers/r300/r300_chipset.h index ff957b7c29c..ab649c38573 100644 --- a/src/gallium/drivers/r300/r300_chipset.h +++ b/src/gallium/drivers/r300/r300_chipset.h @@ -42,18 +42,28 @@ struct r300_capabilities { unsigned num_tex_units; /* Whether or not TCL is physically present */ boolean has_tcl; - /* Whether or not this is R400. The differences compared to their R3xx + /* Whether or not this is RV350 or newer, including all r400 and r500 + * chipsets. The differences compared to the oldest r300 chips are: + * - Blend LTE/GTE thresholds + * - Better MACRO_SWITCH in texture tiling + * - Half float vertex + * - More HyperZ optimizations */ + boolean is_rv350; + /* Whether or not this is R400. The differences compared their rv350 * cousins are: * - Extended fragment shader registers - * - Blend LTE/GTE thresholds */ + * - 3DC texture compression (RGTC2) */ boolean is_r400; /* Whether or not this is an RV515 or newer; R500s have many differences - * that require extra consideration, compared to their R3xx cousins: + * that require extra consideration, compared to their rv350 cousins: * - Extra bit of width and height on texture sizes * - Blend color is split across two registers - * - Blend LTE/GTE thresholds * - Universal Shader (US) block used for fragment shaders - * - FP16 blending and multisampling */ + * - FP16 blending and multisampling + * - Full RGTC texture compression + * - 24-bit depth textures + * - Stencil back-face reference value + * - Ability to render up to 2^24 - 1 vertices with signed index offset */ boolean is_r500; /* Whether or not the second pixel pipe is accessed with the high bit */ boolean high_second_pipe; diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 503af3e78a2..deaa03e1f61 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -186,7 +186,7 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->context.draw_range_elements = r300_swtcl_draw_range_elements; /* Create a Draw. This is used for SW TCL. */ - r300->draw = draw_create(); + r300->draw = draw_create(&r300->context); /* Enable our renderer. */ draw_set_rasterize_stage(r300->draw, r300_draw_stage(r300)); /* Enable Draw's clipping. */ diff --git a/src/gallium/drivers/r300/r300_query.c b/src/gallium/drivers/r300/r300_query.c index 398edb9d101..5c27796e894 100644 --- a/src/gallium/drivers/r300/r300_query.c +++ b/src/gallium/drivers/r300/r300_query.c @@ -25,10 +25,8 @@ #include "r300_context.h" #include "r300_screen.h" -#include "r300_cs.h" #include "r300_emit.h" #include "r300_query.h" -#include "r300_reg.h" #include <stdio.h> diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c index 007f01ace30..23b61df89cc 100644 --- a/src/gallium/drivers/r300/r300_render.c +++ b/src/gallium/drivers/r300/r300_render.c @@ -152,9 +152,9 @@ static boolean immd_is_good_idea(struct r300_context *r300, if (!checked[vbi]) { vbuf = &r300->vertex_buffer[vbi]; - if (r300->context.is_resource_referenced(&r300->context, - vbuf->buffer, - 0, 0)) { + if (r300_buffer_is_referenced(&r300->context, + vbuf->buffer, + R300_REF_CS | R300_REF_HW)) { /* It's a very bad idea to map it... */ return FALSE; } diff --git a/src/gallium/drivers/r300/r300_screen_buffer.c b/src/gallium/drivers/r300/r300_screen_buffer.c index 739f723f163..20a9ffb9f60 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.c +++ b/src/gallium/drivers/r300/r300_screen_buffer.c @@ -26,7 +26,6 @@ #include <stdio.h> #include "util/u_inlines.h" -#include "util/u_format.h" #include "util/u_memory.h" #include "util/u_upload_mgr.h" #include "util/u_math.h" @@ -34,9 +33,9 @@ #include "r300_screen_buffer.h" #include "r300_winsys.h" -static unsigned r300_buffer_is_referenced(struct pipe_context *context, - struct pipe_resource *buf, - unsigned face, unsigned level) +unsigned r300_buffer_is_referenced(struct pipe_context *context, + struct pipe_resource *buf, + enum r300_reference_domain domain) { struct r300_context *r300 = r300_context(context); struct r300_buffer *rbuf = r300_buffer(buf); @@ -44,12 +43,19 @@ static unsigned r300_buffer_is_referenced(struct pipe_context *context, if (r300_buffer_is_user_buffer(buf)) return PIPE_UNREFERENCED; - if (r300->rws->is_buffer_referenced(r300->rws, rbuf->buf)) + if (r300->rws->is_buffer_referenced(r300->rws, rbuf->buf, domain)) return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; return PIPE_UNREFERENCED; } +static unsigned r300_buffer_is_referenced_by_cs(struct pipe_context *context, + struct pipe_resource *buf, + unsigned face, unsigned level) +{ + return r300_buffer_is_referenced(context, buf, R300_REF_CS); +} + /* External helper, not required to implent u_resource_vtbl: */ int r300_upload_index_buffer(struct r300_context *r300, @@ -174,7 +180,6 @@ r300_buffer_transfer_map( struct pipe_context *pipe, rws->buffer_reference(rws, &rbuf->buf, NULL); rbuf->num_ranges = 0; - rbuf->map = NULL; rbuf->buf = r300_winsys_buffer_create(r300screen, 16, rbuf->b.b.bind, /* XXX */ @@ -243,7 +248,7 @@ struct u_resource_vtbl r300_buffer_vtbl = { u_default_resource_get_handle, /* get_handle */ r300_buffer_destroy, /* resource_destroy */ - r300_buffer_is_referenced, /* is_buffer_referenced */ + r300_buffer_is_referenced_by_cs, /* is_buffer_referenced */ u_default_get_transfer, /* get_transfer */ u_default_transfer_destroy, /* transfer_destroy */ r300_buffer_transfer_map, /* transfer_map */ diff --git a/src/gallium/drivers/r300/r300_screen_buffer.h b/src/gallium/drivers/r300/r300_screen_buffer.h index 82660d3e1a4..57f48229b2e 100644 --- a/src/gallium/drivers/r300/r300_screen_buffer.h +++ b/src/gallium/drivers/r300/r300_screen_buffer.h @@ -55,8 +55,6 @@ struct r300_buffer void *user_buffer; struct r300_buffer_range ranges[R300_BUFFER_MAX_RANGES]; unsigned num_ranges; - - void *map; }; /* Functions. */ @@ -77,6 +75,10 @@ struct pipe_resource *r300_user_buffer_create(struct pipe_screen *screen, unsigned bytes, unsigned usage); +unsigned r300_buffer_is_referenced(struct pipe_context *context, + struct pipe_resource *buf, + enum r300_reference_domain domain); + /* Inline functions. */ static INLINE struct r300_buffer *r300_buffer(struct pipe_resource *buffer) diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c index 371e52d2089..9eb8539a655 100644 --- a/src/gallium/drivers/r300/r300_state.c +++ b/src/gallium/drivers/r300/r300_state.c @@ -889,7 +889,7 @@ static void r300_bind_rs_state(struct pipe_context* pipe, void* state) if (r300->draw) { draw_flush(r300->draw); - draw_set_rasterizer_state(r300->draw, &rs->rs); + draw_set_rasterizer_state(r300->draw, &rs->rs, state); } if (rs) { @@ -1192,14 +1192,13 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe, } if (vbo->max_index == ~0) { - /* Bogus value from broken state tracker; hax it. */ - /* TODO - more hax - fixes doom3 from almos on irc */ - if (!vbo->stride) { - fprintf(stderr, "r300: got a VBO with stride 0 fixing up to stide 4\n"); - vbo->stride = 4; - } - vbo->max_index = - (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; + /* if no VBO stride then only one vertex value so max index is 1 */ + /* should think about converting to VS constants like svga does */ + if (!vbo->stride) + vbo->max_index = 1; + else + vbo->max_index = + (vbo->buffer->width0 - vbo->buffer_offset) / vbo->stride; } max_index = MIN2(vbo->max_index, max_index); diff --git a/src/gallium/drivers/r300/r300_state_invariant.c b/src/gallium/drivers/r300/r300_state_invariant.c index ffb175febf1..64d1d18b454 100644 --- a/src/gallium/drivers/r300/r300_state_invariant.c +++ b/src/gallium/drivers/r300/r300_state_invariant.c @@ -41,10 +41,9 @@ struct pipe_viewport_state r300_viewport_identity = { void r300_emit_invariant_state(struct r300_context* r300, unsigned size, void* state) { - struct r300_capabilities* caps = &r300_screen(r300->context.screen)->caps; CS_LOCALS(r300); - BEGIN_CS(12 + (caps->has_tcl ? 2: 0)); + BEGIN_CS(12 + (r300->screen->caps.has_tcl ? 2 : 0)); /*** Graphics Backend (GB) ***/ /* Subpixel multisampling for AA @@ -66,7 +65,7 @@ void r300_emit_invariant_state(struct r300_context* r300, /* Sign/normalize control */ OUT_CS_REG(R300_VAP_PSC_SGN_NORM_CNTL, R300_SGN_NORM_NO_ZERO); /* TCL-only stuff */ - if (caps->has_tcl) { + if (r300->screen->caps.has_tcl) { /* Amount of time to wait for vertex fetches in PVS */ OUT_CS_REG(VAP_PVS_VTX_TIMEOUT_REG, 0xffff); } @@ -74,10 +73,10 @@ void r300_emit_invariant_state(struct r300_context* r300, END_CS; /* XXX unsorted stuff from surface_fill */ - BEGIN_CS(38 + (caps->has_tcl ? 7 : 0) + - (caps->family >= CHIP_FAMILY_RV350 ? 4 : 0)); + BEGIN_CS(38 + (r300->screen->caps.has_tcl ? 7 : 0) + + (r300->screen->caps.is_rv350 ? 4 : 0)); - if (caps->has_tcl) { + if (r300->screen->caps.has_tcl) { /*Flushing PVS is required before the VAP_GB registers can be changed*/ OUT_CS_REG(R300_VAP_PVS_STATE_FLUSH_REG, 0); OUT_CS_REG_SEQ(R300_VAP_GB_VERT_CLIP_ADJ, 4); @@ -107,7 +106,7 @@ void r300_emit_invariant_state(struct r300_context* r300, OUT_CS_REG(R300_SC_EDGERULE, 0x2DA49525); OUT_CS_REG(R300_RB3D_AARESOLVE_CTL, 0x00000000); - if (caps->family >= CHIP_FAMILY_RV350) { + if (r300->screen->caps.is_rv350) { OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_LTE_THRESHOLD, 0x01010101); OUT_CS_REG(R500_RB3D_DISCARD_SRC_PIXEL_GTE_THRESHOLD, 0xFEFEFEFE); } diff --git a/src/gallium/drivers/r300/r300_texture.c b/src/gallium/drivers/r300/r300_texture.c index a4a3f2166f8..8bebeacf860 100644 --- a/src/gallium/drivers/r300/r300_texture.c +++ b/src/gallium/drivers/r300/r300_texture.c @@ -787,7 +787,7 @@ static void r300_setup_miptree(struct r300_screen* screen, { struct pipe_resource* base = &tex->b.b; unsigned stride, size, layer_size, nblocksy, i; - boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_RV350; + boolean rv350_mode = screen->caps.is_rv350; SCREEN_DBG(screen, DBG_TEX, "r300: Making miptree for texture, format %s\n", util_format_name(base->format)); @@ -834,7 +834,7 @@ static void r300_setup_tiling(struct pipe_screen *screen, { struct r300_winsys_screen *rws = (struct r300_winsys_screen *)screen->winsys; enum pipe_format format = tex->b.b.format; - boolean rv350_mode = r300_screen(screen)->caps.family >= CHIP_FAMILY_RV350; + boolean rv350_mode = r300_screen(screen)->caps.is_rv350; boolean is_zb = util_format_is_depth_or_stencil(format); boolean dbg_no_tiling = SCREEN_DBG_ON(r300_screen(screen), DBG_NO_TILING); @@ -880,7 +880,7 @@ static unsigned r300_texture_is_referenced(struct pipe_context *context, struct r300_context *r300 = r300_context(context); struct r300_texture *rtex = (struct r300_texture *)texture; - if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer)) + if (r300->rws->is_buffer_referenced(r300->rws, rtex->buffer, R300_REF_CS)) return PIPE_REFERENCED_FOR_READ | PIPE_REFERENCED_FOR_WRITE; return PIPE_UNREFERENCED; diff --git a/src/gallium/drivers/r300/r300_tgsi_to_rc.c b/src/gallium/drivers/r300/r300_tgsi_to_rc.c index 21a1c45982d..f6428ed760f 100644 --- a/src/gallium/drivers/r300/r300_tgsi_to_rc.c +++ b/src/gallium/drivers/r300/r300_tgsi_to_rc.c @@ -115,10 +115,10 @@ static unsigned translate_opcode(unsigned opcode) /* case TGSI_OPCODE_ENDREP: return RC_OPCODE_ENDREP; */ /* case TGSI_OPCODE_PUSHA: return RC_OPCODE_PUSHA; */ /* case TGSI_OPCODE_POPA: return RC_OPCODE_POPA; */ - /* case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL; */ + case TGSI_OPCODE_CEIL: return RC_OPCODE_CEIL; /* case TGSI_OPCODE_I2F: return RC_OPCODE_I2F; */ /* case TGSI_OPCODE_NOT: return RC_OPCODE_NOT; */ - /* case TGSI_OPCODE_TRUNC: return RC_OPCODE_TRUNC; */ + case TGSI_OPCODE_TRUNC: return RC_OPCODE_FLR; /* case TGSI_OPCODE_SHL: return RC_OPCODE_SHL; */ /* case TGSI_OPCODE_ISHR: return RC_OPCODE_SHR; */ /* case TGSI_OPCODE_AND: return RC_OPCODE_AND; */ diff --git a/src/gallium/drivers/r300/r300_winsys.h b/src/gallium/drivers/r300/r300_winsys.h index 9c348d91158..2bd40176d10 100644 --- a/src/gallium/drivers/r300/r300_winsys.h +++ b/src/gallium/drivers/r300/r300_winsys.h @@ -42,6 +42,11 @@ enum r300_value_id { R300_VID_TEX3D_MIP_BUG, }; +enum r300_reference_domain { /* bitfield */ + R300_REF_CS = 1, + R300_REF_HW = 2 +}; + struct r300_winsys_screen { void (*destroy)(struct r300_winsys_screen *ws); @@ -160,9 +165,8 @@ struct r300_winsys_screen { struct winsys_handle *whandle); boolean (*is_buffer_referenced)(struct r300_winsys_screen *winsys, - struct r300_winsys_buffer *buffer); - - + struct r300_winsys_buffer *buffer, + enum r300_reference_domain domain); }; struct r300_winsys_screen * diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index d0c2978c246..9dcb5586c6e 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -93,6 +93,7 @@ softpipe_destroy( struct pipe_context *pipe ) softpipe->quad.shade->destroy( softpipe->quad.shade ); softpipe->quad.depth_test->destroy( softpipe->quad.depth_test ); softpipe->quad.blend->destroy( softpipe->quad.blend ); + softpipe->quad.pstipple->destroy( softpipe->quad.pstipple ); for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) { sp_destroy_tile_cache(softpipe->cbuf_cache[i]); @@ -296,12 +297,13 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->quad.shade = sp_quad_shade_stage(softpipe); softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe); softpipe->quad.blend = sp_quad_blend_stage(softpipe); + softpipe->quad.pstipple = sp_quad_polygon_stipple_stage(softpipe); /* * Create drawing context and plug our rendering stage into it. */ - softpipe->draw = draw_create(); + softpipe->draw = draw_create(&softpipe->pipe); if (!softpipe->draw) goto fail; @@ -330,7 +332,9 @@ softpipe_create_context( struct pipe_screen *screen, draw_install_aapoint_stage(softpipe->draw, &softpipe->pipe); /* Do polygon stipple w/ texture map + frag prog? */ +#if DO_PSTIPPLE_IN_DRAW_MODULE draw_install_pstipple_stage(softpipe->draw, &softpipe->pipe); +#endif sp_init_surface_functions(softpipe); diff --git a/src/gallium/drivers/softpipe/sp_context.h b/src/gallium/drivers/softpipe/sp_context.h index be8f2cb3e04..92607874b60 100644 --- a/src/gallium/drivers/softpipe/sp_context.h +++ b/src/gallium/drivers/softpipe/sp_context.h @@ -38,6 +38,10 @@ #include "sp_quad_pipe.h" +/** Do polygon stipple in the driver here, or in the draw module? */ +#define DO_PSTIPPLE_IN_DRAW_MODULE 1 + + struct softpipe_vbuf_render; struct draw_context; struct draw_stage; @@ -126,6 +130,7 @@ struct softpipe_context { struct quad_stage *shade; struct quad_stage *depth_test; struct quad_stage *blend; + struct quad_stage *pstipple; struct quad_stage *first; /**< points to one of the above stages */ } quad; diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index 4ee31969e6b..72117c233e5 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -520,6 +520,9 @@ depth_stencil_test_quad(struct quad_stage *qs, face = 0; } + /* 0 = front-face, 1 = back-face */ + assert(face == 0 || face == 1); + /* choose front or back face function, operator, etc */ /* XXX we could do these initializations once per primitive */ func = softpipe->depth_stencil->stencil[face].func; diff --git a/src/gallium/drivers/softpipe/sp_quad_pipe.c b/src/gallium/drivers/softpipe/sp_quad_pipe.c index 1b5bab4eca6..43b8e88e334 100644 --- a/src/gallium/drivers/softpipe/sp_quad_pipe.c +++ b/src/gallium/drivers/softpipe/sp_quad_pipe.c @@ -59,5 +59,10 @@ sp_build_quad_pipeline(struct softpipe_context *sp) sp_push_quad_first( sp, sp->quad.depth_test ); sp_push_quad_first( sp, sp->quad.shade ); } + +#if !DO_PSTIPPLE_IN_DRAW_MODULE + if (sp->rasterizer->poly_stipple_enable) + sp_push_quad_first( sp, sp->quad.pstipple ); +#endif } diff --git a/src/gallium/drivers/softpipe/sp_setup.c b/src/gallium/drivers/softpipe/sp_setup.c index e136cb7cf73..86354664e4b 100644 --- a/src/gallium/drivers/softpipe/sp_setup.c +++ b/src/gallium/drivers/softpipe/sp_setup.c @@ -47,6 +47,7 @@ #define DEBUG_VERTS 0 #define DEBUG_FRAGS 0 + /** * Triangle edge info */ @@ -59,11 +60,16 @@ struct edge { }; +/** + * Max number of quads (2x2 pixel blocks) to process per batch. + * This can't be arbitrarily increased since we depend on some 32-bit + * bitmasks (two bits per quad). + */ #define MAX_QUADS 16 /** - * Triangle setup info (derived from draw_stage). + * Triangle setup info. * Also used for line drawing (taking some liberties). */ struct setup_context { @@ -140,7 +146,7 @@ cull_tri(const struct setup_context *setup, float det) * Clip setup->quad against the scissor/surface bounds. */ static INLINE void -quad_clip( struct setup_context *setup, struct quad_header *quad ) +quad_clip(struct setup_context *setup, struct quad_header *quad) { const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect; const int minx = (int) cliprect->minx; @@ -171,7 +177,7 @@ quad_clip( struct setup_context *setup, struct quad_header *quad ) * Emit a quad (pass to next stage) with clipping. */ static INLINE void -clip_emit_quad( struct setup_context *setup, struct quad_header *quad ) +clip_emit_quad(struct setup_context *setup, struct quad_header *quad) { quad_clip( setup, quad ); @@ -188,12 +194,15 @@ clip_emit_quad( struct setup_context *setup, struct quad_header *quad ) * Given an X or Y coordinate, return the block/quad coordinate that it * belongs to. */ -static INLINE int block( int x ) +static INLINE int +block(int x) { return x & ~(2-1); } -static INLINE int block_x( int x ) + +static INLINE int +block_x(int x) { return x & ~(16-1); } @@ -202,9 +211,10 @@ static INLINE int block_x( int x ) /** * Render a horizontal span of quads */ -static void flush_spans( struct setup_context *setup ) +static void +flush_spans(struct setup_context *setup) { - const int step = 16; + const int step = MAX_QUADS; const int xleft0 = setup->span.left[0]; const int xleft1 = setup->span.left[1]; const int xright0 = setup->span.right[0]; @@ -265,8 +275,9 @@ static void flush_spans( struct setup_context *setup ) #if DEBUG_VERTS -static void print_vertex(const struct setup_context *setup, - const float (*v)[4]) +static void +print_vertex(const struct setup_context *setup, + const float (*v)[4]) { int i; debug_printf(" Vertex: (%p)\n", (void *) v); @@ -280,16 +291,18 @@ static void print_vertex(const struct setup_context *setup, } #endif + /** * Sort the vertices from top to bottom order, setting up the triangle * edge fields (ebot, emaj, etop). * \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise */ -static boolean setup_sort_vertices( struct setup_context *setup, - float det, - const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4] ) +static boolean +setup_sort_vertices(struct setup_context *setup, + float det, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4]) { setup->vprovoke = v2; @@ -374,6 +387,7 @@ static boolean setup_sort_vertices( struct setup_context *setup, /* We need to know if this is a front or back-facing triangle for: * - the GLSL gl_FrontFacing fragment attribute (bool) * - two-sided stencil test + * 0 = front-facing, 1 = back-facing */ setup->facing = ((det > 0.0) ^ @@ -446,9 +460,10 @@ tri_apply_cylindrical_wrap(float v0, * \param slot which attribute slot * \param i which component of the slot (0..3) */ -static void const_coeff( struct setup_context *setup, - struct tgsi_interp_coef *coef, - uint vertSlot, uint i) +static void +const_coeff(struct setup_context *setup, + struct tgsi_interp_coef *coef, + uint vertSlot, uint i) { assert(i <= 3); @@ -590,7 +605,8 @@ setup_fragcoord_coeff(struct setup_context *setup, uint slot) * Compute the setup->coef[] array dadx, dady, a0 values. * Must be called after setup->vmin,vmid,vmax,vprovoke are initialized. */ -static void setup_tri_coefficients( struct setup_context *setup ) +static void +setup_tri_coefficients(struct setup_context *setup) { struct softpipe_context *softpipe = setup->softpipe; const struct sp_fragment_shader *spfs = softpipe->fs; @@ -649,7 +665,8 @@ static void setup_tri_coefficients( struct setup_context *setup ) } if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { - setup->coef[fragSlot].a0[0] = 1.0f - setup->facing; + /* convert 0 to 1.0 and 1 to -1.0 */ + setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dady[0] = 0.0; } @@ -657,8 +674,8 @@ static void setup_tri_coefficients( struct setup_context *setup ) } - -static void setup_tri_edges( struct setup_context *setup ) +static void +setup_tri_edges(struct setup_context *setup) { float vmin_x = setup->vmin[0][0] + setup->pixel_offset; float vmid_x = setup->vmid[0][0] + setup->pixel_offset; @@ -669,17 +686,17 @@ static void setup_tri_edges( struct setup_context *setup ) setup->emaj.sy = ceilf(vmin_y); setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy); - setup->emaj.dxdy = setup->emaj.dx / setup->emaj.dy; + setup->emaj.dxdy = setup->emaj.dy ? setup->emaj.dx / setup->emaj.dy : .0f; setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy; setup->etop.sy = ceilf(vmid_y); setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy); - setup->etop.dxdy = setup->etop.dx / setup->etop.dy; + setup->etop.dxdy = setup->etop.dy ? setup->etop.dx / setup->etop.dy : .0f; setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy; setup->ebot.sy = ceilf(vmin_y); setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy); - setup->ebot.dxdy = setup->ebot.dx / setup->ebot.dy; + setup->ebot.dxdy = setup->ebot.dy ? setup->ebot.dx / setup->ebot.dy : .0f; setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy; } @@ -688,10 +705,11 @@ static void setup_tri_edges( struct setup_context *setup ) * Render the upper or lower half of a triangle. * Scissoring/cliprect is applied here too. */ -static void subtriangle( struct setup_context *setup, - struct edge *eleft, - struct edge *eright, - int lines ) +static void +subtriangle(struct setup_context *setup, + struct edge *eleft, + struct edge *eright, + int lines) { const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect; const int minx = (int) cliprect->minx; @@ -765,9 +783,9 @@ static void subtriangle( struct setup_context *setup, * calculate it here. */ static float -calc_det( const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4] ) +calc_det(const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4]) { /* edge vectors e = v0 - v2, f = v1 - v2 */ const float ex = v0[0][0] - v2[0][0]; @@ -783,10 +801,11 @@ calc_det( const float (*v0)[4], /** * Do setup for triangle rasterization, then render the triangle. */ -void sp_setup_tri( struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4], - const float (*v2)[4] ) +void +sp_setup_tri(struct setup_context *setup, + const float (*v0)[4], + const float (*v1)[4], + const float (*v2)[4]) { float det; @@ -926,7 +945,7 @@ line_persp_coeff(const struct setup_context *setup, * Compute the setup->coef[] array dadx, dady, a0 values. * Must be called after setup->vmin,vmax are initialized. */ -static INLINE boolean +static boolean setup_line_coefficients(struct setup_context *setup, const float (*v0)[4], const float (*v1)[4]) @@ -1002,7 +1021,8 @@ setup_line_coefficients(struct setup_context *setup, } if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { - setup->coef[fragSlot].a0[0] = 1.0f - setup->facing; + /* convert 0 to 1.0 and 1 to -1.0 */ + setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dady[0] = 0.0; } @@ -1047,8 +1067,8 @@ plot(struct setup_context *setup, int x, int y) */ void sp_setup_line(struct setup_context *setup, - const float (*v0)[4], - const float (*v1)[4]) + const float (*v0)[4], + const float (*v1)[4]) { int x0 = (int) v0[0][0]; int x1 = (int) v1[0][0]; @@ -1176,8 +1196,8 @@ point_persp_coeff(const struct setup_context *setup, * XXX could optimize a lot for 1-pixel points. */ void -sp_setup_point( struct setup_context *setup, - const float (*v0)[4] ) +sp_setup_point(struct setup_context *setup, + const float (*v0)[4]) { struct softpipe_context *softpipe = setup->softpipe; const struct sp_fragment_shader *spfs = softpipe->fs; @@ -1248,7 +1268,8 @@ sp_setup_point( struct setup_context *setup, } if (spfs->info.input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) { - setup->coef[fragSlot].a0[0] = 1.0f - setup->facing; + /* convert 0 to 1.0 and 1 to -1.0 */ + setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f; setup->coef[fragSlot].dadx[0] = 0.0; setup->coef[fragSlot].dady[0] = 0.0; } @@ -1377,7 +1398,12 @@ sp_setup_point( struct setup_context *setup, } } -void sp_setup_prepare( struct setup_context *setup ) + +/** + * Called by vbuf code just before we start buffering primitives. + */ +void +sp_setup_prepare(struct setup_context *setup) { struct softpipe_context *sp = setup->softpipe; @@ -1403,8 +1429,8 @@ void sp_setup_prepare( struct setup_context *setup ) } - -void sp_setup_destroy_context( struct setup_context *setup ) +void +sp_setup_destroy_context(struct setup_context *setup) { FREE( setup ); } @@ -1413,7 +1439,8 @@ void sp_setup_destroy_context( struct setup_context *setup ) /** * Create a new primitive setup/render stage. */ -struct setup_context *sp_setup_create_context( struct softpipe_context *softpipe ) +struct setup_context * +sp_setup_create_context(struct softpipe_context *softpipe) { struct setup_context *setup = CALLOC_STRUCT(setup_context); unsigned i; @@ -1430,4 +1457,3 @@ struct setup_context *sp_setup_create_context( struct softpipe_context *softpipe return setup; } - diff --git a/src/gallium/drivers/softpipe/sp_state_rasterizer.c b/src/gallium/drivers/softpipe/sp_state_rasterizer.c index a5b00336d44..c9ede09f268 100644 --- a/src/gallium/drivers/softpipe/sp_state_rasterizer.c +++ b/src/gallium/drivers/softpipe/sp_state_rasterizer.c @@ -49,7 +49,7 @@ void softpipe_bind_rasterizer_state(struct pipe_context *pipe, return; /* pass-through to draw module */ - draw_set_rasterizer_state(softpipe->draw, rasterizer); + draw_set_rasterizer_state(softpipe->draw, rasterizer, rasterizer); softpipe->rasterizer = rasterizer; diff --git a/src/gallium/drivers/svga/svga_pipe_rasterizer.c b/src/gallium/drivers/svga/svga_pipe_rasterizer.c index 35717788677..5253c45cb20 100644 --- a/src/gallium/drivers/svga/svga_pipe_rasterizer.c +++ b/src/gallium/drivers/svga/svga_pipe_rasterizer.c @@ -222,7 +222,8 @@ static void svga_bind_rasterizer_state( struct pipe_context *pipe, svga->curr.rast = raster; - draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL); + draw_set_rasterizer_state(svga->swtnl.draw, raster ? &raster->templ : NULL, + state); svga->dirty |= SVGA_NEW_RAST; } diff --git a/src/gallium/drivers/svga/svga_swtnl_draw.c b/src/gallium/drivers/svga/svga_swtnl_draw.c index 4504bf71fda..eb71c23195b 100644 --- a/src/gallium/drivers/svga/svga_swtnl_draw.c +++ b/src/gallium/drivers/svga/svga_swtnl_draw.c @@ -143,7 +143,7 @@ boolean svga_init_swtnl( struct svga_context *svga ) /* * Create drawing context and plug our rendering stage into it. */ - svga->swtnl.draw = draw_create(); + svga->swtnl.draw = draw_create(&svga->pipe); if (svga->swtnl.draw == NULL) goto fail; diff --git a/src/gallium/drivers/svga/svga_swtnl_state.c b/src/gallium/drivers/svga/svga_swtnl_state.c index 246d34e649e..a7592382936 100644 --- a/src/gallium/drivers/svga/svga_swtnl_state.c +++ b/src/gallium/drivers/svga/svga_swtnl_state.c @@ -113,7 +113,8 @@ static int update_swtnl_draw( struct svga_context *svga, if (dirty & SVGA_NEW_RAST) draw_set_rasterizer_state(svga->swtnl.draw, - &svga->curr.rast->templ); + &svga->curr.rast->templ, + (void *) svga->curr.rast); if (dirty & SVGA_NEW_FRAME_BUFFER) draw_set_mrd(svga->swtnl.draw, diff --git a/src/gallium/include/pipe/p_compiler.h b/src/gallium/include/pipe/p_compiler.h index 09d6b6c9e2f..9b31555f1b1 100644 --- a/src/gallium/include/pipe/p_compiler.h +++ b/src/gallium/include/pipe/p_compiler.h @@ -182,6 +182,44 @@ typedef unsigned char boolean; #endif - +/* You should use these macros to mark if blocks where the if condition + * is either likely to be true, or unlikely to be true. + * + * This will inform human readers of this fact, and will also inform + * the compiler, who will in turn inform the CPU. + * + * CPUs often start executing code inside the if or the else blocks + * without knowing whether the condition is true or not, and will have + * to throw the work away if they find out later they executed the + * wrong part of the if. + * + * If these macros are used, the CPU is more likely to correctly predict + * the right path, and will avoid speculatively executing the wrong branch, + * thus not throwing away work, resulting in better performance. + * + * In light of this, it is also a good idea to mark as "likely" a path + * which is not necessarily always more likely, but that will benefit much + * more from performance improvements since it is already much faster than + * the other path, or viceversa with "unlikely". + * + * Example usage: + * if(unlikely(do_we_need_a_software_fallback())) + * do_software_fallback(); + * else + * render_with_gpu(); + * + * The macros follow the Linux kernel convention, and more examples can + * be found there. + * + * Note that profile guided optimization can offer better results, but + * needs an appropriate coverage suite and does not inform human readers. + */ +#ifdef __GNUC__ +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#else +#define likely(x) !!(x) +#define unlikely(x) !!(x) +#endif #endif /* P_COMPILER_H */ diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 794785006f5..1768241352f 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -16,6 +16,7 @@ x11_INCLUDES = \ -I$(TOP)/src/gallium/drivers \ -I$(TOP)/src/glx \ -I$(TOP)/src/mesa \ + $(X11_CFLAGS) \ $(shell pkg-config --cflags-only-I libdrm) x11_SOURCES = $(wildcard x11/*.c) \ diff --git a/src/gallium/targets/libgl-xlib/Makefile b/src/gallium/targets/libgl-xlib/Makefile index 6cd00cad458..add3a273945 100644 --- a/src/gallium/targets/libgl-xlib/Makefile +++ b/src/gallium/targets/libgl-xlib/Makefile @@ -20,7 +20,8 @@ INCLUDE_DIRS = \ -I$(TOP)/src/gallium/include \ -I$(TOP)/src/gallium/drivers \ -I$(TOP)/src/gallium/state_trackers/glx/xlib \ - -I$(TOP)/src/gallium/auxiliary + -I$(TOP)/src/gallium/auxiliary \ + $(X11_CFLAGS) DEFINES += \ -DGALLIUM_SOFTPIPE diff --git a/src/gallium/winsys/radeon/drm/radeon_buffer.h b/src/gallium/winsys/radeon/drm/radeon_buffer.h index 8782d675df2..b48b6358e01 100644 --- a/src/gallium/winsys/radeon/drm/radeon_buffer.h +++ b/src/gallium/winsys/radeon/drm/radeon_buffer.h @@ -86,5 +86,6 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr); boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf, struct winsys_handle *whandle); -boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf); +boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf, + enum r300_reference_domain domain); #endif diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c index c9179a3620a..9824ada5b33 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c @@ -381,13 +381,25 @@ void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf, } } -boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf) +boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf, + enum r300_reference_domain domain) { struct radeon_drm_buffer *buf = get_drm_buffer(_buf); - uint32_t domain; + uint32_t tmp; + + if (domain & R300_REF_CS) { + if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) { + return TRUE; + } + } + + if (domain & R300_REF_HW) { + if (radeon_bo_is_busy(buf->bo, &tmp)) { + return TRUE; + } + } - return (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs) || - radeon_bo_is_busy(buf->bo, &domain)); + return FALSE; } diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c index d1e65f87c36..2fcf7cf9821 100644 --- a/src/gallium/winsys/radeon/drm/radeon_r300.c +++ b/src/gallium/winsys/radeon/drm/radeon_r300.c @@ -111,11 +111,12 @@ static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws, } static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws, - struct r300_winsys_buffer *buf) + struct r300_winsys_buffer *buf, + enum r300_reference_domain domain) { struct pb_buffer *_buf = radeon_pb_buffer(buf); - return radeon_drm_bufmgr_is_buffer_referenced(_buf); + return radeon_drm_bufmgr_is_buffer_referenced(_buf, domain); } static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws, |