diff options
Diffstat (limited to 'src/mesa/pipe/softpipe')
-rw-r--r-- | src/mesa/pipe/softpipe/sp_context.c | 11 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_context.h | 3 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_quad.c | 7 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_quad.h | 1 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_quad_stencil.c | 134 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_state.h | 23 | ||||
-rw-r--r-- | src/mesa/pipe/softpipe/sp_state_blend.c | 11 |
7 files changed, 174 insertions, 16 deletions
diff --git a/src/mesa/pipe/softpipe/sp_context.c b/src/mesa/pipe/softpipe/sp_context.c index 9becab4918..6afc0c1320 100644 --- a/src/mesa/pipe/softpipe/sp_context.c +++ b/src/mesa/pipe/softpipe/sp_context.c @@ -65,20 +65,21 @@ struct pipe_context *softpipe_create( void ) struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context); softpipe->pipe.destroy = softpipe_destroy; - softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; softpipe->pipe.set_alpha_test_state = softpipe_set_alpha_test_state; - softpipe->pipe.set_blend_state = softpipe_set_blend_state; softpipe->pipe.set_blend_color = softpipe_set_blend_color; + softpipe->pipe.set_blend_state = softpipe_set_blend_state; softpipe->pipe.set_clip_state = softpipe_set_clip_state; softpipe->pipe.set_clear_color_state = softpipe_set_clear_color_state; softpipe->pipe.set_depth_state = softpipe_set_depth_test_state; - softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; - softpipe->pipe.set_setup_state = softpipe_set_setup_state; - softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; + softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state; softpipe->pipe.set_fs_state = softpipe_set_fs_state; softpipe->pipe.set_polygon_stipple = softpipe_set_polygon_stipple; softpipe->pipe.set_sampler_state = softpipe_set_sampler_state; + softpipe->pipe.set_scissor_state = softpipe_set_scissor_state; + softpipe->pipe.set_setup_state = softpipe_set_setup_state; + softpipe->pipe.set_stencil_state = softpipe_set_stencil_state; softpipe->pipe.set_texture_state = softpipe_set_texture_state; + softpipe->pipe.set_viewport_state = softpipe_set_viewport_state; softpipe->pipe.draw_vb = softpipe_draw_vb; softpipe->pipe.clear = softpipe_clear; diff --git a/src/mesa/pipe/softpipe/sp_context.h b/src/mesa/pipe/softpipe/sp_context.h index c6046624a1..2379a99b81 100644 --- a/src/mesa/pipe/softpipe/sp_context.h +++ b/src/mesa/pipe/softpipe/sp_context.h @@ -63,6 +63,7 @@ enum interp_mode { #define SP_NEW_DEPTH_TEST 0x200 #define SP_NEW_SAMPLER 0x400 #define SP_NEW_TEXTURE 0x800 +#define SP_NEW_STENCIL 0x1000 struct softpipe_context { @@ -82,6 +83,7 @@ struct softpipe_context { struct pipe_scissor_state scissor; struct pipe_sampler_state sampler[PIPE_MAX_SAMPLERS]; struct pipe_setup_state setup; + struct pipe_stencil_state stencil; struct pipe_texture_object *texture[PIPE_MAX_SAMPLERS]; struct pipe_viewport_state viewport; GLuint dirty; @@ -117,6 +119,7 @@ struct softpipe_context { struct { struct quad_stage *shade; struct quad_stage *alpha_test; + struct quad_stage *stencil_test; struct quad_stage *depth_test; struct quad_stage *blend; struct quad_stage *output; diff --git a/src/mesa/pipe/softpipe/sp_quad.c b/src/mesa/pipe/softpipe/sp_quad.c index 63126a4da3..31278f529d 100644 --- a/src/mesa/pipe/softpipe/sp_quad.c +++ b/src/mesa/pipe/softpipe/sp_quad.c @@ -16,7 +16,12 @@ sp_build_quad_pipeline(struct softpipe_context *sp) sp->quad.first = sp->quad.blend; } - if (sp->depth_test.enabled) { + if ( sp->stencil.front_enabled + || sp->stencil.front_enabled) { + sp->quad.stencil_test->next = sp->quad.first; + sp->quad.first = sp->quad.stencil_test; + } + else if (sp->depth_test.enabled) { sp->quad.depth_test->next = sp->quad.first; sp->quad.first = sp->quad.depth_test; } diff --git a/src/mesa/pipe/softpipe/sp_quad.h b/src/mesa/pipe/softpipe/sp_quad.h index 79f52721a3..c09905c249 100644 --- a/src/mesa/pipe/softpipe/sp_quad.h +++ b/src/mesa/pipe/softpipe/sp_quad.h @@ -48,6 +48,7 @@ struct quad_stage { struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe ); struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe ); +struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe ); struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe ); struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe ); struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe ); diff --git a/src/mesa/pipe/softpipe/sp_quad_stencil.c b/src/mesa/pipe/softpipe/sp_quad_stencil.c new file mode 100644 index 0000000000..9f59d09906 --- /dev/null +++ b/src/mesa/pipe/softpipe/sp_quad_stencil.c @@ -0,0 +1,134 @@ + +/** + * \brief Quad stencil testing + */ + + +#include "main/glheader.h" +#include "main/imports.h" +#include "sp_context.h" +#include "sp_headers.h" +#include "sp_surface.h" +#include "sp_quad.h" +#include "pipe/p_defines.h" + + +static void +stencil_test_quad(struct quad_stage *qs, struct quad_header *quad) +{ + struct softpipe_context *softpipe = qs->softpipe; + struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf); + GLuint bzzzz[QUAD_SIZE]; /**< Z values fetched from depth buffer */ + GLuint qzzzz[QUAD_SIZE]; /**< Z values from the quad */ + GLuint zmask = 0; + GLuint j; + GLfloat scale; + + assert(sps); /* shouldn't get here if there's no zbuffer */ + + /* + * To increase efficiency, we should probably have multiple versions + * of this function that are specifically for Z16, Z32 and FP Z buffers. + * Try to effectively do that with codegen... + */ + if (sps->surface.format == PIPE_FORMAT_U_Z16) + scale = 65535.0; + else + assert(0); /* XXX fix this someday */ + + /* + * Convert quad's float depth values to int depth values. + * If the Z buffer stores integer values, we _have_ to do the depth + * compares with integers (not floats). Otherwise, the float->int->float + * conversion of Z values (which isn't an identity function) will cause + * Z-fighting errors. + */ + for (j = 0; j < QUAD_SIZE; j++) { + qzzzz[j] = (GLuint) (quad->outputs.depth[j] * scale); + } + + /* get zquad from zbuffer */ + sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz); + + switch (softpipe->depth_test.func) { + case PIPE_FUNC_NEVER: + /* zmask = 0 */ + break; + case PIPE_FUNC_LESS: + /* Note this is pretty much a single sse or cell instruction. + * Like this: quad->mask &= (quad->outputs.depth < zzzz); + */ + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] < bzzzz[j]) + zmask |= 1 << j; + } + break; + case PIPE_FUNC_EQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] == bzzzz[j]) + zmask |= 1 << j; + } + break; + case PIPE_FUNC_LEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] <= bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_GREATER: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] > bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_NOTEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] != bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_GEQUAL: + for (j = 0; j < QUAD_SIZE; j++) { + if (qzzzz[j] >= bzzzz[j]) + zmask |= (1 << j); + } + break; + case PIPE_FUNC_ALWAYS: + zmask = MASK_ALL; + break; + default: + abort(); + } + + quad->mask &= zmask; + + if (softpipe->depth_test.writemask) { + + /* This is also efficient with sse / spe instructions: + */ + for (j = 0; j < QUAD_SIZE; j++) { + if (quad->mask & (1 << j)) { + bzzzz[j] = qzzzz[j]; + } + } + + /* write updated zquad to zbuffer */ + sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz); + } + + if (quad->mask) + qs->next->run(qs->next, quad); +} + + + + +struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe ) +{ + struct quad_stage *stage = CALLOC_STRUCT(quad_stage); + + stage->softpipe = softpipe; + stage->run = stencil_test_quad; + + return stage; +} diff --git a/src/mesa/pipe/softpipe/sp_state.h b/src/mesa/pipe/softpipe/sp_state.h index 38a212b79a..71c1a2d9ba 100644 --- a/src/mesa/pipe/softpipe/sp_state.h +++ b/src/mesa/pipe/softpipe/sp_state.h @@ -56,8 +56,14 @@ void softpipe_set_clip_state( struct pipe_context *, void softpipe_set_depth_test_state( struct pipe_context *, const struct pipe_depth_state * ); -void softpipe_set_viewport_state( struct pipe_context *, - const struct pipe_viewport_state * ); +void softpipe_set_fs_state( struct pipe_context *, + const struct pipe_fs_state * ); + +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_setup_state( struct pipe_context *, const struct pipe_setup_state * ); @@ -66,18 +72,15 @@ void softpipe_set_sampler_state( struct pipe_context *, GLuint unit, const struct pipe_sampler_state * ); +void softpipe_set_stencil_state( struct pipe_context *, + const struct pipe_stencil_state * ); + void softpipe_set_texture_state( struct pipe_context *, GLuint unit, struct pipe_texture_object * ); -void softpipe_set_scissor_state( struct pipe_context *, - const struct pipe_scissor_state * ); - -void softpipe_set_fs_state( struct pipe_context *, - const struct pipe_fs_state * ); - -void softpipe_set_polygon_stipple( struct pipe_context *, - const struct pipe_poly_stipple * ); +void softpipe_set_viewport_state( struct pipe_context *, + const struct pipe_viewport_state * ); void softpipe_update_derived( struct softpipe_context *softpipe ); diff --git a/src/mesa/pipe/softpipe/sp_state_blend.c b/src/mesa/pipe/softpipe/sp_state_blend.c index ae8950e386..8bc22b0efc 100644 --- a/src/mesa/pipe/softpipe/sp_state_blend.c +++ b/src/mesa/pipe/softpipe/sp_state_blend.c @@ -80,3 +80,14 @@ softpipe_set_alpha_test_state(struct pipe_context *pipe, softpipe->dirty |= SP_NEW_ALPHA_TEST; } +void +softpipe_set_stencil_state(struct pipe_context *pipe, + const struct pipe_stencil_state *stencil) +{ + struct softpipe_context *softpipe = softpipe_context(pipe); + + softpipe->stencil = *stencil; + + softpipe->dirty |= SP_NEW_STENCIL; +} + |