LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-xlib-display.c (source / functions) Found Hit Coverage
Test: app.info Lines: 256 0 0.0 %
Date: 2012-06-02 Functions: 19 0 0.0 %

       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                 :             break;
      86                 : 
      87               0 :         _cairo_xlib_remove_close_display_hook_internal (display, hook);
      88                 : 
      89               0 :         hook->func (display, hook);
      90               0 :     }
      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                 :     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                 :     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                 :     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                 :     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                 :     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                 : #ifndef MOZ_EGL_XRENDER_COMPOSITE
     426                 :             /* Too many bugs in the early drivers */
     427               0 :             if (VendorRelease (dpy) < 10699000)
     428               0 :                 display->buggy_pad_reflect = TRUE;
     429                 : #endif
     430                 :         }
     431               0 :     } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
     432               0 :         if (VendorRelease (dpy) <= 40500000)
     433               0 :             display->buggy_repeat = TRUE;
     434                 : 
     435               0 :         display->buggy_gradients = TRUE;
     436               0 :         display->buggy_pad_reflect = TRUE;
     437                 :     }
     438                 : 
     439                 :     /* gradients don't seem to work */
     440               0 :     display->buggy_gradients = TRUE;
     441                 : 
     442                 : 
     443                 :     /* XXX workaround; see https://bugzilla.mozilla.org/show_bug.cgi?id=413583 */
     444                 :     /* If buggy_repeat_force == -1, then initialize.
     445                 :      *    - set to -2, meaning "nothing was specified", and we trust the above detection.
     446                 :      *    - if MOZ_CAIRO_BUGGY_REPEAT is '0' (exactly), then force buggy repeat off
     447                 :      *    - if MOZ_CAIRO_BUGGY_REPEAT is '1' (exactly), then force buggy repeat on
     448                 :      */
     449               0 :     if (buggy_repeat_force == -1) {
     450               0 :         const char *flag = getenv("MOZ_CAIRO_FORCE_BUGGY_REPEAT");
     451                 : 
     452               0 :         buggy_repeat_force = -2;
     453                 : 
     454               0 :         if (flag && flag[0] == '0')
     455               0 :             buggy_repeat_force = 0;
     456               0 :         else if (flag && flag[0] == '1')
     457               0 :             buggy_repeat_force = 1;
     458                 :     }
     459                 : 
     460               0 :     if (buggy_repeat_force != -2)
     461               0 :         display->buggy_repeat = (buggy_repeat_force == 1);
     462                 : 
     463               0 :     display->next = _cairo_xlib_display_list;
     464               0 :     _cairo_xlib_display_list = display;
     465                 : 
     466               0 :     device = &display->base;
     467                 : 
     468                 : UNLOCK:
     469                 :     CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
     470               0 :     return device;
     471                 : }
     472                 : 
     473                 : void
     474               0 : _cairo_xlib_add_close_display_hook (cairo_xlib_display_t        *display,
     475                 :                                     cairo_xlib_hook_t           *hook)
     476                 : {
     477               0 :     hook->prev = NULL;
     478               0 :     hook->next = display->close_display_hooks;
     479               0 :     if (hook->next != NULL)
     480               0 :         hook->next->prev = hook;
     481               0 :     display->close_display_hooks = hook;
     482               0 : }
     483                 : 
     484                 : static void
     485               0 : _cairo_xlib_remove_close_display_hook_internal (cairo_xlib_display_t *display,
     486                 :                                                 cairo_xlib_hook_t *hook)
     487                 : {
     488               0 :     if (display->close_display_hooks == hook)
     489               0 :         display->close_display_hooks = hook->next;
     490               0 :     else if (hook->prev != NULL)
     491               0 :         hook->prev->next = hook->next;
     492                 : 
     493               0 :     if (hook->next != NULL)
     494               0 :         hook->next->prev = hook->prev;
     495                 : 
     496               0 :     hook->prev = NULL;
     497               0 :     hook->next = NULL;
     498               0 : }
     499                 : 
     500                 : void
     501               0 : _cairo_xlib_remove_close_display_hook (cairo_xlib_display_t     *display,
     502                 :                                        cairo_xlib_hook_t        *hook)
     503                 : {
     504               0 :     _cairo_xlib_remove_close_display_hook_internal (display, hook);
     505               0 : }
     506                 : 
     507                 : cairo_status_t
     508               0 : _cairo_xlib_display_queue_resource (cairo_xlib_display_t *display,
     509                 :                                     cairo_xlib_notify_resource_func notify,
     510                 :                                     XID xid)
     511                 : {
     512                 :     cairo_xlib_job_t *job;
     513               0 :     cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
     514                 : 
     515               0 :     if (display->closed == FALSE) {
     516               0 :         job = _cairo_freelist_alloc (&display->wq_freelist);
     517               0 :         if (job != NULL) {
     518               0 :             job->type = RESOURCE;
     519               0 :             job->func.resource.xid = xid;
     520               0 :             job->func.resource.notify = notify;
     521                 : 
     522               0 :             job->next = display->workqueue;
     523               0 :             display->workqueue = job;
     524                 : 
     525               0 :             status = CAIRO_STATUS_SUCCESS;
     526                 :         }
     527                 :     }
     528                 : 
     529               0 :     return status;
     530                 : }
     531                 : 
     532                 : cairo_status_t
     533               0 : _cairo_xlib_display_queue_work (cairo_xlib_display_t *display,
     534                 :                                 cairo_xlib_notify_func notify,
     535                 :                                 void *data,
     536                 :                                 void (*destroy) (void *))
     537                 : {
     538                 :     cairo_xlib_job_t *job;
     539               0 :     cairo_status_t status = CAIRO_STATUS_NO_MEMORY;
     540                 : 
     541               0 :     if (display->closed == FALSE) {
     542               0 :         job = _cairo_freelist_alloc (&display->wq_freelist);
     543               0 :         if (job != NULL) {
     544               0 :             job->type = WORK;
     545               0 :             job->func.work.data    = data;
     546               0 :             job->func.work.notify  = notify;
     547               0 :             job->func.work.destroy = destroy;
     548                 : 
     549               0 :             job->next = display->workqueue;
     550               0 :             display->workqueue = job;
     551                 : 
     552               0 :             status = CAIRO_STATUS_SUCCESS;
     553                 :         }
     554                 :     }
     555                 : 
     556               0 :     return status;
     557                 : }
     558                 : 
     559                 : cairo_status_t
     560               0 : _cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **display)
     561                 : {
     562                 :     cairo_status_t status;
     563                 : 
     564               0 :     status = cairo_device_acquire (device);
     565               0 :     if (status)
     566               0 :         return status;
     567                 : 
     568               0 :     *display = (cairo_xlib_display_t *) device;
     569               0 :     _cairo_xlib_display_notify (*display);
     570               0 :     return status;
     571                 : }
     572                 : 
     573                 : XRenderPictFormat *
     574               0 : _cairo_xlib_display_get_xrender_format (cairo_xlib_display_t    *display,
     575                 :                                         cairo_format_t           format)
     576                 : {
     577                 :     XRenderPictFormat *xrender_format;
     578                 : 
     579                 : #if ! ATOMIC_OP_NEEDS_MEMORY_BARRIER
     580               0 :     xrender_format = display->cached_xrender_formats[format];
     581               0 :     if (likely (xrender_format != NULL))
     582               0 :         return xrender_format;
     583                 : #endif
     584                 : 
     585               0 :     xrender_format = display->cached_xrender_formats[format];
     586               0 :     if (xrender_format == NULL) {
     587                 :         int pict_format;
     588                 : 
     589               0 :         switch (format) {
     590                 :         case CAIRO_FORMAT_A1:
     591               0 :             pict_format = PictStandardA1; break;
     592                 :         case CAIRO_FORMAT_A8:
     593               0 :             pict_format = PictStandardA8; break;
     594                 :         case CAIRO_FORMAT_RGB24:
     595               0 :             pict_format = PictStandardRGB24; break;
     596                 :         case CAIRO_FORMAT_RGB16_565: {
     597               0 :             Visual *visual = NULL;
     598               0 :             Screen *screen = DefaultScreenOfDisplay(display->display);
     599                 :             int j;
     600               0 :             for (j = 0; j < screen->ndepths; j++) {
     601               0 :                 Depth *d = &screen->depths[j];
     602               0 :                 if (d->depth == 16 && d->nvisuals && &d->visuals[0]) {
     603               0 :                     if (d->visuals[0].red_mask   == 0xf800 &&
     604               0 :                         d->visuals[0].green_mask == 0x7e0 &&
     605               0 :                         d->visuals[0].blue_mask  == 0x1f)
     606               0 :                         visual = &d->visuals[0];
     607               0 :                     break;
     608                 :                 }
     609                 :             }
     610               0 :             if (!visual)
     611               0 :                 return NULL;
     612               0 :             xrender_format = XRenderFindVisualFormat(display->display, visual);
     613               0 :             break;
     614                 :         }
     615                 :         case CAIRO_FORMAT_INVALID:
     616                 :         default:
     617               0 :             ASSERT_NOT_REACHED;
     618                 :         case CAIRO_FORMAT_ARGB32:
     619               0 :             pict_format = PictStandardARGB32; break;
     620                 :         }
     621               0 :         if (!xrender_format)
     622               0 :             xrender_format = XRenderFindStandardFormat (display->display,
     623                 :                                                         pict_format);
     624               0 :         display->cached_xrender_formats[format] = xrender_format;
     625                 :     }
     626                 : 
     627               0 :     return xrender_format;
     628                 : }
     629                 : 
     630                 : cairo_xlib_screen_t *
     631               0 : _cairo_xlib_display_get_screen (cairo_xlib_display_t *display,
     632                 :                                 Screen *screen)
     633                 : {
     634                 :     cairo_xlib_screen_t *info;
     635                 : 
     636               0 :     cairo_list_foreach_entry (info, cairo_xlib_screen_t, &display->screens, link) {
     637               0 :         if (info->screen == screen) {
     638               0 :             if (display->screens.next != &info->link)
     639               0 :                 cairo_list_move (&info->link, &display->screens);
     640               0 :             return info;
     641                 :         }
     642                 :     }
     643                 : 
     644               0 :     return NULL;
     645                 : }
     646                 : 
     647                 : void
     648               0 : _cairo_xlib_display_get_xrender_version (cairo_xlib_display_t *display,
     649                 :                                          int *major, int *minor)
     650                 : {
     651               0 :     *major = display->render_major;
     652               0 :     *minor = display->render_minor;
     653               0 : }
     654                 : 
     655                 : cairo_bool_t
     656               0 : _cairo_xlib_display_has_repeat (cairo_device_t *device)
     657                 : {
     658               0 :     return ! ((cairo_xlib_display_t *) device)->buggy_repeat;
     659                 : }
     660                 : 
     661                 : cairo_bool_t
     662               0 : _cairo_xlib_display_has_reflect (cairo_device_t *device)
     663                 : {
     664               0 :     return ! ((cairo_xlib_display_t *) device)->buggy_pad_reflect;
     665                 : }
     666                 : 
     667                 : cairo_bool_t
     668               0 : _cairo_xlib_display_has_gradients (cairo_device_t *device)
     669                 : {
     670               0 :     return ! ((cairo_xlib_display_t *) device)->buggy_gradients;
     671                 : }

Generated by: LCOV version 1.7