Commit 84a3b6e2 authored by Chris Wilson's avatar Chris Wilson 🤔
Browse files

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's avatarChris Wilson <chris@chris-wilson.co.uk>
parent 2c885a27
......@@ -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);
......
......@@ -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
......
......@@ -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;
......
......@@ -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);
......
......@@ -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;
......
......@@ -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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment