[Spice-devel] [PATCH 14/30] Convert cairo canvas copy bits to pixman
Alexander Larsson
alexl at redhat.com
Thu Feb 18 12:58:40 PST 2010
---
common/cairo_canvas.c | 254 ++++++++-----------------------------------------
1 files changed, 41 insertions(+), 213 deletions(-)
diff --git a/common/cairo_canvas.c b/common/cairo_canvas.c
index d0307d8..109a07c 100644
--- a/common/cairo_canvas.c
+++ b/common/cairo_canvas.c
@@ -991,6 +991,33 @@ static void __draw_mask(void *data)
cairo_mask(((DrawMaskData *)data)->cairo, ((DrawMaskData *)data)->mask);
}
+static void copy_region (CairoCanvas *canvas,
+ pixman_region32_t *dest_region,
+ int dx, int dy)
+{
+ pixman_box32_t *dest_rects;
+ int n_rects;
+ int i;
+
+ dest_rects = pixman_region32_rectangles (dest_region, &n_rects);
+
+ if (dy > 0 || (dy == 0 && dx > 0)) {
+ 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 {
+ 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_rects(CairoCanvas *canvas,
pixman_region32_t *region,
uint32_t color)
@@ -1920,226 +1947,27 @@ void canvas_draw_rop3(CairoCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, Spi
cairo_restore(cairo);
}
-#define FAST_COPY_BITS
-
-#ifdef FAST_COPY_BITS
-
-static inline void __canvas_copy_bits_up(uint8_t *data, const int stride,
- const int src_x, const int src_y,
- const int width, const int height,
- const int dest_x, const int dest_y)
-{
- uint8_t *src = data + src_y * stride + src_x * sizeof(uint32_t);
- uint8_t *dest = data + dest_y * stride + dest_x * sizeof(uint32_t);
- uint8_t *end = dest + height * stride;
- for (; dest != end; dest += stride, src += stride) {
- memcpy(dest, src, width * sizeof(uint32_t));
- }
-}
-
-static inline void __canvas_copy_bits_down(uint8_t *data, const int stride,
- const int src_x, const int src_y,
- const int width, const int height,
- const int dest_x, const int dest_y)
-{
- uint8_t *src = data + (src_y + height - 1) * stride + src_x * sizeof(uint32_t);
- uint8_t *end = data + (dest_y - 1) * stride + dest_x * sizeof(uint32_t);
- uint8_t *dest = end + height * stride;
-
- for (; dest != end; dest -= stride, src -= stride) {
- memcpy(dest, src, width * sizeof(uint32_t));
- }
-}
-
-static inline void __canvas_copy_bits_right(uint8_t *data, const int stride,
- const int src_x, const int src_y,
- const int width, const int height,
- const int dest_x, const int dest_y)
-{
- uint8_t *src = data + src_y * stride + (src_x + width - 1) * sizeof(uint32_t);
- uint8_t *dest = data + dest_y * stride + (dest_x + width - 1) * sizeof(uint32_t);
- uint8_t *end = dest + height * stride;
- for (; dest != end; dest += stride, src += stride) {
- uint32_t *src_pix = (uint32_t *)src;
- uint32_t *end_pix = src_pix - width;
- uint32_t *dest_pix = (uint32_t *)dest;
-
- for (; src_pix > end_pix; src_pix--, dest_pix--) {
- *dest_pix = *src_pix;
- }
- }
-}
-
-static inline void __canvas_copy_rect_bits(uint8_t *data, const int stride, SpiceRect *dest_rect,
- SpicePoint *src_pos)
-{
- if (dest_rect->top > src_pos->y) {
- __canvas_copy_bits_down(data, stride, src_pos->x, src_pos->y,
- dest_rect->right - dest_rect->left,
- dest_rect->bottom - dest_rect->top,
- dest_rect->left, dest_rect->top);
- } else if (dest_rect->top < src_pos->y || dest_rect->left < src_pos->x) {
- __canvas_copy_bits_up(data, stride, src_pos->x, src_pos->y,
- dest_rect->right - dest_rect->left,
- dest_rect->bottom - dest_rect->top,
- dest_rect->left, dest_rect->top);
- } else {
- __canvas_copy_bits_right(data, stride, src_pos->x, src_pos->y,
- dest_rect->right - dest_rect->left,
- dest_rect->bottom - dest_rect->top,
- dest_rect->left, dest_rect->top);
- }
-}
-
-static inline void canvas_copy_fix_clip_area(const SpiceRect *dest,
- const SpicePoint *src_pos,
- const SpiceRect *now,
- SpicePoint *ret_pos,
- SpiceRect *ret_dest)
-{
- *ret_dest = *now;
- rect_sect(ret_dest, dest);
- ret_pos->x = src_pos->x + (ret_dest->left - dest->left);
- ret_pos->y = src_pos->y + (ret_dest->top - dest->top);
-}
-
-static inline void __canvas_copy_region_bits(uint8_t *data, int stride, SpiceRect *dest_rect,
- SpicePoint *src_pos, QRegion *region)
-{
- SpiceRect curr_area;
- SpicePoint curr_pos;
- SpiceRect *now;
- SpiceRect *end;
-
- if (dest_rect->top > src_pos->y) {
- end = region->rects - 1;
- now = end + region->num_rects;
- if (dest_rect->left < src_pos->x) {
- for (; now > end; now--) {
- SpiceRect *line_end = now;
- SpiceRect *line_pos;
-
- while (now - 1 > end && now->top == now[-1].top) {
- now--;
- }
-
- for (line_pos = now; line_pos <= line_end; line_pos++) {
- canvas_copy_fix_clip_area(dest_rect, src_pos, line_pos, &curr_pos, &curr_area);
- __canvas_copy_bits_down(data, stride, curr_pos.x, curr_pos.y,
- curr_area.right - curr_area.left,
- curr_area.bottom - curr_area.top,
- curr_area.left, curr_area.top);
- }
- }
- } else {
- for (; now > end; now--) {
- canvas_copy_fix_clip_area(dest_rect, src_pos, now, &curr_pos, &curr_area);
- __canvas_copy_bits_down(data, stride, curr_pos.x, curr_pos.y,
- curr_area.right - curr_area.left,
- curr_area.bottom - curr_area.top,
- curr_area.left, curr_area.top);
- }
- }
- } else if (dest_rect->top < src_pos->y || dest_rect->left < src_pos->x) {
- now = region->rects;
- end = now + region->num_rects;
- if (dest_rect->left > src_pos->x) {
- for (; now < end; now++) {
- SpiceRect *line_end = now;
- SpiceRect *line_pos;
-
- while (now + 1 < end && now->top == now[1].top) {
- now++;
- }
-
- for (line_pos = now; line_pos >= line_end; line_pos--) {
- canvas_copy_fix_clip_area(dest_rect, src_pos, line_pos, &curr_pos, &curr_area);
- __canvas_copy_bits_up(data, stride, curr_pos.x, curr_pos.y,
- curr_area.right - curr_area.left,
- curr_area.bottom - curr_area.top,
- curr_area.left, curr_area.top);
- }
- }
- } else {
- for (; now < end; now++) {
- canvas_copy_fix_clip_area(dest_rect, src_pos, now, &curr_pos, &curr_area);
- __canvas_copy_bits_up(data, stride, curr_pos.x, curr_pos.y,
- curr_area.right - curr_area.left,
- curr_area.bottom - curr_area.top,
- curr_area.left, curr_area.top);
- }
- }
- } else {
- end = region->rects - 1;
- now = end + region->num_rects;
- for (; now > end; now--) {
- canvas_copy_fix_clip_area(dest_rect, src_pos, now, &curr_pos, &curr_area);
- __canvas_copy_bits_right(data, stride, curr_pos.x, curr_pos.y,
- curr_area.right - curr_area.left,
- curr_area.bottom - curr_area.top,
- curr_area.left, curr_area.top);
- }
- }
-}
-
-#endif
-
void canvas_copy_bits(CairoCanvas *canvas, SpiceRect *bbox, SpiceClip *clip, SpicePoint *src_pos)
{
- cairo_t *cairo = canvas->cairo;
- cairo_surface_t *cairo_surface;
- pixman_image_t *surface;
- int32_t width;
- int32_t heigth;
+ pixman_region32_t dest_region;
+ int dx, dy;
- cairo_save(cairo);
-#ifdef FAST_COPY_BITS
- switch (clip->type) {
- case SPICE_CLIP_TYPE_NONE: {
- __canvas_copy_rect_bits((uint8_t *)pixman_image_get_data(canvas->image),
- pixman_image_get_stride(canvas->image),
- bbox, src_pos);
- break;
- }
- case SPICE_CLIP_TYPE_RECTS: {
- uint32_t *n = (uint32_t *)SPICE_GET_ADDRESS(clip->data);
- access_test(&canvas->base, n, sizeof(uint32_t));
+ pixman_region32_init_rect (&dest_region,
+ bbox->left, bbox->top,
+ bbox->right - bbox->left,
+ bbox->bottom - bbox->top);
- SpiceRect *now = (SpiceRect *)(n + 1);
- SpiceRect *end = now + *n;
- access_test(&canvas->base, now, (unsigned long)end - (unsigned long)now);
- uint8_t *data = (uint8_t *)pixman_image_get_data(canvas->image);
- int stride = pixman_image_get_stride(canvas->image);
- //using QRegion in order to sort and remove intersections
- QRegion region;
- region_init(®ion);
- for (; now < end; now++) {
- region_add(®ion, now);
- }
- __canvas_copy_region_bits(data, stride, bbox, src_pos, ®ion);
- region_destroy(®ion);
- break;
- }
- default:
-#endif
- canvas_clip(canvas, clip);
+ canvas_clip_pixman (canvas, &dest_region, clip);
- width = bbox->right - bbox->left;
- heigth = bbox->bottom - bbox->top;
- surface = canvas_surface_from_self(canvas, src_pos, width, heigth);
- cairo_surface = surface_from_pixman_image (surface);
- cairo_set_source_surface(cairo, cairo_surface, bbox->left, bbox->top);
- cairo_rectangle(cairo, bbox->left, bbox->top, width, heigth);
- cairo_set_operator(cairo, CAIRO_OPERATOR_RASTER_COPY);
- cairo_fill(cairo);
- cairo_surface_destroy(cairo_surface);
- pixman_image_unref (surface);
-#ifdef FAST_COPY_BITS
- }
+ dx = bbox->left - src_pos->x;
+ dy = bbox->top - src_pos->y;
-#endif
- cairo_restore(cairo);
+ if (dx != 0 || dy != 0)
+ copy_region (canvas,
+ &dest_region, dx, dy);
+
+ pixman_region32_fini (&dest_region);
}
static void canvas_draw_raster_str(CairoCanvas *canvas, SpiceString *str, int bpp,
--
1.6.6
More information about the Spice-devel
mailing list