diff options
author | Benjamin Otte <otte@gnome.org> | 2009-12-11 18:49:46 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2010-04-07 10:38:42 +0200 |
commit | b60d75cbd4ae9ac60f88617cf290b70bcf514298 (patch) | |
tree | 12d1a62125de324a6366f71a85bf7ffff1b9fe0b | |
parent | 6d3be893630d3fa15b05f8b29944c9216885a868 (diff) |
Move allocation of pixel data into format-specific part of code
This is because planar formats have special requirements about how to
allocate planes, as pixman wants to try to keep the format-specific
requirements of Xv, FFmpeg and GStreamer when allocating the image
memory itself.
-rw-r--r-- | pixman/pixman-bits-image.c | 54 | ||||
-rw-r--r-- | pixman/pixman-format.c | 152 | ||||
-rw-r--r-- | pixman/pixman-private.h | 7 |
3 files changed, 128 insertions, 85 deletions
diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index 3df5508..f5b7b49 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -938,45 +938,6 @@ bits_image_property_changed (pixman_image_t *image) bits->store_scanline_32 = bits_image_store_scanline_32; } -static uint32_t * -create_bits (pixman_format_code_t format, - int width, - int height, - int * rowstride_bytes) -{ - int stride; - int buf_size; - int bpp; - - /* what follows is a long-winded way, avoiding any possibility of integer - * overflows, of saying: - * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); - */ - - bpp = PIXMAN_FORMAT_BPP (format); - if (pixman_multiply_overflows_int (width, bpp)) - return NULL; - - stride = width * bpp; - if (pixman_addition_overflows_int (stride, 0x1f)) - return NULL; - - stride += 0x1f; - stride >>= 5; - - stride *= sizeof (uint32_t); - - if (pixman_multiply_overflows_int (height, stride)) - return NULL; - - buf_size = height * stride; - - if (rowstride_bytes) - *rowstride_bytes = stride; - - return calloc (buf_size, 1); -} - PIXMAN_EXPORT pixman_image_t * pixman_image_create_bits (pixman_format_code_t format, int width, @@ -986,6 +947,9 @@ pixman_image_create_bits (pixman_format_code_t format, { pixman_image_t *image; uint32_t *free_me = NULL; + uint32_t *planes[PIXMAN_MAX_PLANES]; + int rowstrides[PIXMAN_MAX_PLANES]; + unsigned int num_planes; /* must be a whole number of uint32_t's */ @@ -994,14 +958,21 @@ pixman_image_create_bits (pixman_format_code_t format, return_val_if_fail (PIXMAN_FORMAT_BPP (format) >= PIXMAN_FORMAT_DEPTH (format), NULL); + num_planes = pixman_format_num_planes (format); if (!bits && width && height) { - free_me = bits = create_bits (format, width, height, &rowstride_bytes); + free_me = bits = _pixman_format_alloc_bits (format, width, height, planes, rowstrides); if (!bits) return NULL; } + else + { + return_val_if_fail (num_planes == 1, NULL); + planes[0] = bits; + rowstrides[0] = rowstride_bytes; + } - image = pixman_image_create_planar (format, width, height, 1, &bits, &rowstride_bytes); + image = pixman_image_create_planar (format, width, height, num_planes, planes, rowstrides); if (!image) { @@ -1043,6 +1014,7 @@ pixman_image_create_planar (pixman_format_code_t format, image->bits.height = height; image->bits.read_func = NULL; image->bits.write_func = NULL; + image->bits.free_me = NULL; /* XXX: backwards compat: store plane 0 in the old fields, too */ image->bits.bits = bits[0]; diff --git a/pixman/pixman-format.c b/pixman/pixman-format.c index bb31212..6d091e8 100644 --- a/pixman/pixman-format.c +++ b/pixman/pixman-format.c @@ -29,71 +29,119 @@ #include "pixman-private.h" +#include <stdlib.h> + +static uint32_t * +alloc_bits (pixman_format_code_t format, + int width, + int height, + uint32_t ** bits, + int * rowstrides_bytes) +{ + int stride; + int buf_size; + int bpp; + + /* what follows is a long-winded way, avoiding any possibility of integer + * overflows, of saying: + * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t); + */ + + bpp = PIXMAN_FORMAT_BPP (format); + assert (bpp > 0); + if (pixman_multiply_overflows_int (width, bpp)) + return NULL; + + stride = width * bpp; + if (pixman_addition_overflows_int (stride, 0x1f)) + return NULL; + + stride += 0x1f; + stride >>= 5; + + stride *= sizeof (uint32_t); + + if (pixman_multiply_overflows_int (height, stride)) + return NULL; + + buf_size = height * stride; + + bits[0] = calloc (buf_size, 1); + rowstrides_bytes[0] = stride; + + return bits[0]; +} + typedef struct { pixman_format_code_t format; pixman_bool_t supported_source; pixman_bool_t supported_destination; unsigned int num_planes; + uint32_t * (* alloc_bits) (pixman_format_code_t format, + int width, + int height, + uint32_t ** bits, + int * rowstrides_bytes); } format_info_t; static const format_info_t format_infos[] = { - { PIXMAN_a2b10g10r10, TRUE, TRUE, 1 }, - { PIXMAN_x2b10g10r10, TRUE, TRUE, 1 }, - { PIXMAN_a2r10g10b10, TRUE, TRUE, 1 }, - { PIXMAN_x2r10g10b10, TRUE, TRUE, 1 }, - { PIXMAN_a8r8g8b8, TRUE, TRUE, 1 }, - { PIXMAN_x8r8g8b8, TRUE, TRUE, 1 }, - { PIXMAN_a8b8g8r8, TRUE, TRUE, 1 }, - { PIXMAN_x8b8g8r8, TRUE, TRUE, 1 }, - { PIXMAN_b8g8r8a8, TRUE, TRUE, 1 }, - { PIXMAN_b8g8r8x8, TRUE, TRUE, 1 }, - { PIXMAN_r8g8b8, TRUE, TRUE, 1 }, - { PIXMAN_b8g8r8, TRUE, TRUE, 1 }, - { PIXMAN_r5g6b5, TRUE, TRUE, 1 }, - { PIXMAN_b5g6r5, TRUE, TRUE, 1 }, + { PIXMAN_a2b10g10r10, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x2b10g10r10, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a2r10g10b10, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x2r10g10b10, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a8r8g8b8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x8r8g8b8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a8b8g8r8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x8b8g8r8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_b8g8r8a8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_b8g8r8x8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_r8g8b8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_b8g8r8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_r5g6b5, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_b5g6r5, TRUE, TRUE, 1, alloc_bits }, /* 16 bpp formats */ - { PIXMAN_a1r5g5b5, TRUE, TRUE, 1 }, - { PIXMAN_x1r5g5b5, TRUE, TRUE, 1 }, - { PIXMAN_a1b5g5r5, TRUE, TRUE, 1 }, - { PIXMAN_x1b5g5r5, TRUE, TRUE, 1 }, - { PIXMAN_a4r4g4b4, TRUE, TRUE, 1 }, - { PIXMAN_x4r4g4b4, TRUE, TRUE, 1 }, - { PIXMAN_a4b4g4r4, TRUE, TRUE, 1 }, - { PIXMAN_x4b4g4r4, TRUE, TRUE, 1 }, + { PIXMAN_a1r5g5b5, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x1r5g5b5, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a1b5g5r5, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x1b5g5r5, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a4r4g4b4, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x4r4g4b4, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a4b4g4r4, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x4b4g4r4, TRUE, TRUE, 1, alloc_bits }, /* 8bpp formats */ - { PIXMAN_a8, TRUE, TRUE, 1 }, - { PIXMAN_r3g3b2, TRUE, TRUE, 1 }, - { PIXMAN_b2g3r3, TRUE, TRUE, 1 }, - { PIXMAN_a2r2g2b2, TRUE, TRUE, 1 }, - { PIXMAN_a2b2g2r2, TRUE, TRUE, 1 }, - { PIXMAN_c8, TRUE, TRUE, 1 }, - { PIXMAN_g8, TRUE, TRUE, 1 }, - { PIXMAN_x4a4, TRUE, TRUE, 1 }, + { PIXMAN_a8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_r3g3b2, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_b2g3r3, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a2r2g2b2, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a2b2g2r2, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_c8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_g8, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x4a4, TRUE, TRUE, 1, alloc_bits }, /* Collides with PIXMAN_c8 - { PIXMAN_x4c4, TRUE, TRUE, 1 }, + { PIXMAN_x4c4, TRUE, TRUE, 1, alloc_bits }, */ /* Collides with PIXMAN_g8 - { PIXMAN_x4g4, TRUE, TRUE, 1 }, + { PIXMAN_x4g4, TRUE, TRUE, 1, alloc_bits }, */ /* 4bpp formats */ - { PIXMAN_a4, TRUE, TRUE, 1 }, - { PIXMAN_r1g2b1, TRUE, TRUE, 1 }, - { PIXMAN_b1g2r1, TRUE, TRUE, 1 }, - { PIXMAN_a1r1g1b1, TRUE, TRUE, 1 }, - { PIXMAN_a1b1g1r1, TRUE, TRUE, 1 }, - { PIXMAN_c4, TRUE, TRUE, 1 }, - { PIXMAN_g4, TRUE, TRUE, 1 }, + { PIXMAN_a4, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_r1g2b1, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_b1g2r1, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a1r1g1b1, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a1b1g1r1, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_c4, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_g4, TRUE, TRUE, 1, alloc_bits }, /* 1bpp formats */ - { PIXMAN_a1, TRUE, TRUE, 1 }, - { PIXMAN_g1, TRUE, TRUE, 1 }, + { PIXMAN_a1, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_g1, TRUE, TRUE, 1, alloc_bits }, /* YUV formats */ - { PIXMAN_yuy2, TRUE, FALSE, 1 }, - { PIXMAN_yv12, TRUE, FALSE, 1 }, + { PIXMAN_yuy2, TRUE, FALSE, 1, alloc_bits }, + { PIXMAN_yv12, TRUE, FALSE, 1, alloc_bits }, }; /* default values for "invalid" at the end */ static const format_info_t invalid_format = - { 0, FALSE, FALSE, 0 }; + { 0, FALSE, FALSE, 0, NULL }; static const format_info_t * @@ -111,6 +159,22 @@ _get_format_info (pixman_format_code_t format) return &invalid_format; } +uint32_t * +_pixman_format_alloc_bits (pixman_format_code_t format, + int width, + int height, + uint32_t ** bits, + int * rowstrides) +{ + static const format_info_t *info; + + info = _get_format_info (format); + if (info->alloc_bits == NULL) + return NULL; + + return info->alloc_bits (format, width, height, bits, rowstrides); +} + /** * pixman_format_supported_source: * @format: A pixman_format_code_t format diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index b400b55..d66c343 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -280,6 +280,13 @@ _pixman_image_store_scanline_64 (bits_image_t * image, int width, const uint32_t *buffer); +uint32_t * +_pixman_format_alloc_bits (pixman_format_code_t format, + int width, + int height, + uint32_t **bits, + int *rowstrides); + pixman_image_t * _pixman_image_allocate (void); |