summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2009-09-18 11:04:37 +0200
committerSøren Sandmann Pedersen <sandmann@redhat.com>2009-11-20 20:23:55 +0100
commit4e13f9235081dc7b6cacd8706dc4b7a2a8436056 (patch)
tree96473f41510556ffc7bba9f990331eae3d2ab02f
parent7bbd76d9e717921b6198d152840a22093128fd6c (diff)
(Re)add YUY2
Optimized to conert chroma only once when reading adjacent pixels. Supports writing, too.
-rw-r--r--pixman/pixman-access.c165
-rw-r--r--pixman/pixman.c1
-rw-r--r--pixman/pixman.h4
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)