[Spice-devel] [PATCH 26/30] Covert cairo canvas put_image() to pixman

Izik Eidus ieidus at redhat.com
Sun Feb 21 01:11:10 PST 2010


On Thu, 18 Feb 2010 21:58:52 +0100
Alexander Larsson <alexl at redhat.com> wrote:

> ---
>  common/cairo_canvas.c |  119 +++++++++++++++---------------------------------
>  1 files changed, 37 insertions(+), 82 deletions(-)
> 
> diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c
> index 9e61a4f..46956aa 100644
> --- a/common/cairo_canvas.c
> +++ b/common/cairo_canvas.c
> @@ -1051,106 +1051,61 @@ void canvas_draw_copy(CairoCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, Spi
>  }
>  
>  #ifdef WIN32
> -void canvas_put_image(CairoCanvas *canvas, HDC dc, const SpiceRect *dest, const uint8_t *_src_data,
> +void canvas_put_image(CairoCanvas *canvas, HDC dc, const SpiceRect *dest, const uint8_t *src_data,
>                        uint32_t src_width, uint32_t src_height, int src_stride,
>                        const QRegion *clip)
>  #else
> -void canvas_put_image(CairoCanvas *canvas, const SpiceRect *dest, const uint8_t *_src_data,
> +void canvas_put_image(CairoCanvas *canvas, const SpiceRect *dest, const uint8_t *src_data,
>                        uint32_t src_width, uint32_t src_height, int src_stride,
>                        const QRegion *clip)
>  #endif
>  {
> -    cairo_t *cairo = canvas->cairo;
> -    cairo_surface_t* surf = NULL;
> +    pixman_image_t *src;
>      int dest_width;
>      int dest_height;
> -    uint8_t *src_data = (uint8_t *)_src_data;
> -    uint32_t *data;
> -    int nstride;
> -
> -    cairo_save(cairo);
> -
> -    if (clip) {
> -        int num_rects;
> -        pixman_box32_t *rects = pixman_region32_rectangles((pixman_region32_t *)clip,
> -                                                           &num_rects);
> -        const pixman_box32_t *now = rects;
> -        const pixman_box32_t *end = rects + num_rects;
> -        for (; now < end; now++) {
> -            cairo_rectangle(cairo, now->x1, now->y1, now->x2 - now->x1,
> -                            now->y2 - now->y1);
> -        }
> -        cairo_clip(cairo);
> -    }
> +    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) {
> -        int x, y;
> -        int x_mul = (uint32_t)((src_width << 16) / dest_width);
> -        int y_mul = (uint32_t)((src_height << 16) / dest_height);
> -        int new_y;
> -        int set_y;
> -        int nsrc_stride;
> -
> -        if (src_stride < 0) {
> -            nsrc_stride = -src_stride;
> -            src_data = src_data - (src_height - 1) * nsrc_stride;
> -            nsrc_stride = nsrc_stride / 4;
> -        } else {
> -            nsrc_stride = src_stride / 4;
> -        }
> -        if ((dest_width * dest_height) > canvas->private_data_size) {
> -            if (canvas->private_data) {
> -                free(canvas->private_data);
> -                canvas->private_data = NULL;
> -                canvas->private_data_size = 0;
> -            }
> -            canvas->private_data = (uint32_t *)malloc(4 * dest_width * dest_height);
> -            if (!canvas->private_data) {
> -                return;
> -            }
> -            canvas->private_data_size = dest_width * dest_height;
> -        }
> -        if (!clip) {
> -            surf = cairo_get_target(cairo);
> -            data = (uint32_t *)cairo_image_surface_get_data(surf);
> -            nstride = cairo_image_surface_get_stride(surf) / 4;
> -            data += dest->top * nstride + dest->left + (dest_height - 1) * nstride;
> -        } else {
> -            data = (uint32_t *)canvas->private_data;
> -            nstride = dest_width;
> -            data += (dest_height - 1) * nstride;
> -        }
> -
> -        for (y = 0; y < dest_height; ++y) {
> -            int y_mul_stride = -y * nstride;
> -            new_y = ((y * y_mul) >> 16);
> -            set_y = (new_y * nsrc_stride);
> -            for (x = 0; x < dest_width; ++x) {
> -                data[y_mul_stride + x] = ((uint32_t *)src_data)[set_y + ((x * x_mul) >> 16)];
> -            }
> -        }
> -        if (clip) {
> -            surf = cairo_image_surface_create_for_data((uint8_t *)canvas->private_data,
> -                                                       CAIRO_FORMAT_RGB24, dest_width,
> -                                                       dest_height, 4 * dest_width);
> -        }
> -    } else {
> -        surf = cairo_image_surface_create_for_data((uint8_t *)src_data, CAIRO_FORMAT_RGB24,
> -                                                   src_width, src_height, src_stride);
> +        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);

sending again due to problem i had in the mail:

So with the old code when taking a movie and stretching it from 320x120 to 1240x1024 in the client
i get 25% cpu usage, with this code i get 34% cpu usage (pretty big diffrence) this is
amd phenom 2 2800mhz, considering the fact that the old code was nearest algorithem 2,

we probably want to see why it is slower? and we can probably fix it inside the lib?

Thanks.


More information about the Spice-devel mailing list