gallivm: checkpoint: stencil test code
authorBrian Paul <brianp@vmware.com>
Tue, 16 Mar 2010 00:19:04 +0000 (18:19 -0600)
committerBrian Paul <brianp@vmware.com>
Tue, 16 Mar 2010 00:19:04 +0000 (18:19 -0600)
src/gallium/auxiliary/gallivm/lp_bld_depth.c

index 829cffea4c863ba5ed23970eadb91c94fa9448ea..cbc48f986519656cdad6ab7e13a8d629d7f1d1aa 100644 (file)
 #include "util/u_format.h"
 
 #include "lp_bld_type.h"
+#include "lp_bld_arit.h"
 #include "lp_bld_const.h"
 #include "lp_bld_logic.h"
 #include "lp_bld_flow.h"
 #include "lp_bld_debug.h"
 #include "lp_bld_depth.h"
+#include "lp_bld_swizzle.h"
+
+
+
+/**
+ * Do the stencil test comparison (compare fb Z values against ref value.
+ * \param stencilVals  vector of stencil values from framebuffer
+ * \param stencilRef  the stencil reference value, replicated as a vector
+ * \return mask of pass/fail values
+ */
+static LLVMValueRef
+lp_build_stencil_test(struct lp_build_context *bld,
+                      const struct pipe_stencil_state *stencil,
+                      LLVMValueRef stencilVals,
+                      LLVMValueRef stencilRef)
+{
+   const unsigned stencilMax = 255; /* XXX fix */
+   struct lp_type type = bld->type;
+   LLVMValueRef res;
+
+   assert(stencil->enabled);
+
+   if (stencil->valuemask != stencilMax) {
+      /* compute stencilRef = stencilRef & valuemask */
+      LLVMValueRef valuemask = lp_build_const_int_vec(type, stencil->valuemask);
+      stencilRef = LLVMBuildAnd(bld->builder, stencilRef, valuemask, "");
+      /* compute stencilVals = stencilVals & valuemask */
+      stencilVals = LLVMBuildAnd(bld->builder, stencilVals, valuemask, "");
+   }
+
+   res = lp_build_compare(bld->builder, bld->type, stencil->func,
+                          stencilVals, stencilRef);
+
+   return res;
+}
+
+
+/**
+ * Apply the stencil operator (add/sub/keep/etc) to the given vector
+ * of stencil values.
+ * \return  new stencil values vector
+ */
+static LLVMValueRef
+lp_build_stencil_op(struct lp_build_context *bld,
+                    unsigned stencil_op,
+                    LLVMValueRef stencilRef,
+                    const struct pipe_stencil_state *stencil,
+                    LLVMValueRef stencilVals)
+
+{
+   const unsigned stencilMax = 255; /* XXX fix */
+   struct lp_type type = bld->type;
+   LLVMValueRef res;
+   LLVMValueRef max = lp_build_const_int_vec(type, stencilMax);
+
+   switch (stencil_op) {
+   case PIPE_STENCIL_OP_KEEP:
+      res = stencilVals;
+   case PIPE_STENCIL_OP_ZERO:
+      res = bld->zero;
+   case PIPE_STENCIL_OP_REPLACE:
+      res = lp_build_broadcast_scalar(bld, stencilRef);
+   case PIPE_STENCIL_OP_INCR:
+      res = lp_build_add(bld, stencilVals, bld->one);
+      res = lp_build_min(bld, res, max);
+   case PIPE_STENCIL_OP_DECR:
+      res = lp_build_sub(bld, stencilVals, bld->one);
+      res = lp_build_max(bld, res, bld->zero);
+   case PIPE_STENCIL_OP_INCR_WRAP:
+      res = lp_build_add(bld, stencilVals, bld->one);
+      res = LLVMBuildAnd(bld->builder, res, max, "");
+   case PIPE_STENCIL_OP_DECR_WRAP:
+      res = lp_build_sub(bld, stencilVals, bld->one);
+      res = LLVMBuildAnd(bld->builder, res, max, "");
+   case PIPE_STENCIL_OP_INVERT:
+      res = LLVMBuildNot(bld->builder, stencilVals, "");
+   default:
+      assert(0 && "bad stencil op mode");
+      res = NULL;
+   }
+
+   if (stencil->writemask != stencilMax) {
+      /* compute res = (res & mask) | (stencilVals & ~mask) */
+      LLVMValueRef mask = lp_build_const_int_vec(type, stencil->writemask);
+      LLVMValueRef cmask = LLVMBuildNot(bld->builder, mask, "notWritemask");
+      LLVMValueRef t1 = LLVMBuildAnd(bld->builder, res, mask, "t1");
+      LLVMValueRef t2 = LLVMBuildAnd(bld->builder, stencilVals, cmask, "t2");
+      res = LLVMBuildOr(bld->builder, t1, t2, "t1_or_t2");
+   }
+
+   return res;
+}
 
 
 /**
@@ -109,7 +202,14 @@ lp_depth_type(const struct util_format_description *format_desc,
 
 
 /**
- * Depth test.
+ * Generate code for performing depth and/or stencil tests.
+ * We operate on a vector of values (typically a 2x2 quad).
+ *
+ * \param type  the data type of the fragment depth/stencil values
+ * \param format_desc  description of the depth/stencil surface
+ * \param mask  the alive/dead pixel mask for the quad
+ * \param src  the incoming depth/stencil values (a 2x2 quad)
+ * \param dst_ptr  the outgoing/updated depth/stencil values
  */
 void
 lp_build_depth_test(LLVMBuilderRef builder,
@@ -126,6 +226,9 @@ lp_build_depth_test(LLVMBuilderRef builder,
    LLVMValueRef z_bitmask = NULL;
    LLVMValueRef test;
 
+   (void) lp_build_stencil_test;
+   (void) lp_build_stencil_op;
+
    if(!state->enabled)
       return;
 
@@ -198,6 +301,7 @@ lp_build_depth_test(LLVMBuilderRef builder,
 
    lp_build_name(dst, "zsbuf.z");
 
+   /* compare src Z to dst Z, returning 'pass' mask */
    test = lp_build_cmp(&bld, state->func, src, dst);
    lp_build_mask_update(mask, test);