[Spice-commits] client/application.cpp client/application.h client/cairo_canvas.cpp client/canvas.h client/cursor_channel.cpp client/display_channel.cpp client/display_channel.h client/gui client/Makefile.am client/red_cairo_canvas.cpp client/red_cairo_canvas.h client/red_gl_canvas.h client/red_pixmap_cairo.h client/red_pixmap_gdi.h client/red_pixmap_sw.h client/red_sw_canvas.cpp client/red_sw_canvas.h client/screen.cpp client/sw_canvas.cpp client/windows client/x11 common/cairo_canvas.c common/cairo_canvas.h common/canvas_base.c common/gdi_canvas.c common/gl_canvas.c common/gl_canvas.h common/lz.h common/Makefile.am common/sw_canvas.c common/sw_canvas.h server/Makefile.am server/red_dispatcher.c server/reds.c server/red_worker.c server/red_worker.h

Alexander Larsson alexl at kemper.freedesktop.org
Mon May 3 01:42:28 PDT 2010


 client/Makefile.am                  |   14 
 client/application.cpp              |    8 
 client/application.h                |    2 
 client/cairo_canvas.cpp             |   24 
 client/canvas.h                     |    2 
 client/cursor_channel.cpp           |   18 
 client/display_channel.cpp          |   10 
 client/display_channel.h            |    2 
 client/gui/gui.cpp                  |    4 
 client/gui/gui.h                    |    4 
 client/red_cairo_canvas.cpp         |   96 --
 client/red_cairo_canvas.h           |   49 -
 client/red_gl_canvas.h              |    2 
 client/red_pixmap_cairo.h           |   31 
 client/red_pixmap_gdi.h             |    4 
 client/red_pixmap_sw.h              |   31 
 client/red_sw_canvas.cpp            |   96 ++
 client/red_sw_canvas.h              |   49 +
 client/screen.cpp                   |    6 
 client/sw_canvas.cpp                |   24 
 client/windows/red_pixmap_cairo.cpp |  111 ---
 client/windows/red_pixmap_sw.cpp    |  111 +++
 client/windows/redc.vcproj          |   12 
 client/x11/Makefile.am              |   16 
 client/x11/red_pixmap_cairo.cpp     |   91 --
 client/x11/red_pixmap_sw.cpp        |   91 ++
 common/Makefile.am                  |    4 
 common/cairo_canvas.c               | 1332 ------------------------------------
 common/cairo_canvas.h               |   60 -
 common/canvas_base.c                |   50 -
 common/gdi_canvas.c                 |   10 
 common/gl_canvas.c                  |   14 
 common/gl_canvas.h                  |    6 
 common/lz.h                         |    5 
 common/sw_canvas.c                  | 1332 ++++++++++++++++++++++++++++++++++++
 common/sw_canvas.h                  |   60 +
 server/Makefile.am                  |    8 
 server/red_dispatcher.c             |    6 
 server/red_worker.c                 |    4 
 server/red_worker.h                 |    2 
 server/reds.c                       |    6 
 41 files changed, 1903 insertions(+), 1904 deletions(-)

New commits:
commit ae40f270cfbe4629c041074e2b0c28dfd3f554b8
Author: Alexander Larsson <alexl at redhat.com>
Date:   Mon May 3 12:08:00 2010 +0200

    Remove all mentions of "cairo" from the code
    
    The command line option is renamed from "cairo" to "sw", and
    similarly all filenames and types from Cairo to Sw (and similar).

diff --git a/client/Makefile.am b/client/Makefile.am
index 81ad6db..e1c31fd 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -3,20 +3,20 @@ NULL =
 SUBDIRS = $(red_target)
 DIST_SUBDIRS = x11 #windows
 
-RED_COMMON_SRCS =	 		\
+RED_COMMON_SRCS =			\
 	application.cpp			\
 	application.h			\
 	audio_channels.h		\
 	audio_devices.h			\
 	cache.hpp			\
-	cairo_canvas.cpp		\
+	sw_canvas.cpp			\
 	pixman_utils.cpp		\
 	lines.cpp			\
 	canvas.cpp			\
 	canvas.h			\
 	canvas_utils.cpp		\
-	red_cairo_canvas.cpp		\
-	red_cairo_canvas.h		\
+	red_sw_canvas.cpp		\
+	red_sw_canvas.h			\
 	client_net_socket.cpp		\
 	client_net_socket.h		\
 	cmd_line_parser.cpp		\
@@ -66,7 +66,7 @@ RED_COMMON_SRCS =	 		\
 	red_key.h			\
 	red_peer.cpp			\
 	red_peer.h			\
-	red_pixmap_cairo.h		\
+	red_pixmap_sw.h			\
 	red_pixmap_gl.h			\
 	red_pixmap.h			\
 	red_types.h			\
@@ -82,8 +82,8 @@ RED_COMMON_SRCS =	 		\
 	tunnel_channel.h		\
 	hot_keys.cpp			\
 	hot_keys.h			\
-        threads.cpp			\
-        threads.h			\
+	threads.cpp			\
+	threads.h			\
 	utils.cpp			\
 	utils.h				\
 	$(NULL)
diff --git a/client/application.cpp b/client/application.cpp
index efada34..4eb8ac8 100644
--- a/client/application.cpp
+++ b/client/application.cpp
@@ -35,7 +35,7 @@
 #include "red_gdi_canvas.h"
 #endif
 #include "platform.h"
-#include "cairo_canvas.h"
+#include "sw_canvas.h"
 #include "gl_canvas.h"
 #include "quic.h"
 #include "mutex.h"
@@ -378,7 +378,7 @@ Application::Application()
 #ifdef WIN32
     _canvas_types[0] = CANVAS_OPTION_GDI;
 #else
-    _canvas_types[0] = CANVAS_OPTION_CAIRO;
+    _canvas_types[0] = CANVAS_OPTION_SW;
 #endif
 
     _host_auth_opt.type_flags = RedPeer::HostAuthOptions::HOST_AUTH_OP_NAME;
