[Spice-devel] [PATCH 00/30] Convert cairo canvas to use pixman
Izik Eidus
ieidus at redhat.com
Sat Feb 20 01:18:10 PST 2010
On Fri, 19 Feb 2010 16:52:36 +0100
Alexander Larsson <alexl at redhat.com> wrote:
> 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;
>
>
After appling everything include of this on top of the last patch
and build pixman from the git repo i still get:
cc1: warnings being treated as errors
../common/cairo_canvas.c: In function ‘canvas_mask_pixman’:
../common/cairo_canvas.c:303: error: implicit declaration of function ‘pixman_region32_init_from_image’
Any ideas what I am doing wrong?
More information about the Spice-devel
mailing list