summaryrefslogtreecommitdiff
path: root/src/cairo-xlib-render-compositor.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-02-02 01:07:27 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2012-02-02 01:14:16 +0000
commitb454db4b138872121ac003d4ba953f44e1a1dc60 (patch)
treec57d6dda9be4edd30ea862744e2e894ff54931d9 /src/cairo-xlib-render-compositor.c
parentd95172858bbf12ff4596493c49c4eefe562cd81c (diff)
downloadcairo-b454db4b138872121ac003d4ba953f44e1a1dc60.tar.gz
xlib: Set IncludeInferiors when using CopyArea
cairo-xlib semantics state that we copy the contents of a Window's children when we use a Window as a source in a cairo operation. This requires that we set the IncludeInferiors SubwindowMode on the GC. However, we can only set one SubwindowMode for an operation and our semantics are that drawing performed by cairo onto a Window are clipped by its children (the ClipByChildren SubwindowMode). Therefore if we have to copy between two Window, we can not use CopyArea. Furthermore, we cannot tell if an external Drawable is a Window or a Pixmap, therefore we treat all foriegn Drawables as Window. Failure here means falling back to a render path, where we can independently control the subwindow mode on the source and destination, or to a GetImage/PutImage if the xserver does not support render. Reported-by: Benjamin Otte <otte@redhat.com> 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.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index 6ee69e1a7..0faa55766 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -164,6 +164,18 @@ 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;
@@ -180,6 +192,13 @@ copy_boxes (void *_dst,
return status;
}
+ if (! src->owns_pixmap) {
+ XGCValues gcv;
+
+ gcv.subwindow_mode = IncludeInferiors;
+ XChangeGC (dst->display->display, gc, GCSubwindowMode, &gcv);
+ }
+
if (boxes->num_boxes == 1) {
int x1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.x);
int y1 = _cairo_fixed_integer_part (boxes->chunks.base[0].p1.y);
@@ -230,6 +249,13 @@ copy_boxes (void *_dst,
free (rects);
}
+ if (! src->owns_pixmap) {
+ XGCValues gcv;
+
+ gcv.subwindow_mode = ClipByChildren;
+ XChangeGC (dst->display->display, gc, GCSubwindowMode, &gcv);
+ }
+
_cairo_xlib_surface_put_gc (dst->display, dst, gc);
release (dst);
return CAIRO_STATUS_SUCCESS;