cairo_status_t _cairo_xlib_screen_get_visual_info (cairo_xlib_screen_info_t *info, Visual *visual, cairo_xlib_visual_info_t **out) { Display *dpy = info->display->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++) { if (visuals[i]->visualid == visual->visualid) { ret = visuals[i]; break; } } CAIRO_MUTEX_UNLOCK (info->mutex); if (ret != NULL) { *out = ret; return CAIRO_STATUS_SUCCESS; } status = _cairo_xlib_visual_info_create (dpy, XScreenNumberOfScreen (info->screen), visual->visualid, &ret); if (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); ret = visuals[i]; break; } } if (i == new_visuals) status = _cairo_array_append (&info->visuals, &ret); } else status = _cairo_array_append (&info->visuals, &ret); CAIRO_MUTEX_UNLOCK (info->mutex); if (status) { _cairo_xlib_visual_info_destroy (dpy, ret); return status; } *out = ret; return CAIRO_STATUS_SUCCESS; }
void _cairo_xlib_display_notify (cairo_xlib_display_t *display) { cairo_xlib_job_t *jobs, *job, *freelist; Display *dpy = display->display; 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; 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); 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); }
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) if (display->display == dpy) break; CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex); if (display == NULL) return 0; /* 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); _cairo_xlib_display_discard_screens (display); /* catch any that arrived before marking the display as closed */ _cairo_xlib_display_notify (display); XSync (dpy, False); XSetErrorHandler (old_handler); /* * Unhook from the global list */ CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex); prev = &_cairo_xlib_display_list; for (display = _cairo_xlib_display_list; display; display = next) { next = display->next; if (display->display == dpy) { *prev = next; break; } else prev = &display->next; } CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex); assert (display != NULL); _cairo_xlib_display_destroy (display); /* Return value in accordance with requirements of * XESetCloseDisplay */ return 0; }
static cairo_scaled_font_map_t * _cairo_scaled_font_map_lock (void) { CAIRO_MUTEX_LOCK (cairo_scaled_font_map_mutex); if (cairo_scaled_font_map == NULL) { cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t)); if (cairo_scaled_font_map == NULL) goto CLEANUP_MUTEX_LOCK; cairo_scaled_font_map->hash_table = _cairo_hash_table_create (_cairo_scaled_font_keys_equal); if (cairo_scaled_font_map->hash_table == NULL) goto CLEANUP_SCALED_FONT_MAP; cairo_scaled_font_map->num_holdovers = 0; } return cairo_scaled_font_map; CLEANUP_SCALED_FONT_MAP: free (cairo_scaled_font_map); CLEANUP_MUTEX_LOCK: CAIRO_MUTEX_UNLOCK (cairo_scaled_font_map_mutex); return NULL; }
void _cairo_atomic_int_set (int *x, int value) { CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); *x = value; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); }
cairo_status_t _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display, cairo_xlib_notify_resource_func notify, XID xid) { 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) { job->type = RESOURCE; job->func.resource.xid = xid; job->func.resource.notify = notify; job->next = display->workqueue; display->workqueue = job; status = CAIRO_STATUS_SUCCESS; } } CAIRO_MUTEX_UNLOCK (display->mutex); return status; }
void _cairo_xlib_remove_close_display_hooks (Display *dpy, const void *key) { cairo_xlib_display_t *display; cairo_xlib_hook_t *hook, *next, **prev; display = _cairo_xlib_display_get (dpy); if (display == NULL) return; CAIRO_MUTEX_LOCK (display->mutex); prev = &display->close_display_hooks; for (hook = display->close_display_hooks; hook != NULL; hook = next) { next = hook->next; if (hook->key == key) { *prev = hook->next; _cairo_freelist_free (&display->hook_freelist, hook); } else prev = &hook->next; } *prev = NULL; CAIRO_MUTEX_UNLOCK (display->mutex); _cairo_xlib_display_destroy (display); }
cairo_status_t _cairo_xlib_display_queue_work (cairo_xlib_display_t *display, cairo_xlib_notify_func notify, void *data, void (*destroy) (void *)) { 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) { job->type = WORK; job->func.work.data = data; job->func.work.notify = notify; job->func.work.destroy = destroy; job->next = display->workqueue; display->workqueue = job; status = CAIRO_STATUS_SUCCESS; } } CAIRO_MUTEX_UNLOCK (display->mutex); return status; }
cairo_bool_t _cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, const void *key) { cairo_xlib_display_t *display; cairo_xlib_hook_t *hook; cairo_bool_t ret = FALSE; display = _cairo_xlib_display_get (dpy); if (display == NULL) return FALSE; CAIRO_MUTEX_LOCK (display->mutex); if (display->closed == FALSE) { hook = _cairo_freelist_alloc (&display->hook_freelist); if (hook != NULL) { hook->func = func; hook->data = data; hook->key = key; hook->next = display->close_display_hooks; display->close_display_hooks = hook; ret = TRUE; } } CAIRO_MUTEX_UNLOCK (display->mutex); _cairo_xlib_display_destroy (display); return ret; }
cairo_status_t _cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip) { cairo_status_t status = CAIRO_STATUS_SUCCESS; GC oldgc; depth = depth_to_index (depth); CAIRO_MUTEX_LOCK (info->mutex); oldgc = info->gc[depth]; info->gc[depth] = gc; if (reset_clip) info->gc_needs_clip_reset |= 1 << depth; else info->gc_needs_clip_reset &= ~(1 << depth); CAIRO_MUTEX_UNLOCK (info->mutex); if (oldgc != NULL) { status = _cairo_xlib_display_queue_work (info->display, (cairo_xlib_notify_func) XFreeGC, oldgc, NULL); } return status; }
/** * cairo_font_face_destroy: * @font_face: a #cairo_font_face_t * * Decreases the reference count on @font_face by one. If the result * is zero, then @font_face and all associated resources are freed. * See cairo_font_face_reference(). **/ void cairo_font_face_destroy (cairo_font_face_t *font_face) { if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID) return; CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); assert (font_face->ref_count > 0); if (--(font_face->ref_count) > 0) { CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); return; } CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); font_face->backend->destroy (font_face); /* We allow resurrection to deal with some memory management for the * FreeType backend where cairo_ft_font_face_t and cairo_ft_unscaled_font_t * need to effectively mutually reference each other */ if (font_face->ref_count > 0) return; _cairo_user_data_array_fini (&font_face->user_data); free (font_face); }
void _cairo_atomic_int_inc (int *x) { CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); *x += 1; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); }
static cairo_int_status_t _cairo_paginated_surface_show_glyphs (void *abstract_surface, cairo_operator_t op, cairo_pattern_t *source, cairo_glyph_t *glyphs, int num_glyphs, cairo_scaled_font_t *scaled_font) { cairo_paginated_surface_t *surface = abstract_surface; cairo_int_status_t status; /* Optimize away erasing of nothing. */ if (surface->page_is_blank && op == CAIRO_OPERATOR_CLEAR) return CAIRO_STATUS_SUCCESS; surface->page_is_blank = FALSE; /* Since this is a "wrapping" surface, we're calling back into * _cairo_surface_show_glyphs from within a call to the same. * Since _cairo_surface_show_glyphs acquires a mutex, we release * and re-acquire the mutex around this nested call. * * Yes, this is ugly, but we consider it pragmatic as compared to * adding locking code to all 18 surface-backend-specific * show_glyphs functions, (which would get less testing and likely * lead to bugs). */ CAIRO_MUTEX_UNLOCK (scaled_font->mutex); status = _cairo_surface_show_glyphs (surface->meta, op, source, glyphs, num_glyphs, scaled_font); CAIRO_MUTEX_LOCK (scaled_font->mutex); return status; }
void _cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info) { cairo_xlib_screen_info_t **prev; cairo_xlib_screen_info_t *list; assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&info->ref_count)); if (! _cairo_reference_count_dec_and_test (&info->ref_count)) return; CAIRO_MUTEX_LOCK (info->display->mutex); for (prev = &info->display->screens; (list = *prev); prev = &list->next) { if (list == info) { *prev = info->next; break; } } CAIRO_MUTEX_UNLOCK (info->display->mutex); _cairo_xlib_screen_info_close_display (info); _cairo_xlib_display_destroy (info->display); _cairo_array_fini (&info->visuals); CAIRO_MUTEX_FINI (info->mutex); free (info); }
void _cairo_font_reset_static_data (void) { _cairo_scaled_font_map_destroy (); CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex); _cairo_hash_table_destroy (cairo_toy_font_face_hash_table); cairo_toy_font_face_hash_table = NULL; CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex); }
cairo_bool_t _cairo_atomic_int_dec_and_test (int *x) { cairo_bool_t ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = --*x == 0; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); return ret; }
int _cairo_atomic_int_get (int *x) { int ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); return ret; }
void _cairo_toy_font_face_reset_static_data (void) { /* We manually acquire the lock rather than calling * cairo_toy_font_face_hash_table_lock simply to avoid * creating the table only to destroy it again. */ CAIRO_MUTEX_LOCK (_cairo_toy_font_face_mutex); _cairo_hash_table_destroy (cairo_toy_font_face_hash_table); cairo_toy_font_face_hash_table = NULL; CAIRO_MUTEX_UNLOCK (_cairo_toy_font_face_mutex); }
cairo_atomic_intptr_t _cairo_atomic_int_get (cairo_atomic_intptr_t *x) { cairo_atomic_intptr_t ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); return ret; }
int _cairo_atomic_int_cmpxchg (int *x, int oldv, int newv) { int ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; if (ret == oldv) *x = newv; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); return ret; }
cairo_atomic_intptr_t _cairo_atomic_int_cmpxchg_return_old_impl (cairo_atomic_intptr_t *x, cairo_atomic_intptr_t oldv, cairo_atomic_intptr_t newv) { cairo_atomic_intptr_t ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; if (ret == oldv) *x = newv; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); return ret; }
void * _cairo_atomic_ptr_cmpxchg_return_old_impl (void **x, void *oldv, void *newv) { void *ret; CAIRO_MUTEX_LOCK (_cairo_atomic_mutex); ret = *x; if (ret == oldv) *x = newv; CAIRO_MUTEX_UNLOCK (_cairo_atomic_mutex); return ret; }
static void _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display) { cairo_xlib_screen_info_t *screen; cairo_xlib_hook_t *hooks, *list; /* call all registered shutdown routines */ CAIRO_MUTEX_LOCK (display->mutex); for (screen = display->screens; screen != NULL; screen = screen->next) _cairo_xlib_screen_info_close_display (screen); hooks = display->close_display_hooks; while (hooks != NULL) { display->close_display_hooks = NULL; CAIRO_MUTEX_UNLOCK (display->mutex); list = hooks; do { cairo_xlib_hook_t *hook = list; list = hook->next; hook->func (display->display, hook->data); } while (list != NULL); CAIRO_MUTEX_LOCK (display->mutex); do { cairo_xlib_hook_t *hook = hooks; hooks = hook->next; _cairo_freelist_free (&display->hook_freelist, hook); } while (hooks != NULL); hooks = display->close_display_hooks; } display->closed = TRUE; CAIRO_MUTEX_UNLOCK (display->mutex); }
void _cairo_font_reset_static_data (void) { _cairo_scaled_font_map_destroy (); _cairo_lock_global_image_glyph_cache(); _cairo_cache_destroy (_global_image_glyph_cache); _global_image_glyph_cache = NULL; _cairo_unlock_global_image_glyph_cache(); CAIRO_MUTEX_LOCK (cairo_toy_font_face_hash_table_mutex); _cairo_hash_table_destroy (cairo_toy_font_face_hash_table); cairo_toy_font_face_hash_table = NULL; CAIRO_MUTEX_UNLOCK (cairo_toy_font_face_hash_table_mutex); }
void _cairo_drm_device_fini (cairo_drm_device_t *device) { CAIRO_MUTEX_LOCK (_cairo_drm_device_mutex); if (device->prev != NULL) device->prev->next = device->next; else _cairo_drm_known_devices = device->next; if (device->next != NULL) device->next->prev = device->prev; CAIRO_MUTEX_UNLOCK (_cairo_drm_device_mutex); if (device->fd != -1) close (device->fd); }
static void _cairo_surface_snapshot_copy_on_write (cairo_surface_t *surface) { cairo_surface_snapshot_t *snapshot = (cairo_surface_snapshot_t *) surface; cairo_image_surface_t *image; cairo_surface_t *clone; void *extra; cairo_status_t status; TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, snapshot->target->unique_id)); /* We need to make an image copy of the original surface since the * snapshot may exceed the lifetime of the original device, i.e. * when we later need to use the snapshot the data may have already * been lost. */ CAIRO_MUTEX_LOCK (snapshot->mutex); if (snapshot->target->backend->snapshot != NULL) { clone = snapshot->target->backend->snapshot (snapshot->target); if (clone != NULL) { assert (clone->status || ! _cairo_surface_is_snapshot (clone)); goto done; } } /* 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); status = _cairo_surface_set_error (surface, status); goto unlock; } clone = image->base.backend->snapshot (&image->base); _cairo_surface_release_source_image (snapshot->target, image, extra); done: status = _cairo_surface_set_error (surface, clone->status); snapshot->target = snapshot->clone = clone; snapshot->base.type = clone->type; unlock: CAIRO_MUTEX_UNLOCK (snapshot->mutex); }
static void _cairo_xlib_display_discard_screens (cairo_xlib_display_t *display) { cairo_xlib_screen_info_t *screens; CAIRO_MUTEX_LOCK (display->mutex); screens = display->screens; display->screens = NULL; CAIRO_MUTEX_UNLOCK (display->mutex); while (screens != NULL) { cairo_xlib_screen_info_t *screen = screens; screens = screen->next; _cairo_xlib_screen_info_destroy (screen); } }
static cairo_hash_table_t * _cairo_toy_font_face_hash_table_lock (void) { CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); if (cairo_toy_font_face_hash_table == NULL) { cairo_toy_font_face_hash_table = _cairo_hash_table_create (_cairo_toy_font_face_keys_equal); if (cairo_toy_font_face_hash_table == NULL) { CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); return NULL; } } return cairo_toy_font_face_hash_table; }
/** * cairo_font_face_reference: * @font_face: a #cairo_font_face_t, (may be %NULL in which case this * function does nothing). * * Increases the reference count on @font_face by one. This prevents * @font_face from being destroyed until a matching call to * cairo_font_face_destroy() is made. * * The number of references to a #cairo_font_face_t can be get using * cairo_font_face_get_reference_count(). * * Return value: the referenced #cairo_font_face_t. **/ cairo_font_face_t * cairo_font_face_reference (cairo_font_face_t *font_face) { if (font_face == NULL || font_face->ref_count == CAIRO_REF_COUNT_INVALID) return font_face; CAIRO_MUTEX_LOCK (_cairo_font_face_mutex); /* We would normally assert (font_face->ref_count >0) here but we * can't get away with that due to the zombie case as documented * in _cairo_ft_font_face_destroy. */ font_face->ref_count++; CAIRO_MUTEX_UNLOCK (_cairo_font_face_mutex); return font_face; }
GC _cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth) { GC gc; cairo_bool_t needs_reset; depth = depth_to_index (depth); CAIRO_MUTEX_LOCK (info->mutex); gc = info->gc[depth]; info->gc[depth] = NULL; needs_reset = info->gc_needs_clip_reset & (1 << depth); info->gc_needs_clip_reset &= ~(1 << depth); CAIRO_MUTEX_UNLOCK (info->mutex); if (needs_reset) XSetClipMask(info->display->display, gc, None); return gc; }