/** * Do the one or two-sided stencil test op/update. */ static LLVMValueRef lp_build_stencil_op(struct lp_build_context *bld, const struct pipe_stencil_state stencil[2], enum stencil_op op, LLVMValueRef stencilRefs[2], LLVMValueRef stencilVals, LLVMValueRef mask, LLVMValueRef front_facing) { LLVMBuilderRef builder = bld->gallivm->builder; LLVMValueRef res; assert(stencil[0].enabled); /* do front face op */ res = lp_build_stencil_op_single(bld, &stencil[0], op, stencilRefs[0], stencilVals); if (stencil[1].enabled && front_facing != NULL) { /* do back face op */ LLVMValueRef back_res; back_res = lp_build_stencil_op_single(bld, &stencil[1], op, stencilRefs[1], stencilVals); res = lp_build_select(bld, front_facing, res, back_res); } if (stencil[0].writemask != 0xff || (stencil[1].enabled && front_facing != NULL && stencil[1].writemask != 0xff)) { /* mask &= stencil[0].writemask */ LLVMValueRef writemask = lp_build_const_int_vec(bld->gallivm, bld->type, stencil[0].writemask); if (stencil[1].enabled && stencil[1].writemask != stencil[0].writemask && front_facing != NULL) { LLVMValueRef back_writemask = lp_build_const_int_vec(bld->gallivm, bld->type, stencil[1].writemask); writemask = lp_build_select(bld, front_facing, writemask, back_writemask); } mask = LLVMBuildAnd(builder, mask, writemask, ""); /* res = (res & mask) | (stencilVals & ~mask) */ res = lp_build_select_bitwise(bld, mask, res, stencilVals); } else { /* res = mask ? res : stencilVals */ res = lp_build_select(bld, mask, res, stencilVals); } return res; }
/** * Do the one or two-sided stencil test op/update. */ static LLVMValueRef lp_build_stencil_op(struct lp_build_context *bld, const struct pipe_stencil_state stencil[2], enum stencil_op op, LLVMValueRef stencilRefs[2], LLVMValueRef stencilVals, LLVMValueRef mask, LLVMValueRef face) { assert(stencil[0].enabled); if (stencil[1].enabled && face) { /* do two-sided op */ struct lp_build_flow_context *flow_ctx; struct lp_build_if_state if_ctx; LLVMValueRef front_facing; LLVMValueRef zero = LLVMConstReal(LLVMFloatType(), 0.0); LLVMValueRef result = bld->undef; flow_ctx = lp_build_flow_create(bld->builder); lp_build_flow_scope_begin(flow_ctx); lp_build_flow_scope_declare(flow_ctx, &result); /* front_facing = face > 0.0 */ front_facing = LLVMBuildFCmp(bld->builder, LLVMRealUGT, face, zero, ""); lp_build_if(&if_ctx, flow_ctx, bld->builder, front_facing); { result = lp_build_stencil_op_single(bld, &stencil[0], op, stencilRefs[0], stencilVals, mask); } lp_build_else(&if_ctx); { result = lp_build_stencil_op_single(bld, &stencil[1], op, stencilRefs[1], stencilVals, mask); } lp_build_endif(&if_ctx); lp_build_flow_scope_end(flow_ctx); lp_build_flow_destroy(flow_ctx); return result; } else { /* do single-sided op */ return lp_build_stencil_op_single(bld, &stencil[0], op, stencilRefs[0], stencilVals, mask); } }