示例#1
0
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;
}
示例#2
0
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;
}