summaryrefslogtreecommitdiff
path: root/pixman/pixman-format.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/pixman-format.c')
-rw-r--r--pixman/pixman-format.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/pixman/pixman-format.c b/pixman/pixman-format.c
index f89c7cf..7a8a93c 100644
--- a/pixman/pixman-format.c
+++ b/pixman/pixman-format.c
@@ -131,6 +131,43 @@ alloc_y422 (pixman_format_code_t format,
return bits[0];
}
+static uint32_t *
+alloc_y420 (pixman_format_code_t format,
+ int width,
+ int height,
+ uint32_t ** bits,
+ int * rowstrides_bytes)
+{
+ int y_stride, uv_stride, y_height, uv_height, y_size, uv_size;
+
+ if (pixman_addition_overflows_int (width, 7) ||
+ pixman_addition_overflows_int (height, 1))
+ return NULL;
+
+ y_stride = ROUND_UP_4 (width);
+ uv_stride = ROUND_UP_8 (width) / 2;
+ y_height = ROUND_UP_2 (height);
+ uv_height = ROUND_UP_2 (height) / 2;
+
+ if (pixman_multiply_overflows_int (y_stride, y_height))
+ return NULL;
+
+ y_size = y_stride * y_height;
+ uv_size = uv_stride * uv_height;
+
+ if (pixman_addition_overflows_int (y_size, 2 * uv_size))
+ return NULL;
+
+ bits[0] = calloc (y_size + 2 * uv_size, 1);
+ bits[1] = bits[0] + y_size;
+ bits[2] = bits[1] + uv_size;
+ rowstrides_bytes[0] = y_stride;
+ rowstrides_bytes[1] = uv_stride;
+ rowstrides_bytes[2] = uv_stride;
+
+ return bits[0];
+}
+
typedef struct {
pixman_format_code_t format;
pixman_bool_t supported_source;
@@ -200,6 +237,7 @@ static const format_info_t format_infos[] = {
/* planar formats */
{ PIXMAN_y444, TRUE, TRUE, FALSE, 3, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_y444 },
{ PIXMAN_y422, TRUE, TRUE, FALSE, 3, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_y422 },
+ { PIXMAN_y420, TRUE, TRUE, FALSE, 3, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_y420 },
/* packed formats */
{ PIXMAN_yuy2, TRUE, TRUE, FALSE, 1, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_bits },
{ PIXMAN_yvyu, TRUE, TRUE, FALSE, 1, PIXMAN_COLOR_SPACE_YCBCR_SD, alloc_bits },