243
242
cairo_font_options_set_hint_metrics (&info->font_options, CAIRO_HINT_METRICS_ON);
246
static cairo_xlib_screen_info_t *_cairo_xlib_screen_list = NULL;
248
/* NOTE: This function must be called with _cairo_xlib_screen_mutex held. */
250
_cairo_xlib_call_close_display_hooks (cairo_xlib_screen_info_t *info)
252
/* call all registered shutdown routines */
253
while (info->close_display_hooks != NULL) {
254
cairo_xlib_hook_t *hooks = info->close_display_hooks;
255
info->close_display_hooks = NULL;
257
/* drop the list mutex whilst calling the hooks */
258
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
260
cairo_xlib_hook_t *hook = hooks;
263
hook->func (info->display, hook->data);
266
} while (hooks != NULL);
267
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
272
_cairo_xlib_screen_info_reference_lock_held (cairo_xlib_screen_info_t *info)
245
cairo_xlib_screen_info_t *
246
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
274
251
assert (info->ref_count > 0);
275
252
info->ref_count++;
278
cairo_xlib_screen_info_t *
279
_cairo_xlib_screen_info_reference (cairo_xlib_screen_info_t *info)
258
_cairo_xlib_screen_info_close_display (cairo_xlib_screen_info_t *info)
262
for (i = 0; i < ARRAY_LENGTH (info->gc); i++) {
263
if (info->gc[i] != NULL) {
264
XFreeGC (info->display->display, info->gc[i]);
271
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
273
cairo_xlib_screen_info_t **prev;
274
cairo_xlib_screen_info_t *list;
281
276
if (info == NULL)
284
/* use our global mutex until we get a real atomic inc */
285
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
287
_cairo_xlib_screen_info_reference_lock_held (info);
289
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
295
_cairo_xlib_screen_info_destroy_lock_held (cairo_xlib_screen_info_t *info)
297
279
assert (info->ref_count > 0);
298
280
if (--info->ref_count)
301
_cairo_xlib_call_close_display_hooks (info);
283
CAIRO_MUTEX_LOCK (info->display->mutex);
284
for (prev = &info->display->screens; (list = *prev); prev = &list->next) {
290
CAIRO_MUTEX_UNLOCK (info->display->mutex);
292
_cairo_xlib_screen_info_close_display (info);
294
_cairo_xlib_display_destroy (info->display);
306
_cairo_xlib_screen_info_destroy (cairo_xlib_screen_info_t *info)
311
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
313
_cairo_xlib_screen_info_destroy_lock_held (info);
315
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
319
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
321
cairo_xlib_screen_info_t *info, **prev, *next;
324
* Unhook from the global list
326
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
328
prev = &_cairo_xlib_screen_list;
329
for (info = _cairo_xlib_screen_list; info; info = next) {
331
if (info->display == dpy) {
332
/* trigger the hooks explicitly as we know the display is closing */
333
_cairo_xlib_call_close_display_hooks (info);
334
_cairo_xlib_screen_info_destroy_lock_held (info);
341
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
343
/* Return value in accordance with requirements of
344
* XESetCloseDisplay */
349
_cairo_xlib_screen_info_reset (void)
352
* Delete everything in the list.
354
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
356
while (_cairo_xlib_screen_list != NULL) {
357
cairo_xlib_screen_info_t *info = _cairo_xlib_screen_list;
358
_cairo_xlib_screen_list = info->next;
359
_cairo_xlib_screen_info_destroy_lock_held (info);
362
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
366
static cairo_xlib_screen_info_t *
367
_cairo_xlib_screen_info_get_lock_held (Display *dpy, Screen *screen)
369
cairo_xlib_screen_info_t *info;
370
cairo_xlib_screen_info_t **prev;
371
int event_base, error_base;
373
cairo_bool_t seen_display = FALSE;
375
for (prev = &_cairo_xlib_screen_list; (info = *prev); prev = &(*prev)->next)
377
if (info->display == dpy) {
379
if (info->screen == screen) {
383
if (prev != &_cairo_xlib_screen_list) {
385
info->next = _cairo_xlib_screen_list;
386
_cairo_xlib_screen_list = info;
396
info = malloc (sizeof (cairo_xlib_screen_info_t));
401
codes = XAddExtension (dpy);
407
XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
412
info->screen = screen;
413
info->close_display_hooks = NULL;
414
info->has_render = FALSE;
415
_cairo_font_options_init_default (&info->font_options);
418
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
419
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
420
_cairo_xlib_init_screen_font_options (info);
423
info->next = _cairo_xlib_screen_list;
424
_cairo_xlib_screen_list = info;
428
299
cairo_xlib_screen_info_t *
429
300
_cairo_xlib_screen_info_get (Display *dpy, Screen *screen)
431
cairo_xlib_screen_info_t *info;
433
/* There is an apparent deadlock between this mutex and the
434
* mutex for the display, but it's actually safe. For the
435
* app to call XCloseDisplay() while any other thread is
436
* inside this function would be an error in the logic
437
* app, and the CloseDisplay hook is the only other place we
438
* acquire this mutex.
440
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
442
info = _cairo_xlib_screen_info_get_lock_held (dpy, screen);
444
_cairo_xlib_screen_info_reference_lock_held (info);
446
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
452
_cairo_xlib_add_close_display_hook (Display *dpy, void (*func) (Display *, void *), void *data, void *key)
454
cairo_xlib_screen_info_t *info;
455
cairo_xlib_hook_t *hook;
456
cairo_xlib_hook_t **prev;
457
cairo_bool_t success = FALSE;
459
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
461
info = _cairo_xlib_screen_info_get_lock_held (dpy, NULL);
465
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
467
if (hook->key == key) {
302
cairo_xlib_display_t *display;
303
cairo_xlib_screen_info_t *info = NULL, **prev;
305
display = _cairo_xlib_display_get (dpy);
309
CAIRO_MUTEX_LOCK (display->mutex);
310
if (display->closed) {
311
CAIRO_MUTEX_UNLOCK (display->mutex);
315
for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) {
316
if (info->screen == screen) {
471
if (prev != &info->close_display_hooks) {
473
hook->next = info->close_display_hooks;
474
info->close_display_hooks = hook;
481
hook = malloc (sizeof (cairo_xlib_hook_t));
487
hook->next = info->close_display_hooks;
488
info->close_display_hooks = hook;
493
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
498
_cairo_xlib_remove_close_display_hook (Display *dpy, void *key)
500
cairo_xlib_screen_info_t *info;
501
cairo_xlib_hook_t *hook;
502
cairo_xlib_hook_t **prev;
504
CAIRO_MUTEX_LOCK (_cairo_xlib_screen_mutex);
506
info = _cairo_xlib_screen_info_get_lock_held (dpy, NULL);
510
for (prev = &info->close_display_hooks; (hook = *prev); prev = &hook->next)
512
if (hook->key == key) {
520
CAIRO_MUTEX_UNLOCK (_cairo_xlib_screen_mutex);
524
_cairo_xlib_screen_reset_static_data (void)
526
_cairo_xlib_screen_info_reset ();
320
if (prev != &display->screens) {
322
info->next = display->screens;
323
display->screens = info;
328
CAIRO_MUTEX_UNLOCK (display->mutex);
331
info = _cairo_xlib_screen_info_reference (info);
333
info = malloc (sizeof (cairo_xlib_screen_info_t));
335
info->ref_count = 2; /* Add one for display cache */
336
info->display = _cairo_xlib_display_reference (display);
337
info->screen = screen;
338
info->has_render = FALSE;
339
_cairo_font_options_init_default (&info->font_options);
340
memset (info->gc, 0, sizeof (info->gc));
341
info->gc_needs_clip_reset = 0;
344
int event_base, error_base;
345
info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) &&
346
(XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0));
347
_cairo_xlib_init_screen_font_options (dpy, info);
350
CAIRO_MUTEX_LOCK (display->mutex);
351
info->next = display->screens;
352
display->screens = info;
353
CAIRO_MUTEX_UNLOCK (display->mutex);
358
_cairo_xlib_display_destroy (display);
364
depth_to_index (int depth)
380
_cairo_xlib_screen_get_gc (cairo_xlib_screen_info_t *info, int depth)
384
depth = depth_to_index (depth);
386
gc = info->gc[depth];
387
info->gc[depth] = NULL;
389
if (info->gc_needs_clip_reset & (1 << depth)) {
390
XSetClipMask(info->display->display, gc, None);
391
info->gc_needs_clip_reset &= ~(1 << depth);
398
_cairo_xlib_screen_put_gc (cairo_xlib_screen_info_t *info, int depth, GC gc, cairo_bool_t reset_clip)
400
cairo_status_t status = CAIRO_STATUS_SUCCESS;
402
depth = depth_to_index (depth);
404
if (info->gc[depth] != NULL) {
405
status = _cairo_xlib_display_queue_work (info->display,
406
(cairo_xlib_notify_func) XFreeGC,
411
info->gc[depth] = gc;
413
info->gc_needs_clip_reset |= 1 << depth;
415
info->gc_needs_clip_reset &= ~(1 << depth);