Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  cairo-xlib-display.c   Sprache: C

 
/* Cairo - a vector graphics library with display and print output
 *
 * Copyright © 2007 Chris Wilson
 *
 * This library is free software; you can redistribute it and/or
 * modify it either under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 * (the "LGPL") or, at your option, under the terms of the Mozilla
 * Public License Version 1.1 (the "MPL"). If you do not alter this
 * notice, a recipient may use your version of this file under either
 * the MPL or the LGPL.
 *
 * You should have received a copy of the LGPL along with this library
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
 * You should have received a copy of the MPL along with this library
 * in the file COPYING-MPL-1.1
 *
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
 * the specific language governing rights and limitations.
 *
 * The Original Code is the cairo graphics library.
 *
 * The Initial Developer of the Original Code is Chris Wilson.
 *
 * Contributor(s):
 * Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
 */


#include "cairoint.h"

#if !CAIRO_HAS_XLIB_XCB_FUNCTIONS

#include "cairo-xlib-private.h"
#include "cairo-xlib-xrender-private.h"
#include "cairo-freelist-private.h"
#include "cairo-error-private.h"
#include "cairo-list-inline.h"

#include <X11/Xlibint.h> /* For XESetCloseDisplay */

typedef int (*cairo_xlib_error_func_t) (Display     *display,
     XErrorEvent *event);

static cairo_xlib_display_t *_cairo_xlib_display_list;

static int
_noop_error_handler (Display     *display,
       XErrorEvent *event)
{
    return False;  /* return value is ignored */
}

static void
_cairo_xlib_display_finish (void *abstract_display)
{
    cairo_xlib_display_t *display = abstract_display;
    Display *dpy = display->display;

    _cairo_xlib_display_fini_shm (display);

    if (! cairo_device_acquire (&display->base)) {
 cairo_xlib_error_func_t old_handler;

 /* protect the notifies from triggering XErrors */
 XSync (dpy, False);
 old_handler = XSetErrorHandler (_noop_error_handler);

 while (! cairo_list_is_empty (&display->fonts)) {
     _cairo_xlib_font_close (cairo_list_first_entry (&display->fonts,
           cairo_xlib_font_t,
           link));
 }

 while (! cairo_list_is_empty (&display->screens)) {
     _cairo_xlib_screen_destroy (display,
     cairo_list_first_entry (&display->screens,
        cairo_xlib_screen_t,
        link));
 }

 XSync (dpy, False);
 XSetErrorHandler (old_handler);

 cairo_device_release (&display->base);
    }
}

static void
_cairo_xlib_display_destroy (void *abstract_display)
{
    cairo_xlib_display_t *display = abstract_display;

    free (display);
}

static int
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
{
    cairo_xlib_display_t *display, **prev, *next;

    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
    for (display = _cairo_xlib_display_list; display; display = display->next)
 if (display->display == dpy)
     break;
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
    if (display == NULL)
 return 0;

    cairo_device_finish (&display->base);

    /*
     * Unhook from the global list
     */

    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
    prev = &_cairo_xlib_display_list;
    for (display = _cairo_xlib_display_list; display; display = next) {
 next = display->next;
 if (display->display == dpy) {
     *prev = next;
     break;
 } else
     prev = &display->next;
    }
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);

    display->display = NULL; /* catch any later invalid access */
    cairo_device_destroy (&display->base);

    /* Return value in accordance with requirements of
     * XESetCloseDisplay */

    return 0;
}

static const cairo_device_backend_t _cairo_xlib_device_backend = {
    CAIRO_DEVICE_TYPE_XLIB,

    NULL,
    NULL,

    NULL, /* flush */
    _cairo_xlib_display_finish,
    _cairo_xlib_display_destroy,
};

static void _cairo_xlib_display_select_compositor (cairo_xlib_display_t *display)
{
#if 1
    if (display->render_major > 0 || display->render_minor >= 4)
 display->compositor = _cairo_xlib_traps_compositor_get ();
    else if (display->render_major > 0 || display->render_minor >= 0)
 display->compositor = _cairo_xlib_mask_compositor_get ();
    else
 display->compositor = _cairo_xlib_core_compositor_get ();
#else
    display->compositor = _cairo_xlib_fallback_compositor_get ();
#endif
}

