diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-02-23 13:39:37 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2012-02-23 13:44:28 +0000 |
commit | b079f18fade93472db83b4decf086e30711a86d3 (patch) | |
tree | 4b7346326871bd0848dd1fcf3ddbe81e56f91c2e /src/cairo-xlib-render-compositor.c | |
parent | cc09b29752e857e55879a7d773b8be1317eb2001 (diff) | |
download | cairo-b079f18fade93472db83b4decf086e30711a86d3.tar.gz |
xlib: Handle window-to-window copies by avoiding the use of a clip region
Rather than compress the copies into a clip + copy, iterate over and
perform each copy separately so as to avoid the confusion for
window-to-window copies and the solitary GC->pCompositeClip.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-xlib-render-compositor.c')
-rw-r--r-- | src/cairo-xlib-render-compositor.c | 96 |
1 files changed, 54 insertions, 42 deletions
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c index 106793911..86641b9f4 100644 --- a/src/cairo-xlib-render-compositor.c +++ b/src/cairo-xlib-render-compositor.c @@ -164,18 +164,6 @@ copy_boxes (void *_dst, GC gc; int i, j; - /* We can only have a single control for subwindow_mode on the - * GC. If we have a Window destination, we need to set ClipByChildren, - * but if we have a Window source, we need IncludeInferiors. If we have - * both a Window destination and source, we must fallback. There is - * no convenient way to detect if a drawable is a Pixmap or Window, - * therefore we can only rely on those surfaces that we created - * ourselves to be Pixmaps, and treat everything else as a potential - * Window. - */ - if (! src->owns_pixmap && ! dst->owns_pixmap) - return CAIRO_INT_STATUS_UNSUPPORTED; - if (! _cairo_xlib_surface_same_screen (dst, src)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -210,43 +198,67 @@ copy_boxes (void *_dst, x2 - x1, y2 - y1, x1, y1); } else { - XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)]; - XRectangle *rects = stack_rects; - - if (boxes->num_boxes > ARRAY_LENGTH (stack_rects)) { - rects = _cairo_malloc_ab (boxes->num_boxes, sizeof (XRectangle)); - if (unlikely (rects == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - } + /* We can only have a single control for subwindow_mode on the + * GC. If we have a Window destination, we need to set ClipByChildren, + * but if we have a Window source, we need IncludeInferiors. If we have + * both a Window destination and source, we must fallback. There is + * no convenient way to detect if a drawable is a Pixmap or Window, + * therefore we can only rely on those surfaces that we created + * ourselves to be Pixmaps, and treat everything else as a potential + * Window. + */ + if (src == dst || (!src->owns_pixmap && !dst->owns_pixmap)) { + for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { + for (i = 0; i < chunk->count; i++) { + int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); + int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); + int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); + int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); + XCopyArea (dst->dpy, src->drawable, dst->drawable, gc, + x1 + dx, y1 + dy, + x2 - x1, y2 - y1, + x1, y1); + } + } + } else { + XRectangle stack_rects[CAIRO_STACK_ARRAY_LENGTH (XRectangle)]; + XRectangle *rects = stack_rects; - j = 0; - for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { - for (i = 0; i < chunk->count; i++) { - int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); - int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); - int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); - int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); + if (boxes->num_boxes > ARRAY_LENGTH (stack_rects)) { + rects = _cairo_malloc_ab (boxes->num_boxes, sizeof (XRectangle)); + if (unlikely (rects == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + } - rects[j].x = x1; - rects[j].y = y1; - rects[j].width = x2 - x1; - rects[j].height = y2 - y1; - j++; + j = 0; + for (chunk = &boxes->chunks; chunk; chunk = chunk->next) { + for (i = 0; i < chunk->count; i++) { + int x1 = _cairo_fixed_integer_part (chunk->base[i].p1.x); + int y1 = _cairo_fixed_integer_part (chunk->base[i].p1.y); + int x2 = _cairo_fixed_integer_part (chunk->base[i].p2.x); + int y2 = _cairo_fixed_integer_part (chunk->base[i].p2.y); + + rects[j].x = x1; + rects[j].y = y1; + rects[j].width = x2 - x1; + rects[j].height = y2 - y1; + j++; + } } - } - assert (j == boxes->num_boxes); + assert (j == boxes->num_boxes); - XSetClipRectangles (dst->dpy, gc, 0, 0, rects, j, Unsorted); + XSetClipRectangles (dst->dpy, gc, 0, 0, rects, j, Unsorted); - XCopyArea (dst->dpy, src->drawable, dst->drawable, gc, - extents->x + dx, extents->y + dy, - extents->width, extents->height, - extents->x, extents->y); + XCopyArea (dst->dpy, src->drawable, dst->drawable, gc, + extents->x + dx, extents->y + dy, + extents->width, extents->height, + extents->x, extents->y); - XSetClipMask (dst->dpy, gc, None); + XSetClipMask (dst->dpy, gc, None); - if (rects != stack_rects) - free (rects); + if (rects != stack_rects) + free (rects); + } } if (! src->owns_pixmap) { |