From ae40f270cfbe4629c041074e2b0c28dfd3f554b8 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Mon, 3 May 2010 12:08:00 +0200 Subject: 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). --- 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 +++ 10 files changed, 1436 insertions(+), 1437 deletions(-) delete mode 100644 common/cairo_canvas.c delete mode 100644 common/cairo_canvas.h create mode 100644 common/sw_canvas.c create mode 100644 common/sw_canvas.h (limited to 'common') 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 . -*/ - -#include -#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 . -*/ - -#ifndef _H__CANVAS -#define _H__CANVAS - -#include - -#include -#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 . +*/ + +#include +#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 . +*/ + +#ifndef _H__CANVAS +#define _H__CANVAS + +#include + +#include +#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 -- cgit v1.2.3