[Mesa-dev] [PATCH 06/12] main/format_utils: Add a general format conversion function
Jason Ekstrand
jason at jlekstrand.net
Thu Jul 17 11:04:28 PDT 2014
Most format conversion operations required by GL can be performed by
converting one channel at a time, shuffling the channels around, and
optionally filling missing channels with zeros and ones. This adds a
function to do just that in a general, yet efficient, way.
Signed-off-by: Jason Ekstrand <jason.ekstrand at intel.com>
---
src/mesa/main/format_utils.c | 566 +++++++++++++++++++++++++++++++++++++++++++
src/mesa/main/format_utils.h | 18 ++
2 files changed, 584 insertions(+)
diff --git a/src/mesa/main/format_utils.c b/src/mesa/main/format_utils.c
index 241c158..0cb3eae 100644
--- a/src/mesa/main/format_utils.c
+++ b/src/mesa/main/format_utils.c
@@ -54,3 +54,569 @@ _mesa_srgb_ubyte_to_linear_float(uint8_t cl)
return lut[cl];
}
+
+static bool
+swizzle_convert_try_memcpy(void *dst, GLenum dst_type, int num_dst_channels,
+ const void *src, GLenum src_type, int num_src_channels,
+ const uint8_t swizzle[4], bool normalized, int count)
+{
+ int i;
+
+ if (src_type != dst_type)
+ return false;
+ if (num_src_channels != num_dst_channels)
+ return false;
+
+ for (i = 0; i < num_dst_channels; ++i)
+ if (swizzle[i] != i && swizzle[i] != MESA_FORMAT_SWIZZLE_NONE)
+ return false;
+
+ memcpy(dst, src, count * num_src_channels * _mesa_sizeof_type(src_type));
+
+ return true;
+}
+
+/* Note: This loop is carefully crafted for performance. Be careful when
+ * changing it and run some benchmarks to ensure no performance regressions
+ * if you do.
+ */
+#define SWIZZLE_CONVERT_LOOP(DST_TYPE, SRC_TYPE, CONV) \
+ do { \
+ const SRC_TYPE *typed_src = void_src; \
+ DST_TYPE *typed_dst = void_dst; \
+ DST_TYPE tmp[7]; \
+ tmp[4] = 0; \
+ tmp[5] = one; \
+ for (s = 0; s < count; ++s) { \
+ for (j = 0; j < num_src_channels; ++j) { \
+ SRC_TYPE src = typed_src[j]; \
+ tmp[j] = CONV; \
+ } \
+ \
+ typed_dst[0] = tmp[swizzle_x]; \
+ if (num_dst_channels > 1) { \
+ typed_dst[1] = tmp[swizzle_y]; \
+ if (num_dst_channels > 2) { \
+ typed_dst[2] = tmp[swizzle_z]; \
+ if (num_dst_channels > 3) { \
+ typed_dst[3] = tmp[swizzle_w]; \
+ } \
+ } \
+ } \
+ typed_src += num_src_channels; \
+ typed_dst += num_dst_channels; \
+ } \
+ } while (0);
+
+/**
+ * Convert between array-based color formats.
+ *
+ * Most format conversion operations required by GL can be performed by
+ * converting one channel at a time, shuffling the channels around, and
+ * optionally filling missing channels with zeros and ones. This function
+ * does just that in a general, yet efficient, way.
+ *
+ * Most of the parameters are self-explanitory. The swizzle parameter is
+ * an array of 4 numbers (see _mesa_get_format_swizzle) that describes
+ * where each channel in the destination should come from in the source.
+ *
+ * Under most circumstances, the source and destination images must be
+ * different as no care is taken not to clobber one with the other.
+ * However, if they have the same number of bits per pixel, it is safe to
+ * do an in-place conversion.
+ */
+void
+_mesa_swizzle_and_convert(void *void_dst, GLenum dst_type, int num_dst_channels,
+ const void *void_src, GLenum src_type, int num_src_channels,
+ const uint8_t swizzle[4], bool normalized, int count)
+{
+ int s, j;
+ register uint8_t swizzle_x, swizzle_y, swizzle_z, swizzle_w;
+
+ if (swizzle_convert_try_memcpy(void_dst, dst_type, num_dst_channels,
+ void_src, src_type, num_src_channels,
+ swizzle, normalized, count))
+ return;
+
+ swizzle_x = swizzle[0];
+ swizzle_y = swizzle[1];
+ swizzle_z = swizzle[2];
+ swizzle_w = swizzle[3];
+
+ switch (dst_type) {
+ case GL_FLOAT:
+ {
+ const float one = 1.0f;
+ switch (src_type) {
+ case GL_FLOAT:
+ SWIZZLE_CONVERT_LOOP(float, float, src)
+ break;
+ case GL_HALF_FLOAT:
+ SWIZZLE_CONVERT_LOOP(float, uint16_t, _mesa_half_to_float(src))
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(float, uint8_t, UBYTE_TO_FLOAT(src))
+ } else {
+ SWIZZLE_CONVERT_LOOP(float, uint8_t, src)
+ }
+ break;
+ case GL_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(float, int8_t, BYTE_TO_FLOAT(src))
+ } else {
+ SWIZZLE_CONVERT_LOOP(float, int8_t, src)
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(float, uint16_t, USHORT_TO_FLOAT(src))
+ } else {
+ SWIZZLE_CONVERT_LOOP(float, uint16_t, src)
+ }
+ break;
+ case GL_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(float, int16_t, SHORT_TO_FLOAT(src))
+ } else {
+ SWIZZLE_CONVERT_LOOP(float, int16_t, src)
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(float, uint32_t, UINT_TO_FLOAT(src))
+ } else {
+ SWIZZLE_CONVERT_LOOP(float, uint32_t, src)
+ }
+ break;
+ case GL_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(float, int32_t, INT_TO_FLOAT(src))
+ } else {
+ SWIZZLE_CONVERT_LOOP(float, int32_t, src)
+ }
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ case GL_HALF_FLOAT:
+ {
+ const uint16_t one = _mesa_float_to_half(1.0f);
+ switch (src_type) {
+ case GL_FLOAT:
+ SWIZZLE_CONVERT_LOOP(uint16_t, float, _mesa_float_to_half(src))
+ break;
+ case GL_HALF_FLOAT:
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, src)
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint8_t, _mesa_float_to_half(UBYTE_TO_FLOAT(src)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint8_t, _mesa_float_to_half(src))
+ }
+ break;
+ case GL_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int8_t, _mesa_float_to_half(BYTE_TO_FLOAT(src)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int8_t, _mesa_float_to_half(src))
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, _mesa_float_to_half(USHORT_TO_FLOAT(src)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, _mesa_float_to_half(src))
+ }
+ break;
+ case GL_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int16_t, _mesa_float_to_half(SHORT_TO_FLOAT(src)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int16_t, _mesa_float_to_half(src))
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint32_t, _mesa_float_to_half(UINT_TO_FLOAT(src)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint32_t, _mesa_float_to_half(src))
+ }
+ break;
+ case GL_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int32_t, _mesa_float_to_half(INT_TO_FLOAT(src)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int32_t, _mesa_float_to_half(src))
+ }
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ case GL_UNSIGNED_BYTE:
+ {
+ const uint8_t one = normalized ? UINT8_MAX : 1;
+ switch (src_type) {
+ case GL_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, float, FLOAT_TO_UBYTE(CLAMP(src, 0.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, float, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_HALF_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint16_t, FLOAT_TO_UBYTE(CLAMP(_mesa_half_to_float(src), 0.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint16_t, (src & 0x8000) ? 0 : _mesa_half_to_float(src))
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint8_t, src)
+ break;
+ case GL_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, int8_t, (src < 0) ? 0 : ((uint8_t)src * 2) + ((uint8_t)src >> 6))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, int8_t, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint16_t, src >> 8)
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint16_t, src)
+ }
+ break;
+ case GL_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, int16_t, (src < 0) ? 0 : (uint16_t)src >> 7)
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, int16_t, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint32_t, src >> 24)
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint32_t, src)
+ }
+ break;
+ case GL_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, int32_t, (src < 0) ? 0 : (uint32_t)src >> 23)
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, int32_t, (src < 0) ? 0 : src)
+ }
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ case GL_BYTE:
+ {
+ const int8_t one = normalized ? INT8_MAX : 1;
+ switch (src_type) {
+ case GL_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, float, FLOAT_TO_BYTE(CLAMP(src, -1.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, float, src)
+ }
+ break;
+ case GL_HALF_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint16_t, FLOAT_TO_BYTE(CLAMP(_mesa_half_to_float(src), -1.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint8_t, uint16_t, _mesa_half_to_float(src))
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int8_t, uint8_t, src >> 1)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int8_t, uint8_t, src)
+ }
+ break;
+ case GL_BYTE:
+ SWIZZLE_CONVERT_LOOP(int8_t, int8_t, src)
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int8_t, uint16_t, src >> 9)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int8_t, uint16_t, src)
+ }
+ break;
+ case GL_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int8_t, int16_t, src >> 8)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int8_t, int16_t, src)
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int8_t, uint32_t, src >> 25)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int8_t, uint32_t, src)
+ }
+ break;
+ case GL_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int8_t, int32_t, src >> 24)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int8_t, int32_t, src)
+ }
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ case GL_UNSIGNED_SHORT:
+ {
+ const uint16_t one = normalized ? UINT16_MAX : 1;
+ switch (src_type) {
+ case GL_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, float, FLOAT_TO_USHORT(CLAMP(src, 0.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, float, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_HALF_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, FLOAT_TO_USHORT(CLAMP(_mesa_half_to_float(src), 0.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, (src & 0x8000) ? 0 : _mesa_half_to_float(src))
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint8_t, EXTEND_NORMALIZED_UINT((uint16_t)src, 8, 16))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint8_t, src)
+ }
+ break;
+ case GL_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int8_t, (src < 0) ? 0 : EXTEND_NORMALIZED_UINT((uint16_t)src, 7, 16))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int8_t, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, src)
+ break;
+ case GL_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int16_t, (src < 0) ? 0 : EXTEND_NORMALIZED_UINT((uint16_t)src, 15, 16))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int16_t, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint32_t, src >> 16)
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint32_t, src)
+ }
+ break;
+ case GL_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int32_t, (src < 0) ? 0 : (uint32_t)src >> 15)
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, int32_t, (src < 0) ? 0 : src)
+ }
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ case GL_SHORT:
+ {
+ const int16_t one = normalized ? INT16_MAX : 1;
+ switch (src_type) {
+ case GL_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, float, FLOAT_TO_SHORT(CLAMP(src, -1.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, float, src)
+ }
+ break;
+ case GL_HALF_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, FLOAT_TO_SHORT(CLAMP(_mesa_half_to_float(src), -1.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint16_t, uint16_t, _mesa_half_to_float(src))
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int16_t, uint8_t, EXTEND_NORMALIZED_UINT((int16_t)src, 8, 15))
+ } else {
+ SWIZZLE_CONVERT_LOOP(int16_t, uint8_t, src)
+ }
+ break;
+ case GL_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int16_t, int8_t, EXTEND_NORMALIZED_INT((int16_t)src, 7, 15))
+ } else {
+ SWIZZLE_CONVERT_LOOP(int16_t, int8_t, src)
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int16_t, uint16_t, src >> 1)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int16_t, uint16_t, src)
+ }
+ break;
+ case GL_SHORT:
+ SWIZZLE_CONVERT_LOOP(int16_t, int16_t, src)
+ break;
+ case GL_UNSIGNED_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int16_t, uint32_t, src >> 17)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int16_t, uint32_t, src)
+ }
+ break;
+ case GL_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int16_t, int32_t, src >> 16)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int16_t, int32_t, src)
+ }
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ case GL_UNSIGNED_INT:
+ {
+ const uint32_t one = normalized ? UINT32_MAX : 1;
+ switch (src_type) {
+ case GL_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, float, FLOAT_TO_UINT(CLAMP(src, 0.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, float, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_HALF_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint16_t, FLOAT_TO_UINT(CLAMP(_mesa_half_to_float(src), 0.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint16_t, (src & 0x8000) ? 0 : _mesa_half_to_float(src))
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint8_t, EXTEND_NORMALIZED_UINT((uint32_t)src, 8, 32))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint8_t, src)
+ }
+ break;
+ case GL_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, int8_t, (src < 0) ? 0 : EXTEND_NORMALIZED_UINT((uint32_t)src, 7, 32))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, int8_t, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint16_t, EXTEND_NORMALIZED_UINT((uint32_t)src, 16, 32))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint16_t, src)
+ }
+ break;
+ case GL_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, int16_t, (src < 0) ? 0 : EXTEND_NORMALIZED_UINT((uint32_t)src, 15, 32))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, int16_t, (src < 0) ? 0 : src)
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint32_t, src)
+ break;
+ case GL_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, int32_t, (src < 0) ? 0 : EXTEND_NORMALIZED_UINT((uint32_t)src, 31, 32))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, int32_t, (src < 0) ? 0 : src)
+ }
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ case GL_INT:
+ {
+ const int32_t one = normalized ? INT32_MAX : 1;
+ switch (src_type) {
+ case GL_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, float, FLOAT_TO_INT(CLAMP(src, -1.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, float, src)
+ }
+ break;
+ case GL_HALF_FLOAT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint16_t, FLOAT_TO_INT(CLAMP(_mesa_half_to_float(src), -1.0f, 1.0f)))
+ } else {
+ SWIZZLE_CONVERT_LOOP(uint32_t, uint16_t, _mesa_half_to_float(src))
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int32_t, uint8_t, EXTEND_NORMALIZED_UINT((int32_t)src, 8, 31))
+ } else {
+ SWIZZLE_CONVERT_LOOP(int32_t, uint8_t, src)
+ }
+ break;
+ case GL_BYTE:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int32_t, int8_t, EXTEND_NORMALIZED_INT((int32_t)src, 7, 31))
+ } else {
+ SWIZZLE_CONVERT_LOOP(int32_t, int8_t, src)
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int32_t, uint16_t, EXTEND_NORMALIZED_UINT((int32_t)src, 16, 31))
+ } else {
+ SWIZZLE_CONVERT_LOOP(int32_t, uint16_t, src)
+ }
+ break;
+ case GL_SHORT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int32_t, int16_t, EXTEND_NORMALIZED_INT((int32_t)src, 15, 31))
+ } else {
+ SWIZZLE_CONVERT_LOOP(int32_t, int16_t, src)
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ if (normalized) {
+ SWIZZLE_CONVERT_LOOP(int32_t, uint32_t, src >> 1)
+ } else {
+ SWIZZLE_CONVERT_LOOP(int32_t, uint32_t, src)
+ }
+ break;
+ case GL_INT:
+ SWIZZLE_CONVERT_LOOP(int32_t, int32_t, src)
+ break;
+ default:
+ assert(!"Invalid channel type combination");
+ }
+ } break;
+ default:
+ assert(!"Invalid channel type");
+ }
+}
diff --git a/src/mesa/main/format_utils.h b/src/mesa/main/format_utils.h
index 6af3aa5..c5dab7b 100644
--- a/src/mesa/main/format_utils.h
+++ b/src/mesa/main/format_utils.h
@@ -33,6 +33,19 @@
#include "macros.h"
+/* Only guaranteed to work for BITS <= 32 */
+#define MAX_UINT(BITS) ((BITS) == 32 ? UINT32_MAX : ((1u << BITS) - 1))
+
+/* Extends an integer of size Sb to one of size Db in a linear way */
+#define EXTEND_NORMALIZED_UINT(X, Sb, Db) \
+ (((X) * (__typeof__(X))(MAX_UINT(Db) / MAX_UINT(Sb))) + \
+ ((Db % Sb) ? ((X) >> (Sb - Db % Sb)) : (__typeof__(X))0))
+
+/* This is almost the same as extending unsigned int except that we have to
+ * handle the case of -MAX(Sb) */
+#define EXTEND_NORMALIZED_INT(X, Sb, Db) (((X) < -(__typeof__(X))MAX_UINT(Sb)) \
+ ? -(__typeof__(X))MAX_UINT(Db) : EXTEND_NORMALIZED_UINT(X, Sb, Db))
+
/* RGB to sRGB conversion functions */
static inline float
@@ -65,4 +78,9 @@ _mesa_srgb_to_linear(float cs)
float _mesa_srgb_ubyte_to_linear_float(uint8_t cl);
+void
+_mesa_swizzle_and_convert(void *dst, GLenum dst_type, int num_dst_channels,
+ const void *src, GLenum src_type, int num_src_channels,
+ const uint8_t swizzle[4], bool normalized, int count);
+
#endif
--
2.0.1
More information about the mesa-dev
mailing list