summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@redhat.com>2010-02-24 22:46:11 +0100
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-07-07 10:23:04 -0400
commit698e3a35b7351654d5227a90eb9c58b3a513c2b5 (patch)
treeee6c8f435382dbf2ac457cc09284c8f851027683
parent63ec65fbee685c8e3cf882abb69a31072b92e556 (diff)
Add packed YUV formats
YUY2, YVYU, UYVY and VYUY
-rw-r--r--pixman/pixman-access.c202
-rw-r--r--pixman/pixman-format.c6
-rw-r--r--pixman/pixman.h7
3 files changed, 176 insertions, 39 deletions
diff --git a/pixman/pixman-access.c b/pixman/pixman-access.c
index 87eb8cc0..c1713e5a 100644
--- a/pixman/pixman-access.c
+++ b/pixman/pixman-access.c
@@ -1107,24 +1107,70 @@ fetch_scanline_yuy2 (pixman_image_t *image,
for (i = 0; i < width; i++)
{
- int16_t y, u, v;
- int32_t r, g, b;
-
- 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;
-
- /* 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++ = 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);
+ (((uint8_t *) bits)[(x + i) << 1] << 16) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] << 8) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] );
+ }
+}
+
+static void
+fetch_scanline_yvyu (pixman_image_t *image,
+ int x,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t *mask)
+{
+ const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
+ int i;
+
+ for (i = 0; i < width; i++)
+ {
+ *buffer++ = 0xff000000 |
+ (((uint8_t *) bits)[(x + i) << 1] << 16) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) + 3] << 8) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) + 1] );
+ }
+}
+
+static void
+fetch_scanline_uyvy (pixman_image_t *image,
+ int x,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t *mask)
+{
+ const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
+ int i;
+
+ for (i = 0; i < width; i++)
+ {
+ *buffer++ = 0xff000000 |
+ (((uint8_t *) bits)[ ((x + i) << 1) + 1] << 16) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) ] << 8) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) + 2] );
+ }
+}
+
+static void
+fetch_scanline_vyuy (pixman_image_t *image,
+ int x,
+ int line,
+ int width,
+ uint32_t * buffer,
+ const uint32_t *mask)
+{
+ const uint32_t *bits = image->bits.bits + image->bits.rowstride * line;
+ int i;
+
+ for (i = 0; i < width; i++)
+ {
+ *buffer++ = 0xff000000 |
+ (((uint8_t *) bits)[ ((x + i) << 1) + 1] << 16) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) + 2] << 8) |
+ (((uint8_t *) bits)[(((x + i) << 1) & - 4) ] );
}
}
@@ -1827,26 +1873,49 @@ fetch_pixel_yuy2 (bits_image_t *image,
{
const uint32_t *bits = image->bits + image->rowstride * line;
- 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;
+ return 0xff000000 |
+ (((uint8_t *) bits)[ offset << 1 ] << 16) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) + 1] << 8) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) + 3] );
+}
+
+static uint32_t
+fetch_pixel_yvyu (bits_image_t *image,
+ int offset,
+ int line)
+{
+ const uint32_t *bits = image->bits + image->rowstride * line;
- /* G = 1.164(Y - 16) - 0.813(V - 128) - 0.391(U - 128) */
- g = 0x012b27 * y - 0x00d0f2 * v - 0x00647e * u;
+ return 0xff000000 |
+ (((uint8_t *) bits)[ offset << 1 ] << 16) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) + 3] << 8) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) + 1] );
+}
+
+static uint32_t
+fetch_pixel_uyvy (bits_image_t *image,
+ int offset,
+ int line)
+{
+ const uint32_t *bits = image->bits + image->rowstride * line;
- /* B = 1.164(Y - 16) + 2.018(U - 128) */
- b = 0x012b27 * y + 0x0206a2 * u;
+ return 0xff000000 |
+ (((uint8_t *) bits)[ (offset << 1) + 1] << 16) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) ] << 8) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) + 2] );
+}
+
+static uint32_t
+fetch_pixel_vyuy (bits_image_t *image,
+ int offset,
+ int line)
+{
+ const uint32_t *bits = image->bits + image->rowstride * line;
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);
+ (((uint8_t *) bits)[ (offset << 1) + 1] << 16) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) + 2] << 8) |
+ (((uint8_t *) bits)[((offset << 1) & - 4) ] );
}
static uint32_t
@@ -2798,6 +2867,63 @@ store_scanline_y444 (bits_image_t * image,
}
}
+#define SUBSAMPLED(name,Y1,U,Y2,V) \
+static void \
+store_scanline_ ## name (bits_image_t * image, \
+ int x, \
+ int y, \
+ int width, \
+ const uint32_t *values) \
+{ \
+ uint8_t *bits = (uint8_t *) (image->bits + image->rowstride * y + x / 2); \
+ int i; \
+\
+ if (x & 1) \
+ { \
+ bits[Y2] = values[0] >> 16; \
+ bits[U ] = (bits[U] + ((values[0] >> 8) & 0xff)) >> 1; \
+ bits[V ] = (bits[V] + ( values[0] & 0xff)) >> 1; \
+ width--; \
+ x++; \
+ values++; \
+ bits += 4; \
+ } \
+ if (width & 1) \
+ { \
+ pixman_bool_t last_pixel = (x + width == image->width); \
+\
+ width--; \
+\
+ if (last_pixel) \
+ { \
+ bits[2 * width + Y1] = values[width] >> 16; \
+ bits[2 * width + U ] = values[width] >> 8; \
+ bits[2 * width + V ] = values[width]; \
+ } \
+ else \
+ { \
+ bits[2 * width + Y1] = values[width] >> 16; \
+ bits[2 * width + U ] = ((values[width] >> 8) + bits[2 * width + U]) >> 1; \
+ bits[2 * width + V ] = ((values[width] ) + bits[2 * width + V]) >> 1; \
+ } \
+ } \
+\
+ for (i = 0; i < width; i += 2) \
+ { \
+ bits[Y1] = values[i] >> 16; \
+ bits[Y2] = values[i + 1] >> 16; \
+ bits[U ] = ((values[i] & 0xff00) + (values[i + 1] & 0xff00)) >> 9; \
+ bits[V ] = ((values[i] & 0x00ff) + (values[i + 1] & 0x00ff)) >> 1; \
+\
+ bits += 4; \
+ } \
+}
+
+SUBSAMPLED(yuy2, 0, 1, 2, 3)
+SUBSAMPLED(yvyu, 0, 3, 2, 1)
+SUBSAMPLED(uyvy, 1, 0, 3, 2)
+SUBSAMPLED(vyuy, 1, 2, 3, 0)
+
/*
* 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.
@@ -2995,11 +3121,13 @@ static const format_info_t accessors[] =
/* planar formats */
FORMAT_INFO (y444),
+/* packed formats */
+ FORMAT_INFO (yuy2),
+ FORMAT_INFO (yvyu),
+ FORMAT_INFO (uyvy),
+ FORMAT_INFO (vyuy),
+
/* YUV formats */
- { 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,
diff --git a/pixman/pixman-format.c b/pixman/pixman-format.c
index 979e375b..b9aeed75 100644
--- a/pixman/pixman-format.c
+++ b/pixman/pixman-format.c
@@ -169,8 +169,12 @@ static const format_info_t format_infos[] = {
{ PIXMAN_g1, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits },
/* planar formats */
{ PIXMAN_y444, TRUE, TRUE, 3, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_y444 },
+ /* packed formats */
+ { PIXMAN_yuy2, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_bits },
+ { PIXMAN_yvyu, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_bits },
+ { PIXMAN_uyvy, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_bits },
+ { PIXMAN_vyuy, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_bits },
/* YUV formats */
- { PIXMAN_yuy2, TRUE, FALSE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits },
{ PIXMAN_yv12, TRUE, FALSE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }
};
diff --git a/pixman/pixman.h b/pixman/pixman.h
index c6301d78..5d86084d 100644
--- a/pixman/pixman.h
+++ b/pixman/pixman.h
@@ -726,8 +726,13 @@ typedef enum {
/* planar formats */
PIXMAN_y444 = PIXMAN_FORMAT(12,PIXMAN_TYPE_PLANAR,0,0,0,1),
+/* packed formats */
+ PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_PACKED,0,0,0,0),
+ PIXMAN_yvyu = PIXMAN_FORMAT(16,PIXMAN_TYPE_PACKED,0,0,0,1),
+ PIXMAN_uyvy = PIXMAN_FORMAT(16,PIXMAN_TYPE_PACKED,0,0,0,2),
+ PIXMAN_vyuy = PIXMAN_FORMAT(16,PIXMAN_TYPE_PACKED,0,0,0,3),
+
/*deprecated */
- PIXMAN_yuy2 = PIXMAN_FORMAT(16,PIXMAN_TYPE_YUY2,0,0,0,0),
PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0)
} pixman_format_code_t;