# [Pixman] [PATCH 01/11] Add a generic unorm_to_unorm() conversion utility

Søren Sandmann sandmann at cs.au.dk
Fri Sep 2 15:06:27 PDT 2011

```From: Søren Sandmann Pedersen <ssp at redhat.com>

This function can convert between normalized numbers of different
depths. When converting to higher bit depths, it will replicate the
existing bits, when converting to lower bit depths, it will simply
truncate.

This function replaces the expand16() function in pixman-utils.c
---
pixman/pixman-private.h |   43 +++++++++++++++++++++++++++++++++++++++++++
pixman/pixman-utils.c   |   34 +++++-----------------------------
2 files changed, 48 insertions(+), 29 deletions(-)

diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h
index a25897d..90d9011 100644
--- a/pixman/pixman-private.h
+++ b/pixman/pixman-private.h
@@ -783,6 +783,49 @@ pixman_region16_copy_from_region32 (pixman_region16_t *dst,
#   define SCREEN_SHIFT_RIGHT(x,n)	((x) << (n))
#endif

+static force_inline uint32_t
+unorm_to_unorm (uint32_t val, int from_bits, int to_bits)
+{
+    uint32_t result;
+
+    if (from_bits == 0)
+	return 0;
+
+    /* Delete any extra bits */
+    val &= ((1 << from_bits) - 1);
+
+    if (from_bits >= to_bits)
+	return val >> (from_bits - to_bits);
+
+    /* Start out with the high bit of val in the high bit of result. */
+    result = val << (to_bits - from_bits);
+
+    /* Copy the bits in result, doubling the number of bits each time, until
+     * we fill all to_bits. Unrolled manually because from_bits and to_bits
+     * are usually known statically, so the compiler can turn all of this
+     * into a few shifts.
+     */
+#define REPLICATE()							\
+    do									\
+    {									\
+	if (from_bits < to_bits)					\
+	{								\
+	    result |= result >> from_bits;				\
+									\
+	    from_bits *= 2;						\
+	}								\
+    }									\
+    while (0)
+
+    REPLICATE();
+    REPLICATE();
+    REPLICATE();
+    REPLICATE();
+    REPLICATE();
+
+    return result;
+}
+
/*
* Various debugging code
*/
diff --git a/pixman/pixman-utils.c b/pixman/pixman-utils.c
index 49e3488..768ca1b 100644
--- a/pixman/pixman-utils.c
+++ b/pixman/pixman-utils.c
@@ -72,31 +72,6 @@ pixman_malloc_abc (unsigned int a,
}

/*
- * Helper routine to expand a color component from 0 < n <= 8 bits to 16
- * bits by replication.
- */
-static inline uint64_t
-expand16 (const uint8_t val, int nbits)
-{
-    /* Start out with the high bit of val in the high bit of result. */
-    uint16_t result = (uint16_t)val << (16 - nbits);
-
-    if (nbits == 0)
-	return 0;
-
-    /* Copy the bits in result, doubling the number of bits each time, until
-     * we fill all 16 bits.
-     */
-    while (nbits < 16)
-    {
-	result |= result >> nbits;
-	nbits *= 2;
-    }
-
-    return result;
-}
-
-/*
* This function expands images from ARGB8 format to ARGB16.  To preserve
* precision, it needs to know the original source format.  For example, if the
* source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then
@@ -137,10 +112,11 @@ pixman_expand (uint64_t *           dst,
r = (pixel >> r_shift) & r_mask,
g = (pixel >> g_shift) & g_mask,
b = (pixel >> b_shift) & b_mask;
-	const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff,
-	               r16 = expand16 (r, r_size),
-	               g16 = expand16 (g, g_size),
-	               b16 = expand16 (b, b_size);
+	const uint64_t
+	    a16 = a_size ? unorm_to_unorm (a, a_size, 16) : 0xffff,
+	    r16 = unorm_to_unorm (r, r_size, 16),
+	    g16 = unorm_to_unorm (g, g_size, 16),
+	    b16 = unorm_to_unorm (b, b_size, 16);

dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16;
}
--
1.7.4

```

More information about the Pixman mailing list