Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3959 Serge 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 , Mozilla Corporation
34
 */
35
 
36
#include "cairoint.h"
37
 
38
#if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
39
 
40
#include "cairo-xlib-private.h"
41
#include "cairo-xlib-xrender-private.h"
42
#include "cairo-freelist-private.h"
43
#include "cairo-error-private.h"
44
#include "cairo-list-inline.h"
45
 
46
#include 	/* For XESetCloseDisplay */
47
 
48
typedef int (*cairo_xlib_error_func_t) (Display     *display,
49
					XErrorEvent *event);
50
 
51
static cairo_xlib_display_t *_cairo_xlib_display_list;
52
 
53
static int
54
_noop_error_handler (Display     *display,
55
		     XErrorEvent *event)
56
{
57
    return False;		/* return value is ignored */
58
}
59
 
60
static void
61
_cairo_xlib_display_finish (void *abstract_display)
62
{
63
    cairo_xlib_display_t *display = abstract_display;
64
    Display *dpy = display->display;
65
 
66
    _cairo_xlib_display_fini_shm (display);
67
 
68
    if (! cairo_device_acquire (&display->base)) {
69
	cairo_xlib_error_func_t old_handler;
70
 
71
	/* protect the notifies from triggering XErrors */
72
	XSync (dpy, False);
73
	old_handler = XSetErrorHandler (_noop_error_handler);
74
 
75
	while (! cairo_list_is_empty (&display->fonts)) {
76
	    _cairo_xlib_font_close (cairo_list_first_entry (&display->fonts,
77
							    cairo_xlib_font_t,
78
							    link));
79
	}
80
 
81
	while (! cairo_list_is_empty (&display->screens)) {
82
	    _cairo_xlib_screen_destroy (display,
83
					cairo_list_first_entry (&display->screens,
84
								cairo_xlib_screen_t,
85
								link));
86
	}
87
 
88
	XSync (dpy, False);
89
	XSetErrorHandler (old_handler);
90
 
91
	cairo_device_release (&display->base);
92
    }
93
}
94
 
95
static void
96
_cairo_xlib_display_destroy (void *abstract_display)
97
{
98
    cairo_xlib_display_t *display = abstract_display;
99
 
100
    free (display);
101
}
102
 
103
static int
104
_cairo_xlib_close_display (Display *dpy, XExtCodes *codes)
105
{
106
    cairo_xlib_display_t *display, **prev, *next;
107
 
108
    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
109
    for (display = _cairo_xlib_display_list; display; display = display->next)
110
	if (display->display == dpy)
111
	    break;
112
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
113
    if (display == NULL)
114
	return 0;
115
 
116
    cairo_device_finish (&display->base);
117
 
118
    /*
119
     * Unhook from the global list
120
     */
121
    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
122
    prev = &_cairo_xlib_display_list;
123
    for (display = _cairo_xlib_display_list; display; display = next) {
124
	next = display->next;
125
	if (display->display == dpy) {
126
	    *prev = next;
127
	    break;
128
	} else
129
	    prev = &display->next;
130
    }
131
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
132
 
133
    display->display = NULL; /* catch any later invalid access */
134
    cairo_device_destroy (&display->base);
135
 
136
    /* Return value in accordance with requirements of
137
     * XESetCloseDisplay */
138
    return 0;
139
}
140
 
141
static const cairo_device_backend_t _cairo_xlib_device_backend = {
142
    CAIRO_DEVICE_TYPE_XLIB,
143
 
144
    NULL,
145
    NULL,
146
 
147
    NULL, /* flush */
148
    _cairo_xlib_display_finish,
149
    _cairo_xlib_display_destroy,
150
};
151
 
