summaryrefslogtreecommitdiff
path: root/pixman/pixman-intermediate.c
diff options
context:
space:
mode:
Diffstat (limited to 'pixman/pixman-intermediate.c')
-rw-r--r--pixman/pixman-intermediate.c167
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);
+}
+