llvmpipe: implement scissor testing

The scissor test is implemented as another per-quad operation in
the JIT code.  The four scissor box params are passed via the
lp_jit_context.  In the JIT code we compare the quad's x/y coords
against the clip bounds and create a new in/out mask that's AND'd
with the main quad mask.

Note: we should also do scissor testing in the triangle setup code
to improve efficiency.  That's not done yet.
This commit is contained in:
Brian Paul 2010-01-14 19:15:00 -07:00
parent ca12e30d97
commit 4461442849
8 changed files with 135 additions and 8 deletions

View File

@ -79,13 +79,16 @@ lp_jit_init_globals(struct llvmpipe_screen *screen)
/* struct lp_jit_context */
{
LLVMTypeRef elem_types[4];
LLVMTypeRef elem_types[8];
LLVMTypeRef context_type;
elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */
elem_types[1] = LLVMFloatType(); /* alpha_ref_value */
elem_types[2] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */
elem_types[3] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
elem_types[1] = LLVMFloatType(); /* alpha_ref_value */ elem_types[2] = LLVMFloatType(); /* scissor_xmin */
elem_types[3] = LLVMFloatType(); /* scissor_ymin */
elem_types[4] = LLVMFloatType(); /* scissor_xmax */
elem_types[5] = LLVMFloatType(); /* scissor_ymax */
elem_types[6] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */
elem_types[7] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
context_type = LLVMStructType(elem_types, Elements(elem_types), 0);
@ -93,8 +96,16 @@ lp_jit_init_globals(struct llvmpipe_screen *screen)
screen->target, context_type, 0);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
screen->target, context_type, 1);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color,
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmin,
screen->target, context_type, 2);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymin,
screen->target, context_type, 3);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_xmax,
screen->target, context_type, 4);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, scissor_ymax,
screen->target, context_type, 5);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, blend_color,
screen->target, context_type, 6);
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
screen->target, context_type,
LP_JIT_CONTEXT_TEXTURES_INDEX);

View File

@ -79,6 +79,9 @@ struct lp_jit_context
float alpha_ref_value;
/** floats, not ints */
float scissor_xmin, scissor_ymin, scissor_xmax, scissor_ymax;
/* FIXME: store (also?) in floats */
uint8_t *blend_color;
@ -92,10 +95,22 @@ struct lp_jit_context
#define lp_jit_context_alpha_ref_value(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 1, "alpha_ref_value")
#define lp_jit_context_blend_color(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 2, "blend_color")
#define lp_jit_context_scissor_xmin_value(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 2, "scissor_xmin")
#define LP_JIT_CONTEXT_TEXTURES_INDEX 3
#define lp_jit_context_scissor_ymin_value(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 3, "scissor_ymin")
#define lp_jit_context_scissor_xmax_value(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 4, "scissor_xmax")
#define lp_jit_context_scissor_ymax_value(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 5, "scissor_ymax")
#define lp_jit_context_blend_color(_builder, _ptr) \
lp_build_struct_get(_builder, _ptr, 6, "blend_color")
#define LP_JIT_CONTEXT_TEXTURES_INDEX 7
#define lp_jit_context_textures(_builder, _ptr) \
lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures")

View File

