diff options
Diffstat (limited to 'pixman/pixman-intermediate.c')
-rw-r--r-- | pixman/pixman-intermediate.c | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/pixman/pixman-intermediate.c b/pixman/pixman-intermediate.c new file mode 100644 index 0000000..8b65599 --- /dev/null +++ b/pixman/pixman-intermediate.c @@ -0,0 +1,167 @@ +/* + * 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-intermediate-private.h" + +#include <stdlib.h> + +static void +composite_src_x888_y420 (pixman_implementation_t *imp, + pixman_op_t op, + pixman_image_t * src_image, + pixman_image_t * mask_image, + pixman_image_t * dst_image, + int32_t src_x, + int32_t src_y, + int32_t mask_x, + int32_t mask_y, + int32_t dest_x, + int32_t dest_y, + int32_t width, + int32_t height) +{ + uint8_t *ydst, *udst, *vdst; + uint32_t *src; + int ydst_stride, udst_stride, vdst_stride, src_stride; + int x, y; + pixman_bool_t last_row, last_column; + + last_row = (dest_y + height == dst_image->bits.height) && (height & 1); + last_column = (dest_x + width == dst_image->bits.width) && (width & 1); + + /* don't treat odd offsets or sizes */ + if ((dest_x & 1) || + (dest_y & 1) || + (!last_column && (width & 1)) || + (!last_row && (height & 1))) + return; + + /* Y plane */ + PIXMAN_IMAGE_GET_PLANE (src_image, 0, src_x, src_y, uint32_t, src_stride, src, 1); + PIXMAN_IMAGE_GET_PLANE (dst_image, 0, dest_x, dest_y, uint8_t, ydst_stride, ydst, 1); + for (y = 0; y < height; y++) + { + for (x = 0; x < width; x++) + { + ydst[x] = src[x] >> 16; + } + ydst += ydst_stride; + src += src_stride; + } + + /* U and V plane */ + PIXMAN_IMAGE_GET_PLANE (src_image, 0, src_x, src_y, uint32_t, src_stride, src, 1); + PIXMAN_IMAGE_GET_PLANE (dst_image, 1, dest_x / 2, dest_y / 2, uint8_t, udst_stride, udst, 1); + PIXMAN_IMAGE_GET_PLANE (dst_image, 2, dest_x / 2, dest_y / 2, uint8_t, vdst_stride, vdst, 1); + for (y = 1; y < height; y += 2) + { + for (x = 1; x < width; x += 2) + { + udst[x >> 1] = ((src[x - 1] >> 8) + (src[x] >> 8) + (src[x + src_stride - 1] >> 8) + (src[x + src_stride] >> 8)) >> 2; + vdst[x >> 1] = ( src[x - 1] + src[x] + src[x + src_stride - 1] + src[x + src_stride] ) >> 2; + } + if (last_column) + { + udst[width >> 1] = ((src[width - 1] >> 8) + (src[width + src_stride - 1] >> 8)) >> 1; + vdst[width >> 1] = ( src[width - 1] + src[width + src_stride - 1] ) >> 1; + } + udst += udst_stride; + vdst += vdst_stride; + src += 2 * src_stride; + } + + if (last_row) + { + for (x = 1; x < width; x += 2) + { + udst[x >> 1] = ((src[x - 1] >> 8) + (src[x] >> 8)) >> 1; + vdst[x >> 1] = ( src[x - 1] + src[x] ) >> 1; + } + if (last_column) + { + udst[x >> 1] = src[x - 1] >> 8; + vdst[x >> 1] = src[x - 1]; + } + } +} + + +pixman_bool_t +_pixman_format_requires_intermediate (pixman_format_code_t format) +{ + return format == PIXMAN_y420; +} + +pixman_bool_t +_pixman_intermediate_setup (bits_image_t *bits) +{ + uint32_t *planes[PIXMAN_MAX_PLANES], *data; + int rowstrides[PIXMAN_MAX_PLANES]; + int y; + + data = _pixman_format_alloc_bits (PIXMAN_x8r8g8b8, + bits->width, bits->height, + planes, rowstrides); + if (data == NULL) + return FALSE; + + bits->intermediate = pixman_image_create_planar (PIXMAN_x8r8g8b8, + bits->color_space, + bits->width, bits->height, + 1, planes, rowstrides); + if (bits->intermediate == NULL) + { + free (data); + return FALSE; + } + + bits->bits = data; + bits->rowstride = rowstrides[0] / sizeof (uint32_t); + + for (y = 0; y < bits->height; y++) + { + bits->fetch_scanline_raw_32 ((pixman_image_t *) bits, 0, y, bits->width, data, NULL, 0); + data += rowstrides[0] / sizeof (uint32_t); + } + + return TRUE; +} + +void +_pixman_intermediate_finish (bits_image_t *bits) +{ + composite_src_x888_y420 (NULL, PIXMAN_OP_SRC, + bits->intermediate, NULL, (pixman_image_t *) bits, + 0, 0, 0, 0, 0, 0, bits->width, bits->height); + + pixman_image_unref (bits->intermediate); + free (bits->bits); +} + |