summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2011-08-15 10:22:05 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-09-20 06:44:04 -0400
commit22f54dde6bbf87251a0b4ad93bacbdaa7cb508d8 (patch)
tree764960c61b59e016a6279acab7a064be149aa6fd
parentd842669a467be490bb0a40000d0c0fccea0b1b85 (diff)
Add a generic unorm_to_unorm() conversion utility
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
-rw-r--r--pixman/pixman-private.h43
-rw-r--r--pixman/pixman-utils.c34
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;
}