From: Søren Sandmann Pedersen <s...@redhat.com> Three new function pointer fields are added to bits_image_t:
fetch_scanline_float fetch_pixel_float store_scanline_float similar to the existing 32 and 64 bit accessors. The fetcher_info_t struct in pixman_access similarly gets a new get_scanline_float field. For most formats, the new get_scanline_float field is set to a new function fetch_scanline_generic_float() that first calls the 32 bit fetcher uses the 32 bit scanline fetcher and then expands these pixels to floating point. For the 10 bpc formats, new floating point accessors are added that use pixman_unorm_to_float() and pixman_float_to_unorm() to convert back and forth. The PIXMAN_a8r8g8b8_sRGB format is handled with a 256-entry table that maps 8 bit sRGB channels to linear single precision floating point numbers. The sRGB->linear direction can then be done with a simple table lookup. The other direction is currently done with a 4096-entry table which works fine for 16 bit integers, but not so great for floating point. So instead this patch uses a binary search in the sRGB->linear table. The existing 32 bit accessors for the sRGB format are also converted to use this method. --- pixman/pixman-access.c | 619 +++++++++++++++++++++++++++++++++++++++++--- pixman/pixman-bits-image.c | 40 +++- pixman/pixman-private.h | 8 + 3 files changed, 624 insertions(+), 43 deletions(-) diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index 9feafc4..1eef621 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -31,6 +31,7 @@ #include <stdlib.h> #include <string.h> #include <assert.h> +#include <math.h> #include "pixman-accessor.h" #include "pixman-private.h" @@ -635,6 +636,231 @@ fetch_scanline_x2b10g10r10 (pixman_image_t *image, } } +/* Table mapping sRGB-encoded 8 bit numbers to linearly encoded + * floating point numbers. We assume that single precision + * floating point follows the IEEE 754 format. + */ +static const uint32_t to_linear_u[256] = +{ + 0x00000000, 0x399f22b4, 0x3a1f22b4, 0x3a6eb40e, 0x3a9f22b4, 0x3ac6eb61, + 0x3aeeb40e, 0x3b0b3e5d, 0x3b1f22b4, 0x3b33070b, 0x3b46eb61, 0x3b5b518a, + 0x3b70f18a, 0x3b83e1c5, 0x3b8fe614, 0x3b9c87fb, 0x3ba9c9b5, 0x3bb7ad6d, + 0x3bc63547, 0x3bd5635f, 0x3be539bd, 0x3bf5ba70, 0x3c0373b5, 0x3c0c6152, + 0x3c15a703, 0x3c1f45bc, 0x3c293e68, 0x3c3391f4, 0x3c3e4149, 0x3c494d43, + 0x3c54b6c7, 0x3c607eb1, 0x3c6ca5df, 0x3c792d22, 0x3c830aa8, 0x3c89af9e, + 0x3c9085db, 0x3c978dc5, 0x3c9ec7c0, 0x3ca63432, 0x3cadd37d, 0x3cb5a601, + 0x3cbdac20, 0x3cc5e639, 0x3cce54ab, 0x3cd6f7d2, 0x3cdfd00e, 0x3ce8ddb9, + 0x3cf2212c, 0x3cfb9ac1, 0x3d02a569, 0x3d0798dc, 0x3d0ca7e4, 0x3d11d2ae, + 0x3d171963, 0x3d1c7c2e, 0x3d21fb3a, 0x3d2796af, 0x3d2d4ebb, 0x3d332380, + 0x3d39152b, 0x3d3f23e3, 0x3d454fd0, 0x3d4b991c, 0x3d51ffeb, 0x3d588466, + 0x3d5f26b7, 0x3d65e6fe, 0x3d6cc564, 0x3d73c210, 0x3d7add25, 0x3d810b65, + 0x3d84b793, 0x3d88732e, 0x3d8c3e48, 0x3d9018f4, 0x3d940343, 0x3d97fd48, + 0x3d9c0714, 0x3da020b9, 0x3da44a48, 0x3da883d6, 0x3daccd70, 0x3db12728, + 0x3db59110, 0x3dba0b38, 0x3dbe95b2, 0x3dc3308f, 0x3dc7dbe0, 0x3dcc97b4, + 0x3dd1641c, 0x3dd6412a, 0x3ddb2eec, 0x3de02d75, 0x3de53cd3, 0x3dea5d16, + 0x3def8e52, 0x3df4d091, 0x3dfa23e5, 0x3dff885e, 0x3e027f06, 0x3e05427f, + 0x3e080ea2, 0x3e0ae376, 0x3e0dc104, 0x3e10a752, 0x3e139669, 0x3e168e50, + 0x3e198f0e, 0x3e1c98ab, 0x3e1fab2e, 0x3e22c6a0, 0x3e25eb08, 0x3e29186a, + 0x3e2c4ed0, 0x3e2f8e42, 0x3e32d6c4, 0x3e362861, 0x3e39831e, 0x3e3ce702, + 0x3e405416, 0x3e43ca5e, 0x3e4749e4, 0x3e4ad2ae, 0x3e4e64c2, 0x3e520027, + 0x3e55a4e6, 0x3e595303, 0x3e5d0a8a, 0x3e60cb7c, 0x3e6495e0, 0x3e6869bf, + 0x3e6c4720, 0x3e702e08, 0x3e741e7f, 0x3e78188c, 0x3e7c1c34, 0x3e8014c0, + 0x3e822039, 0x3e84308b, 0x3e8645b8, 0x3e885fc3, 0x3e8a7eb0, 0x3e8ca281, + 0x3e8ecb3a, 0x3e90f8df, 0x3e932b72, 0x3e9562f6, 0x3e979f6f, 0x3e99e0e0, + 0x3e9c274e, 0x3e9e72b8, 0x3ea0c322, 0x3ea31892, 0x3ea57308, 0x3ea7d28a, + 0x3eaa3718, 0x3eaca0b7, 0x3eaf0f69, 0x3eb18332, 0x3eb3fc16, 0x3eb67a15, + 0x3eb8fd34, 0x3ebb8576, 0x3ebe12de, 0x3ec0a56e, 0x3ec33d2a, 0x3ec5da14, + 0x3ec87c30, 0x3ecb2380, 0x3ecdd008, 0x3ed081ca, 0x3ed338c9, 0x3ed5f508, + 0x3ed8b68a, 0x3edb7d52, 0x3ede4962, 0x3ee11abe, 0x3ee3f168, 0x3ee6cd64, + 0x3ee9aeb6, 0x3eec955d, 0x3eef815d, 0x3ef272ba, 0x3ef56976, 0x3ef86594, + 0x3efb6717, 0x3efe6e02, 0x3f00bd2b, 0x3f02460c, 0x3f03d1a5, 0x3f055ff8, + 0x3f06f105, 0x3f0884ce, 0x3f0a1b54, 0x3f0bb499, 0x3f0d509f, 0x3f0eef65, + 0x3f1090ef, 0x3f12353c, 0x3f13dc50, 0x3f15862a, 0x3f1732cc, 0x3f18e237, + 0x3f1a946d, 0x3f1c4970, 0x3f1e013f, 0x3f1fbbde, 0x3f21794c, 0x3f23398c, + 0x3f24fca0, 0x3f26c286, 0x3f288b42, 0x3f2a56d3, 0x3f2c253d, 0x3f2df680, + 0x3f2fca9d, 0x3f31a195, 0x3f337b6a, 0x3f35581e, 0x3f3737b1, 0x3f391a24, + 0x3f3aff7a, 0x3f3ce7b2, 0x3f3ed2d0, 0x3f40c0d2, 0x3f42b1bc, 0x3f44a58e, + 0x3f469c49, 0x3f4895ee, 0x3f4a9280, 0x3f4c91ff, 0x3f4e946c, 0x3f5099c8, + 0x3f52a216, 0x3f54ad55, 0x3f56bb88, 0x3f58ccae, 0x3f5ae0cb, 0x3f5cf7de, + 0x3f5f11ec, 0x3f612ef0, 0x3f634eef, 0x3f6571ea, 0x3f6797e1, 0x3f69c0d6, + 0x3f6beccb, 0x3f6e1bc0, 0x3f704db6, 0x3f7282af, 0x3f74baac, 0x3f76f5ae, + 0x3f7933b6, 0x3f7b74c6, 0x3f7db8de, 0x3f800000 +}; + +static const float * const to_linear = (const float *)to_linear_u; + +static uint8_t +to_srgb (float f) +{ + uint8_t low = 0; + uint8_t high = 255; + + while (high - low > 1) + { + uint8_t mid = (low + high) / 2; + + if (to_linear[mid] > f) + high = mid; + else + low = mid; + } + + if (to_linear[high] - f < f - to_linear[low]) + return high; + else + return low; +} + +static void +fetch_scanline_a8r8g8b8_sRGB_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = bits + x; + const uint32_t *end = pixel + width; + argb_t *buffer = (argb_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + argb_t *argb = buffer; + + argb->a = pixman_unorm_to_float ((p >> 24) & 0xff, 8); + + argb->r = to_linear [(p >> 16) & 0xff]; + argb->g = to_linear [(p >> 8) & 0xff]; + argb->b = to_linear [(p >> 0) & 0xff]; + + buffer++; + } +} + +/* Expects a float buffer */ +static void +fetch_scanline_a2r10g10b10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = bits + x; + const uint32_t *end = pixel + width; + argb_t *buffer = (argb_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t a = p >> 30; + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + + buffer->a = pixman_unorm_to_float (a, 2); + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); + + buffer++; + } +} + +/* Expects a float buffer */ +static void +fetch_scanline_x2r10g10b10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + argb_t *buffer = (argb_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + + buffer->a = 1.0; + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); + + buffer++; + } +} + +/* Expects a float buffer */ +static void +fetch_scanline_a2b10g10r10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = bits + x; + const uint32_t *end = pixel + width; + argb_t *buffer = (argb_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t a = p >> 30; + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + buffer->a = pixman_unorm_to_float (a, 2); + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); + + buffer++; + } +} + +/* Expects a float buffer */ +static void +fetch_scanline_x2b10g10r10_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + argb_t *buffer = (argb_t *)b; + + while (pixel < end) + { + uint32_t p = READ (image, pixel++); + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + + buffer->a = 1.0; + buffer->r = pixman_unorm_to_float (r, 10); + buffer->g = pixman_unorm_to_float (g, 10); + buffer->b = pixman_unorm_to_float (b, 10); + + buffer++; + } +} + static void fetch_scanline_yuy2 (pixman_image_t *image, int x, @@ -796,6 +1022,106 @@ fetch_pixel_x2b10g10r10 (bits_image_t *image, return 0xffffULL << 48 | r << 32 | g << 16 | b; } +static argb_t +fetch_pixel_x2r10g10b10_float (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + argb_t argb; + + argb.a = 1.0; + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); + + return argb; +} + +static argb_t +fetch_pixel_a2r10g10b10_float (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t a = p >> 30; + uint64_t r = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t b = p & 0x3ff; + argb_t argb; + + argb.a = pixman_unorm_to_float (a, 2); + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); + + return argb; +} + +static argb_t +fetch_pixel_a2b10g10r10_float (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t a = p >> 30; + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + argb_t argb; + + argb.a = pixman_unorm_to_float (a, 2); + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); + + return argb; +} + +static argb_t +fetch_pixel_x2b10g10r10_float (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + uint64_t b = (p >> 20) & 0x3ff; + uint64_t g = (p >> 10) & 0x3ff; + uint64_t r = p & 0x3ff; + argb_t argb; + + argb.a = 1.0; + argb.r = pixman_unorm_to_float (r, 10); + argb.g = pixman_unorm_to_float (g, 10); + argb.b = pixman_unorm_to_float (b, 10); + + return argb; +} + +static argb_t +fetch_pixel_a8r8g8b8_sRGB_float (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t p = READ (image, bits + offset); + argb_t argb; + + argb.a = pixman_unorm_to_float ((p >> 24) & 0xff, 8); + + argb.r = to_linear [(p >> 16) & 0xff]; + argb.g = to_linear [(p >> 8) & 0xff]; + argb.b = to_linear [(p >> 0) & 0xff]; + + return argb; +} + static uint32_t fetch_pixel_yuy2 (bits_image_t *image, int offset, @@ -939,6 +1265,135 @@ store_scanline_x2b10g10r10 (bits_image_t * image, } } + +static void +store_scanline_a2r10g10b10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + uint16_t a, r, g, b; + + a = pixman_float_to_unorm (values[i].a, 2); + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + + WRITE (image, pixel++, + (a << 30) | (r << 20) | (g << 10) | b); + } +} + +static void +store_scanline_x2r10g10b10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + uint16_t r, g, b; + + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + + WRITE (image, pixel++, + (r << 20) | (g << 10) | b); + } +} + +static void +store_scanline_a2b10g10r10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + uint16_t a, r, g, b; + + a = pixman_float_to_unorm (values[i].a, 2); + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + + WRITE (image, pixel++, + (a << 30) | (b << 20) | (g << 10) | r); + } +} + +static void +store_scanline_x2b10g10r10_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + uint16_t r, g, b; + + r = pixman_float_to_unorm (values[i].r, 10); + g = pixman_float_to_unorm (values[i].g, 10); + b = pixman_float_to_unorm (values[i].b, 10); + + WRITE (image, pixel++, + (b << 20) | (g << 10) | r); + } +} + +static void +store_scanline_a8r8g8b8_sRGB_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint32_t *pixel = bits + x; + argb_t *values = (argb_t *)v; + int i; + + for (i = 0; i < width; ++i) + { + uint8_t a, r, g, b; + + a = pixman_float_to_unorm (values[i].a, 8); + r = to_srgb (values[i].r); + g = to_srgb (values[i].g); + b = to_srgb (values[i].b); + + WRITE (image, pixel++, + (a << 24) | (r << 16) | (g << 8) | b); + } +} + /* * Contracts a 64bpp image to 32bpp and then stores it using a regular 32-bit * store proc. Despite the type, this function expects a uint64_t buffer. @@ -968,6 +1423,36 @@ store_scanline_generic_64 (bits_image_t * image, free (argb8_pixels); } +/* + * Contracts a floating point image to 32bpp and then stores it using a + * regular 32-bit store proc. Despite the type, this function expects an + * argb_t buffer. + */ +static void +store_scanline_generic_float (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint32_t *argb8_pixels; + + assert (image->common.type == BITS); + + argb8_pixels = pixman_malloc_ab (width, sizeof(uint32_t)); + if (!argb8_pixels) + return; + + /* Contract the scanline. We could do this in place if values weren't + * const. + */ + pixman_contract_from_float (argb8_pixels, (argb_t *)values, width); + + image->store_scanline_32 (image, x, y, width, argb8_pixels); + + free (argb8_pixels); +} + /* Despite the type, this function expects both buffer * and mask to be uint64_t */ @@ -1001,6 +1486,19 @@ fetch_scanline_generic_64 (pixman_image_t *image, pixman_expand ((uint64_t *)buffer, buffer, format, width); } +static void +fetch_scanline_generic_float (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask) +{ + image->bits.fetch_scanline_32 (image, x, y, width, buffer, NULL); + + pixman_expand_to_float ((argb_t *)buffer, buffer, image->bits.format, width); +} + /* Despite the type, this function expects a uint64_t *buffer */ static uint64_t fetch_pixel_generic_64 (bits_image_t *image, @@ -1046,11 +1544,20 @@ fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image, while (pixel < end) { + uint8_t a, r, g, b; + tmp = READ (image, pixel++); - *buffer++ = (tmp >> 24) << 24 - | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 - | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 - | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; + + a = (tmp >> 24) & 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_linear[r] * 255.0f + 0.5f; + g = to_linear[g] * 255.0f + 0.5f; + b = to_linear[b] * 255.0f + 0.5f; + + *buffer++ = (a << 24) | (r << 16) | (g << 8) | (b << 0); } } @@ -1085,10 +1592,18 @@ fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, { uint32_t *bits = image->bits + line * image->rowstride; uint32_t tmp = READ (image, bits + offset); - return (tmp >> 24) << 24 - | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 - | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 - | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; + uint8_t a, r, g, b; + + a = (tmp >> 24) & 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_linear[r] * 255.0f + 0.5f; + g = to_linear[g] * 255.0f + 0.5f; + b = to_linear[b] * 255.0f + 0.5f; + + return (a << 24) | (r << 16) | (g << 8) | (b << 0); } static uint64_t @@ -1119,12 +1634,20 @@ store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, for (i = 0; i < width; ++i) { + uint8_t a, r, g, b; + tmp = values[i]; - WRITE (image, pixel++, - ((uint32_t) (tmp >> 24 ) << 24) - | (linear_to_srgb[(tmp >> 16 << 4) & 0xfff] << 16) - | (linear_to_srgb[(tmp >> 8 << 4) & 0xfff] << 8) - | (linear_to_srgb[(tmp >> 0 << 4) & 0xfff] << 0)); + + a = (tmp >> 24) & 0xff; + r = (tmp >> 16) & 0xff; + g = (tmp >> 8) & 0xff; + b = (tmp >> 0) & 0xff; + + r = to_srgb (r * (1/255.0f)); + g = to_srgb (g * (1/255.0f)); + b = to_srgb (b * (1/255.0f)); + + WRITE (image, pixel++, a | (r << 16) | (g << 8) | (b << 0)); } } @@ -1152,6 +1675,19 @@ store_scanline_a8r8g8b8_64_sRGB (bits_image_t *image, } } +static argb_t +fetch_pixel_generic_float (bits_image_t *image, + int offset, + int line) +{ + uint32_t pixel32 = image->fetch_pixel_32 (image, offset, line); + argb_t f; + + pixman_expand_to_float (&f, &pixel32, image->format, 1); + + return f; +} + /* * XXX: The transformed fetch path only works at 32-bpp so far. When all * paths have wide versions, this can be removed. @@ -1176,10 +1712,13 @@ typedef struct pixman_format_code_t format; fetch_scanline_t fetch_scanline_32; fetch_scanline_t fetch_scanline_64; + fetch_scanline_t fetch_scanline_float; fetch_pixel_32_t fetch_pixel_32; fetch_pixel_64_t fetch_pixel_64; + fetch_pixel_float_t fetch_pixel_float; store_scanline_t store_scanline_32; store_scanline_t store_scanline_64; + store_scanline_t store_scanline_float; } format_info_t; #define FORMAT_INFO(format) \ @@ -1187,8 +1726,13 @@ typedef struct PIXMAN_ ## format, \ fetch_scanline_ ## format, \ fetch_scanline_generic_64, \ - fetch_pixel_ ## format, fetch_pixel_generic_64, \ - store_scanline_ ## format, store_scanline_generic_64 \ + fetch_scanline_generic_float, \ + fetch_pixel_ ## format, \ + fetch_pixel_generic_64, \ + fetch_pixel_generic_float, \ + store_scanline_ ## format, \ + store_scanline_generic_64, \ + store_scanline_generic_float \ } static const format_info_t accessors[] = @@ -1206,10 +1750,10 @@ static const format_info_t accessors[] = /* sRGB formats */ { PIXMAN_a8r8g8b8_sRGB, - fetch_scanline_a8r8g8b8_32_sRGB, - fetch_scanline_a8r8g8b8_64_sRGB, - fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB, - store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB }, + fetch_scanline_a8r8g8b8_32_sRGB, fetch_scanline_a8r8g8b8_64_sRGB, fetch_scanline_a8r8g8b8_sRGB_float, + fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB, fetch_pixel_a8r8g8b8_sRGB_float, + store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB, store_scanline_a8r8g8b8_sRGB_float, + }, /* 24bpp formats */ FORMAT_INFO (r8g8b8), @@ -1269,34 +1813,34 @@ static const format_info_t accessors[] = /* Wide formats */ { PIXMAN_a2r10g10b10, - NULL, fetch_scanline_a2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10, - NULL, store_scanline_a2r10g10b10 }, + NULL, fetch_scanline_a2r10g10b10, fetch_scanline_a2r10g10b10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_a2r10g10b10, fetch_pixel_a2r10g10b10_float, + NULL, store_scanline_a2r10g10b10, store_scanline_a2r10g10b10_float }, { PIXMAN_x2r10g10b10, - NULL, fetch_scanline_x2r10g10b10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10, - NULL, store_scanline_x2r10g10b10 }, + NULL, fetch_scanline_x2r10g10b10, fetch_scanline_x2r10g10b10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_x2r10g10b10, fetch_pixel_x2r10g10b10_float, + NULL, store_scanline_x2r10g10b10, store_scanline_x2r10g10b10_float }, { PIXMAN_a2b10g10r10, - NULL, fetch_scanline_a2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10, - NULL, store_scanline_a2b10g10r10 }, + NULL, fetch_scanline_a2b10g10r10, fetch_scanline_a2b10g10r10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_a2b10g10r10, fetch_pixel_a2b10g10r10_float, + NULL, store_scanline_a2b10g10r10, store_scanline_a2b10g10r10_float }, { PIXMAN_x2b10g10r10, - NULL, fetch_scanline_x2b10g10r10, - fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10, - NULL, store_scanline_x2b10g10r10 }, + NULL, fetch_scanline_x2b10g10r10, fetch_scanline_x2b10g10r10_float, + fetch_pixel_generic_lossy_32, fetch_pixel_x2b10g10r10, fetch_pixel_x2b10g10r10_float, + NULL, store_scanline_x2b10g10r10, store_scanline_x2b10g10r10_float }, /* YUV formats */ { PIXMAN_yuy2, - fetch_scanline_yuy2, fetch_scanline_generic_64, - fetch_pixel_yuy2, fetch_pixel_generic_64, - NULL, NULL }, + fetch_scanline_yuy2, fetch_scanline_generic_64, fetch_scanline_generic_float, + fetch_pixel_yuy2, fetch_pixel_generic_64, fetch_pixel_generic_float, + NULL, NULL, NULL }, { PIXMAN_yv12, - fetch_scanline_yv12, fetch_scanline_generic_64, - fetch_pixel_yv12, fetch_pixel_generic_64, + fetch_scanline_yv12, fetch_scanline_generic_64, fetch_scanline_generic_float, + fetch_pixel_yv12, fetch_pixel_generic_64, fetch_pixel_generic_float, NULL, NULL }, { PIXMAN_null }, @@ -1313,10 +1857,13 @@ setup_accessors (bits_image_t *image) { image->fetch_scanline_32 = info->fetch_scanline_32; image->fetch_scanline_64 = info->fetch_scanline_64; + image->fetch_scanline_float = info->fetch_scanline_float; image->fetch_pixel_32 = info->fetch_pixel_32; image->fetch_pixel_64 = info->fetch_pixel_64; + image->fetch_pixel_float = info->fetch_pixel_float; image->store_scanline_32 = info->store_scanline_32; image->store_scanline_64 = info->store_scanline_64; + image->store_scanline_float = info->store_scanline_float; return; } diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index c69e151..07353dc 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -36,6 +36,20 @@ #include "pixman-combine32.h" #include "pixman-inlines.h" +static uint32_t * +_pixman_image_get_scanline_generic_float (pixman_iter_t * iter, + const uint32_t *mask) +{ + pixman_iter_get_scanline_t fetch_32 = iter->data; + uint32_t *buffer = iter->buffer; + + fetch_32 (iter, NULL); + + pixman_expand_to_float ((argb_t *)buffer, buffer, PIXMAN_a8r8g8b8, iter->width); + + return iter->buffer; +} + /* * By default, just evaluate the image at 32bpp and expand. Individual image * types can plug in a better scanline getter if they want to. For example @@ -1129,6 +1143,7 @@ typedef struct uint32_t flags; pixman_iter_get_scanline_t get_scanline_32; pixman_iter_get_scanline_t get_scanline_64; + pixman_iter_get_scanline_t get_scanline_float; } fetcher_info_t; static const fetcher_info_t fetcher_info[] = @@ -1140,7 +1155,8 @@ static const fetcher_info_t fetcher_info[] = FAST_PATH_NO_PAD_REPEAT | FAST_PATH_NO_REFLECT_REPEAT), bits_image_fetch_untransformed_32, - bits_image_fetch_untransformed_64 + bits_image_fetch_untransformed_64, + _pixman_image_get_scanline_generic_float }, #define FAST_BILINEAR_FLAGS \ @@ -1156,13 +1172,15 @@ static const fetcher_info_t fetcher_info[] = { PIXMAN_a8r8g8b8, FAST_BILINEAR_FLAGS, bits_image_fetch_bilinear_no_repeat_8888, - _pixman_image_get_scanline_generic_64 + _pixman_image_get_scanline_generic_64, + _pixman_image_get_scanline_generic_float }, { PIXMAN_x8r8g8b8, FAST_BILINEAR_FLAGS, bits_image_fetch_bilinear_no_repeat_8888, - _pixman_image_get_scanline_generic_64 + _pixman_image_get_scanline_generic_64, + _pixman_image_get_scanline_generic_float }, #define GENERAL_BILINEAR_FLAGS \ @@ -1183,14 +1201,16 @@ static const fetcher_info_t fetcher_info[] = { PIXMAN_ ## format, \ GENERAL_BILINEAR_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ bits_image_fetch_bilinear_affine_ ## name, \ - _pixman_image_get_scanline_generic_64 \ + _pixman_image_get_scanline_generic_64, \ + _pixman_image_get_scanline_generic_float \ }, #define NEAREST_AFFINE_FAST_PATH(name, format, repeat) \ { PIXMAN_ ## format, \ GENERAL_NEAREST_FLAGS | FAST_PATH_ ## repeat ## _REPEAT, \ bits_image_fetch_nearest_affine_ ## name, \ - _pixman_image_get_scanline_generic_64 \ + _pixman_image_get_scanline_generic_64, \ + _pixman_image_get_scanline_generic_float \ }, #define AFFINE_FAST_PATHS(name, format, repeat) \ @@ -1218,11 +1238,17 @@ static const fetcher_info_t fetcher_info[] = { PIXMAN_any, (FAST_PATH_NO_ALPHA_MAP | FAST_PATH_HAS_TRANSFORM | FAST_PATH_AFFINE_TRANSFORM), bits_image_fetch_affine_no_alpha, - _pixman_image_get_scanline_generic_64 + _pixman_image_get_scanline_generic_64, + _pixman_image_get_scanline_generic_float }, /* General */ - { PIXMAN_any, 0, bits_image_fetch_general, _pixman_image_get_scanline_generic_64 }, + { PIXMAN_any, + 0, + bits_image_fetch_general, + _pixman_image_get_scanline_generic_64, + _pixman_image_get_scanline_generic_float + }, { PIXMAN_null }, }; diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index 91f35ed..766dafa 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -70,6 +70,10 @@ typedef uint64_t (*fetch_pixel_64_t) (bits_image_t *image, int x, int y); +typedef argb_t (*fetch_pixel_float_t) (bits_image_t *image, + int x, + int y); + typedef void (*store_scanline_t) (bits_image_t * image, int x, int y, @@ -187,6 +191,10 @@ struct bits_image fetch_pixel_64_t fetch_pixel_64; store_scanline_t store_scanline_64; + fetch_scanline_t fetch_scanline_float; + fetch_pixel_float_t fetch_pixel_float; + store_scanline_t store_scanline_float; + /* Used for indirect access to the bits */ pixman_read_memory_func_t read_func; pixman_write_memory_func_t write_func; -- 1.7.4 _______________________________________________ Pixman mailing list Pixman@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/pixman