mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-08 02:08:03 +02:00
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.
This commit is contained in:
parent
60aefd0d63
commit
a1d0a06b62
6 changed files with 45 additions and 9 deletions
1
AUTHORS
1
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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue