diff options
author | Benjamin Otte <otte@gnome.org> | 2009-12-14 15:48:47 +0100 |
---|---|---|
committer | Søren Sandmann Pedersen <ssp@redhat.com> | 2010-07-07 10:10:03 -0400 |
commit | 62dd909d6576ce018d6ac832b80cd168a3b8d3b4 (patch) | |
tree | 02ece08d478fd4b27835d01426c214ba08073d3b | |
parent | e8246983e5c48b915dc576943df55da3bd6cd9de (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 a52a9e6e..0b3e40db 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 b41a5274..47ee87d8 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 */ @@ -967,7 +969,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) { @@ -981,22 +986,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 (); @@ -1005,6 +1025,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 00000000..383bebd7 --- /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 00000000..10469784 --- /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 6d091e8e..46368e6b 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 fc742c03..975b4640 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; } @@ -246,6 +250,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 61354126..1a032c9c 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 @@ -145,6 +146,20 @@ _pixman_image_get_scanline_32 (pixman_image_t *image, image->common.get_scanline_32 (image, x, y, width, buffer, mask); } +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. */ @@ -159,6 +174,20 @@ _pixman_image_get_scanline_64 (pixman_image_t *image, image->common.get_scanline_64 (image, x, y, width, buffer, unused); } +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 4c4af54a..b8d5a62a 100644 --- a/pixman/pixman-private.h +++ b/pixman/pixman-private.h @@ -202,6 +202,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 */ @@ -248,6 +250,15 @@ _pixman_image_get_scanline_32 (pixman_image_t *image, uint32_t * buffer, const uint32_t *mask); +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. */ @@ -260,6 +271,15 @@ _pixman_image_get_scanline_64 (pixman_image_t *image, const uint32_t *unused); 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, @@ -276,6 +296,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 3c2cf60e..e98e31d7 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 84f3e15e..95042ba4 100644 --- a/pixman/pixman.h +++ b/pixman/pixman.h @@ -721,6 +721,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); @@ -748,6 +756,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, |