152
static void _cairo_xlib_display_select_compositor (cairo_xlib_display_t *display)
153
{
154
#if 1
155
    if (display->render_major > 0 || display->render_minor >= 4)
156
	display->compositor = _cairo_xlib_traps_compositor_get ();
157
    else if (display->render_major > 0 || display->render_minor >= 0)
158
	display->compositor = _cairo_xlib_mask_compositor_get ();
159
    else
160
	display->compositor = _cairo_xlib_core_compositor_get ();
161
#else
162
    display->compositor = _cairo_xlib_fallback_compositor_get ();
163
#endif
164
}
165
 
166
/**
167
 * _cairo_xlib_device_create:
168
 * @dpy: the display to create the device for
169
 *
170
 * Gets the device belonging to @dpy, or creates it if it doesn't exist yet.
171
 *
172
 * Returns: the device belonging to @dpy
173
 **/
174
cairo_device_t *
175
_cairo_xlib_device_create (Display *dpy)
176
{
177
    cairo_xlib_display_t *display;
178
    cairo_xlib_display_t **prev;
179
    cairo_device_t *device;
180
    XExtCodes *codes;
181
    const char *env;
182
 
183
    CAIRO_MUTEX_INITIALIZE ();
184
 
185
    /* There is an apparent deadlock between this mutex and the
186
     * mutex for the display, but it's actually safe. For the
187
     * app to call XCloseDisplay() while any other thread is
188
     * inside this function would be an error in the logic
189
     * app, and the CloseDisplay hook is the only other place we
190
     * acquire this mutex.
191
     */
192
    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
193
 
194
    for (prev = &_cairo_xlib_display_list; (display = *prev); prev = &(*prev)->next)
195
    {
196
	if (display->display == dpy) {
197
	    /*
198
	     * MRU the list
199
	     */
200
	    if (prev != &_cairo_xlib_display_list) {
201
		*prev = display->next;
202
		display->next = _cairo_xlib_display_list;
203
		_cairo_xlib_display_list = display;
204
	    }
205
            device = cairo_device_reference (&display->base);
206
	    goto UNLOCK;
207
	}
208
    }
209
 
210
    display = malloc (sizeof (cairo_xlib_display_t));
211
    if (unlikely (display == NULL)) {
212
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
213
	goto UNLOCK;
214
    }
215
 
216
    _cairo_device_init (&display->base, &_cairo_xlib_device_backend);
217
 
218
    display->display = dpy;
219
    cairo_list_init (&display->screens);
220
    cairo_list_init (&display->fonts);
221
    display->closed = FALSE;
222
 
223
    /* Xlib calls out to the extension close_display hooks in LIFO
224
     * order. So we have to ensure that all extensions that we depend
225
     * on in our close_display hook are properly initialized before we
226
     * add our hook. For now, that means Render, so we call into its
227
     * QueryVersion function to ensure it gets initialized.
228
     */
229
    display->render_major = display->render_minor = -1;
230
    XRenderQueryVersion (dpy, &display->render_major, &display->render_minor);
231
    env = getenv ("CAIRO_DEBUG");
232
    if (env != NULL && (env = strstr (env, "xrender-version=")) != NULL) {
233
	int max_render_major, max_render_minor;
234
 
235
	env += sizeof ("xrender-version=") - 1;
236
	if (sscanf (env, "%d.%d", &max_render_major, &max_render_minor) != 2)
237
	    max_render_major = max_render_minor = -1;
238
 
239
	if (max_render_major < display->render_major ||
240
	    (max_render_major == display->render_major &&
241
	     max_render_minor < display->render_minor))
242
	{
243
	    display->render_major = max_render_major;
244
	    display->render_minor = max_render_minor;
245
	}
246
    }
247
 
248
    _cairo_xlib_display_select_compositor (display);
249
 
250
    display->white = NULL;
251
    memset (display->alpha, 0, sizeof (display->alpha));
252
    memset (display->solid, 0, sizeof (display->solid));
253
    memset (display->solid_cache, 0, sizeof (display->solid_cache));
254
    memset (display->last_solid_cache, 0, sizeof (display->last_solid_cache));
255
 
256
    memset (display->cached_xrender_formats, 0,
257
	    sizeof (display->cached_xrender_formats));
258
 
259
    display->force_precision = -1;
260
 
261
    _cairo_xlib_display_init_shm (display);
262
 
263
    /* Prior to Render 0.10, there is no protocol support for gradients and
264
     * we call function stubs instead, which would silently consume the drawing.
265
     */
266
#if RENDER_MAJOR == 0 && RENDER_MINOR < 10
267
    display->buggy_gradients = TRUE;
268
#else
269
    display->buggy_gradients = FALSE;
270
#endif
271
    display->buggy_pad_reflect = FALSE;
272
    display->buggy_repeat = FALSE;
273
 
274
    /* This buggy_repeat condition is very complicated because there
275
     * are multiple X server code bases (with multiple versioning
276
     * schemes within a code base), and multiple bugs.
277
     *
278
     * The X servers:
279
     *
280
     *    1. The Vendor=="XFree86" code base with release numbers such
281
     *    as 4.7.0 (VendorRelease==40700000).
282
     *
283
     *    2. The Vendor=="X.Org" code base (a descendant of the
284
     *    XFree86 code base). It originally had things like
285
     *    VendorRelease==60700000 for release 6.7.0 but then changed
286
     *    its versioning scheme so that, for example,
287
     *    VendorRelease==10400000 for the 1.4.0 X server within the
288
     *    X.Org 7.3 release.
289
     *
290
     * The bugs:
291
     *
292
     *    1. The original bug that led to the buggy_repeat
293
     *    workaround. This was a bug that Owen Taylor investigated,
294
     *    understood well, and characterized against carious X
295
     *    servers. Confirmed X servers with this bug include:
296
     *
297
     *		"XFree86" <= 40500000
298
     *		"X.Org" <= 60802000 (only with old numbering >= 60700000)
299
     *
300
     *    2. A separate bug resulting in a crash of the X server when
301
     *    using cairo's extend-reflect test case, (which, surprisingly
302
     *    enough was not passing RepeatReflect to the X server, but
303
     *    instead using RepeatNormal in a workaround). Nobody to date
304
     *    has understood the bug well, but it appears to be gone as of
305
     *    the X.Org 1.4.0 server. This bug is coincidentally avoided
306
     *    by using the same buggy_repeat workaround. Confirmed X
307
     *    servers with this bug include:
308
     *
309
     *		"X.org" == 60900000 (old versioning scheme)
310
     *		"X.org"  < 10400000 (new numbering scheme)
311
     *
312
     *    For the old-versioning-scheme X servers we don't know
313
     *    exactly when second the bug started, but since bug 1 is
314
     *    present through 6.8.2 and bug 2 is present in 6.9.0 it seems
315
     *    safest to just blacklist all old-versioning-scheme X servers,
316
     *    (just using VendorRelease < 70000000), as buggy_repeat=TRUE.
317
     */
318
    if (_cairo_xlib_vendor_is_xorg (dpy)) {
319
	if (VendorRelease (dpy) >= 60700000) {
320
	    if (VendorRelease (dpy) < 70000000)
321
		display->buggy_repeat = TRUE;
322
 
323
	    /* We know that gradients simply do not work in early Xorg servers */
324
	    if (VendorRelease (dpy) < 70200000)
325
		display->buggy_gradients = TRUE;
326
 
327
	    /* And the extended repeat modes were not fixed until much later */
328
	    display->buggy_pad_reflect = TRUE;
329
	} else {
330
	    if (VendorRelease (dpy) < 10400000)
331
		display->buggy_repeat = TRUE;
332
 
333
	    /* Too many bugs in the early drivers */
334
	    if (VendorRelease (dpy) < 10699000)
335
		display->buggy_pad_reflect = TRUE;
336
	}
337
    } else if (strstr (ServerVendor (dpy), "XFree86") != NULL) {
338
	if (VendorRelease (dpy) <= 40500000)
339
	    display->buggy_repeat = TRUE;
340
 
341
	display->buggy_gradients = TRUE;
342
	display->buggy_pad_reflect = TRUE;
343
    }
344
 
345
    codes = XAddExtension (dpy);
346
    if (unlikely (codes == NULL)) {
347
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
348
	free (display);
349
	goto UNLOCK;
350
    }
351
 
352
    XESetCloseDisplay (dpy, codes->extension, _cairo_xlib_close_display);
353
    cairo_device_reference (&display->base); /* add one for the CloseDisplay */
354
 
355
    display->next = _cairo_xlib_display_list;
356
    _cairo_xlib_display_list = display;
357
 
358
    device = &display->base;
359
 
360
UNLOCK:
361
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
362
    return device;
363
}
364
 
