[Mesa-dev] [PATCH v3 10/24] main: Add a concept of an array format

Iago Toral itoral at igalia.com
Thu Dec 11 23:21:34 PST 2014


On Thu, 2014-12-11 at 11:24 -0800, Jason Ekstrand wrote:
> 
> 
> On Tue, Dec 9, 2014 at 4:06 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.
>         Whie 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>:
>          - Implement mesa_array_format as a plain bitfiled uint32_t
>         type instead of
>            using a struct inside a union to access the various
>         components packed in
>            it. This is necessary to support bigendian properly, as
>         pointed out by
>            Ian.
>          - Squashed: Make float types normalized
>         ---
>          src/mesa/main/format_info.py |  16 +++++
>          src/mesa/main/formats.c      |  57 ++++++++++++++++++
>          src/mesa/main/formats.h      | 136
>         ++++++++++++++++++++++++++++++++++++++++++-
>          3 files changed, 208 insertions(+), 1 deletion(-)
>         
>         diff --git a/src/mesa/main/format_info.py
>         b/src/mesa/main/format_info.py
>         index 7424fe0..fe2063d 100644
>         --- a/src/mesa/main/format_info.py
>         +++ b/src/mesa/main/format_info.py
>         @@ -192,6 +192,22 @@ for fmat in formats:
>         
>         int(fmat.block_size() / 8))
>         
>             print '      {{ {0} }},'.format(', '.join(map(str,
>         fmat.swizzle)))
>         +   if fmat.is_array():
>         +      chan = fmat.array_element()
>         +      norm = chan.norm or chan.type == parser.FLOAT
>         +      print '      MESA_ARRAY_FORMAT({0}),'.format(',
>         '.join([
>         +         str(chan.size / 8),
>         +         str(int(chan.sign)),
>         +         str(int(chan.type == parser.FLOAT)),
>         +         str(int(norm)),
>         +         str(len(fmat.channels)),
>         +         str(fmat.swizzle[0]),
>         +         str(fmat.swizzle[1]),
>         +         str(fmat.swizzle[2]),
>         +         str(fmat.swizzle[3]),
>         +      ]))
>         +   else:
>         +      print '      0,'
>             print '   },'
>         
>          print '};'
>         diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c
>         index 676ac27..1259892 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,62 @@ _mesa_get_format_swizzle(mesa_format
>         format, uint8_t swizzle_out[4])
>             memcpy(swizzle_out, info->Swizzle, sizeof(info->Swizzle));
>          }
>         
>         +mesa_array_format
>         +_mesa_array_format_flip_channels(mesa_array_format format)
>         +{
>         +   int num_channels;
>         +   uint8_t swizzle[4];
>         +
>         +   num_channels =
>         _mesa_array_format_get_num_channels(format);
>         +   _mesa_array_format_get_swizzle(format, swizzle);
>         +
>         +   if (num_channels == 1)
>         +      return format;
>         +
>         +   if (num_channels == 2) {
>         +      _mesa_array_format_set_swizzle(&format, swizzle[1],
>         swizzle[0],
>         +                                     swizzle[2], swizzle[3]);
>         +      return format;
>         +   }
>         +
>         +   if (num_channels == 4) {
>         +      _mesa_array_format_set_swizzle(&format, swizzle[3],
>         swizzle[2],
>         +                                     swizzle[1], swizzle[0]);
>         +      return format;
>         +   }
>         +
>         +   unreachable("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;
>         +   else
>         +      return
>         _mesa_array_format_flip_channels(info->ArrayFormat);
>         +}
>         +
>         +mesa_format
>         +_mesa_format_from_array_format(uint32_t array_format)
>         +{
>         +   mesa_array_format af;
>         +   unsigned f;
>         +
>         +   assert(_mesa_format_is_mesa_array_format(array_format));
>         +
>         +   if (_mesa_little_endian())
>         +      af = array_format;
>         +   else
>         +      af = _mesa_array_format_flip_channels(array_format);
>         +
>         +   for (f = 1; f < MESA_FORMAT_COUNT; ++f)
>         +      if (_mesa_get_format_info(f)->ArrayFormat == af)
>         +         return f;
>         +
>         +   return MESA_FORMAT_NONE;
>         +}
>         
>          /** Is the given format a compressed format? */
>          GLboolean
>         diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h
>         index 213ab56..746a92f 100644
>         --- a/src/mesa/main/formats.h
>         +++ b/src/mesa/main/formats.h
>         @@ -37,7 +37,6 @@
>          #include <stdbool.h>
>          #include <stdint.h>
>         
>         -
>          #ifdef __cplusplus
>          extern "C" {
>          #endif
>         @@ -82,6 +81,132 @@ enum {
>          };
>         
>          /**
>         + * An uint32_t that encodes the information necessary to
>         represent an
>         + * array format
>         + */
>         +typedef uint32_t mesa_array_format;
>         +
>         +/**
>         + * Encoding for valid array format data types
>         + */
>         +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,
>         +};
>         +
>         +/**
>         + * An enum useful to encode/decode information stored in a
>         mesa_array_format
>         + */
>         +enum {
>         +   MESA_ARRAY_FORMAT_TYPE_IS_SIGNED = 0x4,
>         +   MESA_ARRAY_FORMAT_TYPE_IS_FLOAT = 0x8,
>         +   MESA_ARRAY_FORMAT_TYPE_NORMALIZED = 0x10,
>         +   MESA_ARRAY_FORMAT_DATATYPE_MASK = 0xf,
>         +   MESA_ARRAY_FORMAT_TYPE_MASK = 0x1f,
>         +   MESA_ARRAY_FORMAT_TYPE_SIZE_MASK = 0x3,
>         +   MESA_ARRAY_FORMAT_NUM_CHANS_MASK = 0xe0,
>         +   MESA_ARRAY_FORMAT_SWIZZLE_X_MASK = 0x00700,
>         +   MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK = 0x03800,
>         +   MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK = 0x1c000,
>         +   MESA_ARRAY_FORMAT_SWIZZLE_W_MASK = 0xe0000,
>         +   MESA_ARRAY_FORMAT_BIT = 0x80000000
>         +};
>         +
>         +#define MESA_ARRAY_FORMAT(SIZE, SIGNED, IS_FLOAT, NORM,
>         NUM_CHANS, \
>         +      SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W) (
>         \
>         +   (((SIZE >> 1)      ) & MESA_ARRAY_FORMAT_TYPE_SIZE_MASK) |
>         \
>         +   (((SIGNED)    << 2 ) & MESA_ARRAY_FORMAT_TYPE_IS_SIGNED) |
>         \
>         +   (((IS_FLOAT)  << 3 ) & MESA_ARRAY_FORMAT_TYPE_IS_FLOAT)
>         |       \
>         +   (((NORM)      << 4 ) & MESA_ARRAY_FORMAT_TYPE_NORMALIZED)
>         |     \
>         +   (((NUM_CHANS) << 5 ) & MESA_ARRAY_FORMAT_NUM_CHANS_MASK) |
>         \
>         +   (((SWIZZLE_X) << 8 ) & MESA_ARRAY_FORMAT_SWIZZLE_X_MASK) |
>         \
>         +   (((SWIZZLE_Y) << 11) & MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK) |
>         \
>         +   (((SWIZZLE_Z) << 14) & MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK) |
>         \
>         +   (((SWIZZLE_W) << 17) & MESA_ARRAY_FORMAT_SWIZZLE_W_MASK) |
>         \
>         +   MESA_ARRAY_FORMAT_BIT)
>         +
>         +/**
>         + * Various helpers to access the data encoded in a
>         mesa_array_format
>         + */
>         +static inline bool
>         +_mesa_array_format_is_signed(mesa_array_format f)
>         +{
>         +   return (f & MESA_ARRAY_FORMAT_TYPE_IS_SIGNED) > 0;
>         +}
>         +
>         +static inline bool
>         +_mesa_array_format_is_float(mesa_array_format f)
>         +{
>         +   return (f & MESA_ARRAY_FORMAT_TYPE_IS_FLOAT) > 0;
>         +}
>         +
>         +static inline bool
>         +_mesa_array_format_is_normalized(mesa_array_format f)
>         +{
>         +   return (f & MESA_ARRAY_FORMAT_TYPE_NORMALIZED) > 0;
>         +}
>  
> 
> Any particular reason why you do "> 0" instead of "!= 0"?  I don't
> care that much.  Just curious

