summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-08-14 13:47:14 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2011-08-14 13:47:43 +0100
commit84a3b6e2d0b8103cdc17558b502ecfc4c99b98a3 (patch)
tree3b20ebb9adcbfcf97fba4423966cb5df320a9499
parent2c885a275349c65ec831738ed917ecd16fdd8c65 (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.c5
-rw-r--r--src/cairo-xlib-display.c107
-rw-r--r--src/cairo-xlib-private.h2
-rw-r--r--src/cairo-xlib-screen.c10
-rw-r--r--src/cairo-xlib-surface-private.h1
-rw-r--r--src/cairo-xlib-surface.c4
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;
}