/**
 * _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
 **/

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_status_t
_cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **display)
{
    cairo_status_t status;

    status = cairo_device_acquire (device);
    if (status)
        return status;

    *display = (cairo_xlib_display_t *) device;
    return CAIRO_STATUS_SUCCESS;
}

XRenderPictFormat *
_cairo_xlib_display_get_xrender_format_for_pixman(cairo_xlib_display_t *display,
        pixman_format_code_t format)
{
    Display *dpy = display->display;
    XRenderPictFormat tmpl;
    int mask;

    /* No equivalent in X11 yet. */
    if (format == PIXMAN_rgba_float || format == PIXMAN_rgb_float)
 return NULL;

#define MASK(x) ((1<<(x))-1)

    tmpl.depth = PIXMAN_FORMAT_DEPTH(format);
    mask = PictFormatType | PictFormatDepth;

    switch (PIXMAN_FORMAT_TYPE(format)) {
    case PIXMAN_TYPE_ARGB:
 tmpl.type = PictTypeDirect;

 tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
 if (PIXMAN_FORMAT_A(format))
     tmpl.direct.alpha = (PIXMAN_FORMAT_R(format) +
     PIXMAN_FORMAT_G(format) +
     PIXMAN_FORMAT_B(format));

 tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
 tmpl.direct.red = (PIXMAN_FORMAT_G(format) +
      PIXMAN_FORMAT_B(format));

 tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
 tmpl.direct.green = PIXMAN_FORMAT_B(format);

 tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
 tmpl.direct.blue = 0;

 mask |= PictFormatRed | PictFormatRedMask;
 mask |= PictFormatGreen | PictFormatGreenMask;
 mask |= PictFormatBlue | PictFormatBlueMask;
 mask |= PictFormatAlpha | PictFormatAlphaMask;
 break;

    case PIXMAN_TYPE_ABGR:
 tmpl.type = PictTypeDirect;

 tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
 if (tmpl.direct.alphaMask)
     tmpl.direct.alpha = (PIXMAN_FORMAT_B(format) +
     PIXMAN_FORMAT_G(format) +
     PIXMAN_FORMAT_R(format));

 tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
 tmpl.direct.blue = (PIXMAN_FORMAT_G(format) +
       PIXMAN_FORMAT_R(format));

 tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
 tmpl.direct.green = PIXMAN_FORMAT_R(format);

 tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
 tmpl.direct.red = 0;

 mask |= PictFormatRed | PictFormatRedMask;
 mask |= PictFormatGreen | PictFormatGreenMask;
 mask |= PictFormatBlue | PictFormatBlueMask;
 mask |= PictFormatAlpha | PictFormatAlphaMask;
 break;

    case PIXMAN_TYPE_BGRA:
 tmpl.type = PictTypeDirect;

 tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
 tmpl.direct.blue = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format));

 tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
 tmpl.direct.green = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format) -
        PIXMAN_FORMAT_G(format));

 tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
 tmpl.direct.red = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format) -
      PIXMAN_FORMAT_G(format) - PIXMAN_FORMAT_R(format));

 tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
 tmpl.direct.alpha = 0;

 mask |= PictFormatRed | PictFormatRedMask;
 mask |= PictFormatGreen | PictFormatGreenMask;
 mask |= PictFormatBlue | PictFormatBlueMask;
 mask |= PictFormatAlpha | PictFormatAlphaMask;
 break;

    case PIXMAN_TYPE_A:
 tmpl.type = PictTypeDirect;

 tmpl.direct.alpha = 0;
 tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));

 mask |= PictFormatAlpha | PictFormatAlphaMask;
 break;

    case PIXMAN_TYPE_COLOR:
    case PIXMAN_TYPE_GRAY:
 /* XXX Find matching visual/colormap */
 tmpl.type = PictTypeIndexed;
 //tmpl.colormap = screen->visuals[PIXMAN_FORMAT_VIS(format)].vid;
 //mask |= PictFormatColormap;
 return NULL;
    }
#undef MASK

    /* XXX caching? */
    return XRenderFindFormat(dpy, mask, &tmpl, 0);
}

