forked from KolibriOS/kolibrios
754f9336f0
git-svn-id: svn://kolibrios.org@4349 a494cfbc-eb01-0410-851d-a64ba20cac60
662 lines
20 KiB
C
662 lines
20 KiB
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 = 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 carious 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;
|
|
|
|
#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;
|
|
|
|
#if ! ATOMIC_OP_NEEDS_MEMORY_BARRIER
|
|
xrender_format = display->cached_xrender_formats[format];
|
|
if (likely (xrender_format != NULL))
|
|
return xrender_format;
|
|
#endif
|
|
|
|
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_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 let's 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 */
|