summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Otte <otte@gnome.org>2009-12-11 18:49:46 +0100
committerBenjamin Otte <otte@redhat.com>2010-04-07 10:38:42 +0200
commitb60d75cbd4ae9ac60f88617cf290b70bcf514298 (patch)
tree12d1a62125de324a6366f71a85bf7ffff1b9fe0b
parent6d3be893630d3fa15b05f8b29944c9216885a868 (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.c54
-rw-r--r--pixman/pixman-format.c152
-rw-r--r--pixman/pixman-private.h7
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);