@@ -1793,7 +1793,7 @@ bool Application::set_canvas_option(CmdLineParser& parser, char *val, const char
     typedef std::map< std::string, CanvasOption> CanvasNamesMap;
     CanvasNamesMap canvas_types;
 
-    canvas_types["cairo"] = CANVAS_OPTION_CAIRO;
+    canvas_types["sw"] = CANVAS_OPTION_SW;
 #ifdef WIN32
     canvas_types["gdi"] = CANVAS_OPTION_GDI;
 #endif
@@ -2130,7 +2130,7 @@ void Application::init_globals()
     SSL_library_init();
     SSL_load_error_strings();
 
-    cairo_canvas_init();
+    sw_canvas_init();
 #ifdef USE_OGL
     gl_canvas_init();
 #endif
diff --git a/client/application.h b/client/application.h
index fda6753..1e48ab5 100644
--- a/client/application.h
+++ b/client/application.h
@@ -100,7 +100,7 @@ private:
 
 enum CanvasOption {
     CANVAS_OPTION_INVALID,
-    CANVAS_OPTION_CAIRO,
+    CANVAS_OPTION_SW,
 #ifdef WIN32
     CANVAS_OPTION_GDI,
 #endif
diff --git a/client/cairo_canvas.cpp b/client/cairo_canvas.cpp
deleted file mode 100644
index b239485..0000000
--- a/client/cairo_canvas.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "common.h"
-#include "utils.h"
-
-#define CANVAS_ERROR(format, ...) THROW(format, ## __VA_ARGS__)
-
-#include "../common/cairo_canvas.c"
-
diff --git a/client/canvas.h b/client/canvas.h
index 82badc4..135783b 100644
--- a/client/canvas.h
+++ b/client/canvas.h
@@ -32,7 +32,7 @@
 
 enum CanvasType {
     CANVAS_TYPE_INVALID,
-    CANVAS_TYPE_CAIRO,
+    CANVAS_TYPE_SW,
     CANVAS_TYPE_GL,
     CANVAS_TYPE_GDI,
 };
diff --git a/client/cursor_channel.cpp b/client/cursor_channel.cpp
index db020a0..402d69f 100644
--- a/client/cursor_channel.cpp
+++ b/client/cursor_channel.cpp
@@ -24,7 +24,7 @@
 #include "debug.h"
 #include "utils.h"
 #include "screen.h"
-#include "red_pixmap_cairo.h"
+#include "red_pixmap_sw.h"
 #include "rect.h"
 
 static inline uint8_t revers_bits(uint8_t byte)
@@ -111,8 +111,8 @@ void UnsupportedCursor::draw(RedDrawable& dest, int x, int y, const SpiceRect& a
 }
 
 AlphaCursor::AlphaCursor(const SpiceCursorHeader& header, const uint8_t* data)
-    : _pixmap (new RedPixmapCairo(header.width, header.height,
-                                  RedDrawable::ARGB32, true, NULL))
+    : _pixmap (new RedPixmapSw(header.width, header.height,
+                               RedDrawable::ARGB32, true, NULL))
 {
     int stride = _pixmap->get_stride();
     uint8_t* dest = _pixmap->get_data();
@@ -131,8 +131,8 @@ MonoCursor::MonoCursor(const SpiceCursorHeader& header, const uint8_t* data)
     : _pixmap (NULL)
     , _height (header.height)
 {
-    _pixmap.reset(new RedPixmapCairo(header.width, _height * 2, RedDrawable::A1,
-                                     true, NULL));
+    _pixmap.reset(new RedPixmapSw(header.width, _height * 2, RedDrawable::A1,
+                                  true, NULL));
 
     int dest_stride = _pixmap->get_stride();
     uint8_t *dest_line = _pixmap->get_data();
@@ -175,12 +175,12 @@ private:
 };
 
 ColorCursor::ColorCursor(const SpiceCursorHeader& header)
-    : _pixmap (new RedPixmapCairo(header.width, header.height,
-                                  RedDrawable::ARGB32, true, NULL))
+    : _pixmap (new RedPixmapSw(header.width, header.height,
+                               RedDrawable::ARGB32, true, NULL))
     , _invers (NULL)
 {
-    _invers.reset(new RedPixmapCairo(header.width, header.height, RedDrawable::A1,
-                                     true, NULL));
+    _invers.reset(new RedPixmapSw(header.width, header.height, RedDrawable::A1,
+                                  true, NULL));
 }
 
 void ColorCursor::init_pixels(const SpiceCursorHeader& header, const uint8_t* pixels,
diff --git a/client/display_channel.cpp b/client/display_channel.cpp
index 1a326cf..bffd539 100644
--- a/client/display_channel.cpp
+++ b/client/display_channel.cpp
@@ -31,7 +31,7 @@
 #ifdef USE_OGL
 #include "red_gl_canvas.h"
 #endif
-#include "red_cairo_canvas.h"
+#include "red_sw_canvas.h"
 #include "red_client.h"
 #include "utils.h"
 #include "debug.h"
@@ -1080,17 +1080,17 @@ void DisplayChannel::on_disconnect()
     (*sync_event)->wait();
 }
 
-bool DisplayChannel::create_cairo_canvas(int surface_id, int width, int height, uint32_t format)
+bool DisplayChannel::create_sw_canvas(int surface_id, int width, int height, uint32_t format)
 {
     try {
-        CCanvas *canvas = new CCanvas(surface_id == 0, width, height, format,
+        SCanvas *canvas = new SCanvas(surface_id == 0, width, height, format,
                                       screen()->get_window(),
                                       _pixmap_cache, _palette_cache, _glz_window,
                                       surfaces_mngr.get_surfaces());
         surfaces_mngr.add_canvas(surface_id, canvas);
         surfaces_mngr.add_surface(surface_id, canvas->get_internal_canvas());
         if (surface_id == 0) {
-            LOG_INFO("display %d: using cairo", get_id());
+            LOG_INFO("display %d: using sw", get_id());
         }
     } catch (...) {
         return false;
@@ -1188,7 +1188,7 @@ void DisplayChannel::create_canvas(int surface_id, const std::vector<int>& canva
 
     for (i = 0; i < canvas_types.size(); i++) {
 
-        if (canvas_types[i] == CANVAS_OPTION_CAIRO && create_cairo_canvas(surface_id, width, height, format)) {
+        if (canvas_types[i] == CANVAS_OPTION_SW && create_sw_canvas(surface_id, width, height, format)) {
             break;
         }
 #ifdef USE_OGL
diff --git a/client/display_channel.h b/client/display_channel.h
index e864bfc..52b0cef 100644
--- a/client/display_channel.h
+++ b/client/display_channel.h
@@ -133,7 +133,7 @@ protected:
 private:
     void set_draw_handlers();
     void clear_draw_handlers();
-    bool create_cairo_canvas(int surface_id, int width, int height, uint32_t format);
+    bool create_sw_canvas(int surface_id, int width, int height, uint32_t format);
 #ifdef USE_OGL
     bool create_ogl_canvas(int surface_id, int width, int height, uint32_t format, bool recreate,
                            RenderType rendertype);
diff --git a/client/gui/gui.cpp b/client/gui/gui.cpp
index 3e0f257..9152ff1 100644
--- a/client/gui/gui.cpp
+++ b/client/gui/gui.cpp
@@ -7,7 +7,7 @@
 #include "screen.h"
 #include "utils.h"
 #include "debug.h"
-#include "red_pixmap_cairo.h"
+#include "red_pixmap_sw.h"
 #include "resource_provider.h"
 
 #include "CEGUISystem.h"
@@ -888,7 +888,7 @@ GUI::GUI(Application& app, Application::State state)
     : ScreenLayer (SCREEN_LAYER_GUI, false)
     , _app (app)
     , _state (state)
-    , _pixmap (new RedPixmapCairo(MAIN_GUI_WIDTH, MAIN_GUI_HEIGHT, RedDrawable::RGB32, true, 0))
+    , _pixmap (new RedPixmapSw(MAIN_GUI_WIDTH, MAIN_GUI_HEIGHT, RedDrawable::RGB32, true, 0))
     , _renderer (new CEGUI::SoftRenderer(_pixmap->get_data(), MAIN_GUI_WIDTH, MAIN_GUI_HEIGHT,
                                          _pixmap->get_stride()))
     , _gui_system (new CEGUI::System(_renderer, new CEGUIResourceProvider()))
diff --git a/client/gui/gui.h b/client/gui/gui.h
index fd7e56a..df41efe 100644
--- a/client/gui/gui.h
+++ b/client/gui/gui.h
@@ -6,7 +6,7 @@
 #include "inputs_handler.h"
 #include "application.h"
 
-class RedPixmapCairo;
+class RedPixmapSw;
 
 class GUI : public ScreenLayer, public KeyHandler {
 public:
@@ -86,7 +86,7 @@ private:
 private:
     Application& _app;
     Application::State _state;
-    RedPixmapCairo* _pixmap;
+    RedPixmapSw* _pixmap;
     CEGUI::SoftRenderer* _renderer;
     CEGUI::System* _gui_system;
     Dialog* _dialog;
diff --git a/client/red_cairo_canvas.cpp b/client/red_cairo_canvas.cpp
deleted file mode 100644
index b795acf..0000000
--- a/client/red_cairo_canvas.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "common.h"
-#include <stdint.h>
-#include "red_window.h"
-#include "red_cairo_canvas.h"
-#include "utils.h"
-#include "debug.h"
-#include "region.h"
-#include "red_pixmap_cairo.h"
-
-CCanvas::CCanvas(bool onscreen,
-                 int width, int height, uint32_t format, RedWindow *win,
-                 PixmapCache& pixmap_cache, PaletteCache& palette_cache,
-                 GlzDecoderWindow &glz_decoder_window, CSurfaces& csurfaces)
-    : Canvas (pixmap_cache, palette_cache, glz_decoder_window, csurfaces)
-    , _pixmap (0)
-{
-    if (onscreen) {
-        _pixmap = new RedPixmapCairo(width, height,
-                                     RedDrawable::format_from_surface(format),
-                                     true, win);
-        _canvas = canvas_create_for_data(width, height, format,
-                                         _pixmap->get_data(),
-                                         _pixmap->get_stride(),
-                                         &pixmap_cache.base,
-                                         &palette_cache.base,
-                                         &csurfaces.base,
-                                         &glz_decoder());
-    } else {
-        _canvas = canvas_create(width, height, format,
-                                &pixmap_cache.base,
-                                &palette_cache.base,
-                                &csurfaces.base,
-                                &glz_decoder());
-    }
-    if (_canvas == NULL) {
-        THROW("create canvas failed");
-    }
-}
-
-CCanvas::~CCanvas()
-{
-    _canvas->ops->destroy(_canvas);
-    _canvas = NULL;
-    if (_pixmap) {
-        delete _pixmap;
-        _pixmap = NULL;
-    }
-}
-
-void CCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc)
-{
-    pixman_box32_t *rects;
-    int num_rects;
-
-    ASSERT(_pixmap != NULL);
-
-    rects = pixman_region32_rectangles((pixman_region32_t *)&region, &num_rects);
-    for (int i = 0; i < num_rects; i++) {
-        SpiceRect r;
-
-        r.left = rects[i].x1;
-        r.top = rects[i].y1;
-        r.right = rects[i].x2;
-        r.bottom = rects[i].y2;
-        dest_dc.copy_pixels(*_pixmap, r.left, r.top, r);
-    }
-}
-
-void CCanvas::copy_pixels(const QRegion& region, RedDrawable* dest_dc, const PixmapHeader* pixmap)
-{
-    copy_pixels(region, *dest_dc);
-}
-
-CanvasType CCanvas::get_pixmap_type()
-{
-    return CANVAS_TYPE_CAIRO;
-}
-
diff --git a/client/red_cairo_canvas.h b/client/red_cairo_canvas.h
deleted file mode 100644
index 9f4911b..0000000
--- a/client/red_cairo_canvas.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_CCANVAS
-#define _H_CCANVAS
-
-#include "canvas.h"
-#include "cairo_canvas.h"
-
-class RedPixmap;
-
-class CCanvas: public Canvas {
-public:
-    CCanvas(bool onscreen,
-            int width, int height, uint32_t format, RedWindow *win,
-            PixmapCache& pixmap_cache, PaletteCache& palette_cache,
-            GlzDecoderWindow &glz_decoder_window, CSurfaces &csurfaces);
-    virtual ~CCanvas();
-
-    virtual void thread_touch() {}
-    virtual void copy_pixels(const QRegion& region, RedDrawable* dc,
-                             const PixmapHeader* pixmap);
-    virtual void copy_pixels(const QRegion& region, RedDrawable& dc);
-
-    virtual CanvasType get_pixmap_type();
-
-private:
-    RedPixmap *_pixmap;
-    unsigned long _base;
-    unsigned long _max;
-};
-
-#endif
-
diff --git a/client/red_gl_canvas.h b/client/red_gl_canvas.h
index dfe53d6..0260958 100644
--- a/client/red_gl_canvas.h
+++ b/client/red_gl_canvas.h
@@ -19,7 +19,7 @@
 #define _H_GCANVAS
 
 #include "canvas.h"
-#include "cairo_canvas.h"
+#include "sw_canvas.h"
 #include "gl_canvas.h"
 #include "red_pixmap_gl.h"
 #include "red_window.h"
diff --git a/client/red_pixmap_cairo.h b/client/red_pixmap_cairo.h
deleted file mode 100644
index 7f28532..0000000
--- a/client/red_pixmap_cairo.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_RED_PIXMAP_CAIRO
-#define _H_RED_PIXMAP_CAIRO
-
-#include "red_pixmap.h"
-#include "red_window.h"
-
-class RedPixmapCairo: public RedPixmap {
-public:
-    RedPixmapCairo(int width, int height, Format format, bool top_bottom, RedWindow *window);
-    ~RedPixmapCairo();
-};
-
-#endif
-
diff --git a/client/red_pixmap_gdi.h b/client/red_pixmap_gdi.h
index 524e6f3..bccce84 100644
--- a/client/red_pixmap_gdi.h
+++ b/client/red_pixmap_gdi.h
@@ -16,8 +16,8 @@
    License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
 
-#ifndef _H_RED_PIXMAP_CAIRO
-#define _H_RED_PIXMAP_CAIRO
+#ifndef _H_RED_PIXMAP_GDI
+#define _H_RED_PIXMAP_GDI
 
 #include "red_pixmap.h"
 
diff --git a/client/red_pixmap_sw.h b/client/red_pixmap_sw.h
new file mode 100644
index 0000000..c606135
--- /dev/null
+++ b/client/red_pixmap_sw.h
@@ -0,0 +1,31 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_RED_PIXMAP_SW
+#define _H_RED_PIXMAP_SW
+
+#include "red_pixmap.h"
+#include "red_window.h"
+
+class RedPixmapSw: public RedPixmap {
+public:
+    RedPixmapSw(int width, int height, Format format, bool top_bottom, RedWindow *window);
+    ~RedPixmapSw();
+};
+
+#endif
+
diff --git a/client/red_sw_canvas.cpp b/client/red_sw_canvas.cpp
new file mode 100644
index 0000000..05da430
--- /dev/null
+++ b/client/red_sw_canvas.cpp
@@ -0,0 +1,96 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include <stdint.h>
+#include "red_window.h"
+#include "red_sw_canvas.h"
+#include "utils.h"
+#include "debug.h"
+#include "region.h"
+#include "red_pixmap_sw.h"
+
+SCanvas::SCanvas(bool onscreen,
+                 int width, int height, uint32_t format, RedWindow *win,
+                 PixmapCache& pixmap_cache, PaletteCache& palette_cache,
+                 GlzDecoderWindow &glz_decoder_window, CSurfaces& csurfaces)
+    : Canvas (pixmap_cache, palette_cache, glz_decoder_window, csurfaces)
+    , _pixmap (0)
+{
+    if (onscreen) {
+        _pixmap = new RedPixmapSw(width, height,
+                                  RedDrawable::format_from_surface(format),
+                                  true, win);
+        _canvas = canvas_create_for_data(width, height, format,
+                                         _pixmap->get_data(),
+                                         _pixmap->get_stride(),
+                                         &pixmap_cache.base,
+                                         &palette_cache.base,
+                                         &csurfaces.base,
+                                         &glz_decoder());
+    } else {
+        _canvas = canvas_create(width, height, format,
+                                &pixmap_cache.base,
+                                &palette_cache.base,
+                                &csurfaces.base,
+                                &glz_decoder());
+    }
+    if (_canvas == NULL) {
+        THROW("create canvas failed");
+    }
+}
+
+SCanvas::~SCanvas()
+{
+    _canvas->ops->destroy(_canvas);
+    _canvas = NULL;
+    if (_pixmap) {
+        delete _pixmap;
+        _pixmap = NULL;
+    }
+}
+
+void SCanvas::copy_pixels(const QRegion& region, RedDrawable& dest_dc)
+{
+    pixman_box32_t *rects;
+    int num_rects;
+
+    ASSERT(_pixmap != NULL);
+
+    rects = pixman_region32_rectangles((pixman_region32_t *)&region, &num_rects);
+    for (int i = 0; i < num_rects; i++) {
+        SpiceRect r;
+
+        r.left = rects[i].x1;
+        r.top = rects[i].y1;
+        r.right = rects[i].x2;
+        r.bottom = rects[i].y2;
+        dest_dc.copy_pixels(*_pixmap, r.left, r.top, r);
+    }
+}
+
+void SCanvas::copy_pixels(const QRegion& region, RedDrawable* dest_dc, const PixmapHeader* pixmap)
+{
+    copy_pixels(region, *dest_dc);
+}
+
+CanvasType SCanvas::get_pixmap_type()
+{
+    return CANVAS_TYPE_SW;
+}
+
diff --git a/client/red_sw_canvas.h b/client/red_sw_canvas.h
new file mode 100644
index 0000000..ebac710
--- /dev/null
+++ b/client/red_sw_canvas.h
@@ -0,0 +1,49 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_CCANVAS
+#define _H_CCANVAS
+
+#include "canvas.h"
+#include "sw_canvas.h"
+
+class RedPixmap;
+
+class SCanvas: public Canvas {
+public:
+    SCanvas(bool onscreen,
+            int width, int height, uint32_t format, RedWindow *win,
+            PixmapCache& pixmap_cache, PaletteCache& palette_cache,
+            GlzDecoderWindow &glz_decoder_window, CSurfaces &csurfaces);
+    virtual ~SCanvas();
+
+    virtual void thread_touch() {}
+    virtual void copy_pixels(const QRegion& region, RedDrawable* dc,
+                             const PixmapHeader* pixmap);
+    virtual void copy_pixels(const QRegion& region, RedDrawable& dc);
+
+    virtual CanvasType get_pixmap_type();
+
+private:
+    RedPixmap *_pixmap;
+    unsigned long _base;
+    unsigned long _max;
+};
+
+#endif
+
diff --git a/client/screen.cpp b/client/screen.cpp
index c2bd4e7..1567978 100644
--- a/client/screen.cpp
+++ b/client/screen.cpp
@@ -22,7 +22,7 @@
 #include "utils.h"
 #include "debug.h"
 #include "monitor.h"
-#include "red_pixmap_cairo.h"
+#include "red_pixmap_sw.h"
 #include "resource.h"
 #include "icon.h"
 
@@ -171,8 +171,8 @@ void RedScreen::destroy_composit_area()
 void RedScreen::create_composit_area()
 {
     destroy_composit_area();
-    _composit_area = new RedPixmapCairo(_size.x, _size.y, _window.get_format(),
-                                        false, &_window);
+    _composit_area = new RedPixmapSw(_size.x, _size.y, _window.get_format(),
+                                     false, &_window);
 }
 
 void RedScreen::adjust_window_rect(int x, int y)
diff --git a/client/sw_canvas.cpp b/client/sw_canvas.cpp
new file mode 100644
index 0000000..33ec272
--- /dev/null
+++ b/client/sw_canvas.cpp
@@ -0,0 +1,24 @@
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "utils.h"
+
+#define CANVAS_ERROR(format, ...) THROW(format, ## __VA_ARGS__)
+
+#include "../common/sw_canvas.c"
+
diff --git a/client/windows/red_pixmap_cairo.cpp b/client/windows/red_pixmap_cairo.cpp
deleted file mode 100644
index 1c694db..0000000
--- a/client/windows/red_pixmap_cairo.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "common.h"
-#include "red_pixmap_cairo.h"
-#include "red_pixmap.h"
-#include "debug.h"
-#include "utils.h"
-#include "pixels_source_p.h"
-#include "platform_utils.h"
-
-struct RedPixmap_p {
-    PixelsSource_p pixels_source_p;
-    HBITMAP prev_bitmap;
-};
-
-RedPixmapCairo::RedPixmapCairo(int width, int height, RedDrawable::Format format,
-                               bool top_bottom, RedWindow *win)
-    : RedPixmap(width, height, format, top_bottom)
-{
-    DWORD *pixel_format;
-    ASSERT(format == RedDrawable::ARGB32 || format == RedDrawable::RGB32
-           || format == RedDrawable::RGB16_555 || format == RedDrawable::RGB16_565
-           || format == RedDrawable::A1);
-    ASSERT(sizeof(RedPixmap_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
-
-    struct {
-        BITMAPINFO inf;
-        RGBQUAD palette[255];
-    } bitmap_info;
-
-    memset(&bitmap_info, 0, sizeof(bitmap_info));
-    bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader);
-    bitmap_info.inf.bmiHeader.biWidth = _width;
-    bitmap_info.inf.bmiHeader.biHeight = top_bottom ? -_height : _height;
-
-/*#ifdef USE_OGL
-    // -----------------------------------------------------------------------------
-    // ensure valid access to additional stride.
-    // apparently glReadPixels validate ((ptr of last line) + GL_PACK_ROW_LENGTH + 1).
-    // seen on "ATI Radeon HD 2400 PRO" "2.0.6479 Release"
-    if (top_bottom) {
-        bitmap_info.inf.bmiHeader.biHeight--;
-    } else {
-        bitmap_info.inf.bmiHeader.biHeight++;
-    }
-    //------------------------------------------------------------------------------
-#endif*/
-
-    bitmap_info.inf.bmiHeader.biPlanes = 1;
-    bitmap_info.inf.bmiHeader.biBitCount = RedDrawable::format_to_bpp(format);
-    if (format == RedDrawable::RGB16_565) {
-        bitmap_info.inf.bmiHeader.biCompression = BI_BITFIELDS;
-    } else {
-        bitmap_info.inf.bmiHeader.biCompression = BI_RGB;
-    }
-    switch (format) {
-    case RedDrawable::A1:
-        bitmap_info.inf.bmiColors[0].rgbRed = 0;
-        bitmap_info.inf.bmiColors[0].rgbGreen = 0;
-        bitmap_info.inf.bmiColors[0].rgbBlue = 0;
-        bitmap_info.inf.bmiColors[1].rgbRed = 0xff;
-        bitmap_info.inf.bmiColors[1].rgbGreen = 0xff;
-        bitmap_info.inf.bmiColors[1].rgbBlue = 0xff;
-        break;
-    case RedDrawable::RGB16_565:
-        pixel_format = (DWORD *)bitmap_info.inf.bmiColors;
-        pixel_format[0] = 0xf800;
-        pixel_format[1] = 0x07e0;
-        pixel_format[2] = 0x001f;
-        break;
-    }
-    AutoDC dc(create_compatible_dc());
-    AutoGDIObject bitmap(CreateDIBSection(dc.get(), &bitmap_info.inf, 0,
-                                          (VOID **)&_data, NULL, 0));
-    if (!bitmap.valid()) {
-        THROW("create compatible bitmap failed");
-    }
-/*#ifdef USE_OGL
-    SetWindowOrgEx(dc.get(), 0, -1, NULL); // compensate for one pad line
-#endif*/
-    ((RedPixmap_p*)get_opaque())->prev_bitmap = (HBITMAP)SelectObject(dc.get(), bitmap.release());
-    ((RedPixmap_p*)get_opaque())->pixels_source_p.dc = dc.release();
-}
-
-RedPixmapCairo::~RedPixmapCairo()
-{
-    HDC dc = ((RedPixmap_p*)get_opaque())->pixels_source_p.dc;
-    if (dc) {
-        HBITMAP prev_bitmap = ((RedPixmap_p*)get_opaque())->prev_bitmap;
-        HBITMAP bitmap = (HBITMAP)SelectObject(dc, prev_bitmap);
-        DeleteObject(bitmap);
-        DeleteDC(dc);
-    }
-}
-
diff --git a/client/windows/red_pixmap_sw.cpp b/client/windows/red_pixmap_sw.cpp
new file mode 100644
index 0000000..1a76530
--- /dev/null
+++ b/client/windows/red_pixmap_sw.cpp
@@ -0,0 +1,111 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "red_pixmap_sw.h"
+#include "red_pixmap.h"
+#include "debug.h"
+#include "utils.h"
+#include "pixels_source_p.h"
+#include "platform_utils.h"
+
+struct RedPixmap_p {
+    PixelsSource_p pixels_source_p;
+    HBITMAP prev_bitmap;
+};
+
+RedPixmapSw::RedPixmapSw(int width, int height, RedDrawable::Format format,
+                         bool top_bottom, RedWindow *win)
+    : RedPixmap(width, height, format, top_bottom)
+{
+    DWORD *pixel_format;
+    ASSERT(format == RedDrawable::ARGB32 || format == RedDrawable::RGB32
+           || format == RedDrawable::RGB16_555 || format == RedDrawable::RGB16_565
+           || format == RedDrawable::A1);
+    ASSERT(sizeof(RedPixmap_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
+
+    struct {
+        BITMAPINFO inf;
+        RGBQUAD palette[255];
+    } bitmap_info;
+
+    memset(&bitmap_info, 0, sizeof(bitmap_info));
+    bitmap_info.inf.bmiHeader.biSize = sizeof(bitmap_info.inf.bmiHeader);
+    bitmap_info.inf.bmiHeader.biWidth = _width;
+    bitmap_info.inf.bmiHeader.biHeight = top_bottom ? -_height : _height;
+
+/*#ifdef USE_OGL
+    // -----------------------------------------------------------------------------
+    // ensure valid access to additional stride.
+    // apparently glReadPixels validate ((ptr of last line) + GL_PACK_ROW_LENGTH + 1).
+    // seen on "ATI Radeon HD 2400 PRO" "2.0.6479 Release"
+    if (top_bottom) {
+        bitmap_info.inf.bmiHeader.biHeight--;
+    } else {
+        bitmap_info.inf.bmiHeader.biHeight++;
+    }
+    //------------------------------------------------------------------------------
+#endif*/
+
+    bitmap_info.inf.bmiHeader.biPlanes = 1;
+    bitmap_info.inf.bmiHeader.biBitCount = RedDrawable::format_to_bpp(format);
+    if (format == RedDrawable::RGB16_565) {
+        bitmap_info.inf.bmiHeader.biCompression = BI_BITFIELDS;
+    } else {
+        bitmap_info.inf.bmiHeader.biCompression = BI_RGB;
+    }
+    switch (format) {
+    case RedDrawable::A1:
+        bitmap_info.inf.bmiColors[0].rgbRed = 0;
+        bitmap_info.inf.bmiColors[0].rgbGreen = 0;
+        bitmap_info.inf.bmiColors[0].rgbBlue = 0;
+        bitmap_info.inf.bmiColors[1].rgbRed = 0xff;
+        bitmap_info.inf.bmiColors[1].rgbGreen = 0xff;
+        bitmap_info.inf.bmiColors[1].rgbBlue = 0xff;
+        break;
+    case RedDrawable::RGB16_565:
+        pixel_format = (DWORD *)bitmap_info.inf.bmiColors;
+        pixel_format[0] = 0xf800;
+        pixel_format[1] = 0x07e0;
+        pixel_format[2] = 0x001f;
+        break;
+    }
+    AutoDC dc(create_compatible_dc());
+    AutoGDIObject bitmap(CreateDIBSection(dc.get(), &bitmap_info.inf, 0,
+                                          (VOID **)&_data, NULL, 0));
+    if (!bitmap.valid()) {
+        THROW("create compatible bitmap failed");
+    }
+/*#ifdef USE_OGL
+    SetWindowOrgEx(dc.get(), 0, -1, NULL); // compensate for one pad line
+#endif*/
+    ((RedPixmap_p*)get_opaque())->prev_bitmap = (HBITMAP)SelectObject(dc.get(), bitmap.release());
+    ((RedPixmap_p*)get_opaque())->pixels_source_p.dc = dc.release();
+}
+
+RedPixmapSw::~RedPixmapSw()
+{
+    HDC dc = ((RedPixmap_p*)get_opaque())->pixels_source_p.dc;
+    if (dc) {
+        HBITMAP prev_bitmap = ((RedPixmap_p*)get_opaque())->prev_bitmap;
+        HBITMAP bitmap = (HBITMAP)SelectObject(dc, prev_bitmap);
+        DeleteObject(bitmap);
+        DeleteDC(dc);
+    }
+}
+
diff --git a/client/windows/redc.vcproj b/client/windows/redc.vcproj
index 29e0bfb..d2540ce 100644
--- a/client/windows/redc.vcproj
+++ b/client/windows/redc.vcproj
@@ -43,7 +43,7 @@
 				Name="VCCLCompilerTool"
 				Optimization="0"
 				AdditionalIncludeDirectories=".;..;..\..\common;..\..\..\spice-protocol;..\..\common\win;&quot;..\..\common\win\my_getopt-1.5&quot;;&quot;$(SPICE_LIBS)\include&quot;;&quot;$(SPICE_LIBS)\include\pixman-1&quot;;&quot;$(SPICE_LIBS)\include\CEGUI-0.6.2&quot;"
-				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;CAIRO_CANVAS_ACCESS_TEST;CAIRO_CANVAS_CACHE;RED_DEBUG;CAIRO_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
+				PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;SW_CANVAS_ACCESS_TEST;SW_CANVAS_CACHE;RED_DEBUG;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
 				MinimalRebuild="false"
 				BasicRuntimeChecks="3"
 				RuntimeLibrary="1"
@@ -125,7 +125,7 @@
 			<Tool
 				Name="VCCLCompilerTool"
 				AdditionalIncludeDirectories=".;..;..\..\..\spice-protocol;..\..\common;..\..\common\win;&quot;..\..\common\win\my_getopt-1.5&quot;;&quot;$(SPICE_LIBS)\include&quot;;&quot;$(SPICE_LIBS)\include\pixman-1&quot;;&quot;$(SPICE_LIBS)\include\CEGUI-0.6.2&quot;"
-				PreprocessorDefinitions="WIN32;_WINDOWS;CAIRO_CANVAS_ACCESS_TEST;CAIRO_CANVAS_CACHE;CAIRO_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
+				PreprocessorDefinitions="WIN32;_WINDOWS;SW_CANVAS_ACCESS_TEST;SW_CANVAS_CACHE;SW_CANVAS_NO_CHUNKS;_WIN32_WINNT=0x0500;LOG4CPLUS_STATIC;USE_GLZ;PTW32_STATIC_LIB;CEGUI_STATIC"
 				RuntimeLibrary="0"
 				UsePrecompiledHeader="0"
 				WarningLevel="3"
@@ -192,7 +192,7 @@
 				>
 			</File>
 			<File
-				RelativePath="..\cairo_canvas.cpp"
+				RelativePath="..\sw_canvas.cpp"
 				>
 			</File>
 			<File
@@ -346,7 +346,7 @@
 				>
 			</File>
 			<File
-				RelativePath="..\red_cairo_canvas.cpp"
+				RelativePath="..\red_sw_canvas.cpp"
 				>
 			</File>
 			<File
@@ -374,7 +374,7 @@
 				>
 			</File>
 			<File
-				RelativePath=".\red_pixmap_cairo.cpp"
+				RelativePath=".\red_pixmap_sw.cpp"
 				>
 			</File>
 			<File
@@ -564,7 +564,7 @@
 				>
 			</File>
 			<File
-				RelativePath="..\red_cairo_canvas.h"
+				RelativePath="..\red_sw_canvas.h"
 				>
 			</File>
 			<File
diff --git a/client/x11/Makefile.am b/client/x11/Makefile.am
index e5a3b77..904fb42 100644
--- a/client/x11/Makefile.am
+++ b/client/x11/Makefile.am
@@ -6,9 +6,9 @@ CLIENT_DIR=$(top_srcdir)/client
 SUBDIRS = images
 
 INCLUDES = \
-	-DCAIRO_CANVAS_ACCESS_TEST			\
-	-DCAIRO_CANVAS_CACHE				\
-	-DCAIRO_CANVAS_NO_CHUNKS			\
+	-DSW_CANVAS_ACCESS_TEST				\
+	-DSW_CANVAS_CACHE				\
+	-DSW_CANVAS_NO_CHUNKS				\
 	-DUSE_GLZ					\
 	-DUSE_OGL					\
 	-D__STDC_LIMIT_MACROS				\
@@ -38,12 +38,12 @@ RED_COMMON_SRCS =					\
 	$(CLIENT_DIR)/audio_channels.h			\
 	$(CLIENT_DIR)/audio_devices.h			\
 	$(CLIENT_DIR)/cache.hpp				\
-	$(CLIENT_DIR)/cairo_canvas.cpp			\
+	$(CLIENT_DIR)/sw_canvas.cpp			\
 	$(CLIENT_DIR)/canvas.cpp			\
 	$(CLIENT_DIR)/canvas.h				\
 	$(CLIENT_DIR)/canvas_utils.cpp			\
-	$(CLIENT_DIR)/red_cairo_canvas.cpp		\
-	$(CLIENT_DIR)/red_cairo_canvas.h		\
+	$(CLIENT_DIR)/red_sw_canvas.cpp			\
+	$(CLIENT_DIR)/red_sw_canvas.h			\
 	$(CLIENT_DIR)/cmd_line_parser.cpp		\
 	$(CLIENT_DIR)/cmd_line_parser.h			\
 	$(CLIENT_DIR)/client_net_socket.cpp		\
@@ -93,7 +93,7 @@ RED_COMMON_SRCS =					\
 	$(CLIENT_DIR)/red_key.h				\
 	$(CLIENT_DIR)/red_peer.cpp			\
 	$(CLIENT_DIR)/red_peer.h			\
-	$(CLIENT_DIR)/red_pixmap_cairo.h		\
+	$(CLIENT_DIR)/red_pixmap_sw.h			\
 	$(CLIENT_DIR)/red_pixmap_gl.h			\
 	$(CLIENT_DIR)/red_pixmap.h			\
 	$(CLIENT_DIR)/red_types.h			\
@@ -142,7 +142,7 @@ spicec_SOURCES =			\
 	record.h			\
 	red_drawable.cpp		\
 	red_pixmap.cpp			\
-	red_pixmap_cairo.cpp		\
+	red_pixmap_sw.cpp		\
 	red_pixmap_gl.cpp		\
 	red_window.cpp			\
 	red_window_p.h			\
diff --git a/client/x11/red_pixmap_cairo.cpp b/client/x11/red_pixmap_cairo.cpp
deleted file mode 100644
index 863ed39..0000000
--- a/client/x11/red_pixmap_cairo.cpp
+++ /dev/null
@@ -1,91 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include "common.h"
-#include "red_pixmap_cairo.h"
-#include "debug.h"
-#include "utils.h"
-#include "pixels_source_p.h"
-#include "x_platform.h"
-
-RedPixmapCairo::RedPixmapCairo(int width, int height, RedDrawable::Format format,
-                               bool top_bottom, RedWindow *win)
-    : RedPixmap(width, height, format, top_bottom)
-{
-    ASSERT(format == RedDrawable::ARGB32 || format == RedDrawable::RGB32 ||
-	   format == RedDrawable::RGB16_555 || format == RedDrawable::RGB16_565 ||
-	   format == RedDrawable::A1);
-    ASSERT(sizeof(RedDrawable_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
-    pixman_image_t *pixman_image;
-    XImage *image;
-    XShmSegmentInfo *shminfo;
-    _data = NULL;
-    XVisualInfo *vinfo;
-    int screen_num;
-    RedDrawable::Format screen_format;
-
-    screen_num = win ? win->get_screen_num() : 0;
-    vinfo = XPlatform::get_vinfo()[screen_num];
-    screen_format = XPlatform::get_screen_format(screen_num);
-
-    image = NULL;
-    shminfo = NULL;
-
-    /* Only create XImage if same format as screen (needs re-verifying at
-       draw time!)  */
-    if (RedDrawable::format_copy_compatible(format, screen_format) ||
-        format == A1) {
-        image = XPlatform::create_x_image(format, width, height,
-                                          vinfo->depth, vinfo->visual,
-                                          &shminfo);
-        _stride = image->bytes_per_line;
-        _data = (uint8_t *)image->data;
-    } else {
-        _data = new uint8_t[height * _stride];
-    }
-
-    pixman_image = pixman_image_create_bits(RedDrawable::format_to_pixman(format),
-                                            _width, _height,
-                                            (uint32_t *)_data, _stride);
-    if (pixman_image == NULL) {
-        THROW("surf create failed");
-    }
-
-    ((PixelsSource_p*)get_opaque())->type = PIXELS_SOURCE_TYPE_PIXMAP;
-    ((PixelsSource_p*)get_opaque())->pixmap.shminfo = shminfo;
-    ((PixelsSource_p*)get_opaque())->pixmap.x_image = image;
-    ((PixelsSource_p*)get_opaque())->pixmap.pixman_image = pixman_image;
-    ((PixelsSource_p*)get_opaque())->pixmap.format = format;
-}
-
-RedPixmapCairo::~RedPixmapCairo()
-{
-    ASSERT(((PixelsSource_p*)get_opaque())->type == PIXELS_SOURCE_TYPE_PIXMAP);
-
-    XShmSegmentInfo *shminfo = ((PixelsSource_p*)get_opaque())->pixmap.shminfo;
-    XImage *image = ((PixelsSource_p*)get_opaque())->pixmap.x_image;
-
-    pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
-
-    if (image) {
-        XPlatform::free_x_image(image, shminfo);
-    } else {
-        delete[] _data;
-    }
-}
-
diff --git a/client/x11/red_pixmap_sw.cpp b/client/x11/red_pixmap_sw.cpp
new file mode 100644
index 0000000..2b514b7
--- /dev/null
+++ b/client/x11/red_pixmap_sw.cpp
@@ -0,0 +1,91 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "common.h"
+#include "red_pixmap_sw.h"
+#include "debug.h"
+#include "utils.h"
+#include "pixels_source_p.h"
+#include "x_platform.h"
+
+RedPixmapSw::RedPixmapSw(int width, int height, RedDrawable::Format format,
+                         bool top_bottom, RedWindow *win)
+    : RedPixmap(width, height, format, top_bottom)
+{
+    ASSERT(format == RedDrawable::ARGB32 || format == RedDrawable::RGB32 ||
+           format == RedDrawable::RGB16_555 || format == RedDrawable::RGB16_565 ||
+           format == RedDrawable::A1);
+    ASSERT(sizeof(RedDrawable_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
+    pixman_image_t *pixman_image;
+    XImage *image;
+    XShmSegmentInfo *shminfo;
+    _data = NULL;
+    XVisualInfo *vinfo;
+    int screen_num;
+    RedDrawable::Format screen_format;
+
+    screen_num = win ? win->get_screen_num() : 0;
+    vinfo = XPlatform::get_vinfo()[screen_num];
+    screen_format = XPlatform::get_screen_format(screen_num);
+
+    image = NULL;
+    shminfo = NULL;
+
+    /* Only create XImage if same format as screen (needs re-verifying at
+       draw time!)  */
+    if (RedDrawable::format_copy_compatible(format, screen_format) ||
+        format == A1) {
+        image = XPlatform::create_x_image(format, width, height,
+                                          vinfo->depth, vinfo->visual,
+                                          &shminfo);
+        _stride = image->bytes_per_line;
+        _data = (uint8_t *)image->data;
+    } else {
+        _data = new uint8_t[height * _stride];
+    }
+
+    pixman_image = pixman_image_create_bits(RedDrawable::format_to_pixman(format),
+                                            _width, _height,
+                                            (uint32_t *)_data, _stride);
+    if (pixman_image == NULL) {
+        THROW("surf create failed");
+    }
+
+    ((PixelsSource_p*)get_opaque())->type = PIXELS_SOURCE_TYPE_PIXMAP;
+    ((PixelsSource_p*)get_opaque())->pixmap.shminfo = shminfo;
+    ((PixelsSource_p*)get_opaque())->pixmap.x_image = image;
+    ((PixelsSource_p*)get_opaque())->pixmap.pixman_image = pixman_image;
+    ((PixelsSource_p*)get_opaque())->pixmap.format = format;
+}
+
+RedPixmapSw::~RedPixmapSw()
+{
+    ASSERT(((PixelsSource_p*)get_opaque())->type == PIXELS_SOURCE_TYPE_PIXMAP);
+
+    XShmSegmentInfo *shminfo = ((PixelsSource_p*)get_opaque())->pixmap.shminfo;
+    XImage *image = ((PixelsSource_p*)get_opaque())->pixmap.x_image;
+
+    pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
+
+    if (image) {
+        XPlatform::free_x_image(image, shminfo);
+    } else {
+        delete[] _data;
+    }
+}
+
diff --git a/common/Makefile.am b/common/Makefile.am
index f17f304..222965e 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -1,8 +1,8 @@
 NULL =
 
 COMMON_SRCS = 				\
-	cairo_canvas.h			\
-	cairo_canvas.c			\
+	sw_canvas.h			\
+	sw_canvas.c			\
 	pixman_utils.h			\
 	pixman_utils.c			\
 	canvas_base.h			\
diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c
deleted file mode 100644
index 48f14a9..0000000
--- a/common/cairo_canvas.c
+++ /dev/null
@@ -1,1332 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <math.h>
-#include "cairo_canvas.h"
-#define CANVAS_USE_PIXMAN
-#define CANVAS_SINGLE_INSTANCE
-#include "canvas_base.c"
-#include "rect.h"
-#include "region.h"
-#include "pixman_utils.h"
-
-typedef struct CairoCanvas CairoCanvas;
-
-struct CairoCanvas {
-    CanvasBase base;
-    uint32_t *private_data;
-    int private_data_size;
-    pixman_image_t *image;
-};
-
-static pixman_image_t *canvas_get_pixman_brush(CairoCanvas *canvas,
-                                               SpiceBrush *brush)
-{
-    switch (brush->type) {
-    case SPICE_BRUSH_TYPE_SOLID: {
-        uint32_t color = brush->u.color;
-        pixman_color_t c;
-
-        c.blue = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
-        color >>= canvas->base.color_shift;
-        c.green = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
-        color >>= canvas->base.color_shift;
-        c.red = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
-        c.alpha = 0xffff;
-
-        return pixman_image_create_solid_fill(&c);
-    }
-    case SPICE_BRUSH_TYPE_PATTERN: {
-        CairoCanvas *surface_canvas;
-        pixman_image_t* surface;
-        pixman_transform_t t;
-
-        surface_canvas = (CairoCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat);
-        if (surface_canvas) {
-            surface = surface_canvas->image;
-            surface = pixman_image_ref(surface);
-        } else {
-            surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE);
-        }
-        pixman_transform_init_translate(&t,
-                                        pixman_int_to_fixed(-brush->u.pattern.pos.x),
-                                        pixman_int_to_fixed(-brush->u.pattern.pos.y));
-        pixman_image_set_transform(surface, &t);
-        pixman_image_set_repeat(surface, PIXMAN_REPEAT_NORMAL);
-        return surface;
-    }
-    case SPICE_BRUSH_TYPE_NONE:
-        return NULL;
-    default:
-        CANVAS_ERROR("invalid brush type");
-    }
-}
-
-static pixman_image_t *get_image(SpiceCanvas *canvas)
-{
-    CairoCanvas *cairo_canvas = (CairoCanvas *)canvas;
-
-    pixman_image_ref(cairo_canvas->image);
-
-    return cairo_canvas->image;
-}
-
-static void copy_region(SpiceCanvas *spice_canvas,
-                        pixman_region32_t *dest_region,
-                        int dx, int dy)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_box32_t *dest_rects;
-    int n_rects;
-    int i, j, end_line;
-
-    dest_rects = pixman_region32_rectangles(dest_region, &n_rects);
-
-    if (dy > 0) {
-        if (dx >= 0) {
-            /* south-east: copy x and y in reverse order */
-            for (i = n_rects - 1; i >= 0; i--) {
-                spice_pixman_copy_rect(canvas->image,
-                                       dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
-                                       dest_rects[i].x2 - dest_rects[i].x1,
-                                       dest_rects[i].y2 - dest_rects[i].y1,
-                                       dest_rects[i].x1, dest_rects[i].y1);
-            }
-        } else {
-            /* south-west: Copy y in reverse order, but x in forward order */
-            i = n_rects - 1;
-
-            while (i >= 0) {
-                /* Copy all rects with same y in forward order */
-                for (end_line = i - 1;
-                     end_line >= 0 && dest_rects[end_line].y1 == dest_rects[i].y1;
-                     end_line--) {
-                }
-                for (j = end_line + 1; j <= i; j++) {
-                    spice_pixman_copy_rect(canvas->image,
-                                           dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
-                                           dest_rects[j].x2 - dest_rects[j].x1,
-                                           dest_rects[j].y2 - dest_rects[j].y1,
-                                           dest_rects[j].x1, dest_rects[j].y1);
-                }
-                i = end_line;
-            }
-        }
-    } else {
-        if (dx > 0) {
-            /* north-east: copy y in forward order, but x in reverse order */
-            i = 0;
-
-            while (i < n_rects) {
-                /* Copy all rects with same y in reverse order */
-                for (end_line = i;
-                     end_line < n_rects && dest_rects[end_line].y1 == dest_rects[i].y1;
-                     end_line++) {
-                }
-                for (j = end_line - 1; j >= i; j--) {
-                    spice_pixman_copy_rect(canvas->image,
-                                           dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
-                                           dest_rects[j].x2 - dest_rects[j].x1,
-                                           dest_rects[j].y2 - dest_rects[j].y1,
-                                           dest_rects[j].x1, dest_rects[j].y1);
-                }
-                i = end_line;
-            }
-        } else {
-            /* north-west: Copy x and y in forward order */
-            for (i = 0; i < n_rects; i++) {
-                spice_pixman_copy_rect(canvas->image,
-                                       dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
-                                       dest_rects[i].x2 - dest_rects[i].x1,
-                                       dest_rects[i].y2 - dest_rects[i].y1,
-                                       dest_rects[i].x1, dest_rects[i].y1);
-            }
-        }
-    }
-}
-
-static void fill_solid_spans(SpiceCanvas *spice_canvas,
-                             SpicePoint *points,
-                             int *widths,
-                             int n_spans,
-                             uint32_t color)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    int i;
-
-   for (i = 0; i < n_spans; i++) {
-        spice_pixman_fill_rect(canvas->image,
-                               points[i].x, points[i].y,
-                               widths[i],
-                               1,
-                               color);
-    }
-}
-
-static void fill_solid_rects(SpiceCanvas *spice_canvas,
-                             pixman_box32_t *rects,
-                             int n_rects,
-                             uint32_t color)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    int i;
-
-   for (i = 0; i < n_rects; i++) {
-        spice_pixman_fill_rect(canvas->image,
-                               rects[i].x1, rects[i].y1,
-                               rects[i].x2 - rects[i].x1,
-                               rects[i].y2 - rects[i].y1,
-                               color);
-    }
-}
-
-static void fill_solid_rects_rop(SpiceCanvas *spice_canvas,
-                                 pixman_box32_t *rects,
-                                 int n_rects,
-                                 uint32_t color,
-                                 SpiceROP rop)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    int i;
-
-   for (i = 0; i < n_rects; i++) {
-        spice_pixman_fill_rect_rop(canvas->image,
-                                   rects[i].x1, rects[i].y1,
-                                   rects[i].x2 - rects[i].x1,
-                                   rects[i].y2 - rects[i].y1,
-                                   color, rop);
-    }
-}
-
-static void __fill_tiled_rects(SpiceCanvas *spice_canvas,
-                               pixman_box32_t *rects,
-                               int n_rects,
-                               pixman_image_t *tile,
-                               int offset_x, int offset_y)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    int i;
-
-    for (i = 0; i < n_rects; i++) {
-        spice_pixman_tile_rect(canvas->image,
-                               rects[i].x1, rects[i].y1,
-                               rects[i].x2 - rects[i].x1,
-                               rects[i].y2 - rects[i].y1,
-                               tile, offset_x, offset_y);
-    }
-}
-
-static void fill_tiled_rects(SpiceCanvas *spice_canvas,
-                               pixman_box32_t *rects,
-                               int n_rects,
-                               pixman_image_t *tile,
-                               int offset_x, int offset_y)
-{
-    __fill_tiled_rects(spice_canvas, rects, n_rects, tile, offset_x, offset_y);
-}
-
-static void fill_tiled_rects_from_surface(SpiceCanvas *spice_canvas,
-                                          pixman_box32_t *rects,
-                                          int n_rects,
-                                          SpiceCanvas *surface_canvas,
-                                          int offset_x, int offset_y)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __fill_tiled_rects(spice_canvas, rects, n_rects, cairo_surface_canvas->image, offset_x,
-                       offset_y);
-}
-
-static void __fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
-                                   pixman_box32_t *rects,
-                                   int n_rects,
-                                   pixman_image_t *tile,
-                                   int offset_x, int offset_y,
-                                   SpiceROP rop)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    int i;
-
-    for (i = 0; i < n_rects; i++) {
-        spice_pixman_tile_rect_rop(canvas->image,
-                                   rects[i].x1, rects[i].y1,
-                                   rects[i].x2 - rects[i].x1,
-                                   rects[i].y2 - rects[i].y1,
-                                   tile, offset_x, offset_y,
-                                   rop);
-    }
-}
-static void fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
-                                 pixman_box32_t *rects,
-                                 int n_rects,
-                                 pixman_image_t *tile,
-                                 int offset_x, int offset_y,
-                                 SpiceROP rop)
-{
-    __fill_tiled_rects_rop(spice_canvas, rects, n_rects, tile, offset_x, offset_y, rop);
-}
-
-static void fill_tiled_rects_rop_from_surface(SpiceCanvas *spice_canvas,
-                                              pixman_box32_t *rects,
-                                              int n_rects,
-                                              SpiceCanvas *surface_canvas,
-                                              int offset_x, int offset_y,
-                                              SpiceROP rop)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __fill_tiled_rects_rop(spice_canvas, rects, n_rects, cairo_surface_canvas->image, offset_x,
-                           offset_y, rop);
-}
-
-/* Some pixman implementations of OP_OVER on xRGB32 sets
-   the high bit to 0xff (which is the right value if the
-   destination was ARGB32, and it should be ignored for
-   xRGB32. However, this fills our alpha bits with
-   data that is not wanted or expected by windows, and its
-   causing us to send rgba images rather than rgb images to
-   the client. So, we manually clear these bytes. */
-static void clear_dest_alpha(pixman_image_t *dest,
-                             int x, int y,
-                             int width, int height)
-{
-    uint32_t *data;
-    int stride;
-    int w, h;
-
-    w = pixman_image_get_width(dest);
-    h = pixman_image_get_height(dest);
-
-    if (x + width <= 0 || x >= w ||
-        y + height <= 0 || y >= h ||
-        width == 0 || height == 0) {
-        return;
-    }
-
-    if (x < 0) {
-        width += x;
-        x = 0;
-    }
-    if (x + width > w) {
-        width = w - x;
-    }
-
-    if (y < 0) {
-        height += y;
-        y = 0;
-    }
-    if (y + height > h) {
-        height = h - y;
-    }
-
-    stride = pixman_image_get_stride(dest);
-    data = (uint32_t *) (
-        (uint8_t *)pixman_image_get_data(dest) + y * stride + 4 * x);
-
-    if ((*data & 0xff000000U) == 0xff000000U) {
-        spice_pixman_fill_rect_rop(dest,
-                                   x, y, width, height,
-                                   0x00ffffff, SPICE_ROP_AND);
-    }
-}
-
-static void __blit_image(SpiceCanvas *spice_canvas,
-                         pixman_region32_t *region,
-                         pixman_image_t *src_image,
-                         int offset_x, int offset_y)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_box32_t *rects;
-    int n_rects, i;
-
-    rects = pixman_region32_rectangles(region, &n_rects);
-
-    for (i = 0; i < n_rects; i++) {
-        int src_x, src_y, dest_x, dest_y, width, height;
-
-        dest_x = rects[i].x1;
-        dest_y = rects[i].y1;
-        width = rects[i].x2 - rects[i].x1;
-        height = rects[i].y2 - rects[i].y1;
-
-        src_x = rects[i].x1 - offset_x;
-        src_y = rects[i].y1 - offset_y;
-
-        spice_pixman_blit(canvas->image,
-                          src_image,
-                          src_x, src_y,
-                          dest_x, dest_y,
-                          width, height);
-    }
-}
-
-static void blit_image(SpiceCanvas *spice_canvas,
-                       pixman_region32_t *region,
-                       pixman_image_t *src_image,
-                       int offset_x, int offset_y)
-{
-    __blit_image(spice_canvas, region, src_image, offset_x, offset_y);
-}
-
-static void blit_image_from_surface(SpiceCanvas *spice_canvas,
-                                    pixman_region32_t *region,
-                                    SpiceCanvas *surface_canvas,
-                                    int offset_x, int offset_y)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __blit_image(spice_canvas, region, cairo_surface_canvas->image, offset_x, offset_y);
-}
-
-static void __blit_image_rop(SpiceCanvas *spice_canvas,
-                             pixman_region32_t *region,
-                             pixman_image_t *src_image,
-                             int offset_x, int offset_y,
-                             SpiceROP rop)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_box32_t *rects;
-    int n_rects, i;
-
-    rects = pixman_region32_rectangles(region, &n_rects);
-
-    for (i = 0; i < n_rects; i++) {
-        int src_x, src_y, dest_x, dest_y, width, height;
-
-        dest_x = rects[i].x1;
-        dest_y = rects[i].y1;
-        width = rects[i].x2 - rects[i].x1;
-        height = rects[i].y2 - rects[i].y1;
-
-        src_x = rects[i].x1 - offset_x;
-        src_y = rects[i].y1 - offset_y;
-
-        spice_pixman_blit_rop(canvas->image,
-                              src_image,
-                              src_x, src_y,
-                              dest_x, dest_y,
-                              width, height, rop);
-    }
-}
-
-static void blit_image_rop(SpiceCanvas *spice_canvas,
-                           pixman_region32_t *region,
-                           pixman_image_t *src_image,
-                           int offset_x, int offset_y,
-                           SpiceROP rop)
-{
-    __blit_image_rop(spice_canvas, region, src_image, offset_x, offset_y, rop);
-}
-
-static void blit_image_rop_from_surface(SpiceCanvas *spice_canvas,
-                                        pixman_region32_t *region,
-                                        SpiceCanvas *surface_canvas,
-                                        int offset_x, int offset_y,
-                                        SpiceROP rop)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __blit_image_rop(spice_canvas, region, cairo_surface_canvas->image, offset_x, offset_y, rop);
-}
-
-
-
-static void __scale_image(SpiceCanvas *spice_canvas,
-                          pixman_region32_t *region,
-                          pixman_image_t *src,
-                          int src_x, int src_y,
-                          int src_width, int src_height,
-                          int dest_x, int dest_y,
-                          int dest_width, int dest_height,
-                          int scale_mode)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_transform_t transform;
-    double sx, sy;
-
-    sx = (double)(src_width) / (dest_width);
-    sy = (double)(src_height) / (dest_height);
-
-    pixman_image_set_clip_region32(canvas->image, region);
-
-    pixman_transform_init_scale(&transform,
-                                pixman_double_to_fixed(sx),
-                                pixman_double_to_fixed(sy));
-
-    pixman_image_set_transform(src, &transform);
-    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-    ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
-           scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
-    pixman_image_set_filter(src,
-                            (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
-                            PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
-                            NULL, 0);
-
-    pixman_image_composite32(PIXMAN_OP_SRC,
-                             src, NULL, canvas->image,
-                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
-                             0, 0, /* mask */
-                             dest_x, dest_y, /* dst */
-                             dest_width, dest_height);
-
-    pixman_transform_init_identity(&transform);
-    pixman_image_set_transform(src, &transform);
-
-    pixman_image_set_clip_region32(canvas->image, NULL);
-}
-
-static void scale_image(SpiceCanvas *spice_canvas,
-                        pixman_region32_t *region,
-                        pixman_image_t *src,
-                        int src_x, int src_y,
-                        int src_width, int src_height,
-                        int dest_x, int dest_y,
-                        int dest_width, int dest_height,
-                        int scale_mode)
-{
-    __scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, dest_y,
-                  dest_width,dest_height,scale_mode);
-}
-
-static void scale_image_from_surface(SpiceCanvas *spice_canvas,
-                                     pixman_region32_t *region,
-                                     SpiceCanvas *surface_canvas,
-                                     int src_x, int src_y,
-                                     int src_width, int src_height,
-                                     int dest_x, int dest_y,
-                                     int dest_width, int dest_height,
-                                     int scale_mode)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __scale_image(spice_canvas, region, cairo_surface_canvas->image, src_x, src_y, src_width,
-                  src_height, dest_x, dest_y, dest_width,dest_height,scale_mode);
-}
-
-static void __scale_image_rop(SpiceCanvas *spice_canvas,
-                              pixman_region32_t *region,
-                              pixman_image_t *src,
-                              int src_x, int src_y,
-                              int src_width, int src_height,
-                              int dest_x, int dest_y,
-                              int dest_width, int dest_height,
-                              int scale_mode, SpiceROP rop)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_transform_t transform;
-    pixman_image_t *scaled;
-    pixman_box32_t *rects;
-    int n_rects, i;
-    double sx, sy;
-
-    sx = (double)(src_width) / (dest_width);
-    sy = (double)(src_height) / (dest_height);
-
-    scaled = pixman_image_create_bits(spice_pixman_image_get_format(src),
-                                      dest_width,
-                                      dest_height,
-                                      NULL, 0);
-
-    pixman_region32_translate(region, -dest_x, -dest_y);
-    pixman_image_set_clip_region32(scaled, region);
-
-    pixman_transform_init_scale(&transform,
-                                pixman_double_to_fixed(sx),
-                                pixman_double_to_fixed(sy));
-
-    pixman_image_set_transform(src, &transform);
-    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-    ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
-           scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
-    pixman_image_set_filter(src,
-                            (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
-                            PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
-                            NULL, 0);
-
-    pixman_image_composite32(PIXMAN_OP_SRC,
-                             src, NULL, scaled,
-                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
-                             0, 0, /* mask */
-                             0, 0, /* dst */
-                             dest_width,
-                             dest_height);
-
-    pixman_transform_init_identity(&transform);
-    pixman_image_set_transform(src, &transform);
-
-    /* Translate back */
-    pixman_region32_translate(region, dest_x, dest_y);
-
-    rects = pixman_region32_rectangles(region, &n_rects);
-
-    for (i = 0; i < n_rects; i++) {
-        spice_pixman_blit_rop(canvas->image,
-                              scaled,
-                              rects[i].x1 - dest_x,
-                              rects[i].y1 - dest_y,
-                              rects[i].x1, rects[i].y1,
-                              rects[i].x2 - rects[i].x1,
-                              rects[i].y2 - rects[i].y1,
-                              rop);
-    }
-
-    pixman_image_unref(scaled);
-}
-
-static void scale_image_rop(SpiceCanvas *spice_canvas,
-                            pixman_region32_t *region,
-                            pixman_image_t *src,
-                            int src_x, int src_y,
-                            int src_width, int src_height,
-                            int dest_x, int dest_y,
-                            int dest_width, int dest_height,
-                            int scale_mode, SpiceROP rop)
-{
-    __scale_image_rop(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
-                      dest_y, dest_width, dest_height, scale_mode, rop);
-}
-
-static void scale_image_rop_from_surface(SpiceCanvas *spice_canvas,
-                                         pixman_region32_t *region,
-                                         SpiceCanvas *surface_canvas,
-                                         int src_x, int src_y,
-                                         int src_width, int src_height,
-                                         int dest_x, int dest_y,
-                                         int dest_width, int dest_height,
-                                         int scale_mode, SpiceROP rop)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __scale_image_rop(spice_canvas, region, cairo_surface_canvas->image, src_x, src_y, src_width,
-                      src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, rop);
-}
-
-static pixman_image_t *canvas_get_as_surface(CairoCanvas *canvas,
-                                          int with_alpha)
-{
-    pixman_image_t *target;
-
-    if (with_alpha &&
-        canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
-        target = pixman_image_create_bits(PIXMAN_a8r8g8b8,
-                                          pixman_image_get_width(canvas->image),
-                                          pixman_image_get_height(canvas->image),
-                                          pixman_image_get_data(canvas->image),
-                                          pixman_image_get_stride(canvas->image));
-    } else {
-        target = pixman_image_ref(canvas->image);
-    }
-
-    return target;
-}
-
-static void __blend_image(SpiceCanvas *spice_canvas,
-                          pixman_region32_t *region,
-                          int dest_has_alpha,
-                          pixman_image_t *src,
-                          int src_x, int src_y,
-                          int dest_x, int dest_y,
-                          int width, int height,
-                          int overall_alpha)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_image_t *mask, *dest;
-
-    dest = canvas_get_as_surface(canvas, dest_has_alpha);
-
-    pixman_image_set_clip_region32(dest, region);
-
-    mask = NULL;
-    if (overall_alpha != 0xff) {
-        pixman_color_t color = { 0 };
-        color.alpha = overall_alpha * 0x101;
-        mask = pixman_image_create_solid_fill(&color);
-    }
-
-    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-
-    pixman_image_composite32(PIXMAN_OP_OVER,
-                             src, mask, dest,
-                             src_x, src_y, /* src */
-                             0, 0, /* mask */
-                             dest_x, dest_y, /* dst */
-                             width,
-                             height);
-
-    if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
-        !dest_has_alpha) {
-        clear_dest_alpha(dest, dest_x, dest_y, width, height);
-    }
-
-    if (mask) {
-        pixman_image_unref(mask);
-    }
-
-    pixman_image_set_clip_region32(dest, NULL);
-    pixman_image_unref(dest);
-}
-
-static void blend_image(SpiceCanvas *spice_canvas,
-                        pixman_region32_t *region,
-                        int dest_has_alpha,
-                        pixman_image_t *src,
-                        int src_x, int src_y,
-                        int dest_x, int dest_y,
-                        int width, int height,
-                        int overall_alpha)
-{
-    __blend_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y,
-                  dest_x, dest_y, width, height,
-                  overall_alpha);
-}
-
-static void blend_image_from_surface(SpiceCanvas *spice_canvas,
-                                     pixman_region32_t *region,
-                                     int dest_has_alpha,
-                                     SpiceCanvas *surface_canvas,
-                                     int src_has_alpha,
-                                     int src_x, int src_y,
-                                     int dest_x, int dest_y,
-                                     int width, int height,
-                                     int overall_alpha)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    pixman_image_t *src;
-
-    src = canvas_get_as_surface(cairo_surface_canvas, src_has_alpha);
-    __blend_image(spice_canvas, region, dest_has_alpha,
-                  src, src_x, src_y,
-                  dest_x, dest_y,
-                  width, height, overall_alpha);
-    pixman_image_unref(src);
-}
-
-static void __blend_scale_image(SpiceCanvas *spice_canvas,
-                                pixman_region32_t *region,
-                                int dest_has_alpha,
-                                pixman_image_t *src,
-                                int src_x, int src_y,
-                                int src_width, int src_height,
-                                int dest_x, int dest_y,
-                                int dest_width, int dest_height,
-                                int scale_mode,
-                                int overall_alpha)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_transform_t transform;
-    pixman_image_t *mask, *dest;
-    double sx, sy;
-
-    sx = (double)(src_width) / (dest_width);
-    sy = (double)(src_height) / (dest_height);
-
-    dest = canvas_get_as_surface(canvas, dest_has_alpha);
-
-    pixman_image_set_clip_region32(dest, region);
-
-    pixman_transform_init_scale(&transform,
-                                pixman_double_to_fixed(sx),
-                                pixman_double_to_fixed(sy));
-
-    mask = NULL;
-    if (overall_alpha != 0xff) {
-        pixman_color_t color = { 0 };
-        color.alpha = overall_alpha * 0x101;
-        mask = pixman_image_create_solid_fill(&color);
-    }
-
-    pixman_image_set_transform(src, &transform);
-    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-    ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
-           scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
-    pixman_image_set_filter(src,
-                            (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
-                            PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
-                            NULL, 0);
-
-    pixman_image_composite32(PIXMAN_OP_OVER,
-                             src, mask, dest,
-                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
-                             0, 0, /* mask */
-                             dest_x, dest_y, /* dst */
-                             dest_width, dest_height);
-
-    if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
-        !dest_has_alpha) {
-        clear_dest_alpha(dest, dest_x, dest_y, dest_width, dest_height);
-    }
-
-    pixman_transform_init_identity(&transform);
-    pixman_image_set_transform(src, &transform);
-
-    if (mask) {
-        pixman_image_unref(mask);
-    }
-
-    pixman_image_set_clip_region32(dest, NULL);
-    pixman_image_unref(dest);
-}
-
-static void blend_scale_image(SpiceCanvas *spice_canvas,
-                              pixman_region32_t *region,
-                              int dest_has_alpha,
-                              pixman_image_t *src,
-                              int src_x, int src_y,
-                              int src_width, int src_height,
-                              int dest_x, int dest_y,
-                              int dest_width, int dest_height,
-                              int scale_mode,
-                              int overall_alpha)
-{
-    __blend_scale_image(spice_canvas, region, dest_has_alpha,
-                        src, src_x, src_y, src_width, src_height,
-                        dest_x, dest_y, dest_width, dest_height,
-                        scale_mode, overall_alpha);
-}
-
-static void blend_scale_image_from_surface(SpiceCanvas *spice_canvas,
-                                           pixman_region32_t *region,
-                                           int dest_has_alpha,
-                                           SpiceCanvas *surface_canvas,
-                                           int src_has_alpha,
-                                           int src_x, int src_y,
-                                           int src_width, int src_height,
-                                           int dest_x, int dest_y,
-                                           int dest_width, int dest_height,
-                                           int scale_mode,
-                                           int overall_alpha)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    pixman_image_t *src;
-
-    src = canvas_get_as_surface(cairo_surface_canvas, src_has_alpha);
-    __blend_scale_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, src_width,
-                        src_height, dest_x, dest_y, dest_width, dest_height, scale_mode,
-                        overall_alpha);
-    pixman_image_unref(src);
-}
-
-static void __colorkey_image(SpiceCanvas *spice_canvas,
-                             pixman_region32_t *region,
-                             pixman_image_t *src_image,
-                             int offset_x, int offset_y,
-                             uint32_t transparent_color)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_box32_t *rects;
-    int n_rects, i;
-
-    rects = pixman_region32_rectangles(region, &n_rects);
-
-    for (i = 0; i < n_rects; i++) {
-        int src_x, src_y, dest_x, dest_y, width, height;
-
-        dest_x = rects[i].x1;
-        dest_y = rects[i].y1;
-        width = rects[i].x2 - rects[i].x1;
-        height = rects[i].y2 - rects[i].y1;
-
-        src_x = rects[i].x1 - offset_x;
-        src_y = rects[i].y1 - offset_y;
-
-        spice_pixman_blit_colorkey(canvas->image,
-                                   src_image,
-                                   src_x, src_y,
-                                   dest_x, dest_y,
-                                   width, height,
-                                   transparent_color);
-    }
-}
-
-static void colorkey_image(SpiceCanvas *spice_canvas,
-                           pixman_region32_t *region,
-                           pixman_image_t *src_image,
-                           int offset_x, int offset_y,
-                           uint32_t transparent_color)
-{
-    __colorkey_image(spice_canvas, region, src_image, offset_x, offset_y, transparent_color);
-}
-
-static void colorkey_image_from_surface(SpiceCanvas *spice_canvas,
-                                        pixman_region32_t *region,
-                                        SpiceCanvas *surface_canvas,
-                                        int offset_x, int offset_y,
-                                        uint32_t transparent_color)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __colorkey_image(spice_canvas, region, cairo_surface_canvas->image, offset_x, offset_y,
-                     transparent_color);
-}
-
-static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
-                                   pixman_region32_t *region,
-                                   pixman_image_t *src,
-                                   int src_x, int src_y,
-                                   int src_width, int src_height,
-                                   int dest_x, int dest_y,
-                                   int dest_width, int dest_height,
-                                   uint32_t transparent_color)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_transform_t transform;
-    pixman_image_t *scaled;
-    pixman_box32_t *rects;
-    int n_rects, i;
-    double sx, sy;
-
-    sx = (double)(src_width) / (dest_width);
-    sy = (double)(src_height) / (dest_height);
-
-    scaled = pixman_image_create_bits(spice_pixman_image_get_format (src),
-                                      dest_width,
-                                      dest_height,
-                                      NULL, 0);
-
-    pixman_region32_translate(region, -dest_x, -dest_y);
-    pixman_image_set_clip_region32(scaled, region);
-
-    pixman_transform_init_scale(&transform,
-                                pixman_double_to_fixed(sx),
-                                pixman_double_to_fixed(sy));
-
-    pixman_image_set_transform(src, &transform);
-    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-    pixman_image_set_filter(src,
-                            PIXMAN_FILTER_NEAREST,
-                            NULL, 0);
-
-    pixman_image_composite32(PIXMAN_OP_SRC,
-                             src, NULL, scaled,
-                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
-                             0, 0, /* mask */
-                             0, 0, /* dst */
-                             dest_width,
-                             dest_height);
-
-    pixman_transform_init_identity(&transform);
-    pixman_image_set_transform(src, &transform);
-
-    /* Translate back */
-    pixman_region32_translate(region, dest_x, dest_y);
-
-    rects = pixman_region32_rectangles(region, &n_rects);
-
-    for (i = 0; i < n_rects; i++) {
-        spice_pixman_blit_colorkey(canvas->image,
-                                   scaled,
-                                   rects[i].x1 - dest_x,
-                                   rects[i].y1 - dest_y,
-                                   rects[i].x1, rects[i].y1,
-                                   rects[i].x2 - rects[i].x1,
-                                   rects[i].y2 - rects[i].y1,
-                                   transparent_color);
-    }
-
-    pixman_image_unref(scaled);
-}
-
-static void colorkey_scale_image(SpiceCanvas *spice_canvas,
-                                 pixman_region32_t *region,
-                                 pixman_image_t *src,
-                                 int src_x, int src_y,
-                                 int src_width, int src_height,
-                                 int dest_x, int dest_y,
-                                 int dest_width, int dest_height,
-                                 uint32_t transparent_color)
-{
-    __colorkey_scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
-                           dest_y, dest_width, dest_height, transparent_color);
-}
-
-static void colorkey_scale_image_from_surface(SpiceCanvas *spice_canvas,
-                                              pixman_region32_t *region,
-                                              SpiceCanvas *surface_canvas,
-                                              int src_x, int src_y,
-                                              int src_width, int src_height,
-                                              int dest_x, int dest_y,
-                                              int dest_width, int dest_height,
-                                              uint32_t transparent_color)
-{
-    CairoCanvas *cairo_surface_canvas = (CairoCanvas *)surface_canvas;
-    __colorkey_scale_image(spice_canvas, region, cairo_surface_canvas->image, src_x, src_y,
-                           src_width, src_height, dest_x, dest_y, dest_width, dest_height,
-                           transparent_color);
-}
-
-static void canvas_put_image(SpiceCanvas *spice_canvas,
-#ifdef WIN32
-                             HDC dc,
-#endif
-                             const SpiceRect *dest, const uint8_t *src_data,
-                             uint32_t src_width, uint32_t src_height, int src_stride,
-                             const QRegion *clip)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_image_t *src;
-    int dest_width;
-    int dest_height;
-    double sx, sy;
-    pixman_transform_t transform;
-
-    src = pixman_image_create_bits(PIXMAN_x8r8g8b8,
-                                   src_width,
-                                   src_height,
-                                   (uint32_t*)src_data,
-                                   src_stride);
-
-
-    if (clip) {
-        pixman_image_set_clip_region32 (canvas->image, (pixman_region32_t *)clip);
-    }
-
-    dest_width = dest->right - dest->left;
-    dest_height = dest->bottom - dest->top;
-
-    if (dest_width != src_width || dest_height != src_height) {
-        sx = (double)(src_width) / (dest_width);
-        sy = (double)(src_height) / (dest_height);
-
-        pixman_transform_init_scale(&transform,
-                                    pixman_double_to_fixed(sx),
-                                    pixman_double_to_fixed(sy));
-        pixman_image_set_transform(src, &transform);
-        pixman_image_set_filter(src,
-                                PIXMAN_FILTER_NEAREST,
-                                NULL, 0);
-    }
-
-    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
-
-    pixman_image_composite32(PIXMAN_OP_SRC,
-                             src, NULL, canvas->image,
-                             0, 0, /* src */
-                             0, 0, /* mask */
-                             dest->left, dest->top, /* dst */
-                             dest_width, dest_height);
-
-
-    if (clip) {
-        pixman_image_set_clip_region32(canvas->image, NULL);
-    }
-    pixman_image_unref(src);
-}
-
-
-static void canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox,
-                             SpiceClip *clip, SpiceText *text)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_region32_t dest_region;
-    pixman_image_t *str_mask, *brush;
-    SpiceString *str;
-    SpicePoint pos;
-    int depth;
-
-    pixman_region32_init_rect(&dest_region,
-                              bbox->left, bbox->top,
-                              bbox->right - bbox->left,
-                              bbox->bottom - bbox->top);
-
-    canvas_clip_pixman(&canvas->base, &dest_region, clip);
-
-    if (!pixman_region32_not_empty(&dest_region)) {
-        touch_brush(&canvas->base, &text->fore_brush);
-        touch_brush(&canvas->base, &text->back_brush);
-        pixman_region32_fini(&dest_region);
-        return;
-    }
-
-    if (!rect_is_empty(&text->back_area)) {
-        pixman_region32_t back_region;
-
-        /* Nothing else makes sense for text and we should deprecate it
-         * and actually it means OVER really */
-        ASSERT(text->fore_mode == SPICE_ROPD_OP_PUT);
-
-        pixman_region32_init_rect(&back_region,
-                                  text->back_area.left,
-                                  text->back_area.top,
-                                  text->back_area.right - text->back_area.left,
-                                  text->back_area.bottom - text->back_area.top);
-
-        pixman_region32_intersect(&back_region, &back_region, &dest_region);
-
-        if (pixman_region32_not_empty(&back_region)) {
-            draw_brush(spice_canvas, &back_region, &text->back_brush, SPICE_ROP_COPY);
-        }
-
-        pixman_region32_fini(&back_region);
-    }
-    str = (SpiceString *)SPICE_GET_ADDRESS(text->str);
-
-    if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) {
-        depth = 1;
-    } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) {
-        depth = 4;
-    } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) {
-        WARN("untested path A8 glyphs");
-        depth = 8;
-    } else {
-        WARN("unsupported path vector glyphs");
-        pixman_region32_fini (&dest_region);
-        return;
-    }
-
-    brush = canvas_get_pixman_brush(canvas, &text->fore_brush);
-
-    str_mask = canvas_get_str_mask(&canvas->base, str, depth, &pos);
-    if (brush) {
-        pixman_image_set_clip_region32(canvas->image, &dest_region);
-
-        pixman_image_composite32(PIXMAN_OP_OVER,
-                                 brush,
-                                 str_mask,
-                                 canvas->image,
-                                 0, 0,
-                                 0, 0,
-                                 pos.x, pos.y,
-                                 pixman_image_get_width(str_mask),
-                                 pixman_image_get_height(str_mask));
-        if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
-            clear_dest_alpha(canvas->image, pos.x, pos.y,
-                             pixman_image_get_width(str_mask),
-                             pixman_image_get_height(str_mask));
-        }
-        pixman_image_unref(brush);
-
-        pixman_image_set_clip_region32(canvas->image, NULL);
-    }
-    pixman_image_unref(str_mask);
-    pixman_region32_fini(&dest_region);
-}
-
-static void canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest,
-                             int dest_stride, const SpiceRect *area)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    pixman_image_t* surface;
-    uint8_t *src;
-    int src_stride;
-    uint8_t *dest_end;
-    int bpp;
-
-    ASSERT(canvas && area);
-
-    surface = canvas->image;
-
-    bpp = spice_pixman_image_get_bpp(surface) / 8;
-
-    src_stride = pixman_image_get_stride(surface);
-    src = (uint8_t *)pixman_image_get_data(surface) +
-        area->top * src_stride + area->left * bpp;
-    dest_end = dest + (area->bottom - area->top) * dest_stride;
-    for (; dest != dest_end; dest += dest_stride, src += src_stride) {
-        memcpy(dest, src, (area->right - area->left) * bpp);
-    }
-}
-
-static void canvas_clear(SpiceCanvas *spice_canvas)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    spice_pixman_fill_rect(canvas->image,
-                           0, 0,
-                           pixman_image_get_width(canvas->image),
-                           pixman_image_get_height(canvas->image),
-                           0);
-}
-
-static void canvas_set_access_params(SpiceCanvas *spice_canvas,
-                                     unsigned long base, unsigned long max)
-{
-#ifdef CAIRO_CANVAS_ACCESS_TEST
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    __canvas_set_access_params(&canvas->base, base, max);
-#endif
-}
-
-static void canvas_destroy(SpiceCanvas *spice_canvas)
-{
-    CairoCanvas *canvas = (CairoCanvas *)spice_canvas;
-    if (!canvas) {
-        return;
-    }
-    pixman_image_unref(canvas->image);
-    canvas_base_destroy(&canvas->base);
-    if (canvas->private_data) {
-        free(canvas->private_data);
-    }
-    free(canvas);
-}
-
-static int need_init = 1;
-static SpiceCanvasOps cairo_canvas_ops;
-
-static SpiceCanvas *canvas_create_common(pixman_image_t *image,
-                                         uint32_t format
-#ifdef CAIRO_CANVAS_CACHE
-                           , SpiceImageCache *bits_cache
-                           , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                           , SpiceImageCache *bits_cache
-#endif
-                           , SpiceImageSurfaces *surfaces
-                           , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                           , SpiceVirtMapping *virt_mapping
-#endif
-                           )
-{
-    CairoCanvas *canvas;
-    int init_ok;
-
-    if (need_init) {
-        return NULL;
-    }
-    spice_pixman_image_set_format(image,
-                                  spice_surface_format_to_pixman (format));
-
-    canvas = spice_new0(CairoCanvas, 1);
-    init_ok = canvas_base_init(&canvas->base, &cairo_canvas_ops,
-                               pixman_image_get_width (image),
-                               pixman_image_get_height (image),
-                               format
-#ifdef CAIRO_CANVAS_CACHE
-                               , bits_cache
-                               , palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                               , bits_cache
-#endif
-                               , surfaces
-                               , glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                               , virt_mapping
-#endif
-                               );
-    canvas->private_data = NULL;
-    canvas->private_data_size = 0;
-
-    canvas->image = image;
-
-    return (SpiceCanvas *)canvas;
-}
-
-SpiceCanvas *canvas_create(int width, int height, uint32_t format
-#ifdef CAIRO_CANVAS_CACHE
-                           , SpiceImageCache *bits_cache
-                           , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                           , SpiceImageCache *bits_cache
-#endif
-                           , SpiceImageSurfaces *surfaces
-                           , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                           , SpiceVirtMapping *virt_mapping
-#endif
-                           )
-{
-    pixman_image_t *image;
-
-    image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
-                                     width, height, NULL, 0);
-
-    return canvas_create_common(image, format
-#ifdef CAIRO_CANVAS_CACHE
-                                , bits_cache
-                                , palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                                , bits_cache
-#endif
-                                , surfaces
-                                , glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                                , virt_mapping
-#endif
-                                );
-}
-
-SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
-                                    uint8_t *data, size_t stride
-#ifdef CAIRO_CANVAS_CACHE
-                           , SpiceImageCache *bits_cache
-                           , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                           , SpiceImageCache *bits_cache
-#endif
-                           , SpiceImageSurfaces *surfaces
-                           , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                           , SpiceVirtMapping *virt_mapping
-#endif
-                           )
-{
-    pixman_image_t *image;
-
-    image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
-                                     width, height, (uint32_t *)data, stride);
-
-    return canvas_create_common(image, format
-#ifdef CAIRO_CANVAS_CACHE
-                                , bits_cache
-                                , palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                                , bits_cache
-#endif
-                                , surfaces
-                                , glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                                , virt_mapping
-#endif
-                                );
-}
-
-void cairo_canvas_init() //unsafe global function
-{
-    if (!need_init) {
-        return;
-    }
-    need_init = 0;
-
-    canvas_base_init_ops(&cairo_canvas_ops);
-    cairo_canvas_ops.draw_text = canvas_draw_text;
-    cairo_canvas_ops.put_image = canvas_put_image;
-    cairo_canvas_ops.clear = canvas_clear;
-    cairo_canvas_ops.read_bits = canvas_read_bits;
-    cairo_canvas_ops.set_access_params = canvas_set_access_params;
-    cairo_canvas_ops.destroy = canvas_destroy;
-
-    cairo_canvas_ops.fill_solid_spans = fill_solid_spans;
-    cairo_canvas_ops.fill_solid_rects = fill_solid_rects;
-    cairo_canvas_ops.fill_solid_rects_rop = fill_solid_rects_rop;
-    cairo_canvas_ops.fill_tiled_rects = fill_tiled_rects;
-    cairo_canvas_ops.fill_tiled_rects_from_surface = fill_tiled_rects_from_surface;
-    cairo_canvas_ops.fill_tiled_rects_rop = fill_tiled_rects_rop;
-    cairo_canvas_ops.fill_tiled_rects_rop_from_surface = fill_tiled_rects_rop_from_surface;
-    cairo_canvas_ops.blit_image = blit_image;
-    cairo_canvas_ops.blit_image_from_surface = blit_image_from_surface;
-    cairo_canvas_ops.blit_image_rop = blit_image_rop;
-    cairo_canvas_ops.blit_image_rop_from_surface = blit_image_rop_from_surface;
-    cairo_canvas_ops.scale_image = scale_image;
-    cairo_canvas_ops.scale_image_from_surface = scale_image_from_surface;
-    cairo_canvas_ops.scale_image_rop = scale_image_rop;
-    cairo_canvas_ops.scale_image_rop_from_surface = scale_image_rop_from_surface;
-    cairo_canvas_ops.blend_image = blend_image;
-    cairo_canvas_ops.blend_image_from_surface = blend_image_from_surface;
-    cairo_canvas_ops.blend_scale_image = blend_scale_image;
-    cairo_canvas_ops.blend_scale_image_from_surface = blend_scale_image_from_surface;
-    cairo_canvas_ops.colorkey_image = colorkey_image;
-    cairo_canvas_ops.colorkey_image_from_surface = colorkey_image_from_surface;
-    cairo_canvas_ops.colorkey_scale_image = colorkey_scale_image;
-    cairo_canvas_ops.colorkey_scale_image_from_surface = colorkey_scale_image_from_surface;
-    cairo_canvas_ops.copy_region = copy_region;
-    cairo_canvas_ops.get_image = get_image;
-    rop3_init();
-}
diff --git a/common/cairo_canvas.h b/common/cairo_canvas.h
deleted file mode 100644
index c97380e..0000000
--- a/common/cairo_canvas.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/*
-   Copyright (C) 2009 Red Hat, Inc.
-
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   This library 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
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H__CANVAS
-#define _H__CANVAS
-
-#include <stdint.h>
-
-#include <spice/draw.h>
-#include "pixman_utils.h"
-#include "canvas_base.h"
-#include "region.h"
-
-SpiceCanvas *canvas_create(int width, int height, uint32_t format
-#ifdef CAIRO_CANVAS_CACHE
-                           , SpiceImageCache *bits_cache
-                           , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                           , SpiceImageCache *bits_cache
-#endif
-			   , SpiceImageSurfaces *surfaces
-                           , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                           , SpiceVirtMapping *virt_mapping
-#endif
-                           );
-
-SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, size_t stride
-#ifdef CAIRO_CANVAS_CACHE
-                           , SpiceImageCache *bits_cache
-                           , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
-                           , SpiceImageCache *bits_cache
-#endif
-			   , SpiceImageSurfaces *surfaces
-                           , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
-                           , SpiceVirtMapping *virt_mapping
-#endif
-                           );
-
-
-void cairo_canvas_init();
-
-#endif
diff --git a/common/canvas_base.c b/common/canvas_base.c
index 3600a2f..9fd2ae2 100644
--- a/common/canvas_base.c
+++ b/common/canvas_base.c
@@ -43,7 +43,7 @@
 }
 #endif
 
-#ifdef CAIRO_CANVAS_ACCESS_TEST
+#ifdef SW_CANVAS_ACCESS_TEST
 #define access_test(cancas, ptr, size)                                                         \
     if ((unsigned long)(ptr) < (cancas)->base ||                                               \
                                             (unsigned long)(ptr) + (size) > (cancas)->max) {   \
@@ -163,7 +163,7 @@ typedef struct QuicData {
     QuicUsrContext usr;
     QuicContext *quic;
     jmp_buf jmp_env;
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
     SPICE_ADDRESS next;
     SpiceVirtMapping *virt_mapping;
 #endif
@@ -175,7 +175,7 @@ typedef struct CanvasBase {
     uint32_t color_shift;
     uint32_t color_mask;
     QuicData quic_data;
-#ifdef CAIRO_CANVAS_ACCESS_TEST
+#ifdef SW_CANVAS_ACCESS_TEST
     unsigned long base;
     unsigned long max;
 #endif
@@ -185,10 +185,10 @@ typedef struct CanvasBase {
     int height;
     pixman_region32_t canvas_region;
 
-#if defined(CAIRO_CANVAS_CACHE) || defined(CAIRO_CANVAS_IMAGE_CACHE)
+#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
     SpiceImageCache *bits_cache;
 #endif
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
     SpicePaletteCache *palette_cache;
 #endif
 #ifdef WIN32
@@ -205,7 +205,7 @@ typedef struct CanvasBase {
 } CanvasBase;
 
 
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
 
 #ifdef __GNUC__
 #define ATTR_PACKED __attribute__ ((__packed__))
@@ -453,7 +453,7 @@ static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceQUICImage *image
     int stride;
     int width;
     int height;
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
     DataChunk **tmp;
     DataChunk *chunk;
 #endif
@@ -463,7 +463,7 @@ static pixman_image_t *canvas_get_quic(CanvasBase *canvas, SpiceQUICImage *image
         CANVAS_ERROR("quic error, %s", quic_data->message_buf);
     }
 
-#ifdef CAIRO_CANVAS_NO_CHUNKS
+#ifdef SW_CANVAS_NO_CHUNKS
     if (quic_decode_begin(quic_data->quic, (uint32_t *)image->quic.data,
                           image->quic.data_size >> 2, &type, &width, &height) == QUIC_ERROR) {
         CANVAS_ERROR("quic decode begin failed");
@@ -586,7 +586,7 @@ static pixman_image_t *canvas_bitmap_to_surface(CanvasBase *canvas, SpiceBitmap*
 }
 
 
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
 
 static inline SpicePalette *canvas_get_palette(CanvasBase *canvas, SPICE_ADDRESS base_palette, uint8_t flags)
 {
@@ -942,7 +942,7 @@ static SpiceCanvas *canvas_get_surface_mask_internal(CanvasBase *canvas, SPICE_A
     return NULL;
 }
 
-#if defined(CAIRO_CANVAS_CACHE) || defined(CAIRO_CANVAS_IMAGE_CACHE)
+#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
 
 //#define DEBUG_LZ
 
@@ -987,7 +987,7 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
         surface = canvas_get_quic(canvas, image, 0, want_original);
         break;
     }
-#ifdef CAIRO_CANVAS_NO_CHUNKS
+#ifdef SW_CANVAS_NO_CHUNKS
     case SPICE_IMAGE_TYPE_LZ_PLT: {
         access_test(canvas, descriptor, sizeof(SpiceLZPLTImage));
         LZImage *image = (LZImage *)descriptor;
@@ -1002,7 +1002,7 @@ static pixman_image_t *canvas_get_image_internal(CanvasBase *canvas, SPICE_ADDRE
     }
 #endif
 
-#if defined(CAIRO_CANVAS_CACHE)
+#if defined(SW_CANVAS_CACHE)
     case SPICE_IMAGE_TYPE_GLZ_RGB: {
         access_test(canvas, descriptor, sizeof(SpiceLZRGBImage));
         LZImage *image = (LZImage *)descriptor;
@@ -1340,7 +1340,7 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int
     access_test(canvas, descriptor, sizeof(SpiceImageDescriptor));
     need_invers = mask->flags & SPICE_MASK_FLAGS_INVERS;
 
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
     cache_me = descriptor->flags & SPICE_IMAGE_FLAGS_CACHE_ME;
 #else
     cache_me = 0;
@@ -1354,7 +1354,7 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int
         surface = canvas_get_bitmap_mask(canvas, &bitmap->bitmap, is_invers);
         break;
     }
-#if defined(CAIRO_CANVAS_CACHE) || defined(CAIRO_CANVAS_IMAGE_CACHE)
+#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
     case SPICE_IMAGE_TYPE_FROM_CACHE:
         surface = canvas->bits_cache->ops->get(canvas->bits_cache, descriptor->id);
         is_invers = 0;
@@ -1364,7 +1364,7 @@ static pixman_image_t *canvas_get_mask(CanvasBase *canvas, SpiceQMask *mask, int
         CANVAS_ERROR("invalid image type");
     }
 
-#if defined(CAIRO_CANVAS_CACHE) || defined(CAIRO_CANVAS_IMAGE_CACHE)
+#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
     if (cache_me) {
         canvas->bits_cache->ops->put(canvas->bits_cache, descriptor->id, surface);
     }
@@ -1658,7 +1658,7 @@ static void quic_usr_free(QuicUsrContext *usr, void *ptr)
     free(ptr);
 }
 
-#ifdef CAIRO_CANVAS_NO_CHUNKS
+#ifdef SW_CANVAS_NO_CHUNKS
 
 static int quic_usr_more_space(QuicUsrContext *usr, uint32_t **io_ptr, int rows_completed)
 {
@@ -1736,7 +1736,7 @@ static int quic_usr_more_lines(QuicUsrContext *usr, uint8_t **lines)
     return 0;
 }
 
-#ifdef CAIRO_CANVAS_ACCESS_TEST
+#ifdef SW_CANVAS_ACCESS_TEST
 static void __canvas_set_access_params(CanvasBase *canvas, unsigned long base, unsigned long max)
 {
     canvas->base = base;
@@ -1747,7 +1747,7 @@ static void __canvas_set_access_params(CanvasBase *canvas, unsigned long base, u
 static void canvas_base_destroy(CanvasBase *canvas)
 {
     quic_destroy(canvas->quic_data.quic);
-#ifdef CAIRO_CANVAS_NO_CHUNKS
+#ifdef SW_CANVAS_NO_CHUNKS
     lz_destroy(canvas->lz_data.lz);
 #endif
 #ifdef GDI_CANVAS
@@ -3226,15 +3226,15 @@ inline static void canvas_base_init_ops(SpiceCanvasOps *ops)
 
 static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
                             int width, int height, uint32_t format
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
                             , SpiceImageCache *bits_cache
                             , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
+#elif defined(SW_CANVAS_IMAGE_CACHE)
                             , SpiceImageCache *bits_cache
 #endif
                             , SpiceImageSurfaces *surfaces
                             , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
                             , SpiceVirtMapping *virt_mapping
 #endif
                             )
@@ -3247,13 +3247,13 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
     canvas->quic_data.usr.free = quic_usr_free;
     canvas->quic_data.usr.more_space = quic_usr_more_space;
     canvas->quic_data.usr.more_lines = quic_usr_more_lines;
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
     canvas->quic_data.virt_mapping = virt_mapping;
 #endif
     if (!(canvas->quic_data.quic = quic_create(&canvas->quic_data.usr))) {
             return 0;
     }
-#ifdef CAIRO_CANVAS_NO_CHUNKS
+#ifdef SW_CANVAS_NO_CHUNKS
     canvas->lz_data.usr.error = lz_usr_error;
     canvas->lz_data.usr.warn = lz_usr_warn;
     canvas->lz_data.usr.info = lz_usr_warn;
@@ -3286,10 +3286,10 @@ static int canvas_base_init(CanvasBase *canvas, SpiceCanvasOps *ops,
                               canvas->width,
                               canvas->height);
 
-#if defined(CAIRO_CANVAS_CACHE) || defined(CAIRO_CANVAS_IMAGE_CACHE)
+#if defined(SW_CANVAS_CACHE) || defined(SW_CANVAS_IMAGE_CACHE)
     canvas->bits_cache = bits_cache;
 #endif
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
     canvas->palette_cache = palette_cache;
 #endif
 
diff --git a/common/gdi_canvas.c b/common/gdi_canvas.c
index 56b7643..af1de95 100644
--- a/common/gdi_canvas.c
+++ b/common/gdi_canvas.c
@@ -1837,7 +1837,7 @@ static void gdi_canvas_clear(SpiceCanvas *spice_canvas)
 
 static void gdi_canvas_set_access_params(SpiceCanvas *spice_canvas, unsigned long base, unsigned long max)
 {
-#ifdef CAIRO_CANVAS_ACCESS_TEST
+#ifdef SW_CANVAS_ACCESS_TEST
     GdiCanvas *canvas = (GdiCanvas *)spice_canvas;
     __canvas_set_access_params(&canvas->base, base, max);
 #endif
@@ -1858,10 +1858,10 @@ static SpiceCanvasOps gdi_canvas_ops;
 
 SpiceCanvas *gdi_canvas_create(int width, int height,
                                HDC dc, RecurciveMutex* lock, uint32_t format
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
                              , SpiceImageCache *bits_cache
                              , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
+#elif defined(SW_CANVAS_IMAGE_CACHE)
                              , SpiceImageCache *bits_cache
 #endif
                             , SpiceImageSurfaces *surfaces
@@ -1877,10 +1877,10 @@ SpiceCanvas *gdi_canvas_create(int width, int height,
     canvas = spice_new0(GdiCanvas, 1);
     init_ok = canvas_base_init(&canvas->base, &gdi_canvas_ops,
                                width, height, format
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
                                ,bits_cache
                                ,palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
+#elif defined(SW_CANVAS_IMAGE_CACHE)
                                , bits_cache
 #endif
                                , surfaces
diff --git a/common/gl_canvas.c b/common/gl_canvas.c
index 63d6977..82c846e 100644
--- a/common/gl_canvas.c
+++ b/common/gl_canvas.c
@@ -812,7 +812,7 @@ static void gl_canvas_group_end(SpiceCanvas *spice_canvas)
 
 static void gl_canvas_set_access_params(SpiceCanvas *spice_canvas, unsigned long base, unsigned long max)
 {
-#ifdef CAIRO_CANVAS_ACCESS_TEST
+#ifdef SW_CANVAS_ACCESS_TEST
     GLCanvas *canvas = (GLCanvas *)spice_canvas;
     __canvas_set_access_params(&canvas->base, base, max);
 #endif
@@ -822,15 +822,15 @@ static int need_init = 1;
 static SpiceCanvasOps gl_canvas_ops;
 
 SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
                               , SpiceImageCache *bits_cache
                               , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
+#elif defined(SW_CANVAS_IMAGE_CACHE)
                               , SpiceImageCache *bits_cache
 #endif
                               , SpiceImageSurfaces *surfaces
                               , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
                               , SpiceVirtMapping *virt_mapping
 #endif
                            )
@@ -849,15 +849,15 @@ SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
     canvas->private_data = NULL;
     init_ok = canvas_base_init(&canvas->base, &gl_canvas_ops,
                                width, height, format
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
                                , bits_cache
                                , palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
+#elif defined(SW_CANVAS_IMAGE_CACHE)
                                , bits_cache
 #endif
                                , surfaces
                                , glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
                                , virt_mapping
 #endif
                                );
diff --git a/common/gl_canvas.h b/common/gl_canvas.h
index 615ca89..6dd25e9 100644
--- a/common/gl_canvas.h
+++ b/common/gl_canvas.h
@@ -22,15 +22,15 @@
 #include "region.h"
 
 SpiceCanvas *gl_canvas_create(int width, int height, uint32_t format
-#ifdef CAIRO_CANVAS_CACHE
+#ifdef SW_CANVAS_CACHE
                            , SpiceImageCache *bits_cache
                            , SpicePaletteCache *palette_cache
-#elif defined(CAIRO_CANVAS_IMAGE_CACHE)
+#elif defined(SW_CANVAS_IMAGE_CACHE)
                            , SpiceImageCache *bits_cache
 #endif
 			   , SpiceImageSurfaces *surfaces
                            , SpiceGlzDecoder *glz_decoder
-#ifndef CAIRO_CANVAS_NO_CHUNKS
+#ifndef SW_CANVAS_NO_CHUNKS
                             , SpiceVirtMapping *virt_mapping
 #endif
                            );
diff --git a/common/lz.h b/common/lz.h
index 3ad6caa..1c80df7 100644
--- a/common/lz.h
+++ b/common/lz.h
@@ -62,9 +62,8 @@ void lz_decode_begin(LzContext *lz, uint8_t *io_ptr, unsigned int num_io_bytes,
         Improtant: if the image is plt1/4 and to_type is rgb32, the image
         will decompressed including the last bits in each line. This means buffer should be
         larger than width*height if neede and you shoud use stride to fix it.
-        Note: If the image is down to top, set the stride in the cairo surface to negative.
-        use cairo_image_surface_create_for_data to create the surface and
-        cairo_surface_set_user_data in order to free the data in the destroy callback.
+        Note: If the image is down to top, set the stride in the sw surface to negative.
+        use alloc_lz_image_surface create the surface.
 */
 void lz_decode(LzContext *lz, LzImageType to_type, uint8_t *buf);
 
