diff options
author | Benjamin Otte <otte@gnome.org> | 2009-09-18 11:04:37 +0200 |
---|---|---|
committer | Søren Sandmann Pedersen <sandmann@redhat.com> | 2009-11-20 20:23:55 +0100 |
commit | 4e13f9235081dc7b6cacd8706dc4b7a2a8436056 (patch) | |
tree | 96473f41510556ffc7bba9f990331eae3d2ab02f | |
parent | 7bbd76d9e717921b6198d152840a22093128fd6c (diff) |
(Re)add YUY2
Optimized to conert chroma only once when reading adjacent pixels.
Supports writing, too.
-rw-r--r-- | pixman/pixman-access.c | 165 | ||||
-rw-r--r-- | pixman/pixman.c | 1 | ||||
-rw-r--r-- | pixman/pixman.h | 4 |
3 files changed, 111 insertions, 59 deletions
diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c index b864b374..f591fed2 100644 --- a/pixman/pixman-access.c +++ b/pixman/pixman-access.c @@ -1145,7 +1145,6 @@ fetch_scanline_ayuv (pixman_image_t *image, } } -#if 0 static void fetch_scanline_yuy2 (pixman_image_t *image, int x, @@ -1155,32 +1154,54 @@ fetch_scanline_yuy2 (pixman_image_t *image, const uint32_t *mask, uint32_t mask_bits) { - const uint32_t *bits = image->bits.bits + image->bits.rowstride * line; - int i; + const uint8_t *bits = (const uint8_t *) (image->bits.bits + image->bits.rowstride * line); + int i, end; + int32_t y, y2, u, v, r, g, b, r2, g2, b2; - for (i = 0; i < width; i++) + i = x; + end = x + width; + if (i & 1) { + y = bits[i << 1]; + u = bits[((i << 1) & ~3) + 1]; + v = bits[((i << 1) & ~3) + 3]; + + YUV2RGB_CHROMA (r, g, b, u, v); + YUV2RGB_ADD (r, g, b, y); + YUV2RGB_STORE (*buffer, r, g, b); + + buffer++; + i++; + } + for (; i < end; i += 2) { - int16_t y, u, v; - int32_t r, g, b; + y = bits[(i << 1)]; + u = bits[(i << 1) + 1]; + y2 = bits[(i << 1) + 2]; + v = bits[(i << 1) + 3]; - y = ((uint8_t *) bits)[(x + i) << 1] - 16; - u = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] - 128; - v = ((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] - 128; + YUV2RGB_CHROMA (r, g, b, u, v); + r2 = r; + g2 = g; + b2 = b; + YUV2RGB_ADD (r, g, b, y); + YUV2RGB_STORE (buffer[0], r, g, b); + YUV2RGB_ADD (r2, g2, b2, y2); + YUV2RGB_STORE (buffer[1], r2, g2, b2); - /* R = 1.164(Y - 16) + 1.596(V - 128) */ - r = 0x012b27 * y + 0x019a2e * v; - /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ - g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; - /* B = 1.164(Y - 16) + 2.018(U - 128) */ - b = 0x012b27 * y + 0x0206a2 * u; + buffer += 2; + } + if (end & 1) { + y = bits[i << 1]; + u = bits[((i << 1) & ~3) + 1]; + v = bits[((i << 1) & ~3) + 3]; - *buffer++ = 0xff000000 | - (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | - (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | - (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); + YUV2RGB_CHROMA (r, g, b, u, v); + YUV2RGB_ADD (r, g, b, y); + YUV2RGB_STORE (*buffer, r, g, b); } } +#if 0 static void fetch_scanline_yv12 (pixman_image_t *image, int x, @@ -1865,36 +1886,27 @@ fetch_pixel_ayuv (bits_image_t *image, return pixel; } -#if 0 static uint32_t fetch_pixel_yuy2 (bits_image_t *image, int offset, int line) { const uint32_t *bits = image->bits + image->rowstride * line; + int32_t y, u, v, r, g, b; + uint32_t pixel; - int16_t y, u, v; - int32_t r, g, b; - - y = ((uint8_t *) bits)[offset << 1] - 16; - u = ((uint8_t *) bits)[((offset << 1) & - 4) + 1] - 128; - v = ((uint8_t *) bits)[((offset << 1) & - 4) + 3] - 128; - - /* R = 1.164(Y - 16) + 1.596(V - 128) */ - r = 0x012b27 * y + 0x019a2e * v; - - /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */ - g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u; - - /* B = 1.164(Y - 16) + 2.018(U - 128) */ - b = 0x012b27 * y + 0x0206a2 * u; - - return 0xff000000 | - (r >= 0 ? r < 0x1000000 ? r & 0xff0000 : 0xff0000 : 0) | - (g >= 0 ? g < 0x1000000 ? (g >> 8) & 0x00ff00 : 0x00ff00 : 0) | - (b >= 0 ? b < 0x1000000 ? (b >> 16) & 0x0000ff : 0x0000ff : 0); + y = bits[offset << 1]; + u = bits[((offset << 1) & ~3) + 1]; + v = bits[((offset << 1) & ~3) + 3]; + + YUV2RGB_CHROMA (r, g, b, u, v); + YUV2RGB_ADD (r, g, b, y); + YUV2RGB_STORE (pixel, r, g, b); + + return pixel; } +#if 0 static uint32_t fetch_pixel_yv12 (bits_image_t *image, int offset, @@ -2779,12 +2791,7 @@ store_scanline_ayuv (bits_image_t * image, for (i = 0; i < width; i++) { - int32_t a, r, g, b; - - a = values[i] >> 24; - r = (values[i] >> 16) & 0xff; - g = (values[i] >> 8 ) & 0xff; - b = values[i] & 0xff; + SPLIT_A (values[i]); UNPREMULTIPLY (r, g, b, a); @@ -2797,6 +2804,60 @@ store_scanline_ayuv (bits_image_t * image, } } +static void +store_scanline_yuy2 (bits_image_t * image, + int x, + int y, + int width, + const uint32_t *values) +{ + uint8_t *bits = (uint8_t *) (image->bits + image->rowstride * y); + int i, end; + int32_t u, v; + + i = x; + end = x + width; + if (i & 1) + { + SPLIT (values[i]); + + bits[(i << 1)] = RGB2Y (r, g, b) >> 16; + u = bits[(i << 1) - 1]; + bits[(i << 1) - 1] = (RGB2U (r, g, b) + (u << 16)) >> 17; + v = bits[(i << 1) + 1]; + bits[(i << 1) + 1] = (RGB2V (r, g, b) + (v << 16)) >> 17; + + values++; + i++; + } + for (; i < end; i += 2) + { + { + SPLIT(values[i]); + + bits[i << 1] = RGB2Y (r, g, b) >> 16; + u = RGB2U (r, g, b); + v = RGB2V (r, g, b); + } + { + SPLIT(values[i + 1]); + + bits[(i << 1) + 1] = (RGB2U (r, g, b) + u) >> 17; + bits[(i << 1) + 2] = RGB2Y (r, g, b) >> 16; + bits[(i << 1) + 3] = (RGB2V (r, g, b) + v) >> 17; + } + } + if (end & 1) { + SPLIT (values[i]); + + bits[(i << 1)] = RGB2Y (r, g, b) >> 16; + u = bits[(i << 1) + 1]; + bits[(i << 1) - 1] = (RGB2U (r, g, b) + (u << 16)) >> 17; + v = bits[(i << 1) + 3]; + bits[(i << 1) + 1] = (RGB2V (r, g, b) + (v << 16)) >> 17; + } +} + /* * 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. @@ -2994,17 +3055,7 @@ static const format_info_t accessors[] = /* YUV formats */ FORMAT_INFO (ayuv), -#if 0 - { PIXMAN_yuy2, - fetch_scanline_yuy2, fetch_scanline_generic_64, - fetch_pixel_yuy2, fetch_pixel_generic_64, - NULL, NULL }, - - { PIXMAN_yv12, - fetch_scanline_yv12, fetch_scanline_generic_64, - fetch_pixel_yv12, fetch_pixel_generic_64, - NULL, NULL }, -#endif + FORMAT_INFO (yuy2), { PIXMAN_null }, }; diff --git a/pixman/pixman.c b/pixman/pixman.c index 4c584216..2d89b4af 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -512,6 +512,7 @@ pixman_format_supported_source (pixman_format_code_t format) case PIXMAN_g1: /* YUV formats */ case PIXMAN_ayuv: + case PIXMAN_yuy2: return TRUE; default: diff --git a/pixman/pixman.h b/pixman/pixman.h index 59ede46b..e341acdc 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -689,7 +689,7 @@ typedef enum { PIXMAN_g1 = PIXMAN_FORMAT(1,PIXMAN_TYPE_GRAY,0,0,0,0), /* YUV formats */ - PIXMAN_ayuv = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,8,8,8,8) + PIXMAN_ayuv = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,8,8,8,8), // PIXMAN_i420 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) // PIXMAN_iyu1 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) // PIXMAN_iyu2 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) @@ -708,7 +708,7 @@ typedef enum { // PIXMAN_y42b = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) // PIXMAN_y444 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) // PIXMAN_yuv9 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) -// PIXMAN_yuy2 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) + PIXMAN_yuy2 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YUV_PACKED,0,8,4,4) // PIXMAN_yv12 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) // PIXMAN_yvu9 = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) // PIXMAN_yvyu = PIXMAN_FORMAT(32,PIXMAN_TYPE_YUV_PACKED,0,0,0,0) |