summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Jaeger <ThJaeger@gmail.com>2009-02-19 12:02:41 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2009-06-05 17:26:09 +0100
commita1d0a06b6275cac3974be84919993e187394fe43 (patch)
treeb5d1d034388f807c6d2208ff08063410caef82d1
parent60aefd0d634c531353c92b77b36424b142efeb93 (diff)
downloadcairo-a1d0a06b6275cac3974be84919993e187394fe43.tar.gz
xlib, xcb: Hand off EXTEND_PAD/EXTEND_REFLECT to Render
Most drivers and the X server used to have incorrect RepeatPad/RepeatReflect implementations, forcing cairo to fall back to client-side software rendering, which is painfully slow due to pixmaps being transfered over the wire. These issues are mostly fixed in the drivers (with the exception of radeonhd, whose developers didn't respond) and the RepeatPad software fallback is implemented correctly as of pixman-0.15.0, so this patch will hand off composite operations with EXTEND_PAD/EXTEND_REFLECT source patterns to XRender. There is no way to detect whether the X server or the drivers use a broken Render implementation, we make a guess based on the server version: It's probably safe to assume that 1.7 X servers will use fixed drivers and a recent enough version of pixman.
-rw-r--r--AUTHORS1
-rw-r--r--src/cairo-xcb-surface.c15
-rw-r--r--src/cairo-xlib-display.c15
-rw-r--r--src/cairo-xlib-private.h1
-rw-r--r--src/cairo-xlib-surface-private.h1
-rw-r--r--src/cairo-xlib-surface.c21
6 files changed, 45 insertions, 9 deletions
diff --git a/AUTHORS b/AUTHORS
index 8c061743b..9856a8819 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -35,6 +35,7 @@ Richard Henderson <rth@twiddle.net> "slim" macros for better shared libraries
James Henstridge <james@daa.com.au> Build fixes related to freetype
Graydon Hoare <graydon@redhat.com> Support for non-render X server, first real text support
Thomas Hunger <info@teh-web.de> Initial version of cairo_in_stroke/fill
+Thomas Jaeger <ThJaeger@gmail.com> Extended repeat modes for X
Björn Lindqvist <bjourne@gmail.com> Performance test cases
Kristian Høgsberg <krh@redhat.com> PDF backend, PS backend with meta-surfaces
Amaury Jacquot <sxpert@esitcom.org> Documentation review, appplication testing
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 30a5c6b34..78d9a0082 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -101,6 +101,8 @@ typedef struct cairo_xcb_surface {
#define CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
#define CAIRO_SURFACE_RENDER_HAS_FILTERS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 6)
+#define CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
+#define CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 10)
static void
_cairo_xcb_surface_ensure_gc (cairo_xcb_surface_t *surface);
@@ -854,13 +856,22 @@ _cairo_xcb_surface_set_attributes (cairo_xcb_surface_t *surface,
switch (attributes->extend) {
case CAIRO_EXTEND_NONE:
- _cairo_xcb_surface_set_repeat (surface, 0);
+ _cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_NONE);
break;
case CAIRO_EXTEND_REPEAT:
- _cairo_xcb_surface_set_repeat (surface, 1);
+ _cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_NORMAL);
break;
case CAIRO_EXTEND_REFLECT:
+ if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_REFLECT(surface))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ _cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_REFLECT);
+ break;
case CAIRO_EXTEND_PAD:
+ if (!CAIRO_SURFACE_RENDER_HAS_REPEAT_PAD(surface))
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ _cairo_xcb_surface_set_repeat (surface, XCB_RENDER_REPEAT_PAD);
+ break;
+ default:
return CAIRO_INT_STATUS_UNSUPPORTED;
}
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c
index af244abe4..65df2b719 100644
--- a/src/cairo-xlib-display.c
+++ b/src/cairo-xlib-display.c
@@ -285,6 +285,7 @@ _cairo_xlib_display_get (Display *dpy,
sizeof (display->cached_xrender_formats));
display->buggy_repeat = FALSE;
+ display->buggy_pad_reflect = TRUE;
/* This buggy_repeat condition is very complicated because there
* are multiple X server code bases (with multiple versioning
@@ -331,13 +332,19 @@ _cairo_xlib_display_get (Display *dpy,
* (just using VendorRelase < 70000000), as buggy_repeat=TRUE.
*/
if (strstr (ServerVendor (dpy), "X.Org") != NULL) {
- if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) < 70000000)
- display->buggy_repeat = TRUE;
- if (VendorRelease (dpy) < 10400000)
- display->buggy_repeat = TRUE;
+ if (VendorRelease (dpy) >= 60700000) {
+ if (VendorRelease (dpy) < 70000000)
+ display->buggy_repeat = TRUE;
+ } else {
+ if (VendorRelease (dpy) < 10400000)
+ display->buggy_repeat = TRUE;
+ if (VendorRelease (dpy) >= 10699000)
+ display->buggy_pad_reflect = FALSE;
+ }
} else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
if (VendorRelease (dpy) <= 40500000)
display->buggy_repeat = TRUE;
+
}
display->next = _cairo_xlib_display_list;
diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h
index b9c84b845..4995bc6f9 100644
--- a/src/cairo-xlib-private.h
+++ b/src/cairo-xlib-private.h
@@ -73,6 +73,7 @@ struct _cairo_xlib_display {
cairo_xlib_hook_t *close_display_hooks;
unsigned int buggy_repeat :1;
+ unsigned int buggy_pad_reflect :1;
unsigned int closed :1;
};
diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h
index fe37e5fbd..164fe15f2 100644
--- a/src/cairo-xlib-surface-private.h
+++ b/src/cairo-xlib-surface-private.h
@@ -76,6 +76,7 @@ struct _cairo_xlib_surface {
* we can reuse the test for now.
*/
cairo_bool_t buggy_repeat;
+ cairo_bool_t buggy_pad_reflect;
int width;
int height;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index aa6b3d17b..67b4ca6f3 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1466,7 +1466,15 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface,
_cairo_xlib_surface_set_repeat (surface, RepeatNormal);
break;
case CAIRO_EXTEND_REFLECT:
+ if (surface->buggy_pad_reflect)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ _cairo_xlib_surface_set_repeat (surface, RepeatReflect);
+ break;
case CAIRO_EXTEND_PAD:
+ if (surface->buggy_pad_reflect)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ _cairo_xlib_surface_set_repeat (surface, RepeatPad);
+ break;
default:
return CAIRO_INT_STATUS_UNSUPPORTED;
}
@@ -1768,7 +1776,9 @@ _cairo_xlib_surface_composite (cairo_operator_t op,
src_x, src_y,
mask_x, mask_y,
width, height,
- CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
+ dst->buggy_pad_reflect ?
+ CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
+ CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
(cairo_surface_t **) &mask,
&src_attr, &mask_attr);
@@ -2181,7 +2191,9 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op,
status = _cairo_pattern_acquire_surface (pattern, &dst->base,
CAIRO_CONTENT_COLOR_ALPHA,
src_x, src_y, width, height,
- CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
+ dst->buggy_pad_reflect ?
+ CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
+ CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attributes);
if (unlikely (status))
@@ -2686,6 +2698,7 @@ _cairo_xlib_surface_create_internal (Display *dpy,
/* so we can use the XTile fallback */
surface->buggy_repeat = TRUE;
}
+ surface->buggy_pad_reflect = screen_info->display->buggy_pad_reflect;
surface->dst_picture = None;
surface->src_picture = None;
@@ -4125,7 +4138,9 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst,
CAIRO_CONTENT_COLOR_ALPHA,
glyph_extents.x, glyph_extents.y,
glyph_extents.width, glyph_extents.height,
- CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
+ dst->buggy_pad_reflect ?
+ CAIRO_PATTERN_ACQUIRE_NO_REFLECT :
+ CAIRO_PATTERN_ACQUIRE_NONE,
(cairo_surface_t **) &src,
&attributes);
if (unlikely (status))