diff --git a/common/sw_canvas.c b/common/sw_canvas.c
new file mode 100644
index 0000000..a541c7d
--- /dev/null
+++ b/common/sw_canvas.c
@@ -0,0 +1,1332 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <math.h>
+#include "sw_canvas.h"
+#define CANVAS_USE_PIXMAN
+#define CANVAS_SINGLE_INSTANCE
+#include "canvas_base.c"
+#include "rect.h"
+#include "region.h"
+#include "pixman_utils.h"
+
+typedef struct SwCanvas SwCanvas;
+
+struct SwCanvas {
+    CanvasBase base;
+    uint32_t *private_data;
+    int private_data_size;
+    pixman_image_t *image;
+};
+
+static pixman_image_t *canvas_get_pixman_brush(SwCanvas *canvas,
+                                               SpiceBrush *brush)
+{
+    switch (brush->type) {
+    case SPICE_BRUSH_TYPE_SOLID: {
+        uint32_t color = brush->u.color;
+        pixman_color_t c;
+
+        c.blue = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
+        color >>= canvas->base.color_shift;
+        c.green = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
+        color >>= canvas->base.color_shift;
+        c.red = ((color & canvas->base.color_mask) * 0xffff) / canvas->base.color_mask;
+        c.alpha = 0xffff;
+
+        return pixman_image_create_solid_fill(&c);
+    }
+    case SPICE_BRUSH_TYPE_PATTERN: {
+        SwCanvas *surface_canvas;
+        pixman_image_t* surface;
+        pixman_transform_t t;
+
+        surface_canvas = (SwCanvas *)canvas_get_surface(&canvas->base, brush->u.pattern.pat);
+        if (surface_canvas) {
+            surface = surface_canvas->image;
+            surface = pixman_image_ref(surface);
+        } else {
+            surface = canvas_get_image(&canvas->base, brush->u.pattern.pat, FALSE);
+        }
+        pixman_transform_init_translate(&t,
+                                        pixman_int_to_fixed(-brush->u.pattern.pos.x),
+                                        pixman_int_to_fixed(-brush->u.pattern.pos.y));
+        pixman_image_set_transform(surface, &t);
+        pixman_image_set_repeat(surface, PIXMAN_REPEAT_NORMAL);
+        return surface;
+    }
+    case SPICE_BRUSH_TYPE_NONE:
+        return NULL;
+    default:
+        CANVAS_ERROR("invalid brush type");
+    }
+}
+
+static pixman_image_t *get_image(SpiceCanvas *canvas)
+{
+    SwCanvas *sw_canvas = (SwCanvas *)canvas;
+
+    pixman_image_ref(sw_canvas->image);
+
+    return sw_canvas->image;
+}
+
+static void copy_region(SpiceCanvas *spice_canvas,
+                        pixman_region32_t *dest_region,
+                        int dx, int dy)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_box32_t *dest_rects;
+    int n_rects;
+    int i, j, end_line;
+
+    dest_rects = pixman_region32_rectangles(dest_region, &n_rects);
+
+    if (dy > 0) {
+        if (dx >= 0) {
+            /* south-east: copy x and y in reverse order */
+            for (i = n_rects - 1; i >= 0; i--) {
+                spice_pixman_copy_rect(canvas->image,
+                                       dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
+                                       dest_rects[i].x2 - dest_rects[i].x1,
+                                       dest_rects[i].y2 - dest_rects[i].y1,
+                                       dest_rects[i].x1, dest_rects[i].y1);
+            }
+        } else {
+            /* south-west: Copy y in reverse order, but x in forward order */
+            i = n_rects - 1;
+
+            while (i >= 0) {
+                /* Copy all rects with same y in forward order */
+                for (end_line = i - 1;
+                     end_line >= 0 && dest_rects[end_line].y1 == dest_rects[i].y1;
+                     end_line--) {
+                }
+                for (j = end_line + 1; j <= i; j++) {
+                    spice_pixman_copy_rect(canvas->image,
+                                           dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
+                                           dest_rects[j].x2 - dest_rects[j].x1,
+                                           dest_rects[j].y2 - dest_rects[j].y1,
+                                           dest_rects[j].x1, dest_rects[j].y1);
+                }
+                i = end_line;
+            }
+        }
+    } else {
+        if (dx > 0) {
+            /* north-east: copy y in forward order, but x in reverse order */
+            i = 0;
+
+            while (i < n_rects) {
+                /* Copy all rects with same y in reverse order */
+                for (end_line = i;
+                     end_line < n_rects && dest_rects[end_line].y1 == dest_rects[i].y1;
+                     end_line++) {
+                }
+                for (j = end_line - 1; j >= i; j--) {
+                    spice_pixman_copy_rect(canvas->image,
+                                           dest_rects[j].x1 - dx, dest_rects[j].y1 - dy,
+                                           dest_rects[j].x2 - dest_rects[j].x1,
+                                           dest_rects[j].y2 - dest_rects[j].y1,
+                                           dest_rects[j].x1, dest_rects[j].y1);
+                }
+                i = end_line;
+            }
+        } else {
+            /* north-west: Copy x and y in forward order */
+            for (i = 0; i < n_rects; i++) {
+                spice_pixman_copy_rect(canvas->image,
+                                       dest_rects[i].x1 - dx, dest_rects[i].y1 - dy,
+                                       dest_rects[i].x2 - dest_rects[i].x1,
+                                       dest_rects[i].y2 - dest_rects[i].y1,
+                                       dest_rects[i].x1, dest_rects[i].y1);
+            }
+        }
+    }
+}
+
+static void fill_solid_spans(SpiceCanvas *spice_canvas,
+                             SpicePoint *points,
+                             int *widths,
+                             int n_spans,
+                             uint32_t color)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    int i;
+
+   for (i = 0; i < n_spans; i++) {
+        spice_pixman_fill_rect(canvas->image,
+                               points[i].x, points[i].y,
+                               widths[i],
+                               1,
+                               color);
+    }
+}
+
+static void fill_solid_rects(SpiceCanvas *spice_canvas,
+                             pixman_box32_t *rects,
+                             int n_rects,
+                             uint32_t color)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    int i;
+
+   for (i = 0; i < n_rects; i++) {
+        spice_pixman_fill_rect(canvas->image,
+                               rects[i].x1, rects[i].y1,
+                               rects[i].x2 - rects[i].x1,
+                               rects[i].y2 - rects[i].y1,
+                               color);
+    }
+}
+
+static void fill_solid_rects_rop(SpiceCanvas *spice_canvas,
+                                 pixman_box32_t *rects,
+                                 int n_rects,
+                                 uint32_t color,
+                                 SpiceROP rop)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    int i;
+
+   for (i = 0; i < n_rects; i++) {
+        spice_pixman_fill_rect_rop(canvas->image,
+                                   rects[i].x1, rects[i].y1,
+                                   rects[i].x2 - rects[i].x1,
+                                   rects[i].y2 - rects[i].y1,
+                                   color, rop);
+    }
+}
+
+static void __fill_tiled_rects(SpiceCanvas *spice_canvas,
+                               pixman_box32_t *rects,
+                               int n_rects,
+                               pixman_image_t *tile,
+                               int offset_x, int offset_y)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    int i;
+
+    for (i = 0; i < n_rects; i++) {
+        spice_pixman_tile_rect(canvas->image,
+                               rects[i].x1, rects[i].y1,
+                               rects[i].x2 - rects[i].x1,
+                               rects[i].y2 - rects[i].y1,
+                               tile, offset_x, offset_y);
+    }
+}
+
+static void fill_tiled_rects(SpiceCanvas *spice_canvas,
+                               pixman_box32_t *rects,
+                               int n_rects,
+                               pixman_image_t *tile,
+                               int offset_x, int offset_y)
+{
+    __fill_tiled_rects(spice_canvas, rects, n_rects, tile, offset_x, offset_y);
+}
+
+static void fill_tiled_rects_from_surface(SpiceCanvas *spice_canvas,
+                                          pixman_box32_t *rects,
+                                          int n_rects,
+                                          SpiceCanvas *surface_canvas,
+                                          int offset_x, int offset_y)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __fill_tiled_rects(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x,
+                       offset_y);
+}
+
+static void __fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
+                                   pixman_box32_t *rects,
+                                   int n_rects,
+                                   pixman_image_t *tile,
+                                   int offset_x, int offset_y,
+                                   SpiceROP rop)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    int i;
+
+    for (i = 0; i < n_rects; i++) {
+        spice_pixman_tile_rect_rop(canvas->image,
+                                   rects[i].x1, rects[i].y1,
+                                   rects[i].x2 - rects[i].x1,
+                                   rects[i].y2 - rects[i].y1,
+                                   tile, offset_x, offset_y,
+                                   rop);
+    }
+}
+static void fill_tiled_rects_rop(SpiceCanvas *spice_canvas,
+                                 pixman_box32_t *rects,
+                                 int n_rects,
+                                 pixman_image_t *tile,
+                                 int offset_x, int offset_y,
+                                 SpiceROP rop)
+{
+    __fill_tiled_rects_rop(spice_canvas, rects, n_rects, tile, offset_x, offset_y, rop);
+}
+
+static void fill_tiled_rects_rop_from_surface(SpiceCanvas *spice_canvas,
+                                              pixman_box32_t *rects,
+                                              int n_rects,
+                                              SpiceCanvas *surface_canvas,
+                                              int offset_x, int offset_y,
+                                              SpiceROP rop)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __fill_tiled_rects_rop(spice_canvas, rects, n_rects, sw_surface_canvas->image, offset_x,
+                           offset_y, rop);
+}
+
+/* Some pixman implementations of OP_OVER on xRGB32 sets
+   the high bit to 0xff (which is the right value if the
+   destination was ARGB32, and it should be ignored for
+   xRGB32. However, this fills our alpha bits with
+   data that is not wanted or expected by windows, and its
+   causing us to send rgba images rather than rgb images to
+   the client. So, we manually clear these bytes. */
+static void clear_dest_alpha(pixman_image_t *dest,
+                             int x, int y,
+                             int width, int height)
+{
+    uint32_t *data;
+    int stride;
+    int w, h;
+
+    w = pixman_image_get_width(dest);
+    h = pixman_image_get_height(dest);
+
+    if (x + width <= 0 || x >= w ||
+        y + height <= 0 || y >= h ||
+        width == 0 || height == 0) {
+        return;
+    }
+
+    if (x < 0) {
+        width += x;
+        x = 0;
+    }
+    if (x + width > w) {
+        width = w - x;
+    }
+
+    if (y < 0) {
+        height += y;
+        y = 0;
+    }
+    if (y + height > h) {
+        height = h - y;
+    }
+
+    stride = pixman_image_get_stride(dest);
+    data = (uint32_t *) (
+        (uint8_t *)pixman_image_get_data(dest) + y * stride + 4 * x);
+
+    if ((*data & 0xff000000U) == 0xff000000U) {
+        spice_pixman_fill_rect_rop(dest,
+                                   x, y, width, height,
+                                   0x00ffffff, SPICE_ROP_AND);
+    }
+}
+
+static void __blit_image(SpiceCanvas *spice_canvas,
+                         pixman_region32_t *region,
+                         pixman_image_t *src_image,
+                         int offset_x, int offset_y)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_box32_t *rects;
+    int n_rects, i;
+
+    rects = pixman_region32_rectangles(region, &n_rects);
+
+    for (i = 0; i < n_rects; i++) {
+        int src_x, src_y, dest_x, dest_y, width, height;
+
+        dest_x = rects[i].x1;
+        dest_y = rects[i].y1;
+        width = rects[i].x2 - rects[i].x1;
+        height = rects[i].y2 - rects[i].y1;
+
+        src_x = rects[i].x1 - offset_x;
+        src_y = rects[i].y1 - offset_y;
+
+        spice_pixman_blit(canvas->image,
+                          src_image,
+                          src_x, src_y,
+                          dest_x, dest_y,
+                          width, height);
+    }
+}
+
+static void blit_image(SpiceCanvas *spice_canvas,
+                       pixman_region32_t *region,
+                       pixman_image_t *src_image,
+                       int offset_x, int offset_y)
+{
+    __blit_image(spice_canvas, region, src_image, offset_x, offset_y);
+}
+
+static void blit_image_from_surface(SpiceCanvas *spice_canvas,
+                                    pixman_region32_t *region,
+                                    SpiceCanvas *surface_canvas,
+                                    int offset_x, int offset_y)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __blit_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y);
+}
+
+static void __blit_image_rop(SpiceCanvas *spice_canvas,
+                             pixman_region32_t *region,
+                             pixman_image_t *src_image,
+                             int offset_x, int offset_y,
+                             SpiceROP rop)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_box32_t *rects;
+    int n_rects, i;
+
+    rects = pixman_region32_rectangles(region, &n_rects);
+
+    for (i = 0; i < n_rects; i++) {
+        int src_x, src_y, dest_x, dest_y, width, height;
+
+        dest_x = rects[i].x1;
+        dest_y = rects[i].y1;
+        width = rects[i].x2 - rects[i].x1;
+        height = rects[i].y2 - rects[i].y1;
+
+        src_x = rects[i].x1 - offset_x;
+        src_y = rects[i].y1 - offset_y;
+
+        spice_pixman_blit_rop(canvas->image,
+                              src_image,
+                              src_x, src_y,
+                              dest_x, dest_y,
+                              width, height, rop);
+    }
+}
+
+static void blit_image_rop(SpiceCanvas *spice_canvas,
+                           pixman_region32_t *region,
+                           pixman_image_t *src_image,
+                           int offset_x, int offset_y,
+                           SpiceROP rop)
+{
+    __blit_image_rop(spice_canvas, region, src_image, offset_x, offset_y, rop);
+}
+
+static void blit_image_rop_from_surface(SpiceCanvas *spice_canvas,
+                                        pixman_region32_t *region,
+                                        SpiceCanvas *surface_canvas,
+                                        int offset_x, int offset_y,
+                                        SpiceROP rop)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __blit_image_rop(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y, rop);
+}
+
+
+
+static void __scale_image(SpiceCanvas *spice_canvas,
+                          pixman_region32_t *region,
+                          pixman_image_t *src,
+                          int src_x, int src_y,
+                          int src_width, int src_height,
+                          int dest_x, int dest_y,
+                          int dest_width, int dest_height,
+                          int scale_mode)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_transform_t transform;
+    double sx, sy;
+
+    sx = (double)(src_width) / (dest_width);
+    sy = (double)(src_height) / (dest_height);
+
+    pixman_image_set_clip_region32(canvas->image, region);
+
+    pixman_transform_init_scale(&transform,
+                                pixman_double_to_fixed(sx),
+                                pixman_double_to_fixed(sy));
+
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+    ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
+           scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
+    pixman_image_set_filter(src,
+                            (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
+                            PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
+                            NULL, 0);
+
+    pixman_image_composite32(PIXMAN_OP_SRC,
+                             src, NULL, canvas->image,
+                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
+                             0, 0, /* mask */
+                             dest_x, dest_y, /* dst */
+                             dest_width, dest_height);
+
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
+
+    pixman_image_set_clip_region32(canvas->image, NULL);
+}
+
+static void scale_image(SpiceCanvas *spice_canvas,
+                        pixman_region32_t *region,
+                        pixman_image_t *src,
+                        int src_x, int src_y,
+                        int src_width, int src_height,
+                        int dest_x, int dest_y,
+                        int dest_width, int dest_height,
+                        int scale_mode)
+{
+    __scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x, dest_y,
+                  dest_width,dest_height,scale_mode);
+}
+
+static void scale_image_from_surface(SpiceCanvas *spice_canvas,
+                                     pixman_region32_t *region,
+                                     SpiceCanvas *surface_canvas,
+                                     int src_x, int src_y,
+                                     int src_width, int src_height,
+                                     int dest_x, int dest_y,
+                                     int dest_width, int dest_height,
+                                     int scale_mode)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width,
+                  src_height, dest_x, dest_y, dest_width,dest_height,scale_mode);
+}
+
+static void __scale_image_rop(SpiceCanvas *spice_canvas,
+                              pixman_region32_t *region,
+                              pixman_image_t *src,
+                              int src_x, int src_y,
+                              int src_width, int src_height,
+                              int dest_x, int dest_y,
+                              int dest_width, int dest_height,
+                              int scale_mode, SpiceROP rop)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_transform_t transform;
+    pixman_image_t *scaled;
+    pixman_box32_t *rects;
+    int n_rects, i;
+    double sx, sy;
+
+    sx = (double)(src_width) / (dest_width);
+    sy = (double)(src_height) / (dest_height);
+
+    scaled = pixman_image_create_bits(spice_pixman_image_get_format(src),
+                                      dest_width,
+                                      dest_height,
+                                      NULL, 0);
+
+    pixman_region32_translate(region, -dest_x, -dest_y);
+    pixman_image_set_clip_region32(scaled, region);
+
+    pixman_transform_init_scale(&transform,
+                                pixman_double_to_fixed(sx),
+                                pixman_double_to_fixed(sy));
+
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+    ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
+           scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
+    pixman_image_set_filter(src,
+                            (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
+                            PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
+                            NULL, 0);
+
+    pixman_image_composite32(PIXMAN_OP_SRC,
+                             src, NULL, scaled,
+                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
+                             0, 0, /* mask */
+                             0, 0, /* dst */
+                             dest_width,
+                             dest_height);
+
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
+
+    /* Translate back */
+    pixman_region32_translate(region, dest_x, dest_y);
+
+    rects = pixman_region32_rectangles(region, &n_rects);
+
+    for (i = 0; i < n_rects; i++) {
+        spice_pixman_blit_rop(canvas->image,
+                              scaled,
+                              rects[i].x1 - dest_x,
+                              rects[i].y1 - dest_y,
+                              rects[i].x1, rects[i].y1,
+                              rects[i].x2 - rects[i].x1,
+                              rects[i].y2 - rects[i].y1,
+                              rop);
+    }
+
+    pixman_image_unref(scaled);
+}
+
+static void scale_image_rop(SpiceCanvas *spice_canvas,
+                            pixman_region32_t *region,
+                            pixman_image_t *src,
+                            int src_x, int src_y,
+                            int src_width, int src_height,
+                            int dest_x, int dest_y,
+                            int dest_width, int dest_height,
+                            int scale_mode, SpiceROP rop)
+{
+    __scale_image_rop(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
+                      dest_y, dest_width, dest_height, scale_mode, rop);
+}
+
+static void scale_image_rop_from_surface(SpiceCanvas *spice_canvas,
+                                         pixman_region32_t *region,
+                                         SpiceCanvas *surface_canvas,
+                                         int src_x, int src_y,
+                                         int src_width, int src_height,
+                                         int dest_x, int dest_y,
+                                         int dest_width, int dest_height,
+                                         int scale_mode, SpiceROP rop)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __scale_image_rop(spice_canvas, region, sw_surface_canvas->image, src_x, src_y, src_width,
+                      src_height, dest_x, dest_y, dest_width, dest_height, scale_mode, rop);
+}
+
+static pixman_image_t *canvas_get_as_surface(SwCanvas *canvas,
+                                          int with_alpha)
+{
+    pixman_image_t *target;
+
+    if (with_alpha &&
+        canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
+        target = pixman_image_create_bits(PIXMAN_a8r8g8b8,
+                                          pixman_image_get_width(canvas->image),
+                                          pixman_image_get_height(canvas->image),
+                                          pixman_image_get_data(canvas->image),
+                                          pixman_image_get_stride(canvas->image));
+    } else {
+        target = pixman_image_ref(canvas->image);
+    }
+
+    return target;
+}
+
+static void __blend_image(SpiceCanvas *spice_canvas,
+                          pixman_region32_t *region,
+                          int dest_has_alpha,
+                          pixman_image_t *src,
+                          int src_x, int src_y,
+                          int dest_x, int dest_y,
+                          int width, int height,
+                          int overall_alpha)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_image_t *mask, *dest;
+
+    dest = canvas_get_as_surface(canvas, dest_has_alpha);
+
+    pixman_image_set_clip_region32(dest, region);
+
+    mask = NULL;
+    if (overall_alpha != 0xff) {
+        pixman_color_t color = { 0 };
+        color.alpha = overall_alpha * 0x101;
+        mask = pixman_image_create_solid_fill(&color);
+    }
+
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+
+    pixman_image_composite32(PIXMAN_OP_OVER,
+                             src, mask, dest,
+                             src_x, src_y, /* src */
+                             0, 0, /* mask */
+                             dest_x, dest_y, /* dst */
+                             width,
+                             height);
+
+    if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
+        !dest_has_alpha) {
+        clear_dest_alpha(dest, dest_x, dest_y, width, height);
+    }
+
+    if (mask) {
+        pixman_image_unref(mask);
+    }
+
+    pixman_image_set_clip_region32(dest, NULL);
+    pixman_image_unref(dest);
+}
+
+static void blend_image(SpiceCanvas *spice_canvas,
+                        pixman_region32_t *region,
+                        int dest_has_alpha,
+                        pixman_image_t *src,
+                        int src_x, int src_y,
+                        int dest_x, int dest_y,
+                        int width, int height,
+                        int overall_alpha)
+{
+    __blend_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y,
+                  dest_x, dest_y, width, height,
+                  overall_alpha);
+}
+
+static void blend_image_from_surface(SpiceCanvas *spice_canvas,
+                                     pixman_region32_t *region,
+                                     int dest_has_alpha,
+                                     SpiceCanvas *surface_canvas,
+                                     int src_has_alpha,
+                                     int src_x, int src_y,
+                                     int dest_x, int dest_y,
+                                     int width, int height,
+                                     int overall_alpha)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    pixman_image_t *src;
+
+    src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha);
+    __blend_image(spice_canvas, region, dest_has_alpha,
+                  src, src_x, src_y,
+                  dest_x, dest_y,
+                  width, height, overall_alpha);
+    pixman_image_unref(src);
+}
+
+static void __blend_scale_image(SpiceCanvas *spice_canvas,
+                                pixman_region32_t *region,
+                                int dest_has_alpha,
+                                pixman_image_t *src,
+                                int src_x, int src_y,
+                                int src_width, int src_height,
+                                int dest_x, int dest_y,
+                                int dest_width, int dest_height,
+                                int scale_mode,
+                                int overall_alpha)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_transform_t transform;
+    pixman_image_t *mask, *dest;
+    double sx, sy;
+
+    sx = (double)(src_width) / (dest_width);
+    sy = (double)(src_height) / (dest_height);
+
+    dest = canvas_get_as_surface(canvas, dest_has_alpha);
+
+    pixman_image_set_clip_region32(dest, region);
+
+    pixman_transform_init_scale(&transform,
+                                pixman_double_to_fixed(sx),
+                                pixman_double_to_fixed(sy));
+
+    mask = NULL;
+    if (overall_alpha != 0xff) {
+        pixman_color_t color = { 0 };
+        color.alpha = overall_alpha * 0x101;
+        mask = pixman_image_create_solid_fill(&color);
+    }
+
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+    ASSERT(scale_mode == SPICE_IMAGE_SCALE_MODE_INTERPOLATE ||
+           scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST);
+    pixman_image_set_filter(src,
+                            (scale_mode == SPICE_IMAGE_SCALE_MODE_NEAREST) ?
+                            PIXMAN_FILTER_NEAREST : PIXMAN_FILTER_GOOD,
+                            NULL, 0);
+
+    pixman_image_composite32(PIXMAN_OP_OVER,
+                             src, mask, dest,
+                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
+                             0, 0, /* mask */
+                             dest_x, dest_y, /* dst */
+                             dest_width, dest_height);
+
+    if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB &&
+        !dest_has_alpha) {
+        clear_dest_alpha(dest, dest_x, dest_y, dest_width, dest_height);
+    }
+
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
+
+    if (mask) {
+        pixman_image_unref(mask);
+    }
+
+    pixman_image_set_clip_region32(dest, NULL);
+    pixman_image_unref(dest);
+}
+
+static void blend_scale_image(SpiceCanvas *spice_canvas,
+                              pixman_region32_t *region,
+                              int dest_has_alpha,
+                              pixman_image_t *src,
+                              int src_x, int src_y,
+                              int src_width, int src_height,
+                              int dest_x, int dest_y,
+                              int dest_width, int dest_height,
+                              int scale_mode,
+                              int overall_alpha)
+{
+    __blend_scale_image(spice_canvas, region, dest_has_alpha,
+                        src, src_x, src_y, src_width, src_height,
+                        dest_x, dest_y, dest_width, dest_height,
+                        scale_mode, overall_alpha);
+}
+
+static void blend_scale_image_from_surface(SpiceCanvas *spice_canvas,
+                                           pixman_region32_t *region,
+                                           int dest_has_alpha,
+                                           SpiceCanvas *surface_canvas,
+                                           int src_has_alpha,
+                                           int src_x, int src_y,
+                                           int src_width, int src_height,
+                                           int dest_x, int dest_y,
+                                           int dest_width, int dest_height,
+                                           int scale_mode,
+                                           int overall_alpha)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    pixman_image_t *src;
+
+    src = canvas_get_as_surface(sw_surface_canvas, src_has_alpha);
+    __blend_scale_image(spice_canvas, region, dest_has_alpha, src, src_x, src_y, src_width,
+                        src_height, dest_x, dest_y, dest_width, dest_height, scale_mode,
+                        overall_alpha);
+    pixman_image_unref(src);
+}
+
+static void __colorkey_image(SpiceCanvas *spice_canvas,
+                             pixman_region32_t *region,
+                             pixman_image_t *src_image,
+                             int offset_x, int offset_y,
+                             uint32_t transparent_color)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_box32_t *rects;
+    int n_rects, i;
+
+    rects = pixman_region32_rectangles(region, &n_rects);
+
+    for (i = 0; i < n_rects; i++) {
+        int src_x, src_y, dest_x, dest_y, width, height;
+
+        dest_x = rects[i].x1;
+        dest_y = rects[i].y1;
+        width = rects[i].x2 - rects[i].x1;
+        height = rects[i].y2 - rects[i].y1;
+
+        src_x = rects[i].x1 - offset_x;
+        src_y = rects[i].y1 - offset_y;
+
+        spice_pixman_blit_colorkey(canvas->image,
+                                   src_image,
+                                   src_x, src_y,
+                                   dest_x, dest_y,
+                                   width, height,
+                                   transparent_color);
+    }
+}
+
+static void colorkey_image(SpiceCanvas *spice_canvas,
+                           pixman_region32_t *region,
+                           pixman_image_t *src_image,
+                           int offset_x, int offset_y,
+                           uint32_t transparent_color)
+{
+    __colorkey_image(spice_canvas, region, src_image, offset_x, offset_y, transparent_color);
+}
+
+static void colorkey_image_from_surface(SpiceCanvas *spice_canvas,
+                                        pixman_region32_t *region,
+                                        SpiceCanvas *surface_canvas,
+                                        int offset_x, int offset_y,
+                                        uint32_t transparent_color)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __colorkey_image(spice_canvas, region, sw_surface_canvas->image, offset_x, offset_y,
+                     transparent_color);
+}
+
+static void __colorkey_scale_image(SpiceCanvas *spice_canvas,
+                                   pixman_region32_t *region,
+                                   pixman_image_t *src,
+                                   int src_x, int src_y,
+                                   int src_width, int src_height,
+                                   int dest_x, int dest_y,
+                                   int dest_width, int dest_height,
+                                   uint32_t transparent_color)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_transform_t transform;
+    pixman_image_t *scaled;
+    pixman_box32_t *rects;
+    int n_rects, i;
+    double sx, sy;
+
+    sx = (double)(src_width) / (dest_width);
+    sy = (double)(src_height) / (dest_height);
+
+    scaled = pixman_image_create_bits(spice_pixman_image_get_format (src),
+                                      dest_width,
+                                      dest_height,
+                                      NULL, 0);
+
+    pixman_region32_translate(region, -dest_x, -dest_y);
+    pixman_image_set_clip_region32(scaled, region);
+
+    pixman_transform_init_scale(&transform,
+                                pixman_double_to_fixed(sx),
+                                pixman_double_to_fixed(sy));
+
+    pixman_image_set_transform(src, &transform);
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+    pixman_image_set_filter(src,
+                            PIXMAN_FILTER_NEAREST,
+                            NULL, 0);
+
+    pixman_image_composite32(PIXMAN_OP_SRC,
+                             src, NULL, scaled,
+                             ROUND(src_x / sx), ROUND(src_y / sy), /* src */
+                             0, 0, /* mask */
+                             0, 0, /* dst */
+                             dest_width,
+                             dest_height);
+
+    pixman_transform_init_identity(&transform);
+    pixman_image_set_transform(src, &transform);
+
+    /* Translate back */
+    pixman_region32_translate(region, dest_x, dest_y);
+
+    rects = pixman_region32_rectangles(region, &n_rects);
+
+    for (i = 0; i < n_rects; i++) {
+        spice_pixman_blit_colorkey(canvas->image,
+                                   scaled,
+                                   rects[i].x1 - dest_x,
+                                   rects[i].y1 - dest_y,
+                                   rects[i].x1, rects[i].y1,
+                                   rects[i].x2 - rects[i].x1,
+                                   rects[i].y2 - rects[i].y1,
+                                   transparent_color);
+    }
+
+    pixman_image_unref(scaled);
+}
+
+static void colorkey_scale_image(SpiceCanvas *spice_canvas,
+                                 pixman_region32_t *region,
+                                 pixman_image_t *src,
+                                 int src_x, int src_y,
+                                 int src_width, int src_height,
+                                 int dest_x, int dest_y,
+                                 int dest_width, int dest_height,
+                                 uint32_t transparent_color)
+{
+    __colorkey_scale_image(spice_canvas, region, src, src_x, src_y, src_width, src_height, dest_x,
+                           dest_y, dest_width, dest_height, transparent_color);
+}
+
+static void colorkey_scale_image_from_surface(SpiceCanvas *spice_canvas,
+                                              pixman_region32_t *region,
+                                              SpiceCanvas *surface_canvas,
+                                              int src_x, int src_y,
+                                              int src_width, int src_height,
+                                              int dest_x, int dest_y,
+                                              int dest_width, int dest_height,
+                                              uint32_t transparent_color)
+{
+    SwCanvas *sw_surface_canvas = (SwCanvas *)surface_canvas;
+    __colorkey_scale_image(spice_canvas, region, sw_surface_canvas->image, src_x, src_y,
+                           src_width, src_height, dest_x, dest_y, dest_width, dest_height,
+                           transparent_color);
+}
+
+static void canvas_put_image(SpiceCanvas *spice_canvas,
+#ifdef WIN32
+                             HDC dc,
+#endif
+                             const SpiceRect *dest, const uint8_t *src_data,
+                             uint32_t src_width, uint32_t src_height, int src_stride,
+                             const QRegion *clip)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_image_t *src;
+    int dest_width;
+    int dest_height;
+    double sx, sy;
+    pixman_transform_t transform;
+
+    src = pixman_image_create_bits(PIXMAN_x8r8g8b8,
+                                   src_width,
+                                   src_height,
+                                   (uint32_t*)src_data,
+                                   src_stride);
+
+
+    if (clip) {
+        pixman_image_set_clip_region32 (canvas->image, (pixman_region32_t *)clip);
+    }
+
+    dest_width = dest->right - dest->left;
+    dest_height = dest->bottom - dest->top;
+
+    if (dest_width != src_width || dest_height != src_height) {
+        sx = (double)(src_width) / (dest_width);
+        sy = (double)(src_height) / (dest_height);
+
+        pixman_transform_init_scale(&transform,
+                                    pixman_double_to_fixed(sx),
+                                    pixman_double_to_fixed(sy));
+        pixman_image_set_transform(src, &transform);
+        pixman_image_set_filter(src,
+                                PIXMAN_FILTER_NEAREST,
+                                NULL, 0);
+    }
+
+    pixman_image_set_repeat(src, PIXMAN_REPEAT_NONE);
+
+    pixman_image_composite32(PIXMAN_OP_SRC,
+                             src, NULL, canvas->image,
+                             0, 0, /* src */
+                             0, 0, /* mask */
+                             dest->left, dest->top, /* dst */
+                             dest_width, dest_height);
+
+
+    if (clip) {
+        pixman_image_set_clip_region32(canvas->image, NULL);
+    }
+    pixman_image_unref(src);
+}
+
+
+static void canvas_draw_text(SpiceCanvas *spice_canvas, SpiceRect *bbox,
+                             SpiceClip *clip, SpiceText *text)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_region32_t dest_region;
+    pixman_image_t *str_mask, *brush;
+    SpiceString *str;
+    SpicePoint pos;
+    int depth;
+
+    pixman_region32_init_rect(&dest_region,
+                              bbox->left, bbox->top,
+                              bbox->right - bbox->left,
+                              bbox->bottom - bbox->top);
+
+    canvas_clip_pixman(&canvas->base, &dest_region, clip);
+
+    if (!pixman_region32_not_empty(&dest_region)) {
+        touch_brush(&canvas->base, &text->fore_brush);
+        touch_brush(&canvas->base, &text->back_brush);
+        pixman_region32_fini(&dest_region);
+        return;
+    }
+
+    if (!rect_is_empty(&text->back_area)) {
+        pixman_region32_t back_region;
+
+        /* Nothing else makes sense for text and we should deprecate it
+         * and actually it means OVER really */
+        ASSERT(text->fore_mode == SPICE_ROPD_OP_PUT);
+
+        pixman_region32_init_rect(&back_region,
+                                  text->back_area.left,
+                                  text->back_area.top,
+                                  text->back_area.right - text->back_area.left,
+                                  text->back_area.bottom - text->back_area.top);
+
+        pixman_region32_intersect(&back_region, &back_region, &dest_region);
+
+        if (pixman_region32_not_empty(&back_region)) {
+            draw_brush(spice_canvas, &back_region, &text->back_brush, SPICE_ROP_COPY);
+        }
+
+        pixman_region32_fini(&back_region);
+    }
+    str = (SpiceString *)SPICE_GET_ADDRESS(text->str);
+
+    if (str->flags & SPICE_STRING_FLAGS_RASTER_A1) {
+        depth = 1;
+    } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A4) {
+        depth = 4;
+    } else if (str->flags & SPICE_STRING_FLAGS_RASTER_A8) {
+        WARN("untested path A8 glyphs");
+        depth = 8;
+    } else {
+        WARN("unsupported path vector glyphs");
+        pixman_region32_fini (&dest_region);
+        return;
+    }
+
+    brush = canvas_get_pixman_brush(canvas, &text->fore_brush);
+
+    str_mask = canvas_get_str_mask(&canvas->base, str, depth, &pos);
+    if (brush) {
+        pixman_image_set_clip_region32(canvas->image, &dest_region);
+
+        pixman_image_composite32(PIXMAN_OP_OVER,
+                                 brush,
+                                 str_mask,
+                                 canvas->image,
+                                 0, 0,
+                                 0, 0,
+                                 pos.x, pos.y,
+                                 pixman_image_get_width(str_mask),
+                                 pixman_image_get_height(str_mask));
+        if (canvas->base.format == SPICE_SURFACE_FMT_32_xRGB) {
+            clear_dest_alpha(canvas->image, pos.x, pos.y,
+                             pixman_image_get_width(str_mask),
+                             pixman_image_get_height(str_mask));
+        }
+        pixman_image_unref(brush);
+
+        pixman_image_set_clip_region32(canvas->image, NULL);
+    }
+    pixman_image_unref(str_mask);
+    pixman_region32_fini(&dest_region);
+}
+
+static void canvas_read_bits(SpiceCanvas *spice_canvas, uint8_t *dest,
+                             int dest_stride, const SpiceRect *area)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    pixman_image_t* surface;
+    uint8_t *src;
+    int src_stride;
+    uint8_t *dest_end;
+    int bpp;
+
+    ASSERT(canvas && area);
+
+    surface = canvas->image;
+
+    bpp = spice_pixman_image_get_bpp(surface) / 8;
+
+    src_stride = pixman_image_get_stride(surface);
+    src = (uint8_t *)pixman_image_get_data(surface) +
+        area->top * src_stride + area->left * bpp;
+    dest_end = dest + (area->bottom - area->top) * dest_stride;
+    for (; dest != dest_end; dest += dest_stride, src += src_stride) {
+        memcpy(dest, src, (area->right - area->left) * bpp);
+    }
+}
+
+static void canvas_clear(SpiceCanvas *spice_canvas)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    spice_pixman_fill_rect(canvas->image,
+                           0, 0,
+                           pixman_image_get_width(canvas->image),
+                           pixman_image_get_height(canvas->image),
+                           0);
+}
+
+static void canvas_set_access_params(SpiceCanvas *spice_canvas,
+                                     unsigned long base, unsigned long max)
+{
+#ifdef SW_CANVAS_ACCESS_TEST
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    __canvas_set_access_params(&canvas->base, base, max);
+#endif
+}
+
+static void canvas_destroy(SpiceCanvas *spice_canvas)
+{
+    SwCanvas *canvas = (SwCanvas *)spice_canvas;
+    if (!canvas) {
+        return;
+    }
+    pixman_image_unref(canvas->image);
+    canvas_base_destroy(&canvas->base);
+    if (canvas->private_data) {
+        free(canvas->private_data);
+    }
+    free(canvas);
+}
+
+static int need_init = 1;
+static SpiceCanvasOps sw_canvas_ops;
+
+static SpiceCanvas *canvas_create_common(pixman_image_t *image,
+                                         uint32_t format
+#ifdef SW_CANVAS_CACHE
+                           , SpiceImageCache *bits_cache
+                           , SpicePaletteCache *palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                           , SpiceImageCache *bits_cache
+#endif
+                           , SpiceImageSurfaces *surfaces
+                           , SpiceGlzDecoder *glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                           , SpiceVirtMapping *virt_mapping
+#endif
+                           )
+{
+    SwCanvas *canvas;
+    int init_ok;
+
+    if (need_init) {
+        return NULL;
+    }
+    spice_pixman_image_set_format(image,
+                                  spice_surface_format_to_pixman (format));
+
+    canvas = spice_new0(SwCanvas, 1);
+    init_ok = canvas_base_init(&canvas->base, &sw_canvas_ops,
+                               pixman_image_get_width (image),
+                               pixman_image_get_height (image),
+                               format
+#ifdef SW_CANVAS_CACHE
+                               , bits_cache
+                               , palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                               , bits_cache
+#endif
+                               , surfaces
+                               , glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                               , virt_mapping
+#endif
+                               );
+    canvas->private_data = NULL;
+    canvas->private_data_size = 0;
+
+    canvas->image = image;
+
+    return (SpiceCanvas *)canvas;
+}
+
+SpiceCanvas *canvas_create(int width, int height, uint32_t format
+#ifdef SW_CANVAS_CACHE
+                           , SpiceImageCache *bits_cache
+                           , SpicePaletteCache *palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                           , SpiceImageCache *bits_cache
+#endif
+                           , SpiceImageSurfaces *surfaces
+                           , SpiceGlzDecoder *glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                           , SpiceVirtMapping *virt_mapping
+#endif
+                           )
+{
+    pixman_image_t *image;
+
+    image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
+                                     width, height, NULL, 0);
+
+    return canvas_create_common(image, format
+#ifdef SW_CANVAS_CACHE
+                                , bits_cache
+                                , palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                                , bits_cache
+#endif
+                                , surfaces
+                                , glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                                , virt_mapping
+#endif
+                                );
+}
+
+SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format,
+                                    uint8_t *data, size_t stride
+#ifdef SW_CANVAS_CACHE
+                           , SpiceImageCache *bits_cache
+                           , SpicePaletteCache *palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                           , SpiceImageCache *bits_cache
+#endif
+                           , SpiceImageSurfaces *surfaces
+                           , SpiceGlzDecoder *glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                           , SpiceVirtMapping *virt_mapping
+#endif
+                           )
+{
+    pixman_image_t *image;
+
+    image = pixman_image_create_bits(spice_surface_format_to_pixman (format),
+                                     width, height, (uint32_t *)data, stride);
+
+    return canvas_create_common(image, format
+#ifdef SW_CANVAS_CACHE
+                                , bits_cache
+                                , palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                                , bits_cache
+#endif
+                                , surfaces
+                                , glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                                , virt_mapping
+#endif
+                                );
+}
+
+void sw_canvas_init() //unsafe global function
+{
+    if (!need_init) {
+        return;
+    }
+    need_init = 0;
+
+    canvas_base_init_ops(&sw_canvas_ops);
+    sw_canvas_ops.draw_text = canvas_draw_text;
+    sw_canvas_ops.put_image = canvas_put_image;
+    sw_canvas_ops.clear = canvas_clear;
+    sw_canvas_ops.read_bits = canvas_read_bits;
+    sw_canvas_ops.set_access_params = canvas_set_access_params;
+    sw_canvas_ops.destroy = canvas_destroy;
+
+    sw_canvas_ops.fill_solid_spans = fill_solid_spans;
+    sw_canvas_ops.fill_solid_rects = fill_solid_rects;
+    sw_canvas_ops.fill_solid_rects_rop = fill_solid_rects_rop;
+    sw_canvas_ops.fill_tiled_rects = fill_tiled_rects;
+    sw_canvas_ops.fill_tiled_rects_from_surface = fill_tiled_rects_from_surface;
+    sw_canvas_ops.fill_tiled_rects_rop = fill_tiled_rects_rop;
+    sw_canvas_ops.fill_tiled_rects_rop_from_surface = fill_tiled_rects_rop_from_surface;
+    sw_canvas_ops.blit_image = blit_image;
+    sw_canvas_ops.blit_image_from_surface = blit_image_from_surface;
+    sw_canvas_ops.blit_image_rop = blit_image_rop;
+    sw_canvas_ops.blit_image_rop_from_surface = blit_image_rop_from_surface;
+    sw_canvas_ops.scale_image = scale_image;
+    sw_canvas_ops.scale_image_from_surface = scale_image_from_surface;
+    sw_canvas_ops.scale_image_rop = scale_image_rop;
+    sw_canvas_ops.scale_image_rop_from_surface = scale_image_rop_from_surface;
+    sw_canvas_ops.blend_image = blend_image;
+    sw_canvas_ops.blend_image_from_surface = blend_image_from_surface;
+    sw_canvas_ops.blend_scale_image = blend_scale_image;
+    sw_canvas_ops.blend_scale_image_from_surface = blend_scale_image_from_surface;
+    sw_canvas_ops.colorkey_image = colorkey_image;
+    sw_canvas_ops.colorkey_image_from_surface = colorkey_image_from_surface;
+    sw_canvas_ops.colorkey_scale_image = colorkey_scale_image;
+    sw_canvas_ops.colorkey_scale_image_from_surface = colorkey_scale_image_from_surface;
+    sw_canvas_ops.copy_region = copy_region;
+    sw_canvas_ops.get_image = get_image;
+    rop3_init();
+}
diff --git a/common/sw_canvas.h b/common/sw_canvas.h
new file mode 100644
index 0000000..c3aef24
--- /dev/null
+++ b/common/sw_canvas.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   Copyright (C) 2009 Red Hat, Inc.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library 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
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H__CANVAS
+#define _H__CANVAS
+
+#include <stdint.h>
+
+#include <spice/draw.h>
+#include "pixman_utils.h"
+#include "canvas_base.h"
+#include "region.h"
+
+SpiceCanvas *canvas_create(int width, int height, uint32_t format
+#ifdef SW_CANVAS_CACHE
+                           , SpiceImageCache *bits_cache
+                           , SpicePaletteCache *palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                           , SpiceImageCache *bits_cache
+#endif
+			   , SpiceImageSurfaces *surfaces
+                           , SpiceGlzDecoder *glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                           , SpiceVirtMapping *virt_mapping
+#endif
+                           );
+
+SpiceCanvas *canvas_create_for_data(int width, int height, uint32_t format, uint8_t *data, size_t stride
+#ifdef SW_CANVAS_CACHE
+                           , SpiceImageCache *bits_cache
+                           , SpicePaletteCache *palette_cache
+#elif defined(SW_CANVAS_IMAGE_CACHE)
+                           , SpiceImageCache *bits_cache
+#endif
+			   , SpiceImageSurfaces *surfaces
+                           , SpiceGlzDecoder *glz_decoder
+#ifndef SW_CANVAS_NO_CHUNKS
+                           , SpiceVirtMapping *virt_mapping
+#endif
+                           );
+
+
+void sw_canvas_init();
+
+#endif
diff --git a/server/Makefile.am b/server/Makefile.am
index f121168..baa61cf 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -1,7 +1,7 @@
 NULL =
 
 INCLUDES = \
