[Mesa-dev] [PATCH v3 03/28] mesa: Add a rebase_swizzle parameter to _mesa_format_convert

Jason Ekstrand jason at jlekstrand.net
Fri Dec 12 10:52:18 PST 2014


Looks good!
Reviewed-by: Jason Ekstrand <jason.ekstrand at intel.com>

On Tue, Dec 9, 2014 at 4:07 AM, Iago Toral Quiroga <itoral at igalia.com>
wrote:
>
> The new parameter allows callers to provide a rebase swizzle that
> the function needs to use to match the requirements of the base
> internal format involved. This is necessary when the source or
> destination internal formats (depending on whether we are doing
> the conversion for a pixel download or a pixel upload respectively)
> do not match the base formats of the source or destination
> formats of the conversion. This can happen when the driver does not
> support the internal formats and uses a different format to store
> pixel data internally.
>
> For example, a texture upload from RGB to Luminance in a driver
> that does not support textures with a Luminance format may decide
> to store the Luminance data as RGBA. In this case we want to store
> the RGBA values as (R,R,R,1). Following the same example, when we
> download from that texture to RGBA we want to read (R,0,0,1). The
> rebase_swizzle parameter allows these transforms to happen.
> ---
>  src/mesa/main/format_utils.c | 239
> ++++++++++++++++++++++++++++++-------------
>  src/mesa/main/format_utils.h |   2 +-
>  2 files changed, 171 insertions(+), 70 deletions(-)
>
> diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c
> index ba0be13..040c79a 100644
> --- a/src/mesa/main/format_utils.c
> +++ b/src/mesa/main/format_utils.c
> @@ -279,6 +279,75 @@ gl_type_for_array_format_datatype(enum
> mesa_array_format_datatype type)
>     }
>  }
>
> +/* Takes a src to RGBA swizzle and applies a rebase swizzle to it. This
> + * is used when we need to rebase a format to match a different
> + * base internal format.
> + *
> + * The rebase swizzle can be NULL, which means that no rebase is
> necessary,
> + * in which case the src to RGBA swizzle is copied to the output without
> + * changes.
> + *
> + * The resulting rebased swizzle and well as the input swizzles are
> + * all 4-element swizzles, but the rebase swizzle can be NULL if no rebase
> + * is necessary.
> + */
> +static void
> +compute_rebased_rgba_component_mapping(uint8_t *src2rgba,
> +                                       uint8_t *rebase_swizzle,
> +                                       uint8_t *rebased_src2rgba)
> +{
> +   int i;
> +
> +   if (rebase_swizzle) {
> +      for (i = 0; i < 4; i++) {
> +         if (rebase_swizzle[i] > MESA_FORMAT_SWIZZLE_W)
> +            rebased_src2rgba[i] = rebase_swizzle[i];
> +         else
> +            rebased_src2rgba[i] = src2rgba[rebase_swizzle[i]];
> +      }
> +   } else {
> +      /* No rebase needed, so src2rgba is all that we need */
> +      memcpy(rebased_src2rgba, src2rgba, 4 * sizeof(uint8_t));
> +   }
> +}
> +
> +/* Computes the final swizzle transform to apply from src to dst in a
> + * conversion that might involve a rebase swizzle.
> + *
> + * This is used to compute the swizzle transform to apply in conversions
> + * between array formats where we have a src2rgba swizzle, a rgba2dst
> swizzle
> + * and possibly, a rebase swizzle.
> + *
> + * The final swizzle transform to apply (src2dst) when a rebase swizzle is
> + * involved is: src -> rgba -> base -> rgba -> dst
> + */
> +static void
> +compute_src2dst_component_mapping(uint8_t *src2rgba, uint8_t *rgba2dst,
> +                                  uint8_t *rebase_swizzle, uint8_t
> *src2dst)
> +{
> +   int i;
> +
> +   if (!rebase_swizzle) {
> +      for (i = 0; i < 4; i++) {
> +         if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) {
> +            src2dst[i] = rgba2dst[i];
> +         } else {
> +            src2dst[i] = src2rgba[rgba2dst[i]];
> +         }
> +      }
> +   } else {
> +      for (i = 0; i < 4; i++) {
> +         if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) {
> +            src2dst[i] = rgba2dst[i];
> +         } else if (rebase_swizzle[rgba2dst[i]] > MESA_FORMAT_SWIZZLE_W) {
> +            src2dst[i] = rebase_swizzle[rgba2dst[i]];
> +         } else {
> +            src2dst[i] = src2rgba[rebase_swizzle[rgba2dst[i]]];
> +         }
> +      }
> +   }
> +}
> +
>  /**
>   * This can be used to convert between most color formats.
>   *
> @@ -299,24 +368,31 @@ gl_type_for_array_format_datatype(enum
> mesa_array_format_datatype type)
>   * \param src_stride  The stride of the source format in bytes.
>   * \param width  The width, in pixels, of the source image to convert.
>   * \param height  The height, in pixels, of the source image to convert.
> + * \param rebase_swizzle  A swizzle transform to apply during the
> conversion,
> + *                        typically used to match a different internal
> base
> + *                        format involved. NULL if no rebase transform is
> needed
> + *                        (i.e. the internal base format and the base
> format of
> + *                        the dst or the src -depending on whether we are
> doing
> + *                        an upload or a download respectively- are the
> same).
>   */
>  void
>  _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t
> dst_stride,
>                       void *void_src, uint32_t src_format, size_t
> src_stride,
> -                     size_t width, size_t height)
> +                     size_t width, size_t height, uint8_t *rebase_swizzle)
>  {
>     uint8_t *dst = (uint8_t *)void_dst;
>     uint8_t *src = (uint8_t *)void_src;
>     mesa_array_format src_array_format, dst_array_format;
>     bool src_format_is_mesa_array_format, dst_format_is_mesa_array_format;
>     uint8_t src2dst[4], src2rgba[4], rgba2dst[4], dst2rgba[4];
> +   uint8_t rebased_src2rgba[4];
>     GLenum src_gl_type, dst_gl_type, common_gl_type;
>     bool normalized, dst_integer, src_integer, is_signed;
>     int src_num_channels = 0, dst_num_channels = 0;
>     uint8_t (*tmp_ubyte)[4];
>     float (*tmp_float)[4];
>     uint32_t (*tmp_uint)[4];
> -   int i, bits;
> +   int bits;
>     size_t row;
>
>     if (_mesa_format_is_mesa_array_format(src_format)) {
> @@ -337,67 +413,79 @@ _mesa_format_convert(void *void_dst, uint32_t
> dst_format, size_t dst_stride,
>        dst_array_format = _mesa_format_to_array_format(dst_format);
>     }
>
> -   /* Handle the cases where we can directly unpack */
> -   if (!src_format_is_mesa_array_format) {
> -      if (dst_array_format == RGBA8888_FLOAT) {
> -         for (row = 0; row < height; ++row) {
> -            _mesa_unpack_rgba_row(src_format, width,
> -                                  src, (float (*)[4])dst);
> -            src += src_stride;
> -            dst += dst_stride;
> -         }
> -         return;
> -      } else if (dst_array_format == RGBA8888_UBYTE) {
> -         assert(!_mesa_is_format_integer_color(src_format));
> -         for (row = 0; row < height; ++row) {
> -            _mesa_unpack_ubyte_rgba_row(src_format, width,
> -                                        src, (uint8_t (*)[4])dst);
> -            src += src_stride;
> -            dst += dst_stride;
> -         }
> -         return;
> -      } else if (dst_array_format == RGBA8888_UINT &&
> -                 _mesa_is_format_unsigned(src_format)) {
> -         assert(_mesa_is_format_integer_color(src_format));
> -         for (row = 0; row < height; ++row) {
> -            _mesa_unpack_uint_rgba_row(src_format, width,
> -                                       src, (uint32_t (*)[4])dst);
> -            src += src_stride;
> -            dst += dst_stride;
> +   /* First we see if we can implement the conversion with a direct pack
> +    * or unpack.
> +    *
> +    * In this case we want to be careful when we need to apply a swizzle
> to
> +    * match an internal base format, since in these cases a simple
> pack/unpack
> +    * to the dst format from the src format may not match the requirements
> +    * of the internal base format. For now we decide to be safe and
> +    * avoid this path in these scenarios but in the future we may want to
> +    * enable it for specific combinations that are known to work.
> +    */
> +   if (!rebase_swizzle) {
> +      /* Handle the cases where we can directly unpack */
> +      if (!src_format_is_mesa_array_format) {
> +         if (dst_array_format == RGBA8888_FLOAT) {
> +            for (row = 0; row < height; ++row) {
> +               _mesa_unpack_rgba_row(src_format, width,
> +                                     src, (float (*)[4])dst);
> +               src += src_stride;
> +               dst += dst_stride;
> +            }
> +            return;
> +         } else if (dst_array_format == RGBA8888_UBYTE) {
> +            assert(!_mesa_is_format_integer_color(src_format));
> +            for (row = 0; row < height; ++row) {
> +               _mesa_unpack_ubyte_rgba_row(src_format, width,
> +                                           src, (uint8_t (*)[4])dst);
> +               src += src_stride;
> +               dst += dst_stride;
> +            }
> +            return;
> +         } else if (dst_array_format == RGBA8888_UINT &&
> +                    _mesa_is_format_unsigned(src_format)) {
> +            assert(_mesa_is_format_integer_color(src_format));
> +            for (row = 0; row < height; ++row) {
> +               _mesa_unpack_uint_rgba_row(src_format, width,
> +                                          src, (uint32_t (*)[4])dst);
> +               src += src_stride;
> +               dst += dst_stride;
> +            }
> +            return;
>           }
> -         return;
>        }
> -   }
>
> -   /* Handle the cases where we can directly pack */
> -   if (!dst_format_is_mesa_array_format) {
> -      if (src_array_format == RGBA8888_FLOAT) {
> -         for (row = 0; row < height; ++row) {
> -            _mesa_pack_float_rgba_row(dst_format, width,
> -                                      (const float (*)[4])src, dst);
> -            src += src_stride;
> -            dst += dst_stride;
> -         }
> -         return;
> -      } else if (src_array_format == RGBA8888_UBYTE) {
> -         assert(!_mesa_is_format_integer_color(dst_format));
> -         for (row = 0; row < height; ++row) {
> -            _mesa_pack_ubyte_rgba_row(dst_format, width,
> -                                      (const uint8_t (*)[4])src, dst);
> -            src += src_stride;
> -            dst += dst_stride;
> -         }
> -         return;
> -      } else if (src_array_format == RGBA8888_UINT &&
> -                 _mesa_is_format_unsigned(dst_format)) {
> -         assert(_mesa_is_format_integer_color(dst_format));
> -         for (row = 0; row < height; ++row) {
> -            _mesa_pack_uint_rgba_row(dst_format, width,
> -                                     (const uint32_t (*)[4])src, dst);
> -            src += src_stride;
> -            dst += dst_stride;
> +      /* Handle the cases where we can directly pack */
> +      if (!dst_format_is_mesa_array_format) {
> +         if (src_array_format == RGBA8888_FLOAT) {
> +            for (row = 0; row < height; ++row) {
> +               _mesa_pack_float_rgba_row(dst_format, width,
> +                                         (const float (*)[4])src, dst);
> +               src += src_stride;
> +               dst += dst_stride;
> +            }
> +            return;
> +         } else if (src_array_format == RGBA8888_UBYTE) {
> +            assert(!_mesa_is_format_integer_color(dst_format));
> +            for (row = 0; row < height; ++row) {
> +               _mesa_pack_ubyte_rgba_row(dst_format, width,
> +                                         (const uint8_t (*)[4])src, dst);
> +               src += src_stride;
> +               dst += dst_stride;
> +            }
> +            return;
> +         } else if (src_array_format == RGBA8888_UINT &&
> +                    _mesa_is_format_unsigned(dst_format)) {
> +            assert(_mesa_is_format_integer_color(dst_format));
> +            for (row = 0; row < height; ++row) {
> +               _mesa_pack_uint_rgba_row(dst_format, width,
> +                                        (const uint32_t (*)[4])src, dst);
> +               src += src_stride;
> +               dst += dst_stride;
> +            }
> +            return;
>           }
> -         return;
>        }
>     }
>
> @@ -432,13 +520,8 @@ _mesa_format_convert(void *void_dst, uint32_t
> dst_format, size_t dst_stride,
>        assert(_mesa_array_format_is_normalized(src_array_format) ==
>               _mesa_array_format_is_normalized(dst_array_format));
>
> -      for (i = 0; i < 4; i++) {
> -         if (rgba2dst[i] > MESA_FORMAT_SWIZZLE_W) {
> -            src2dst[i] = rgba2dst[i];
> -         } else {
> -            src2dst[i] = src2rgba[rgba2dst[i]];
> -         }
> -      }
> +      compute_src2dst_component_mapping(src2rgba, rgba2dst,
> rebase_swizzle,
> +                                        src2dst);
>
>        for (row = 0; row < height; ++row) {
>           _mesa_swizzle_and_convert(dst, dst_gl_type, dst_num_channels,
> @@ -526,16 +609,22 @@ _mesa_format_convert(void *void_dst, uint32_t
> dst_format, size_t dst_stride,
>         */
>        common_gl_type = is_signed ? GL_INT : GL_UNSIGNED_INT;
>        if (src_array_format) {
> +         compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle,
> +                                                rebased_src2rgba);
>           for (row = 0; row < height; ++row) {
>              _mesa_swizzle_and_convert(tmp_uint + row * width,
> common_gl_type, 4,
>                                        src, src_gl_type, src_num_channels,
> -                                      src2rgba, normalized, width);
> +                                      rebased_src2rgba, normalized,
> width);
>              src += src_stride;
>           }
>        } else {
>           for (row = 0; row < height; ++row) {
>              _mesa_unpack_uint_rgba_row(src_format, width,
>                                         src, tmp_uint + row * width);
> +            if (rebase_swizzle)
> +               _mesa_swizzle_and_convert(tmp_uint + row * width,
> common_gl_type, 4,
> +                                         tmp_uint + row * width,
> common_gl_type, 4,
> +                                         rebase_swizzle, false, width);
>              src += src_stride;
>           }
>        }
> @@ -564,16 +653,22 @@ _mesa_format_convert(void *void_dst, uint32_t
> dst_format, size_t dst_stride,
>        tmp_float = malloc(width * height * sizeof(*tmp_float));
>
>        if (src_format_is_mesa_array_format) {
> +         compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle,
> +                                                rebased_src2rgba);
>           for (row = 0; row < height; ++row) {
>              _mesa_swizzle_and_convert(tmp_float + row * width, GL_FLOAT,
> 4,
>                                        src, src_gl_type, src_num_channels,
> -                                      src2rgba, normalized, width);
> +                                      rebased_src2rgba, normalized,
> width);
>              src += src_stride;
>           }
>        } else {
>           for (row = 0; row < height; ++row) {
>              _mesa_unpack_rgba_row(src_format, width,
>                                    src, tmp_float + row * width);
> +            if (rebase_swizzle)
> +               _mesa_swizzle_and_convert(tmp_float + row * width,
> GL_FLOAT, 4,
> +                                         tmp_float + row * width,
> GL_FLOAT, 4,
> +                                         rebase_swizzle, false, width);
>              src += src_stride;
>           }
>        }
> @@ -598,16 +693,22 @@ _mesa_format_convert(void *void_dst, uint32_t
> dst_format, size_t dst_stride,
>        tmp_ubyte = malloc(width * height * sizeof(*tmp_ubyte));
>
>        if (src_format_is_mesa_array_format) {
> +         compute_rebased_rgba_component_mapping(src2rgba, rebase_swizzle,
> +                                                rebased_src2rgba);
>           for (row = 0; row < height; ++row) {
>              _mesa_swizzle_and_convert(tmp_ubyte + row * width,
> GL_UNSIGNED_BYTE, 4,
>                                        src, src_gl_type, src_num_channels,
> -                                      src2rgba, normalized, width);
> +                                      rebased_src2rgba, normalized,
> width);
>              src += src_stride;
>           }
>        } else {
>           for (row = 0; row < height; ++row) {
>              _mesa_unpack_ubyte_rgba_row(src_format, width,
>                                          src, tmp_ubyte + row * width);
> +            if (rebase_swizzle)
> +               _mesa_swizzle_and_convert(tmp_ubyte + row * width,
> GL_UNSIGNED_BYTE, 4,
> +                                         tmp_ubyte + row * width,
> GL_UNSIGNED_BYTE, 4,
> +                                         rebase_swizzle, false, width);
>              src += src_stride;
>           }
>        }
> diff --git a/src/mesa/main/format_utils.h b/src/mesa/main/format_utils.h
> index 28b4715..1633f1e 100644
> --- a/src/mesa/main/format_utils.h
> +++ b/src/mesa/main/format_utils.h
> @@ -184,6 +184,6 @@ _mesa_compute_component_mapping(GLenum inFormat,
> GLenum outFormat, GLubyte *map)
>  void
>  _mesa_format_convert(void *void_dst, uint32_t dst_format, size_t
> dst_stride,
>                       void *void_src, uint32_t src_format, size_t
> src_stride,
> -                     size_t width, size_t height);
> +                     size_t width, size_t height, uint8_t
> *rebase_swizzle);
>
>  #endif
> --
> 1.9.1
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/mesa-dev/attachments/20141212/36d84505/attachment-0001.html>


More information about the mesa-dev mailing list