diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-08-14 13:47:14 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-08-14 13:47:43 +0100 |
commit | 84a3b6e2d0b8103cdc17558b502ecfc4c99b98a3 (patch) | |
tree | 3b20ebb9adcbfcf97fba4423966cb5df320a9499 | |
parent | 2c885a275349c65ec831738ed917ecd16fdd8c65 (diff) |
xlib: Mark surfaces as finished when the Display is finished/destroyed/closed.
Fixes xlib-surface-source with the recording-surface
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/cairo-surface-snapshot.c | 5 | ||||
-rw-r--r-- | src/cairo-xlib-display.c | 107 | ||||
-rw-r--r-- | src/cairo-xlib-private.h | 2 | ||||
-rw-r--r-- | src/cairo-xlib-screen.c | 10 | ||||
-rw-r--r-- | src/cairo-xlib-surface-private.h | 1 | ||||
-rw-r--r-- | src/cairo-xlib-surface.c | 4 |
6 files changed, 76 insertions, 53 deletions
diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c index c499e0b4..16153e21 100644 --- a/src/cairo-surface-snapshot.c +++ b/src/cairo-surface-snapshot.c @@ -145,7 +145,10 @@ _cairo_surface_snapshot_copy_on_write (cairo_surface_t *surface) goto done; } - /* XXX copy to a similar surface, leave acquisition till later? */ + /* XXX copy to a similar surface, leave acquisition till later? + * We should probably leave such decisions to the backend in case we + * rely upon devices/connections like Xlib. + */ status = _cairo_surface_acquire_source_image (snapshot->target, &image, &extra); if (unlikely (status)) { snapshot->target = _cairo_surface_create_in_error (status); diff --git a/src/cairo-xlib-display.c b/src/cairo-xlib-display.c index fe93e1ca..59e602de 100644 --- a/src/cairo-xlib-display.c +++ b/src/cairo-xlib-display.c @@ -93,40 +93,6 @@ _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display) display->closed = TRUE; } -static void -_cairo_xlib_display_finish (void *abstract_display) -{ - cairo_xlib_display_t *display = abstract_display; - - display->display = NULL; -} - -static void -_cairo_xlib_display_destroy (void *abstract_display) -{ - cairo_xlib_display_t *display = abstract_display; - - /* destroy all outstanding notifies */ - while (display->workqueue != NULL) { - cairo_xlib_job_t *job = display->workqueue; - display->workqueue = job->next; - - if (job->type == WORK && job->func.work.destroy != NULL) - job->func.work.destroy (job->func.work.data); - - _cairo_freelist_free (&display->wq_freelist, job); - } - _cairo_freelist_fini (&display->wq_freelist); - - while (! cairo_list_is_empty (&display->screens)) { - _cairo_xlib_screen_destroy (cairo_list_first_entry (&display->screens, - cairo_xlib_screen_t, - link)); - } - - free (display); -} - static int _noop_error_handler (Display *display, XErrorEvent *event) @@ -187,11 +153,64 @@ _cairo_xlib_display_notify (cairo_xlib_display_t *display) } } +static void +_cairo_xlib_display_finish (void *abstract_display) +{ + cairo_xlib_display_t *display = abstract_display; + Display *dpy = display->display; + + if (! cairo_device_acquire (&display->base)) { + cairo_xlib_error_func_t old_handler; + + /* protect the notifies from triggering XErrors */ + XSync (dpy, False); + old_handler = XSetErrorHandler (_noop_error_handler); + + _cairo_xlib_display_notify (display); + _cairo_xlib_call_close_display_hooks (display); + + /* catch any that arrived before marking the display as closed */ + _cairo_xlib_display_notify (display); + + XSync (dpy, False); + XSetErrorHandler (old_handler); + + cairo_device_release (&display->base); + } + + display->display = NULL; +} + +static void +_cairo_xlib_display_destroy (void *abstract_display) +{ + cairo_xlib_display_t *display = abstract_display; + + /* destroy all outstanding notifies */ + while (display->workqueue != NULL) { + cairo_xlib_job_t *job = display->workqueue; + display->workqueue = job->next; + + if (job->type == WORK && job->func.work.destroy != NULL) + job->func.work.destroy (job->func.work.data); + + _cairo_freelist_free (&display->wq_freelist, job); + } + _cairo_freelist_fini (&display->wq_freelist); + + while (! cairo_list_is_empty (&display->screens)) { + _cairo_xlib_screen_destroy (cairo_list_first_entry (&display->screens, + cairo_xlib_screen_t, + link)); + } + + free (display); +} + static int _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) { cairo_xlib_display_t *display, **prev, *next; - cairo_xlib_error_func_t old_handler; CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex); for (display = _cairo_xlib_display_list; display; display = display->next) @@ -201,22 +220,7 @@ _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) if (display == NULL) return 0; - if (! cairo_device_acquire (&display->base)) { - /* protect the notifies from triggering XErrors */ - XSync (dpy, False); - old_handler = XSetErrorHandler (_noop_error_handler); - - _cairo_xlib_display_notify (display); - _cairo_xlib_call_close_display_hooks (display); - - /* catch any that arrived before marking the display as closed */ - _cairo_xlib_display_notify (display); - - XSync (dpy, False); - XSetErrorHandler (old_handler); - - cairo_device_release (&display->base); - } + cairo_device_finish (&display->base); /* * Unhook from the global list @@ -235,7 +239,6 @@ _cairo_xlib_close_display (Display *dpy, XExtCodes *codes) assert (display != NULL); - cairo_device_finish (&display->base); cairo_device_destroy (&display->base); /* Return value in accordance with requirements of diff --git a/src/cairo-xlib-private.h b/src/cairo-xlib-private.h index d10e986d..3a32eff2 100644 --- a/src/cairo-xlib-private.h +++ b/src/cairo-xlib-private.h @@ -109,6 +109,8 @@ struct _cairo_xlib_screen { cairo_device_t *device; Screen *screen; + cairo_list_t surfaces; + cairo_bool_t has_font_options; cairo_font_options_t font_options; diff --git a/src/cairo-xlib-screen.c b/src/cairo-xlib-screen.c index dc060c2e..356131fa 100644 --- a/src/cairo-xlib-screen.c +++ b/src/cairo-xlib-screen.c @@ -277,6 +277,15 @@ _cairo_xlib_screen_close_display (cairo_xlib_display_t *display, dpy = display->display; + while (! cairo_list_is_empty (&info->surfaces)) { + cairo_xlib_surface_t *surface; + + surface = cairo_list_first_entry (&info->surfaces, + cairo_xlib_surface_t, + link); + cairo_surface_finish (&surface->base); + } + for (i = 0; i < ARRAY_LENGTH (info->gc); i++) { if (info->gc_depths[i] != 0) { XFreeGC (dpy, info->gc[i]); @@ -336,6 +345,7 @@ _cairo_xlib_screen_get (Display *dpy, memset (info->gc_depths, 0, sizeof (info->gc_depths)); memset (info->gc, 0, sizeof (info->gc)); + cairo_list_init (&info->surfaces); cairo_list_init (&info->visuals); cairo_list_add (&info->link, &display->screens); diff --git a/src/cairo-xlib-surface-private.h b/src/cairo-xlib-surface-private.h index 34732b4f..b56b245c 100644 --- a/src/cairo-xlib-surface-private.h +++ b/src/cairo-xlib-surface-private.h @@ -46,6 +46,7 @@ struct _cairo_xlib_surface { cairo_xlib_screen_t *screen; cairo_xlib_hook_t close_display_hook; + cairo_list_t link; Drawable drawable; cairo_bool_t owns_pixmap; diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 885dc592..6cc215b5 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -466,6 +466,8 @@ _cairo_xlib_surface_finish (void *abstract_surface) X_DEBUG ((display->display, "finish (drawable=%x)", (unsigned int) surface->drawable)); + cairo_list_del (&surface->link); + status = _cairo_xlib_display_acquire (surface->base.device, &display); if (unlikely (status)) return status; @@ -3388,6 +3390,8 @@ found: surface->b_mask = 0; } + cairo_list_add (&surface->link, &screen->surfaces); + return &surface->base; } |