<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Mar 6, 2018 at 5:06 AM, Pohjolainen, Topi <span dir="ltr"><<a href="mailto:topi.pohjolainen@gmail.com" target="_blank">topi.pohjolainen@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Fri, Jan 26, 2018 at 05:59:51PM -0800, Jason Ekstrand wrote:<br>
> This adds helpers to ISL to convert an isl_color_value to and from<br>
> binary data encoded with a given isl_format.  The conversion is done<br>
> using ISL's built-in format introspection so it's fairly slow as format<br>
> conversions go but it should be fine for a single pixel value.  In<br>
> particular, we can use this to convert clear colors.<br>
><br>
> As a side-effect, we now rely on the sRGB helpers in libmesautil so we<br>
> need to tweak the build system a bit.  All prior uses of src/util in ISL<br>
> were header-only.<br>
> ---<br>
>  src/intel/<a href="http://Makefile.compiler.am" rel="noreferrer" target="_blank">Makefile.compiler.am</a> |   2 +-<br>
>  src/intel/<a href="http://Makefile.isl.am" rel="noreferrer" target="_blank">Makefile.isl.am</a>      |   1 +<br>
>  src/intel/isl/isl.h            |   7 ++<br>
>  src/intel/isl/isl_format.c     | 214 ++++++++++++++++++++++++++++++<wbr>+++++++++++<br>
>  src/intel/isl/meson.build      |   2 +-<br>
>  5 files changed, 224 insertions(+), 2 deletions(-)<br>
><br>
> diff --git a/src/intel/<a href="http://Makefile.compiler.am" rel="noreferrer" target="_blank">Makefile.compiler.<wbr>am</a> b/src/intel/<a href="http://Makefile.compiler.am" rel="noreferrer" target="_blank">Makefile.compiler.<wbr>am</a><br>
> index 45e7a6c..d5b9920 100644<br>
> --- a/src/intel/<a href="http://Makefile.compiler.am" rel="noreferrer" target="_blank">Makefile.compiler.<wbr>am</a><br>
> +++ b/src/intel/<a href="http://Makefile.compiler.am" rel="noreferrer" target="_blank">Makefile.compiler.<wbr>am</a><br>
> @@ -49,8 +49,8 @@ TEST_LIBS = \<br>
>       compiler/<a href="http://libintel_compiler.la" rel="noreferrer" target="_blank">libintel_compiler.la</a> \<br>
>       common/<a href="http://libintel_common.la" rel="noreferrer" target="_blank">libintel_common.la</a> \<br>
>       $(top_builddir)/src/compiler/<wbr>nir/<a href="http://libnir.la" rel="noreferrer" target="_blank">libnir.la</a> \<br>
> -     $(top_builddir)/src/util/<a href="http://libmesautil.la" rel="noreferrer" target="_blank">libme<wbr>sautil.la</a> \<br>
>       $(top_builddir)/src/intel/isl/<a href="http://libisl.la" rel="noreferrer" target="_blank"><wbr>libisl.la</a> \<br>
> +     $(top_builddir)/src/util/<a href="http://libmesautil.la" rel="noreferrer" target="_blank">libme<wbr>sautil.la</a> \<br>
>       $(PTHREAD_LIBS) \<br>
>       $(DLOPEN_LIBS)<br>
><br>
> diff --git a/src/intel/<a href="http://Makefile.isl.am" rel="noreferrer" target="_blank">Makefile.isl.am</a> b/src/intel/<a href="http://Makefile.isl.am" rel="noreferrer" target="_blank">Makefile.isl.am</a><br>
> index 31273af..8e2cf20 100644<br>
> --- a/src/intel/<a href="http://Makefile.isl.am" rel="noreferrer" target="_blank">Makefile.isl.am</a><br>
> +++ b/src/intel/<a href="http://Makefile.isl.am" rel="noreferrer" target="_blank">Makefile.isl.am</a><br>
> @@ -78,6 +78,7 @@ TESTS += $(check_PROGRAMS)<br>
>  isl_tests_isl_surf_get_image_<wbr>offset_test_LDADD = \<br>
>       common/<a href="http://libintel_common.la" rel="noreferrer" target="_blank">libintel_common.la</a> \<br>
>       isl/<a href="http://libisl.la" rel="noreferrer" target="_blank">libisl.la</a> \<br>
> +     $(top_builddir)/src/util/<a href="http://libmesautil.la" rel="noreferrer" target="_blank">libme<wbr>sautil.la</a> \<br>
>       -lm<br>
><br>
>  # ------------------------------<wbr>------------------------------<wbr>----------------<br>
> diff --git a/src/intel/isl/isl.h b/src/intel/isl/isl.h<br>
> index 04d0f0b..4806c0c 100644<br>
> --- a/src/intel/isl/isl.h<br>
> +++ b/src/intel/isl/isl.h<br>
> @@ -1535,6 +1535,13 @@ enum isl_format isl_format_rgb_to_rgba(enum isl_format rgb) ATTRIBUTE_CONST;<br>
>  enum isl_format isl_format_rgb_to_rgbx(enum isl_format rgb) ATTRIBUTE_CONST;<br>
>  enum isl_format isl_format_rgbx_to_rgba(enum isl_format rgb) ATTRIBUTE_CONST;<br>
><br>
> +void isl_color_value_pack(const union isl_color_value *value,<br>
> +                          enum isl_format format,<br>
> +                          uint32_t *data_out);<br>
> +void isl_color_value_unpack(union isl_color_value *value,<br>
> +                            enum isl_format format,<br>
> +                            const uint32_t *data_in);<br>
> +<br>
>  bool isl_is_storage_image_format(<wbr>enum isl_format fmt);<br>
><br>
>  enum isl_format<br>
> diff --git a/src/intel/isl/isl_format.c b/src/intel/isl/isl_format.c<br>
> index 46af175..793c84b 100644<br>
> --- a/src/intel/isl/isl_format.c<br>
> +++ b/src/intel/isl/isl_format.c<br>
> @@ -24,8 +24,17 @@<br>
>  #include <assert.h><br>
><br>
>  #include "isl.h"<br>
> +#include "isl_priv.h"<br>
>  #include "common/gen_device_info.h"<br>
><br>
> +#include "main/macros.h" /* Needed for MAX3 and MAX2 for format_rgb9e5 */<br>
> +#include "util/format_srgb.h"<br>
> +#include "util/format_rgb9e5.h"<br>
> +#include "util/format_r11g11b10f.h"<br>
> +<br>
> +/* Header-only format conversion include */<br>
> +#include "main/format_utils.h"<br>
> +<br>
>  struct surface_format_info {<br>
>     bool exists;<br>
>     uint8_t sampling;<br>
> @@ -806,3 +815,208 @@ isl_format_rgbx_to_rgba(enum isl_format rgbx)<br>
>        return rgbx;<br>
>     }<br>
>  }<br>
> +<br>
> +static inline void<br>
> +pack_channel(const union isl_color_value *value, unsigned i,<br>
> +             const struct isl_channel_layout *layout,<br>
> +             enum isl_colorspace colorspace,<br>
> +             uint32_t data_out[4])<br>
> +{<br>
> +   if (layout->type == ISL_VOID)<br>
> +      return;<br>
> +<br>
> +   if (colorspace == ISL_COLORSPACE_SRGB)<br>
> +      assert(layout->type == ISL_UNORM);<br>
> +<br>
> +   uint32_t packed;<br>
> +   switch (layout->type) {<br>
> +   case ISL_UNORM:<br>
> +      if (colorspace == ISL_COLORSPACE_SRGB) {<br>
> +         if (layout->bits == 8) {<br>
> +            packed = util_format_linear_float_to_<wbr>srgb_8unorm(value->f32[i]);<br>
> +         } else {<br>
> +            float srgb = util_format_linear_to_srgb_<wbr>float(value->f32[i]);<br>
> +            packed = _mesa_float_to_unorm(srgb, layout->bits);<br>
> +         }<br>
> +      } else {<br>
> +         packed = _mesa_float_to_unorm(value-><wbr>f32[i], layout->bits);<br>
> +      }<br>
> +      break;<br>
> +   case ISL_SNORM:<br>
> +      packed = _mesa_float_to_snorm(value-><wbr>f32[i], layout->bits);<br>
> +      break;<br>
> +   case ISL_SFLOAT:<br>
> +      assert(layout->bits == 16 || layout->bits == 32);<br>
> +      if (layout->bits == 16) {<br>
> +         packed = _mesa_float_to_half(value-><wbr>f32[i]);<br>
> +      } else {<br>
> +         packed = value->u32[i];<br>
> +      }<br>
> +      break;<br>
> +   case ISL_UINT:<br>
> +      packed = MIN(value->u32[i], MAX_UINT(layout->bits));<br>
> +      break;<br>
> +   case ISL_SINT:<br>
> +      packed = MIN(MAX(value->u32[i], MIN_INT(layout->bits)),<br>
> +                   MAX_INT(layout->bits));<br>
> +      break;<br>
> +<br>
> +   default:<br>
> +      unreachable("Invalid channel type");<br>
> +   }<br>
> +<br>
> +   unsigned dword = layout->start_bit / 32;<br>
> +   unsigned bit = layout->start_bit % 32;<br>
> +   assert(bit + layout->bits <= 32);<br>
> +   data_out[dword] |= (packed & MAX_UINT(layout->bits)) << bit;<br>
> +}<br>
> +<br>
> +/**<br>
> + * Take an isl_color_value and pack it into the actual bits as specified by<br>
> + * the isl_format.  This function is very slow for a format conversion<br>
> + * function but should be fine for a single pixel worth of data.<br>
> + */<br>
> +void<br>
> +isl_color_value_pack(const union isl_color_value *value,<br>
> +                     enum isl_format format,<br>
> +                     uint32_t *data_out)<br>
> +{<br>
> +   const struct isl_format_layout *fmtl = isl_format_get_layout(format);<br>
> +   assert(fmtl->colorspace == ISL_COLORSPACE_LINEAR ||<br>
> +          fmtl->colorspace == ISL_COLORSPACE_SRGB);<br>
> +   assert(!isl_format_is_<wbr>compressed(format));<br>
> +<br>
> +   memset(data_out, 0, isl_align(fmtl->bpb, 32) / 8);<br>
> +<br>
> +   if (format == ISL_FORMAT_R9G9B9E5_SHAREDEXP) {<br>
> +      data_out[0] = float3_to_rgb9e5(value->f32);<br>
> +      return;<br>
> +   } else if (format == ISL_FORMAT_R11G11B10_FLOAT) {<br>
> +      data_out[0] = float3_to_r11g11b10f(value-><wbr>f32);<br>
> +      return;<br>
> +   }<br>
> +<br>
> +   pack_channel(value, 0, &fmtl->channels.r, fmtl->colorspace, data_out);<br>
> +   pack_channel(value, 1, &fmtl->channels.g, fmtl->colorspace, data_out);<br>
> +   pack_channel(value, 2, &fmtl->channels.b, fmtl->colorspace, data_out);<br>
> +   pack_channel(value, 3, &fmtl->channels.a, ISL_COLORSPACE_LINEAR, data_out);<br>
> +   pack_channel(value, 0, &fmtl->channels.l, fmtl->colorspace, data_out);<br>
> +   pack_channel(value, 0, &fmtl->channels.i, ISL_COLORSPACE_LINEAR, data_out);<br>
> +   assert(fmtl->channels.p.bits == 0);<br>
> +}<br>
> +<br>
> +/** Extend an N-bit signed integer to 32 bits */<br>
> +static inline int32_t<br>
> +sign_extend(int32_t x, unsigned bits)<br>
> +{<br>
> +   if (bits < 32) {<br>
> +      unsigned shift = 32 - bits;<br>
> +      return (x << shift) >> shift;<br>
> +   } else {<br>
> +      return x;<br>
> +   }<br>
> +}<br>
> +<br>
> +static inline void<br>
> +unpack_channel(union isl_color_value *value,<br>
> +               unsigned start, unsigned count,<br>
> +               const struct isl_channel_layout *layout,<br>
> +               enum isl_colorspace colorspace,<br>
> +               const uint32_t *data_in)<br>
> +{<br>
> +   if (layout->type == ISL_VOID)<br>
> +      return;<br>
> +<br>
> +   unsigned dword = layout->start_bit / 32;<br>
> +   unsigned bit = layout->start_bit % 32;<br>
> +   assert(bit + layout->bits <= 32);<br>
> +   uint32_t packed = (data_in[dword] >> bit) & MAX_UINT(layout->bits);<br>
> +<br>
> +   union {<br>
> +      uint32_t u32;<br>
> +      float f32;<br>
> +   } unpacked;<br>
> +<br>
> +   if (colorspace == ISL_COLORSPACE_SRGB)<br>
> +      assert(layout->type == ISL_UNORM);<br>
> +<br>
> +   switch (layout->type) {<br>
> +   case ISL_UNORM:<br>
> +      unpacked.f32 = _mesa_unorm_to_float(packed, layout->bits);<br>
> +      if (colorspace == ISL_COLORSPACE_SRGB) {<br>
> +         if (layout->bits == 8) {<br>
> +            unpacked.f32 = util_format_srgb_8unorm_to_<wbr>linear_float(packed);<br>
> +         } else {<br>
> +            float srgb = _mesa_unorm_to_float(packed, layout->bits);<br>
> +            unpacked.f32 = util_format_srgb_to_linear_<wbr>float(srgb);<br>
> +         }<br>
> +      } else {<br>
> +         unpacked.f32 = _mesa_unorm_to_float(packed, layout->bits);<br>
> +      }<br>
> +      break;<br>
> +   case ISL_SNORM:<br>
> +      unpacked.f32 = _mesa_snorm_to_float(sign_<wbr>extend(packed, layout->bits),<br>
> +                                          layout->bits);<br>
> +      break;<br>
> +   case ISL_SFLOAT:<br>
> +      assert(layout->bits == 16 || layout->bits == 32);<br>
> +      if (layout->bits == 16) {<br>
> +         unpacked.f32 = _mesa_half_to_float(packed);<br>
> +      } else {<br>
> +         unpacked.u32 = packed;<br>
> +      }<br>
> +      break;<br>
> +   case ISL_UINT:<br>
> +      unpacked.u32 = packed;<br>
> +      break;<br>
> +   case ISL_SINT:<br>
> +      unpacked.u32 = sign_extend(packed, layout->bits);<br>
> +      break;<br>
> +<br>
> +   default:<br>
> +      unreachable("Invalid channel type");<br>
> +   }<br>
> +<br>
> +   for (unsigned i = 0; i < count; i++)<br>
> +      value->u32[start + i] = unpacked.u32;<br>
> +}<br>
> +<br>
> +/**<br>
> + * Take unpack an isl_color_value from the actual bits as specified by<br>
> + * the isl_format.  This function is very slow for a format conversion<br>
> + * function but should be fine for a single pixel worth of data.<br>
> + */<br>
> +void<br>
> +isl_color_value_unpack(union isl_color_value *value,<br>
> +                       enum isl_format format,<br>
> +                       const uint32_t data_in[4])<br>
> +{<br>
> +   const struct isl_format_layout *fmtl = isl_format_get_layout(format);<br>
> +   assert(fmtl->colorspace == ISL_COLORSPACE_LINEAR ||<br>
> +          fmtl->colorspace == ISL_COLORSPACE_SRGB);<br>
> +   assert(!isl_format_is_<wbr>compressed(format));<br>
> +<br>
> +   /* Default to opaque black. */<br>
> +   memset(value, 0, sizeof(*value));<br>
> +   if (isl_format_has_int_channel(<wbr>format)) {<br>
> +      value->u32[3] = 1u;<br>
> +   } else {<br>
> +      value->f32[3] = 1.0f;<br>
> +   }<br>
> +<br>
> +   if (format == ISL_FORMAT_R9G9B9E5_SHAREDEXP) {<br>
> +      rgb9e5_to_float3(data_in[0], value->f32);<br>
> +      return;<br>
> +   } else if (format == ISL_FORMAT_R11G11B10_FLOAT) {<br>
> +      r11g11b10f_to_float3(data_in[<wbr>0], value->f32);<br>
> +      return;<br>
> +   }<br>
> +<br>
> +   unpack_channel(value, 0, 1, &fmtl->channels.r, fmtl->colorspace, data_in);<br>
> +   unpack_channel(value, 1, 1, &fmtl->channels.g, fmtl->colorspace, data_in);<br>
> +   unpack_channel(value, 2, 1, &fmtl->channels.b, fmtl->colorspace, data_in);<br>
> +   unpack_channel(value, 3, 1, &fmtl->channels.a, ISL_COLORSPACE_LINEAR, data_in);<br>
> +   unpack_channel(value, 0, 3, &fmtl->channels.l, fmtl->colorspace, data_in);<br>
> +   unpack_channel(value, 0, 4, &fmtl->channels.i, ISL_COLORSPACE_LINEAR, data_in);<br>
<br>
</div></div>I guess I don't know enough about formats to understand why we leave alpha<br>
channel intact for luminance but trash it in case of intensity?<br></blockquote><div><br></div><div>Luminance effectively has a swizzle of RRR1 but intensity is RRRR.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Other than that this looks good to me. Patches 22 and 23 are:<br>
<br>
Reviewed-by: Topi Pohjolainen <<a href="mailto:topi.pohjolainen@intel.com">topi.pohjolainen@intel.com</a>><br>
<span class=""><br>
> +   assert(fmtl->channels.p.bits == 0);<br>
> +}<br>
> diff --git a/src/intel/isl/meson.build b/src/intel/isl/meson.build<br>
> index 0838c32..e9ec5ba 100644<br>
> --- a/src/intel/isl/meson.build<br>
> +++ b/src/intel/isl/meson.build<br>
> @@ -95,7 +95,7 @@ if with_tests<br>
>        'tests/isl_surf_get_image_<wbr>offset_test.c',<br>
>        dependencies : dep_m,<br>
>        include_directories : [inc_common, inc_intel],<br>
> -      link_with : [libisl, libintel_common],<br>
> +      link_with : [libisl, libintel_common, libmesa_util],<br>
>      )<br>
>    )<br>
>  endif<br>
> --<br>
> 2.5.0.400.gff86faf<br>
><br>
</span>> ______________________________<wbr>_________________<br>
> mesa-dev mailing list<br>
> <a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
> <a href="https://lists.freedesktop.org/mailman/listinfo/mesa-dev" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>mailman/listinfo/mesa-dev</a><br>
</blockquote></div><br></div></div>