365
cairo_status_t
366
_cairo_xlib_display_acquire (cairo_device_t *device, cairo_xlib_display_t **display)
367
{
368
    cairo_status_t status;
369
 
370
    status = cairo_device_acquire (device);
371
    if (status)
372
        return status;
373
 
374
    *display = (cairo_xlib_display_t *) device;
375
    return CAIRO_STATUS_SUCCESS;
376
}
377
 
378
XRenderPictFormat *
379
_cairo_xlib_display_get_xrender_format_for_pixman(cairo_xlib_display_t *display,
380
						  pixman_format_code_t format)
381
{
382
    Display *dpy = display->display;
383
    XRenderPictFormat tmpl;
384
    int mask;
385
 
386
#define MASK(x) ((1<<(x))-1)
387
 
388
    tmpl.depth = PIXMAN_FORMAT_DEPTH(format);
389
    mask = PictFormatType | PictFormatDepth;
390
 
391
    switch (PIXMAN_FORMAT_TYPE(format)) {
392
    case PIXMAN_TYPE_ARGB:
393
	tmpl.type = PictTypeDirect;
394
 
395
	tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
396
	if (PIXMAN_FORMAT_A(format))
397
	    tmpl.direct.alpha = (PIXMAN_FORMAT_R(format) +
398
				 PIXMAN_FORMAT_G(format) +
399
				 PIXMAN_FORMAT_B(format));
400
 
401
	tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
402
	tmpl.direct.red = (PIXMAN_FORMAT_G(format) +
403
			   PIXMAN_FORMAT_B(format));
404
 
405
	tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
406
	tmpl.direct.green = PIXMAN_FORMAT_B(format);
407
 
408
	tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
409
	tmpl.direct.blue = 0;
410
 
411
	mask |= PictFormatRed | PictFormatRedMask;
412
	mask |= PictFormatGreen | PictFormatGreenMask;
413
	mask |= PictFormatBlue | PictFormatBlueMask;
414
	mask |= PictFormatAlpha | PictFormatAlphaMask;
415
	break;
416
 
417
    case PIXMAN_TYPE_ABGR:
418
	tmpl.type = PictTypeDirect;
419
 
420
	tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
421
	if (tmpl.direct.alphaMask)
422
	    tmpl.direct.alpha = (PIXMAN_FORMAT_B(format) +
423
				 PIXMAN_FORMAT_G(format) +
424
				 PIXMAN_FORMAT_R(format));
425
 
426
	tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
427
	tmpl.direct.blue = (PIXMAN_FORMAT_G(format) +
428
			    PIXMAN_FORMAT_R(format));
429
 
430
	tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
431
	tmpl.direct.green = PIXMAN_FORMAT_R(format);
432
 
433
	tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
434
	tmpl.direct.red = 0;
435
 
436
	mask |= PictFormatRed | PictFormatRedMask;
437
	mask |= PictFormatGreen | PictFormatGreenMask;
438
	mask |= PictFormatBlue | PictFormatBlueMask;
439
	mask |= PictFormatAlpha | PictFormatAlphaMask;
440
	break;
441
 
442
    case PIXMAN_TYPE_BGRA:
443
	tmpl.type = PictTypeDirect;
444
 
445
	tmpl.direct.blueMask = MASK(PIXMAN_FORMAT_B(format));
446
	tmpl.direct.blue = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format));
