LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-xlib-display.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 262 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Cairo - a vector graphics library with display and print output
       2             :  *
       3             :  * Copyright © 2007 Chris Wilson
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it either under the terms of the GNU Lesser General Public
       7             :  * License version 2.1 as published by the Free Software Foundation
       8             :  * (the "LGPL") or, at your option, under the terms of the Mozilla
       9             :  * Public License Version 1.1 (the "MPL"). If you do not alter this
      10             :  * notice, a recipient may use your version of this file under either
      11             :  * the MPL or the LGPL.
      12             :  *
      13             :  * You should have received a copy of the LGPL along with this library
      14             :  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
      15             :  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
      16             :  * You should have received a copy of the MPL along with this library
      17             :  * in the file COPYING-MPL-1.1
      18             :  *
      19             :  * The contents of this file are subject to the Mozilla Public License
      20             :  * Version 1.1 (the "License"); you may not use this file except in
      21             :  * compliance with the License. You may obtain a copy of the License at
      22             :  * http://www.mozilla.org/MPL/
      23             :  *
      24             :  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
      25             :  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
      26             :  * the specific language governing rights and limitations.
      27             :  *
      28             :  * The Original Code is the cairo graphics library.
      29             :  *
      30             :  * The Initial Developer of the Original Code is Chris Wilson.
      31             :  *
      32             :  * Contributor(s):
      33             :  *      Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
      34             :  */
      35             : 
      36             : #include "cairoint.h"
      37             : 
      38             : #include "cairo-xlib-private.h"
      39             : #include "cairo-xlib-xrender-private.h"
      40             : #include "cairo-freelist-private.h"
      41             : #include "cairo-error-private.h"
      42             : 
      43             : #include <X11/Xlibint.h>  /* For XESetCloseDisplay */
      44             : 
      45             : typedef int (*cairo_xlib_error_func_t) (Display     *display,
      46             :                                         XErrorEvent *event);
      47             : 
      48             : struct _cairo_xlib_job {
      49             :     cairo_xlib_job_t *next;
      50             :     enum {
      51             :         RESOURCE,
      52             :         WORK
      53             :     } type;
      54             :     union {
      55             :         struct {
      56             :             cairo_xlib_notify_resource_func notify;
      57             :             XID xid;
      58             :         } resource;
      59             :         struct {
      60             :             cairo_xlib_notify_func notify;
      61             :             void *data;
      62             :             void (*destroy) (void *);
      63             :         } work;
      64             :     } func;
      65             : };
      66             : 
      67             : static cairo_xlib_display_t *_cairo_xlib_display_list;
      68             : 
      69             : static void
      70             : _cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
      71             :                                                 cairo_xlib_hook_t *hook);
      72             : 
      73             : static void
      74           0 : _cairo_xlib_call_close_display_hooks (cairo_xlib_display_t *display)
      75             : {
      76             :     cairo_xlib_screen_t *screen;
      77             :     cairo_xlib_hook_t *hook;
      78             : 
      79           0 :     cairo_list_foreach_entry (screen, cairo_xlib_screen_t, &display->screens, link)
      80           0 :         _cairo_xlib_screen_close_display (display, screen);
      81             : 
      82             :     while (TRUE) {
      83           0 :         hook = display->close_display_hooks;
      84           0 :         if (hook == NULL)
      85           0 :             break;
      86             : 
      87           0 :         _cairo_xlib_remove_close_display_hook_internal (display, hook);
      88             : 
      89           0 :         hook->func (display, hook);
      90             :     }
      91           0 :     display->closed = TRUE;
      92           0 : }
      93             : 
      94             : static void
      95           0 : _cairo_xlib_display_finish (void *abstract_display)
      96             : {
      97           0 :     cairo_xlib_display_t *display = abstract_display;
      98             : 
      99           0 :     display->display = NULL;
     100           0 : }
     101             : 
     102             : static void
     103           0 : _cairo_xlib_display_destroy (void *abstract_display)
     104             : {
     105           0 :     cairo_xlib_display_t *display = abstract_display;
     106             : 
     107             :     /* destroy all outstanding notifies */
     108           0 :     while (display->workqueue != NULL) {
     109           0 :         cairo_xlib_job_t *job = display->workqueue;
     110           0 :         display->workqueue = job->next;
     111             : 
     112           0 :         if (job->type == WORK && job->func.work.destroy != NULL)
     113           0 :             job->func.work.destroy (job->func.work.data);
     114             : 
     115           0 :         _cairo_freelist_free (&display->wq_freelist, job);
     116             :     }
     117           0 :     _cairo_freelist_fini (&display->wq_freelist);
     118             : 
     119           0 :     while (! cairo_list_is_empty (&display->screens)) {
     120           0 :         _cairo_xlib_screen_destroy (cairo_list_first_entry (&display->screens,
     121             :                                                             cairo_xlib_screen_t,
     122             :                                                             link));
     123             :     }
     124             : 
     125           0 :     free (display);
     126           0 : }
     127             : 
     128             : static int
     129           0 : _noop_error_handler (Display     *display,
     130             :                      XErrorEvent *event)
     131             : {
     132           0 :     return False;               /* return value is ignored */
     133             : }
     134             : 
     135             : static void
     136           0 : _cairo_xlib_display_notify (cairo_xlib_display_t *display)
     137             : {
     138             :     cairo_xlib_job_t *jobs, *job, *freelist;
     139           0 :     Display *dpy = display->display;
     140             : 
     141             :     /* Optimistic atomic pointer read -- don't care if it is wrong due to
     142             :      * contention as we will check again very shortly.
     143             :      */
     144           0 :     if (display->workqueue == NULL)
     145           0 :         return;
     146             : 
     147           0 :     jobs = display->workqueue;
     148           0 :     while (jobs != NULL) {
     149           0 :         display->workqueue = NULL;
     150             : 
     151             :         /* reverse the list to obtain FIFO order */
     152           0 :         job = NULL;
     153             :         do {
     154           0 :             cairo_xlib_job_t *next = jobs->next;
     155           0 :             jobs->next = job;
     156           0 :             job = jobs;
     157           0 :             jobs = next;
     158           0 :         } while (jobs != NULL);
     159           0 :         freelist = jobs = job;
     160             : 
     161             :         do {
     162           0 :             job = jobs;
     163           0 :             jobs = job->next;
     164             : 
     165           0 :             switch (job->type){
     166             :             case WORK:
     167           0 :                 job->func.work.notify (dpy, job->func.work.data);
     168           0 :                 if (job->func.work.destroy != NULL)
     169           0 :                     job->func.work.destroy (job->func.work.data);
     170           0 :                 break;
     171             : 
     172             :             case RESOURCE:
     173           0 :                 job->func.resource.notify (dpy, job->func.resource.xid);
     174           0 :                 break;
     175             :             }
     176           0 :         } while (jobs != NULL);
     177             : 
     178             :         do {
     179           0 :             job = freelist;
     180           0 :             freelist = job->next;
     181           0 :             _cairo_freelist_free (&display->wq_freelist, job);
     182           0 :         } while (freelist != NULL);
     183             : 
     184           0 :         jobs = display->workqueue;
     185             :     }
     186             : }
     187             : 
     188             : static int
     189           0 : _cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
     190             : {
     191             :     cairo_xlib_display_t *display, **prev, *next;
     192             :     cairo_xlib_error_func_t old_handler;
     193             : 
     194           0 :     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
     195           0 :     for (display = _cairo_xlib_display_list; display; display = display->next)
     196           0 :         if (display->display == dpy)
     197           0 :             break;
     198           0 :     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
     199           0 :     if (display == NULL)
     200           0 :         return 0;
     201             : 
     202           0 :     if (! cairo_device_acquire (&display->base)) {
     203             :       /* protect the notifies from triggering XErrors */
     204           0 :       XSync (dpy, False);
     205           0 :       old_handler = XSetErrorHandler (_noop_error_handler);
     206             : 
     207           0 :       _cairo_xlib_display_notify (display);
     208           0 :       _cairo_xlib_call_close_display_hooks (display);
     209             : 
     210             :       /* catch any that arrived before marking the display as closed */
     211           0 :       _cairo_xlib_display_notify (display);
     212             : 
     213           0 :       XSync (dpy, False);
     214           0 :       XSetErrorHandler (old_handler);
     215             : 
     216           0 :       cairo_device_release (&display->base);
     217             :     }
     218             : 
     219             :     /*
     220             :      * Unhook from the global list
     221             :      */
     222           0 :     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
     223           0 :     prev = &_cairo_xlib_display_list;
     224           0 :     for (display = _cairo_xlib_display_list; display; display = next) {
     225           0 :         next = display->next;
     226           0 :         if (display->display == dpy) {
     227           0 :             *prev = next;
     228           0 :             break;
     229             :         } else
     230           0 :             prev = &display->next;
     231             :     }
     232           0 :     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
     233             : 
     234           0 :     assert (display != NULL);
     235             : 
     236           0 :     cairo_device_finish (&display->base);
     237           0 :     cairo_device_destroy (&display->base);
     238             : 
     239             :     /* Return value in accordance with requirements of
     240             :      * XESetCloseDisplay */
     241           0 :     return 0;
     242             : }
     243             : 
     244             : static const cairo_device_backend_t _cairo_xlib_device_backend = {
     245             :     CAIRO_DEVICE_TYPE_XLIB,
     246             : 
     247             :     NULL,
     248             :     NULL,
     249             : 
     250             :     NULL, /* flush */
     251             :     _cairo_xlib_display_finish,
     252             :     _cairo_xlib_display_destroy,
     253             : };
     254             : 
     255             : /**
     256             :  * cairo_xlib_device_create:
     257             :  * @dpy: the display to create the device for
     258             :  *
     259             :  * Gets the device belonging to @dpy, or creates it if it doesn't exist yet.
     260             :  *
     261             :  * Returns: the device belonging to @dpy
     262             :  **/
     263             : cairo_device_t *
     264           0 : _cairo_xlib_device_create (Display *dpy)
     265             : {
     266             :     cairo_xlib_display_t *display;
     267             :     cairo_xlib_display_t **prev;
     268             :     cairo_device_t *device;
     269             :     XExtCodes *codes;
     270             :     const char *env;
     271             : 
     272             :     static int buggy_repeat_force = -1;
     273             : 
     274             :     CAIRO_MUTEX_INITIALIZE ();
     275             : 
     276             :     /* There is an apparent deadlock between this mutex and the
     277             :      * mutex for the display, but it's actually safe. For the
     278             :      * app to call XCloseDisplay() while any other thread is
     279             :      * inside this function would be an error in the logic
     280             :      * app, and the CloseDisplay hook is the only other place we
     281             :      * acquire this mutex.
     282             :      */
     283           0 :     CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
     284             : 
     285           0 :     for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next)
     286             :     {
     287           0 :         if (display->display == dpy) {
     288             :             /*
     289             :              * MRU the list
     290             :              */
     291           0 :             if (prev != &_cairo_xlib_display_list) {
     292           0 :                 *prev = display->next;
     293           0 :                 display->next = _cairo_xlib_display_list;
     294           0 :                 _cairo_xlib_display_list = display;
     295             :             }
     296           0 :             device = cairo_device_reference (&display->base);
     297           0 :             goto UNLOCK;
     298             :         }
     299             :     }
     300             : 
     301           0 :     display = malloc (sizeof (cairo_xlib_display_t));
     302           0 :     if (unlikely (display == NULL)) {
     303           0 :         device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
     304           0 :         goto UNLOCK;
     305             :     }
     306             : 
     307             :     /* Xlib calls out to the extension close_display hooks in LIFO
     308             :      * order. So we have to ensure that all extensions that we depend
     309             :      * on in our close_display hook are properly initialized before we
     310             :      * add our hook. For now, that means Render, so we call into its
     311             :      * QueryVersion function to ensure it gets initialized.
     312             :      */
     313           0 :     display->render_major = display->render_minor = -1;
     314           0 :     XRenderQueryVersion (dpy, &display->render_major, &display->render_minor);
     315           0 :     env = getenv ("CAIRO_DEBUG");
     316           0 :     if (env != NULL && (env = strstr (env, "xrender-version=")) != NULL) {
     317             :         int max_render_major, max_render_minor;
     318             : 
     319           0 :         env += sizeof ("xrender-version=") - 1;
     320           0 :         if (sscanf (env, "%d.%d", &max_render_major, &max_render_minor) != 2)
     321           0 :             max_render_major = max_render_minor = -1;
     322             : 
     323           0 :         if (max_render_major < display->render_major ||
     324           0 :             (max_render_major == display->render_major &&
     325           0 :              max_render_minor < display->render_minor))
     326             :         {
     327           0 :             display->render_major = max_render_major;
     328           0 :             display->render_minor = max_render_minor;
     329             :         }
     330             :     }
     331             : 
     332           0 :     codes = XAddExtension (dpy);
     333           0 :     if (unlikely (codes == NULL)) {
     334           0 :         device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
     335           0 :         free (display);
     336           0 :         goto UNLOCK;
     337             :     }
     338             : 
     339           0 :     _cairo_device_init (&display->base, &_cairo_xlib_device_backend);
     340             : 
     341           0 :     XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
     342             : 
     343           0 :     _cairo_freelist_init (&display->wq_freelist, sizeof (cairo_xlib_job_t));
     344             : 
     345           0 :     cairo_device_reference (&display->base); /* add one for the CloseDisplay */
     346           0 :     display->display = dpy;
     347           0 :     cairo_list_init (&display->screens);
     348           0 :     display->workqueue = NULL;
     349           0 :     display->close_display_hooks = NULL;
     350           0 :     display->closed = FALSE;
     351             : 
     352           0 :     memset (display->cached_xrender_formats, 0,
     353             :             sizeof (display->cached_xrender_formats));
     354             : 
     355             :     /* Prior to Render 0.10, there is no protocol support for gradients and
     356             :      * we call function stubs instead, which would silently consume the drawing.
     357             :      */
     358             : #if RENDER_MAJOR == 0 && RENDER_MINOR < 10
     359             :     display->buggy_gradients = TRUE;
     360             : #else
     361           0 :     display->buggy_gradients = FALSE;
     362             : #endif
     363           0 :     display->buggy_pad_reflect = FALSE;
     364           0 :     display->buggy_repeat = FALSE;
     365             : 
     366             :     /* This buggy_repeat condition is very complicated because there
     367             :      * are multiple X server code bases (with multiple versioning
     368             :      * schemes within a code base), and multiple bugs.
     369             :      *
     370             :      * The X servers:
     371             :      *
     372             :      *    1. The Vendor=="XFree86" code base with release numbers such
     373             :      *    as 4.7.0 (VendorRelease==40700000).
     374             :      *
     375             :      *    2. The Vendor=="X.Org" code base (a descendant of the
     376             :      *    XFree86 code base). It originally had things like
     377             :      *    VendorRelease==60700000 for release 6.7.0 but then changed
     378             :      *    its versioning scheme so that, for example,
     379             :      *    VendorRelease==10400000 for the 1.4.0 X server within the
     380             :      *    X.Org 7.3 release.
     381             :      *
     382             :      * The bugs:
     383             :      *
     384             :      *    1. The original bug that led to the buggy_repeat
     385             :      *    workaround. This was a bug that Owen Taylor investigated,
     386             :      *    understood well, and characterized against carious X
     387             :      *    servers. Confirmed X servers with this bug include:
     388             :      *
     389             :      *          "XFree86" <= 40500000
     390             :      *          "X.Org" <= 60802000 (only with old numbering >= 60700000)
     391             :      *
     392             :      *    2. A separate bug resulting in a crash of the X server when
     393             :      *    using cairo's extend-reflect test case, (which, surprisingly
     394             :      *    enough was not passing RepeatReflect to the X server, but
     395             :      *    instead using RepeatNormal in a workaround). Nobody to date
     396             :      *    has understood the bug well, but it appears to be gone as of
     397             :      *    the X.Org 1.4.0 server. This bug is coincidentally avoided
     398             :      *    by using the same buggy_repeat workaround. Confirmed X
     399             :      *    servers with this bug include:
     400             :      *
     401             :      *          "X.org" == 60900000 (old versioning scheme)
     402             :      *          "X.org"  < 10400000 (new numbering scheme)
     403             :      *
     404             :      *    For the old-versioning-scheme X servers we don't know
     405             :      *    exactly when second the bug started, but since bug 1 is
     406             :      *    present through 6.8.2 and bug 2 is present in 6.9.0 it seems
     407             :      *    safest to just blacklist all old-versioning-scheme X servers,
     408             :      *    (just using VendorRelease < 70000000), as buggy_repeat=TRUE.
     409             :      */
     410           0 :     if (strstr (ServerVendor (dpy), "X.Org") != NULL) {
     411           0 :         if (VendorRelease (dpy) >= 60700000) {
     412           0 :             if (VendorRelease (dpy) < 70000000)
     413           0 :                 display->buggy_repeat = TRUE;
     414             : 
     415             :             /* We know that gradients simply do not work in early Xorg servers */
     416           0 :             if (VendorRelease (dpy) < 70200000)
     417           0 :                 display->buggy_gradients = TRUE;
     418             : 
     419             :             /* And the extended repeat modes were not fixed until much later */
     420           0 :             display->buggy_pad_reflect = TRUE;
     421             :         } else {
     422           0 :             if (VendorRelease (dpy) < 10400000)
     423           0 :                 display->buggy_repeat = TRUE;
     424             : 
     425             :             /* Too many bugs in the early drivers */
     426           0 :             if (VendorRelease (dpy) < 10699000)
     427           0 :                 display->buggy_pad_reflect = TRUE;
     428             :         }
     429           0 :     } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
     430           0 :         if (VendorRelease (dpy) <= 40500000)
     431           0 :             display->buggy_repeat = TRUE;
     432             : 
     433           0 :         display->buggy_gradients = TRUE;
     434           0 :         display->buggy_pad_reflect = TRUE;
     435             :     }
     436             : 
     437             :     /* gradients don't seem to work */
     438           0 :     display->buggy_gradients = TRUE;
     439             : 
     440             : 
     441             :     /* XXX workaround; see https://bugzilla.mozilla.org/show_bug.cgi?id=413583 */
     442             :     /* If buggy_repeat_force == -1, then initialize.
     443             :      *    - set to -2, meaning "nothing was specified", and we trust the above detection.
     444             :      *    - if MOZ_CAIRO_BUGGY_REPEAT is '0' (exactly), then force buggy repeat off
     445             :      *    - if MOZ_CAIRO_BUGGY_REPEAT is '1' (exactly), then force buggy repeat on
     446             :      */
     447           0 :     if (buggy_repeat_force == -1) {
     448           0 :         const char *flag = getenv("MOZ_CAIRO_FORCE_BUGGY_REPEAT");
     449             : 
     450           0 :         buggy_repeat_force = -2;
     451             : 
     452           0 :         if (flag && flag[0] == '0')
     453           0 :             buggy_repeat_force = 0;
     454           0 :         else if (flag && flag[0] == '1')
     455           0 :             buggy_repeat_force = 1;
     456             :     }
     457             : 
     458           0 :     if (buggy_repeat_force != -2)
     459           0 :         display->buggy_repeat = (buggy_repeat_force == 1);
     460             : 
     461           0 :     display->next = _cairo_xlib_display_list;
     462           0 :     _cairo_xlib_display_list = display;
     463             : 
     464           0 :     device = &display->base;
     465             : 
     466             : UNLOCK:
     467           0 :     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
     468           0 :     return device;
     469             : }
     470             : 
     471             : void
     472           0 : _cairo_xlib_add_close_display_hook (cairo_xlib_display_t        *display,
     473             :                                     cairo_xlib_hook_t           *hook)
     474             : {
     475           0 :     hook->prev = NULL;
     476           0 :     hook->next = display->close_display_hooks;
     477           0 :     if (hook->next != NULL)
     478           0 :         hook->next->prev = hook;
     479           0 :     display->close_display_hooks = hook;
     480           0 : }
     481             : 
     482             : static void
     483           0 : _cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
     484             :                                                 cairo_xlib_hook_t *hook)
     485             : {
     486           0 :     if (display->close_display_hooks == hook)
     487           0 :         display->close_display_hooks = hook->next;
     488           0 :     else if (hook->prev != NULL)
     489           0 :         hook->prev->next = hook->next;
     490             : 
     491           0 :     if (hook->next != NULL)
     492           0 :         hook->next->prev = hook->prev;
     493             : 
     494           0 :     hook->prev = NULL;
     495           0 :     hook->next = NULL;
     496           0 : }
     497             : 
     498             : void
     499           0 : _cairo_xlib_remove_close_display_hook (cairo_xlib_display_t     *display,
     500             :                                        cairo_xlib_hook_t        *hook)
     501             : {
     502           0 :     _cairo_xlib_remove_close_display_hook_internal (display, hook);
     503           0 : }
     504             : 
     505             : cairo_status_t
     506           0 : _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
     507             :                                     cairo_xlib_notify_resource_func notify,
     508             :                                     XID xid)
     509             : {
     510             :     cairo_xlib_job_t *job;
     511           0 :     cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
     512             : 
     513           0 :     if (display->closed == FALSE) {
     514           0 :         job = _cairo_freelist_alloc (&display->wq_freelist);
     515           0 :         if (job != NULL) {
     516           0 :             job->type = RESOURCE;
     517           0 :             job->func.resource.xid = xid;
     518           0 :             job->func.resource.notify = notify;
     519             : 
     520           0 :             job->next = display->workqueue;
     521           0 :             display->workqueue = job;
     522             : 
     523           0 :             status = CAIRO_STATUS_SUCCESS;
     524             :         }
     525             :     }
     526             : 
     527           0 :     return status;
     528             : }
     529             : 
     530             : cairo_status_t
     531           0 : _cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
     532             :                                 cairo_xlib_notify_func notify,
     533             :                                 void *data,
     534             :                                 void (*destroy) (void *))
     535             : {
     536             :     cairo_xlib_job_t *job;
     537           0 :     cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
     538             : 
     539           0 :     if (display->closed == FALSE) {
     540           0 :         job = _cairo_freelist_alloc (&display->wq_freelist);
     541           0 :         if (job != NULL) {
     542           0 :             job->type = WORK;
     543           0 :             job->func.work.data    = data;
     544           0 :             job->func.work.notify  = notify;
     545           0 :             job->func.work.destroy = destroy;
     546             : 
     547           0 :             job->next = display->workqueue;
     548           0 :             display->workqueue = job;
     549             : 
     550           0 :             status = CAIRO_STATUS_SUCCESS;
     551             :         }
     552             :     }
     553             : 
     554           0 :     return status;
     555             : }
     556             : 
     557             : cairo_status_t
     558           0 : _cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **display)
     559             : {
     560             :     cairo_status_t status;
     561             : 
     562           0 :     status = cairo_device_acquire (device);
     563           0 :     if (status)
     564           0 :         return status;
     565             : 
     566           0 :     *display = (cairo_xlib_display_t *) device;
     567           0 :     _cairo_xlib_display_notify (*display);
     568           0 :     return status;
     569             : }
     570             : 
     571             : XRenderPictFormat *
     572           0 : _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t    *display,
     573             :                                         cairo_format_t           format)
     574             : {
     575             :     XRenderPictFormat *xrender_format;
     576             : 
     577             : #if ! ATOMIC_OP_NEEDS_MEMORY_BARRIER
     578           0 :     xrender_format = display->cached_xrender_formats[format];
     579           0 :     if (likely (xrender_format != NULL))
     580           0 :         return xrender_format;
     581             : #endif
     582             : 
     583           0 :     xrender_format = display->cached_xrender_formats[format];
     584           0 :     if (xrender_format == NULL) {
     585             :         int pict_format;
     586             : 
     587           0 :         switch (format) {
     588             :         case CAIRO_FORMAT_A1:
     589           0 :             pict_format = PictStandardA1; break;
     590             :         case CAIRO_FORMAT_A8:
     591           0 :             pict_format = PictStandardA8; break;
     592             :         case CAIRO_FORMAT_RGB24:
     593           0 :             pict_format = PictStandardRGB24; break;
     594             :         case CAIRO_FORMAT_RGB16_565: {
     595           0 :             Visual *visual = NULL;
     596           0 :             Screen *screen = DefaultScreenOfDisplay(display->display);
     597             :             int j;
     598           0 :             for (j = 0; j < screen->ndepths; j++) {
     599           0 :                 Depth *d = &screen->depths[j];
     600           0 :                 if (d->depth == 16 && d->nvisuals && &d->visuals[0]) {
     601           0 :                     if (d->visuals[0].red_mask   == 0xf800 &&
     602           0 :                         d->visuals[0].green_mask == 0x7e0 &&
     603           0 :                         d->visuals[0].blue_mask  == 0x1f)
     604           0 :                         visual = &d->visuals[0];
     605           0 :                     break;
     606             :                 }
     607             :             }
     608           0 :             if (!visual)
     609           0 :                 return NULL;
     610           0 :             xrender_format = XRenderFindVisualFormat(display->display, visual);
     611           0 :             break;
     612             :         }
     613             :         case CAIRO_FORMAT_INVALID:
     614             :         default:
     615           0 :             ASSERT_NOT_REACHED;
     616             :         case CAIRO_FORMAT_ARGB32:
     617           0 :             pict_format = PictStandardARGB32; break;
     618             :         }
     619           0 :         if (!xrender_format)
     620           0 :             xrender_format = XRenderFindStandardFormat (display->display,
     621             :                                                         pict_format);
     622           0 :         display->cached_xrender_formats[format] = xrender_format;
     623             :     }
     624             : 
     625           0 :     return xrender_format;
     626             : }
     627             : 
     628             : cairo_xlib_screen_t *
     629           0 : _cairo_xlib_display_get_screen (cairo_xlib_display_t *display,
     630             :                                 Screen *screen)
     631             : {
     632             :     cairo_xlib_screen_t *info;
     633             : 
     634           0 :     cairo_list_foreach_entry (info, cairo_xlib_screen_t, &display->screens, link) {
     635           0 :         if (info->screen == screen) {
     636           0 :             if (display->screens.next != &info->link)
     637           0 :                 cairo_list_move (&info->link, &display->screens);
     638           0 :             return info;
     639             :         }
     640             :     }
     641             : 
     642           0 :     return NULL;
     643             : }
     644             : 
     645             : void
     646           0 : _cairo_xlib_display_get_xrender_version (cairo_xlib_display_t *display,
     647             :                                          int *major, int *minor)
     648             : {
     649           0 :     *major = display->render_major;
     650           0 :     *minor = display->render_minor;
     651           0 : }
     652             : 
     653             : cairo_bool_t
     654           0 : _cairo_xlib_display_has_repeat (cairo_device_t *device)
     655             : {
     656           0 :     return ! ((cairo_xlib_display_t *) device)->buggy_repeat;
     657             : }
     658             : 
     659             : cairo_bool_t
     660           0 : _cairo_xlib_display_has_reflect (cairo_device_t *device)
     661             : {
     662           0 :     return ! ((cairo_xlib_display_t *) device)->buggy_pad_reflect;
     663             : }
     664             : 
     665             : cairo_bool_t
     666           0 : _cairo_xlib_display_has_gradients (cairo_device_t *device)
     667             : {
     668           0 :     return ! ((cairo_xlib_display_t *) device)->buggy_gradients;
     669             : }

Generated by: LCOV version 1.13