diff options
-rw-r--r-- | src/cairo-xlib-display.c | 234 | ||||
-rw-r--r-- | src/cairo-xlib-private.h | 66 | ||||
-rw-r--r-- | src/cairo-xlib-screen.c | 161 | ||||
-rw-r--r-- | src/cairo-xlib-surface-private.h | 2 | ||||
-rw-r--r-- | src/cairo-xlib-surface.c | 557 |
5 files changed, 494 insertions, 526 deletions
diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c index 69b7c66b..be65c227 100644 --- a/src/cairo-xlib-display.c +++ b/src/cairo-xlib-display.c @@ -39,32 +39,9 @@ #include "cairo-xlib-xrender-private.h" #include "cairo-error-private.h" -#include "cairo-freelist-private.h" #include <X11/Xlibint.h> /* For XESetCloseDisplay */ -struct _cairo_xlib_display { - cairo_xlib_display_t *next; - cairo_reference_count_t ref_count; - cairo_mutex_t mutex; - - Display *display; - cairo_xlib_screen_t *screens; - - int render_major; - int render_minor; - XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_RGB16_565 + 1]; - - cairo_xlib_job_t *workqueue; - cairo_freelist_t wq_freelist; - - cairo_xlib_hook_t *close_display_hooks; - unsigned int buggy_gradients :1; - unsigned int buggy_pad_reflect :1; - unsigned int buggy_repeat :1; - unsigned int closed :1; -}; - typedef int (*cairo_xlib_error_func_t) (Display *display, XErrorEvent *event); @@ -99,11 +76,8 @@ _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display) cairo_xlib_screen_t *screen; cairo_xlib_hook_t *hook; - /* call all registered shutdown routines */ - CAIRO_MUTEX_LOCK (display->mutex); - for (screen = display->screens; screen != NULL; screen = screen->next) - _cairo_xlib_screen_close_display (screen); + _cairo_xlib_screen_close_display (display, screen); while (TRUE) { hook = display->close_display_hooks; @@ -112,13 +86,9 @@ _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display) _cairo_xlib_remove_close_display_hook_internal (display, hook); - CAIRO_MUTEX_UNLOCK (display->mutex); hook->func (display, hook); - CAIRO_MUTEX_LOCK (display->mutex); } display->closed = TRUE; - - CAIRO_MUTEX_UNLOCK (display->mutex); } static void @@ -126,10 +96,8 @@ _cairo_xlib_display_discard_screens (cairo_xlib_display_t *display) { cairo_xlib_screen_t *screens; - CAIRO_MUTEX_LOCK (display->mutex); screens = display->screens; display->screens = NULL; - CAIRO_MUTEX_UNLOCK (display->mutex); while (screens != NULL) { cairo_xlib_screen_t *screen = screens; @@ -139,23 +107,10 @@ _cairo_xlib_display_discard_screens (cairo_xlib_display_t *display) } } -cairo_xlib_display_t * -_cairo_xlib_display_reference (cairo_xlib_display_t *display) -{ - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count)); - - _cairo_reference_count_inc (&display->ref_count); - - return display; -} - -void -_cairo_xlib_display_destroy (cairo_xlib_display_t *display) +static void +_cairo_xlib_display_destroy (void *abstract_display) { - assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&display->ref_count)); - - if (! _cairo_reference_count_dec_and_test (&display->ref_count)) - return; + cairo_xlib_display_t *display = abstract_display; /* destroy all outstanding notifies */ while (display->workqueue != NULL) { @@ -169,8 +124,6 @@ _cairo_xlib_display_destroy (cairo_xlib_display_t *display) } _cairo_freelist_fini (&display->wq_freelist); - CAIRO_MUTEX_FINI (display->mutex); - free (display); } @@ -180,6 +133,60 @@ _noop_error_handler (Display *display, { return False; /* return value is ignored */ } + +static void +_cairo_xlib_display_notify (cairo_xlib_display_t *display) +{ + cairo_xlib_job_t *jobs, *job, *freelist; + Display *dpy = display->display; + + /* Optimistic atomic pointer read -- don't care if it is wrong due to + * contention as we will check again very shortly. + */ + if (display->workqueue == NULL) + return; + + jobs = display->workqueue; + while (jobs != NULL) { + display->workqueue = NULL; + + /* reverse the list to obtain FIFO order */ + job = NULL; + do { + cairo_xlib_job_t *next = jobs->next; + jobs->next = job; + job = jobs; + jobs = next; + } while (jobs != NULL); + freelist = jobs = job; + + do { + job = jobs; + jobs = job->next; + + switch (job->type){ + case WORK: + job->func.work.notify (dpy, job->func.work.data); + if (job->func.work.destroy != NULL) + job->func.work.destroy (job->func.work.data); + break; + + case RESOURCE: + job->func.resource.notify (dpy, job->func.resource.xid); + break; + } + } while (jobs != NULL); + + do { + job = freelist; + freelist = job->next; + _cairo_freelist_free (&display->wq_freelist, job); + } while (freelist != NULL); + + jobs = display->workqueue; + } +} + static int _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) { @@ -198,12 +205,15 @@ _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) XSync (dpy, False); old_handler = XSetErrorHandler (_noop_error_handler); + if (cairo_device_acquire (&display->base)) + return 0; _cairo_xlib_display_notify (display); _cairo_xlib_call_close_display_hooks (display); _cairo_xlib_display_discard_screens (display); /* catch any that arrived before marking the display as closed */ _cairo_xlib_display_notify (display); + cairo_device_release (&display->base); XSync (dpy, False); XSetErrorHandler (old_handler); @@ -231,6 +241,17 @@ _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) return 0; } +static const cairo_device_backend_t _cairo_xlib_device_backend = { + CAIRO_DEVICE_TYPE_XLIB, + + NULL, + NULL, + + NULL, /* flush */ + NULL, /* finish */ + _cairo_xlib_display_destroy, +}; + cairo_status_t _cairo_xlib_display_get (Display *dpy, cairo_xlib_display_t **out) @@ -266,7 +287,7 @@ _cairo_xlib_display_get (Display *dpy, } if (display != NULL) { - display = _cairo_xlib_display_reference (display); + cairo_device_reference (&display->base); goto UNLOCK; } @@ -309,12 +330,13 @@ _cairo_xlib_display_get (Display *dpy, goto UNLOCK; } + _cairo_device_init (&display->base, &_cairo_xlib_device_backend); + XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display); _cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t)); - CAIRO_REFERENCE_COUNT_INIT (&display->ref_count, 2); /* add one for the CloseDisplay */ - CAIRO_MUTEX_INIT (display->mutex); + cairo_device_reference (&display->base); /* add one for the CloseDisplay */ display->display = dpy; display->screens = NULL; display->workqueue = NULL; @@ -419,16 +441,13 @@ void _cairo_xlib_add_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook) { - CAIRO_MUTEX_LOCK (display->mutex); hook->prev = NULL; hook->next = display->close_display_hooks; if (hook->next != NULL) hook->next->prev = hook; display->close_display_hooks = hook; - CAIRO_MUTEX_UNLOCK (display->mutex); } -/* display->mutex must be held */ static void _cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook) @@ -449,9 +468,7 @@ void _cairo_xlib_remove_close_display_hook (cairo_xlib_display_t *display, cairo_xlib_hook_t *hook) { - CAIRO_MUTEX_LOCK (display->mutex); _cairo_xlib_remove_close_display_hook_internal (display, hook); - CAIRO_MUTEX_UNLOCK (display->mutex); } cairo_status_t @@ -462,7 +479,6 @@ _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display, cairo_xlib_job_t *job; cairo_status_t status = CAIRO_STATUS_NO_MEMORY; - CAIRO_MUTEX_LOCK (display->mutex); if (display->closed == FALSE) { job = _cairo_freelist_alloc (&display->wq_freelist); if (job != NULL) { @@ -476,7 +492,6 @@ _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display, status = CAIRO_STATUS_SUCCESS; } } - CAIRO_MUTEX_UNLOCK (display->mutex); return status; } @@ -490,7 +505,6 @@ _cairo_xlib_display_queue_work (cairo_xlib_display_t *display, cairo_xlib_job_t *job; cairo_status_t status = CAIRO_STATUS_NO_MEMORY; - CAIRO_MUTEX_LOCK (display->mutex); if (display->closed == FALSE) { job = _cairo_freelist_alloc (&display->wq_freelist); if (job != NULL) { @@ -505,66 +519,22 @@ _cairo_xlib_display_queue_work (cairo_xlib_display_t *display, status = CAIRO_STATUS_SUCCESS; } } - CAIRO_MUTEX_UNLOCK (display->mutex); return status; } -void -_cairo_xlib_display_notify (cairo_xlib_display_t *display) +cairo_status_t +_cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **display) { - cairo_xlib_job_t *jobs, *job, *freelist; - Display *dpy = display->display; - - /* Optimistic atomic pointer read -- don't care if it is wrong due to - * contention as we will check again very shortly. - */ - if (display->workqueue == NULL) - return; - - CAIRO_MUTEX_LOCK (display->mutex); - jobs = display->workqueue; - while (jobs != NULL) { - display->workqueue = NULL; - CAIRO_MUTEX_UNLOCK (display->mutex); - - /* reverse the list to obtain FIFO order */ - job = NULL; - do { - cairo_xlib_job_t *next = jobs->next; - jobs->next = job; - job = jobs; - jobs = next; - } while (jobs != NULL); - freelist = jobs = job; + cairo_status_t status; - do { - job = jobs; - jobs = job->next; + status = cairo_device_acquire (device); + if (status) + return status; - switch (job->type){ - case WORK: - job->func.work.notify (dpy, job->func.work.data); - if (job->func.work.destroy != NULL) - job->func.work.destroy (job->func.work.data); - break; - - case RESOURCE: - job->func.resource.notify (dpy, job->func.resource.xid); - break; - } - } while (jobs != NULL); - - CAIRO_MUTEX_LOCK (display->mutex); - do { - job = freelist; - freelist = job->next; - _cairo_freelist_free (&display->wq_freelist, job); - } while (freelist != NULL); - - jobs = display->workqueue; - } - CAIRO_MUTEX_UNLOCK (display->mutex); + *display = (cairo_xlib_display_t *) device; + _cairo_xlib_display_notify (*display); + return status; } XRenderPictFormat * @@ -579,7 +549,6 @@ _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, return xrender_format; #endif - CAIRO_MUTEX_LOCK (display->mutex); xrender_format = display->cached_xrender_formats[format]; if (xrender_format == NULL) { int pict_format; @@ -605,10 +574,8 @@ _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, break; } } - if (!visual) { - CAIRO_MUTEX_UNLOCK (display->mutex); + if (!visual) return NULL; - } xrender_format = XRenderFindVisualFormat(display->display, visual); break; } @@ -623,17 +590,10 @@ _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, pict_format); display->cached_xrender_formats[format] = xrender_format; } - CAIRO_MUTEX_UNLOCK (display->mutex); return xrender_format; } -Display * -_cairo_xlib_display_get_dpy (cairo_xlib_display_t *display) -{ - return display->display; -} - void _cairo_xlib_display_remove_screen (cairo_xlib_display_t *display, cairo_xlib_screen_t *screen) @@ -641,14 +601,12 @@ _cairo_xlib_display_remove_screen (cairo_xlib_display_t *display, cairo_xlib_screen_t **prev; cairo_xlib_screen_t *list; - CAIRO_MUTEX_LOCK (display->mutex); for (prev = &display->screens; (list = *prev); prev = &list->next) { if (list == screen) { *prev = screen->next; break; } } - CAIRO_MUTEX_UNLOCK (display->mutex); } cairo_status_t @@ -658,11 +616,8 @@ _cairo_xlib_display_get_screen (cairo_xlib_display_t *display, { cairo_xlib_screen_t *info = NULL, **prev; - CAIRO_MUTEX_LOCK (display->mutex); - if (display->closed) { - CAIRO_MUTEX_UNLOCK (display->mutex); + if (display->closed) return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED); - } for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) { if (info->screen == screen) { @@ -677,7 +632,6 @@ _cairo_xlib_display_get_screen (cairo_xlib_display_t *display, break; } } - CAIRO_MUTEX_UNLOCK (display->mutex); *out = info; return CAIRO_STATUS_SUCCESS; @@ -688,10 +642,8 @@ void _cairo_xlib_display_add_screen (cairo_xlib_display_t *display, cairo_xlib_screen_t *screen) { - CAIRO_MUTEX_LOCK (display->mutex); screen->next = display->screens; display->screens = screen; - CAIRO_MUTEX_UNLOCK (display->mutex); } void @@ -703,19 +655,19 @@ _cairo_xlib_display_get_xrender_version (cairo_xlib_display_t *display, } cairo_bool_t -_cairo_xlib_display_has_repeat (cairo_xlib_display_t *display) +_cairo_xlib_display_has_repeat (cairo_device_t *device) { - return ! display->buggy_repeat; + return ! ((cairo_xlib_display_t *) device)->buggy_repeat; } cairo_bool_t -_cairo_xlib_display_has_reflect (cairo_xlib_display_t *display) +_cairo_xlib_display_has_reflect (cairo_device_t *device) { - return ! display->buggy_pad_reflect; + return ! ((cairo_xlib_display_t *) device)->buggy_pad_reflect; } cairo_bool_t -_cairo_xlib_display_has_gradients (cairo_xlib_display_t *display) +_cairo_xlib_display_has_gradients (cairo_device_t *device) { - return ! display->buggy_gradients; + return ! ((cairo_xlib_display_t *) device)->buggy_gradients; } diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h index afdf6a6b..550520da 100644 --- a/src/cairo-xlib-private.h +++ b/src/cairo-xlib-private.h @@ -41,7 +41,8 @@ #include "cairo-xlib-xrender-private.h" #include "cairo-compiler-private.h" -#include "cairo-mutex-private.h" +#include "cairo-device-private.h" +#include "cairo-freelist-private.h" #include "cairo-reference-count-private.h" #include "cairo-types-private.h" @@ -63,6 +64,28 @@ struct _cairo_xlib_hook { /* size of gray ramp */ #define RAMP_SIZE 16 +struct _cairo_xlib_display { + cairo_device_t base; + + cairo_xlib_display_t *next; + + Display *display; + cairo_xlib_screen_t *screens; + + int render_major; + int render_minor; + XRenderPictFormat *cached_xrender_formats[CAIRO_FORMAT_RGB16_565 + 1]; + + cairo_xlib_job_t *workqueue; + cairo_freelist_t wq_freelist; + + cairo_xlib_hook_t *close_display_hooks; + unsigned int buggy_gradients :1; + unsigned int buggy_pad_reflect :1; + unsigned int buggy_repeat :1; + unsigned int closed :1; +}; + typedef struct _cairo_xlib_visual_info { VisualID visualid; struct { uint8_t a, r, g, b; } colors[256]; @@ -75,9 +98,8 @@ typedef struct _cairo_xlib_visual_info { struct _cairo_xlib_screen { cairo_xlib_screen_t *next; cairo_reference_count_t ref_count; - cairo_mutex_t mutex; - cairo_xlib_display_t *display; + cairo_device_t *device; Screen *screen; cairo_bool_t has_render; @@ -93,21 +115,6 @@ struct _cairo_xlib_screen { cairo_private cairo_status_t _cairo_xlib_display_get (Display *display, cairo_xlib_display_t **out); -cairo_private cairo_xlib_display_t * -_cairo_xlib_display_reference (cairo_xlib_display_t *info); - -cairo_private void -_cairo_xlib_display_destroy (cairo_xlib_display_t *info); - -cairo_private void -_cairo_xlib_display_lock (cairo_xlib_display_t *display); - -cairo_private void -_cairo_xlib_display_unlock (cairo_xlib_display_t *display); - -cairo_private Display * -_cairo_xlib_display_get_dpy (cairo_xlib_display_t *info); - cairo_private void _cairo_xlib_display_add_screen (cairo_xlib_display_t *display, cairo_xlib_screen_t *screen); @@ -136,21 +143,22 @@ cairo_private cairo_status_t _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display, cairo_xlib_notify_resource_func notify, XID resource); -cairo_private void -_cairo_xlib_display_notify (cairo_xlib_display_t *display); +cairo_private cairo_status_t +_cairo_xlib_display_acquire (cairo_device_t *device, + cairo_xlib_display_t **display); cairo_private void _cairo_xlib_display_get_xrender_version (cairo_xlib_display_t *display, int *major, int *minor); cairo_private cairo_bool_t -_cairo_xlib_display_has_repeat (cairo_xlib_display_t *display); +_cairo_xlib_display_has_repeat (cairo_device_t *device); cairo_private cairo_bool_t -_cairo_xlib_display_has_reflect (cairo_xlib_display_t *display); +_cairo_xlib_display_has_reflect (cairo_device_t *device); cairo_private cairo_bool_t -_cairo_xlib_display_has_gradients (cairo_xlib_display_t *display); +_cairo_xlib_display_has_gradients (cairo_device_t *device); cairo_private XRenderPictFormat * _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display, @@ -167,15 +175,18 @@ cairo_private void _cairo_xlib_screen_destroy (cairo_xlib_screen_t *info); cairo_private void -_cairo_xlib_screen_close_display (cairo_xlib_screen_t *info); +_cairo_xlib_screen_close_display (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info); cairo_private GC -_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info, +_cairo_xlib_screen_get_gc (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info, int depth, Drawable drawable); cairo_private void -_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info, +_cairo_xlib_screen_put_gc (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info, int depth, GC gc); @@ -183,7 +194,8 @@ cairo_private cairo_font_options_t * _cairo_xlib_screen_get_font_options (cairo_xlib_screen_t *info); cairo_private cairo_status_t -_cairo_xlib_screen_get_visual_info (cairo_xlib_screen_t *info, +_cairo_xlib_screen_get_visual_info (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info, Visual *visual, cairo_xlib_visual_info_t **out); diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c index 18f974b3..2831acac 100644 --- a/src/cairo-xlib-screen.c +++ b/src/cairo-xlib-screen.c @@ -267,25 +267,18 @@ _cairo_xlib_screen_reference (cairo_xlib_screen_t *info) } void -_cairo_xlib_screen_close_display (cairo_xlib_screen_t *info) +_cairo_xlib_screen_close_display (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info) { cairo_xlib_visual_info_t **visuals; Display *dpy; cairo_atomic_int_t old; int i; - CAIRO_MUTEX_LOCK (info->mutex); + dpy = display->display; - dpy = _cairo_xlib_display_get_dpy (info->display); - -#if HAS_ATOMIC_OPS - do { - old = _cairo_atomic_int_get (&info->gc_depths); - } while (_cairo_atomic_int_cmpxchg (&info->gc_depths, old, 0) != old); -#else old = info->gc_depths; info->gc_depths = 0; -#endif for (i = 0; i < ARRAY_LENGTH (info->gc); i++) { if ((old >> (8*i)) & 0xff) @@ -296,28 +289,28 @@ _cairo_xlib_screen_close_display (cairo_xlib_screen_t *info) for (i = 0; i < _cairo_array_num_elements (&info->visuals); i++) _cairo_xlib_visual_info_destroy (dpy, visuals[i]); _cairo_array_truncate (&info->visuals, 0); - - CAIRO_MUTEX_UNLOCK (info->mutex); } void _cairo_xlib_screen_destroy (cairo_xlib_screen_t *info) { + cairo_xlib_display_t *display; + assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count)); if (! _cairo_reference_count_dec_and_test (&info->ref_count)) return; - _cairo_xlib_display_remove_screen (info->display, info); + if (! _cairo_xlib_display_acquire (info->device, &display)) { + _cairo_xlib_display_remove_screen (display, info); + _cairo_xlib_screen_close_display (display, info); - _cairo_xlib_screen_close_display (info); - - _cairo_xlib_display_destroy (info->display); + cairo_device_release (&display->base); + } + cairo_device_destroy (info->device); _cairo_array_fini (&info->visuals); - CAIRO_MUTEX_FINI (info->mutex); - free (info); } @@ -348,8 +341,7 @@ _cairo_xlib_screen_get (Display *dpy, } CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */ - CAIRO_MUTEX_INIT (info->mutex); - info->display = display; + info->device = &display->base; info->screen = screen; info->has_render = FALSE; info->has_font_options = FALSE; @@ -377,103 +369,19 @@ _cairo_xlib_screen_get (Display *dpy, return CAIRO_STATUS_SUCCESS; CLEANUP_DISPLAY: - _cairo_xlib_display_destroy (display); + cairo_device_destroy ((cairo_device_t *) display); return status; } -#if HAS_ATOMIC_OPS -GC -_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info, - int depth, - Drawable drawable) -{ - XGCValues gcv; - cairo_atomic_int_t old, new; - int i; - GC gc; - - do { - gc = NULL; - old = info->gc_depths; - if (old == 0) - break; - - if (((old >> 0) & 0xff) == depth) - i = 0; - else if (((old >> 8) & 0xff) == depth) - i = 1; - else if (((old >> 16) & 0xff) == depth) - i = 2; - else if (((old >> 24) & 0xff) == depth) - i = 3; - else - break; - - gc = info->gc[i]; - new = old & ~(0xff << (8*i)); - } while (_cairo_atomic_int_cmpxchg (&info->gc_depths, old, new) != old); - - if (likely (gc != NULL)) { - (void) _cairo_atomic_ptr_cmpxchg (&info->gc[i], gc, NULL); - return gc; - } - - gcv.graphics_exposures = False; - gcv.fill_style = FillTiled; - return XCreateGC (_cairo_xlib_display_get_dpy (info->display), - drawable, - GCGraphicsExposures | GCFillStyle, &gcv); -} - -void -_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info, - int depth, - GC gc) -{ - int i, old, new; - - do { - do { - i = -1; - old = info->gc_depths; - - if (((old >> 0) & 0xff) == 0) - i = 0; - else if (((old >> 8) & 0xff) == 0) - i = 1; - else if (((old >> 16) & 0xff) == 0) - i = 2; - else if (((old >> 24) & 0xff) == 0) - i = 3; - else - goto out; - - new = old | (depth << (8*i)); - } while (_cairo_atomic_ptr_cmpxchg (&info->gc[i], NULL, gc) != NULL); - } while (_cairo_atomic_int_cmpxchg (&info->gc_depths, old, new) != old); - - return; - -out: - if (unlikely (_cairo_xlib_display_queue_work (info->display, - (cairo_xlib_notify_func) XFreeGC, - gc, - NULL))) - { - /* leak the server side resource... */ - XFree ((char *) gc); - } -} -#else GC -_cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info, +_cairo_xlib_screen_get_gc (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info, int depth, Drawable drawable) { GC gc = NULL; int i; - CAIRO_MUTEX_LOCK (info->mutex); for (i = 0; i < ARRAY_LENGTH (info->gc); i++) { if (((info->gc_depths >> (8*i)) & 0xff) == depth) { info->gc_depths &= ~(0xff << (8*i)); @@ -481,14 +389,13 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info, break; } } - CAIRO_MUTEX_UNLOCK (info->mutex); if (gc == NULL) { XGCValues gcv; gcv.graphics_exposures = False; gcv.fill_style = FillTiled; - gc = XCreateGC (_cairo_xlib_display_get_dpy (info->display), + gc = XCreateGC (display->display, drawable, GCGraphicsExposures | GCFillStyle, &gcv); } @@ -497,13 +404,13 @@ _cairo_xlib_screen_get_gc (cairo_xlib_screen_t *info, } void -_cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info, +_cairo_xlib_screen_put_gc (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info, int depth, GC gc) { int i; - CAIRO_MUTEX_LOCK (info->mutex); for (i = 0; i < ARRAY_LENGTH (info->gc); i++) { if (((info->gc_depths >> (8*i)) & 0xff) == 0) break; @@ -515,7 +422,7 @@ _cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info, /* perform random substitution to ensure fair caching over depths */ i = rand () % ARRAY_LENGTH (info->gc); status = - _cairo_xlib_display_queue_work (info->display, + _cairo_xlib_display_queue_work (display, (cairo_xlib_notify_func) XFreeGC, info->gc[i], NULL); @@ -528,21 +435,18 @@ _cairo_xlib_screen_put_gc (cairo_xlib_screen_t *info, info->gc[i] = gc; info->gc_depths &= ~(0xff << (8*i)); info->gc_depths |= depth << (8*i); - CAIRO_MUTEX_UNLOCK (info->mutex); } -#endif cairo_status_t -_cairo_xlib_screen_get_visual_info (cairo_xlib_screen_t *info, +_cairo_xlib_screen_get_visual_info (cairo_xlib_display_t *display, + cairo_xlib_screen_t *info, Visual *visual, cairo_xlib_visual_info_t **out) { - Display *dpy = _cairo_xlib_display_get_dpy (info->display); cairo_xlib_visual_info_t **visuals, *ret = NULL; cairo_status_t status; int i, n_visuals; - CAIRO_MUTEX_LOCK (info->mutex); visuals = _cairo_array_index (&info->visuals, 0); n_visuals = _cairo_array_num_elements (&info->visuals); for (i = 0; i < n_visuals; i++) { @@ -551,28 +455,26 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_t *info, break; } } - CAIRO_MUTEX_UNLOCK (info->mutex); if (ret != NULL) { *out = ret; return CAIRO_STATUS_SUCCESS; } - status = _cairo_xlib_visual_info_create (dpy, + status = _cairo_xlib_visual_info_create (display->display, XScreenNumberOfScreen (info->screen), visual->visualid, &ret); if (unlikely (status)) return status; - CAIRO_MUTEX_LOCK (info->mutex); if (n_visuals != _cairo_array_num_elements (&info->visuals)) { /* check that another thread has not added our visual */ int new_visuals = _cairo_array_num_elements (&info->visuals); visuals = _cairo_array_index (&info->visuals, 0); for (i = n_visuals; i < new_visuals; i++) { if (visuals[i]->visualid == visual->visualid) { - _cairo_xlib_visual_info_destroy (dpy, ret); + _cairo_xlib_visual_info_destroy (display->display, ret); ret = visuals[i]; break; } @@ -581,10 +483,9 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_t *info, status = _cairo_array_append (&info->visuals, &ret); } else status = _cairo_array_append (&info->visuals, &ret); - CAIRO_MUTEX_UNLOCK (info->mutex); if (unlikely (status)) { - _cairo_xlib_visual_info_destroy (dpy, ret); + _cairo_xlib_visual_info_destroy (display->display, ret); return status; } @@ -595,21 +496,21 @@ _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_t *info, cairo_font_options_t * _cairo_xlib_screen_get_font_options (cairo_xlib_screen_t *info) { - if (info->has_font_options) - return &info->font_options; - - CAIRO_MUTEX_LOCK (info->mutex); if (! info->has_font_options) { _cairo_font_options_init_default (&info->font_options); if (info->screen != NULL) { - _cairo_xlib_init_screen_font_options (_cairo_xlib_display_get_dpy (info->display), - info); + cairo_xlib_display_t *display; + + if (! _cairo_xlib_display_acquire (info->device, &display)) { + _cairo_xlib_init_screen_font_options (display->display, + info); + cairo_device_release (&display->base); + } } info->has_font_options = TRUE; } - CAIRO_MUTEX_UNLOCK (info->mutex); return &info->font_options; } diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h index b30848d5..8309246f 100644 --- a/src/cairo-xlib-surface-private.h +++ b/src/cairo-xlib-surface-private.h @@ -44,8 +44,6 @@ typedef struct _cairo_xlib_surface cairo_xlib_surface_t; struct _cairo_xlib_surface { cairo_surface_t base; - Display *dpy; - cairo_xlib_display_t *display; cairo_xlib_screen_t *screen; cairo_xlib_hook_t close_display_hook; diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 51c0f836..f127a9c3 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -118,18 +118,6 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen, int height, int depth); -static cairo_status_t -_cairo_xlib_surface_get_gc (cairo_xlib_surface_t *surface, GC *gc); - -static void -_cairo_xlib_surface_put_gc (cairo_xlib_surface_t *surface, GC gc); - -static void -_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface); - -static void -_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface); - static cairo_bool_t _cairo_surface_is_xlib (cairo_surface_t *surface); @@ -285,6 +273,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src, cairo_xlib_surface_t *src = abstract_src; XRenderPictFormat *xrender_format; cairo_xlib_surface_t *surface; + cairo_xlib_display_t *display; Pixmap pix; if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) @@ -293,7 +282,8 @@ _cairo_xlib_surface_create_similar (void *abstract_src, if (! CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (src)) return NULL; - _cairo_xlib_display_notify (src->display); + if (_cairo_xlib_display_acquire (src->base.device, &display)) + return NULL; /* If we never found an XRenderFormat or if it isn't compatible * with the content being requested, then we fallback to just @@ -304,7 +294,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src, if ((xrender_format != NULL && _xrender_format_to_content (xrender_format) == content) || (xrender_format = - _cairo_xlib_display_get_xrender_format (src->display, + _cairo_xlib_display_get_xrender_format (display, _cairo_format_from_content (content)))) { Visual *visual; @@ -312,7 +302,7 @@ _cairo_xlib_surface_create_similar (void *abstract_src, /* We've got a compatible XRenderFormat now, which means the * similar surface will match the existing surface as closely in * visual/depth etc. as possible. */ - pix = XCreatePixmap (src->dpy, src->drawable, + pix = XCreatePixmap (display->display, src->drawable, width <= 0 ? 1 : width, height <= 0 ? 1 : height, xrender_format->depth); @@ -335,12 +325,14 @@ _cairo_xlib_surface_create_similar (void *abstract_src, /* No compatabile XRenderFormat, see if we can make an ordinary pixmap, * so that we can still accelerate blits with XCopyArea(). */ - if (content != CAIRO_CONTENT_COLOR) + if (content != CAIRO_CONTENT_COLOR) { + cairo_device_release (&display->base); return NULL; + } depth = DefaultDepthOfScreen (screen); - pix = XCreatePixmap (src->dpy, RootWindowOfScreen (screen), + pix = XCreatePixmap (display->display, RootWindowOfScreen (screen), width <= 0 ? 1 : width, height <= 0 ? 1 : height, depth); @@ -351,17 +343,21 @@ _cairo_xlib_surface_create_similar (void *abstract_src, width, height, depth); #else /* No compatabile XRenderFormat, just say no. */ + cairo_device_release (&display->base); return NULL; #endif } if (unlikely (surface->base.status)) { - XFreePixmap (src->dpy, pix); + XFreePixmap (display->display, pix); + cairo_device_release (&display->base); return &surface->base; } surface->owns_pixmap = TRUE; + cairo_device_release (&display->base); + return &surface->base; } @@ -369,10 +365,14 @@ static cairo_status_t _cairo_xlib_surface_finish (void *abstract_surface) { cairo_xlib_surface_t *surface = abstract_surface; - cairo_xlib_display_t *display = surface->display; - cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_status_t status; + cairo_xlib_display_t *display; + + X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable)); - X_DEBUG ((surface->dpy, "finish (drawable=%x)", (unsigned int) surface->drawable)); + status = _cairo_xlib_display_acquire (surface->base.device, &display); + if (unlikely (status)) + return status; if (surface->owns_pixmap) { cairo_status_t status2; @@ -400,20 +400,20 @@ _cairo_xlib_surface_finish (void *abstract_surface) status = status2; } else { if (surface->dst_picture != None) - XRenderFreePicture (surface->dpy, surface->dst_picture); + XRenderFreePicture (display->display, surface->dst_picture); if (surface->src_picture != None) - XRenderFreePicture (surface->dpy, surface->src_picture); + XRenderFreePicture (display->display, surface->src_picture); } if (surface->clip_rects != surface->embedded_clip_rects) free (surface->clip_rects); - if (surface->dpy != NULL) { - _cairo_xlib_remove_close_display_hook (surface->display, + if (display->display != NULL) + _cairo_xlib_remove_close_display_hook (display, &surface->close_display_hook); - surface->dpy = NULL; - } + + cairo_device_release (&display->base); _cairo_xlib_screen_destroy (surface->screen); @@ -422,6 +422,32 @@ _cairo_xlib_surface_finish (void *abstract_surface) return status; } +static cairo_status_t +_cairo_xlib_surface_get_gc (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface, + GC *gc) +{ + *gc = _cairo_xlib_screen_get_gc (display, + surface->screen, + surface->depth, + surface->drawable); + if (unlikely (*gc == NULL)) + return _cairo_error (CAIRO_STATUS_NO_MEMORY); + + return CAIRO_STATUS_SUCCESS; +} + +static void +_cairo_xlib_surface_put_gc (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface, + GC gc) +{ + _cairo_xlib_screen_put_gc (display, + surface->screen, + surface->depth, + gc); +} + static int _noop_error_handler (Display *display, XErrorEvent *event) @@ -708,6 +734,7 @@ _get_image_surface (cairo_xlib_surface_t *surface, cairo_rectangle_int_t extents; pixman_format_code_t pixman_format; cairo_format_masks_t xlib_masks; + cairo_xlib_display_t *display; extents.x = 0; extents.y = 0; @@ -721,6 +748,10 @@ _get_image_surface (cairo_xlib_surface_t *surface, } } + status = _cairo_xlib_display_acquire (surface->base.device, &display); + if (status) + return status; + if (image_rect) *image_rect = extents; @@ -732,7 +763,7 @@ _get_image_surface (cairo_xlib_surface_t *surface, old_handler = XSetErrorHandler (_noop_error_handler); - ximage = XGetImage (surface->dpy, + ximage = XGetImage (display->display, surface->drawable, extents.x, extents.y, extents.width, extents.height, @@ -762,33 +793,35 @@ _get_image_surface (cairo_xlib_surface_t *surface, Pixmap pixmap; GC gc; - status = _cairo_xlib_surface_get_gc (surface, &gc); + status = _cairo_xlib_surface_get_gc (display, surface, &gc); if (unlikely (status)) - return status; + goto BAIL; - pixmap = XCreatePixmap (surface->dpy, + pixmap = XCreatePixmap (display->display, surface->drawable, extents.width, extents.height, surface->depth); if (pixmap) { - XCopyArea (surface->dpy, surface->drawable, pixmap, gc, + XCopyArea (display->display, surface->drawable, pixmap, gc, extents.x, extents.y, extents.width, extents.height, 0, 0); - ximage = XGetImage (surface->dpy, + ximage = XGetImage (display->display, pixmap, 0, 0, extents.width, extents.height, AllPlanes, ZPixmap); - XFreePixmap (surface->dpy, pixmap); + XFreePixmap (display->display, pixmap); } - _cairo_xlib_surface_put_gc (surface, gc); + _cairo_xlib_surface_put_gc (display, surface, gc); - if (ximage == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (ximage == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto BAIL; + } } _swap_ximage_to_native (ximage); @@ -873,7 +906,8 @@ _get_image_surface (cairo_xlib_surface_t *surface, } else { format = CAIRO_FORMAT_RGB24; - status = _cairo_xlib_screen_get_visual_info (surface->screen, + status = _cairo_xlib_screen_get_visual_info (display, + surface->screen, surface->visual, &visual_info); if (unlikely (status)) @@ -919,7 +953,10 @@ _get_image_surface (cairo_xlib_surface_t *surface, } BAIL: - XDestroyImage (ximage); + if (ximage) + XDestroyImage (ximage); + + cairo_device_release (&display->base); if (unlikely (status)) { if (image) { @@ -932,7 +969,8 @@ _get_image_surface (cairo_xlib_surface_t *surface, } static void -_cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface) +_cairo_xlib_surface_ensure_src_picture (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface) { if (!surface->src_picture) { XRenderPictureAttributes pa; @@ -941,7 +979,7 @@ _cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface) pa.subwindow_mode = IncludeInferiors; mask |= CPSubwindowMode; - surface->src_picture = XRenderCreatePicture (surface->dpy, + surface->src_picture = XRenderCreatePicture (display->display, surface->drawable, surface->xrender_format, mask, &pa); @@ -949,17 +987,18 @@ _cairo_xlib_surface_ensure_src_picture (cairo_xlib_surface_t *surface) } static void -_cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface) +_cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface) { if (surface->clip_region != NULL) { - XRenderSetPictureClipRectangles (surface->dpy, surface->dst_picture, + XRenderSetPictureClipRectangles (display->display, surface->dst_picture, 0, 0, surface->clip_rects, surface->num_clip_rects); } else { XRenderPictureAttributes pa; pa.clip_mask = None; - XRenderChangePicture (surface->dpy, surface->dst_picture, + XRenderChangePicture (display->display, surface->dst_picture, CPClipMask, &pa); } @@ -967,37 +1006,18 @@ _cairo_xlib_surface_set_picture_clip_rects (cairo_xlib_surface_t *surface) } static void -_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_surface_t *surface) +_cairo_xlib_surface_ensure_dst_picture (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface) { if (!surface->dst_picture) { - surface->dst_picture = XRenderCreatePicture (surface->dpy, + surface->dst_picture = XRenderCreatePicture (display->display, surface->drawable, surface->xrender_format, 0, NULL); } if (surface->clip_dirty & CAIRO_XLIB_SURFACE_CLIP_DIRTY_PICTURE) - _cairo_xlib_surface_set_picture_clip_rects (surface); -} - -static cairo_status_t -_cairo_xlib_surface_get_gc (cairo_xlib_surface_t *surface, GC *gc) -{ - *gc = _cairo_xlib_screen_get_gc (surface->screen, - surface->depth, - surface->drawable); - if (unlikely (*gc == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); - - return CAIRO_STATUS_SUCCESS; -} - -static void -_cairo_xlib_surface_put_gc (cairo_xlib_surface_t *surface, GC gc) -{ - _cairo_xlib_screen_put_gc (surface->screen, - surface->depth, - gc); + _cairo_xlib_surface_set_picture_clip_rects (display, surface); } static cairo_status_t @@ -1010,6 +1030,7 @@ _draw_image_surface (cairo_xlib_surface_t *surface, int dst_x, int dst_y) { + cairo_xlib_display_t *display; XImage ximage; cairo_format_masks_t image_masks; int native_byte_order = _native_byte_order_lsb () ? LSBFirst : MSBFirst; @@ -1031,6 +1052,10 @@ _draw_image_surface (cairo_xlib_surface_t *surface, ximage.blue_mask = surface->b_mask; ximage.xoffset = 0; + status = _cairo_xlib_display_acquire (surface->base.device, &display); + if (unlikely (status)) + return status; + if (!_pixman_format_to_masks (image->pixman_format, &image_masks)) { pixman_format_code_t intermediate_format; @@ -1049,8 +1074,10 @@ _draw_image_surface (cairo_xlib_surface_t *surface, image->height, NULL, 0); - if (pixman_image == NULL) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (pixman_image == NULL) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto BAIL; + } pixman_image_composite32 (PIXMAN_OP_SRC, image->pixman_image, @@ -1109,8 +1136,10 @@ _draw_image_surface (cairo_xlib_surface_t *surface, ximage.bits_per_pixel); ximage.bytes_per_line = stride; ximage.data = _cairo_malloc_ab (stride, ximage.height); - if (unlikely (ximage.data == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (unlikely (ximage.data == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto BAIL; + } own_data = TRUE; @@ -1130,7 +1159,8 @@ _draw_image_surface (cairo_xlib_surface_t *surface, _characterize_field (surface->g_mask, &o_g_width, &o_g_shift); _characterize_field (surface->b_mask, &o_b_width, &o_b_shift); } else { - status = _cairo_xlib_screen_get_visual_info (surface->screen, + status = _cairo_xlib_screen_get_visual_info (display, + surface->screen, surface->visual, &visual_info); if (unlikely (status)) @@ -1201,17 +1231,20 @@ _draw_image_surface (cairo_xlib_surface_t *surface, } } - status = _cairo_xlib_surface_get_gc (surface, &gc); + status = _cairo_xlib_surface_get_gc (display, surface, &gc); if (unlikely (status)) goto BAIL; - XPutImage (surface->dpy, surface->drawable, gc, + XPutImage (display->display, surface->drawable, gc, &ximage, src_x, src_y, dst_x, dst_y, width, height); - _cairo_xlib_surface_put_gc (surface, gc); + _cairo_xlib_surface_put_gc (display, surface, gc); BAIL: + + cairo_device_release (&display->base); + if (own_data) free (ximage.data); if (pixman_image) @@ -1229,8 +1262,6 @@ _cairo_xlib_surface_acquire_source_image (void *abstract_surf cairo_image_surface_t *image; cairo_status_t status; - _cairo_xlib_display_notify (surface->display); - status = _get_image_surface (surface, NULL, &image, NULL); if (unlikely (status)) return status; @@ -1248,8 +1279,6 @@ _cairo_xlib_surface_snapshot (void *abstract_surface) cairo_image_surface_t *image; cairo_status_t status; - _cairo_xlib_display_notify (surface->display); - status = _get_image_surface (surface, NULL, &image, NULL); if (unlikely (status)) return _cairo_surface_create_in_error (status); @@ -1276,8 +1305,6 @@ _cairo_xlib_surface_acquire_dest_image (void *abstract_surfac cairo_image_surface_t *image; cairo_status_t status; - _cairo_xlib_display_notify (surface->display); - status = _get_image_surface (surface, interest_rect, &image, image_rect_out); if (unlikely (status)) return status; @@ -1333,8 +1360,6 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface, cairo_xlib_surface_t *clone; cairo_status_t status; - _cairo_xlib_display_notify (surface->display); - if (src->backend == surface->base.backend ) { cairo_xlib_surface_t *xlib_src = (cairo_xlib_surface_t *)src; @@ -1396,6 +1421,7 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac cairo_image_surface_t *image; cairo_xlib_surface_t *surface = NULL; cairo_status_t status = CAIRO_STATUS_SUCCESS; + cairo_xlib_display_t *display; int width = ARRAY_LENGTH (dither_pattern[0]); int height = ARRAY_LENGTH (dither_pattern); @@ -1412,10 +1438,15 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac if (unlikely (status)) goto BAIL; - pixmap = XCreatePixmap (other->dpy, + status = _cairo_xlib_display_acquire (other->base.device, &display); + if (unlikely (status)) + goto BAIL; + + pixmap = XCreatePixmap (display->display, other->drawable, width, height, other->depth); + cairo_device_release (&display->base); surface = (cairo_xlib_surface_t *) _cairo_xlib_surface_create_internal (other->screen, @@ -1445,12 +1476,16 @@ _cairo_xlib_surface_create_solid_pattern_surface (void *abstrac BAIL: cairo_surface_destroy (&image->base); - if (unlikely (status)) { - if (pixmap != None) - XFreePixmap (other->dpy, pixmap); - cairo_surface_destroy (&surface->base); + if (status) { + if (pixmap != None) { + if (!_cairo_xlib_display_acquire (other->base.device, &display)) { + XFreePixmap (display->display, pixmap); + cairo_device_release (&display->base); + } + } + cairo_surface_destroy (&surface->base); - return _cairo_surface_create_in_error (status); + return _cairo_surface_create_in_error (status); } surface->owns_pixmap = TRUE; @@ -1466,7 +1501,8 @@ _cairo_xlib_surface_can_repaint_solid_pattern_surface (void *abstract_surface, } static cairo_status_t -_cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface, +_cairo_xlib_surface_set_matrix (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface, cairo_matrix_t *matrix, double xc, double yc) @@ -1486,14 +1522,15 @@ _cairo_xlib_surface_set_matrix (cairo_xlib_surface_t *surface, if (! CAIRO_SURFACE_RENDER_HAS_PICTURE_TRANSFORM (surface)) return UNSUPPORTED ("XRender does not support picture transforms"); - XRenderSetPictureTransform (surface->dpy, surface->src_picture, &xtransform); + XRenderSetPictureTransform (display->display, surface->src_picture, &xtransform); surface->xtransform = xtransform; return CAIRO_STATUS_SUCCESS; } static cairo_status_t -_cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, +_cairo_xlib_surface_set_filter (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface, cairo_filter_t filter) { const char *render_filter; @@ -1535,7 +1572,7 @@ _cairo_xlib_surface_set_filter (cairo_xlib_surface_t *surface, break; } - XRenderSetPictureFilter (surface->dpy, surface->src_picture, + XRenderSetPictureFilter (display->display, surface->src_picture, (char *) render_filter, NULL, 0); surface->filter = filter; @@ -1601,7 +1638,8 @@ _cairo_xlib_surface_set_component_alpha (cairo_xlib_surface_t *surface, } static cairo_int_status_t -_cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, +_cairo_xlib_surface_set_attributes (cairo_xlib_display_t *display, + cairo_xlib_surface_t *surface, cairo_surface_attributes_t *attributes, double xc, double yc) @@ -1610,10 +1648,10 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, XRenderPictureAttributes pa; unsigned long mask = 0; - _cairo_xlib_surface_ensure_src_picture (surface); + _cairo_xlib_surface_ensure_src_picture (display, surface); - status = _cairo_xlib_surface_set_matrix (surface, &attributes->matrix, - xc, yc); + status = _cairo_xlib_surface_set_matrix (display, surface, + &attributes->matrix, xc, yc); if (unlikely (status)) return status; @@ -1628,12 +1666,12 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t *surface, if (unlikely (status)) return status; - status = _cairo_xlib_surface_set_filter (surface, attributes->filter); + status = _cairo_xlib_surface_set_filter (display, surface, attributes->filter); if (unlikely (status)) return status; if (mask) - XRenderChangePicture (surface->dpy, surface->src_picture, mask, &pa); + XRenderChangePicture (display->display, surface->src_picture, mask, &pa); return CAIRO_STATUS_SUCCESS; } @@ -1905,7 +1943,8 @@ _render_operator (cairo_operator_t op) } static cairo_int_status_t -_cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_surface_t *dst, +_cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_display_t *display, + cairo_xlib_surface_t *dst, const cairo_pattern_t *pattern, int x, int y, int width, int height, @@ -1967,7 +2006,7 @@ _cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_surface_t *dst, * XSync call here seems to avoid the issue so I'll keep it here * until it's solved. */ - XSync (dst->dpy, False); + XSync (display->display, False); #endif if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR) { @@ -2015,7 +2054,7 @@ _cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_surface_t *dst, grad.p2.y = _cairo_fixed_to_16_16 (linear->p2.y); } - picture = XRenderCreateLinearGradient (dst->dpy, &grad, + picture = XRenderCreateLinearGradient (display->display, &grad, stops, colors, gradient->n_stops); } else { @@ -2030,7 +2069,7 @@ _cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_surface_t *dst, grad.outer.y = _cairo_fixed_to_16_16 (radial->c2.y); grad.outer.radius = _cairo_fixed_to_16_16 (radial->r2); - picture = XRenderCreateRadialGradient (dst->dpy, &grad, + picture = XRenderCreateRadialGradient (display->display, &grad, stops, colors, gradient->n_stops); @@ -2043,7 +2082,7 @@ _cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_surface_t *dst, return _cairo_error (CAIRO_STATUS_NO_MEMORY); /* Wrap the remote Picture in an xlib surface. */ - format = _cairo_xlib_display_get_xrender_format (dst->display, + format = _cairo_xlib_display_get_xrender_format (display, CAIRO_FORMAT_ARGB32); surface = (cairo_xlib_surface_t *) @@ -2051,7 +2090,7 @@ _cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_surface_t *dst, NULL, format, 0, 0, 32); if (unlikely (surface->base.status)) { - XRenderFreePicture (dst->dpy, picture); + XRenderFreePicture (display->display, picture); return surface->base.status; } @@ -2084,9 +2123,10 @@ _cairo_xlib_surface_acquire_pattern_surface (cairo_xlib_surface_t *dst, } static cairo_int_status_t -_cairo_xlib_surface_acquire_pattern_surfaces (cairo_xlib_surface_t *dst, - const cairo_pattern_t *src, - const cairo_pattern_t *mask, +_cairo_xlib_surface_acquire_pattern_surfaces (cairo_xlib_display_t *display, + cairo_xlib_surface_t *dst, + const cairo_pattern_t *src, + const cairo_pattern_t *mask, int src_x, int src_y, int mask_x, @@ -2106,7 +2146,8 @@ _cairo_xlib_surface_acquire_pattern_surfaces (cairo_xlib_surface_t *dst, { cairo_int_status_t status; - status = _cairo_xlib_surface_acquire_pattern_surface (dst, src, + status = _cairo_xlib_surface_acquire_pattern_surface (display, + dst, src, src_x, src_y, width, height, src_out, @@ -2115,7 +2156,8 @@ _cairo_xlib_surface_acquire_pattern_surfaces (cairo_xlib_surface_t *dst, return status; if (mask) { - status = _cairo_xlib_surface_acquire_pattern_surface (dst, mask, + status = _cairo_xlib_surface_acquire_pattern_surface (display, + dst, mask, mask_x, mask_y, width, @@ -2166,6 +2208,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, cairo_xlib_surface_t *dst = abstract_dst; cairo_xlib_surface_t *src; cairo_xlib_surface_t *mask; + cairo_xlib_display_t *display; cairo_int_status_t status; cairo_rectangle_int_t src_extents; composite_operation_t operation; @@ -2182,7 +2225,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, if (operation == DO_UNSUPPORTED) return UNSUPPORTED ("unsupported operation"); - X_DEBUG ((dst->dpy, "composite (dst=%x)", (unsigned int) dst->drawable)); + X_DEBUG ((display->display, "composite (dst=%x)", (unsigned int) dst->drawable)); src_extents.x = src_x; src_extents.y = src_y; @@ -2194,10 +2237,12 @@ _cairo_xlib_surface_composite (cairo_operator_t op, ! _cairo_pattern_is_opaque (src_pattern, &src_extents)); - _cairo_xlib_display_notify (dst->display); + status = _cairo_xlib_display_acquire (dst-> base.device, &display); + if (unlikely (status)) + return status; status = - _cairo_xlib_surface_acquire_pattern_surfaces (dst, + _cairo_xlib_surface_acquire_pattern_surfaces (display, dst, src_pattern, mask_pattern, src_x, src_y, mask_x, mask_y, @@ -2205,7 +2250,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, &src, &mask, &src_attr, &mask_attr); if (unlikely (status)) - return status; + goto BAIL0; /* check for fallback surfaces that we cannot handle ... */ assert (_cairo_surface_is_xlib (&src->base)); @@ -2226,7 +2271,8 @@ _cairo_xlib_surface_composite (cairo_operator_t op, switch (operation) { case DO_RENDER: - status = _cairo_xlib_surface_set_attributes (src, &src_attr, + status = _cairo_xlib_surface_set_attributes (display, + src, &src_attr, dst_x + width / 2., dst_y + height / 2.); if (unlikely (status)) @@ -2236,15 +2282,16 @@ _cairo_xlib_surface_composite (cairo_operator_t op, if (unlikely (status)) goto BAIL; - _cairo_xlib_surface_ensure_dst_picture (dst); + _cairo_xlib_surface_ensure_dst_picture (display, dst); if (mask) { - status = _cairo_xlib_surface_set_attributes (mask, &mask_attr, + status = _cairo_xlib_surface_set_attributes (display, + mask, &mask_attr, dst_x + width / 2., dst_y + height/ 2.); if (unlikely (status)) goto BAIL; - XRenderComposite (dst->dpy, + XRenderComposite (display->display, _render_operator (op), src->src_picture, mask->src_picture, @@ -2256,7 +2303,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, dst_x, dst_y, width, height); } else { - XRenderComposite (dst->dpy, + XRenderComposite (display->display, _render_operator (op), src->src_picture, 0, @@ -2271,7 +2318,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, break; case DO_XCOPYAREA: - status = _cairo_xlib_surface_get_gc (dst, &gc); + status = _cairo_xlib_surface_get_gc (display, dst, &gc); if (unlikely (status)) goto BAIL; @@ -2281,7 +2328,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, assert (is_integer_translation); if (clip_region == NULL) { - XCopyArea (dst->dpy, src->drawable, dst->drawable, gc, + XCopyArea (display->display, src->drawable, dst->drawable, gc, src_x + src_attr.x_offset + itx, src_y + src_attr.y_offset + ity, width, height, @@ -2297,14 +2344,14 @@ _cairo_xlib_surface_composite (cairo_operator_t op, cairo_rectangle_int_t rect; cairo_region_get_rectangle (clip_region, n, &rect); - XCopyArea (dst->dpy, src->drawable, dst->drawable, gc, + XCopyArea (display->display, src->drawable, dst->drawable, gc, rect.x + src_x, rect.y + src_y, rect.width, rect.height, rect.x, rect.y); } } - _cairo_xlib_surface_put_gc (dst, gc); + _cairo_xlib_surface_put_gc (display, dst, gc); break; case DO_XTILE: @@ -2316,7 +2363,7 @@ _cairo_xlib_surface_composite (cairo_operator_t op, * _recategorize_composite_operation. */ - status = _cairo_xlib_surface_get_gc (dst, &gc); + status = _cairo_xlib_surface_get_gc (display, dst, &gc); if (unlikely (status)) goto BAIL; @@ -2325,12 +2372,12 @@ _cairo_xlib_surface_composite (cairo_operator_t op, /* This is a pre-condition for DO_XTILE. */ assert (is_integer_translation); - XSetTSOrigin (dst->dpy, gc, + XSetTSOrigin (display->display, gc, - (itx + src_attr.x_offset), - (ity + src_attr.y_offset)); - XSetTile (dst->dpy, gc, src->drawable); + XSetTile (display->display, gc, src->drawable); if (clip_region == NULL) { - XFillRectangle (dst->dpy, dst->drawable, gc, + XFillRectangle (display->display, dst->drawable, gc, dst_x, dst_y, width, height); } else { int n, num_rects; @@ -2340,12 +2387,12 @@ _cairo_xlib_surface_composite (cairo_operator_t op, cairo_rectangle_int_t rect; cairo_region_get_rectangle (clip_region, n, &rect); - XFillRectangle (dst->dpy, dst->drawable, gc, + XFillRectangle (display->display, dst->drawable, gc, rect.x, rect.y, rect.width, rect.height); } } - _cairo_xlib_surface_put_gc (dst, gc); + _cairo_xlib_surface_put_gc (display, dst, gc); break; case DO_UNSUPPORTED: @@ -2370,6 +2417,9 @@ _cairo_xlib_surface_composite (cairo_operator_t op, _cairo_pattern_release_surface (src_pattern, &src->base, &src_attr); + BAIL0: + cairo_device_release (&display->base); + return status; } @@ -2384,16 +2434,21 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface, cairo_solid_pattern_t solid; cairo_surface_t *solid_surface = NULL; cairo_surface_attributes_t attrs; + cairo_xlib_display_t *display; GC gc; int i; _cairo_pattern_init_solid (&solid, color, CAIRO_CONTENT_COLOR); - status = _cairo_xlib_surface_get_gc (surface, &gc); + status = _cairo_xlib_display_acquire (surface->base.device, &display); + if (unlikely (status)) + return status; + + status = _cairo_xlib_surface_get_gc (display, surface, &gc); if (unlikely (status)) return status; - X_DEBUG ((surface->dpy, "solid_fill_rectangles (dst=%x)", (unsigned int) surface->drawable)); + X_DEBUG ((display->display, "solid_fill_rectangles (dst=%x)", (unsigned int) surface->drawable)); status = _cairo_pattern_acquire_surface (&solid.base, &surface->base, 0, 0, @@ -2403,27 +2458,30 @@ _cairo_xlib_surface_solid_fill_rectangles (cairo_xlib_surface_t *surface, &solid_surface, &attrs); if (unlikely (status)) { - _cairo_xlib_surface_put_gc (surface, gc); + _cairo_xlib_surface_put_gc (display, surface, gc); + cairo_device_release (&display->base); return status; } assert (_cairo_surface_is_xlib (solid_surface)); - XSetTSOrigin (surface->dpy, gc, + XSetTSOrigin (display->display, gc, - (surface->base.device_transform.x0 + attrs.x_offset), - (surface->base.device_transform.y0 + attrs.y_offset)); - XSetTile (surface->dpy, gc, + XSetTile (display->display, gc, ((cairo_xlib_surface_t *) solid_surface)->drawable); for (i = 0; i < num_rects; i++) { - XFillRectangle (surface->dpy, surface->drawable, gc, + XFillRectangle (display->display, surface->drawable, gc, rects[i].x, rects[i].y, rects[i].width, rects[i].height); } - _cairo_xlib_surface_put_gc (surface, gc); + _cairo_xlib_surface_put_gc (display, surface, gc); _cairo_pattern_release_surface (&solid.base, solid_surface, &attrs); + + cairo_device_release (&display->base); return CAIRO_STATUS_SUCCESS; } @@ -2436,12 +2494,11 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, int num_rects) { cairo_xlib_surface_t *surface = abstract_surface; + cairo_xlib_display_t *display; XRenderColor render_color; cairo_status_t status; int i; - _cairo_xlib_display_notify (surface->display); - if (!CAIRO_SURFACE_RENDER_SUPPORTS_OPERATOR (surface, op)) return CAIRO_INT_STATUS_UNSUPPORTED; @@ -2457,7 +2514,11 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, return UNSUPPORTED ("no support for FillRectangles with this op"); } - X_DEBUG ((surface->dpy, "fill_rectangles (dst=%x)", (unsigned int) surface->drawable)); + status = _cairo_xlib_display_acquire (surface->base.device, &display); + if (unlikely (status)) + return status; + + X_DEBUG ((display->display, "fill_rectangles (dst=%x)", (unsigned int) surface->drawable)); render_color.red = color->red_short; render_color.green = color->green_short; @@ -2467,12 +2528,12 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, status = _cairo_xlib_surface_set_clip_region (surface, NULL); assert (status == CAIRO_STATUS_SUCCESS); - _cairo_xlib_surface_ensure_dst_picture (surface); + _cairo_xlib_surface_ensure_dst_picture (display, surface); if (num_rects == 1) { /* Take advantage of the protocol compaction that libXrender performs * to amalgamate sequences of XRenderFillRectangle(). */ - XRenderFillRectangle (surface->dpy, + XRenderFillRectangle (display->display, _render_operator (op), surface->dst_picture, &render_color, @@ -2486,8 +2547,10 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, if (num_rects > ARRAY_LENGTH (static_xrects)) { xrects = _cairo_malloc_ab (num_rects, sizeof (XRectangle)); - if (unlikely (xrects == NULL)) - return _cairo_error (CAIRO_STATUS_NO_MEMORY); + if (unlikely (xrects == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto BAIL; + } } for (i = 0; i < num_rects; i++) { @@ -2497,7 +2560,7 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, xrects[i].height = rects[i].height; } - XRenderFillRectangles (surface->dpy, + XRenderFillRectangles (display->display, _render_operator (op), surface->dst_picture, &render_color, xrects, num_rects); @@ -2506,7 +2569,9 @@ _cairo_xlib_surface_fill_rectangles (void *abstract_surface, free (xrects); } - return CAIRO_STATUS_SUCCESS; +BAIL: + cairo_device_release (&display->base); + return status; } #define CAIRO_FIXED_16_16_MIN -32768 @@ -2564,6 +2629,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, cairo_surface_attributes_t attributes; cairo_xlib_surface_t *dst = abstract_dst; cairo_xlib_surface_t *src; + cairo_xlib_display_t *display; cairo_int_status_t status; composite_operation_t operation; int render_reference_x, render_reference_y; @@ -2573,8 +2639,6 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, XTrapezoid *xtraps = xtraps_stack; int i; - _cairo_xlib_display_notify (dst->display); - if (! CAIRO_SURFACE_RENDER_HAS_TRAPEZOIDS (dst)) return UNSUPPORTED ("XRender does not support CompositeTrapezoids"); @@ -2582,15 +2646,20 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, if (operation == DO_UNSUPPORTED) return UNSUPPORTED ("unsupported operation"); - X_DEBUG ((dst->dpy, "composite_trapezoids (dst=%x)", (unsigned int) dst->drawable)); + status = _cairo_xlib_display_acquire (dst->base.device, &display); + if (unlikely (status)) + return status; + + X_DEBUG ((display->display, "composite_trapezoids (dst=%x)", (unsigned int) dst->drawable)); - status = _cairo_xlib_surface_acquire_pattern_surface (dst, + status = _cairo_xlib_surface_acquire_pattern_surface (display, + dst, pattern, src_x, src_y, width, height, &src, &attributes); if (unlikely (status)) - return status; + goto BAIL0; operation = _recategorize_composite_operation (dst, op, src, &attributes, TRUE); @@ -2602,7 +2671,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, switch (antialias) { case CAIRO_ANTIALIAS_NONE: pict_format = - _cairo_xlib_display_get_xrender_format (dst->display, + _cairo_xlib_display_get_xrender_format (display, CAIRO_FORMAT_A1); break; case CAIRO_ANTIALIAS_GRAY: @@ -2610,7 +2679,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, case CAIRO_ANTIALIAS_DEFAULT: default: pict_format = - _cairo_xlib_display_get_xrender_format (dst->display, + _cairo_xlib_display_get_xrender_format (display, CAIRO_FORMAT_A8); break; } @@ -2619,9 +2688,10 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, if (unlikely (status)) goto BAIL; - _cairo_xlib_surface_ensure_dst_picture (dst); + _cairo_xlib_surface_ensure_dst_picture (display, dst); - status = _cairo_xlib_surface_set_attributes (src, &attributes, + status = _cairo_xlib_surface_set_attributes (display, + src, &attributes, dst_x + width / 2., dst_y + height / 2.); if (unlikely (status)) @@ -2684,7 +2754,7 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, render_src_x = src_x + render_reference_x - dst_x; render_src_y = src_y + render_reference_y - dst_y; - XRenderCompositeTrapezoids (dst->dpy, + XRenderCompositeTrapezoids (display->display, _render_operator (op), src->src_picture, dst->dst_picture, pict_format, @@ -2723,6 +2793,8 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t op, BAIL: _cairo_pattern_release_surface (pattern, &src->base, &attributes); + BAIL0: + cairo_device_release (&display->base); return status; } @@ -2766,22 +2838,27 @@ _cairo_xlib_surface_is_similar (void *surface_a, cairo_xlib_surface_t *a = surface_a; cairo_xlib_surface_t *b = surface_b; XRenderPictFormat *xrender_format = b->xrender_format; + cairo_xlib_display_t *display; if (! _cairo_xlib_surface_same_screen (a, b)) return FALSE; + if (_cairo_xlib_display_acquire (b->base.device, &display)) + return FALSE; + /* now inspect the content to check that a is similar to b */ if (xrender_format == NULL && b->visual != NULL) - xrender_format = XRenderFindVisualFormat (b->dpy, b->visual); + xrender_format = XRenderFindVisualFormat (display->display, b->visual); if (xrender_format == NULL || _xrender_format_to_content (xrender_format) != content) { xrender_format = _cairo_xlib_display_get_xrender_format ( - b->display, + display, _cairo_format_from_content (content)); } + cairo_device_release (&display->base); return a->xrender_format == xrender_format; } @@ -2848,8 +2925,7 @@ _cairo_xlib_surface_detach_display (cairo_xlib_display_t *display, void *data) close_display_hook); Display *dpy; - dpy = surface->dpy; - surface->dpy = NULL; + dpy = display->display; X_DEBUG ((dpy, "detach (drawable=%x)", (unsigned int) surface->drawable)); @@ -2880,7 +2956,9 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen, int depth) { cairo_xlib_surface_t *surface; - + cairo_xlib_display_t *display; + cairo_status_t status; + CAIRO_MUTEX_INITIALIZE (); if (depth == 0) { @@ -2923,23 +3001,22 @@ found: if (unlikely (surface == NULL)) return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); - surface->dpy = _cairo_xlib_display_get_dpy (screen->display); - - /* initialize and hook into the CloseDisplay callback */ - surface->close_display_hook.func = _cairo_xlib_surface_detach_display; - _cairo_xlib_add_close_display_hook (screen->display, - &surface->close_display_hook); + status = _cairo_xlib_display_acquire (screen->device, &display); + if (unlikely (status)) { + free (surface); + return _cairo_surface_create_in_error (_cairo_error (status)); + } - _cairo_xlib_display_get_xrender_version (screen->display, + _cairo_xlib_display_get_xrender_version (display, &surface->render_major, &surface->render_minor); if (CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (surface)) { if (!xrender_format) { if (visual) { - xrender_format = XRenderFindVisualFormat (surface->dpy, visual); + xrender_format = XRenderFindVisualFormat (display->display, visual); } else if (depth == 1) { xrender_format = - _cairo_xlib_display_get_xrender_format (screen->display, + _cairo_xlib_display_get_xrender_format (display, CAIRO_FORMAT_A1); } } @@ -2949,13 +3026,19 @@ found: surface->render_minor = -1; } + /* initialize and hook into the CloseDisplay callback */ + surface->close_display_hook.func = _cairo_xlib_surface_detach_display; + _cairo_xlib_add_close_display_hook (display, + &surface->close_display_hook); + + cairo_device_release (&display->base); + _cairo_surface_init (&surface->base, &cairo_xlib_surface_backend, - NULL, /* device */ + screen->device, _xrender_format_to_content (xrender_format)); surface->screen = _cairo_xlib_screen_reference (screen); - surface->display = screen->display; surface->drawable = drawable; surface->owns_pixmap = FALSE; @@ -2963,17 +3046,17 @@ found: surface->width = width; surface->height = height; - surface->buggy_repeat = ! _cairo_xlib_display_has_repeat (surface->display); + surface->buggy_repeat = ! _cairo_xlib_display_has_repeat (screen->device); if (! CAIRO_SURFACE_RENDER_HAS_FILL_RECTANGLES (surface)) { /* so we can use the XTile fallback */ surface->buggy_repeat = TRUE; } - surface->buggy_pad_reflect = ! _cairo_xlib_display_has_reflect (surface->display); + surface->buggy_pad_reflect = ! _cairo_xlib_display_has_reflect (screen->device); if (! CAIRO_SURFACE_RENDER_HAS_EXTENDED_REPEAT (surface)) surface->buggy_pad_reflect = TRUE; - surface->buggy_gradients = ! _cairo_xlib_display_has_gradients (surface->display); + surface->buggy_gradients = ! _cairo_xlib_display_has_gradients (screen->device); if (! CAIRO_SURFACE_RENDER_HAS_GRADIENTS (surface)) surface->buggy_gradients = TRUE; @@ -3323,11 +3406,17 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, return; if (surface->drawable != drawable) { - X_DEBUG ((surface->dpy, "set_drawable (drawable=%x)", (unsigned int) drawable)); + cairo_xlib_display_t *display; + + status = _cairo_xlib_display_acquire (surface->base.device, &display); + if (unlikely (status)) + return; + + X_DEBUG ((display->display, "set_drawable (drawable=%x)", (unsigned int) drawable)); if (surface->dst_picture != None) { status = _cairo_xlib_display_queue_resource ( - surface->display, + display, XRenderFreePicture, surface->dst_picture); if (unlikely (status)) { @@ -3340,7 +3429,7 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, if (surface->src_picture != None) { status = _cairo_xlib_display_queue_resource ( - surface->display, + display, XRenderFreePicture, surface->src_picture); if (unlikely (status)) { @@ -3351,6 +3440,8 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, surface->src_picture = None; } + cairo_device_release (&display->base); + surface->drawable = drawable; } surface->width = width; @@ -3370,14 +3461,12 @@ cairo_xlib_surface_set_drawable (cairo_surface_t *abstract_surface, Display * cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface) { - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - if (! _cairo_surface_is_xlib (abstract_surface)) { _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return NULL; } - return surface->dpy; + return ((cairo_xlib_display_t *) abstract_surface->device)->display; } /** @@ -3541,7 +3630,7 @@ typedef struct _cairo_xlib_font_glyphset_info { typedef struct _cairo_xlib_surface_font_private { cairo_scaled_font_t *scaled_font; cairo_xlib_hook_t close_display_hook; - cairo_xlib_display_t *display; + cairo_device_t *device; cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS]; } cairo_xlib_surface_font_private_t; @@ -3566,32 +3655,29 @@ _cairo_xlib_surface_remove_scaled_font (cairo_xlib_display_t *display, CAIRO_MUTEX_UNLOCK (scaled_font->mutex); if (font_private != NULL) { - Display *dpy; int i; - dpy = _cairo_xlib_display_get_dpy (display); for (i = 0; i < NUM_GLYPHSETS; i++) { cairo_xlib_font_glyphset_info_t *glyphset_info; glyphset_info = &font_private->glyphset_info[i]; if (glyphset_info->glyphset) - XRenderFreeGlyphSet (dpy, glyphset_info->glyphset); + XRenderFreeGlyphSet (display->display, glyphset_info->glyphset); if (glyphset_info->pending_free_glyphs != NULL) free (glyphset_info->pending_free_glyphs); } - _cairo_xlib_display_destroy (font_private->display); + cairo_device_destroy (font_private->device); free (font_private); } } static cairo_status_t -_cairo_xlib_surface_font_init (Display *dpy, +_cairo_xlib_surface_font_init (cairo_xlib_display_t *display, cairo_scaled_font_t *scaled_font) { cairo_xlib_surface_font_private_t *font_private; - cairo_status_t status; int i; font_private = malloc (sizeof (cairo_xlib_surface_font_private_t)); @@ -3599,16 +3685,12 @@ _cairo_xlib_surface_font_init (Display *dpy, return _cairo_error (CAIRO_STATUS_NO_MEMORY); font_private->scaled_font = scaled_font; - status = _cairo_xlib_display_get (dpy, &font_private->display); - if (unlikely (status)) { - free (font_private); - return status; - } + font_private->device = cairo_device_reference (&display->base); /* initialize and hook into the CloseDisplay callback */ font_private->close_display_hook.func = _cairo_xlib_surface_remove_scaled_font; - _cairo_xlib_add_close_display_hook (font_private->display, + _cairo_xlib_add_close_display_hook (display, &font_private->close_display_hook); @@ -3635,13 +3717,17 @@ static void _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) { cairo_xlib_surface_font_private_t *font_private; + cairo_status_t status; font_private = scaled_font->surface_private; if (font_private != NULL) { cairo_xlib_display_t *display; int i; - display = font_private->display; + status = _cairo_xlib_display_acquire (font_private->device, &display); + if (status) + goto BAIL; + _cairo_xlib_remove_close_display_hook (display, &font_private->close_display_hook); @@ -3654,8 +3740,6 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) free (glyphset_info->pending_free_glyphs); if (glyphset_info->glyphset) { - cairo_status_t status; - status = _cairo_xlib_display_queue_resource (display, XRenderFreeGlyphSet, glyphset_info->glyphset); @@ -3663,7 +3747,9 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font) } } - _cairo_xlib_display_destroy (display); + cairo_device_release (&display->base); +BAIL: + cairo_device_destroy (&display->base); free (font_private); } } @@ -3711,10 +3797,16 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph, if (to_free != NULL && to_free->glyph_count == ARRAY_LENGTH (to_free->glyph_indices)) { - status = _cairo_xlib_display_queue_work (font_private->display, - (cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs, - to_free, - free); + cairo_xlib_display_t *display; + + status = _cairo_xlib_display_acquire (font_private->device, &display); + if (status == CAIRO_STATUS_SUCCESS) { + status = _cairo_xlib_display_queue_work (display, + (cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs, + to_free, + free); + cairo_device_release (&display->base); + } /* XXX cannot propagate failure */ if (unlikely (status)) free (to_free); @@ -3771,13 +3863,18 @@ _cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scale font_private = scaled_font->surface_private; glyphset_info = &font_private->glyphset_info[glyphset_index]; if (glyphset_info->glyphset == None) { - cairo_xlib_display_t *display = font_private->display; + cairo_xlib_display_t *display; + + if (_cairo_xlib_display_acquire (font_private->device, &display)) + return NULL; glyphset_info->xrender_format = _cairo_xlib_display_get_xrender_format (display, glyphset_info->format); - glyphset_info->glyphset = XRenderCreateGlyphSet (_cairo_xlib_display_get_dpy (display), + glyphset_info->glyphset = XRenderCreateGlyphSet (display->display, glyphset_info->xrender_format); + + cairo_device_release (&display->base); } return glyphset_info; @@ -3843,7 +3940,7 @@ _cairo_xlib_scaled_font_get_glyphset_info_for_pending_free_glyph ( } static cairo_status_t -_cairo_xlib_surface_add_glyph (Display *dpy, +_cairo_xlib_surface_add_glyph (cairo_xlib_display_t *display, cairo_scaled_font_t *scaled_font, cairo_scaled_glyph_t **pscaled_glyph) { @@ -3882,7 +3979,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, } if (scaled_font->surface_private == NULL) { - status = _cairo_xlib_surface_font_init (dpy, scaled_font); + status = _cairo_xlib_surface_font_init (display, scaled_font); if (unlikely (status)) return status; } @@ -3893,7 +3990,8 @@ _cairo_xlib_surface_add_glyph (Display *dpy, /* XRenderAddGlyph does not handle a glyph surface larger than the extended maximum XRequest size. */ { int len = cairo_format_stride_for_width (glyphset_info->format, glyph_surface->width) * glyph_surface->height; - int max_request_size = (XExtendedMaxRequestSize (dpy) ? XExtendedMaxRequestSize (dpy) : XMaxRequestSize (dpy)) * 4 - + int max_request_size = (XExtendedMaxRequestSize (display->display) ? XExtendedMaxRequestSize (display->display) + : XMaxRequestSize (display->display)) * 4 - sz_xRenderAddGlyphsReq - sz_xGlyphInfo - 8; @@ -3962,7 +4060,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, switch (_cairo_xlib_get_glyphset_index_for_format (scaled_glyph->surface->format)) { case GLYPHSET_INDEX_A1: /* local bitmaps are always stored with bit == byte */ - if (_native_byte_order_lsb() != (BitmapBitOrder (dpy) == LSBFirst)) { + if (_native_byte_order_lsb() != (BitmapBitOrder (display->display) == LSBFirst)) { int c = glyph_surface->stride * glyph_surface->height; unsigned char *d; unsigned char *new, *n; @@ -3987,7 +4085,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, case GLYPHSET_INDEX_A8: break; case GLYPHSET_INDEX_ARGB32: - if (_native_byte_order_lsb() != (ImageByteOrder (dpy) == LSBFirst)) { + if (_native_byte_order_lsb() != (ImageByteOrder (display->display) == LSBFirst)) { unsigned int c = glyph_surface->stride * glyph_surface->height / 4; const uint32_t *d; uint32_t *new, *n; @@ -4012,7 +4110,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy, } /* XXX assume X server wants pixman padding. Xft assumes this as well */ - XRenderAddGlyphs (dpy, glyphset_info->glyphset, + XRenderAddGlyphs (display->display, glyphset_info->glyphset, &glyph_index, &glyph_info, 1, (char *) data, glyph_surface->stride * glyph_surface->height); @@ -4079,7 +4177,8 @@ COMPILE_TIME_ASSERT (sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t)); (((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y) static cairo_status_t -_emit_glyphs_chunk (cairo_xlib_surface_t *dst, +_emit_glyphs_chunk (cairo_xlib_display_t *display, + cairo_xlib_surface_t *dst, cairo_xlib_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, @@ -4178,7 +4277,7 @@ _emit_glyphs_chunk (cairo_xlib_surface_t *dst, * expected number of xGlyphElts. */ assert (nelt == num_elts); - composite_text_func (dst->dpy, + composite_text_func (display->display, _render_operator (op), src->src_picture, dst->dst_picture, @@ -4200,7 +4299,8 @@ _emit_glyphs_chunk (cairo_xlib_surface_t *dst, #define _cairo_sz_xGlyphElt (sz_xGlyphElt + 4) static cairo_status_t -_cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, +_cairo_xlib_surface_emit_glyphs (cairo_xlib_display_t *display, + cairo_xlib_surface_t *dst, cairo_xlib_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font, @@ -4220,14 +4320,13 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, int num_elts = 0; int num_out_glyphs = 0; - int max_request_size = XMaxRequestSize (dst->dpy) * 4 + int max_request_size = XMaxRequestSize (display->display) * 4 - MAX (sz_xRenderCompositeGlyphs8Req, MAX(sz_xRenderCompositeGlyphs16Req, sz_xRenderCompositeGlyphs32Req)); int request_size = 0; - _cairo_xlib_surface_ensure_dst_picture (dst); - _cairo_xlib_display_notify (dst->display); + _cairo_xlib_surface_ensure_dst_picture (display, dst); for (i = 0; i < num_glyphs; i++) { int this_x, this_y; @@ -4267,7 +4366,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, /* Send unsent glyphs to the server */ if (_cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph) == NULL) { - status = _cairo_xlib_surface_add_glyph (dst->dpy, + status = _cairo_xlib_surface_add_glyph (display, scaled_font, &scaled_glyph); if (unlikely (status)) { @@ -4314,7 +4413,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, */ if (request_size + width > max_request_size - _cairo_sz_xGlyphElt || (this_glyphset_info != glyphset_info)) { - status = _emit_glyphs_chunk (dst, glyphs, i, + status = _emit_glyphs_chunk (display, dst, glyphs, i, scaled_font, op, src, attributes, num_elts, old_width, glyphset_info); if (unlikely (status)) @@ -4357,7 +4456,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst, } if (num_elts) { - status = _emit_glyphs_chunk (dst, glyphs, i, + status = _emit_glyphs_chunk (display, dst, glyphs, i, scaled_font, op, src, attributes, num_elts, width, glyphset_info); } @@ -4378,7 +4477,7 @@ _cairo_xlib_surface_owns_font (cairo_xlib_surface_t *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->display != dst->display)) + (font_private != NULL && font_private->device != dst->base.device)) { return FALSE; } @@ -4398,11 +4497,11 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, { cairo_int_status_t status = CAIRO_STATUS_SUCCESS; cairo_xlib_surface_t *dst = (cairo_xlib_surface_t*) abstract_dst; - composite_operation_t operation; cairo_surface_attributes_t attributes; cairo_xlib_surface_t *src = NULL; cairo_region_t *clip_region = NULL; + cairo_xlib_display_t *display; if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE_TEXT (dst)) return UNSUPPORTED ("XRender does not support CompositeText"); @@ -4442,7 +4541,11 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, if (! _cairo_xlib_surface_owns_font (dst, scaled_font)) return UNSUPPORTED ("unowned font"); - X_DEBUG ((dst->dpy, "show_glyphs (dst=%x)", (unsigned int) dst->drawable)); + status = _cairo_xlib_display_acquire (dst->base.device, &display); + if (unlikely (status)) + return status; + + X_DEBUG ((display->display, "show_glyphs (dst=%x)", (unsigned int) dst->drawable)); if (clip_region != NULL && cairo_region_num_rectangles (clip_region) == 1) @@ -4469,7 +4572,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, status = _cairo_xlib_surface_set_clip_region (dst, clip_region); if (unlikely (status)) - return status; + goto BAIL0; /* After passing all those tests, we're now committed to rendering * these glyphs or to fail trying. We first upload any glyphs to @@ -4514,7 +4617,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, } } - status = _cairo_xlib_surface_acquire_pattern_surface (dst, src_pattern, + status = _cairo_xlib_surface_acquire_pattern_surface (display, + dst, src_pattern, glyph_extents.x, glyph_extents.y, glyph_extents.width, @@ -4531,13 +4635,14 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, goto BAIL1; } - status = _cairo_xlib_surface_set_attributes (src, &attributes, 0, 0); + status = _cairo_xlib_surface_set_attributes (display, src, &attributes, 0, 0); if (unlikely (status)) goto BAIL1; _cairo_scaled_font_freeze_cache (scaled_font); if (_cairo_xlib_surface_owns_font (dst, scaled_font)) { - status = _cairo_xlib_surface_emit_glyphs (dst, + status = _cairo_xlib_surface_emit_glyphs (display, + dst, (cairo_xlib_glyph_t *) glyphs, num_glyphs, scaled_font, @@ -4554,7 +4659,7 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, if (src) _cairo_pattern_release_surface (src_pattern, &src->base, &attributes); BAIL0: - _cairo_xlib_display_notify (dst->display); + cairo_device_release (&display->base); return status; } |