diff options
| -rw-r--r-- | src/gallium/drivers/llvmpipe/lp_bld_arit.c | 54 | 
1 files changed, 50 insertions, 4 deletions
| diff --git a/src/gallium/drivers/llvmpipe/lp_bld_arit.c b/src/gallium/drivers/llvmpipe/lp_bld_arit.c index 83ca06acf8..93e797cb44 100644 --- a/src/gallium/drivers/llvmpipe/lp_bld_arit.c +++ b/src/gallium/drivers/llvmpipe/lp_bld_arit.c @@ -361,6 +361,8 @@ lp_build_mul(struct lp_build_context *bld,               LLVMValueRef b)  {     const struct lp_type type = bld->type; +   LLVMValueRef shift; +   LLVMValueRef res;     if(a == bld->zero)        return bld->zero; @@ -394,10 +396,31 @@ lp_build_mul(struct lp_build_context *bld,        assert(0);     } -   if(LLVMIsConstant(a) && LLVMIsConstant(b)) -      return LLVMConstMul(a, b); +   if(type.fixed) +      shift = lp_build_int_const_scalar(type, type.width/2); +   else +      shift = NULL; -   return LLVMBuildMul(bld->builder, a, b, ""); +   if(LLVMIsConstant(a) && LLVMIsConstant(b)) { +      res =  LLVMConstMul(a, b); +      if(shift) { +         if(type.sign) +            res = LLVMConstAShr(res, shift); +         else +            res = LLVMConstLShr(res, shift); +      } +   } +   else { +      res = LLVMBuildMul(bld->builder, a, b, ""); +      if(shift) { +         if(type.sign) +            res = LLVMBuildAShr(bld->builder, res, shift, ""); +         else +            res = LLVMBuildLShr(bld->builder, res, shift, ""); +      } +   } + +   return res;  } @@ -432,13 +455,36 @@ lp_build_div(struct lp_build_context *bld,  } +/** + * Linear interpolation. + * + * This also works for integer values with a few caveats. + * + * @sa http://www.stereopsis.com/doubleblend.html + */  LLVMValueRef  lp_build_lerp(struct lp_build_context *bld,                LLVMValueRef x,                LLVMValueRef v0,                LLVMValueRef v1)  { -   return lp_build_add(bld, v0, lp_build_mul(bld, x, lp_build_sub(bld, v1, v0))); +   LLVMValueRef delta; +   LLVMValueRef res; + +   delta = lp_build_sub(bld, v1, v0); + +   res = lp_build_mul(bld, x, delta); + +   res = lp_build_add(bld, v0, res); + +   if(bld->type.fixed) +      /* XXX: This step is necessary for lerping 8bit colors stored on 16bits, +       * but it will be wrong for other uses. Basically we need a more +       * powerful lp_type, capable of further distinguishing the values +       * interpretation from the value storage. */ +      res = LLVMBuildAnd(bld->builder, res, lp_build_int_const_scalar(bld->type, (1 << bld->type.width/2) - 1), ""); + +   return res;  } | 