447
 
448
	tmpl.direct.greenMask = MASK(PIXMAN_FORMAT_G(format));
449
	tmpl.direct.green = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format) -
450
			     PIXMAN_FORMAT_G(format));
451
 
452
	tmpl.direct.redMask = MASK(PIXMAN_FORMAT_R(format));
453
	tmpl.direct.red = (PIXMAN_FORMAT_BPP(format) - PIXMAN_FORMAT_B(format) -
454
			   PIXMAN_FORMAT_G(format) - PIXMAN_FORMAT_R(format));
455
 
456
	tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
457
	tmpl.direct.alpha = 0;
458
 
459
	mask |= PictFormatRed | PictFormatRedMask;
460
	mask |= PictFormatGreen | PictFormatGreenMask;
461
	mask |= PictFormatBlue | PictFormatBlueMask;
462
	mask |= PictFormatAlpha | PictFormatAlphaMask;
463
	break;
464
 
465
    case PIXMAN_TYPE_A:
466
	tmpl.type = PictTypeDirect;
467
 
468
	tmpl.direct.alpha = 0;
469
	tmpl.direct.alphaMask = MASK(PIXMAN_FORMAT_A(format));
470
 
471
	mask |= PictFormatAlpha | PictFormatAlphaMask;
472
	break;