-	-I. 					\
+	-I.					\
 	-I$(top_srcdir)/common			\
 	-I$(top_srcdir)/common/linux	\
 	$(PROTOCOL_CFLAGS)			\
@@ -12,14 +12,14 @@ INCLUDES = \
 	$(SSL_CFLAGS)				\
 	$(CELT051_CFLAGS)			\
 	$(SLIRP_CFLAGS)				\
-	-DCAIRO_CANVAS_IMAGE_CACHE		\
+	-DSW_CANVAS_IMAGE_CACHE			\
 	-DRED_STATISTICS			\
 	$(WARN_CFLAGS)                          \
 	$(VISIBILITY_HIDDEN_CFLAGS)		\
 	$(NULL)
 
-COMMON_SRCS = 						\
-	$(top_srcdir)/common/cairo_canvas.c		\
+COMMON_SRCS =						\
+	$(top_srcdir)/common/sw_canvas.c		\
 	$(top_srcdir)/common/pixman_utils.c		\
 	$(top_srcdir)/common/lines.c			\
 	$(top_srcdir)/common/gl_canvas.c		\
diff --git a/server/red_dispatcher.c b/server/red_dispatcher.c
index 5b719bd..b3cf8cd 100644
--- a/server/red_dispatcher.c
+++ b/server/red_dispatcher.c
@@ -28,7 +28,7 @@
 #include "vd_interface.h"
 #include "red_worker.h"
 #include "quic.h"
