Exemple #1
0
/**
 * 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);
   }
}