[Mesa-dev] [PATCH v2 10/23] mesa: Add a concept of an array format

Ian Romanick idr at freedesktop.org
Wed Dec 3 14:52:00 PST 2014


On 12/01/2014 03:04 AM, Iago Toral Quiroga 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.
> ---
>  src/mesa/main/format_info.py | 41 +++++++++++++++++++++++++++++
>  src/mesa/main/formats.c      | 56 ++++++++++++++++++++++++++++++++++++++-
>  src/mesa/main/formats.h      | 62 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 158 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");

Use unreachable() to prevent warnings in non-debug builds.

> +}
> +
> +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;
>  }
>  
> -

Spurious whitespace change.

>  /**
>   * 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..8b62788 100644
> --- a/src/mesa/main/formats.h
> +++ b/src/mesa/main/formats.h
> @@ -81,6 +81,62 @@ 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,
> +};
> +
> +#define MESA_ARRAY_FORMAT_TYPE_IS_SIGNED 0x4
> +#define MESA_ARRAY_FORMAT_TYPE_IS_FLOAT 0x8
> +#define MESA_ARRAY_FORMAT_BIT 0x80000000

This...

> +
> +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 */

...and this are not correct on big-endian.

> +   };
> +   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;

I'd either make this unsigned or uint_fast8_t... I'd bet that it doesn't
make any difference.

> +   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)
> +
> +static inline int
> +_mesa_array_format_datatype_size(enum mesa_array_format_datatype type)
> +{
> +   return 1 << (type & 0x3);
> +}
> +
>  /**
>   * Mesa texture/renderbuffer image formats.
>   */
> @@ -469,6 +525,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);
>  
> 



More information about the mesa-dev mailing list