Mesa (lp-binning): llvmpipe: implement scissor testing

Brian Paul brianp at kemper.freedesktop.org
Fri Jan 15 02:24:02 UTC 2010


Module: Mesa
Branch: lp-binning
Commit: 4461442849bfdb817334b38567136f7f9dabdf59
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=4461442849bfdb817334b38567136f7f9dabdf59

Author: Brian Paul <brianp at vmware.com>
Date:   Thu Jan 14 19:15:00 2010 -0700

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.

---

 src/gallium/drivers/llvmpipe/lp_jit.c           |   21 +++++++--
 src/gallium/drivers/llvmpipe/lp_jit.h           |   19 +++++++-
 src/gallium/drivers/llvmpipe/lp_setup.c         |   34 +++++++++++++++
 src/gallium/drivers/llvmpipe/lp_setup.h         |    4 ++
 src/gallium/drivers/llvmpipe/lp_setup_context.h |    6 +++
 src/gallium/drivers/llvmpipe/lp_state.h         |    1 +
 src/gallium/drivers/llvmpipe/lp_state_derived.c |    4 ++
 src/gallium/drivers/llvmpipe/lp_state_fs.c      |   52 +++++++++++++++++++++++
 8 files changed, 134 insertions(+), 7 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_jit.c b/src/gallium/drivers/llvmpipe/lp_jit.c
index 4ef0783..429cb97 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.c
+++ b/src/gallium/drivers/llvmpipe/lp_jit.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_jit.h b/src/gallium/drivers/llvmpipe/lp_jit.h
index 3b31691..9cbe1bd 100644
--- a/src/gallium/drivers/llvmpipe/lp_jit.h
+++ b/src/gallium/drivers/llvmpipe/lp_jit.h
@@ -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_scissor_xmin_value(_builder, _ptr) \
+   lp_build_struct_get(_builder, _ptr, 2, "scissor_xmin")
+
+#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, 2, "blend_color")
+   lp_build_struct_get(_builder, _ptr, 6, "blend_color")
 
-#define LP_JIT_CONTEXT_TEXTURES_INDEX 3
+#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")
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 649e979..284337e 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
index 429abeb..c7ef3d3 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -114,6 +114,10 @@ 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);
 
diff --git a/src/gallium/drivers/llvmpipe/lp_setup_context.h b/src/gallium/drivers/llvmpipe/lp_setup_context.h
index e6f6f0e..fc0aef1 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup_context.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup_context.h
@@ -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 *,
diff --git a/src/gallium/drivers/llvmpipe/lp_state.h b/src/gallium/drivers/llvmpipe/lp_state.h
index 4c6747b..ddb152c 100644
--- a/src/gallium/drivers/llvmpipe/lp_state.h
+++ b/src/gallium/drivers/llvmpipe/lp_state.h
@@ -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;
diff --git a/src/gallium/drivers/llvmpipe/lp_state_derived.c b/src/gallium/drivers/llvmpipe/lp_state_derived.c
index 2c349fd..28af477 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_derived.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_derived.c
@@ -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);
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index 26a2d6c..d12d3f6 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -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;
 




More information about the mesa-commit mailing list