[Spice-devel] [PATCH 00/30] Convert cairo canvas to use pixman

Alexander Larsson alexl at redhat.com
Fri Feb 19 07:52:36 PST 2010


On Fri, 2010-02-19 at 16:50 +0100, Alexander Larsson wrote:
> On Thu, 2010-02-18 at 21:58 +0100, Alexander Larsson wrote:
> > This series converts the software based canvas "cairo_canvas" to use
> > pixman for rendering instead of cairo. It uses the upstream pixman
> > (the latest version, 0.7.16 is needed) thus dropping the
> dependencies
> > on qcairo and qpixman (and additionally cairo is not linked into the
> > server at all).
> > 
> > After the whole series is applied its possible to build spice with
> > upstream cairo and pixman 0.7.16. However, if you want to compile
> and
> > run intermediate steps (for instance when bisecting) you need to do
> > some extra work:
> 
> Seems i missed some qcairo parts:

Wrong patch:

commit 0de8c72dc4f57cbba6bb93e97a44b09da45a6ffd
Author: Alexander Larsson <alexl at redhat.com>
Date:   Fri Feb 19 16:48:55 2010 +0100

    Remove cairo use in client

diff --git a/client/x11/pixels_source.cpp b/client/x11/pixels_source.cpp
index 7b9ed05..144c296 100644
--- a/client/x11/pixels_source.cpp
+++ b/client/x11/pixels_source.cpp
@@ -25,9 +25,9 @@
 
 
 static void create_image(const PixmapHeader* pixmap, PixelsSource_p& pixels_source,
-                         cairo_format_t cairo_format)
+                         pixman_format_code_t format)
 {
-    cairo_surface_t* cairo_surf;
+    pixman_image_t *pixman_image;
     XImage *image = new XImage;
 
     memset(image, 0, sizeof(*image));
@@ -53,10 +53,11 @@ static void create_image(const PixmapHeader* pixmap, PixelsSource_p& pixels_sour
             THROW("init image failed");
         }
 
-        cairo_surf = cairo_image_surface_create_for_data(pixmap->data, cairo_format,
-                                                         pixmap->width, pixmap->height,
-                                                         pixmap->stride);
-        if (cairo_surface_status(cairo_surf) != CAIRO_STATUS_SUCCESS) {
+        pixman_image = pixman_image_create_bits(format,
+                                                pixmap->width, pixmap->height,
+                                                (uint32_t *)pixmap->data,
+                                                pixmap->stride);
+        if (pixman_image == NULL) {
             THROW("surf create failed");
         }
     } catch (...) {
@@ -66,7 +67,7 @@ static void create_image(const PixmapHeader* pixmap, PixelsSource_p& pixels_sour
 
     pixels_source.type = PIXELS_SOURCE_TYPE_PIXMAP;
     pixels_source.pixmap.x_image = image;
-    pixels_source.pixmap.cairo_surf = cairo_surf;
+    pixels_source.pixmap.pixman_image = pixman_image;
 }
 
 PixelsSource::PixelsSource()
@@ -85,12 +86,12 @@ ImageFromRes::ImageFromRes(int res_id)
     if (!pixmap) {
         THROW("no image %d", res_id);
     }
-    create_image(pixmap, *(PixelsSource_p*)get_opaque(), CAIRO_FORMAT_RGB24);
+    create_image(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_x8r8g8b8);
 }
 
 ImageFromRes::~ImageFromRes()
 {
-    cairo_surface_destroy(((PixelsSource_p*)get_opaque())->pixmap.cairo_surf);
+    pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
     delete ((PixelsSource_p*)get_opaque())->pixmap.x_image;
 }
 
@@ -109,12 +110,12 @@ AlphaImageFromRes::AlphaImageFromRes(int res_id)
     if (!pixmap) {
         THROW("no image %d", res_id);
     }
-    create_image(pixmap, *(PixelsSource_p*)get_opaque(), CAIRO_FORMAT_ARGB32);
+    create_image(pixmap, *(PixelsSource_p*)get_opaque(), PIXMAN_a8r8g8b8);
 }
 
 AlphaImageFromRes::~AlphaImageFromRes()
 {
-    cairo_surface_destroy(((PixelsSource_p*)get_opaque())->pixmap.cairo_surf);
+    pixman_image_unref(((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
     delete ((PixelsSource_p*)get_opaque())->pixmap.x_image;
 }
 
diff --git a/client/x11/pixels_source_p.h b/client/x11/pixels_source_p.h
index 69d6998..9605ae4 100644
--- a/client/x11/pixels_source_p.h
+++ b/client/x11/pixels_source_p.h
@@ -24,7 +24,7 @@
 #include <X11/extensions/XShm.h>
 #include "red_window.h"
 #include "red_pixmap_gl.h"
-#include "cairo.h"
+#include "pixman_utils.h"
 
 enum {
     PIXELS_SOURCE_TYPE_INVALID,
@@ -53,12 +53,12 @@ struct PixelsSource_p {
         struct {
             XImage* x_image;
             XShmSegmentInfo *shminfo;
-            cairo_surface_t* cairo_surf;
+            pixman_image_t* pixman_image;
         } x_shm_drawable;
 
         struct {
             XImage* x_image;
-            cairo_surface_t* cairo_surf;
+            pixman_image_t* pixman_image;
         } pixmap;
 
         struct {
@@ -79,9 +79,6 @@ struct PixelsSource_p {
 
 struct RedDrawable_p {
     PixelsSource_p source;
-    union {
-        cairo_t* cairo;
-    };
 };
 
 #endif
diff --git a/client/x11/red_drawable.cpp b/client/x11/red_drawable.cpp
index 7485c94..dc33749 100644
--- a/client/x11/red_drawable.cpp
+++ b/client/x11/red_drawable.cpp
@@ -237,18 +237,18 @@ static inline void copy_to_pixmap_from_shmdrawable(const RedDrawable_p* dest,
                                                    const PixelsSource_p* source,
                                                    int src_x, int src_y)
 {
-    cairo_t* cairo = dest->cairo;
-    cairo_surface_t* surf = source->x_shm_drawable.cairo_surf;
-
-    ASSERT(cairo);
-    ASSERT(surf);
-
-    cairo_set_source_surface(cairo, surf, area.left + offset.x - src_x,
-                             area.top + offset.y - src_y);
-    cairo_set_operator(cairo, CAIRO_OPERATOR_RASTER_COPY);
-    cairo_rectangle(cairo, area.left + offset.x, area.top + offset.y, area.right - area.left,
-                    area.bottom - area.top);
-    cairo_fill(cairo);
+    pixman_image_t *dest_surface =  dest->source.pixmap.pixman_image;
+    pixman_image_t *src_surface = source->x_shm_drawable.pixman_image;
+
+    pixman_image_composite32 (PIXMAN_OP_SRC,
+                              src_surface, NULL, dest_surface,
+                              src_x + offset.x,
+                              src_y + offset.y,
+                              0, 0,
+                              area.left + offset.x,
+                              area.top + offset.y,
+                              area.right - area.left,
+                              area.bottom - area.top);
 }
 
 static inline void copy_to_pixmap_from_pixmap(const RedDrawable_p* dest,
@@ -257,18 +257,18 @@ static inline void copy_to_pixmap_from_pixmap(const RedDrawable_p* dest,
                                               const PixelsSource_p* source,
                                               int src_x, int src_y)
 {
-    cairo_t* cairo = dest->cairo;
-    cairo_surface_t* surf = source->pixmap.cairo_surf;
-
-    ASSERT(cairo);
-    ASSERT(surf);
-
-    cairo_set_source_surface(cairo, surf, area.left + offset.x - src_x,
-                             area.top + offset.y - src_y);
-    cairo_set_operator(cairo, CAIRO_OPERATOR_RASTER_COPY);
-    cairo_rectangle(cairo, area.left + offset.x, area.top + offset.y, area.right - area.left,
-                    area.bottom - area.top);
-    cairo_fill(cairo);
+    pixman_image_t *dest_surface =  dest->source.pixmap.pixman_image;
+    pixman_image_t *src_surface = source->pixmap.pixman_image;
+
+    pixman_image_composite32 (PIXMAN_OP_SRC,
+                              src_surface, NULL, dest_surface,
+                              src_x + offset.x,
+                              src_y + offset.y,
+                              0, 0,
+                              area.left + offset.x,
+                              area.top + offset.y,
+                              area.right - area.left,
+                              area.bottom - area.top);
 }
 
 static inline void copy_to_pixmap_from_gltexture(const RedDrawable_p* dest,
@@ -384,18 +384,18 @@ static inline void blend_to_pixmap_from_pixmap(const RedDrawable_p* dest,
                                                const PixelsSource_p* source,
                                                int src_x, int src_y)
 {
-    cairo_t* cairo = dest->cairo;
-    cairo_surface_t* surf = source->pixmap.cairo_surf;
-
-    ASSERT(cairo);
-    ASSERT(surf);
-
-    cairo_set_source_surface(cairo, surf, (area.left + offset.x - src_x),
-                             (area.top + offset.y - src_y));
-    cairo_set_operator(cairo, CAIRO_OPERATOR_ATOP);
-    cairo_rectangle(cairo, area.left + offset.x, area.top + offset.y, area.right - area.left,
-                    area.bottom - area.top);
-    cairo_fill(cairo);
+    pixman_image_t *dest_surface =  dest->source.pixmap.pixman_image;
+    pixman_image_t *src_surface = source->pixmap.pixman_image;
+
+    pixman_image_composite32 (PIXMAN_OP_ATOP,
+                              src_surface, NULL, dest_surface,
+                              src_x + offset.x,
+                              src_y + offset.y,
+                              0, 0,
+                              area.left + offset.x,
+                              area.top + offset.y,
+                              area.right - area.left,
+                              area.bottom - area.top);
 }
 
 static inline void blend_to_pixmap(const RedDrawable_p* dest,
@@ -460,41 +460,74 @@ static inline void combine_to_pixmap_from_pixmap(const RedDrawable_p* dest,
                                                  int src_x, int src_y,
                                                  RedDrawable::CombineOP op)
 {
-    cairo_t* cairo = dest->cairo;
-    cairo_surface_t* surf = source->pixmap.cairo_surf;
+    pixman_image_t *dest_surface =  dest->source.pixmap.pixman_image;
+    pixman_image_t *src_surface = source->pixmap.pixman_image;
 
-    ASSERT(cairo);
-    ASSERT(surf);
-    cairo_operator_t cairo_op;
+    SpiceROP rop;
     switch (op) {
     case RedDrawable::OP_COPY:
-        cairo_op = CAIRO_OPERATOR_RASTER_COPY;
+        rop = SPICE_ROP_COPY;
         break;
     case RedDrawable::OP_AND:
-        cairo_op = CAIRO_OPERATOR_RASTER_AND;
+        rop = SPICE_ROP_AND;
         break;
     case RedDrawable::OP_XOR:
-        cairo_op = CAIRO_OPERATOR_RASTER_XOR;
+        rop = SPICE_ROP_XOR;
         break;
     default:
         THROW("invalid op %d", op);
     }
 
 
-    cairo_set_operator(cairo, cairo_op);
-    if (cairo_image_surface_get_format(surf) == CAIRO_FORMAT_A1) {
-        cairo_rectangle(cairo, area.left + offset.x, area.top + offset.y, area.right - area.left,
-                        area.bottom - area.top);
-        cairo_clip(cairo);
-        cairo_set_source_rgb(cairo, 1, 1, 1);
-        cairo_mask_surface(cairo, surf, area.left + offset.x - src_x, area.top + offset.y - src_y);
-        cairo_reset_clip(cairo);
+    if (pixman_image_get_depth (src_surface) == 1) {
+        pixman_image_t *temp;
+
+        temp = pixman_image_create_bits(pixman_image_get_depth(dest_surface) == 24 ?
+                                        PIXMAN_x8r8g8b8 : PIXMAN_a8r8g8b8,
+                                        area.right - area.left,
+                                        area.bottom - area.top, NULL, 0);
+
+        /* Copy from dest to temp */
+        pixman_image_composite32(PIXMAN_OP_SRC,
+                                 dest_surface, NULL, temp,
+                                 area.left + offset.x,
+                                 area.top + offset.y,
+                                 0, 0,
+                                 0, 0,
+                                 area.right - area.left,
+                                 area.bottom - area.top);
+
+        /* rop white over temp */
+        spice_pixman_fill_rect_rop(temp,
+                                   0, 0,
+                                   area.right - area.left,
+                                   area.bottom - area.top,
+                                   0xffffff,
+                                   rop);
+
+        /* copy back using a1 mask */
+        pixman_image_composite32(PIXMAN_OP_SRC,
+                                 dest_surface, src_surface, dest_surface,
+                                 0, 0,
+                                 src_x + offset.x,
+                                 src_y + offset.y,
+                                 area.left + offset.x,
+                                 area.top + offset.y,
+                                 area.right - area.left,
+                                 area.bottom - area.top);
+
+        pixman_image_unref(temp);
+
     } else {
-        cairo_set_source_surface(cairo, surf, area.left + offset.x - src_x,
-                                 area.top + offset.y - src_y);
-        cairo_rectangle(cairo, area.left + offset.x, area.top + offset.y, area.right - area.left,
-                        area.bottom - area.top);
-        cairo_fill(cairo);
+        spice_pixman_blit_rop (dest_surface,
+                               src_surface,
+                               src_x + offset.x,
+                               src_y + offset.y,
+                               area.left + offset.x,
+                               area.top + offset.y,
+                               area.right - area.left,
+                               area.bottom - area.top,
+                               rop);
     }
 }
 
@@ -606,17 +639,13 @@ static inline void fill_gl_drawable(RedDrawable_p* dest, const SpiceRect& area,
 static inline void fill_pixmap(RedDrawable_p* dest, const SpiceRect& area, rgb32_t color,
                                const SpicePoint& offset)
 {
-    cairo_t* cairo = dest->cairo;
-
-    ASSERT(cairo);
-    cairo_set_source_rgb(cairo,
-                         (double)rgb32_get_red(color) / 0xff,
-                         (double)rgb32_get_green(color) / 0xff,
-                         (double)rgb32_get_blue(color) / 0xff);
-    cairo_rectangle(cairo, area.left + offset.x, area.top + offset.y, area.right - area.left,
-                    area.bottom - area.top);
-    cairo_set_operator(cairo, CAIRO_OPERATOR_RASTER_COPY);
-    cairo_fill(cairo);
+    pixman_image_t *dest_surface =  dest->source.pixmap.pixman_image;
+
+    spice_pixman_fill_rect (dest_surface,
+                            area.left + offset.x, area.top + offset.y,
+                            area.right - area.left,
+                            area.bottom - area.top,
+                            color);
 }
 
 void RedDrawable::fill_rect(const SpiceRect& area, rgb32_t color)
@@ -668,18 +697,28 @@ static inline void frame_drawable(RedDrawable_p* dest, const SpiceRect& area, rg
 static inline void frame_pixmap(RedDrawable_p* dest, const SpiceRect& area, rgb32_t color,
                                 const SpicePoint& offset)
 {
-    cairo_t* cairo = dest->cairo;
-
-    ASSERT(cairo);
-    cairo_set_source_rgb(cairo,
-                         (double)rgb32_get_red(color) / 0xff,
-                         (double)rgb32_get_green(color) / 0xff,
-                         (double)rgb32_get_blue(color) / 0xff);
-    cairo_rectangle(cairo, area.left + offset.x, area.top + offset.y, area.right - area.left,
-                    area.bottom - area.top);
-    cairo_set_line_width(cairo, 1);
-    cairo_set_operator(cairo, CAIRO_OPERATOR_RASTER_COPY);
-    cairo_stroke(cairo);
+    pixman_image_t *dest_surface =  dest->source.pixmap.pixman_image;
+
+    spice_pixman_fill_rect (dest_surface,
+                            area.left + offset.x, area.top + offset.y,
+                            area.right - area.left,
+                            1,
+                            color);
+    spice_pixman_fill_rect (dest_surface,
+                            area.left + offset.x, area.bottom + offset.y,
+                            area.right - area.left,
+                            1,
+                            color);
+    spice_pixman_fill_rect (dest_surface,
+                            area.left + offset.x, area.top + offset.y,
+                            1,
+                            area.bottom - area.top,
+                            color);
+    spice_pixman_fill_rect (dest_surface,
+                            area.right + offset.x, area.top + offset.y,
+                            1,
+                            area.bottom - area.top,
+                            color);
 }
 
 void RedDrawable::frame_rect(const SpiceRect& area, rgb32_t color)
diff --git a/client/x11/red_pixmap_cairo.cpp b/client/x11/red_pixmap_cairo.cpp
index 7ca9315..b8b627b 100644
--- a/client/x11/red_pixmap_cairo.cpp
+++ b/client/x11/red_pixmap_cairo.cpp
@@ -28,10 +28,9 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
                                bool top_bottom, rgb32_t* pallet, RedWindow *win)
     : RedPixmap(width, height, format, top_bottom, pallet)
 {
-    cairo_surface_t* cairo_surf = NULL;
-    cairo_t* cairo = NULL;
     ASSERT(format == RedPixmap::ARGB32 || format == RedPixmap::RGB32 || format == RedPixmap::A1);
     ASSERT(sizeof(RedDrawable_p) <= PIXELES_SOURCE_OPAQUE_SIZE);
+    pixman_image_t *pixman_image;
     XImage *image = NULL;
     XShmSegmentInfo *shminfo = NULL;
     _data = NULL;
@@ -40,7 +39,7 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
 
 
     try {
-        cairo_format_t cairo_format;
+        pixman_format_code_t pixman_format;
 
         if (win) {
             vinfo = XPlatform::get_vinfo()[win->get_screen_num()];
@@ -55,12 +54,12 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
             case RedPixmap::ARGB32:
             case RedPixmap::RGB32:
                 depth = XPlatform::get_vinfo()[0]->depth;
-                cairo_format = format == RedPixmap::ARGB32 ? CAIRO_FORMAT_ARGB32 :
-                                                             CAIRO_FORMAT_RGB24;
+                pixman_format = format == RedPixmap::ARGB32 ? PIXMAN_a8r8g8b8 :
+                                                             PIXMAN_x8r8g8b8;
                 break;
             case RedPixmap::A1:
                 depth = 1;
-                cairo_format = CAIRO_FORMAT_A1;
+                pixman_format = PIXMAN_a1;
                 break;
             default:
                 THROW("unsupported format %d", format);
@@ -122,13 +121,13 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
                 image->red_mask = 0x00ff0000;
                 image->green_mask = 0x0000ff00;
                 image->blue_mask = 0x000000ff;
-                cairo_format = format == RedPixmap::ARGB32 ? CAIRO_FORMAT_ARGB32 :
-                                                             CAIRO_FORMAT_RGB24;
+                pixman_format = format == RedPixmap::ARGB32 ? PIXMAN_a8r8g8b8 :
+                                                             PIXMAN_x8r8g8b8;
                 break;
             case RedPixmap::A1:
                 image->depth = 1;
                 image->format = XYBitmap;
-                cairo_format = CAIRO_FORMAT_A1;
+                pixman_format = PIXMAN_a1;
                 break;
             default:
                 THROW("unsupported format %d", format);
@@ -138,23 +137,16 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
                 THROW("init image failed");
             }
         }
-        cairo_surf = cairo_image_surface_create_for_data(_data, cairo_format, _width, _height,
-                                                         _stride);
-        if (cairo_surface_status(cairo_surf) != CAIRO_STATUS_SUCCESS) {
+        pixman_image = pixman_image_create_bits (pixman_format, _width, _height, (uint32_t *)_data, _stride);
+        if (pixman_image == NULL) {
             THROW("surf create failed");
         }
 
-        cairo = cairo_create(cairo_surf);
-        cairo_surface_destroy(cairo_surf);
-        if (cairo_status(cairo) != CAIRO_STATUS_SUCCESS) {
-            THROW("cairo create failed failed");
-        }
         if (!using_shm) {
-            ((PixelsSource_p*)get_opaque())->pixmap.cairo_surf = cairo_surf;
+            ((PixelsSource_p*)get_opaque())->pixmap.pixman_image = pixman_image;
         } else {
-            ((PixelsSource_p*)get_opaque())->x_shm_drawable.cairo_surf = cairo_surf;
+            ((PixelsSource_p*)get_opaque())->x_shm_drawable.pixman_image = pixman_image;
         }
-        ((RedDrawable_p*)get_opaque())->cairo = cairo;
     } catch (...) {
         if (using_shm) {
             if (image) {
@@ -178,11 +170,12 @@ RedPixmapCairo::RedPixmapCairo(int width, int height, RedPixmap::Format format,
 
 RedPixmapCairo::~RedPixmapCairo()
 {
-    cairo_destroy(((RedDrawable_p*)get_opaque())->cairo);
     if (((PixelsSource_p*)get_opaque())->type == PIXELS_SOURCE_TYPE_PIXMAP) {
+        pixman_image_unref (((PixelsSource_p*)get_opaque())->pixmap.pixman_image);
         delete ((PixelsSource_p*)get_opaque())->pixmap.x_image;
         delete[] _data;
     } else {
+        pixman_image_unref (((PixelsSource_p*)get_opaque())->x_shm_drawable.pixman_image);
         XShmSegmentInfo *shminfo = ((PixelsSource_p*)get_opaque())->x_shm_drawable.shminfo;
         XShmDetach(XPlatform::get_display(), shminfo);
         XDestroyImage(((PixelsSource_p*)get_opaque())->x_shm_drawable.x_image);
diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c
index a6c82ee..8d549e6 100644
--- a/common/cairo_canvas.c
+++ b/common/cairo_canvas.c
@@ -240,7 +240,7 @@ static void canvas_mask_pixman (CairoCanvas *canvas,
                                 pixman_region32_t *dest_region,
                                 SpiceQMask *mask, int x, int y)
 {
-    pixman_image_t *image;
+    pixman_image_t *image, *subimage;
     int needs_invert;
     pixman_region32_t mask_region;
     uint32_t *mask_data;
@@ -298,10 +298,11 @@ static void canvas_mask_pixman (CairoCanvas *canvas,
     mask_width = extents.x2 - extents.x1;
     mask_height = extents.y2 - extents.y1;
 
-    spice_pixman_region32_init_from_bitmap (&mask_region,
-                                            mask_data,
-                                            mask_width, mask_height,
-                                            mask_stride / 4);
+    subimage = pixman_image_create_bits (PIXMAN_a1, mask_width, mask_height,
+                                         mask_data, mask_stride);
+    pixman_region32_init_from_image (&mask_region,
+                                     subimage);
+    pixman_image_unref (subimage);
 
     if (needs_invert) {
         pixman_box32_t rect;


-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 Alexander Larsson                                            Red Hat, Inc 
       alexl at redhat.com            alexander.larsson at gmail.com 
He's a short-sighted Amish jungle king She's a ditzy red-headed stripper 
living on borrowed time. They fight crime! 



More information about the Spice-devel mailing list