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:
parent
ca12e30d97
commit
4461442849
|
@ -79,13 +79,16 @@ lp_jit_init_globals(struct llvmpipe_screen *screen)
|
||||||
|
|
||||||
/* struct lp_jit_context */
|
/* struct lp_jit_context */
|
||||||
{
|
{
|
||||||
LLVMTypeRef elem_types[4];
|
LLVMTypeRef elem_types[8];
|
||||||
LLVMTypeRef context_type;
|
LLVMTypeRef context_type;
|
||||||
|
|
||||||
elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */
|
elem_types[0] = LLVMPointerType(LLVMFloatType(), 0); /* constants */
|
||||||
elem_types[1] = LLVMFloatType(); /* alpha_ref_value */
|
elem_types[1] = LLVMFloatType(); /* alpha_ref_value */ elem_types[2] = LLVMFloatType(); /* scissor_xmin */
|
||||||
elem_types[2] = LLVMPointerType(LLVMInt8Type(), 0); /* blend_color */
|
elem_types[3] = LLVMFloatType(); /* scissor_ymin */
|
||||||
elem_types[3] = LLVMArrayType(texture_type, PIPE_MAX_SAMPLERS); /* textures */
|
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);
|
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);
|
screen->target, context_type, 0);
|
||||||
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
|
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, alpha_ref_value,
|
||||||
screen->target, context_type, 1);
|
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);
|
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,
|
LP_CHECK_MEMBER_OFFSET(struct lp_jit_context, textures,
|
||||||
screen->target, context_type,
|
screen->target, context_type,
|
||||||
LP_JIT_CONTEXT_TEXTURES_INDEX);
|
LP_JIT_CONTEXT_TEXTURES_INDEX);
|
||||||
|
|
|
@ -79,6 +79,9 @@ struct lp_jit_context
|
||||||
|
|
||||||
float alpha_ref_value;
|
float alpha_ref_value;
|
||||||
|
|
||||||
|
/** floats, not ints */
|
||||||
|
float scissor_xmin, scissor_ymin, scissor_xmax, scissor_ymax;
|
||||||
|
|
||||||
/* FIXME: store (also?) in floats */
|
/* FIXME: store (also?) in floats */
|
||||||
uint8_t *blend_color;
|
uint8_t *blend_color;
|
||||||
|
|
||||||
|
@ -92,10 +95,22 @@ struct lp_jit_context
|
||||||
#define lp_jit_context_alpha_ref_value(_builder, _ptr) \
|
#define lp_jit_context_alpha_ref_value(_builder, _ptr) \
|
||||||
lp_build_struct_get(_builder, _ptr, 1, "alpha_ref_value")
|
lp_build_struct_get(_builder, _ptr, 1, "alpha_ref_value")
|
||||||
|
|
||||||
#define lp_jit_context_blend_color(_builder, _ptr) \
|
#define lp_jit_context_scissor_xmin_value(_builder, _ptr) \
|
||||||
lp_build_struct_get(_builder, _ptr, 2, "blend_color")
|
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) \
|
#define lp_jit_context_textures(_builder, _ptr) \
|
||||||
lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures")
|
lp_build_struct_get_ptr(_builder, _ptr, LP_JIT_CONTEXT_TEXTURES_INDEX, "textures")
|
||||||
|
|
|
@ -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
|
void
|
||||||
lp_setup_set_flatshade_first( struct setup_context *setup,
|
lp_setup_set_flatshade_first( struct setup_context *setup,
|
||||||
boolean flatshade_first )
|
boolean flatshade_first )
|
||||||
|
@ -534,6 +549,25 @@ lp_setup_update_state( struct setup_context *setup )
|
||||||
setup->dirty |= LP_SETUP_NEW_FS;
|
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) {
|
if(setup->dirty & LP_SETUP_NEW_CONSTANTS) {
|
||||||
struct pipe_buffer *buffer = setup->constants.current;
|
struct pipe_buffer *buffer = setup->constants.current;
|
||||||
|
|
|
@ -113,6 +113,10 @@ void
|
||||||
lp_setup_set_blend_color( struct setup_context *setup,
|
lp_setup_set_blend_color( struct setup_context *setup,
|
||||||
const struct pipe_blend_color *blend_color );
|
const struct pipe_blend_color *blend_color );
|
||||||
|
|
||||||
|
void
|
||||||
|
lp_setup_set_scissor( struct setup_context *setup,
|
||||||
|
const struct pipe_scissor_state *scissor );
|
||||||
|
|
||||||
void
|
void
|
||||||
lp_setup_set_sampler_textures( struct setup_context *setup,
|
lp_setup_set_sampler_textures( struct setup_context *setup,
|
||||||
unsigned num, struct pipe_texture **texture);
|
unsigned num, struct pipe_texture **texture);
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
#define LP_SETUP_NEW_FS 0x01
|
#define LP_SETUP_NEW_FS 0x01
|
||||||
#define LP_SETUP_NEW_CONSTANTS 0x02
|
#define LP_SETUP_NEW_CONSTANTS 0x02
|
||||||
#define LP_SETUP_NEW_BLEND_COLOR 0x04
|
#define LP_SETUP_NEW_BLEND_COLOR 0x04
|
||||||
|
#define LP_SETUP_NEW_SCISSOR 0x08
|
||||||
|
|
||||||
|
|
||||||
struct lp_scene_queue;
|
struct lp_scene_queue;
|
||||||
|
@ -122,6 +123,11 @@ struct setup_context
|
||||||
uint8_t *stored;
|
uint8_t *stored;
|
||||||
} blend_color;
|
} blend_color;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
struct pipe_scissor_state current;
|
||||||
|
const void *stored;
|
||||||
|
} scissor;
|
||||||
|
|
||||||
unsigned dirty; /**< bitmask of LP_SETUP_NEW_x bits */
|
unsigned dirty; /**< bitmask of LP_SETUP_NEW_x bits */
|
||||||
|
|
||||||
void (*point)( struct setup_context *,
|
void (*point)( struct setup_context *,
|
||||||
|
|
|
@ -72,6 +72,7 @@ struct lp_fragment_shader_variant_key
|
||||||
enum pipe_format zsbuf_format;
|
enum pipe_format zsbuf_format;
|
||||||
unsigned nr_cbufs:8;
|
unsigned nr_cbufs:8;
|
||||||
unsigned flatshade:1;
|
unsigned flatshade:1;
|
||||||
|
unsigned scissor:1;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
ubyte colormask;
|
ubyte colormask;
|
||||||
|
|
|
@ -160,6 +160,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
||||||
|
|
||||||
if (llvmpipe->dirty & (LP_NEW_FS |
|
if (llvmpipe->dirty & (LP_NEW_FS |
|
||||||
LP_NEW_BLEND |
|
LP_NEW_BLEND |
|
||||||
|
LP_NEW_SCISSOR |
|
||||||
LP_NEW_DEPTH_STENCIL_ALPHA |
|
LP_NEW_DEPTH_STENCIL_ALPHA |
|
||||||
LP_NEW_RASTERIZER |
|
LP_NEW_RASTERIZER |
|
||||||
LP_NEW_SAMPLER |
|
LP_NEW_SAMPLER |
|
||||||
|
@ -170,6 +171,9 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
|
||||||
lp_setup_set_blend_color(llvmpipe->setup,
|
lp_setup_set_blend_color(llvmpipe->setup,
|
||||||
&llvmpipe->blend_color);
|
&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)
|
if (llvmpipe->dirty & LP_NEW_DEPTH_STENCIL_ALPHA)
|
||||||
lp_setup_set_alpha_ref_value(llvmpipe->setup,
|
lp_setup_set_alpha_ref_value(llvmpipe->setup,
|
||||||
llvmpipe->depth_stencil->alpha.ref_value);
|
llvmpipe->depth_stencil->alpha.ref_value);
|
||||||
|
|
|
@ -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.
|
* Generate the fragment shader, depth/stencil test, and alpha tests.
|
||||||
* \param i which quad in the tile, in range [0,3]
|
* \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 */
|
/* 'mask' will control execution based on quad's pixel alive/killed state */
|
||||||
lp_build_mask_begin(&mask, flow, type, *pmask);
|
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 =
|
early_depth_test =
|
||||||
key->depth.enabled &&
|
key->depth.enabled &&
|
||||||
|
@ -968,6 +1018,7 @@ make_variant_key(struct llvmpipe_context *lp,
|
||||||
/* alpha.ref_value is passed in jit_context */
|
/* alpha.ref_value is passed in jit_context */
|
||||||
|
|
||||||
key->flatshade = lp->rasterizer->flatshade;
|
key->flatshade = lp->rasterizer->flatshade;
|
||||||
|
key->scissor = lp->rasterizer->scissor;
|
||||||
|
|
||||||
if (lp->framebuffer.nr_cbufs) {
|
if (lp->framebuffer.nr_cbufs) {
|
||||||
memcpy(&key->blend, lp->blend, sizeof key->blend);
|
memcpy(&key->blend, lp->blend, sizeof key->blend);
|
||||||
|
@ -1033,6 +1084,7 @@ llvmpipe_update_fs(struct llvmpipe_context *lp)
|
||||||
key.blend.colormask == 0xf &&
|
key.blend.colormask == 0xf &&
|
||||||
!key.alpha.enabled &&
|
!key.alpha.enabled &&
|
||||||
!key.depth.enabled &&
|
!key.depth.enabled &&
|
||||||
|
!key.scissor &&
|
||||||
!shader->info.uses_kill
|
!shader->info.uses_kill
|
||||||
? TRUE : FALSE;
|
? TRUE : FALSE;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue