third_party/cairo/src/cairo-xlib-display.c
cairo_device_t *
_cairo_xlib_device_create (Display *dpy)
{
    cairo_xlib_display_t *display;
    cairo_xlib_display_t **prev;
    cairo_device_t *device;
    XExtCodes *codes;
    const char *env;

    CAIRO_MUTEX_INITIALIZE ();

    /* 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;
	    }
            device = cairo_device_reference (&display->base);
	    goto UNLOCK;
	}
    }

    display = _cairo_malloc (sizeof (cairo_xlib_display_t));
    if (unlikely (display == NULL)) {
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
	goto UNLOCK;
    }

    _cairo_device_init (&display->base, &_cairo_xlib_device_backend);

    display->display = dpy;
    cairo_list_init (&display->screens);
    cairo_list_init (&display->fonts);
    display->closed = FALSE;

    /* 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.
     */
    display->render_major = display->render_minor = -1;
    XRenderQueryVersion (dpy, &display->render_major, &display->render_minor);
    env = getenv ("CAIRO_DEBUG");
    if (env != NULL && (env = strstr (env, "xrender-version=")) != NULL) {
	int max_render_major, max_render_minor;

	env += sizeof ("xrender-version=") - 1;
	if (sscanf (env, "%d.%d", &max_render_major, &max_render_minor) != 2)
	    max_render_major = max_render_minor = -1;

	if (max_render_major < display->render_major ||
	    (max_render_major == display->render_major &&
	     max_render_minor < display->render_minor))
	{
	    display->render_major = max_render_major;
	    display->render_minor = max_render_minor;
	}
    }

    _cairo_xlib_display_select_compositor (display);

    display->white = NULL;
    memset (display->alpha, 0, sizeof (display->alpha));
    memset (display->solid, 0, sizeof (display->solid));
    memset (display->solid_cache, 0, sizeof (display->solid_cache));
    memset (display->last_solid_cache, 0, sizeof (display->last_solid_cache));

    memset (display->cached_xrender_formats, 0,
	    sizeof (display->cached_xrender_formats));

    display->force_precision = -1;

    _cairo_xlib_display_init_shm (display);

    /* Prior to Render 0.10, there is no protocol support for gradients and
     * we call function stubs instead, which would silently consume the drawing.
     */
#if RENDER_MAJOR == 0 && RENDER_MINOR < 10
    display->buggy_gradients = TRUE;
#else
    display->buggy_gradients = FALSE;
#endif
    display->buggy_pad_reflect = FALSE;
    display->buggy_repeat = FALSE;

    /* This buggy_repeat condition is very complicated because there
     * are multiple X server code bases (with multiple versioning
     * schemes within a code base), and multiple bugs.
     *
     * The X servers:
     *
     *    1. The Vendor=="XFree86" code base with release numbers such
     *    as 4.7.0 (VendorRelease==40700000).
     *
     *    2. The Vendor=="X.Org" code base (a descendant of the
     *    XFree86 code base). It originally had things like
     *    VendorRelease==60700000 for release 6.7.0 but then changed
     *    its versioning scheme so that, for example,
     *    VendorRelease==10400000 for the 1.4.0 X server within the
     *    X.Org 7.3 release.
     *
     * The bugs:
     *
     *    1. The original bug that led to the buggy_repeat
     *    workaround. This was a bug that Owen Taylor investigated,
     *    understood well, and characterized against various X
     *    servers. Confirmed X servers with this bug include:
     *
     *		"XFree86" <= 40500000
     *		"X.Org" <= 60802000 (only with old numbering >= 60700000)
     *
     *    2. A separate bug resulting in a crash of the X server when
     *    using cairo's extend-reflect test case, (which, surprisingly
     *    enough was not passing RepeatReflect to the X server, but
     *    instead using RepeatNormal in a workaround). Nobody to date
     *    has understood the bug well, but it appears to be gone as of
     *    the X.Org 1.4.0 server. This bug is coincidentally avoided
     *    by using the same buggy_repeat workaround. Confirmed X
     *    servers with this bug include:
     *
     *		"X.org" == 60900000 (old versioning scheme)
     *		"X.org"  < 10400000 (new numbering scheme)
     *
     *    For the old-versioning-scheme X servers we don't know
     *    exactly when second the bug started, but since bug 1 is
     *    present through 6.8.2 and bug 2 is present in 6.9.0 it seems
     *    safest to just blacklist all old-versioning-scheme X servers,
     *    (just using VendorRelease < 70000000), as buggy_repeat=TRUE.
     */
    if (_cairo_xlib_vendor_is_xorg (dpy)) {
	if (VendorRelease (dpy) >= 60700000) {
	    if (VendorRelease (dpy) < 70000000)
		display->buggy_repeat = TRUE;

	    /* We know that gradients simply do not work in early Xorg servers */
	    if (VendorRelease (dpy) < 70200000)
		display->buggy_gradients = TRUE;

	    /* And the extended repeat modes were not fixed until much later */
	    display->buggy_pad_reflect = TRUE;
	} else {
	    if (VendorRelease (dpy) < 10400000)
		display->buggy_repeat = TRUE;

	    /* Too many bugs in the early drivers */
	    if (VendorRelease (dpy) < 10699000)
		display->buggy_pad_reflect = TRUE;
	}
    } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
	if (VendorRelease (dpy) <= 40500000)
	    display->buggy_repeat = TRUE;

	display->buggy_gradients = TRUE;
	display->buggy_pad_reflect = TRUE;
    }

    codes = XAddExtension (dpy);
    if (unlikely (codes == NULL)) {
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
	free (display);
	goto UNLOCK;
    }

    XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
    cairo_device_reference (&display->base); /* add one for the CloseDisplay */

    display->next = _cairo_xlib_display_list;
    _cairo_xlib_display_list = display;

    device = &display->base;

UNLOCK:
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
    return device;
}
/**
 * _cairo_xlib_device_create:
 * @dpy: the display to create the device for
 *
 * Gets the device belonging to @dpy, or creates it if it doesn't exist yet.
 *
 * Returns: the device belonging to @dpy
 **/
@dpy: the display to create the device for

Gets the device belonging to @dpy, or creates it if it doesn't exist yet.

the device belonging to @dpy
@dpy : the display to create the device for Gets the device belonging to @dpy or creates it if it doesn ' t exist yet . the device belonging to @dpy
cairo_device_t *
_cairo_xlib_device_create (Display *dpy)
{
    cairo_xlib_display_t *display;
    cairo_xlib_display_t **prev;
    cairo_device_t *device;
    XExtCodes *codes;
    const char *env;
    CAIRO_MUTEX_INITIALIZE ();
    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
    for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next)
    {
	if (display->display == dpy) {
	    if (prev != &_cairo_xlib_display_list) {
		*prev = display->next;
		display->next = _cairo_xlib_display_list;
		_cairo_xlib_display_list = display;
	    }
            device = cairo_device_reference (&display->base);
	    goto UNLOCK;
	}
    }
    display = _cairo_malloc (sizeof (cairo_xlib_display_t));
    if (unlikely (display == NULL)) {
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
	goto UNLOCK;
    }
    _cairo_device_init (&display->base, &_cairo_xlib_device_backend);
    display->display = dpy;
    cairo_list_init (&display->screens);
    cairo_list_init (&display->fonts);
    display->closed = FALSE;
    display->render_major = display->render_minor = -1;
    XRenderQueryVersion (dpy, &display->render_major, &display->render_minor);
    env = getenv ("CAIRO_DEBUG");
    if (env != NULL && (env = strstr (env, "xrender-version=")) != NULL) {
	int max_render_major, max_render_minor;
	env += sizeof ("xrender-version=") - 1;
	if (sscanf (env, "%d.%d", &max_render_major, &max_render_minor) != 2)
	    max_render_major = max_render_minor = -1;
	if (max_render_major < display->render_major ||
	    (max_render_major == display->render_major &&
	     max_render_minor < display->render_minor))
	{
	    display->render_major = max_render_major;
	    display->render_minor = max_render_minor;
	}
    }
    _cairo_xlib_display_select_compositor (display);
    display->white = NULL;
    memset (display->alpha, 0, sizeof (display->alpha));
    memset (display->solid, 0, sizeof (display->solid));
    memset (display->solid_cache, 0, sizeof (display->solid_cache));
    memset (display->last_solid_cache, 0, sizeof (display->last_solid_cache));
    memset (display->cached_xrender_formats, 0,
	    sizeof (display->cached_xrender_formats));
    display->force_precision = -1;
    _cairo_xlib_display_init_shm (display);
#if RENDER_MAJOR == 0 && RENDER_MINOR < 10
    display->buggy_gradients = TRUE;
#else
    display->buggy_gradients = FALSE;
#endif
    display->buggy_pad_reflect = FALSE;
    display->buggy_repeat = FALSE;
    if (_cairo_xlib_vendor_is_xorg (dpy)) {
	if (VendorRelease (dpy) >= 60700000) {
	    if (VendorRelease (dpy) < 70000000)
		display->buggy_repeat = TRUE;
	    if (VendorRelease (dpy) < 70200000)
		display->buggy_gradients = TRUE;
	    display->buggy_pad_reflect = TRUE;
	} else {
	    if (VendorRelease (dpy) < 10400000)
		display->buggy_repeat = TRUE;
	    if (VendorRelease (dpy) < 10699000)
		display->buggy_pad_reflect = TRUE;
	}
    } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
	if (VendorRelease (dpy) <= 40500000)
	    display->buggy_repeat = TRUE;
	display->buggy_gradients = TRUE;
	display->buggy_pad_reflect = TRUE;
    }
    codes = XAddExtension (dpy);
    if (unlikely (codes == NULL)) {
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
	free (display);
	goto UNLOCK;
    }
    XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
    cairo_device_reference (&display->base); 
    display->next = _cairo_xlib_display_list;
    _cairo_xlib_display_list = display;
    device = &display->base;
UNLOCK:
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
    return device;
}
cairo_device_t * _cairo_xlib_device_create ( Display * dpy ) { cairo_xlib_display_t * display ; cairo_xlib_display_t * * prev ; cairo_device_t * device ; XExtCodes * codes ; const char * env ; CAIRO_MUTEX_INITIALIZE ( ) ; CAIRO_MUTEX_LOCK ( _cairo_xlib_display_mutex ) ; for ( prev = & _cairo_xlib_display_list ; ( display = * prev ) ; prev = & ( * prev ) -> next ) { if ( display -> display == dpy ) { if ( prev != & _cairo_xlib_display_list ) { * prev = display -> next ; display -> next = _cairo_xlib_display_list ; _cairo_xlib_display_list = display ; } device = cairo_device_reference ( & display -> base ) ; goto UNLOCK ; } } display = _cairo_malloc ( sizeof ( cairo_xlib_display_t ) ) ; if ( unlikely ( display == NULL ) ) { device = _cairo_device_create_in_error ( CAIRO_STATUS_NO_MEMORY ) ; goto UNLOCK ; } _cairo_device_init ( & display -> base , & _cairo_xlib_device_backend ) ; display -> display = dpy ; cairo_list_init ( & display -> screens ) ; cairo_list_init ( & display -> fonts ) ; display -> closed = FALSE ; display -> render_major = display -> render_minor = -1 ; XRenderQueryVersion ( dpy , & display -> render_major , & display -> render_minor ) ; env = getenv ( " " ) ; if ( env != NULL && ( env = strstr ( env , " " ) ) != NULL ) { int max_render_major , max_render_minor ; env += sizeof ( " " ) - 1 ; if ( sscanf ( env , " " , & max_render_major , & max_render_minor ) != 2 ) max_render_major = max_render_minor = -1 ; if ( max_render_major < display -> render_major || ( max_render_major == display -> render_major && max_render_minor < display -> render_minor ) ) { display -> render_major = max_render_major ; display -> render_minor = max_render_minor ; } } _cairo_xlib_display_select_compositor ( display ) ; display -> white = NULL ; memset ( display -> alpha , 0 , sizeof ( display -> alpha ) ) ; memset ( display -> solid , 0 , sizeof ( display -> solid ) ) ; memset ( display -> solid_cache , 0 , sizeof ( display -> solid_cache ) ) ; memset ( display -> last_solid_cache , 0 , sizeof ( display -> last_solid_cache ) ) ; memset ( display -> cached_xrender_formats , 0 , sizeof ( display -> cached_xrender_formats ) ) ; display -> force_precision = -1 ; _cairo_xlib_display_init_shm ( display ) ; #if RENDER_MAJOR == 0 && RENDER_MINOR < 10 display -> buggy_gradients = TRUE ; #else display -> buggy_gradients = FALSE ; #endif display -> buggy_pad_reflect = FALSE ; display -> buggy_repeat = FALSE ; if ( _cairo_xlib_vendor_is_xorg ( dpy ) ) { if ( VendorRelease ( dpy ) >= 60700000 ) { if ( VendorRelease ( dpy ) < 70000000 ) display -> buggy_repeat = TRUE ; if ( VendorRelease ( dpy ) < 70200000 ) display -> buggy_gradients = TRUE ; display -> buggy_pad_reflect = TRUE ; } else { if ( VendorRelease ( dpy ) < 10400000 ) display -> buggy_repeat = TRUE ; if ( VendorRelease ( dpy ) < 10699000 ) display -> buggy_pad_reflect = TRUE ; } } else if ( strstr ( ServerVendor ( dpy ) , " " ) != NULL ) { if ( VendorRelease ( dpy ) <= 40500000 ) display -> buggy_repeat = TRUE ; display -> buggy_gradients = TRUE ; display -> buggy_pad_reflect = TRUE ; } codes = XAddExtension ( dpy ) ; if ( unlikely ( codes == NULL ) ) { device = _cairo_device_create_in_error ( CAIRO_STATUS_NO_MEMORY ) ; free ( display ) ; goto UNLOCK ; } XESetCloseDisplay ( dpy , codes -> extension , _cairo_xlib_close_display ) ; cairo_device_reference ( & display -> base ) ; display -> next = _cairo_xlib_display_list ; _cairo_xlib_display_list = display ; device = & display -> base ; UNLOCK : CAIRO_MUTEX_UNLOCK ( _cairo_xlib_display_mutex ) ; return device ; }
_cairo_xlib_device_create:
 @dpy: the display to create the device for
_cairo_xlib_device_create : @dpy : the display to create the device for
/* 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.
     */ /*
	     * MRU the list
	     */ /* 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.
     */ /* Prior to Render 0.10, there is no protocol support for gradients and
     * we call function stubs instead, which would silently consume the drawing.
     */ /* This buggy_repeat condition is very complicated because there
     * are multiple X server code bases (with multiple versioning
     * schemes within a code base), and multiple bugs.
     *
     * The X servers:
     *
     *    1. The Vendor=="XFree86" code base with release numbers such
     *    as 4.7.0 (VendorRelease==40700000).
     *
     *    2. The Vendor=="X.Org" code base (a descendant of the
     *    XFree86 code base). It originally had things like
     *    VendorRelease==60700000 for release 6.7.0 but then changed
     *    its versioning scheme so that, for example,
     *    VendorRelease==10400000 for the 1.4.0 X server within the
     *    X.Org 7.3 release.
     *
     * The bugs:
     *
     *    1. The original bug that led to the buggy_repeat
     *    workaround. This was a bug that Owen Taylor investigated,
     *    understood well, and characterized against various X
     *    servers. Confirmed X servers with this bug include:
     *
     *		"XFree86" <= 40500000
     *		"X.Org" <= 60802000 (only with old numbering >= 60700000)
     *
     *    2. A separate bug resulting in a crash of the X server when
     *    using cairo's extend-reflect test case, (which, surprisingly
     *    enough was not passing RepeatReflect to the X server, but
     *    instead using RepeatNormal in a workaround). Nobody to date
     *    has understood the bug well, but it appears to be gone as of
     *    the X.Org 1.4.0 server. This bug is coincidentally avoided
     *    by using the same buggy_repeat workaround. Confirmed X
     *    servers with this bug include:
     *
     *		"X.org" == 60900000 (old versioning scheme)
     *		"X.org"  < 10400000 (new numbering scheme)
     *
     *    For the old-versioning-scheme X servers we don't know
     *    exactly when second the bug started, but since bug 1 is
     *    present through 6.8.2 and bug 2 is present in 6.9.0 it seems
     *    safest to just blacklist all old-versioning-scheme X servers,
     *    (just using VendorRelease < 70000000), as buggy_repeat=TRUE.
     */ /* We know that gradients simply do not work in early Xorg servers */ /* And the extended repeat modes were not fixed until much later */ /* Too many bugs in the early drivers */ /* add one for the CloseDisplay */