gallivm: (trivial) fix typo in argument declaration of lp_build_size_query_soa
[mesa.git] / src / gallium / auxiliary / gallivm / lp_bld_format_srgb.c
index f949a8daff1611a6c4ad255e94a9e53be6bfcaed..2b1fe643849324b8d631904bb1321bb1ec1a4616 100644 (file)
@@ -147,7 +147,7 @@ lp_build_srgb_to_linear(struct gallivm_state *gallivm,
  *
  * @param src   float (vector) value(s) to convert.
  */
-LLVMValueRef
+static LLVMValueRef
 lp_build_linear_to_srgb(struct gallivm_state *gallivm,
                         struct lp_type src_type,
                         LLVMValueRef src)
@@ -242,8 +242,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).
@@ -293,3 +295,52 @@ lp_build_linear_to_srgb(struct gallivm_state *gallivm,
    f32_bld.type.sign = 0;
    return lp_build_iround(&f32_bld, tmp);
 }
+
+
+/**
+ * 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).
+ *
+ * @param src   float SoA (vector) values to convert.
+ */
+LLVMValueRef
+lp_build_float_to_srgb_packed(struct gallivm_state *gallivm,
+                              const struct util_format_description *dst_fmt,
+                              struct lp_type src_type,
+                              LLVMValueRef *src)
+{
+   LLVMBuilderRef builder = gallivm->builder;
+   unsigned chan;
+   struct lp_build_context f32_bld;
+   struct lp_type int32_type = lp_int_type(src_type);
+   LLVMValueRef tmpsrgb[4], alpha, dst;
+
+   lp_build_context_init(&f32_bld, gallivm, src_type);
+
+   /* 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]);
+   }
+   /*
+    * 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_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) {
+         unsigned ls;
+         LLVMValueRef shifted, shift_val;
+         ls = dst_fmt->channel[dst_fmt->swizzle[chan]].shift;
+         shift_val = lp_build_const_int_vec(gallivm, int32_type, ls);
+         shifted = LLVMBuildShl(builder, tmpsrgb[chan], shift_val, "");
+         dst = LLVMBuildOr(builder, dst, shifted, "");
+      }
+   }
+   return dst;
+}