[Mesa-dev] [PATCH 09/20] mesa: Add a concept of an array format

Jason Ekstrand jason at jlekstrand.net
Tue Nov 18 10:46:42 PST 2014


On Tue, Nov 18, 2014 at 12:43 AM, Iago Toral Quiroga <itoral at igalia.com>
wrote:

> From: Jason Ekstrand <jason.ekstrand at intel.com>
>
> An array format is a 32-bit integer format identifier that can represent
> any format that can be represented as an array of standard GL datatypes.
> While the MESA_FORMAT enums provide several of these, they don't account
> for all of them.
>
> v2 by Iago Toral Quiroga <itoral at igalia.com>:
> - Set pad to 0 and array_format_bit to 1 for all mesa array formats.
> - Fix array_format_flip_channels, since it was not doing what was expected.
>

I'm not terribly surprised, I never got a chance to test that function
before I handed it off to you.  I'm curious how you found it though, given
that it's only run on big endian architectures.  Maybe it was just
obviously wrong.  (silly me).  In any case, the new version looks good to
me.
--Jason


> ---
>  src/mesa/main/format_info.py | 41 ++++++++++++++++++++++++++++++++
>  src/mesa/main/formats.c      | 56
> +++++++++++++++++++++++++++++++++++++++++++-
>  src/mesa/main/formats.h      | 55
> +++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 151 insertions(+), 1 deletion(-)
>
> diff --git a/src/mesa/main/format_info.py b/src/mesa/main/format_info.py
> index 7424fe0..315767d 100644
> --- a/src/mesa/main/format_info.py
> +++ b/src/mesa/main/format_info.py
> @@ -98,6 +98,32 @@ def get_gl_data_type(fmat):
>     else:
>        assert False
>
> +def get_array_format_datatype(chan):
> +   if chan.type == parser.FLOAT:
> +      if chan.size == 16:
> +         return 'MESA_ARRAY_FORMAT_TYPE_HALF'
> +      elif chan.size == 32:
> +         return 'MESA_ARRAY_FORMAT_TYPE_FLOAT'
> +      else:
> +         assert False
> +   elif chan.type in (parser.SIGNED, parser.UNSIGNED):
> +      datatype = 'MESA_ARRAY_FORMAT_TYPE_'
> +      if chan.type == parser.UNSIGNED:
> +         datatype += 'U'
> +
> +      if chan.size == 8:
> +         datatype += 'BYTE'
> +      elif chan.size == 16:
> +         datatype += 'SHORT'
> +      elif chan.size == 32:
> +         datatype += 'INT'
> +      else:
> +         print chan.size
> +         assert False
> +      return datatype
> +   else:
> +      assert False
> +
>  def get_mesa_layout(fmat):
>     if fmat.layout == 'array':
>        return 'MESA_FORMAT_LAYOUT_ARRAY'
> @@ -192,6 +218,21 @@ for fmat in formats:
>                                         int(fmat.block_size() / 8))
>
>     print '      {{ {0} }},'.format(', '.join(map(str, fmat.swizzle)))
> +   if fmat.is_array() and fmat.colorspace in ('rgb', 'srgb'):
> +      chan = fmat.array_element()
> +      print '      {{{{ {0} }}}},'.format(', '.join([
> +         get_array_format_datatype(chan),
> +         str(int(chan.norm)),
> +         str(len(fmat.channels)),
> +         str(fmat.swizzle[0]),
> +         str(fmat.swizzle[1]),
> +         str(fmat.swizzle[2]),
> +         str(fmat.swizzle[3]),
> +         str(int(0)),
> +         str(int(1))
> +      ]))
> +   else:
> +      print '      {{ MESA_ARRAY_FORMAT_TYPE_UBYTE, 0, 0, 0, 0, 0, 0, 0,
> 0 }},'
>     print '   },'
>
>  print '};'
> diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
> index 7ec0507..f86925e 100644
> --- a/src/mesa/main/formats.c
> +++ b/src/mesa/main/formats.c
> @@ -71,6 +71,7 @@ struct gl_format_info
>     GLubyte BytesPerBlock;
>
>     uint8_t Swizzle[4];
> +   mesa_array_format ArrayFormat;
>  };
>
>  #include "format_info.c"
> @@ -269,6 +270,60 @@ _mesa_get_format_swizzle(mesa_format format, uint8_t
> swizzle_out[4])
>     memcpy(swizzle_out, info->Swizzle, sizeof(info->Swizzle));
>  }
>
> +static mesa_array_format
> +array_format_flip_channels(mesa_array_format format)
> +{
> +   if (format.num_channels == 1)
> +      return format;
> +
> +   if (format.num_channels == 2) {
> +      int tmp = format.swizzle_x;
> +      format.swizzle_x = format.swizzle_y;
> +      format.swizzle_y = tmp;
> +      return format;
> +   }
> +
> +   if (format.num_channels == 4) {
> +      int tmp = format.swizzle_x;
> +      format.swizzle_x = format.swizzle_w;
> +      format.swizzle_w = tmp;
> +      tmp = format.swizzle_y;
> +      format.swizzle_y = format.swizzle_z;
> +      format.swizzle_z = tmp;
> +      return format;
> +   }
> +
> +   assert(!"Invalid array format");
> +}
> +
> +uint32_t
> +_mesa_format_to_array_format(mesa_format format)
> +{
> +   const struct gl_format_info *info = _mesa_get_format_info(format);
> +   if (_mesa_little_endian())
> +      return info->ArrayFormat.as_uint;
> +   else
> +      return array_format_flip_channels(info->ArrayFormat).as_uint;
> +}
> +
> +mesa_format
> +_mesa_format_from_array_format(uint32_t array_format)
> +{
> +   mesa_array_format af;
> +   unsigned f;
> +
> +   af.as_uint = array_format;
> +   af.pad = 0;
> +   if (!_mesa_little_endian())
> +      af = array_format_flip_channels(af);
> +
> +   assert(af.array_format_bit);
> +   for (f = 1; f < MESA_FORMAT_COUNT; ++f)
> +      if (_mesa_get_format_info(f)->ArrayFormat.as_uint == af.as_uint)
> +         return f;
> +
> +   return MESA_FORMAT_NONE;
> +}
>
>  /** Is the given format a compressed format? */
>  GLboolean
> @@ -278,7 +333,6 @@ _mesa_is_format_compressed(mesa_format format)
>     return info->BlockWidth > 1 || info->BlockHeight > 1;
>  }
>
> -
>  /**
>   * Determine if the given format represents a packed depth/stencil buffer.
>   */
> diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
> index 213ab56..7642875 100644
> --- a/src/mesa/main/formats.h
> +++ b/src/mesa/main/formats.h
> @@ -81,6 +81,55 @@ enum {
>     MESA_FORMAT_SWIZZLE_NONE = 6,
>  };
>
> +enum  mesa_array_format_datatype {
> +   MESA_ARRAY_FORMAT_TYPE_UBYTE = 0x0,
> +   MESA_ARRAY_FORMAT_TYPE_USHORT = 0x1,
> +   MESA_ARRAY_FORMAT_TYPE_UINT = 0x2,
> +   MESA_ARRAY_FORMAT_TYPE_BYTE = 0x4,
> +   MESA_ARRAY_FORMAT_TYPE_SHORT = 0x5,
> +   MESA_ARRAY_FORMAT_TYPE_INT = 0x6,
> +   MESA_ARRAY_FORMAT_TYPE_HALF = 0xd,
> +   MESA_ARRAY_FORMAT_TYPE_FLOAT = 0xe,
> +
> +   MESA_ARRAY_FORMAT_TYPE_IS_SIGNED = 0x4,
> +   MESA_ARRAY_FORMAT_TYPE_IS_FLOAT = 0x8,
> +};
> +
> +typedef union {
> +   struct {
> +      enum mesa_array_format_datatype type:4;
> +      bool normalized:1;
> +      unsigned num_channels:3;
> +      unsigned swizzle_x:3;
> +      unsigned swizzle_y:3;
> +      unsigned swizzle_z:3;
> +      unsigned swizzle_w:3;
> +      unsigned pad:11;
> +      unsigned array_format_bit:1; /* Must always be 1 */
> +   };
> +   uint32_t as_uint;
> +} mesa_array_format;
> +
> +static const mesa_array_format _mesa_array_format_none = {{
> +   MESA_ARRAY_FORMAT_TYPE_UBYTE,
> +   0, 0, 0, 0, 0, 0, 0, 0
> +}};
> +
> +static inline unsigned
> +_mesa_ilog2(unsigned x)
> +{
> +   uint8_t i;
> +   for (i = 1; i < 32; ++i)
> +      if (x <= (1u << i))
> +         return i;
> +   return 32;
> +}
> +
> +#define MESA_ARRAY_FORMAT_TYPE(SIZE, SIGNED, IS_FLOAT, NORM) (     \
> +   ((_mesa_ilog2(SIZE)) & MESA_ARRAY_FORMAT_TYPE_SIZE_MASK) |      \
> +   (((SIGNED)    << 2 ) & MESA_ARRAY_FORMAT_TYPE_IS_SIGNED) |      \
> +   (((IS_FLOAT)  << 3 ) & MESA_ARRAY_FORMAT_TYPE_IS_FLOAT)
> +
>  /**
>   * Mesa texture/renderbuffer image formats.
>   */
> @@ -469,6 +518,12 @@ _mesa_get_format_block_size(mesa_format format,
> GLuint *bw, GLuint *bh);
>  extern void
>  _mesa_get_format_swizzle(mesa_format format, uint8_t swizzle_out[4]);
>
> +extern uint32_t
> +_mesa_format_to_array_format(mesa_format format);
> +
> +extern mesa_format
> +_mesa_format_from_array_format(uint32_t array_format);
> +
>  extern GLboolean
>  _mesa_is_format_compressed(mesa_format format);
>
> --
> 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/20141118/42fccc6a/attachment.html>


More information about the mesa-dev mailing list