+ assert(!z_src_type.sign);
+ assert(z_src_type.norm);
+ }
+
+ /* Pick the depth type. */
+ z_type = lp_depth_type(format_desc, z_src_type.width*z_src_type.length);
+
+ /* FIXME: Cope with a depth test type with a different bit width. */
+ assert(z_type.width == z_src_type.width);
+ assert(z_type.length == z_src_type.length);
+
+ /* Sanity checking */
+ {
+ const unsigned z_swizzle = format_desc->swizzle[0];
+ const unsigned s_swizzle = format_desc->swizzle[1];
+
+ assert(z_swizzle != UTIL_FORMAT_SWIZZLE_NONE ||
+ s_swizzle != UTIL_FORMAT_SWIZZLE_NONE);
+
+ assert(depth->enabled || stencil[0].enabled);
+
+ assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
+ assert(format_desc->block.width == 1);
+ assert(format_desc->block.height == 1);
+
+ if (stencil[0].enabled) {
+ assert(format_desc->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
+ format_desc->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM);
+ }
+
+ assert(z_swizzle < 4);
+ assert(format_desc->block.bits == z_type.width);
+ if (z_type.floating) {
+ assert(z_swizzle == 0);
+ assert(format_desc->channel[z_swizzle].type ==
+ UTIL_FORMAT_TYPE_FLOAT);
+ assert(format_desc->channel[z_swizzle].size ==
+ format_desc->block.bits);
+ }
+ else {
+ assert(format_desc->channel[z_swizzle].type ==
+ UTIL_FORMAT_TYPE_UNSIGNED);
+ assert(format_desc->channel[z_swizzle].normalized);
+ assert(!z_type.fixed);
+ }
+ }
+
+
+ /* Setup build context for Z vals */
+ lp_build_context_init(&z_bld, gallivm, z_type);
+
+ /* Setup build context for stencil vals */
+ s_type = lp_type_int_vec(z_type.width);
+ lp_build_context_init(&s_bld, gallivm, s_type);
+
+ /* Load current z/stencil value from z/stencil buffer */
+ zs_dst_ptr = LLVMBuildBitCast(builder,
+ zs_dst_ptr,
+ LLVMPointerType(z_bld.vec_type, 0), "");
+ zs_dst = LLVMBuildLoad(builder, zs_dst_ptr, "");
+
+ lp_build_name(zs_dst, "zs_dst");
+
+
+ /* Compute and apply the Z/stencil bitmasks and shifts.
+ */
+ {
+ unsigned s_shift, s_mask;
+
+ if (get_z_shift_and_mask(format_desc, &z_shift, &z_width, &z_mask)) {
+ if (z_mask != 0xffffffff) {
+ z_bitmask = lp_build_const_int_vec(gallivm, z_type, z_mask);
+ }
+
+ /*
+ * Align the framebuffer Z 's LSB to the right.
+ */
+ if (z_shift) {
+ LLVMValueRef shift = lp_build_const_int_vec(gallivm, z_type, z_shift);
+ z_dst = LLVMBuildLShr(builder, zs_dst, shift, "z_dst");
+ } else if (z_bitmask) {
+ /* TODO: Instead of loading a mask from memory and ANDing, it's
+ * probably faster to just shake the bits with two shifts. */
+ z_dst = LLVMBuildAnd(builder, zs_dst, z_bitmask, "z_dst");
+ } else {
+ z_dst = zs_dst;
+ lp_build_name(z_dst, "z_dst");
+ }
+ }
+
+ if (get_s_shift_and_mask(format_desc, &s_shift, &s_mask)) {
+ if (s_shift) {
+ LLVMValueRef shift = lp_build_const_int_vec(gallivm, s_type, s_shift);
+ stencil_vals = LLVMBuildLShr(builder, zs_dst, shift, "");
+ stencil_shift = shift; /* used below */
+ }
+ else {
+ stencil_vals = zs_dst;
+ }
+
+ if (s_mask != 0xffffffff) {
+ LLVMValueRef mask = lp_build_const_int_vec(gallivm, s_type, s_mask);
+ stencil_vals = LLVMBuildAnd(builder, stencil_vals, mask, "");
+ }
+
+ lp_build_name(stencil_vals, "s_dst");
+ }
+ }
+
+ if (stencil[0].enabled) {
+
+ if (face) {
+ LLVMValueRef zero = lp_build_const_int32(gallivm, 0);
+
+ /* front_facing = face != 0 ? ~0 : 0 */
+ front_facing = LLVMBuildICmp(builder, LLVMIntNE, face, zero, "");
+ front_facing = LLVMBuildSExt(builder, front_facing,
+ LLVMIntTypeInContext(gallivm->context,
+ s_bld.type.length*s_bld.type.width),
+ "");
+ front_facing = LLVMBuildBitCast(builder, front_facing,
+ s_bld.int_vec_type, "");
+ }
+
+ /* convert scalar stencil refs into vectors */
+ stencil_refs[0] = lp_build_broadcast_scalar(&s_bld, stencil_refs[0]);
+ stencil_refs[1] = lp_build_broadcast_scalar(&s_bld, stencil_refs[1]);
+
+ s_pass_mask = lp_build_stencil_test(&s_bld, stencil,
+ stencil_refs, stencil_vals,
+ front_facing);
+
+ /* apply stencil-fail operator */
+ {
+ LLVMValueRef s_fail_mask = lp_build_andnot(&s_bld, orig_mask, s_pass_mask);
+ stencil_vals = lp_build_stencil_op(&s_bld, stencil, S_FAIL_OP,
+ stencil_refs, stencil_vals,
+ s_fail_mask, front_facing);
+ }
+ }
+
+ if (depth->enabled) {
+ /*
+ * Convert fragment Z to the desired type, aligning the LSB to the right.
+ */
+
+ assert(z_type.width == z_src_type.width);
+ assert(z_type.length == z_src_type.length);
+ assert(lp_check_value(z_src_type, z_src));
+ if (z_src_type.floating) {
+ /*
+ * Convert from floating point values
+ */
+
+ if (!z_type.floating) {
+ z_src = lp_build_clamped_float_to_unsigned_norm(gallivm,
+ z_src_type,
+ z_width,
+ z_src);
+ }
+ } else {
+ /*
+ * Convert from unsigned normalized values.
+ */
+
+ assert(!z_src_type.sign);
+ assert(!z_src_type.fixed);
+ assert(z_src_type.norm);
+ assert(!z_type.floating);
+ if (z_src_type.width > z_width) {
+ LLVMValueRef shift = lp_build_const_int_vec(gallivm, z_src_type,
+ z_src_type.width - z_width);
+ z_src = LLVMBuildLShr(builder, z_src, shift, "");
+ }
+ }
+ assert(lp_check_value(z_type, z_src));
+
+ lp_build_name(z_src, "z_src");
+
+ /* compare src Z to dst Z, returning 'pass' mask */
+ z_pass = lp_build_cmp(&z_bld, depth->func, z_src, z_dst);
+
+ if (!stencil[0].enabled) {
+ /* We can potentially skip all remaining operations here, but only
+ * if stencil is disabled because we still need to update the stencil
+ * buffer values. Don't need to update Z buffer values.
+ */
+ lp_build_mask_update(mask, z_pass);
+
+ if (do_branch) {
+ lp_build_mask_check(mask);
+ do_branch = FALSE;
+ }