473
 
474
    case PIXMAN_TYPE_COLOR:
475
    case PIXMAN_TYPE_GRAY:
476
	/* XXX Find matching visual/colormap */
477
	tmpl.type = PictTypeIndexed;
478
	//tmpl.colormap = screen->visuals[PIXMAN_FORMAT_VIS(format)].vid;
479
	//mask |= PictFormatColormap;
480
	return NULL;
481
    }
482
#undef MASK
483
 
484
    /* XXX caching? */
485
    return XRenderFindFormat(dpy, mask, &tmpl, 0);
486
}
487
 
488
XRenderPictFormat *
489
_cairo_xlib_display_get_xrender_format (cairo_xlib_display_t	*display,
490
	                                cairo_format_t		 format)
491
{
492
    XRenderPictFormat *xrender_format;
493
 
494
#if ! ATOMIC_OP_NEEDS_MEMORY_BARRIER
495
    xrender_format = display->cached_xrender_formats[format];
496
    if (likely (xrender_format != NULL))
497
	return xrender_format;
498
#endif
499
 
500
    xrender_format = display->cached_xrender_formats[format];
501
    if (xrender_format == NULL) {
502
	int pict_format = PictStandardNUM;
503
 
504
	switch (format) {
505
	case CAIRO_FORMAT_A1:
506
	    pict_format = PictStandardA1; break;
507
	case CAIRO_FORMAT_A8:
508
	    pict_format = PictStandardA8; break;
509
	case CAIRO_FORMAT_RGB24:
510
	    pict_format = PictStandardRGB24; break;
511
	case CAIRO_FORMAT_RGB16_565:
512
	    xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
513
									       PIXMAN_r5g6b5);
514
	    break;
515
	case CAIRO_FORMAT_RGB30:
516
	    xrender_format = _cairo_xlib_display_get_xrender_format_for_pixman(display,
517
									       PIXMAN_x2r10g10b10);
518
	    break;
519
	case CAIRO_FORMAT_INVALID:
520
	default:
521
	    ASSERT_NOT_REACHED;
522
	case CAIRO_FORMAT_ARGB32:
523
	    pict_format = PictStandardARGB32; break;
524
	}
525
	if (pict_format != PictStandardNUM)
526
	    xrender_format =
527
		XRenderFindStandardFormat (display->display, pict_format);
528
	display->cached_xrender_formats[format] = xrender_format;
529
    }
530
 
531
    return xrender_format;
532
}
533
 