-#include "cairo_canvas.h"
+#include "sw_canvas.h"
 #include "gl_canvas.h"
 #include "reds.h"
 #include "red_dispatcher.h"
@@ -131,7 +131,7 @@ typedef struct RendererInfo {
 } RendererInfo;
 
 static RendererInfo renderers_info[] = {
-    {RED_RENDERER_CAIRO, "cairo"},
+    {RED_RENDERER_SW, "sw"},
     {RED_RENDERER_OGL_PBUF, "oglpbuf"},
     {RED_RENDERER_OGL_PIXMAP, "oglpixmap"},
     {RED_RENDERER_INVALID, NULL},
@@ -483,7 +483,7 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
     }
 
     quic_init();
-    cairo_canvas_init();
+    sw_canvas_init();
     gl_canvas_init();
 
     if (socketpair(AF_LOCAL, SOCK_STREAM, 0, channels) == -1) {
diff --git a/server/red_worker.c b/server/red_worker.c
index e9b2ade..59cca3d 100644
--- a/server/red_worker.c
+++ b/server/red_worker.c
@@ -36,7 +36,7 @@
 #include "region.h"
 #include <spice/protocol.h>
 #include "red_worker.h"
-#include "cairo_canvas.h"
+#include "sw_canvas.h"
 #include "gl_canvas.h"
 #include "ogl_ctx.h"
 #include "quic.h"
@@ -7951,7 +7951,7 @@ static inline void *create_canvas_for_surface(RedWorker *worker, RedSurface *sur
     SpiceCanvas *canvas;
 
     switch (renderer) {
-    case RED_RENDERER_CAIRO:
+    case RED_RENDERER_SW:
         canvas = canvas_create_for_data(width, height, format,
                                         line_0, stride,
                                         &worker->image_cache.base,
diff --git a/server/red_worker.h b/server/red_worker.h
index e54e4bf..5807237 100644
--- a/server/red_worker.h
+++ b/server/red_worker.h
@@ -77,7 +77,7 @@ typedef uint32_t RedWorkeMessage;
 
 enum {
     RED_RENDERER_INVALID,
-    RED_RENDERER_CAIRO,
+    RED_RENDERER_SW,
     RED_RENDERER_OGL_PBUF,
     RED_RENDERER_OGL_PIXMAP,
 };
diff --git a/server/reds.c b/server/reds.c
index 7d7fd44..866f35a 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -81,7 +81,7 @@ static int spice_port = -1;
 static int spice_secure_port = -1;
 static char spice_addr[256];
 static int spice_family = PF_UNSPEC;
-static char *default_renderer = "cairo";
+static char *default_renderer = "sw";
 
 static int ticketing_enabled = 1; //Ticketing is enabled by default
 static pthread_mutex_t *lock_cs;
@@ -4038,7 +4038,7 @@ int __attribute__ ((visibility ("default"))) spice_parse_args(const char *in_arg
         }
     } while (args);
 
-    if (!renderers_opt && !red_dispatcher_add_renderer("cairo")) {
+    if (!renderers_opt && !red_dispatcher_add_renderer("sw")) {
         goto error;
     }
 
@@ -4061,7 +4061,7 @@ const char *spice_usage_str[] __attribute__ ((visibility ("default"))) = {
     "[,ic=on|auto_glz|auto_lz|quic|glz|lz|off]",
     "[,playback-compression=on|off]",
     "[,password=password][,disable-ticketing]",
-    "[,renderer=oglpbuf+oglpixmap+cairo]",
+    "[,renderer=oglpbuf+oglpixmap+sw]",
     "[,sslkeys=key directory,sslcerts=certs directory,sslpassword=pem password,",
     "                                              sslciphersuite=cipher suite]",
     "[,secure-channels=all|channel+channel+...]",


More information about the Spice-commits mailing list