mesa/format_utils: Add a function to convert a mesa_format to an array format
authorJason Ekstrand <jason.ekstrand@intel.com>
Fri, 11 Jul 2014 15:52:12 +0000 (08:52 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 5 Aug 2014 17:56:16 +0000 (10:56 -0700)
This commits adds the _mesa_format_to_array function that determines if the
given format can be represented as an array format and computes the array
format parameters. This is a direct helper function for using
_mesa_swizzle_and_convert

v2: Better documentation and commit message
v3: Fixed a potential segfault from an invalid endianness swizzle

Signed-off-by: Jason Ekstrand <jason.ekstrand@intel.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
src/mesa/main/format_utils.c
src/mesa/main/format_utils.h

index 86259696cc85bfd9174773c0e98e6264bfb9f281..240e3bc0c19b9972187244313d1c4383ea564bb2 100644 (file)
 #include "format_utils.h"
 #include "glformats.h"
 
+static const uint8_t map_identity[7] = { 0, 1, 2, 3, 4, 5, 6 };
+static const uint8_t map_3210[7] = { 3, 2, 1, 0, 4, 5, 6 };
+static const uint8_t map_1032[7] = { 1, 0, 3, 2, 4, 5, 6 };
+
+/**
+ * Describes a format as an array format, if possible
+ *
+ * A helper function for figuring out if a (possibly packed) format is
+ * actually an array format and, if so, what the array parameters are.
+ *
+ * \param[in]  format         the mesa format
+ * \param[out] type           the GL type of the array (GL_BYTE, etc.)
+ * \param[out] num_components the number of components in the array
+ * \param[out] swizzle        a swizzle describing how to get from the
+ *                            given format to RGBA
+ * \param[out] normalized     for integer formats, this represents whether
+ *                            the format is a normalized integer or a
+ *                            regular integer
+ * \return  true if this format is an array format, false otherwise
+ */
+bool
+_mesa_format_to_array(mesa_format format, GLenum *type, int *num_components,
+                      uint8_t swizzle[4], bool *normalized)
+{
+   int i;
+   GLuint format_components;
+   uint8_t packed_swizzle[4];
+   const uint8_t *endian;
+
+   if (_mesa_is_format_compressed(format))
+      return false;
+
+   *normalized = !_mesa_is_format_integer(format);
+
+   _mesa_format_to_type_and_comps(format, type, &format_components);
+
+   switch (_mesa_get_format_layout(format)) {
+   case MESA_FORMAT_LAYOUT_ARRAY:
+      *num_components = format_components;
+      _mesa_get_format_swizzle(format, swizzle);
+      return true;
+   case MESA_FORMAT_LAYOUT_PACKED:
+      switch (*type) {
+      case GL_UNSIGNED_BYTE:
+      case GL_BYTE:
+         if (_mesa_get_format_max_bits(format) != 8)
+            return false;
+         *num_components = _mesa_get_format_bytes(format);
+         switch (*num_components) {
+         case 1:
+            endian = map_identity;
+            break;
+         case 2:
+            endian = _mesa_little_endian() ? map_identity : map_1032;
+            break;
+         case 4:
+            endian = _mesa_little_endian() ? map_identity : map_3210;
+            break;
+         default:
+            endian = map_identity;
+            assert(!"Invalid number of components");
+         }
+         break;
+      case GL_UNSIGNED_SHORT:
+      case GL_SHORT:
+      case GL_HALF_FLOAT:
+         if (_mesa_get_format_max_bits(format) != 16)
+            return false;
+         *num_components = _mesa_get_format_bytes(format) / 2;
+         switch (*num_components) {
+         case 1:
+            endian = map_identity;
+            break;
+         case 2:
+            endian = _mesa_little_endian() ? map_identity : map_1032;
+            break;
+         default:
+            endian = map_identity;
+            assert(!"Invalid number of components");
+         }
+         break;
+      case GL_UNSIGNED_INT:
+      case GL_INT:
+      case GL_FLOAT:
+         /* This isn't packed.  At least not really. */
+         assert(format_components == 1);
+         if (_mesa_get_format_max_bits(format) != 32)
+            return false;
+         *num_components = format_components;
+         endian = map_identity;
+         break;
+      default:
+         return false;
+      }
+
+      _mesa_get_format_swizzle(format, packed_swizzle);
+
+      for (i = 0; i < 4; ++i)
+         swizzle[i] = endian[packed_swizzle[i]];
+
+      return true;
+   case MESA_FORMAT_LAYOUT_OTHER:
+   default:
+      return false;
+   }
+}
+
 /* A bunch of format conversion macros and helper functions used below */
 
 /* Only guaranteed to work for BITS <= 32 */
index 11546aaf04b3152edbd777102d73d4e4b2e3f16b..9f778e37734a817afc36156ecbe02ee34cf37cb8 100644 (file)
 
 #include "imports.h"
 
+bool
+_mesa_format_to_array(mesa_format, GLenum *type, int *num_components,
+                      uint8_t swizzle[4], bool *normalized);
+
 void
 _mesa_swizzle_and_convert(void *dst, GLenum dst_type, int num_dst_channels,
                           const void *src, GLenum src_type, int num_src_channels,