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

Iago Toral Quiroga itoral at igalia.com
Mon Dec 1 03:04:19 PST 2014


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");
+}
+
+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..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
+
+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)
+
+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);
 
-- 
1.9.1



More information about the mesa-dev mailing list