diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2013-01-13 17:20:24 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2013-01-13 18:37:08 +0000 |
commit | 7012334ebb424b619312e1fa397cc3b8a3ffd770 (patch) | |
tree | 8cbf002161b16ca186651734b4e188aab9b6d97a /src/cairo-xlib-source.c | |
parent | 503b6b9e2ea65805a77d527c00cf242ec86d479b (diff) | |
download | cairo-7012334ebb424b619312e1fa397cc3b8a3ffd770.tar.gz |
xlib: Handle lack of XRenderFillRectangles
Remember to check for a supported render version before making a
FillRectangle request, and fallback to the core protocol where possible
instead.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'src/cairo-xlib-source.c')
-rw-r--r-- | src/cairo-xlib-source.c | 70 |
1 files changed, 60 insertions, 10 deletions
diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c index 0689d8299..d0d6c0edd 100644 --- a/src/cairo-xlib-source.c +++ b/src/cairo-xlib-source.c @@ -71,6 +71,8 @@ _cairo_xlib_source_finish (void *abstract_surface) cairo_xlib_source_t *source = abstract_surface; XRenderFreePicture (source->dpy, source->picture); + if (source->pixmap) + XFreePixmap (source->dpy, source->pixmap); return CAIRO_STATUS_SUCCESS; } @@ -86,6 +88,8 @@ _cairo_xlib_proxy_finish (void *abstract_surface) cairo_xlib_proxy_t *proxy = abstract_surface; XRenderFreePicture (proxy->source.dpy, proxy->source.picture); + if (proxy->source.pixmap) + XFreePixmap (proxy->source.dpy, proxy->source.pixmap); _cairo_xlib_shm_surface_mark_active (proxy->owner); cairo_surface_destroy (proxy->owner); return CAIRO_STATUS_SUCCESS; @@ -98,7 +102,7 @@ static const cairo_surface_backend_t cairo_xlib_proxy_backend = { }; static cairo_surface_t * -source (cairo_xlib_surface_t *dst, Picture picture) +source (cairo_xlib_surface_t *dst, Picture picture, Pixmap pixmap) { cairo_xlib_source_t *source; @@ -108,6 +112,8 @@ source (cairo_xlib_surface_t *dst, Picture picture) source = malloc (sizeof (cairo_image_surface_t)); if (unlikely (source == NULL)) { XRenderFreePicture (dst->display->display, picture); + if (pixmap) + XFreePixmap (dst->display->display, pixmap); return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); } @@ -118,6 +124,7 @@ source (cairo_xlib_surface_t *dst, Picture picture) /* The source exists only within an operation */ source->picture = picture; + source->pixmap = pixmap; source->dpy = dst->display->display; return &source->base; @@ -433,22 +440,65 @@ gradient_source (cairo_xlib_surface_t *dst, return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y); } - return source (dst, picture); + return source (dst, picture, None); } static cairo_surface_t * color_source (cairo_xlib_surface_t *dst, const cairo_color_t *color) { - XRenderColor xrender_color; + Display *dpy = dst->display->display; + XRenderColor xcolor; + Picture picture; + Pixmap pixmap = None; + + xcolor.red = color->red_short; + xcolor.green = color->green_short; + xcolor.blue = color->blue_short; + xcolor.alpha = color->alpha_short; + + if (CAIRO_RENDER_HAS_GRADIENTS(dst->display)) { + picture = XRenderCreateSolidFill (dpy, &xcolor); + } else { + XRenderPictureAttributes pa; + int mask = 0; + + pa.repeat = RepeatNormal; + mask |= CPRepeat; - xrender_color.red = color->red_short; - xrender_color.green = color->green_short; - xrender_color.blue = color->blue_short; - xrender_color.alpha = color->alpha_short; + pixmap = XCreatePixmap (dpy, dst->drawable, 1, 1, 32); + picture = XRenderCreatePicture (dpy, pixmap, + _cairo_xlib_display_get_xrender_format (dst->display, CAIRO_FORMAT_ARGB32), + mask, &pa); + + if (CAIRO_RENDER_HAS_FILL_RECTANGLES(dst->display)) { + XRectangle r = { 0, 0, 1, 1}; + XRenderFillRectangles (dpy, PictOpSrc, picture, &xcolor, &r, 1); + } else { + XGCValues gcv; + GC gc; + + gc = _cairo_xlib_screen_get_gc (dst->display, dst->screen, + 32, pixmap); + if (unlikely (gc == NULL)) { + XFreePixmap (dpy, pixmap); + return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); + } + + gcv.foreground = 0; + gcv.foreground |= color->alpha_short >> 8 << 24; + gcv.foreground |= color->red_short >> 8 << 16; + gcv.foreground |= color->green_short >> 8 << 8; + gcv.foreground |= color->blue_short >> 8 << 0; + gcv.fill_style = FillSolid; + + XChangeGC (dpy, gc, GCFillStyle | GCForeground, &gcv); + XFillRectangle (dpy, pixmap, gc, 0, 0, 1, 1); + + _cairo_xlib_screen_put_gc (dst->display, dst->screen, 32, gc); + } + } - return source (dst, - XRenderCreateSolidFill (dst->display->display, - &xrender_color)); + return source (dst, picture, pixmap); } static cairo_surface_t * |