+ }
+ else {
+ /* no depth test, apply Zpass operator to stencil buffer values */
+ apply_stencil_op(data, quad->inout.mask, zPassOp, ref, wrtMask);
+ }
+ }
+}
+
+
+#define ALPHATEST( FUNC, COMP ) \
+ static int \
+ alpha_test_quads_##FUNC( struct quad_stage *qs, \
+ struct quad_header *quads[], \
+ unsigned nr ) \
+ { \
+ const float ref = qs->softpipe->depth_stencil->alpha.ref_value; \
+ const uint cbuf = 0; /* only output[0].alpha is tested */ \
+ unsigned pass_nr = 0; \
+ unsigned i; \
+ \
+ for (i = 0; i < nr; i++) { \
+ const float *aaaa = quads[i]->output.color[cbuf][3]; \
+ unsigned passMask = 0; \
+ \
+ if (aaaa[0] COMP ref) passMask |= (1 << 0); \
+ if (aaaa[1] COMP ref) passMask |= (1 << 1); \
+ if (aaaa[2] COMP ref) passMask |= (1 << 2); \
+ if (aaaa[3] COMP ref) passMask |= (1 << 3); \
+ \
+ quads[i]->inout.mask &= passMask; \
+ \
+ if (quads[i]->inout.mask) \
+ quads[pass_nr++] = quads[i]; \
+ } \
+ \
+ return pass_nr; \
+ }
+
+
+ALPHATEST( LESS, < )
+ALPHATEST( EQUAL, == )
+ALPHATEST( LEQUAL, <= )
+ALPHATEST( GREATER, > )
+ALPHATEST( NOTEQUAL, != )
+ALPHATEST( GEQUAL, >= )
+
+
+/* XXX: Incorporate into shader using KILP.
+ */
+static int
+alpha_test_quads(struct quad_stage *qs,
+ struct quad_header *quads[],
+ unsigned nr)
+{
+ switch (qs->softpipe->depth_stencil->alpha.func) {
+ case PIPE_FUNC_LESS:
+ return alpha_test_quads_LESS( qs, quads, nr );
+ case PIPE_FUNC_EQUAL:
+ return alpha_test_quads_EQUAL( qs, quads, nr );
+ break;
+ case PIPE_FUNC_LEQUAL:
+ return alpha_test_quads_LEQUAL( qs, quads, nr );
+ case PIPE_FUNC_GREATER:
+ return alpha_test_quads_GREATER( qs, quads, nr );
+ case PIPE_FUNC_NOTEQUAL:
+ return alpha_test_quads_NOTEQUAL( qs, quads, nr );
+ case PIPE_FUNC_GEQUAL:
+ return alpha_test_quads_GEQUAL( qs, quads, nr );
+ case PIPE_FUNC_ALWAYS:
+ return nr;
+ case PIPE_FUNC_NEVER:
+ default:
+ return 0;
+ }
+}
+
+
+static unsigned mask_count[16] =
+{
+ 0, /* 0x0 */
+ 1, /* 0x1 */
+ 1, /* 0x2 */
+ 2, /* 0x3 */
+ 1, /* 0x4 */
+ 2, /* 0x5 */
+ 2, /* 0x6 */
+ 3, /* 0x7 */
+ 1, /* 0x8 */
+ 2, /* 0x9 */
+ 2, /* 0xa */
+ 3, /* 0xb */
+ 2, /* 0xc */
+ 3, /* 0xd */
+ 3, /* 0xe */
+ 4, /* 0xf */
+};
+
+
+
+/** helper to get number of Z buffer bits */
+static unsigned
+get_depth_bits(struct quad_stage *qs)
+{
+ struct pipe_surface *zsurf = qs->softpipe->framebuffer.zsbuf;
+ if (zsurf)
+ return util_format_get_component_bits(zsurf->format,
+ UTIL_FORMAT_COLORSPACE_ZS, 0);
+ else
+ return 0;
+}
+
+
+
+/**
+ * General depth/stencil test function. Used when there's no fast-path.
+ */
+static void
+depth_test_quads_fallback(struct quad_stage *qs,
+ struct quad_header *quads[],
+ unsigned nr)
+{
+ unsigned i, pass = 0;
+ const struct sp_fragment_shader *fs = qs->softpipe->fs;
+ boolean interp_depth = !fs->info.writes_z;
+ struct depth_data data;
+
+
+ if (qs->softpipe->depth_stencil->alpha.enabled) {
+ nr = alpha_test_quads(qs, quads, nr);
+ }
+
+ if (get_depth_bits(qs) > 0 &&
+ (qs->softpipe->depth_stencil->depth.enabled ||
+ qs->softpipe->depth_stencil->stencil[0].enabled)) {
+
+ data.ps = qs->softpipe->framebuffer.zsbuf;
+ data.format = data.ps->format;
+ data.tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache,
+ quads[0]->input.x0,
+ quads[0]->input.y0);
+
+ for (i = 0; i < nr; i++) {
+ get_depth_stencil_values(&data, quads[i]);
+
+ if (qs->softpipe->depth_stencil->depth.enabled) {
+ if (interp_depth)
+ interpolate_quad_depth(quads[i]);
+
+ convert_quad_depth(&data, quads[i]);