<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>