XRenderPictFormat *
_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t *display,
                                 cairo_format_t   format)
{
    XRenderPictFormat *xrender_format;

    xrender_format = display->cached_xrender_formats[format];
    if (xrender_format == NULL) {
 int pict_format = PictStandardNUM;

 switch (format) {
 case CAIRO_FORMAT_A1:
     pict_format = PictStandardA1; break;
 case CAIRO_FORMAT_A8:
     pict_format = PictStandardA8; break;
 case CAIRO_FORMAT_RGB24:
     pict_format = PictStandardRGB24; break;
 case CAIRO_FORMAT_RGB16_565:
     xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
                PIXMAN_r5g6b5);
     break;
 case CAIRO_FORMAT_RGB30:
     xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
                PIXMAN_x2r10g10b10);
     break;
 case CAIRO_FORMAT_RGBA128F:
     xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
                PIXMAN_rgba_float);
     break;
 case CAIRO_FORMAT_RGB96F:
     xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
                PIXMAN_rgb_float);
     break;
 case CAIRO_FORMAT_INVALID:
 default:
     ASSERT_NOT_REACHED;
 case CAIRO_FORMAT_ARGB32:
     pict_format = PictStandardARGB32; break;
 }
 if (pict_format != PictStandardNUM)
     xrender_format =
  XRenderFindStandardFormat (display->display, pict_format);
 display->cached_xrender_formats[format] = xrender_format;
    }

    return xrender_format;
}

cairo_xlib_screen_t *
_cairo_xlib_display_get_screen (cairo_xlib_display_t *display,
    Screen *screen)
{
    cairo_xlib_screen_t *info;

    cairo_list_foreach_entry (info, cairo_xlib_screen_t, &display->screens, link) {
 if (info->screen == screen) {
            if (display->screens.next != &info->link)
                cairo_list_move (&info->link, &display->screens);
            return info;
        }
    }

    return NULL;
}

cairo_bool_t
_cairo_xlib_display_has_repeat (cairo_device_t *device)
{
    return ! ((cairo_xlib_display_t *) device)->buggy_repeat;
}

cairo_bool_t
_cairo_xlib_display_has_reflect (cairo_device_t *device)
{
    return ! ((cairo_xlib_display_t *) device)->buggy_pad_reflect;
}

cairo_bool_t
_cairo_xlib_display_has_gradients (cairo_device_t *device)
{
    return ! ((cairo_xlib_display_t *) device)->buggy_gradients;
}

/**
 * cairo_xlib_device_debug_cap_xrender_version:
 * @device: a #cairo_device_t for the Xlib backend
 * @major_version: major version to restrict to
 * @minor_version: minor version to restrict to
 *
 * Restricts all future Xlib surfaces for this devices to the specified version
 * of the RENDER extension. This function exists solely for debugging purpose.
 * It lets you find out how cairo would behave with an older version of
 * the RENDER extension.
 *
 * Use the special values -1 and -1 for disabling the RENDER extension.
 *
 * Since: 1.12
 **/

void
cairo_xlib_device_debug_cap_xrender_version (cairo_device_t *device,
          int major_version,
          int minor_version)
{
    cairo_xlib_display_t *display = (cairo_xlib_display_t *) device;

    if (device == NULL || device->status)
 return;

    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB)
 return;

    if (major_version < display->render_major ||
 (major_version == display->render_major &&
  minor_version < display->render_minor))
    {
 display->render_major = major_version;
 display->render_minor = minor_version;
    }

    _cairo_xlib_display_select_compositor (display);
}

/**
 * cairo_xlib_device_debug_set_precision:
 * @device: a #cairo_device_t for the Xlib backend
 * @precision: the precision to use
 *
 * Render supports two modes of precision when rendering trapezoids. Set
 * the precision to the desired mode.
 *
 * Since: 1.12
 **/

void
cairo_xlib_device_debug_set_precision (cairo_device_t *device,
           int precision)
{
    if (device == NULL || device->status)
 return;
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
 cairo_status_t status;

 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
 (void) status;
 return;
    }

    ((cairo_xlib_display_t *) device)->force_precision = precision;
}

/**
 * cairo_xlib_device_debug_get_precision:
 * @device: a #cairo_device_t for the Xlib backend
 *
 * Get the Xrender precision mode.
 *
 * Returns: the render precision mode
 *
 * Since: 1.12
 **/

int
cairo_xlib_device_debug_get_precision (cairo_device_t *device)
{
    if (device == NULL || device->status)
 return -1;
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
 cairo_status_t status;

 status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
 (void) status;
 return -1;
    }

    return ((cairo_xlib_display_t *) device)->force_precision;
}

#endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */

Messung V0.5
C=98 H=92 G=94

¤ Dauer der Verarbeitung: 0.28 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge