[Spice-devel] [PATCH 02/30] Add pixman utilities

Alexander Larsson alexl at redhat.com
Thu Feb 18 12:58:28 PST 2010


This includes:
 * pixman region from SpiceRects
 * pixman region from bitmask
 * rop2 enum
 * solid fill
 * solid fill with rop
 * tiled fill
 * tiled fill with rop
 * blit
 * blit with rop
 * copy rect
---
 client/Makefile.am      |    1 +
 client/pixman_utils.cpp |   25 +
 client/x11/Makefile.am  |    1 +
 common/Makefile.am      |    2 +
 common/pixman_utils.c   | 1286 +++++++++++++++++++++++++++++++++++++++++++++++
 common/pixman_utils.h   |  112 ++++
 server/Makefile.am      |    1 +
 7 files changed, 1428 insertions(+), 0 deletions(-)
 create mode 100644 client/pixman_utils.cpp
 create mode 100644 common/pixman_utils.c
 create mode 100644 common/pixman_utils.h

diff --git a/client/Makefile.am b/client/Makefile.am
index b453e94..c59b6f3 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -10,6 +10,7 @@ RED_COMMON_SRCS =	 		\
 	audio_devices.h			\
 	cache.hpp			\
 	cairo_canvas.cpp		\
+	pixman_utils.cpp		\
 	canvas.cpp			\
 	canvas.h			\
 	canvas_utils.cpp		\
diff --git a/client/pixman_utils.cpp b/client/pixman_utils.cpp
new file mode 100644
index 0000000..337e07c
--- /dev/null
+++ b/client/pixman_utils.cpp
@@ -0,0 +1,25 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "utils.h"
+
+
+#define CANVAS_ERROR(format, ...) THROW(format, ## __VA_ARGS__)
+
+#include "../common/pixman_utils.c"
+
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am
index c5efd86..e50c4ae 100644
--- a/client/x11/Makefile.am
+++ b/client/x11/Makefile.am
@@ -71,6 +71,7 @@ RED_COMMON_SRCS = 					\
 	$(top_srcdir)/client/menu.cpp			\
 	$(top_srcdir)/client/menu.h			\
 	$(top_srcdir)/client/pixels_source.h		\
+	$(top_srcdir)/client/pixman_utils.cpp		\
 	$(top_srcdir)/client/platform.h			\
 	$(top_srcdir)/client/playback_channel.cpp	\
 	$(top_srcdir)/client/process_loop.cpp		\
diff --git a/common/Makefile.am b/common/Makefile.am
index 7fcdfe9..2d18440 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -3,6 +3,8 @@ NULL =
 COMMON_SRCS = 				\
 	cairo_canvas.h			\
 	cairo_canvas.c			\
+	pixman_utils.h			\
+	pixman_utils.c			\
 	canvas_base.h			\
 	canvas_base.c			\
 	canvas_utils.h			\
