diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c index b1fc67e9e..cdae8c926 100644 --- a/src/cairo-xlib-display.c +++ b/src/cairo-xlib-display.c @@ -287,6 +287,9 @@ _cairo_xlib_display_get (Display *dpy) display->close_display_hooks = NULL; display->closed = FALSE; + memset (display->cached_xrender_formats, 0, + sizeof (display->cached_xrender_formats)); + display->buggy_repeat = FALSE; if (strstr (ServerVendor (dpy), "X.Org") != NULL) { /* When modularized, the X.Org server VendorRelease was @@ -485,3 +488,35 @@ _cairo_xlib_display_notify (cairo_xlib_display_t *display) } CAIRO_MUTEX_UNLOCK (display->mutex); } + +XRenderPictFormat * +_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, + cairo_format_t format) +{ + XRenderPictFormat *xrender_format; + + CAIRO_MUTEX_LOCK (display->mutex); + xrender_format = display->cached_xrender_formats[format]; + if (xrender_format == NULL) { + int pict_format; + + switch (format) { + case CAIRO_FORMAT_A1: + pict_format = PictStandardA1; break; + case CAIRO_FORMAT_A8: + pict_format = PictStandardA8; break; + case CAIRO_FORMAT_RGB24: + pict_format = PictStandardRGB24; break; + default: + ASSERT_NOT_REACHED; + case CAIRO_FORMAT_ARGB32: + pict_format = PictStandardARGB32; break; + } + xrender_format = XRenderFindStandardFormat (display->display, + pict_format); + display->cached_xrender_formats[format] = xrender_format; + } + CAIRO_MUTEX_UNLOCK (display->mutex); + + return xrender_format; +} diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h index 2d9737d93..a88e6b532 100644 --- a/src/cairo-xlib-private.h +++ b/src/cairo-xlib-private.h @@ -34,6 +34,7 @@ #define CAIRO_XLIB_PRIVATE_H #include "cairo-xlib.h" +#include "cairo-xlib-xrender-private.h" #include "cairo-compiler-private.h" #include "cairo-freelist-private.h" @@ -61,6 +62,8 @@ struct _cairo_xlib_display { Display *display; cairo_xlib_screen_info_t *screens; + XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_A1 + 1]; + cairo_xlib_job_t *workqueue; cairo_freelist_t wq_freelist; @@ -118,6 +121,10 @@ _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display, cairo_private void _cairo_xlib_display_notify (cairo_xlib_display_t *display); +cairo_private XRenderPictFormat * +_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, + cairo_format_t format); + cairo_private cairo_xlib_screen_info_t * _cairo_xlib_screen_info_get (Display *display, Screen *screen); diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index acb51c560..1b094f9cb 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -117,24 +117,6 @@ static const XTransform identity = { { #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) -static XRenderPictFormat * -_CAIRO_FORMAT_TO_XRENDER_FORMAT(Display *dpy, cairo_format_t format) -{ - int pict_format; - switch (format) { - case CAIRO_FORMAT_A1: - pict_format = PictStandardA1; break; - case CAIRO_FORMAT_A8: - pict_format = PictStandardA8; break; - case CAIRO_FORMAT_RGB24: - pict_format = PictStandardRGB24; break; - case CAIRO_FORMAT_ARGB32: - default: - pict_format = PictStandardARGB32; break; - } - return XRenderFindStandardFormat (dpy, pict_format); -} - static cairo_surface_t * _cairo_xlib_surface_create_similar_with_format (void *abstract_src, cairo_format_t format, @@ -145,15 +127,20 @@ _cairo_xlib_surface_create_similar_with_format (void *abstract_src, Display *dpy = src->dpy; Pixmap pix; cairo_xlib_surface_t *surface; - XRenderPictFormat *xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (dpy, - format); + XRenderPictFormat *xrender_format; /* As a good first approximation, if the display doesn't have even * the most elementary RENDER operation, then we're better off * using image surfaces for all temporary operations, so return NULL * and let the fallback code happen. */ - if (xrender_format == NULL || ! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)) + if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src)) + return NULL; + + xrender_format = _cairo_xlib_display_get_xrender_format ( + src->screen_info->display, + format); + if (xrender_format == NULL) return NULL; pix = XCreatePixmap (dpy, src->drawable, @@ -2031,8 +2018,9 @@ _cairo_xlib_surface_is_similar (void *surface_a, if (xrender_format == NULL || _xrender_format_to_content (xrender_format) != content) { - xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT (b->dpy, - _cairo_format_from_content (content)); + xrender_format = _cairo_xlib_display_get_xrender_format ( + b->screen_info->display, + _cairo_format_from_content (content)); } @@ -2691,8 +2679,8 @@ typedef struct _cairo_xlib_font_glyphset_info { } cairo_xlib_font_glyphset_info_t; typedef struct _cairo_xlib_surface_font_private { - Display *dpy; - cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS]; + cairo_xlib_display_t *display; + cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS]; } cairo_xlib_surface_font_private_t; static void @@ -2711,12 +2699,16 @@ _cairo_xlib_surface_remove_scaled_font (Display *dpy, if (font_private != NULL) { int i; + for (i = 0; i < NUM_GLYPHSETS; i++) { - cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i]; - if (glyphset_info->glyphset) { - XRenderFreeGlyphSet (font_private->dpy, glyphset_info->glyphset); - } + cairo_xlib_font_glyphset_info_t *glyphset_info; + + glyphset_info = &font_private->glyphset_info[i]; + if (glyphset_info->glyphset) + XRenderFreeGlyphSet (dpy, glyphset_info->glyphset); } + + _cairo_xlib_display_destroy (font_private->display); free (font_private); } } @@ -2729,25 +2721,26 @@ _cairo_xlib_surface_font_init (Display *dpy, int i; font_private = malloc (sizeof (cairo_xlib_surface_font_private_t)); - if (!font_private) + if (font_private == NULL) return _cairo_error (CAIRO_STATUS_NO_MEMORY); - if (!_cairo_xlib_add_close_display_hook (dpy, - _cairo_xlib_surface_remove_scaled_font, - scaled_font, scaled_font)) { + if (! _cairo_xlib_add_close_display_hook (dpy, + _cairo_xlib_surface_remove_scaled_font, + scaled_font, scaled_font)) + { free (font_private); return _cairo_error (CAIRO_STATUS_NO_MEMORY); } - font_private->dpy = dpy; + font_private->display = _cairo_xlib_display_get (dpy); for (i = 0; i < NUM_GLYPHSETS; i++) { cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i]; switch (i) { - case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break; - case GLYPHSET_INDEX_A8: glyphset_info->format = CAIRO_FORMAT_A8; break; - case GLYPHSET_INDEX_A1: glyphset_info->format = CAIRO_FORMAT_A1; break; - default: ASSERT_NOT_REACHED; break; + case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break; + case GLYPHSET_INDEX_A8: glyphset_info->format = CAIRO_FORMAT_A8; break; + case GLYPHSET_INDEX_A1: glyphset_info->format = CAIRO_FORMAT_A1; break; + default: ASSERT_NOT_REACHED; break; } glyphset_info->xrender_format = NULL; glyphset_info->glyphset = None; @@ -2762,31 +2755,31 @@ _cairo_xlib_surface_font_init (Display *dpy, static void _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) { - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + cairo_xlib_surface_font_private_t *font_private; - if (font_private) { + font_private = scaled_font->surface_private; + if (font_private != NULL) { cairo_xlib_display_t *display; + int i; - _cairo_xlib_remove_close_display_hooks (font_private->dpy, scaled_font); + display = font_private->display; + _cairo_xlib_remove_close_display_hooks (display->display, scaled_font); - display = _cairo_xlib_display_get (font_private->dpy); - if (display != NULL) { - int i; + for (i = 0; i < NUM_GLYPHSETS; i++) { + cairo_xlib_font_glyphset_info_t *glyphset_info; - for (i = 0; i < NUM_GLYPHSETS; i++) { - cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i]; - if (glyphset_info->glyphset) { - cairo_status_t status; - status = _cairo_xlib_display_queue_resource (display, - XRenderFreeGlyphSet, - glyphset_info->glyphset); - (void) status; /* XXX cannot propagate failure */ - } + glyphset_info = &font_private->glyphset_info[i]; + if (glyphset_info->glyphset) { + cairo_status_t status; + + status = _cairo_xlib_display_queue_resource (display, + XRenderFreeGlyphSet, + glyphset_info->glyphset); + (void) status; /* XXX cannot propagate failure */ } - - _cairo_xlib_display_destroy (display); } + _cairo_xlib_display_destroy (display); free (font_private); } } @@ -2819,28 +2812,31 @@ static void _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, cairo_scaled_font_t *scaled_font) { - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + cairo_xlib_surface_font_private_t *font_private; + cairo_xlib_font_glyphset_info_t *glyphset_info; - if (font_private != NULL && scaled_glyph->surface_private != NULL) { - cairo_xlib_display_t *display = _cairo_xlib_display_get (font_private->dpy); - if (display != NULL) { - struct _cairo_xlib_render_free_glyphs *arg = malloc (sizeof (*arg)); - if (arg != NULL) { - cairo_status_t status; - arg->glyphset = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph)->glyphset; - arg->glyph_index = _cairo_scaled_glyph_index (scaled_glyph); - status = _cairo_xlib_display_queue_work (display, - (cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs, - arg, - free); - if (status) { - /* XXX cannot propagate failure */ - free (arg); - } + font_private = scaled_font->surface_private; + glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph); + if (font_private != NULL && glyphset_info != NULL) { + cairo_xlib_display_t *display; + struct _cairo_xlib_render_free_glyphs *arg; + + display = font_private->display; + arg = malloc (sizeof (*arg)); + if (arg != NULL) { + cairo_status_t status; + + arg->glyphset = glyphset_info->glyphset; + arg->glyph_index = _cairo_scaled_glyph_index (scaled_glyph); + + status = _cairo_xlib_display_queue_work (display, + (cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs, + arg, + free); + if (status) { + /* XXX cannot propagate failure */ + free (arg); } - - _cairo_xlib_display_destroy (display); - } } } @@ -2857,7 +2853,7 @@ static cairo_xlib_font_glyphset_info_t * _cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scaled_font, cairo_format_t format) { - cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private; + cairo_xlib_surface_font_private_t *font_private; cairo_xlib_font_glyphset_info_t *glyphset_info; int glyphset_index; @@ -2869,11 +2865,16 @@ _cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scale case CAIRO_FORMAT_A1: glyphset_index = GLYPHSET_INDEX_A1; break; } + font_private = scaled_font->surface_private; glyphset_info = &font_private->glyphset_info[glyphset_index]; - if (glyphset_info->glyphset == None) { - glyphset_info->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(font_private->dpy, glyphset_info->format); - glyphset_info->glyphset = XRenderCreateGlyphSet (font_private->dpy, glyphset_info->xrender_format); + cairo_xlib_display_t *display = font_private->display; + + glyphset_info->xrender_format = + _cairo_xlib_display_get_xrender_format (display, + glyphset_info->format); + glyphset_info->glyphset = XRenderCreateGlyphSet (display->display, + glyphset_info->xrender_format); } return glyphset_info; @@ -3442,7 +3443,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, font_private = scaled_font->surface_private; if ((scaled_font->surface_backend != NULL && scaled_font->surface_backend != &cairo_xlib_surface_backend) || - (font_private != NULL && font_private->dpy != dst->dpy)) + (font_private != NULL && font_private->display != dst->screen_info->display)) return CAIRO_INT_STATUS_UNSUPPORTED; /* After passing all those tests, we're now committed to rendering