534
cairo_xlib_screen_t *
535
_cairo_xlib_display_get_screen (cairo_xlib_display_t *display,
536
				Screen *screen)
537
{
538
    cairo_xlib_screen_t *info;
539
 
540
    cairo_list_foreach_entry (info, cairo_xlib_screen_t, &display->screens, link) {
541
	if (info->screen == screen) {
542
            if (display->screens.next != &info->link)
543
                cairo_list_move (&info->link, &display->screens);
544
            return info;
545
        }
546
    }
547
 
548
    return NULL;
549
}
550
 
551
cairo_bool_t
552
_cairo_xlib_display_has_repeat (cairo_device_t *device)
553
{
554
    return ! ((cairo_xlib_display_t *) device)->buggy_repeat;
555
}
556
 
557
cairo_bool_t
558
_cairo_xlib_display_has_reflect (cairo_device_t *device)
559
{
560
    return ! ((cairo_xlib_display_t *) device)->buggy_pad_reflect;
561
}
562
 
563
cairo_bool_t
564
_cairo_xlib_display_has_gradients (cairo_device_t *device)
565
{
566
    return ! ((cairo_xlib_display_t *) device)->buggy_gradients;
567
}
568
 
569
/**
570
 * cairo_xlib_device_debug_cap_xrender_version:
571
 * @device: a #cairo_device_t for the Xlib backend
572
 * @major_version: major version to restrict to
573
 * @minor_version: minor version to restrict to
574
 *
575
 * Restricts all future Xlib surfaces for this devices to the specified version
576
 * of the RENDER extension. This function exists solely for debugging purpose.
577
 * It let's you find out how cairo would behave with an older version of
578
 * the RENDER extension.
579
 *
580
 * Use the special values -1 and -1 for disabling the RENDER extension.
581
 *
582
 * Since: 1.12
583
 **/
584
void
585
cairo_xlib_device_debug_cap_xrender_version (cairo_device_t *device,
586
					     int major_version,
587
					     int minor_version)
588
{
589
    cairo_xlib_display_t *display = (cairo_xlib_display_t *) device;
590
 
591
    if (device == NULL || device->status)
592
	return;
593
 
594
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB)
595
	return;
596
 
597
    if (major_version < display->render_major ||
598
	(major_version == display->render_major &&
599
	 minor_version < display->render_minor))
600
    {
601
	display->render_major = major_version;
602
	display->render_minor = minor_version;
603
    }
604
 
605
    _cairo_xlib_display_select_compositor (display);
606
}
607
 
608
/**
609
 * cairo_xlib_device_debug_set_precision:
610
 * @device: a #cairo_device_t for the Xlib backend
611
 * @precision: the precision to use
612
 *
613
 * Render supports two modes of precision when rendering trapezoids. Set
614
 * the precision to the desired mode.
615
 *
616
 * Since: 1.12
617
 **/
618
void
619
cairo_xlib_device_debug_set_precision (cairo_device_t *device,
620
				       int precision)
621
{
622
    if (device == NULL || device->status)
623
	return;
624
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
625
	cairo_status_t status;
626
 
627
	status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
628
	(void) status;
629
	return;
630
    }
631
 
632
    ((cairo_xlib_display_t *) device)->force_precision = precision;
633
}
634
 
635
/**
636
 * cairo_xlib_device_debug_get_precision:
637
 * @device: a #cairo_device_t for the Xlib backend
638
 *
639
 * Get the Xrender precision mode.
640
 *
641
 * Returns: the render precision mode
642
 *
643
 * Since: 1.12
644
 **/
645
int
646
cairo_xlib_device_debug_get_precision (cairo_device_t *device)
647
{
648
    if (device == NULL || device->status)
649
	return -1;
650
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
651
	cairo_status_t status;
652
 
653
	status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
654
	(void) status;
655
	return -1;
656
    }
657
 
658
    return ((cairo_xlib_display_t *) device)->force_precision;
659
}
660
 
661
#endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */