cairo_xlib_screen_info_t * _cairo_xlib_screen_info_get (cairo_xlib_display_t *display, Screen *screen) { cairo_xlib_screen_info_t *info = NULL, **prev; CAIRO_MUTEX_LOCK (display->mutex); if (display->closed) { CAIRO_MUTEX_UNLOCK (display->mutex); return NULL; } for (prev = &display->screens; (info = *prev); prev = &(*prev)->next) { if (info->screen == screen) { /* * MRU the list */ if (prev != &display->screens) { *prev = info->next; info->next = display->screens; display->screens = info; } break; } } CAIRO_MUTEX_UNLOCK (display->mutex); if (info != NULL) { info = _cairo_xlib_screen_info_reference (info); } else { info = malloc (sizeof (cairo_xlib_screen_info_t)); if (info != NULL) { CAIRO_REFERENCE_COUNT_INIT (&info->ref_count, 2); /* Add one for display cache */ CAIRO_MUTEX_INIT (info->mutex); info->display = _cairo_xlib_display_reference (display); info->screen = screen; info->has_render = FALSE; _cairo_font_options_init_default (&info->font_options); memset (info->gc, 0, sizeof (info->gc)); info->gc_needs_clip_reset = 0; _cairo_array_init (&info->visuals, sizeof (cairo_xlib_visual_info_t*)); if (screen) { Display *dpy = display->display; int event_base, error_base; info->has_render = (XRenderQueryExtension (dpy, &event_base, &error_base) && (XRenderFindVisualFormat (dpy, DefaultVisual (dpy, DefaultScreen (dpy))) != 0)); _cairo_xlib_init_screen_font_options (dpy, info); } CAIRO_MUTEX_LOCK (display->mutex); info->next = display->screens; display->screens = info; CAIRO_MUTEX_UNLOCK (display->mutex); } } return info; }
cairo_xlib_display_t * _cairo_xlib_display_get (Display *dpy) { cairo_xlib_display_t *display; cairo_xlib_display_t **prev; XExtCodes *codes; int major_unused, minor_unused; /* There is an apparent deadlock between this mutex and the * mutex for the display, but it's actually safe. For the * app to call XCloseDisplay() while any other thread is * inside this function would be an error in the logic * app, and the CloseDisplay hook is the only other place we * acquire this mutex. */ CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex); for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next) { if (display->display == dpy) { /* * MRU the list */ if (prev != &_cairo_xlib_display_list) { *prev = display->next; display->next = _cairo_xlib_display_list; _cairo_xlib_display_list = display; } break; } } if (display != NULL) { display = _cairo_xlib_display_reference (display); goto UNLOCK; } display = malloc (sizeof (cairo_xlib_display_t)); if (display == NULL) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); goto UNLOCK; } /* Xlib calls out to the extension close_display hooks in LIFO * order. So we have to ensure that all extensions that we depend * on in our close_display hook are properly initialized before we * add our hook. For now, that means Render, so we call into its * QueryVersion function to ensure it gets initialized. */ XRenderQueryVersion (dpy, &major_unused, &minor_unused); codes = XAddExtension (dpy); if (codes == NULL) { _cairo_error_throw (CAIRO_STATUS_NO_MEMORY); free (display); display = NULL; goto UNLOCK; } XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display); _cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t)); _cairo_freelist_init (&display->hook_freelist, sizeof (cairo_xlib_hook_t)); CAIRO_REFERENCE_COUNT_INIT (&display->ref_count, 2); /* add one for the CloseDisplay */ CAIRO_MUTEX_INIT (display->mutex); display->display = dpy; display->screens = NULL; display->workqueue = NULL; display->close_display_hooks = NULL; display->closed = FALSE; display->buggy_repeat = FALSE; if (strstr (ServerVendor (dpy), "X.Org") != NULL) { /* When modularized, the X.Org server VendorRelease was * bogusly reset to a very small number, without any change in * the ServerVendor string. We avoid considering the new * servers with the small number as buggy by restricting the * test to known bad releases. But there could be a problem * again in the future if X.Org server versions ever climb * back up to 6.7 or 6.8. */ if (VendorRelease (dpy) >= 60700000 && VendorRelease (dpy) <= 60802000) display->buggy_repeat = TRUE; /* But even the new modular server has bugs, (bad enough to * crash the X server), that it so happens we can avoid with * the exact same buggy_repeat workaround. We've verified that * this bug exists as least as late as version 1.3.0.0, (which * is in Fedora 8), and is gone again in version 1.4.99.901 * (from a Fedora 9 Beta). Versions between those are still * unknown, but until we learn more, we'll assume that any 1.3 * version is buggy. */ if (VendorRelease (dpy) < 10400000) display->buggy_repeat = TRUE; } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) { if (VendorRelease (dpy) <= 40500000) display->buggy_repeat = TRUE; } display->next = _cairo_xlib_display_list; _cairo_xlib_display_list = display; UNLOCK: CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex); return display; }