# 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
*/
}
/*
- * 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
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;
}