diff options
Diffstat (limited to 'src/gallium/drivers/softpipe')
22 files changed, 484 insertions, 333 deletions
diff --git a/src/gallium/drivers/softpipe/Makefile b/src/gallium/drivers/softpipe/Makefile index 35d426aa3ea..28953582f0a 100644 --- a/src/gallium/drivers/softpipe/Makefile +++ b/src/gallium/drivers/softpipe/Makefile @@ -23,8 +23,8 @@ C_SOURCES = \ sp_state_blend.c \ sp_state_clip.c \ sp_state_derived.c \ - sp_state_fs.c \ sp_state_sampler.c \ + sp_state_shader.c \ sp_state_so.c \ sp_state_rasterizer.c \ sp_state_surface.c \ diff --git a/src/gallium/drivers/softpipe/SConscript b/src/gallium/drivers/softpipe/SConscript index be5917a6886..d5f4d28aeff 100644 --- a/src/gallium/drivers/softpipe/SConscript +++ b/src/gallium/drivers/softpipe/SConscript @@ -24,9 +24,9 @@ softpipe = env.ConvenienceLibrary( 'sp_state_blend.c', 'sp_state_clip.c', 'sp_state_derived.c', - 'sp_state_fs.c', 'sp_state_rasterizer.c', 'sp_state_sampler.c', + 'sp_state_shader.c', 'sp_state_so.c', 'sp_state_surface.c', 'sp_state_vertex.c', diff --git a/src/gallium/drivers/softpipe/sp_context.c b/src/gallium/drivers/softpipe/sp_context.c index a7c9959b3e1..b5d30bc6fc9 100644 --- a/src/gallium/drivers/softpipe/sp_context.c +++ b/src/gallium/drivers/softpipe/sp_context.c @@ -228,61 +228,17 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.priv = priv; /* state setters */ - softpipe->pipe.create_blend_state = softpipe_create_blend_state; - softpipe->pipe.bind_blend_state = softpipe_bind_blend_state; - softpipe->pipe.delete_blend_state = softpipe_delete_blend_state; - - softpipe->pipe.create_sampler_state = softpipe_create_sampler_state; - softpipe->pipe.bind_fragment_sampler_states = softpipe_bind_sampler_states; - softpipe->pipe.bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states; - softpipe->pipe.bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states; - softpipe->pipe.delete_sampler_state = softpipe_delete_sampler_state; - - softpipe->pipe.create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state; - softpipe->pipe.bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state; - softpipe->pipe.delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state; - - softpipe->pipe.create_rasterizer_state = softpipe_create_rasterizer_state; - softpipe->pipe.bind_rasterizer_state = softpipe_bind_rasterizer_state; - softpipe->pipe.delete_rasterizer_state = softpipe_delete_rasterizer_state; - - softpipe->pipe.create_fs_state = softpipe_create_fs_state; - softpipe->pipe.bind_fs_state = softpipe_bind_fs_state; - softpipe->pipe.delete_fs_state = softpipe_delete_fs_state; - - softpipe->pipe.create_vs_state = softpipe_create_vs_state; - softpipe->pipe.bind_vs_state = softpipe_bind_vs_state; - softpipe->pipe.delete_vs_state = softpipe_delete_vs_state; - - softpipe->pipe.create_gs_state = softpipe_create_gs_state; - softpipe->pipe.bind_gs_state = softpipe_bind_gs_state; - softpipe->pipe.delete_gs_state = softpipe_delete_gs_state; - - softpipe->pipe.create_vertex_elements_state = softpipe_create_vertex_elements_state; - softpipe->pipe.bind_vertex_elements_state = softpipe_bind_vertex_elements_state; - softpipe->pipe.delete_vertex_elements_state = softpipe_delete_vertex_elements_state; - - softpipe->pipe.create_stream_output_state = softpipe_create_stream_output_state; - softpipe->pipe.bind_stream_output_state = softpipe_bind_stream_output_state; - softpipe->pipe.delete_stream_output_state = softpipe_delete_stream_output_state; - - softpipe->pipe.set_blend_color = softpipe_set_blend_color; - softpipe->pipe.set_stencil_ref = softpipe_set_stencil_ref; - softpipe->pipe.set_clip_state = softpipe_set_clip_state; - softpipe->pipe.set_sample_mask = softpipe_set_sample_mask; - softpipe->pipe.set_constant_buffer = softpipe_set_constant_buffer; + softpipe_init_blend_funcs(&softpipe->pipe); + softpipe_init_clip_funcs(&softpipe->pipe); + softpipe_init_query_funcs( softpipe ); + softpipe_init_rasterizer_funcs(&softpipe->pipe); + softpipe_init_sampler_funcs(&softpipe->pipe); + softpipe_init_shader_funcs(&softpipe->pipe); + softpipe_init_streamout_funcs(&softpipe->pipe); + softpipe_init_texture_funcs( &softpipe->pipe ); + softpipe_init_vertex_funcs(&softpipe->pipe); + softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; - softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple; - softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; - softpipe->pipe.set_fragment_sampler_views = softpipe_set_sampler_views; - softpipe->pipe.set_vertex_sampler_views = softpipe_set_vertex_sampler_views; - softpipe->pipe.set_geometry_sampler_views = softpipe_set_geometry_sampler_views; - softpipe->pipe.create_sampler_view = softpipe_create_sampler_view; - softpipe->pipe.sampler_view_destroy = softpipe_sampler_view_destroy; - softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; - softpipe->pipe.set_stream_output_buffers = softpipe_set_stream_output_buffers; - softpipe->pipe.set_vertex_buffers = softpipe_set_vertex_buffers; - softpipe->pipe.set_index_buffer = softpipe_set_index_buffer; softpipe->pipe.draw_vbo = softpipe_draw_vbo; softpipe->pipe.draw_stream_output = softpipe_draw_stream_output; @@ -292,9 +248,6 @@ softpipe_create_context( struct pipe_screen *screen, softpipe->pipe.is_resource_referenced = softpipe_is_resource_referenced; - softpipe_init_query_funcs( softpipe ); - softpipe_init_texture_funcs( &softpipe->pipe ); - softpipe->pipe.render_condition = softpipe_render_condition; /* diff --git a/src/gallium/drivers/softpipe/sp_fs_exec.c b/src/gallium/drivers/softpipe/sp_fs_exec.c index 67e2c8f8bc4..346e1b402ba 100644 --- a/src/gallium/drivers/softpipe/sp_fs_exec.c +++ b/src/gallium/drivers/softpipe/sp_fs_exec.c @@ -158,9 +158,17 @@ exec_run( const struct sp_fragment_shader *base, case TGSI_SEMANTIC_POSITION: { uint j; - for (j = 0; j < 4; j++) { + + for (j = 0; j < 4; j++) quad->output.depth[j] = machine->Outputs[i].xyzw[2].f[j]; - } + } + break; + case TGSI_SEMANTIC_STENCIL: + { + uint j; + + for (j = 0; j < 4; j++) + quad->output.stencil[j] = (unsigned)machine->Outputs[i].xyzw[1].f[j]; } break; } diff --git a/src/gallium/drivers/softpipe/sp_fs_sse.c b/src/gallium/drivers/softpipe/sp_fs_sse.c index daa158df7c4..5b18cd035e3 100644 --- a/src/gallium/drivers/softpipe/sp_fs_sse.c +++ b/src/gallium/drivers/softpipe/sp_fs_sse.c @@ -169,9 +169,15 @@ fs_sse_run( const struct sp_fragment_shader *base, case TGSI_SEMANTIC_POSITION: { uint j; - for (j = 0; j < 4; j++) { - quad->output.depth[j] = machine->Outputs[0].xyzw[2].f[j]; - } + for (j = 0; j < 4; j++) + quad->output.depth[j] = machine->Outputs[i].xyzw[2].f[j]; + } + break; + case TGSI_SEMANTIC_STENCIL: + { + uint j; + for (j = 0; j < 4; j++) + quad->output.stencil[j] = machine->Outputs[i].xyzw[1].f[j]; } break; } diff --git a/src/gallium/drivers/softpipe/sp_quad.h b/src/gallium/drivers/softpipe/sp_quad.h index a3236bd1169..e745aa80619 100644 --- a/src/gallium/drivers/softpipe/sp_quad.h +++ b/src/gallium/drivers/softpipe/sp_quad.h @@ -85,6 +85,7 @@ struct quad_header_output /** colors in SOA format (rrrr, gggg, bbbb, aaaa) */ float color[PIPE_MAX_COLOR_BUFS][NUM_CHANNELS][QUAD_SIZE]; float depth[QUAD_SIZE]; + uint8_t stencil[QUAD_SIZE]; }; diff --git a/src/gallium/drivers/softpipe/sp_quad_depth_test.c b/src/gallium/drivers/softpipe/sp_quad_depth_test.c index 5590d408929..c8f5f89568a 100644 --- a/src/gallium/drivers/softpipe/sp_quad_depth_test.c +++ b/src/gallium/drivers/softpipe/sp_quad_depth_test.c @@ -47,6 +47,8 @@ struct depth_data { unsigned bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */ unsigned qzzzz[QUAD_SIZE]; /**< Z values from the quad */ ubyte stencilVals[QUAD_SIZE]; + boolean use_shader_stencil_refs; + ubyte shader_stencil_refs[QUAD_SIZE]; struct softpipe_cached_tile *tile; }; @@ -186,6 +188,33 @@ convert_quad_depth( struct depth_data *data, } +/** + * Compute the depth_data::shader_stencil_refs[] values from the float fragment stencil values. + */ +static void +convert_quad_stencil( struct depth_data *data, + const struct quad_header *quad ) +{ + unsigned j; + + data->use_shader_stencil_refs = TRUE; + /* Copy quads stencil values + */ + switch (data->format) { + case PIPE_FORMAT_Z24X8_UNORM: + case PIPE_FORMAT_Z24_UNORM_S8_USCALED: + case PIPE_FORMAT_X8Z24_UNORM: + case PIPE_FORMAT_S8_USCALED_Z24_UNORM: + { + for (j = 0; j < QUAD_SIZE; j++) { + data->shader_stencil_refs[j] = ((unsigned)(quad->output.stencil[j])); + } + } + break; + default: + assert(0); + } +} /** * Write data->bzzzz[] values and data->stencilVals into the Z/stencil buffer. @@ -272,8 +301,14 @@ do_stencil_test(struct depth_data *data, { unsigned passMask = 0x0; unsigned j; + ubyte refs[QUAD_SIZE]; - ref &= valMask; + for (j = 0; j < QUAD_SIZE; j++) { + if (data->use_shader_stencil_refs) + refs[j] = data->shader_stencil_refs[j] & valMask; + else + refs[j] = ref & valMask; + } switch (func) { case PIPE_FUNC_NEVER: @@ -281,42 +316,42 @@ do_stencil_test(struct depth_data *data, break; case PIPE_FUNC_LESS: for (j = 0; j < QUAD_SIZE; j++) { - if (ref < (data->stencilVals[j] & valMask)) { + if (refs[j] < (data->stencilVals[j] & valMask)) { passMask |= (1 << j); } } break; case PIPE_FUNC_EQUAL: for (j = 0; j < QUAD_SIZE; j++) { - if (ref == (data->stencilVals[j] & valMask)) { + if (refs[j] == (data->stencilVals[j] & valMask)) { passMask |= (1 << j); } } break; case PIPE_FUNC_LEQUAL: for (j = 0; j < QUAD_SIZE; j++) { - if (ref <= (data->stencilVals[j] & valMask)) { + if (refs[j] <= (data->stencilVals[j] & valMask)) { passMask |= (1 << j); } } break; case PIPE_FUNC_GREATER: for (j = 0; j < QUAD_SIZE; j++) { - if (ref > (data->stencilVals[j] & valMask)) { + if (refs[j] > (data->stencilVals[j] & valMask)) { passMask |= (1 << j); } } break; case PIPE_FUNC_NOTEQUAL: for (j = 0; j < QUAD_SIZE; j++) { - if (ref != (data->stencilVals[j] & valMask)) { + if (refs[j] != (data->stencilVals[j] & valMask)) { passMask |= (1 << j); } } break; case PIPE_FUNC_GEQUAL: for (j = 0; j < QUAD_SIZE; j++) { - if (ref >= (data->stencilVals[j] & valMask)) { + if (refs[j] >= (data->stencilVals[j] & valMask)) { passMask |= (1 << j); } } @@ -348,9 +383,14 @@ apply_stencil_op(struct depth_data *data, { unsigned j; ubyte newstencil[QUAD_SIZE]; + ubyte refs[QUAD_SIZE]; for (j = 0; j < QUAD_SIZE; j++) { newstencil[j] = data->stencilVals[j]; + if (data->use_shader_stencil_refs) + refs[j] = data->shader_stencil_refs[j]; + else + refs[j] = ref; } switch (op) { @@ -367,7 +407,7 @@ apply_stencil_op(struct depth_data *data, case PIPE_STENCIL_OP_REPLACE: for (j = 0; j < QUAD_SIZE; j++) { if (mask & (1 << j)) { - newstencil[j] = ref; + newstencil[j] = refs[j]; } } break; @@ -688,15 +728,18 @@ depth_test_quads_fallback(struct quad_stage *qs, unsigned i, pass = 0; const struct sp_fragment_shader *fs = qs->softpipe->fs; boolean interp_depth = !fs->info.writes_z; + boolean shader_stencil_ref = fs->info.writes_stencil; struct depth_data data; + data.use_shader_stencil_refs = FALSE; if (qs->softpipe->depth_stencil->alpha.enabled) { nr = alpha_test_quads(qs, quads, nr); } - if (qs->softpipe->depth_stencil->depth.enabled || - qs->softpipe->depth_stencil->stencil[0].enabled) { + if (qs->softpipe->framebuffer.zsbuf && + (qs->softpipe->depth_stencil->depth.enabled || + qs->softpipe->depth_stencil->stencil[0].enabled)) { data.ps = qs->softpipe->framebuffer.zsbuf; data.format = data.ps->format; @@ -715,6 +758,9 @@ depth_test_quads_fallback(struct quad_stage *qs, } if (qs->softpipe->depth_stencil->stencil[0].enabled) { + if (shader_stencil_ref) + convert_quad_stencil(&data, quads[i]); + depth_stencil_test_quad(qs, &data, quads[i]); write_depth_stencil_values(&data, quads[i]); } @@ -805,6 +851,9 @@ choose_depth_test(struct quad_stage *qs, boolean occlusion = qs->softpipe->active_query_count; + if(!qs->softpipe->framebuffer.zsbuf) + depth = depthwrite = stencil = FALSE; + /* default */ qs->run = depth_test_quads_fallback; diff --git a/src/gallium/drivers/softpipe/sp_quad_pipe.c b/src/gallium/drivers/softpipe/sp_quad_pipe.c index 43b8e88e334..2cfd02a22c6 100644 --- a/src/gallium/drivers/softpipe/sp_quad_pipe.c +++ b/src/gallium/drivers/softpipe/sp_quad_pipe.c @@ -47,7 +47,8 @@ sp_build_quad_pipeline(struct softpipe_context *sp) sp->framebuffer.zsbuf && !sp->depth_stencil->alpha.enabled && !sp->fs->info.uses_kill && - !sp->fs->info.writes_z; + !sp->fs->info.writes_z && + !sp->fs->info.writes_stencil; sp->quad.first = sp->quad.blend; diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 2053d02f628..37557d11940 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -114,6 +114,8 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) return 1; case PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE: return 0; + case PIPE_CAP_SHADER_STENCIL_EXPORT: + return 1; default: return 0; } diff --git a/src/gallium/drivers/softpipe/sp_state.h b/src/gallium/drivers/softpipe/sp_state.h index 39d204de8a9..525bf23734a 100644 --- a/src/gallium/drivers/softpipe/sp_state.h +++ b/src/gallium/drivers/softpipe/sp_state.h @@ -70,6 +70,8 @@ struct sp_fragment_shader { struct tgsi_shader_info info; + struct draw_fragment_shader *draw_shader; + boolean origin_lower_left; /**< fragment shader uses lower left position origin? */ boolean pixel_center_integer; /**< fragment shader uses integer pixel center? */ @@ -113,126 +115,40 @@ struct sp_so_state { }; -void * -softpipe_create_blend_state(struct pipe_context *, - const struct pipe_blend_state *); -void softpipe_bind_blend_state(struct pipe_context *, - void *); -void softpipe_delete_blend_state(struct pipe_context *, - void *); - -void * -softpipe_create_sampler_state(struct pipe_context *, - const struct pipe_sampler_state *); -void softpipe_bind_sampler_states(struct pipe_context *, unsigned, void **); void -softpipe_bind_vertex_sampler_states(struct pipe_context *, - unsigned num_samplers, - void **samplers); -void -softpipe_bind_geometry_sampler_states(struct pipe_context *, - unsigned num_samplers, - void **samplers); -void softpipe_delete_sampler_state(struct pipe_context *, void *); - -void * -softpipe_create_depth_stencil_state(struct pipe_context *, - const struct pipe_depth_stencil_alpha_state *); -void softpipe_bind_depth_stencil_state(struct pipe_context *, void *); -void softpipe_delete_depth_stencil_state(struct pipe_context *, void *); - -void * -softpipe_create_rasterizer_state(struct pipe_context *, - const struct pipe_rasterizer_state *); -void softpipe_bind_rasterizer_state(struct pipe_context *, void *); -void softpipe_delete_rasterizer_state(struct pipe_context *, void *); - -void softpipe_set_framebuffer_state( struct pipe_context *, - const struct pipe_framebuffer_state * ); - -void softpipe_set_blend_color( struct pipe_context *pipe, - const struct pipe_blend_color *blend_color ); - -void softpipe_set_stencil_ref( struct pipe_context *pipe, - const struct pipe_stencil_ref *stencil_ref ); - -void softpipe_set_clip_state( struct pipe_context *, - const struct pipe_clip_state * ); - -void softpipe_set_sample_mask( struct pipe_context *, - unsigned sample_mask ); - -void softpipe_set_constant_buffer(struct pipe_context *, - uint shader, uint index, - struct pipe_resource *buf); - -void *softpipe_create_fs_state(struct pipe_context *, - const struct pipe_shader_state *); -void softpipe_bind_fs_state(struct pipe_context *, void *); -void softpipe_delete_fs_state(struct pipe_context *, void *); -void *softpipe_create_vs_state(struct pipe_context *, - const struct pipe_shader_state *); -void softpipe_bind_vs_state(struct pipe_context *, void *); -void softpipe_delete_vs_state(struct pipe_context *, void *); -void *softpipe_create_gs_state(struct pipe_context *, - const struct pipe_shader_state *); -void softpipe_bind_gs_state(struct pipe_context *, void *); -void softpipe_delete_gs_state(struct pipe_context *, void *); - -void *softpipe_create_vertex_elements_state(struct pipe_context *, - unsigned count, - const struct pipe_vertex_element *); -void softpipe_bind_vertex_elements_state(struct pipe_context *, void *); -void softpipe_delete_vertex_elements_state(struct pipe_context *, void *); - -void softpipe_set_polygon_stipple( struct pipe_context *, - const struct pipe_poly_stipple * ); - -void softpipe_set_scissor_state( struct pipe_context *, - const struct pipe_scissor_state * ); - -void softpipe_set_sampler_views( struct pipe_context *, - unsigned num, - struct pipe_sampler_view ** ); +softpipe_init_blend_funcs(struct pipe_context *pipe); void -softpipe_set_vertex_sampler_views(struct pipe_context *, - unsigned num, - struct pipe_sampler_view **); +softpipe_init_clip_funcs(struct pipe_context *pipe); void -softpipe_set_geometry_sampler_views(struct pipe_context *, - unsigned num, - struct pipe_sampler_view **); - -struct pipe_sampler_view * -softpipe_create_sampler_view(struct pipe_context *pipe, - struct pipe_resource *texture, - const struct pipe_sampler_view *templ); +softpipe_init_sampler_funcs(struct pipe_context *pipe); void -softpipe_sampler_view_destroy(struct pipe_context *pipe, - struct pipe_sampler_view *view); +softpipe_init_rasterizer_funcs(struct pipe_context *pipe); -void softpipe_set_viewport_state( struct pipe_context *, - const struct pipe_viewport_state * ); - -void softpipe_set_vertex_buffers(struct pipe_context *, - unsigned count, - const struct pipe_vertex_buffer *); +void +softpipe_init_shader_funcs(struct pipe_context *pipe); -void softpipe_set_index_buffer(struct pipe_context *, - const struct pipe_index_buffer *); +void +softpipe_init_streamout_funcs(struct pipe_context *pipe); +void +softpipe_init_vertex_funcs(struct pipe_context *pipe); -void softpipe_update_derived( struct softpipe_context *softpipe ); +void +softpipe_set_framebuffer_state(struct pipe_context *, + const struct pipe_framebuffer_state *); +void +softpipe_update_derived( struct softpipe_context *softpipe ); void softpipe_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info); -void softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode); +void +softpipe_draw_stream_output(struct pipe_context *pipe, unsigned mode); void softpipe_map_transfers(struct softpipe_context *sp); @@ -253,20 +169,5 @@ softpipe_get_vertex_info(struct softpipe_context *softpipe); struct vertex_info * softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe); -void * -softpipe_create_stream_output_state( - struct pipe_context *pipe, - const struct pipe_stream_output_state *templ); -void -softpipe_bind_stream_output_state(struct pipe_context *pipe, - void *so); -void -softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so); - -void -softpipe_set_stream_output_buffers(struct pipe_context *pipe, - struct pipe_resource **buffers, - int *offsets, - int num_buffers); #endif diff --git a/src/gallium/drivers/softpipe/sp_state_blend.c b/src/gallium/drivers/softpipe/sp_state_blend.c index 2a203f44e50..12863824b8e 100644 --- a/src/gallium/drivers/softpipe/sp_state_blend.c +++ b/src/gallium/drivers/softpipe/sp_state_blend.c @@ -34,15 +34,17 @@ #include "sp_state.h" -void * +static void * softpipe_create_blend_state(struct pipe_context *pipe, const struct pipe_blend_state *blend) { return mem_dup(blend, sizeof(*blend)); } -void softpipe_bind_blend_state( struct pipe_context *pipe, - void *blend ) + +static void +softpipe_bind_blend_state(struct pipe_context *pipe, + void *blend) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -53,15 +55,18 @@ void softpipe_bind_blend_state( struct pipe_context *pipe, softpipe->dirty |= SP_NEW_BLEND; } -void softpipe_delete_blend_state(struct pipe_context *pipe, - void *blend) + +static void +softpipe_delete_blend_state(struct pipe_context *pipe, + void *blend) { FREE( blend ); } -void softpipe_set_blend_color( struct pipe_context *pipe, - const struct pipe_blend_color *blend_color ) +static void +softpipe_set_blend_color(struct pipe_context *pipe, + const struct pipe_blend_color *blend_color) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -73,19 +78,15 @@ void softpipe_set_blend_color( struct pipe_context *pipe, } -/** XXX move someday? Or consolidate all these simple state setters - * into one file. - */ - - -void * +static void * softpipe_create_depth_stencil_state(struct pipe_context *pipe, const struct pipe_depth_stencil_alpha_state *depth_stencil) { return mem_dup(depth_stencil, sizeof(*depth_stencil)); } -void + +static void softpipe_bind_depth_stencil_state(struct pipe_context *pipe, void *depth_stencil) { @@ -96,14 +97,17 @@ softpipe_bind_depth_stencil_state(struct pipe_context *pipe, softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA; } -void + +static void softpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth) { FREE( depth ); } -void softpipe_set_stencil_ref( struct pipe_context *pipe, - const struct pipe_stencil_ref *stencil_ref ) + +static void +softpipe_set_stencil_ref(struct pipe_context *pipe, + const struct pipe_stencil_ref *stencil_ref) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -112,9 +116,28 @@ void softpipe_set_stencil_ref( struct pipe_context *pipe, softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA; } -void + +static void softpipe_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask) { } + +void +softpipe_init_blend_funcs(struct pipe_context *pipe) +{ + pipe->create_blend_state = softpipe_create_blend_state; + pipe->bind_blend_state = softpipe_bind_blend_state; + pipe->delete_blend_state = softpipe_delete_blend_state; + + pipe->set_blend_color = softpipe_set_blend_color; + + pipe->create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state; + pipe->bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state; + pipe->delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state; + + pipe->set_stencil_ref = softpipe_set_stencil_ref; + + pipe->set_sample_mask = softpipe_set_sample_mask; +} diff --git a/src/gallium/drivers/softpipe/sp_state_clip.c b/src/gallium/drivers/softpipe/sp_state_clip.c index 4946c776e3e..f3a4c234e27 100644 --- a/src/gallium/drivers/softpipe/sp_state_clip.c +++ b/src/gallium/drivers/softpipe/sp_state_clip.c @@ -32,8 +32,9 @@ #include "draw/draw_context.h" -void softpipe_set_clip_state( struct pipe_context *pipe, - const struct pipe_clip_state *clip ) +static void +softpipe_set_clip_state(struct pipe_context *pipe, + const struct pipe_clip_state *clip) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -42,8 +43,9 @@ void softpipe_set_clip_state( struct pipe_context *pipe, } -void softpipe_set_viewport_state( struct pipe_context *pipe, - const struct pipe_viewport_state *viewport ) +static void +softpipe_set_viewport_state(struct pipe_context *pipe, + const struct pipe_viewport_state *viewport) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -55,8 +57,9 @@ void softpipe_set_viewport_state( struct pipe_context *pipe, } -void softpipe_set_scissor_state( struct pipe_context *pipe, - const struct pipe_scissor_state *scissor ) +static void +softpipe_set_scissor_state(struct pipe_context *pipe, + const struct pipe_scissor_state *scissor) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -67,8 +70,9 @@ void softpipe_set_scissor_state( struct pipe_context *pipe, } -void softpipe_set_polygon_stipple( struct pipe_context *pipe, - const struct pipe_poly_stipple *stipple ) +static void +softpipe_set_polygon_stipple(struct pipe_context *pipe, + const struct pipe_poly_stipple *stipple) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -77,3 +81,13 @@ void softpipe_set_polygon_stipple( struct pipe_context *pipe, softpipe->poly_stipple = *stipple; /* struct copy */ softpipe->dirty |= SP_NEW_STIPPLE; } + + +void +softpipe_init_clip_funcs(struct pipe_context *pipe) +{ + pipe->set_clip_state = softpipe_set_clip_state; + pipe->set_viewport_state = softpipe_set_viewport_state; + pipe->set_scissor_state = softpipe_set_scissor_state; + pipe->set_polygon_stipple = softpipe_set_polygon_stipple; +} diff --git a/src/gallium/drivers/softpipe/sp_state_rasterizer.c b/src/gallium/drivers/softpipe/sp_state_rasterizer.c index c9ede09f268..3cd4acd7432 100644 --- a/src/gallium/drivers/softpipe/sp_state_rasterizer.c +++ b/src/gallium/drivers/softpipe/sp_state_rasterizer.c @@ -33,15 +33,17 @@ -void * +static void * softpipe_create_rasterizer_state(struct pipe_context *pipe, const struct pipe_rasterizer_state *rast) { return mem_dup(rast, sizeof(*rast)); } -void softpipe_bind_rasterizer_state(struct pipe_context *pipe, - void *rasterizer) + +static void +softpipe_bind_rasterizer_state(struct pipe_context *pipe, + void *rasterizer) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -56,10 +58,19 @@ void softpipe_bind_rasterizer_state(struct pipe_context *pipe, softpipe->dirty |= SP_NEW_RASTERIZER; } -void softpipe_delete_rasterizer_state(struct pipe_context *pipe, - void *rasterizer) + +static void +softpipe_delete_rasterizer_state(struct pipe_context *pipe, + void *rasterizer) { FREE( rasterizer ); } +void +softpipe_init_rasterizer_funcs(struct pipe_context *pipe) +{ + pipe->create_rasterizer_state = softpipe_create_rasterizer_state; + pipe->bind_rasterizer_state = softpipe_bind_rasterizer_state; + pipe->delete_rasterizer_state = softpipe_delete_rasterizer_state; +} diff --git a/src/gallium/drivers/softpipe/sp_state_sampler.c b/src/gallium/drivers/softpipe/sp_state_sampler.c index 79d9516ad9c..b59fbc33ed6 100644 --- a/src/gallium/drivers/softpipe/sp_state_sampler.c +++ b/src/gallium/drivers/softpipe/sp_state_sampler.c @@ -33,7 +33,6 @@ #include "util/u_inlines.h" #include "draw/draw_context.h" -#include "draw/draw_context.h" #include "sp_context.h" #include "sp_state.h" @@ -54,7 +53,7 @@ static struct sp_sampler *sp_sampler( struct pipe_sampler_state *sampler ) } -void * +static void * softpipe_create_sampler_state(struct pipe_context *pipe, const struct pipe_sampler_state *sampler) { @@ -67,7 +66,7 @@ softpipe_create_sampler_state(struct pipe_context *pipe, } -void +static void softpipe_bind_sampler_states(struct pipe_context *pipe, unsigned num, void **sampler) { @@ -94,7 +93,7 @@ softpipe_bind_sampler_states(struct pipe_context *pipe, } -void +static void softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, unsigned num_samplers, void **samplers) @@ -118,10 +117,14 @@ softpipe_bind_vertex_sampler_states(struct pipe_context *pipe, softpipe->num_vertex_samplers = num_samplers; + draw_set_samplers(softpipe->draw, + softpipe->vertex_samplers, + softpipe->num_vertex_samplers); + softpipe->dirty |= SP_NEW_SAMPLER; } -void +static void softpipe_bind_geometry_sampler_states(struct pipe_context *pipe, unsigned num_samplers, void **samplers) @@ -149,7 +152,7 @@ softpipe_bind_geometry_sampler_states(struct pipe_context *pipe, } -struct pipe_sampler_view * +static struct pipe_sampler_view * softpipe_create_sampler_view(struct pipe_context *pipe, struct pipe_resource *resource, const struct pipe_sampler_view *templ) @@ -168,7 +171,7 @@ softpipe_create_sampler_view(struct pipe_context *pipe, } -void +static void softpipe_sampler_view_destroy(struct pipe_context *pipe, struct pipe_sampler_view *view) { @@ -177,7 +180,7 @@ softpipe_sampler_view_destroy(struct pipe_context *pipe, } -void +static void softpipe_set_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) @@ -207,7 +210,7 @@ softpipe_set_sampler_views(struct pipe_context *pipe, } -void +static void softpipe_set_vertex_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) @@ -234,10 +237,15 @@ softpipe_set_vertex_sampler_views(struct pipe_context *pipe, softpipe->num_vertex_sampler_views = num; + draw_set_sampler_views(softpipe->draw, + softpipe->vertex_sampler_views, + softpipe->num_vertex_sampler_views); + softpipe->dirty |= SP_NEW_TEXTURE; } -void + +static void softpipe_set_geometry_sampler_views(struct pipe_context *pipe, unsigned num, struct pipe_sampler_view **views) @@ -319,8 +327,6 @@ get_sampler_varient( unsigned unit, } - - void softpipe_reset_sampler_varients(struct softpipe_context *softpipe) { @@ -395,9 +401,7 @@ softpipe_reset_sampler_varients(struct softpipe_context *softpipe) } } - - -void +static void softpipe_delete_sampler_state(struct pipe_context *pipe, void *sampler) { @@ -413,4 +417,20 @@ softpipe_delete_sampler_state(struct pipe_context *pipe, } +void +softpipe_init_sampler_funcs(struct pipe_context *pipe) +{ + pipe->create_sampler_state = softpipe_create_sampler_state; + pipe->bind_fragment_sampler_states = softpipe_bind_sampler_states; + pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states; + pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states; + pipe->delete_sampler_state = softpipe_delete_sampler_state; + + pipe->set_fragment_sampler_views = softpipe_set_sampler_views; + pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views; + pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views; + + pipe->create_sampler_view = softpipe_create_sampler_view; + pipe->sampler_view_destroy = softpipe_sampler_view_destroy; +} diff --git a/src/gallium/drivers/softpipe/sp_state_fs.c b/src/gallium/drivers/softpipe/sp_state_shader.c index ded242d3dc5..7fff338ccea 100644 --- a/src/gallium/drivers/softpipe/sp_state_fs.c +++ b/src/gallium/drivers/softpipe/sp_state_shader.c @@ -42,7 +42,7 @@ #include "tgsi/tgsi_parse.h" -void * +static void * softpipe_create_fs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { @@ -60,7 +60,15 @@ softpipe_create_fs_state(struct pipe_context *pipe, state = softpipe_create_fs_exec( softpipe, templ ); } - assert(state); + if (!state) + return NULL; + + /* draw's fs state */ + state->draw_shader = draw_create_fragment_shader(softpipe->draw, templ); + if (!state->draw_shader) { + state->delete( state ); + return NULL; + } /* get/save the summary info for this shader */ tgsi_scan_shader(templ->tokens, &state->info); @@ -76,7 +84,7 @@ softpipe_create_fs_state(struct pipe_context *pipe, } -void +static void softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -90,11 +98,14 @@ softpipe_bind_fs_state(struct pipe_context *pipe, void *fs) softpipe->fs = fs; + draw_bind_fragment_shader(softpipe->draw, + (softpipe->fs ? softpipe->fs->draw_shader : NULL)); + softpipe->dirty |= SP_NEW_FS; } -void +static void softpipe_delete_fs_state(struct pipe_context *pipe, void *fs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -109,11 +120,13 @@ softpipe_delete_fs_state(struct pipe_context *pipe, void *fs) tgsi_exec_machine_bind_shader(softpipe->fs_machine, NULL, 0, NULL); } + draw_delete_fragment_shader(softpipe->draw, state->draw_shader); + state->delete( state ); } -void * +static void * softpipe_create_vs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { @@ -148,7 +161,7 @@ fail: } -void +static void softpipe_bind_vs_state(struct pipe_context *pipe, void *vs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -162,7 +175,7 @@ softpipe_bind_vs_state(struct pipe_context *pipe, void *vs) } -void +static void softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -174,34 +187,8 @@ softpipe_delete_vs_state(struct pipe_context *pipe, void *vs) FREE( state ); } -void -softpipe_set_constant_buffer(struct pipe_context *pipe, - uint shader, uint index, - struct pipe_resource *constants) -{ - struct softpipe_context *softpipe = softpipe_context(pipe); - unsigned size = constants ? constants->width0 : 0; - const void *data = constants ? softpipe_resource(constants)->data : NULL; - - assert(shader < PIPE_SHADER_TYPES); - draw_flush(softpipe->draw); - - /* note: reference counting */ - pipe_resource_reference(&softpipe->constants[shader][index], constants); - - if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { - draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size); - } - - softpipe->mapped_constants[shader][index] = data; - softpipe->const_buffer_size[shader][index] = size; - - softpipe->dirty |= SP_NEW_CONSTANTS; -} - - -void * +static void * softpipe_create_gs_state(struct pipe_context *pipe, const struct pipe_shader_state *templ) { @@ -240,7 +227,7 @@ fail: } -void +static void softpipe_bind_gs_state(struct pipe_context *pipe, void *gs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -254,7 +241,7 @@ softpipe_bind_gs_state(struct pipe_context *pipe, void *gs) } -void +static void softpipe_delete_gs_state(struct pipe_context *pipe, void *gs) { struct softpipe_context *softpipe = softpipe_context(pipe); @@ -266,3 +253,49 @@ softpipe_delete_gs_state(struct pipe_context *pipe, void *gs) (state) ? state->draw_data : 0); FREE(state); } + + +static void +softpipe_set_constant_buffer(struct pipe_context *pipe, + uint shader, uint index, + struct pipe_resource *constants) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned size = constants ? constants->width0 : 0; + const void *data = constants ? softpipe_resource(constants)->data : NULL; + + assert(shader < PIPE_SHADER_TYPES); + + draw_flush(softpipe->draw); + + /* note: reference counting */ + pipe_resource_reference(&softpipe->constants[shader][index], constants); + + if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) { + draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size); + } + + softpipe->mapped_constants[shader][index] = data; + softpipe->const_buffer_size[shader][index] = size; + + softpipe->dirty |= SP_NEW_CONSTANTS; +} + + +void +softpipe_init_shader_funcs(struct pipe_context *pipe) +{ + pipe->create_fs_state = softpipe_create_fs_state; + pipe->bind_fs_state = softpipe_bind_fs_state; + pipe->delete_fs_state = softpipe_delete_fs_state; + + pipe->create_vs_state = softpipe_create_vs_state; + pipe->bind_vs_state = softpipe_bind_vs_state; + pipe->delete_vs_state = softpipe_delete_vs_state; + + pipe->create_gs_state = softpipe_create_gs_state; + pipe->bind_gs_state = softpipe_bind_gs_state; + pipe->delete_gs_state = softpipe_delete_gs_state; + + pipe->set_constant_buffer = softpipe_set_constant_buffer; +} diff --git a/src/gallium/drivers/softpipe/sp_state_so.c b/src/gallium/drivers/softpipe/sp_state_so.c index cfe23f9e846..ddfa3ef765a 100644 --- a/src/gallium/drivers/softpipe/sp_state_so.c +++ b/src/gallium/drivers/softpipe/sp_state_so.c @@ -34,7 +34,7 @@ #include "draw/draw_context.h" -void * +static void * softpipe_create_stream_output_state(struct pipe_context *pipe, const struct pipe_stream_output_state *templ) { @@ -57,7 +57,8 @@ softpipe_create_stream_output_state(struct pipe_context *pipe, return so; } -void + +static void softpipe_bind_stream_output_state(struct pipe_context *pipe, void *so) { @@ -72,13 +73,15 @@ softpipe_bind_stream_output_state(struct pipe_context *pipe, draw_set_so_state(softpipe->draw, &sp_so->base); } -void + +static void softpipe_delete_stream_output_state(struct pipe_context *pipe, void *so) { FREE( so ); } -void + +static void softpipe_set_stream_output_buffers(struct pipe_context *pipe, struct pipe_resource **buffers, int *offsets, @@ -122,3 +125,16 @@ softpipe_set_stream_output_buffers(struct pipe_context *pipe, draw_set_mapped_so_buffers(softpipe->draw, map_buffers, num_buffers); } + + + +void +softpipe_init_streamout_funcs(struct pipe_context *pipe) +{ + pipe->create_stream_output_state = softpipe_create_stream_output_state; + pipe->bind_stream_output_state = softpipe_bind_stream_output_state; + pipe->delete_stream_output_state = softpipe_delete_stream_output_state; + + pipe->set_stream_output_buffers = softpipe_set_stream_output_buffers; +} + diff --git a/src/gallium/drivers/softpipe/sp_state_vertex.c b/src/gallium/drivers/softpipe/sp_state_vertex.c index b650fcaea5c..7d8055f2baf 100644 --- a/src/gallium/drivers/softpipe/sp_state_vertex.c +++ b/src/gallium/drivers/softpipe/sp_state_vertex.c @@ -36,7 +36,7 @@ #include "draw/draw_context.h" -void * +static void * softpipe_create_vertex_elements_state(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_element *attribs) @@ -51,7 +51,8 @@ softpipe_create_vertex_elements_state(struct pipe_context *pipe, return velems; } -void + +static void softpipe_bind_vertex_elements_state(struct pipe_context *pipe, void *velems) { @@ -66,13 +67,15 @@ softpipe_bind_vertex_elements_state(struct pipe_context *pipe, draw_set_vertex_elements(softpipe->draw, sp_velems->count, sp_velems->velem); } -void + +static void softpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems) { FREE( velems ); } -void + +static void softpipe_set_vertex_buffers(struct pipe_context *pipe, unsigned count, const struct pipe_vertex_buffer *buffers) @@ -89,7 +92,8 @@ softpipe_set_vertex_buffers(struct pipe_context *pipe, draw_set_vertex_buffers(softpipe->draw, count, buffers); } -void + +static void softpipe_set_index_buffer(struct pipe_context *pipe, const struct pipe_index_buffer *ib) { @@ -102,3 +106,15 @@ softpipe_set_index_buffer(struct pipe_context *pipe, draw_set_index_buffer(softpipe->draw, ib); } + + +void +softpipe_init_vertex_funcs(struct pipe_context *pipe) +{ + pipe->create_vertex_elements_state = softpipe_create_vertex_elements_state; + pipe->bind_vertex_elements_state = softpipe_bind_vertex_elements_state; + pipe->delete_vertex_elements_state = softpipe_delete_vertex_elements_state; + + pipe->set_vertex_buffers = softpipe_set_vertex_buffers; + pipe->set_index_buffer = softpipe_set_index_buffer; +} diff --git a/src/gallium/drivers/softpipe/sp_tex_sample.c b/src/gallium/drivers/softpipe/sp_tex_sample.c index e654bb77c29..088e48f81fe 100644 --- a/src/gallium/drivers/softpipe/sp_tex_sample.c +++ b/src/gallium/drivers/softpipe/sp_tex_sample.c @@ -105,14 +105,14 @@ lerp_3d(float a, float b, float c, /** * Compute coord % size for repeat wrap modes. - * Note that if coord is a signed integer, coord % size doesn't give - * the right value for coord < 0 (in terms of texture repeat). Just - * casting to unsigned fixes that. + * Note that if coord is negative, coord % size doesn't give the right + * value. To avoid that problem we add a large multiple of the size + * (rather than using a conditional). */ static INLINE int repeat(int coord, unsigned size) { - return (int) ((unsigned) coord % size); + return (coord + size * 1024) % size; } @@ -656,7 +656,8 @@ get_texel_2d(const struct sp_sampler_varient *samp, if (x < 0 || x >= (int) u_minify(texture->width0, level) || y < 0 || y >= (int) u_minify(texture->height0, level)) { - return samp->sampler->border_color; + return sp_tex_tile_cache_border_color(samp->cache, + samp->sampler->border_color); } else { return get_texel_2d_no_border( samp, addr, x, y ); @@ -750,7 +751,8 @@ get_texel_3d(const struct sp_sampler_varient *samp, if (x < 0 || x >= (int) u_minify(texture->width0, level) || y < 0 || y >= (int) u_minify(texture->height0, level) || z < 0 || z >= (int) u_minify(texture->depth0, level)) { - return samp->sampler->border_color; + return sp_tex_tile_cache_border_color(samp->cache, + samp->sampler->border_color); } else { return get_texel_3d_no_border( samp, addr, x, y, z ); diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index eb74f14a7be..e817c0c8cf5 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -298,3 +298,23 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, +/** + * Return the swizzled border color. + */ +const float * +sp_tex_tile_cache_border_color(struct softpipe_tex_tile_cache *tc, + const float border_color[4]) +{ + float rgba01[6]; + + COPY_4V(rgba01, border_color); + rgba01[PIPE_SWIZZLE_ZERO] = 0.0f; + rgba01[PIPE_SWIZZLE_ONE] = 1.0f; + + tc->swz_border_color[0] = rgba01[tc->swizzle_r]; + tc->swz_border_color[1] = rgba01[tc->swizzle_g]; + tc->swz_border_color[2] = rgba01[tc->swizzle_b]; + tc->swz_border_color[3] = rgba01[tc->swizzle_a]; + + return tc->swz_border_color; +} diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h index 0794ffa0c53..05f25133daa 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.h @@ -90,6 +90,8 @@ struct softpipe_tex_tile_cache unsigned format; struct softpipe_tex_cached_tile *last_tile; /**< most recently retrieved tile */ + + float swz_border_color[4]; /**< swizzled border color */ }; @@ -154,7 +156,9 @@ sp_get_cached_tile_tex(struct softpipe_tex_tile_cache *tc, } - +const float * +sp_tex_tile_cache_border_color(struct softpipe_tex_tile_cache *tc, + const float border_color[4]); #endif /* SP_TEX_TILE_CACHE_H */ diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index bf33fd94173..aa76b8aa1ec 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -38,6 +38,8 @@ #include "util/u_tile.h" #include "sp_tile_cache.h" +static struct softpipe_cached_tile * +sp_alloc_tile(struct softpipe_tile_cache *tc); /** @@ -94,9 +96,19 @@ sp_create_tile_cache( struct pipe_context *pipe ) if (tc) { tc->pipe = pipe; for (pos = 0; pos < NUM_ENTRIES; pos++) { - tc->entries[pos].addr.bits.invalid = 1; + tc->tile_addrs[pos].bits.invalid = 1; + } + tc->last_tile_addr.bits.invalid = 1; + + /* this allocation allows us to guarantee that allocation + * failures are never fatal later + */ + tc->tile = MALLOC_STRUCT( softpipe_cached_tile ); + if (!tc->tile) + { + FREE(tc); + return NULL; } - tc->last_tile = &tc->entries[0]; /* any tile */ /* XXX this code prevents valgrind warnings about use of uninitialized * memory in programs that don't clear the surface before rendering. @@ -120,7 +132,10 @@ sp_destroy_tile_cache(struct softpipe_tile_cache *tc) for (pos = 0; pos < NUM_ENTRIES; pos++) { /*assert(tc->entries[pos].x < 0);*/ + FREE( tc->entries[pos] ); } + FREE( tc->tile ); + if (tc->transfer) { tc->pipe->transfer_destroy(tc->pipe, tc->transfer); } @@ -285,11 +300,14 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) uint numCleared = 0; assert(pt->resource); + if (!tc->tile) + tc->tile = sp_alloc_tile(tc); + /* clear the scratch tile to the clear value */ if (tc->depth_stencil) { - clear_tile(&tc->tile, pt->resource->format, tc->clear_val); + clear_tile(tc->tile, pt->resource->format, tc->clear_val); } else { - clear_tile_rgba(&tc->tile, pt->resource->format, tc->clear_color); + clear_tile_rgba(tc->tile, pt->resource->format, tc->clear_color); } /* push the tile to all positions marked as clear */ @@ -303,12 +321,12 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) pipe_put_tile_raw(tc->pipe, pt, x, y, TILE_SIZE, TILE_SIZE, - tc->tile.data.any, 0/*STRIDE*/); + tc->tile->data.any, 0/*STRIDE*/); } else { pipe_put_tile_rgba(tc->pipe, pt, x, y, TILE_SIZE, TILE_SIZE, - (float *) tc->tile.data.color); + (float *) tc->tile->data.color); } numCleared++; } @@ -323,6 +341,27 @@ sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc) #endif } +static void +sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos) +{ + if (!tc->tile_addrs[pos].bits.invalid) { + if (tc->depth_stencil) { + pipe_put_tile_raw(tc->pipe, tc->transfer, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, + TILE_SIZE, TILE_SIZE, + tc->entries[pos]->data.depth32, 0/*STRIDE*/); + } + else { + pipe_put_tile_rgba(tc->pipe, tc->transfer, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, + TILE_SIZE, TILE_SIZE, + (float *) tc->entries[pos]->data.color); + } + tc->tile_addrs[pos].bits.invalid = 1; /* mark as empty */ + } +} /** * Flush the tile cache: write all dirty tiles back to the transfer. @@ -337,28 +376,21 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) if (pt) { /* caching a drawing transfer */ for (pos = 0; pos < NUM_ENTRIES; pos++) { - struct softpipe_cached_tile *tile = tc->entries + pos; - if (!tile->addr.bits.invalid) { - if (tc->depth_stencil) { - pipe_put_tile_raw(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, - TILE_SIZE, TILE_SIZE, - tile->data.depth32, 0/*STRIDE*/); - } - else { - pipe_put_tile_rgba(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, - TILE_SIZE, TILE_SIZE, - (float *) tile->data.color); - } - tile->addr.bits.invalid = 1; /* mark as empty */ - inuse++; + struct softpipe_cached_tile *tile = tc->entries[pos]; + if (!tile) + { + assert(tc->tile_addrs[pos].bits.invalid); + continue; } + + sp_flush_tile(tc, pos); + ++inuse; } sp_tile_cache_flush_clear(tc); + + + tc->last_tile_addr.bits.invalid = 1; } #if 0 @@ -366,6 +398,38 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) #endif } +static struct softpipe_cached_tile * +sp_alloc_tile(struct softpipe_tile_cache *tc) +{ + struct softpipe_cached_tile * tile = MALLOC_STRUCT(softpipe_cached_tile); + if (!tile) + { + /* in this case, steal an existing tile */ + if (!tc->tile) + { + unsigned pos; + for (pos = 0; pos < NUM_ENTRIES; ++pos) { + if (!tc->entries[pos]) + continue; + + sp_flush_tile(tc, pos); + tc->tile = tc->entries[pos]; + tc->entries[pos] = NULL; + break; + } + + /* this should never happen */ + if (!tc->tile) + abort(); + } + + tile = tc->tile; + tc->tile = NULL; + + tc->last_tile_addr.bits.invalid = 1; + } + return tile; +} /** * Get a tile from the cache. @@ -380,30 +444,35 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, /* cache pos/entry: */ const int pos = CACHE_POS(addr.bits.x, addr.bits.y); - struct softpipe_cached_tile *tile = tc->entries + pos; + struct softpipe_cached_tile *tile = tc->entries[pos]; + + if (!tile) { + tile = sp_alloc_tile(tc); + tc->entries[pos] = tile; + } - if (addr.value != tile->addr.value) { + if (addr.value != tc->tile_addrs[pos].value) { assert(pt->resource); - if (tile->addr.bits.invalid == 0) { + if (tc->tile_addrs[pos].bits.invalid == 0) { /* put dirty tile back in framebuffer */ if (tc->depth_stencil) { pipe_put_tile_raw(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { pipe_put_tile_rgba(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, (float *) tile->data.color); } } - tile->addr = addr; + tc->tile_addrs[pos] = addr; if (is_clear_flag_set(tc->clear_flags, addr)) { /* don't get tile from framebuffer, just clear it */ @@ -419,15 +488,15 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, /* get new tile data from transfer */ if (tc->depth_stencil) { pipe_get_tile_raw(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, tile->data.depth32, 0/*STRIDE*/); } else { pipe_get_tile_rgba(tc->pipe, pt, - tile->addr.bits.x * TILE_SIZE, - tile->addr.bits.y * TILE_SIZE, + tc->tile_addrs[pos].bits.x * TILE_SIZE, + tc->tile_addrs[pos].bits.y * TILE_SIZE, TILE_SIZE, TILE_SIZE, (float *) tile->data.color); } @@ -435,6 +504,7 @@ sp_find_cached_tile(struct softpipe_tile_cache *tc, } tc->last_tile = tile; + tc->last_tile_addr = addr; return tile; } @@ -464,7 +534,7 @@ sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba, memset(tc->clear_flags, 255, sizeof(tc->clear_flags)); for (pos = 0; pos < NUM_ENTRIES; pos++) { - struct softpipe_cached_tile *tile = tc->entries + pos; - tile->addr.bits.invalid = 1; + tc->tile_addrs[pos].bits.invalid = 1; } + tc->last_tile_addr.bits.invalid = 1; } diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index e03d53eb24e..031c7c1ea5c 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -57,7 +57,6 @@ union tile_address { struct softpipe_cached_tile { - union tile_address addr; union { float color[TILE_SIZE][TILE_SIZE][4]; uint color32[TILE_SIZE][TILE_SIZE]; @@ -83,14 +82,16 @@ struct softpipe_tile_cache struct pipe_transfer *transfer; void *transfer_map; - struct softpipe_cached_tile entries[NUM_ENTRIES]; + union tile_address tile_addrs[NUM_ENTRIES]; + struct softpipe_cached_tile *entries[NUM_ENTRIES]; uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32]; float clear_color[4]; /**< for color bufs */ uint clear_val; /**< for z+stencil, or packed color clear value */ boolean depth_stencil; /**< Is the surface a depth/stencil format? */ - struct softpipe_cached_tile tile; /**< scratch tile for clears */ + struct softpipe_cached_tile *tile; /**< scratch tile for clears */ + union tile_address last_tile_addr; struct softpipe_cached_tile *last_tile; /**< most recently retrieved tile */ }; @@ -147,7 +148,7 @@ sp_get_cached_tile(struct softpipe_tile_cache *tc, { union tile_address addr = tile_address( x, y ); - if (tc->last_tile->addr.value == addr.value) + if (tc->last_tile_addr.value == addr.value) return tc->last_tile; return sp_find_cached_tile( tc, addr ); |