iris: Don't enable smooth points when point sprites are enabled
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_format_srgb.c
index 848d6f8121b3ed8b061d14384c510f59fa7cb067..d5cf698b060d3d2cb3496dfa407ffea3f95183ac 100644 (file)
  *   (3rd order polynomial is required for crappy but just sufficient accuracy)
  *
  * @param src   integer (vector) value(s) to convert
- *              (8 bit values unpacked to 32 bit already).
+ *              (chan_bits bit values unpacked to 32 bit already).
  */
 LLVMValueRef
 lp_build_srgb_to_linear(struct gallivm_state *gallivm,
                         struct lp_type src_type,
+                        unsigned chan_bits,
                         LLVMValueRef src)
 {
    struct lp_type f32_type = lp_type_float_vec(32, src_type.length * 32);
@@ -105,6 +106,8 @@ lp_build_srgb_to_linear(struct gallivm_state *gallivm,
    };
 
    assert(src_type.width == 32);
+   /* Technically this would work with more bits too but would be inaccurate. */
+   assert(chan_bits <= 8);
 
    lp_build_context_init(&f32_bld, gallivm, f32_type);
 
@@ -124,6 +127,12 @@ lp_build_srgb_to_linear(struct gallivm_state *gallivm,
     */
    /* doing the 1/255 mul as part of the approximation */
    srcf = lp_build_int_to_float(&f32_bld, src);
+   if (chan_bits != 8) {
+      /* could adjust all the constants instead */
+      LLVMValueRef rescale_const = lp_build_const_vec(gallivm, f32_type,
+                                                      255.0f / ((1 << chan_bits) - 1));
+      srcf = lp_build_mul(&f32_bld, srcf, rescale_const);
+   }
    lin_const = lp_build_const_vec(gallivm, f32_type, 1.0f / (12.6f * 255.0f));
    part_lin = lp_build_mul(&f32_bld, srcf, lin_const);
 
@@ -150,6 +159,7 @@ lp_build_srgb_to_linear(struct gallivm_state *gallivm,
 static LLVMValueRef
 lp_build_linear_to_srgb(struct gallivm_state *gallivm,
                         struct lp_type src_type,
+                        unsigned chan_bits,
                         LLVMValueRef src)
 {
    LLVMBuilderRef builder = gallivm->builder;
@@ -242,8 +252,10 @@ lp_build_linear_to_srgb(struct gallivm_state *gallivm,
        * error metric if you'd want to tweak them, they also MUST fit with
        * the crappy polynomial above for srgb->linear since it is required
        * that each srgb value maps back to the same value).
-       * This function has an error of max +-0.17 (and we'd only require +-0.6),
-       * for the approximated srgb->linear values the error is naturally larger
+       * This function has an error of max +-0.17. Not sure this is actually
+       * enough, we require +-0.6 but that may include the +-0.5 from integer
+       * conversion. Seems to pass all relevant tests though...
+       * For the approximated srgb->linear values the error is naturally larger
        * (+-0.42) but still accurate enough (required +-0.5 essentially).
        * All in all (including min/max clamp, conversion) 15 instructions.
        * FMA would help (minus 2 instructions).
@@ -277,8 +289,7 @@ lp_build_linear_to_srgb(struct gallivm_state *gallivm,
       c_const = lp_build_const_vec(gallivm, src_type, -0.0620f * 255.0f);
 
       tmp = lp_build_mul(&f32_bld, a_const, x0375);
-      tmp2 = lp_build_mul(&f32_bld, b_const, x05);
-      tmp2 = lp_build_add(&f32_bld, tmp2, c_const);
+      tmp2 = lp_build_mad(&f32_bld, b_const, x05, c_const);
       pow_final = lp_build_add(&f32_bld, tmp, tmp2);
    }
 
@@ -290,6 +301,13 @@ lp_build_linear_to_srgb(struct gallivm_state *gallivm,
    is_linear = lp_build_compare(gallivm, src_type, PIPE_FUNC_LEQUAL, src, lin_thresh);
    tmp = lp_build_select(&f32_bld, is_linear, lin, pow_final);
 
+   if (chan_bits != 8) {
+      /* could adjust all the constants instead */
+      LLVMValueRef rescale_const = lp_build_const_vec(gallivm, src_type,
+                                                      ((1 << chan_bits) - 1) / 255.0f);
+      tmp = lp_build_mul(&f32_bld, tmp, rescale_const);
+   }
+
    f32_bld.type.sign = 0;
    return lp_build_iround(&f32_bld, tmp);
 }
@@ -298,7 +316,9 @@ lp_build_linear_to_srgb(struct gallivm_state *gallivm,
 /**
  * Convert linear float soa values to packed srgb AoS values.
  * This only handles packed formats which are 4x8bit in size
- * (rgba and rgbx plus swizzles).
+ * (rgba and rgbx plus swizzles), and 16bit 565-style formats
+ * with no alpha. (In the latter case the return values won't be
+ * fully packed, it will look like r5g6b5x16r5g6b5x16...)
  *
  * @param src   float SoA (vector) values to convert.
  */
@@ -318,20 +338,21 @@ lp_build_float_to_srgb_packed(struct gallivm_state *gallivm,
 
    /* rgb is subject to linear->srgb conversion, alpha is not */
    for (chan = 0; chan < 3; chan++) {
-      tmpsrgb[chan] = lp_build_linear_to_srgb(gallivm, src_type, src[chan]);
+      unsigned chan_bits = dst_fmt->channel[dst_fmt->swizzle[chan]].size;
+      tmpsrgb[chan] = lp_build_linear_to_srgb(gallivm, src_type, chan_bits, src[chan]);
    }
    /*
     * can't use lp_build_conv since we want to keep values as 32bit
     * here so we can interleave with rgb to go from SoA->AoS.
     */
-   alpha = lp_build_clamp(&f32_bld, src[3], f32_bld.zero, f32_bld.one);
+   alpha = lp_build_clamp_zero_one_nanzero(&f32_bld, src[3]);
    alpha = lp_build_mul(&f32_bld, alpha,
                         lp_build_const_vec(gallivm, src_type, 255.0f));
    tmpsrgb[3] = lp_build_iround(&f32_bld, alpha);
 
    dst = lp_build_zero(gallivm, int32_type);
    for (chan = 0; chan < dst_fmt->nr_channels; chan++) {
-      if (dst_fmt->swizzle[chan] <= UTIL_FORMAT_SWIZZLE_W) {
+      if (dst_fmt->swizzle[chan] <= PIPE_SWIZZLE_W) {
          unsigned ls;
          LLVMValueRef shifted, shift_val;
          ls = dst_fmt->channel[dst_fmt->swizzle[chan]].shift;