mesa_array_format is an uint32_t so this can't be < 0. Anyway, using !=
0 may be more clear so I'll change that.

Iago

>  
> 
>         +
>         +static inline enum mesa_array_format_datatype
>         +_mesa_array_format_get_datatype(mesa_array_format f)
>         +{
>         +   return (enum mesa_array_format_datatype)
>         +            (f & MESA_ARRAY_FORMAT_DATATYPE_MASK);
>         +}
>         +
>         +static inline int
>         +_mesa_array_format_datatype_get_size(enum
>         mesa_array_format_datatype type)
>         +{
>         +   return 1 << (type & MESA_ARRAY_FORMAT_TYPE_SIZE_MASK);
>         +}
>         +
>         +static inline int
>         +_mesa_array_format_get_type_size(mesa_array_format f)
>         +{
>         +   return 1 << (f & MESA_ARRAY_FORMAT_TYPE_SIZE_MASK);
>         +}
>         +
>         +static inline int
>         +_mesa_array_format_get_num_channels(mesa_array_format f)
>         +{
>         +   return (f & MESA_ARRAY_FORMAT_NUM_CHANS_MASK) >> 5;
>         +}
>         +
>         +static inline void
>         +_mesa_array_format_get_swizzle(mesa_array_format f, uint8_t
>         *swizzle)
>         +{
>         +   swizzle[0] = (f & MESA_ARRAY_FORMAT_SWIZZLE_X_MASK) >> 8;
>         +   swizzle[1] = (f & MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK) >> 11;
>         +   swizzle[2] = (f & MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK) >> 14;
>         +   swizzle[3] = (f & MESA_ARRAY_FORMAT_SWIZZLE_W_MASK) >> 17;
>         +}
>         +
>         +static inline void
>         +_mesa_array_format_set_swizzle(mesa_array_format *f,
>         +                               int32_t x, int32_t y, int32_t
>         z, int32_t w)
>         +{
>         +   *f |= ((x << 8 ) & MESA_ARRAY_FORMAT_SWIZZLE_X_MASK) |
>         +         ((y << 11) & MESA_ARRAY_FORMAT_SWIZZLE_Y_MASK) |
>         +         ((z << 14) & MESA_ARRAY_FORMAT_SWIZZLE_Z_MASK) |
>         +         ((w << 17) & MESA_ARRAY_FORMAT_SWIZZLE_W_MASK);
>         +}
>         +
>         +/**
>         + * A helper to know if the format stored in a uint32_t is a
>         mesa_format
>         + * or a mesa_array_format
>         + */
>         +static inline bool
>         +_mesa_format_is_mesa_array_format(uint32_t f)
>         +{
>         +   return (f & MESA_ARRAY_FORMAT_BIT) > 0;
>         +}
>         +
>         +/**
>           * Mesa texture/renderbuffer image formats.
>           */
>          typedef enum
>         @@ -466,9 +591,18 @@ _mesa_get_format_base_format(mesa_format
>         format);
>          extern void
>          _mesa_get_format_block_size(mesa_format format, GLuint *bw,
>         GLuint *bh);
>         
>         +extern mesa_array_format
>         +_mesa_array_format_flip_channels(mesa_array_format format);
>         +
>          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
> 
> 




More information about the mesa-dev mailing list