diff options
author | Benjamin Otte <otte@gnome.org> | 2009-12-14 15:48:47 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2010-04-07 10:38:42 +0200 |
commit | dec875bad712cd0f39cce903ce8cd4939e0417f8 (patch) | |
tree | 8d28362a848d38167ec57c3f6576b69e1c1f2127 | |
parent | b60d75cbd4ae9ac60f88617cf290b70bcf514298 (diff) |
Add pixman_color_space_t
This differentiates pixel data from just having a format code to having
a pixel layout - pixman_format_code_t - and color space -
pixman_color_space_t.
No new formats were added, only the option to create unmultiplied ARGB
images exists now.
In the future the general code path will look like this:
Each colorspace provides a "canonical" format. pixman-access.c will
provide accessors to read/write data from/to the image representation to
the canonical format. Additional functions that convert between
different color spaces will be added. These will be called from the
generic store/fetch paths, so the accessors do not need to care about
the color space.
As a first step, compositing will still be done in ARGB, so the general
path will look like this:
src => fetch => convert \
> combine => convert => store => dest
dest => fetch => convert /
Benefits of this approach for adding more formats:
- Minimal changes required to current code.
With a simple check of the color space, all optimizations can continue
working with a minimal performance impact. Even in the general case
optimized store/fetch functions can be used.
- Ease of optimization for common paths
Common cases can be optimized easily. For example, Pixel-aligned
rectangular fills with PIXMAN_OP_SRC and the same color space can
be done with:
src => fetch => store => dest
and not a lot of code is required to do this.
- Extensibility
More color spaces can easily be added later, possibly even making use
of the same accessors for data storage, i.e. linear RGB, more color
matrices for YCbCr or even CMYK.
-rw-r--r-- | pixman/Makefile.am | 2 | ||||
-rw-r--r-- | pixman/pixman-bits-image.c | 43 | ||||
-rw-r--r-- | pixman/pixman-color-space-private.h | 50 | ||||
-rw-r--r-- | pixman/pixman-color-space.c | 185 | ||||
-rw-r--r-- | pixman/pixman-format.c | 95 | ||||
-rw-r--r-- | pixman/pixman-general.c | 39 | ||||
-rw-r--r-- | pixman/pixman-image.c | 29 | ||||
-rw-r--r-- | pixman/pixman-private.h | 23 | ||||
-rw-r--r-- | pixman/pixman.c | 57 | ||||
-rw-r--r-- | pixman/pixman.h | 9 |
10 files changed, 441 insertions, 91 deletions
diff --git a/pixman/Makefile.am b/pixman/Makefile.am index a52a9e6..0b3e40d 100644 --- a/pixman/Makefile.am +++ b/pixman/Makefile.am @@ -15,6 +15,8 @@ libpixman_1_la_SOURCES = \ pixman-private.h \ pixman-image.c \ pixman-implementation.c \ + pixman-color-space.c \ + pixman-color-space-private.h \ pixman-combine32.c \ pixman-combine32.h \ pixman-combine64.c \ diff --git a/pixman/pixman-bits-image.c b/pixman/pixman-bits-image.c index f5b7b49..a2c1a51 100644 --- a/pixman/pixman-bits-image.c +++ b/pixman/pixman-bits-image.c @@ -32,7 +32,9 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> + #include "pixman-private.h" +#include "pixman-color-space-private.h" #include "pixman-combine32.h" /* Store functions */ @@ -972,7 +974,10 @@ pixman_image_create_bits (pixman_format_code_t format, rowstrides[0] = rowstride_bytes; } - image = pixman_image_create_planar (format, width, height, num_planes, planes, rowstrides); + image = pixman_image_create_planar (format, + _pixman_format_get_default_color_space (format), + width, height, + num_planes, planes, rowstrides); if (!image) { @@ -986,22 +991,37 @@ pixman_image_create_bits (pixman_format_code_t format, return image; } +static pixman_color_space_t +_pixman_color_space_optimize (pixman_format_code_t format, + pixman_color_space_t color_space) +{ + if (color_space == PIXMAN_COLOR_SPACE_ARGB_UNMULTIPLIED && + !PIXMAN_FORMAT_A (format)) + return PIXMAN_COLOR_SPACE_ARGB; + + return color_space; +} + PIXMAN_EXPORT pixman_image_t * -pixman_image_create_planar (pixman_format_code_t format, - int width, - int height, - unsigned int num_planes, - uint32_t ** bits, - int * rowstrides_bytes) +pixman_image_create_planar (pixman_format_code_t format, + pixman_color_space_t color_space, + int width, + int height, + unsigned int num_planes, + uint32_t ** bits, + int * rowstrides_bytes) { pixman_image_t *image; unsigned int plane; - return_val_if_fail (bits == NULL || rowstrides_bytes == NULL, NULL); + return_val_if_fail (bits != NULL && rowstrides_bytes != NULL, NULL); return_val_if_fail (num_planes == pixman_format_num_planes (format), NULL); - for (plane = 0; plane < num_planes; plane++) { - return_val_if_fail (bits[plane] == NULL, NULL); - return_val_if_fail ((rowstrides_bytes[plane] % sizeof (uint32_t)) == 0, NULL); + if (width && height) + { + for (plane = 0; plane < num_planes; plane++) { + return_val_if_fail (bits[plane] != NULL, NULL); + return_val_if_fail ((rowstrides_bytes[plane] % sizeof (uint32_t)) == 0, NULL); + } } image = _pixman_image_allocate (); @@ -1010,6 +1030,7 @@ pixman_image_create_planar (pixman_format_code_t format, image->type = BITS; image->bits.format = format; + image->bits.color_space = _pixman_color_space_optimize (format, color_space); image->bits.width = width; image->bits.height = height; image->bits.read_func = NULL; diff --git a/pixman/pixman-color-space-private.h b/pixman/pixman-color-space-private.h new file mode 100644 index 0000000..383bebd --- /dev/null +++ b/pixman/pixman-color-space-private.h @@ -0,0 +1,50 @@ +/* + * Copyright © 2010 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef PIXMAN_COLOR_SPACE_PRIVATE_H +#define PIXMAN_COLOR_SPACE_PRIVATE_H + +#include "pixman-private.h" + +void +_pixman_color_space_to_argb_32 (pixman_color_space_t color_space, + uint32_t * values, + int width); + +void +_pixman_color_space_from_argb_32 (pixman_color_space_t color_space, + uint32_t * values, + int width); + +void +_pixman_color_space_to_argb_64 (pixman_color_space_t color_space, + uint64_t * values, + int width); + +void +_pixman_color_space_from_argb_64 (pixman_color_space_t color_space, + uint64_t * values, + int width); + +#endif /* PIXMAN_COLOR_SPACE_PRIVATE_H */ diff --git a/pixman/pixman-color-space.c b/pixman/pixman-color-space.c new file mode 100644 index 0000000..1046978 --- /dev/null +++ b/pixman/pixman-color-space.c @@ -0,0 +1,185 @@ +/* + * Copyright © 2010 Red Hat, Inc. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * Author: Benjamin Otte <otte@gnome.org> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "pixman-color-space-private.h" + +#include "pixman-private.h" + +/* uint32_t versions */ + +static uint32_t +premultiply_32 (uint32_t value) +{ + uint32_t alpha = value >> 24; + return (value & 0xff000000) | + (((value & 0x00ff0000) * alpha / 255) & 0x00ff0000) | + (((value & 0x0000ff00) * alpha / 255) & 0x0000ff00) | + (((value & 0x000000ff) * alpha / 255) & 0x000000ff); +} + +static uint32_t +unpremultiply_32 (uint32_t value) +{ + uint32_t alpha = value >> 24; + + if (alpha == 0) + return 0; + + return (value & 0xff000000) | + ((((value & 0x00ff0000) * 255 + 127) / alpha) & 0x00ff0000) | + ((((value & 0x0000ff00) * 255 + 127) / alpha) & 0x0000ff00) | + ((((value & 0x000000ff) * 255 + 127) / alpha) & 0x000000ff); +} + +void +_pixman_color_space_to_argb_32 (pixman_color_space_t color_space, + uint32_t * values, + int width) +{ + int i; + + switch (color_space) + { + case PIXMAN_COLOR_SPACE_ARGB: + break; + case PIXMAN_COLOR_SPACE_ARGB_UNMULTIPLIED: + for (i = 0; i < width; i++) + values[i] = premultiply_32 (values[i]); + break; + case PIXMAN_COLOR_SPACE_YCBCR_HD: + case PIXMAN_COLOR_SPACE_YCBCR_SD: + case PIXMAN_COLOR_SPACE_YCBCR_JPEG: + /* XXX */ + break; + default: + break; + } +} + +void +_pixman_color_space_from_argb_32 (pixman_color_space_t color_space, + uint32_t * values, + int width) +{ + int i; + + switch (color_space) + { + case PIXMAN_COLOR_SPACE_ARGB: + break; + case PIXMAN_COLOR_SPACE_ARGB_UNMULTIPLIED: + for (i = 0; i < width; i++) + values[i] = unpremultiply_32 (values[i]); + break; + case PIXMAN_COLOR_SPACE_YCBCR_HD: + case PIXMAN_COLOR_SPACE_YCBCR_SD: + case PIXMAN_COLOR_SPACE_YCBCR_JPEG: + /* XXX */ + break; + default: + break; + } +} + +/* uint64_t versions */ + +static uint64_t +premultiply_64 (uint64_t value) +{ + uint32_t alpha = value >> 48; + return (value & 0xffff000000000000ULL) | + (((value & 0x0000ffff00000000ULL) * alpha / 65535) & 0x0000ffff00000000ULL) | + (((value & 0x00000000ffff0000ULL) * alpha / 65535) & 0x00000000ffff0000ULL) | + (((value & 0x000000000000ffffULL) * alpha / 65535) & 0x000000000000ffffULL); +} + +static uint32_t +unpremultiply_64 (uint64_t value) +{ + uint32_t alpha = value >> 48; + + if (alpha == 0) + return 0; + + return (value & 0xffff000000000000ULL) | + ((((value & 0x0000ffff00000000ULL) * 255 + 127) / alpha) & 0x0000ffff00000000ULL) | + ((((value & 0x00000000ffff0000ULL) * 255 + 127) / alpha) & 0x00000000ffff0000ULL) | + ((((value & 0x000000000000ffffULL) * 255 + 127) / alpha) & 0x000000000000ffffULL); +} + +void +_pixman_color_space_to_argb_64 (pixman_color_space_t color_space, + uint64_t * values, + int width) +{ + int i; + + switch (color_space) + { + case PIXMAN_COLOR_SPACE_ARGB: + break; + case PIXMAN_COLOR_SPACE_ARGB_UNMULTIPLIED: + for (i = 0; i < width; i++) + values[i] = premultiply_64 (values[i]); + break; + case PIXMAN_COLOR_SPACE_YCBCR_HD: + case PIXMAN_COLOR_SPACE_YCBCR_SD: + case PIXMAN_COLOR_SPACE_YCBCR_JPEG: + /* XXX */ + break; + default: + break; + } +} + +void +_pixman_color_space_from_argb_64 (pixman_color_space_t color_space, + uint64_t * values, + int width) +{ + int i; + + switch (color_space) + { + case PIXMAN_COLOR_SPACE_ARGB: + break; + case PIXMAN_COLOR_SPACE_ARGB_UNMULTIPLIED: + for (i = 0; i < width; i++) + values[i] = unpremultiply_64 (values[i]); + break; + case PIXMAN_COLOR_SPACE_YCBCR_HD: + case PIXMAN_COLOR_SPACE_YCBCR_SD: + case PIXMAN_COLOR_SPACE_YCBCR_JPEG: + /* XXX */ + break; + default: + break; + } +} diff --git a/pixman/pixman-format.c b/pixman/pixman-format.c index 6d091e8..46368e6 100644 --- a/pixman/pixman-format.c +++ b/pixman/pixman-format.c @@ -77,6 +77,7 @@ typedef struct { pixman_bool_t supported_source; pixman_bool_t supported_destination; unsigned int num_planes; + pixman_color_space_t default_color_space; uint32_t * (* alloc_bits) (pixman_format_code_t format, int width, int height, @@ -85,63 +86,63 @@ typedef struct { } format_info_t; static const format_info_t format_infos[] = { - { 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 }, + { PIXMAN_a2b10g10r10, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x2b10g10r10, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a2r10g10b10, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x2r10g10b10, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a8r8g8b8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x8r8g8b8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a8b8g8r8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x8b8g8r8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_b8g8r8a8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_b8g8r8x8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_r8g8b8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_b8g8r8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_r5g6b5, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_b5g6r5, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, /* 16 bpp formats */ - { 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 }, + { PIXMAN_a1r5g5b5, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x1r5g5b5, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a1b5g5r5, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x1b5g5r5, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a4r4g4b4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x4r4g4b4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a4b4g4r4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x4b4g4r4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, /* 8bpp formats */ - { 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 }, + { PIXMAN_a8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_r3g3b2, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_b2g3r3, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a2r2g2b2, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a2b2g2r2, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_c8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_g8, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_x4a4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, /* Collides with PIXMAN_c8 - { PIXMAN_x4c4, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x4c4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, */ /* Collides with PIXMAN_g8 - { PIXMAN_x4g4, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_x4g4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, */ /* 4bpp formats */ - { 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 }, + { PIXMAN_a4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_r1g2b1, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_b1g2r1, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a1r1g1b1, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_a1b1g1r1, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_c4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_g4, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, /* 1bpp formats */ - { PIXMAN_a1, TRUE, TRUE, 1, alloc_bits }, - { PIXMAN_g1, TRUE, TRUE, 1, alloc_bits }, + { PIXMAN_a1, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_g1, TRUE, TRUE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, /* YUV formats */ - { PIXMAN_yuy2, TRUE, FALSE, 1, alloc_bits }, - { PIXMAN_yv12, TRUE, FALSE, 1, alloc_bits }, + { PIXMAN_yuy2, TRUE, FALSE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, + { PIXMAN_yv12, TRUE, FALSE, 1, PIXMAN_COLOR_SPACE_ARGB, alloc_bits }, }; /* default values for "invalid" at the end */ static const format_info_t invalid_format = - { 0, FALSE, FALSE, 0, NULL }; + { 0, FALSE, FALSE, 0, PIXMAN_COLOR_SPACE_ARGB, NULL }; static const format_info_t * @@ -175,6 +176,12 @@ _pixman_format_alloc_bits (pixman_format_code_t format, return info->alloc_bits (format, width, height, bits, rowstrides); } +pixman_color_space_t +_pixman_format_get_default_color_space (pixman_format_code_t format) +{ + return _get_format_info (format)->default_color_space; +} + /** * pixman_format_supported_source: * @format: A pixman_format_code_t format diff --git a/pixman/pixman-general.c b/pixman/pixman-general.c index bddf79a..1d18133 100644 --- a/pixman/pixman-general.c +++ b/pixman/pixman-general.c @@ -36,8 +36,8 @@ #include <stdlib.h> #include <string.h> #include "pixman-private.h" +#include "pixman-color-space-private.h" #include "pixman-combine32.h" -#include "pixman-private.h" #define SCANLINE_BUFFER_LENGTH 8192 @@ -106,29 +106,32 @@ general_composite_rect (pixman_implementation_t *imp, if (op == PIXMAN_OP_CLEAR) fetch_src = NULL; - else if (wide) - fetch_src = _pixman_image_get_scanline_64; + else if (src->common.type == BITS && + src->bits.color_space != PIXMAN_COLOR_SPACE_ARGB) + fetch_src = wide ? _pixman_image_get_scanline_64_argb : _pixman_image_get_scanline_32_argb; else - fetch_src = _pixman_image_get_scanline_32; + fetch_src = wide ? _pixman_image_get_scanline_64 : _pixman_image_get_scanline_32; if (!mask || op == PIXMAN_OP_CLEAR) fetch_mask = NULL; - else if (wide) - fetch_mask = _pixman_image_get_scanline_64; + else if (mask->common.type == BITS && + mask->bits.color_space != PIXMAN_COLOR_SPACE_ARGB) + fetch_mask = wide ? _pixman_image_get_scanline_64_argb : _pixman_image_get_scanline_32_argb; else - fetch_mask = _pixman_image_get_scanline_32; + fetch_mask = wide ? _pixman_image_get_scanline_64 : _pixman_image_get_scanline_32; if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC) fetch_dest = NULL; - else if (wide) - fetch_dest = _pixman_image_get_scanline_64; + else if (dest->common.type == BITS && + dest->bits.color_space != PIXMAN_COLOR_SPACE_ARGB) + fetch_dest = wide ? _pixman_image_get_scanline_64_argb : _pixman_image_get_scanline_32_argb; else - fetch_dest = _pixman_image_get_scanline_32; + fetch_dest = wide ? _pixman_image_get_scanline_64 : _pixman_image_get_scanline_32; if (wide) - store = _pixman_image_store_scanline_64; + store = _pixman_image_store_scanline_64; else - store = _pixman_image_store_scanline_32; + store = _pixman_image_store_scanline_32; /* Skip the store step and composite directly into the * destination if the output format of the compose func matches @@ -143,14 +146,15 @@ general_composite_rect (pixman_implementation_t *imp, (op == PIXMAN_OP_OVER || op == PIXMAN_OP_ADD || op == PIXMAN_OP_SRC || - op == PIXMAN_OP_CLEAR || + op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_IN_REVERSE || op == PIXMAN_OP_OUT_REVERSE || op == PIXMAN_OP_DST))) { if (!wide && - !dest->common.alpha_map && - !dest->bits.write_func) + !dest->common.alpha_map && + !dest->bits.write_func && + dest->bits.color_space == PIXMAN_COLOR_SPACE_ARGB) { store = NULL; } @@ -247,6 +251,11 @@ general_composite_rect (pixman_implementation_t *imp, (void *)mask_buffer, width); + if (wide) + _pixman_color_space_from_argb_64 (dest->bits.color_space, (uint64_t *) dest_buffer, width); + else + _pixman_color_space_from_argb_32 (dest->bits.color_space, (uint32_t *) dest_buffer, width); + /* write back */ store (&(dest->bits), dest_x, dest_y + i, width, (void *)dest_buffer); diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index 6b878c3..ca06acf 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -30,6 +30,7 @@ #include <assert.h> #include "pixman-private.h" +#include "pixman-color-space-private.h" #include "pixman-combine32.h" pixman_bool_t @@ -148,6 +149,20 @@ _pixman_image_get_scanline_32 (pixman_image_t *image, image->common.get_scanline_32 (image, x, y, width, buffer, mask, mask_bits); } +void +_pixman_image_get_scanline_32_argb (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask, + uint32_t mask_bits) +{ + image->common.get_scanline_32 (image, x, y, width, buffer, mask, mask_bits); + + _pixman_color_space_to_argb_32 (image->bits.color_space, buffer, width); +} + /* Even thought the type of buffer is uint32_t *, the function actually expects * a uint64_t *buffer. */ @@ -163,6 +178,20 @@ _pixman_image_get_scanline_64 (pixman_image_t *image, image->common.get_scanline_64 (image, x, y, width, buffer, unused, unused2); } +void +_pixman_image_get_scanline_64_argb (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *unused, + uint32_t unused2) +{ + image->common.get_scanline_64 (image, x, y, width, buffer, unused, unused2); + + _pixman_color_space_to_argb_64 (image->bits.color_space, (uint64_t *) buffer, width); +} + static void image_property_changed (pixman_image_t *image) { diff --git a/pixman/pixman-private.h b/pixman/pixman-private.h index d66c343..40ed9e3 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -203,6 +203,8 @@ struct bits_image pixman_read_memory_func_t read_func; pixman_write_memory_func_t write_func; + pixman_color_space_t color_space; + struct { uint32_t * bits; int rowstride; /* in number of uint32_t's */ @@ -251,6 +253,15 @@ _pixman_image_get_scanline_32 (pixman_image_t *image, const uint32_t *mask, uint32_t mask_bits); +void +_pixman_image_get_scanline_32_argb (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *mask, + uint32_t mask_bits); + /* Even thought the type of buffer is uint32_t *, the function actually expects * a uint64_t *buffer. */ @@ -264,6 +275,15 @@ _pixman_image_get_scanline_64 (pixman_image_t *image, uint32_t unused2); void +_pixman_image_get_scanline_64_argb (pixman_image_t *image, + int x, + int y, + int width, + uint32_t * buffer, + const uint32_t *unused, + uint32_t unused2); + +void _pixman_image_store_scanline_32 (bits_image_t * image, int x, int y, @@ -280,6 +300,9 @@ _pixman_image_store_scanline_64 (bits_image_t * image, int width, const uint32_t *buffer); +pixman_color_space_t +_pixman_format_get_default_color_space (pixman_format_code_t format); + uint32_t * _pixman_format_alloc_bits (pixman_format_code_t format, int width, diff --git a/pixman/pixman.c b/pixman/pixman.c index 3c2cf60..e98e31d 100644 --- a/pixman/pixman.c +++ b/pixman/pixman.c @@ -588,6 +588,7 @@ do_composite (pixman_implementation_t *imp, const pixman_fast_path_t *info; cache_t *cache; int i; + pixman_bool_t is_argb; src_format = src->common.extended_format_code; src_flags = src->common.flags; @@ -653,29 +654,37 @@ do_composite (pixman_implementation_t *imp, if (op == PIXMAN_OP_DST) return; + /* check color spaces */ + is_argb = (dest->type != BITS || dest->bits.color_space == PIXMAN_COLOR_SPACE_ARGB) && + (!mask || mask->type != BITS || mask->bits.color_space == PIXMAN_COLOR_SPACE_ARGB) && + (src->type != BITS || src->bits.color_space == PIXMAN_COLOR_SPACE_ARGB); + /* Check cache for fast paths */ cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache); - for (i = 0; i < N_CACHED_FAST_PATHS; ++i) + if (is_argb) { - info = &(cache->cache[i]); - - /* Note that we check for equality here, not whether - * the cached fast path matches. This is to prevent - * us from selecting an overly general fast path - * when a more specific one would work. - */ - if (info->op == op && - info->src_format == src_format && - info->mask_format == mask_format && - info->dest_format == dest_format && - info->src_flags == src_flags && - info->mask_flags == mask_flags && - info->dest_flags == dest_flags && - info->func) - { - goto found; - } + for (i = 0; i < N_CACHED_FAST_PATHS; ++i) + { + info = &(cache->cache[i]); + + /* Note that we check for equality here, not whether + * the cached fast path matches. This is to prevent + * us from selecting an overly general fast path + * when a more specific one would work. + */ + if (info->op == op && + info->src_format == src_format && + info->mask_format == mask_format && + info->dest_format == dest_format && + info->src_flags == src_flags && + info->mask_flags == mask_flags && + info->dest_flags == dest_flags && + info->func) + { + goto found; + } + } } while (imp) @@ -685,6 +694,8 @@ do_composite (pixman_implementation_t *imp, while (info->op != PIXMAN_OP_NONE) { if ((info->op == op || info->op == PIXMAN_OP_any) && + /* color space */ + (is_argb || info->op == PIXMAN_OP_any) && /* Formats */ ((info->src_format == src_format) || (info->src_format == PIXMAN_any)) && @@ -877,10 +888,14 @@ color_to_uint32 (const pixman_color_t *color) static pixman_bool_t color_to_pixel (pixman_color_t * color, uint32_t * pixel, - pixman_format_code_t format) + pixman_format_code_t format, + pixman_color_space_t color_space) { uint32_t c = color_to_uint32 (color); + if (color_space != PIXMAN_COLOR_SPACE_ARGB) + return FALSE; + if (!(format == PIXMAN_a8r8g8b8 || format == PIXMAN_x8r8g8b8 || format == PIXMAN_a8b8g8r8 || @@ -998,7 +1013,7 @@ pixman_image_fill_boxes (pixman_op_t op, { uint32_t pixel; - if (color_to_pixel (color, &pixel, dest->bits.format)) + if (color_to_pixel (color, &pixel, dest->bits.format, dest->bits.color_space)) { pixman_region32_t fill_region; int n_rects, j; diff --git a/pixman/pixman.h b/pixman/pixman.h index 89ce899..f483163 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -709,6 +709,14 @@ typedef enum { PIXMAN_yv12 = PIXMAN_FORMAT(12,PIXMAN_TYPE_YV12,0,0,0,0) } pixman_format_code_t; +typedef enum { + PIXMAN_COLOR_SPACE_ARGB, + PIXMAN_COLOR_SPACE_ARGB_UNMULTIPLIED, + PIXMAN_COLOR_SPACE_YCBCR_HD, + PIXMAN_COLOR_SPACE_YCBCR_SD, + PIXMAN_COLOR_SPACE_YCBCR_JPEG +} pixman_color_space_t; + /* Querying supported format values. */ pixman_bool_t pixman_format_supported_destination (pixman_format_code_t format); pixman_bool_t pixman_format_supported_source (pixman_format_code_t format); @@ -736,6 +744,7 @@ pixman_image_t *pixman_image_create_bits (pixman_format_code_t uint32_t *bits, int rowstride_bytes); pixman_image_t *pixman_image_create_planar (pixman_format_code_t format, + pixman_color_space_t color_space, int width, int height, unsigned int num_planes, |