diff --git a/common/pixman_utils.c b/common/pixman_utils.c
new file mode 100644
index 0000000..84df957
--- /dev/null
+++ b/common/pixman_utils.c
@@ -0,0 +1,1286 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "pixman_utils.h"
+#include <stdlib.h>
+#include <string.h>
+
+/*************************************************************
+ ***********   Copied from pixman-region.c        ************
+ *************************************************************/
+
+/* We're doing 32bit only atm, but keep this to be generically useful */
+
+typedef pixman_box32_t		box_type_t;
+typedef pixman_region32_data_t	region_data_type_t;
+typedef pixman_region32_t	region_type_t;
+
+typedef struct {
+    int x, y;
+} point_type_t;
+
+#define pixman_region32_init_from_bitmap spice_pixman_region32_init_from_bitmap
+
+#define PREFIX(x) pixman_region32##x
+
+/* Below this is 16/32bit intependent */
+
+#ifndef FALSE
+#   define FALSE 0
+#endif
+
+#ifndef TRUE
+#   define TRUE 1
+#endif
+
+#ifndef UINT32_MAX
+# define UINT32_MAX             (4294967295U)
+#endif
+
+/* from pixman-edge-imp.h */
+#ifdef WORDS_BIGENDIAN
+#   define SCREEN_SHIFT_LEFT(x,n)	((x) << (n))
+#   define SCREEN_SHIFT_RIGHT(x,n)	((x) >> (n))
+#else
+#   define SCREEN_SHIFT_LEFT(x,n)	((x) >> (n))
+#   define SCREEN_SHIFT_RIGHT(x,n)	((x) << (n))
+#endif
+
+#define PIXREGION_BOXPTR(reg) ((box_type_t *)((reg)->data + 1))
+#define PIXREGION_BOX(reg, i) (&PIXREGION_BOXPTR (reg)[i])
+#define PIXREGION_TOP(reg) PIXREGION_BOX (reg, (reg)->data->numRects)
+#define PIXREGION_END(reg) PIXREGION_BOX (reg, (reg)->data->numRects - 1)
+
+static const box_type_t PREFIX (_empty_box_) = { 0, 0, 0, 0 };
+static const region_data_type_t PREFIX (_broken_data_) = { 0, 0 };
+
+static box_type_t *pixman_region_empty_box =
+    (box_type_t *)&PREFIX (_empty_box_);
+static region_data_type_t *pixman_broken_data =
+    (region_data_type_t *)&PREFIX (_broken_data_);
+
+static size_t
+PIXREGION_SZOF (size_t n)
+{
+    size_t size = n * sizeof(box_type_t);
+
+    if (n > UINT32_MAX / sizeof(box_type_t))
+        return 0;
+
+    if (sizeof(region_data_type_t) > UINT32_MAX - size)
+        return 0;
+
+    return size + sizeof(region_data_type_t);
+}
+
+static void *
+alloc_data (size_t n)
+{
+    size_t sz = PIXREGION_SZOF (n);
+
+    if (!sz)
+        return NULL;
+
+    return malloc (sz);
+}
+
+#define FREE_DATA(reg) if ((reg)->data && (reg)->data->size) free ((reg)->data)
+
+static pixman_bool_t
+pixman_break (region_type_t *region)
+{
+    FREE_DATA (region);
+
+    region->extents = *pixman_region_empty_box;
+    region->data = pixman_broken_data;
+
+    return FALSE;
+}
+
+static pixman_bool_t
+pixman_rect_alloc (region_type_t * region,
+                   int             n)
+{
+    region_data_type_t *data;
+
+    if (!region->data)
+    {
+        n++;
+        region->data = (region_data_type_t *)alloc_data (n);
+
+        if (!region->data)
+            return pixman_break (region);
+
+        region->data->numRects = 1;
+        *PIXREGION_BOXPTR (region) = region->extents;
+    }
+    else if (!region->data->size)
+    {
+        region->data = (region_data_type_t *)alloc_data (n);
+
+        if (!region->data)
+            return pixman_break (region);
+
+        region->data->numRects = 0;
+    }
+    else
+    {
+        size_t data_size;
+
+        if (n == 1)
+        {
+            n = region->data->numRects;
+            if (n > 500) /* XXX pick numbers out of a hat */
+                n = 250;
+        }
+
+        n += region->data->numRects;
+        data_size = PIXREGION_SZOF (n);
+
+        if (!data_size)
+        {
+            data = NULL;
+        }
+        else
+        {
+            data = (region_data_type_t *)
+                realloc (region->data, PIXREGION_SZOF (n));
+        }
+
+        if (!data)
+            return pixman_break (region);
+
+        region->data = data;
+    }
+
+    region->data->size = n;
+
+    return TRUE;
+}
+
+/*************************************************************
+ **********   copied from X, fbpixmap.c and fb.h    **********
+ *************************************************************/
+
+/* We only use uint32_t for bits and little endian bitmasks */
+#define READ(_ptr) (*(_ptr))
+
+/* This is the code from fbpixmap.c */
+
+#define BM_ADDRECT(reg,r,fr,rx1,ry1,rx2,ry2)			\
+if (((rx1) < (rx2)) && ((ry1) < (ry2)) &&			\
+    (!((reg)->data->numRects &&					\
+       ((r-1)->y1 == (ry1)) &&					\
+       ((r-1)->y2 == (ry2)) &&					\
+       ((r-1)->x1 <= (rx1)) &&					\
+       ((r-1)->x2 >= (rx2)))))					\
+{								\
+    if (!(reg)->data ||                                         \
+        (reg)->data->numRects == (reg)->data->size)		\
+    {								\
+        if (!pixman_rect_alloc (reg, 1))			\
+          goto error;						\
+        fr = PIXREGION_BOXPTR(reg);				\
+        r = fr + (reg)->data->numRects;				\
+    }								\
+    r->x1 = (rx1);						\
+    r->y1 = (ry1);						\
+    r->x2 = (rx2);						\
+    r->y2 = (ry2);						\
+    (reg)->data->numRects++;					\
+    if(r->x1 < (reg)->extents.x1)				\
+        (reg)->extents.x1 = r->x1;				\
+    if(r->x2 > (reg)->extents.x2)				\
+        (reg)->extents.x2 = r->x2;				\
+    r++;							\
+}
+
+/* Convert bitmap clip mask into clipping region.
+ * First, goes through each line and makes boxes by noting the transitions
+ * from 0 to 1 and 1 to 0.
+ * Then it coalesces the current line with the previous if they have boxes
+ * at the same X coordinates.
+ */
+void
+PREFIX (_init_from_bitmap) (region_type_t *region,
+                            uint32_t *data,
+                            int width, int height, int stride)
+{
+    uint32_t mask0 = 0xffffffff & ~SCREEN_SHIFT_RIGHT(0xffffffff, 1);
+    box_type_t *first_rect, *rects, *prect_line_start;
+    box_type_t *old_rect, *new_rect;
+    uint32_t *pw, w, *pw_line, *pw_line_end;
+    int	irect_prev_start, irect_line_start;
+    int	h, base, rx1 = 0, crects;
+    int	ib;
+    pixman_bool_t in_box, same;
+
+    PREFIX(_init) (region);
+
+    first_rect = PIXREGION_BOXPTR(region);
+    rects = first_rect;
+
+    pw_line = data;
+
+    region->extents.x1 = width - 1;
+    region->extents.x2 = 0;
+    irect_prev_start = -1;
+    for (h = 0; h < height; h++)
+    {
+        pw = pw_line;
+        pw_line += stride;
+        irect_line_start = rects - first_rect;
+
+        /* If the Screen left most bit of the word is set, we're starting in
+         * a box */
+        if (READ(pw) & mask0)
+        {
+            in_box = TRUE;
+            rx1 = 0;
+        }
+        else
+            in_box = FALSE;
+
+        /* Process all words which are fully in the pixmap */
+        pw_line_end = pw + (width >> 5);
+        for (base = 0; pw < pw_line_end; base += 32)
+        {
+            w = READ(pw++);
+            if (in_box)
+            {
+                if (!~w)
+                    continue;
+            }
+            else
+            {
+                if (!w)
+                    continue;
+            }
+            for (ib = 0; ib < 32; ib++)
+            {
+                /* If the Screen left most bit of the word is set, we're
+                 * starting a box */
+                if (w & mask0)
+                {
+                    if (!in_box)
+                    {
+                        rx1 = base + ib;
+                        /* start new box */
+                        in_box = TRUE;
+                    }
+                }
+                else
+                {
+                    if (in_box)
+                    {
+                        /* end box */
+                        BM_ADDRECT(region, rects, first_rect,
+                                   rx1, h, base + ib, h + 1);
+                        in_box = FALSE;
+                    }
+                }
+                /* Shift the word VISUALLY left one. */
+                w = SCREEN_SHIFT_LEFT(w, 1);
+            }
+        }
+
+        if (width & 31)
+        {
+            /* Process final partial word on line */
+             w = READ(pw++);
+            for (ib = 0; ib < (width & 31); ib++)
+            {
+                /* If the Screen left most bit of the word is set, we're
+                 * starting a box */
+                if (w & mask0)
+                {
+                    if (!in_box)
+                    {
+                        rx1 = base + ib;
+                        /* start new box */
+                        in_box = TRUE;
+                    }
+                }
+                else
+                {
+                    if (in_box)
+                    {
+                        /* end box */
+                        BM_ADDRECT(region, rects, first_rect,
+                                   rx1, h, base + ib, h + 1);
+                        in_box = FALSE;
+                    }
+                }
+                /* Shift the word VISUALLY left one. */
+                w = SCREEN_SHIFT_LEFT(w, 1);
+            }
+        }
+        /* If scanline ended with last bit set, end the box */
+        if (in_box)
+        {
+            BM_ADDRECT(region, rects, first_rect,
+                       rx1, h, base + (width & 31), h + 1);
+        }
+        /* if all rectangles on this line have the same x-coords as
+         * those on the previous line, then add 1 to all the previous  y2s and
+         * throw away all the rectangles from this line
+         */
+        same = FALSE;
+        if (irect_prev_start != -1)
+        {
+            crects = irect_line_start - irect_prev_start;
+            if (crects != 0 &&
+                crects == ((rects - first_rect) - irect_line_start))
+            {
+                old_rect = first_rect + irect_prev_start;
+                new_rect = prect_line_start = first_rect + irect_line_start;
+                same = TRUE;
+                while (old_rect < prect_line_start)
+                {
+                    if ((old_rect->x1 != new_rect->x1) ||
+                        (old_rect->x2 != new_rect->x2))
+                    {
+                          same = FALSE;
+                          break;
+                    }
+                    old_rect++;
+                    new_rect++;
+                }
+                if (same)
+                {
+                    old_rect = first_rect + irect_prev_start;
+                    while (old_rect < prect_line_start)
+                    {
+                        old_rect->y2 += 1;
+                        old_rect++;
+                    }
+                    rects -= crects;
+                    region->data->numRects -= crects;
+                }
+            }
+        }
+        if(!same)
+            irect_prev_start = irect_line_start;
+    }
+    if (!region->data->numRects)
+        region->extents.x1 = region->extents.x2 = 0;
+    else
+    {
+        region->extents.y1 = PIXREGION_BOXPTR(region)->y1;
+        region->extents.y2 = PIXREGION_END(region)->y2;
+        if (region->data->numRects == 1)
+        {
+            free (region->data);
+            region->data = NULL;
+        }
+    }
+
+ error:
+    return;
+}
+
+#include <stdio.h>
+
+#ifndef ASSERT
+#define ASSERT(x) if (!(x)) {                               \
+    printf("%s: ASSERT %s failed\n", __FUNCTION__, #x);     \
+    abort();                                                \
+}
+#endif
+
+#define SOLID_RASTER_OP(_name, _size, _type, _equation)  \
+static void                                        \
+solid_rop_ ## _name ## _ ## _size (_type *ptr, int len, _type src)  \
+{                                                  \
+    while (len--) {                                \
+        _type dst = *ptr;                          \
+        if (dst) /* avoid unused warning */;       \
+        *ptr = (_type)(_equation);                 \
+        ptr++;                                     \
+    }                                              \
+}                                                  \
+
+#define TILED_RASTER_OP(_name, _size, _type, _equation) \
+static void                                        \
+tiled_rop_ ## _name ## _ ## _size (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width)	\
+{                                                  \
+    while (len--) {                                \
+        _type src = *tile;                         \
+        _type dst = *ptr;                          \
+        if (src) /* avoid unused warning */;       \
+        if (dst) /* avoid unused warning */;       \
+        *ptr = (_type)(_equation);                 \
+        ptr++;                                     \
+        tile++;                                    \
+        if (tile == tile_end)                      \
+            tile -= tile_width;                    \
+    }                                              \
+}                                                  \
+
+#define COPY_RASTER_OP(_name, _size, _type, _equation) \
+static void                                        \
+ copy_rop_ ## _name ## _ ## _size (_type *ptr, _type *src_line, int len)	\
+{                                                  \
+    while (len--) {                                \
+        _type src = *src_line;                     \
+        _type dst = *ptr;                          \
+        if (src) /* avoid unused warning */;       \
+        if (dst) /* avoid unused warning */;       \
+        *ptr = (_type)(_equation);                 \
+        ptr++;                                     \
+        src_line++;                                \
+    }                                              \
+}                                                  \
+
+#define RASTER_OP(name, equation) \
+    SOLID_RASTER_OP(name, 8, uint8_t, equation) \
+    SOLID_RASTER_OP(name, 16, uint16_t, equation) \
+    SOLID_RASTER_OP(name, 32, uint32_t, equation) \
+    TILED_RASTER_OP(name, 8, uint8_t, equation) \
+    TILED_RASTER_OP(name, 16, uint16_t, equation) \
+    TILED_RASTER_OP(name, 32, uint32_t, equation) \
+    COPY_RASTER_OP(name, 8, uint8_t, equation) \
+    COPY_RASTER_OP(name, 16, uint16_t, equation) \
+    COPY_RASTER_OP(name, 32, uint32_t, equation)
+
+RASTER_OP(clear, 0x0)
+RASTER_OP(and, src & dst)
+RASTER_OP(and_reverse, src & ~dst)
+RASTER_OP(copy, src)
+RASTER_OP(and_inverted, ~src & dst)
+RASTER_OP(noop, dst)
+RASTER_OP(xor, src ^ dst)
+RASTER_OP(or, src | dst)
+RASTER_OP(nor, ~src & ~dst)
+RASTER_OP(equiv, ~src ^ dst)
+RASTER_OP(invert, ~dst)
+RASTER_OP(or_reverse, src | ~dst)
+RASTER_OP(copy_inverted, ~src)
+RASTER_OP(or_inverted, ~src | dst)
+RASTER_OP(nand, ~src | ~dst)
+RASTER_OP(set, 0xffffffff)
+
+typedef void (*solid_rop_8_func_t)(uint8_t *ptr, int len, uint8_t src);
+typedef void (*solid_rop_16_func_t)(uint16_t *ptr, int len, uint16_t src);
+typedef void (*solid_rop_32_func_t)(uint32_t *ptr, int len, uint32_t src);
+typedef void (*tiled_rop_8_func_t)(uint8_t *ptr, int len, uint8_t *tile, uint8_t *tile_end, int tile_width);
+typedef void (*tiled_rop_16_func_t)(uint16_t *ptr, int len, uint16_t *tile, uint16_t *tile_end, int tile_width);
+typedef void (*tiled_rop_32_func_t)(uint32_t *ptr, int len, uint32_t *tile, uint32_t *tile_end, int tile_width);
+typedef void (*copy_rop_8_func_t)(uint8_t *ptr, uint8_t *src, int len);
+typedef void (*copy_rop_16_func_t)(uint16_t *ptr, uint16_t *src, int len);
+typedef void (*copy_rop_32_func_t)(uint32_t *ptr, uint32_t *src, int len);
+
+#define ROP_TABLE(_type, _size)						\
+static void (*solid_rops_ ## _size[16]) (_type *ptr, int len, _type src) = { \
+    solid_rop_clear_ ## _size,  \
+    solid_rop_and_ ## _size,    \
+    solid_rop_and_reverse_ ## _size,    \
+    solid_rop_copy_ ## _size,    \
+    solid_rop_and_inverted_ ## _size,    \
+    solid_rop_noop_ ## _size,    \
+    solid_rop_xor_ ## _size,    \
+    solid_rop_or_ ## _size,    \
+    solid_rop_nor_ ## _size,    \
+    solid_rop_equiv_ ## _size,    \
+    solid_rop_invert_ ## _size,    \
+    solid_rop_or_reverse_ ## _size,    \
+    solid_rop_copy_inverted_ ## _size,    \
+    solid_rop_or_inverted_ ## _size,    \
+    solid_rop_nand_ ## _size,    \
+    solid_rop_set_ ## _size    \
+};                          \
+static void (*tiled_rops_ ## _size[16]) (_type *ptr, int len, _type *tile, _type *tile_end, int tile_width) = { \
+    tiled_rop_clear_ ## _size,  \
+    tiled_rop_and_ ## _size,    \
+    tiled_rop_and_reverse_ ## _size,    \
+    tiled_rop_copy_ ## _size,    \
+    tiled_rop_and_inverted_ ## _size,    \
+    tiled_rop_noop_ ## _size,    \
+    tiled_rop_xor_ ## _size,    \
+    tiled_rop_or_ ## _size,    \
+    tiled_rop_nor_ ## _size,    \
+    tiled_rop_equiv_ ## _size,    \
+    tiled_rop_invert_ ## _size,    \
+    tiled_rop_or_reverse_ ## _size,    \
+    tiled_rop_copy_inverted_ ## _size,    \
+    tiled_rop_or_inverted_ ## _size,    \
+    tiled_rop_nand_ ## _size,    \
+    tiled_rop_set_ ## _size    \
+}; \
+static void (*copy_rops_ ## _size[16]) (_type *ptr, _type *tile, int len) = { \
+    copy_rop_clear_ ## _size,  \
+    copy_rop_and_ ## _size,    \
+    copy_rop_and_reverse_ ## _size,    \
+    copy_rop_copy_ ## _size,    \
+    copy_rop_and_inverted_ ## _size,    \
+    copy_rop_noop_ ## _size,    \
+    copy_rop_xor_ ## _size,    \
+    copy_rop_or_ ## _size,    \
+    copy_rop_nor_ ## _size,    \
+    copy_rop_equiv_ ## _size,    \
+    copy_rop_invert_ ## _size,    \
+    copy_rop_or_reverse_ ## _size,    \
+    copy_rop_copy_inverted_ ## _size,    \
+    copy_rop_or_inverted_ ## _size,    \
+    copy_rop_nand_ ## _size,    \
+    copy_rop_set_ ## _size    \
+};
+
+ROP_TABLE(uint8_t, 8)
+ROP_TABLE(uint16_t, 16)
+ROP_TABLE(uint32_t, 32)
+
+void
+spice_pixman_fill_rect (pixman_image_t *dest,
+                        int x, int y,
+                        int width, int height,
+                        uint32_t value)
+{
+    uint32_t *bits;
+    int stride, depth;
+    uint32_t byte_width;
+    uint8_t *byte_line;
+
+    bits = pixman_image_get_data (dest);
+    stride = pixman_image_get_stride (dest);
+    depth = pixman_image_get_depth (dest);
+    /* stride is in bytes, depth in bits */
+
+    ASSERT(x >= 0);
+    ASSERT(y >= 0);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+    ASSERT(x + width <= pixman_image_get_width (dest));
+    ASSERT(y + height <= pixman_image_get_height (dest));
+
+    if (depth == 24)
+        depth = 32; /* Needed for pixman_fill */
+
+    if (pixman_fill (bits,
+                     stride / 4,
+                     depth,
+                     x, y,
+                     width, height,
+                     value))
+        return;
+
+    if (depth == 8) {
+        byte_line = ((uint8_t *)bits) + stride * y + x;
+        byte_width = width;
+        value = (value & 0xff) * 0x01010101;
+    } else if (depth == 16) {
+        byte_line = ((uint8_t *)bits) + stride * y + x * 2;
+        byte_width = 2 * width;
+        value = (value & 0xffff) * 0x00010001;
+    } else {
+        ASSERT (depth == 32 || depth == 24)
+        byte_line = ((uint8_t *)bits) + stride * y + x * 4;
+        byte_width = 4 * width;
+    }
+
+    while (height--) {
+        int w;
+        uint8_t *d = byte_line;
+
+        byte_line += stride;
+        w = byte_width;
+
+        while (w >= 1 && ((unsigned long)d & 1)) {
+            *(uint8_t *)d = (value & 0xff);
+            w--;
+            d++;
+        }
+
+        while (w >= 2 && ((unsigned long)d & 3)) {
+            *(uint16_t *)d = value;
+            w -= 2;
+            d += 2;
+        }
+
+        while (w >= 4 && ((unsigned long)d & 7)) {
+            *(uint32_t *)d = value;
+
+            w -= 4;
+            d += 4;
+        }
+
+        while (w >= 4) {
+            *(uint32_t *)d = value;
+
+            w -= 4;
+            d += 4;
+        }
+
+        while (w >= 2) {
+            *(uint16_t *)d = value;
+            w -= 2;
+            d += 2;
+        }
+
+        while (w >= 1) {
+            *(uint8_t *)d = (value & 0xff);
+            w--;
+            d++;
+        }
+    }
+}
+
+void
+spice_pixman_fill_rect_rop (pixman_image_t *dest,
+                            int x, int y,
+                            int width, int height,
+                            uint32_t value,
+                            SpiceROP rop)
+{
+    uint32_t *bits;
+    int stride, depth;
+    uint8_t *byte_line;
+
+    bits = pixman_image_get_data (dest);
+    stride = pixman_image_get_stride (dest);
+    depth = pixman_image_get_depth (dest);
+    /* stride is in bytes, depth in bits */
+
+    ASSERT(x >= 0);
+    ASSERT(y >= 0);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+    ASSERT(x + width <= pixman_image_get_width (dest));
+    ASSERT(y + height <= pixman_image_get_height (dest));
+    ASSERT(rop >= 0 && rop < 16);
+
+    if (depth == 8) {
+        solid_rop_8_func_t rop_func = solid_rops_8[rop];
+
+        byte_line = ((uint8_t *)bits) + stride * y + x;
+        while (height--) {
+            rop_func ((uint8_t *)byte_line, width, (uint8_t)value);
+            byte_line += stride;
+        }
+
+    } else if (depth == 16) {
+        solid_rop_16_func_t rop_func = solid_rops_16[rop];
+
+        byte_line = ((uint8_t *)bits) + stride * y + x * 2;
+        while (height--) {
+            rop_func ((uint16_t *)byte_line, width, (uint16_t)value);
+            byte_line += stride;
+        }
+    }  else {
+        solid_rop_32_func_t rop_func = solid_rops_32[rop];
+
+        ASSERT (depth == 32 || depth == 24);
+
+        byte_line = ((uint8_t *)bits) + stride * y + x * 4;
+        while (height--) {
+            rop_func ((uint32_t *)byte_line, width, (uint32_t)value);
+            byte_line += stride;
+        }
+    }
+}
+
+void
+spice_pixman_tile_rect (pixman_image_t *dest,
+                        int x, int y,
+                        int width, int height,
+                        pixman_image_t *tile,
+                        int offset_x,
+                        int offset_y)
+{
+    uint32_t *bits, *tile_bits;
+    int stride, depth;
+    int tile_width, tile_height, tile_stride;
+    uint8_t *byte_line;
+    uint8_t *tile_line;
+    int tile_start_x, tile_start_y, tile_end_dx;
+
+    bits = pixman_image_get_data (dest);
+    stride = pixman_image_get_stride (dest);
+    depth = pixman_image_get_depth (dest);
+    /* stride is in bytes, depth in bits */
+
+    tile_bits = pixman_image_get_data (tile);
+    tile_stride = pixman_image_get_stride (tile);
+    tile_width = pixman_image_get_width (tile);
+    tile_height = pixman_image_get_height (tile);
+
+    ASSERT(x >= 0);
+    ASSERT(y >= 0);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+    ASSERT(x + width <= pixman_image_get_width (dest));
+    ASSERT(y + height <= pixman_image_get_height (dest));
+    ASSERT(depth == pixman_image_get_depth (tile));
+
+    tile_start_x = (x - offset_x) % tile_width;
+    if (tile_start_x < 0)
+        tile_start_x += tile_width;
+    tile_start_y = (y - offset_y) % tile_height;
+    if (tile_start_y < 0)
+        tile_start_y += tile_height;
+    tile_end_dx = tile_width - tile_start_x;
+
+    if (depth == 8) {
+        byte_line = ((uint8_t *)bits) + stride * y + x;
+        tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x;
+        while (height--) {
+            tiled_rop_copy_8 ((uint8_t *)byte_line, width, (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx, tile_width);
+            byte_line += stride;
+            tile_line += tile_stride;
+            if (++tile_start_y == tile_height) {
+                tile_line -= tile_height * tile_stride;
+                tile_start_y = 0;
+            }
+        }
+
+    } else if (depth == 16) {
+        byte_line = ((uint8_t *)bits) + stride * y + x * 2;
+        tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2;
+        while (height--) {
+            tiled_rop_copy_16 ((uint16_t *)byte_line, width, (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx, tile_width);
+            byte_line += stride;
+            tile_line += tile_stride;
+            if (++tile_start_y == tile_height) {
+                tile_line -= tile_height * tile_stride;
+                tile_start_y = 0;
+            }
+        }
+    }  else {
+        ASSERT (depth == 32 || depth == 24);
+
+        byte_line = ((uint8_t *)bits) + stride * y + x * 4;
+        tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4;
+        while (height--) {
+            tiled_rop_copy_32 ((uint32_t *)byte_line, width, (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx, tile_width);
+            byte_line += stride;
+            tile_line += tile_stride;
+            if (++tile_start_y == tile_height) {
+                tile_line -= tile_height * tile_stride;
+                tile_start_y = 0;
+            }
+        }
+    }
+}
+
+void
+spice_pixman_tile_rect_rop (pixman_image_t *dest,
+                            int x, int y,
+                            int width, int height,
+                            pixman_image_t *tile,
+                            int offset_x,
+                            int offset_y,
+                            SpiceROP rop)
+{
+    uint32_t *bits, *tile_bits;
+    int stride, depth;
+    int tile_width, tile_height, tile_stride;
+    uint8_t *byte_line;
+    uint8_t *tile_line;
+    int tile_start_x, tile_start_y, tile_end_dx;
+
+    bits = pixman_image_get_data (dest);
+    stride = pixman_image_get_stride (dest);
+    depth = pixman_image_get_depth (dest);
+    /* stride is in bytes, depth in bits */
+
+    tile_bits = pixman_image_get_data (tile);
+    tile_stride = pixman_image_get_stride (tile);
+    tile_width = pixman_image_get_width (tile);
+    tile_height = pixman_image_get_height (tile);
+
+    ASSERT(x >= 0);
+    ASSERT(y >= 0);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+    ASSERT(x + width <= pixman_image_get_width (dest));
+    ASSERT(y + height <= pixman_image_get_height (dest));
+    ASSERT(rop >= 0 && rop < 16);
+    ASSERT(depth == pixman_image_get_depth (tile));
+
+    tile_start_x = (x - offset_x) % tile_width;
+    if (tile_start_x < 0)
+        tile_start_x += tile_width;
+    tile_start_y = (y - offset_y) % tile_height;
+    if (tile_start_y < 0)
+        tile_start_y += tile_height;
+    tile_end_dx = tile_width - tile_start_x;
+
+    if (depth == 8) {
+        tiled_rop_8_func_t rop_func = tiled_rops_8[rop];
+
+        byte_line = ((uint8_t *)bits) + stride * y + x;
+        tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x;
+        while (height--) {
+            rop_func ((uint8_t *)byte_line, width, (uint8_t *)tile_line, (uint8_t *)tile_line + tile_end_dx, tile_width);
+            byte_line += stride;
+            tile_line += tile_stride;
+            if (++tile_start_y == tile_height) {
+                tile_line -= tile_height * tile_stride;
+                tile_start_y = 0;
+            }
+        }
+
+    } else if (depth == 16) {
+        tiled_rop_16_func_t rop_func = tiled_rops_16[rop];
+
+        byte_line = ((uint8_t *)bits) + stride * y + x * 2;
+        tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 2;
+        while (height--) {
+            rop_func ((uint16_t *)byte_line, width, (uint16_t *)tile_line, (uint16_t *)tile_line + tile_end_dx, tile_width);
+            byte_line += stride;
+            tile_line += tile_stride;
+            if (++tile_start_y == tile_height) {
+                tile_line -= tile_height * tile_stride;
+                tile_start_y = 0;
+            }
+        }
+    }  else {
+        tiled_rop_32_func_t rop_func = tiled_rops_32[rop];
+
+        ASSERT (depth == 32 || depth == 24);
+
+        byte_line = ((uint8_t *)bits) + stride * y + x * 4;
+        tile_line = ((uint8_t *)tile_bits) + tile_stride * tile_start_y + tile_start_x * 4;
+        while (height--) {
+            rop_func ((uint32_t *)byte_line, width, (uint32_t *)tile_line, (uint32_t *)tile_line + tile_end_dx, tile_width);
+            byte_line += stride;
+            tile_line += tile_stride;
+            if (++tile_start_y == tile_height) {
+                tile_line -= tile_height * tile_stride;
+                tile_start_y = 0;
+            }
+        }
+    }
+}
+
+
+void
+spice_pixman_blit (pixman_image_t *dest,
+                   pixman_image_t *src,
+                   int src_x, int src_y,
+                   int dest_x, int dest_y,
+                   int width, int height)
+{
+    uint32_t *bits, *src_bits;
+    int stride, depth;
+    int src_width, src_height, src_stride;
+    uint8_t *byte_line;
+    uint8_t *src_line;
+    int byte_width;
+
+    bits = pixman_image_get_data (dest);
+    stride = pixman_image_get_stride (dest);
+    depth = pixman_image_get_depth (dest);
+    /* stride is in bytes, depth in bits */
+
+    src_bits = pixman_image_get_data (src);
+    src_stride = pixman_image_get_stride (src);
+    src_width = pixman_image_get_width (src);
+    src_height = pixman_image_get_height (src);
+
+    /* Clip source */
+    if (src_x < 0) {
+        width += src_x;
+        dest_x -= src_x;
+        src_x = 0;
+    }
+    if (src_y < 0) {
+        height += src_y;
+        dest_y -= src_y;
+        src_y = 0;
+    }
+    if (src_x + width > src_width) {
+        width = src_width - src_x;
+    }
+    if (src_y + height > src_height) {
+        height = src_height - src_y;
+    }
+
+    if (width <= 0 || height <= 0)
+        return;
+
+    ASSERT(src_x >= 0);
+    ASSERT(src_y >= 0);
+    ASSERT(dest_x >= 0);
+    ASSERT(dest_y >= 0);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+    ASSERT(dest_x + width <= pixman_image_get_width (dest));
+    ASSERT(dest_y + height <= pixman_image_get_height (dest));
+    ASSERT(src_x + width <= pixman_image_get_width (src));
+    ASSERT(src_y + height <= pixman_image_get_height (src));
+    ASSERT(depth == pixman_image_get_depth (src));
+
+    if (depth == 24)
+        depth = 32; /* Needed for pixman_blt */
+
+    if (pixman_blt (src_bits,
+                    bits,
+                    src_stride / 4,
+                    stride / 4,
+                    depth, depth,
+                    src_x, src_y,
+                    dest_x, dest_y,
+                    width, height))
+        return;
+
+    if (depth == 8) {
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x;
+        byte_width = width;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x;
+    } else if (depth == 16) {
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2;
+        byte_width = width * 2;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2;
+    }  else {
+        ASSERT (depth == 32 || depth == 24);
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4;
+        byte_width = width * 4;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4;
+    }
+
+    while (height--) {
+        memcpy (byte_line, src_line, byte_width);
+        byte_line += stride;
+        src_line += src_stride;
+    }
+}
+
+void
+spice_pixman_blit_rop (pixman_image_t *dest,
+                       pixman_image_t *src,
+                       int src_x, int src_y,
+                       int dest_x, int dest_y,
+                       int width, int height,
+                       SpiceROP rop)
+{
+    uint32_t *bits, *src_bits;
+    int stride, depth;
+    int src_width, src_height, src_stride;
+    uint8_t *byte_line;
+    uint8_t *src_line;
+
+    bits = pixman_image_get_data (dest);
+    stride = pixman_image_get_stride (dest);
+    depth = pixman_image_get_depth (dest);
+    /* stride is in bytes, depth in bits */
+
+    src_bits = pixman_image_get_data (src);
+    src_stride = pixman_image_get_stride (src);
+    src_width = pixman_image_get_width (src);
+    src_height = pixman_image_get_height (src);
+
+    /* Clip source */
+    if (src_x < 0) {
+        width += src_x;
+        dest_x -= src_x;
+        src_x = 0;
+    }
+    if (src_y < 0) {
+        height += src_y;
+        dest_y -= src_y;
+        src_y = 0;
+    }
+    if (src_x + width > src_width) {
+        width = src_width - src_x;
+    }
+    if (src_y + height > src_height) {
+        height = src_height - src_y;
+    }
+
+    if (width <= 0 || height <= 0)
+        return;
+
+    ASSERT(src_x >= 0);
+    ASSERT(src_y >= 0);
+    ASSERT(dest_x >= 0);
+    ASSERT(dest_y >= 0);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+    ASSERT(dest_x + width <= pixman_image_get_width (dest));
+    ASSERT(dest_y + height <= pixman_image_get_height (dest));
+    ASSERT(src_x + width <= pixman_image_get_width (src));
+    ASSERT(src_y + height <= pixman_image_get_height (src));
+    ASSERT(depth == pixman_image_get_depth (src));
+
+    if (depth == 8) {
+        copy_rop_8_func_t rop_func = copy_rops_8[rop];
+
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x;
+
+        while (height--) {
+            rop_func ((uint8_t *)byte_line, (uint8_t *)src_line, width);
+            byte_line += stride;
+            src_line += src_stride;
+        }
+    } else if (depth == 16) {
+        copy_rop_16_func_t rop_func = copy_rops_16[rop];
+
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2;
+
+        while (height--) {
+            rop_func ((uint16_t *)byte_line, (uint16_t *)src_line, width);
+            byte_line += stride;
+            src_line += src_stride;
+        }
+    }  else {
+        copy_rop_32_func_t rop_func = copy_rops_32[rop];
+
+        ASSERT (depth == 32 || depth == 24);
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4;
+
+        while (height--) {
+            rop_func ((uint32_t *)byte_line, (uint32_t *)src_line, width);
+            byte_line += stride;
+            src_line += src_stride;
+        }
+    }
+
+}
+
+void
+spice_pixman_blit_colorkey (pixman_image_t *dest,
+                            pixman_image_t *src,
+                            int src_x, int src_y,
+                            int dest_x, int dest_y,
+                            int width, int height,
+                            uint32_t transparent_color)
+{
+    uint32_t *bits, *src_bits;
+    int stride, depth;
+    int src_width, src_height, src_stride;
+    uint8_t *byte_line;
+    uint8_t *src_line;
+    int x;
+
+    bits = pixman_image_get_data (dest);
+    stride = pixman_image_get_stride (dest);
+    depth = pixman_image_get_depth (dest);
+    /* stride is in bytes, depth in bits */
+
+    src_bits = pixman_image_get_data (src);
+    src_stride = pixman_image_get_stride (src);
+    src_width = pixman_image_get_width (src);
+    src_height = pixman_image_get_height (src);
+
+    /* Clip source */
+    if (src_x < 0) {
+        width += src_x;
+        dest_x -= src_x;
+        src_x = 0;
+    }
+    if (src_y < 0) {
+        height += src_y;
+        dest_y -= src_y;
+        src_y = 0;
+    }
+    if (src_x + width > src_width) {
+        width = src_width - src_x;
+    }
+    if (src_y + height > src_height) {
+        height = src_height - src_y;
+    }
+
+    if (width <= 0 || height <= 0)
+        return;
+
+    ASSERT(src_x >= 0);
+    ASSERT(src_y >= 0);
+    ASSERT(dest_x >= 0);
+    ASSERT(dest_y >= 0);
+    ASSERT(width > 0);
+    ASSERT(height > 0);
+    ASSERT(dest_x + width <= pixman_image_get_width (dest));
+    ASSERT(dest_y + height <= pixman_image_get_height (dest));
+    ASSERT(src_x + width <= pixman_image_get_width (src));
+    ASSERT(src_y + height <= pixman_image_get_height (src));
+    ASSERT(depth == pixman_image_get_depth (src));
+
+    if (depth == 8) {
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x;
+
+        while (height--) {
+            uint8_t *d = (uint8_t *)byte_line;
+            uint8_t *s = (uint8_t *)byte_line;
+
+            s = (uint8_t *)src_line;
+            for (x = 0; x < width; x++) {
+                uint8_t val = *s;
+                if (val != (uint8_t)transparent_color) {
+                    *d = val;
+                }
+                s++; d++;
+            }
+
+            byte_line += stride;
+            src_line += src_stride;
+        }
+    } else if (depth == 16) {
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 2;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 2;
+
+        while (height--) {
+            uint16_t *d = (uint16_t *)byte_line;
+            uint16_t *s = (uint16_t *)byte_line;
+
+            s = (uint16_t *)src_line;
+            for (x = 0; x < width; x++) {
+                uint16_t val = *s;
+                if (val != (uint16_t)transparent_color) {
+                    *d = val;
+                }
+                s++; d++;
+            }
+
+            byte_line += stride;
+            src_line += src_stride;
+        }
+    }  else {
+        ASSERT (depth == 32 || depth == 24);
+        byte_line = ((uint8_t *)bits) + stride * dest_y + dest_x * 4;
+        src_line = ((uint8_t *)src_bits) + src_stride * src_y + src_x * 4;
+
+        while (height--) {
+            uint32_t *d = (uint32_t *)byte_line;
+            uint32_t *s = (uint32_t *)byte_line;
+
+            s = (uint32_t *)src_line;
+            for (x = 0; x < width; x++) {
+                uint32_t val = *s;
+                if (val != (0xffffff & transparent_color)) {
+                    *d = val;
+                }
+                s++; d++;
+            }
+
+            byte_line += stride;
+            src_line += src_stride;
+        }
+    }
+}
+
+static void copy_bits_up(uint8_t *data, const int stride,
+                         const int src_x, const int src_y,
+                         const int width, const int height,
+                         const int dest_x, const int dest_y)
+{
+    uint8_t *src = data + src_y * stride + src_x * sizeof(uint32_t);
+    uint8_t *dest = data + dest_y * stride + dest_x * sizeof(uint32_t);
+    uint8_t *end = dest + height * stride;
+    for (; dest != end; dest += stride, src += stride) {
+        memcpy(dest, src, width * sizeof(uint32_t));
+    }
+}
+
+static void copy_bits_down(uint8_t *data, const int stride,
+                           const int src_x, const int src_y,
+                           const int width, const int height,
+                           const int dest_x, const int dest_y)
+{
+    uint8_t *src = data + (src_y + height - 1) * stride + src_x * sizeof(uint32_t);
+    uint8_t *end = data + (dest_y - 1) * stride + dest_x * sizeof(uint32_t);
+    uint8_t *dest = end + height * stride;
+
+    for (; dest != end; dest -= stride, src -= stride) {
+        memcpy(dest, src, width * sizeof(uint32_t));
+    }
+}
+
+static void copy_bits_same_line(uint8_t *data, const int stride,
+                                const int src_x, const int src_y,
+                                const int width, const int height,
+                                const int dest_x, const int dest_y)
+{
+    uint8_t *src = data + src_y * stride + src_x * sizeof(uint32_t);
+    uint8_t *dest = data + dest_y * stride + dest_x * sizeof(uint32_t);
+    uint8_t *end = dest + height * stride;
+    for (; dest != end; dest += stride, src += stride) {
+        memmove(dest, src, width * sizeof(uint32_t));
+    }
+}
+
+void spice_pixman_copy_rect (pixman_image_t *image,
+                             int src_x, int src_y,
+                             int width, int height,
+                             int dest_x, int dest_y)
+{
+    uint8_t *data;
+    int stride;
+
+    data = (uint8_t *)pixman_image_get_data(image);
+    stride = pixman_image_get_stride(image);
+
+    ASSERT(pixman_image_get_depth (image) == 24 ||
+           pixman_image_get_depth (image) == 32);
+
+    if (dest_y > src_y) {
+        copy_bits_down(data, stride,
+                       src_x, src_y,
+                       width, height,
+                       dest_x, dest_y);
+    } else if (dest_y < src_y) {
+        copy_bits_up(data, stride,
+                     src_x, src_y,
+                     width, height,
+                     dest_x, dest_y);
+    } else {
+        copy_bits_same_line(data, stride,
+                            src_x, src_y,
+                            width, height,
+                            dest_x, dest_y);
+    }
+}
+
+pixman_bool_t
+spice_pixman_region32_init_rects (pixman_region32_t *region,
+                                  const SpiceRect   *rects,
+                                  int                count)
+{
+    pixman_box32_t boxes_array[10];
+    pixman_box32_t *boxes;
+    pixman_bool_t res;
+    int i;
+
+    if (count < 10)
+        boxes = boxes_array;
+    else {
+        boxes = (pixman_box32_t *)malloc (sizeof(pixman_box32_t) * count);
+        if (boxes == NULL)
+            return FALSE;
+    }
+
+    for (i = 0; i < count; i++) {
+        boxes[i].x1 = rects[i].left;
+        boxes[i].y1 = rects[i].top;
+        boxes[i].x2 = rects[i].right;
+        boxes[i].y2 = rects[i].bottom;
+    }
+
+    res = pixman_region32_init_rects (region,
+                                      boxes,
+                                      count);
+
+    if (count >= 10)
+        free (boxes);
+
+    return res;
+}
diff --git a/common/pixman_utils.h b/common/pixman_utils.h
new file mode 100644
index 0000000..933cd8f
--- /dev/null
+++ b/common/pixman_utils.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This program is free software; you can redistribute it and/or
+   modify it under the terms of the GNU General Public License as
+   published by the Free Software Foundation; either version 2 of
+   the License, or (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H__PIXMAN_UTILS
+#define _H__PIXMAN_UTILS
+
+#ifdef  __cplusplus
+extern "C" {
+#endif
+
+#include <pixman.h>
+
+#ifdef  __cplusplus
+}
+#endif
+
+#include <spice/draw.h>
+
+/* This lists all possible 2 argument binary raster ops.
+ * This enum has the same values as the X11 GXcopy type
+ * and same as the GL constants (GL_AND etc) if you
+ * or it with 0x1500. However it is not exactly the
+ * same as the win32 ROP2 type (they use another order).
+ */
+typedef enum {
+    SPICE_ROP_CLEAR,         /* 0x0    0 */
+    SPICE_ROP_AND,           /* 0x1    src AND dst */
+    SPICE_ROP_AND_REVERSE,   /* 0x2    src AND NOT dst */
+    SPICE_ROP_COPY,          /* 0x3    src */
+    SPICE_ROP_AND_INVERTED,  /* 0x4    (NOT src) AND dst */
+    SPICE_ROP_NOOP,          /* 0x5    dst */
+    SPICE_ROP_XOR,           /* 0x6    src XOR dst */
+    SPICE_ROP_OR,            /* 0x7    src OR dst */
+    SPICE_ROP_NOR,           /* 0x8    (NOT src) AND (NOT dst) */
+    SPICE_ROP_EQUIV,         /* 0x9    (NOT src) XOR dst */
+    SPICE_ROP_INVERT,        /* 0xa    NOT dst */
+    SPICE_ROP_OR_REVERSE,    /* 0xb    src OR (NOT dst) */
+    SPICE_ROP_COPY_INVERTED, /* 0xc    NOT src */
+    SPICE_ROP_OR_INVERTED,   /* 0xd    (NOT src) OR dst */
+    SPICE_ROP_NAND,          /* 0xe    (NOT src) OR (NOT dst) */
+    SPICE_ROP_SET            /* 0xf    1 */
+} SpiceROP;
+
+
+void spice_pixman_region32_init_from_bitmap (pixman_region32_t *region,
+                                             uint32_t *data,
+                                             int width, int height,
+                                             int stride);
+pixman_bool_t spice_pixman_region32_init_rects (pixman_region32_t *region,
+                                                const SpiceRect   *rects,
+                                                int                count);
+
+void spice_pixman_fill_rect (pixman_image_t *dest,
+                             int x, int y,
+                             int w, int h,
+                             uint32_t value);
+void spice_pixman_fill_rect_rop (pixman_image_t *dest,
+                                 int x, int y,
+                                 int w, int h,
+                                 uint32_t value,
+                                 SpiceROP rop);
+void spice_pixman_tile_rect (pixman_image_t *dest,
+                             int x, int y,
+                             int w, int h,
+                             pixman_image_t *tile,
+                             int offset_x,
+                             int offset_y);
+void spice_pixman_tile_rect_rop (pixman_image_t *dest,
+                                 int x, int y,
+                                 int w, int h,
+                                 pixman_image_t *tile,
+                                 int offset_x,
+                                 int offset_y,
+                                 SpiceROP rop);
+void spice_pixman_blit (pixman_image_t *dest,
+                        pixman_image_t *src,
+                        int src_x, int src_y,
+                        int dest_x, int dest_y,
+                        int w, int h);
+void spice_pixman_blit_rop (pixman_image_t *dest,
+                            pixman_image_t *src,
+                            int src_x, int src_y,
+                            int dest_x, int dest_y,
+                            int w, int h,
+                            SpiceROP rop);
+void spice_pixman_blit_colorkey (pixman_image_t *dest,
+                                 pixman_image_t *src,
+                                 int src_x, int src_y,
+                                 int dest_x, int dest_y,
+                                 int width, int height,
+                                 uint32_t transparent_color);
+void spice_pixman_copy_rect (pixman_image_t *image,
+                             int src_x, int src_y,
+                             int w, int h,
+                             int dest_x, int dest_y);
+
+#endif /* _H__PIXMAN_UTILS */
diff --git a/server/Makefile.am b/server/Makefile.am
index 03f15a3..b2bea00 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -20,6 +20,7 @@ INCLUDES = \
 
 COMMON_SRCS = 						\
 	$(top_srcdir)/common/cairo_canvas.c		\
+	$(top_srcdir)/common/pixman_utils.c		\
 	$(top_srcdir)/common/gl_canvas.c		\
 	$(top_srcdir)/common/region.c			\
 	$(top_srcdir)/common/glc.c			\
-- 
1.6.6



More information about the Spice-devel mailing list