@ -413,6 +413,21 @@ lp_setup_set_blend_color( struct setup_context *setup,
}
void
lp_setup_set_scissor( struct setup_context *setup,
const struct pipe_scissor_state *scissor )
{
LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
assert(scissor);
if (memcmp(&setup->scissor.current, scissor, sizeof(*scissor)) != 0) {
setup->scissor.current = *scissor; /* struct copy */
setup->dirty |= LP_SETUP_NEW_SCISSOR;
}
}
void
lp_setup_set_flatshade_first( struct setup_context *setup,
boolean flatshade_first )
@ -534,6 +549,25 @@ lp_setup_update_state( struct setup_context *setup )
setup->dirty |= LP_SETUP_NEW_FS;
}
if (setup->dirty & LP_SETUP_NEW_SCISSOR) {
float *stored;
stored = lp_scene_alloc_aligned(scene, 4 * sizeof(int32_t), 16);
stored[0] = (float) setup->scissor.current.minx;
stored[1] = (float) setup->scissor.current.miny;
stored[2] = (float) setup->scissor.current.maxx;
stored[3] = (float) setup->scissor.current.maxy;
setup->scissor.stored = stored;
setup->fs.current.jit_context.scissor_xmin = stored[0];
setup->fs.current.jit_context.scissor_ymin = stored[1];
setup->fs.current.jit_context.scissor_xmax = stored[2];
setup->fs.current.jit_context.scissor_ymax = stored[3];
setup->dirty |= LP_SETUP_NEW_FS;
}
if(setup->dirty & LP_SETUP_NEW_CONSTANTS) {
struct pipe_buffer *buffer = setup->constants.current;

View File

@ -113,6 +113,10 @@ void
lp_setup_set_blend_color( struct setup_context *setup,
const struct pipe_blend_color *blend_color );
void
lp_setup_set_scissor( struct setup_context *setup,
const struct pipe_scissor_state *scissor );
void
lp_setup_set_sampler_textures( struct setup_context *setup,
unsigned num, struct pipe_texture **texture);

View File

@ -45,6 +45,7 @@
#define LP_SETUP_NEW_FS 0x01
#define LP_SETUP_NEW_CONSTANTS 0x02
#define LP_SETUP_NEW_BLEND_COLOR 0x04
#define LP_SETUP_NEW_SCISSOR 0x08
struct lp_scene_queue;
@ -122,6 +123,11 @@ struct setup_context
uint8_t *stored;
} blend_color;
struct {
struct pipe_scissor_state current;
const void *stored;
} scissor;
unsigned dirty; /**< bitmask of LP_SETUP_NEW_x bits */
void (*point)( struct setup_context *,

View File

@ -72,6 +72,7 @@ struct lp_fragment_shader_variant_key
enum pipe_format zsbuf_format;
unsigned nr_cbufs:8;
unsigned flatshade:1;
unsigned scissor:1;
struct {
ubyte colormask;

View File

@ -160,6 +160,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
if (llvmpipe->dirty & (LP_NEW_FS |
LP_NEW_BLEND |
LP_NEW_SCISSOR |
LP_NEW_DEPTH_STENCIL_ALPHA |
LP_NEW_RASTERIZER |
LP_NEW_SAMPLER |
@ -170,6 +171,9 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
lp_setup_set_blend_color(llvmpipe->setup,
&llvmpipe->blend_color);
if (llvmpipe->dirty & LP_NEW_SCISSOR)
lp_setup_set_scissor(llvmpipe->setup, &llvmpipe->scissor);
if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA)
lp_setup_set_alpha_ref_value(llvmpipe->setup,
llvmpipe->depth_stencil->alpha.ref_value);

View File

@ -304,6 +304,51 @@ generate_tri_edge_mask(LLVMBuilderRef builder,
}
static LLVMValueRef
generate_scissor_test(LLVMBuilderRef builder,
LLVMValueRef context_ptr,
const struct lp_build_interp_soa_context *interp,
struct lp_type type)
{
LLVMTypeRef vec_type = lp_build_vec_type(type);
LLVMValueRef xpos = interp->pos[0], ypos = interp->pos[1];
LLVMValueRef xmin, ymin, xmax, ymax;
LLVMValueRef m0, m1, m2, m3, m;
/* xpos, ypos contain the window coords for the four pixels in the quad */
assert(xpos);
assert(ypos);
/* get the current scissor bounds, convert to vectors */
xmin = lp_jit_context_scissor_xmin_value(builder, context_ptr);
xmin = lp_build_broadcast(builder, vec_type, xmin);
ymin = lp_jit_context_scissor_ymin_value(builder, context_ptr);
ymin = lp_build_broadcast(builder, vec_type, ymin);
xmax = lp_jit_context_scissor_xmax_value(builder, context_ptr);
xmax = lp_build_broadcast(builder, vec_type, xmax);
ymax = lp_jit_context_scissor_ymax_value(builder, context_ptr);
ymax = lp_build_broadcast(builder, vec_type, ymax);
/* compare the fragment's position coordinates against the scissor bounds */
m0 = lp_build_compare(builder, type, PIPE_FUNC_GEQUAL, xpos, xmin);
m1 = lp_build_compare(builder, type, PIPE_FUNC_GEQUAL, ypos, ymin);
m2 = lp_build_compare(builder, type, PIPE_FUNC_LESS, xpos, xmax);
m3 = lp_build_compare(builder, type, PIPE_FUNC_LESS, ypos, ymax);
/* AND all the masks together */
m = LLVMBuildAnd(builder, m0, m1, "");
m = LLVMBuildAnd(builder, m, m2, "");
m = LLVMBuildAnd(builder, m, m3, "");
lp_build_name(m, "scissormask");
return m;
}
/**
* Generate the fragment shader, depth/stencil test, and alpha tests.
* \param i which quad in the tile, in range [0,3]
@ -372,6 +417,11 @@ generate_fs(struct llvmpipe_context *lp,
/* 'mask' will control execution based on quad's pixel alive/killed state */
lp_build_mask_begin(&mask, flow, type, *pmask);
if (key->scissor) {
LLVMValueRef smask =
generate_scissor_test(builder, context_ptr, interp, type);
lp_build_mask_update(&mask, smask);
}
early_depth_test =
key->depth.enabled &&
@ -968,6 +1018,7 @@ make_variant_key(struct llvmpipe_context *lp,
/* alpha.ref_value is passed in jit_context */
key->flatshade = lp->rasterizer->flatshade;
key->scissor = lp->rasterizer->scissor;
if (lp->framebuffer.nr_cbufs) {
memcpy(&key->blend, lp->blend, sizeof key->blend);
@ -1033,6 +1084,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
key.blend.colormask == 0xf &&
!key.alpha.enabled &&
!key.depth.enabled &&
!key.scissor &&
!shader->info.uses_kill
? TRUE : FALSE;