Subversion Repositories Kolibri OS

Rev

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

Rev Author Line No. Line
4349 Serge 1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2002 University of Southern California
4
 * Copyright © 2009 Intel Corporation
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it either under the terms of the GNU Lesser General Public
8
 * License version 2.1 as published by the Free Software Foundation
9
 * (the "LGPL") or, at your option, under the terms of the Mozilla
10
 * Public License Version 1.1 (the "MPL"). If you do not alter this
11
 * notice, a recipient may use your version of this file under either
12
 * the MPL or the LGPL.
13
 *
14
 * You should have received a copy of the LGPL along with this library
15
 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16
 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17
 * You should have received a copy of the MPL along with this library
18
 * in the file COPYING-MPL-1.1
19
 *
20
 * The contents of this file are subject to the Mozilla Public License
21
 * Version 1.1 (the "License"); you may not use this file except in
22
 * compliance with the License. You may obtain a copy of the License at
23
 * http://www.mozilla.org/MPL/
24
 *
25
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26
 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27
 * the specific language governing rights and limitations.
28
 *
29
 * The Original Code is the cairo graphics library.
30
 *
31
 * The Initial Developer of the Original Code is University of Southern
32
 * California.
33
 *
34
 * Contributor(s):
35
 *	Carl D. Worth 
36
 *	Chris Wilson 
37
 */
38
 
39
#include "cairoint.h"
40
 
41
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
42
 
43
#include "cairo-xlib.h"
44
#include "cairo-xcb.h"
45
 
46
#include "cairo-xcb-private.h"
47
#include "cairo-xlib-xrender-private.h"
48
 
49
#include "cairo-default-context-private.h"
50
#include "cairo-list-inline.h"
51
#include "cairo-image-surface-private.h"
52
#include "cairo-surface-backend-private.h"
53
 
54
#include 
55
#include 	/* For XESetCloseDisplay */
56
 
57
struct cairo_xlib_xcb_display_t {
58
    cairo_device_t  base;
59
 
60
    Display        *dpy;
61
    cairo_device_t *xcb_device;
62
    XExtCodes      *codes;
63
 
64
    cairo_list_t    link;
65
};
66
typedef struct cairo_xlib_xcb_display_t cairo_xlib_xcb_display_t;
67
 
68
/* List of all #cairo_xlib_xcb_display_t alive,
69
 * protected by _cairo_xlib_display_mutex */
70
static cairo_list_t displays;
71
 
72
static cairo_surface_t *
73
_cairo_xlib_xcb_surface_create (void *dpy,
74
				void *scr,
75
				void *visual,
76
				void *format,
77
				cairo_surface_t *xcb);
78
 
79
static cairo_surface_t *
80
_cairo_xlib_xcb_surface_create_similar (void			*abstract_other,
81
					cairo_content_t		 content,
82
					int			 width,
83
					int			 height)
84
{
85
    cairo_xlib_xcb_surface_t *other = abstract_other;
86
    cairo_surface_t *xcb;
87
 
88
    xcb = other->xcb->base.backend->create_similar (other->xcb, content, width, height);
89
    if (unlikely (xcb == NULL || xcb->status))
90
	return xcb;
91
 
92
    return _cairo_xlib_xcb_surface_create (other->display, other->screen, NULL, NULL, xcb);
93
}
94
 
95
static cairo_status_t
96
_cairo_xlib_xcb_surface_finish (void *abstract_surface)
97
{
98
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
99
    cairo_status_t status;
100
 
101
    cairo_surface_finish (&surface->xcb->base);
102
    status = surface->xcb->base.status;
103
    cairo_surface_destroy (&surface->xcb->base);
104
    surface->xcb = NULL;
105
 
106
    return status;
107
}
108
 
109
static cairo_surface_t *
110
_cairo_xlib_xcb_surface_create_similar_image (void			*abstract_other,
111
					      cairo_format_t		 format,
112
					      int			 width,
113
					      int			 height)
114
{
115
    cairo_xlib_xcb_surface_t *surface = abstract_other;
116
    return cairo_surface_create_similar_image (&surface->xcb->base, format, width, height);
117
}
118
 
119
static cairo_image_surface_t *
120
_cairo_xlib_xcb_surface_map_to_image (void *abstract_surface,
121
				      const cairo_rectangle_int_t *extents)
122
{
123
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
124
    return _cairo_surface_map_to_image (&surface->xcb->base, extents);
125
}
126
 
127
static cairo_int_status_t
128
_cairo_xlib_xcb_surface_unmap (void *abstract_surface,
129
			       cairo_image_surface_t *image)
130
{
131
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
132
    return _cairo_surface_unmap_image (&surface->xcb->base, image);
133
}
134
 
135
static cairo_surface_t *
136
_cairo_xlib_xcb_surface_source (void *abstract_surface,
137
				cairo_rectangle_int_t *extents)
138
{
139
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
140
    return _cairo_surface_get_source (&surface->xcb->base, extents);
141
}
142
 
143
static cairo_status_t
144
_cairo_xlib_xcb_surface_acquire_source_image (void *abstract_surface,
145
					      cairo_image_surface_t **image_out,
146
					      void **image_extra)
147
{
148
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
149
    return _cairo_surface_acquire_source_image (&surface->xcb->base,
150
						image_out, image_extra);
151
}
152
 
153
static void
154
_cairo_xlib_xcb_surface_release_source_image (void *abstract_surface,
155
					      cairo_image_surface_t *image_out,
156
					      void *image_extra)
157
{
158
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
159
    _cairo_surface_release_source_image (&surface->xcb->base, image_out, image_extra);
160
}
161
 
162
static cairo_bool_t
163
_cairo_xlib_xcb_surface_get_extents (void *abstract_surface,
164
				     cairo_rectangle_int_t *extents)
165
{
166
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
167
    return _cairo_surface_get_extents (&surface->xcb->base, extents);
168
}
169
 
170
static void
171
_cairo_xlib_xcb_surface_get_font_options (void *abstract_surface,
172
					  cairo_font_options_t *options)
173
{
174
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
175
    cairo_surface_get_font_options (&surface->xcb->base, options);
176
}
177
 
178
static cairo_int_status_t
179
_cairo_xlib_xcb_surface_paint (void			*abstract_surface,
180
			       cairo_operator_t		 op,
181
			       const cairo_pattern_t	*source,
182
			       const cairo_clip_t	*clip)
183
{
184
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
185
    return _cairo_surface_paint (&surface->xcb->base, op, source, clip);
186
}
187
 
188
static cairo_int_status_t
189
_cairo_xlib_xcb_surface_mask (void			*abstract_surface,
190
			      cairo_operator_t		 op,
191
			      const cairo_pattern_t	*source,
192
			      const cairo_pattern_t	*mask,
193
			      const cairo_clip_t	*clip)
194
{
195
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
196
    return _cairo_surface_mask (&surface->xcb->base, op, source, mask, clip);
197
}
198
 
199
static cairo_int_status_t
200
_cairo_xlib_xcb_surface_stroke (void				*abstract_surface,
201
				cairo_operator_t		 op,
202
				const cairo_pattern_t		*source,
203
				const cairo_path_fixed_t	*path,
204
				const cairo_stroke_style_t	*style,
205
				const cairo_matrix_t		*ctm,
206
				const cairo_matrix_t		*ctm_inverse,
207
				double				 tolerance,
208
				cairo_antialias_t		 antialias,
209
				const cairo_clip_t		*clip)
210
{
211
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
212
    return _cairo_surface_stroke (&surface->xcb->base,
213
				  op, source, path, style, ctm, ctm_inverse,
214
				  tolerance, antialias, clip);
215
}
216
 
217
static cairo_int_status_t
218
_cairo_xlib_xcb_surface_fill (void			*abstract_surface,
219
			      cairo_operator_t		 op,
220
			      const cairo_pattern_t	*source,
221
			      const cairo_path_fixed_t	*path,
222
			      cairo_fill_rule_t		 fill_rule,
223
			      double			 tolerance,
224
			      cairo_antialias_t		 antialias,
225
			      const cairo_clip_t	*clip)
226
{
227
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
228
    return _cairo_surface_fill (&surface->xcb->base,
229
				op, source, path,
230
				fill_rule, tolerance,
231
				antialias, clip);
232
}
233
 
234
static cairo_int_status_t
235
_cairo_xlib_xcb_surface_glyphs (void			*abstract_surface,
236
				cairo_operator_t	 op,
237
				const cairo_pattern_t	*source,
238
				cairo_glyph_t		*glyphs,
239
				int			 num_glyphs,
240
				cairo_scaled_font_t	*scaled_font,
241
				const cairo_clip_t	*clip)
242
{
243
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
244
    return _cairo_surface_show_text_glyphs (&surface->xcb->base, op, source,
245
					    NULL, 0,
246
					    glyphs, num_glyphs,
247
					    NULL, 0, 0,
248
					    scaled_font, clip);
249
}
250
 
251
static cairo_status_t
252
_cairo_xlib_xcb_surface_flush (void *abstract_surface, unsigned flags)
253
{
254
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
255
    /* We have to call cairo_surface_flush() to make sure snapshots are detached */
256
    return _cairo_surface_flush (&surface->xcb->base, flags);
257
}
258
 
259
static cairo_status_t
260
_cairo_xlib_xcb_surface_mark_dirty (void *abstract_surface,
261
				    int x, int y,
262
				    int width, int height)
263
{
264
    cairo_xlib_xcb_surface_t *surface = abstract_surface;
265
    cairo_surface_mark_dirty_rectangle (&surface->xcb->base, x, y, width, height);
266
    return cairo_surface_status (&surface->xcb->base);
267
}
268
 
269
static const cairo_surface_backend_t _cairo_xlib_xcb_surface_backend = {
270
    CAIRO_SURFACE_TYPE_XLIB,
271
    _cairo_xlib_xcb_surface_finish,
272
 
273
    _cairo_default_context_create, /* XXX */
274
 
275
    _cairo_xlib_xcb_surface_create_similar,
276
    _cairo_xlib_xcb_surface_create_similar_image,
277
    _cairo_xlib_xcb_surface_map_to_image,
278
    _cairo_xlib_xcb_surface_unmap,
279
 
280
    _cairo_xlib_xcb_surface_source,
281
    _cairo_xlib_xcb_surface_acquire_source_image,
282
    _cairo_xlib_xcb_surface_release_source_image,
283
    NULL, /* snapshot */
284
 
285
    NULL, /* copy_page */
286
    NULL, /* show_page */
287
 
288
    _cairo_xlib_xcb_surface_get_extents,
289
    _cairo_xlib_xcb_surface_get_font_options,
290
 
291
    _cairo_xlib_xcb_surface_flush,
292
    _cairo_xlib_xcb_surface_mark_dirty,
293
 
294
    _cairo_xlib_xcb_surface_paint,
295
    _cairo_xlib_xcb_surface_mask,
296
    _cairo_xlib_xcb_surface_stroke,
297
    _cairo_xlib_xcb_surface_fill,
298
    NULL, /* fill_stroke */
299
    _cairo_xlib_xcb_surface_glyphs,
300
};
301
 
302
static void
303
_cairo_xlib_xcb_display_finish (void *abstract_display)
304
{
305
    cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) abstract_display;
306
 
307
    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
308
    cairo_list_del (&display->link);
309
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
310
 
311
    cairo_device_destroy (display->xcb_device);
312
    display->xcb_device = NULL;
313
 
314
    XESetCloseDisplay (display->dpy, display->codes->extension, NULL);
315
    /* Drop the reference from _cairo_xlib_xcb_device_create */
316
    cairo_device_destroy (&display->base);
317
}
318
 
319
static int
320
_cairo_xlib_xcb_close_display(Display *dpy, XExtCodes *codes)
321
{
322
    cairo_xlib_xcb_display_t *display;
323
 
324
    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
325
    cairo_list_foreach_entry (display,
326
			      cairo_xlib_xcb_display_t,
327
			      &displays,
328
			      link)
329
    {
330
	if (display->dpy == dpy)
331
	{
332
	    /* _cairo_xlib_xcb_display_finish will lock the mutex again
333
	     * -> deadlock (This mutex isn't recursive) */
334
	    cairo_device_reference (&display->base);
335
	    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
336
 
337
	    /* Make sure the xcb and xlib-xcb devices are finished */
338
	    cairo_device_finish (display->xcb_device);
339
	    cairo_device_finish (&display->base);
340
 
341
	    cairo_device_destroy (&display->base);
342
	    return 0;
343
	}
344
    }
345
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
346
 
347
    return 0;
348
}
349
 
350
static const cairo_device_backend_t _cairo_xlib_xcb_device_backend = {
351
    CAIRO_DEVICE_TYPE_XLIB,
352
 
353
    NULL,
354
    NULL,
355
 
356
    NULL, /* flush */
357
    _cairo_xlib_xcb_display_finish,
358
    free, /* destroy */
359
};
360
 
361
static cairo_device_t *
362
_cairo_xlib_xcb_device_create (Display *dpy, cairo_device_t *xcb_device)
363
{
364
    cairo_xlib_xcb_display_t *display = NULL;
365
    cairo_device_t *device;
366
 
367
    if (xcb_device == NULL)
368
	return NULL;
369
 
370
    CAIRO_MUTEX_INITIALIZE ();
371
 
372
    CAIRO_MUTEX_LOCK (_cairo_xlib_display_mutex);
373
    if (displays.next == NULL) {
374
	cairo_list_init (&displays);
375
    }
376
 
377
    cairo_list_foreach_entry (display,
378
			      cairo_xlib_xcb_display_t,
379
			      &displays,
380
			      link)
381
    {
382
	if (display->dpy == dpy) {
383
	    /* Maintain MRU order. */
384
	    if (displays.next != &display->link)
385
		cairo_list_move (&display->link, &displays);
386
 
387
	    /* Grab a reference for our caller */
388
	    device = cairo_device_reference (&display->base);
389
	    assert (display->xcb_device == xcb_device);
390
	    goto unlock;
391
	}
392
    }
393
 
394
    display = malloc (sizeof (cairo_xlib_xcb_display_t));
395
    if (unlikely (display == NULL)) {
396
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
397
	goto unlock;
398
    }
399
 
400
    display->codes = XAddExtension (dpy);
401
    if (unlikely (display->codes == NULL)) {
402
	device = _cairo_device_create_in_error (CAIRO_STATUS_NO_MEMORY);
403
	free (display);
404
	goto unlock;
405
    }
406
 
407
    _cairo_device_init (&display->base, &_cairo_xlib_xcb_device_backend);
408
 
409
    XESetCloseDisplay (dpy, display->codes->extension, _cairo_xlib_xcb_close_display);
410
    /* Add a reference for _cairo_xlib_xcb_display_finish. This basically means
411
     * that the device's reference count never drops to zero
412
     * as long as our Display* is alive. We need this because there is no
413
     * "XDelExtension" to undo XAddExtension and having lots of registered
414
     * extensions slows down libX11. */
415
    cairo_device_reference (&display->base);
416
 
417
    display->dpy = dpy;
418
    display->xcb_device = cairo_device_reference(xcb_device);
419
 
420
    cairo_list_add (&display->link, &displays);
421
    device = &display->base;
422
 
423
unlock:
424
    CAIRO_MUTEX_UNLOCK (_cairo_xlib_display_mutex);
425
 
426
    return device;
427
}
428
 
429
static cairo_surface_t *
430
_cairo_xlib_xcb_surface_create (void *dpy,
431
				void *scr,
432
				void *visual,
433
				void *format,
434
				cairo_surface_t *xcb)
435
{
436
    cairo_xlib_xcb_surface_t *surface;
437
 
438
    if (unlikely (xcb->status))
439
	return xcb;
440
 
441
    surface = malloc (sizeof (*surface));
442
    if (unlikely (surface == NULL)) {
443
	cairo_surface_destroy (xcb);
444
	return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
445
    }
446
 
447
    _cairo_surface_init (&surface->base,
448
			 &_cairo_xlib_xcb_surface_backend,
449
			 _cairo_xlib_xcb_device_create (dpy, xcb->device),
450
			 xcb->content);
451
 
452
    /* _cairo_surface_init() got another reference to the device, drop ours */
453
    cairo_device_destroy (surface->base.device);
454
 
455
    surface->display = dpy;
456
    surface->screen = scr;
457
    surface->visual = visual;
458
    surface->format = format;
459
    surface->xcb = (cairo_xcb_surface_t *) xcb;
460
 
461
    return &surface->base;
462
}
463
 
464
static Screen *
465
_cairo_xlib_screen_from_visual (Display *dpy, Visual *visual)
466
{
467
    int s, d, v;
468
 
469
    for (s = 0; s < ScreenCount (dpy); s++) {
470
	Screen *screen;
471
 
472
	screen = ScreenOfDisplay (dpy, s);
473
	if (visual == DefaultVisualOfScreen (screen))
474
	    return screen;
475
 
476
	for (d = 0; d < screen->ndepths; d++) {
477
	    Depth  *depth;
478
 
479
	    depth = &screen->depths[d];
480
	    for (v = 0; v < depth->nvisuals; v++)
481
		if (visual == &depth->visuals[v])
482
		    return screen;
483
	}
484
    }
485
 
486
    return NULL;
487
}
488
 
489
cairo_surface_t *
490
cairo_xlib_surface_create (Display     *dpy,
491
			   Drawable	drawable,
492
			   Visual      *visual,
493
			   int		width,
494
			   int		height)
495
{
496
    Screen *scr;
497
    xcb_visualtype_t xcb_visual;
498
 
499
    scr = _cairo_xlib_screen_from_visual (dpy, visual);
500
    if (scr == NULL)
501
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
502
 
503
    xcb_visual.visual_id = visual->visualid;
504
#if defined(__cplusplus) || defined(c_plusplus)
505
    xcb_visual._class = visual->c_class;
506
#else
507
    xcb_visual._class = visual->class;
508
#endif
509
    xcb_visual.bits_per_rgb_value = visual->bits_per_rgb;
510
    xcb_visual.colormap_entries = visual->map_entries;
511
    xcb_visual.red_mask = visual->red_mask;
512
    xcb_visual.green_mask = visual->green_mask;
513
    xcb_visual.blue_mask = visual->blue_mask;
514
 
515
    return _cairo_xlib_xcb_surface_create (dpy, scr, visual, NULL,
516
					   cairo_xcb_surface_create (XGetXCBConnection (dpy),
517
								     drawable,
518
								     &xcb_visual,
519
								     width, height));
520
}
521
 
522
cairo_surface_t *
523
cairo_xlib_surface_create_for_bitmap (Display  *dpy,
524
				      Pixmap	bitmap,
525
				      Screen   *scr,
526
				      int	width,
527
				      int	height)
528
{
529
    return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, NULL,
530
					   cairo_xcb_surface_create_for_bitmap (XGetXCBConnection (dpy),
531
										(xcb_screen_t *) scr,
532
										bitmap,
533
										width, height));
534
}
535
 
536
#if CAIRO_HAS_XLIB_XRENDER_SURFACE
537
static xcb_screen_t *
538
_cairo_xcb_screen_from_root (xcb_connection_t *connection,
539
			     xcb_window_t id)
540
{
541
    xcb_screen_iterator_t s;
542
 
543
    s = xcb_setup_roots_iterator (xcb_get_setup (connection));
544
    for (; s.rem; xcb_screen_next (&s)) {
545
	if (s.data->root == id)
546
	    return s.data;
547
    }
548
 
549
    return NULL;
550
}
551
cairo_surface_t *
552
cairo_xlib_surface_create_with_xrender_format (Display		    *dpy,
553
					       Drawable		    drawable,
554
					       Screen		    *scr,
555
					       XRenderPictFormat    *format,
556
					       int		    width,
557
					       int		    height)
558
{
559
    xcb_render_pictforminfo_t xcb_format;
560
    xcb_connection_t *connection;
561
    xcb_screen_t *screen;
562
 
563
    xcb_format.id = format->id;
564
    xcb_format.type = format->type;
565
    xcb_format.depth = format->depth;
566
    xcb_format.direct.red_shift = format->direct.red;
567
    xcb_format.direct.red_mask = format->direct.redMask;
568
    xcb_format.direct.green_shift = format->direct.green;
569
    xcb_format.direct.green_mask = format->direct.greenMask;
570
    xcb_format.direct.blue_shift = format->direct.blue;
571
    xcb_format.direct.blue_mask = format->direct.blueMask;
572
    xcb_format.direct.alpha_shift = format->direct.alpha;
573
    xcb_format.direct.alpha_mask = format->direct.alphaMask;
574
    xcb_format.colormap = format->colormap;
575
 
576
    connection = XGetXCBConnection (dpy);
577
    screen = _cairo_xcb_screen_from_root (connection, (xcb_window_t) scr->root);
578
 
579
    return _cairo_xlib_xcb_surface_create (dpy, scr, NULL, format,
580
					   cairo_xcb_surface_create_with_xrender_format (connection, screen,
581
											 drawable,
582
											 &xcb_format,
583
											 width, height));
584
}
585
 
586
XRenderPictFormat *
587
cairo_xlib_surface_get_xrender_format (cairo_surface_t *surface)
588
{
589
    cairo_xlib_xcb_surface_t *xlib_surface = (cairo_xlib_xcb_surface_t *) surface;
590
 
591
    /* Throw an error for a non-xlib surface */
592
    if (surface->type != CAIRO_SURFACE_TYPE_XLIB) {
593
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
594
	return NULL;
595
    }
596
 
597
    return xlib_surface->format;
598
}
599
#endif
600
 
601
void
602
cairo_xlib_surface_set_size (cairo_surface_t *abstract_surface,
603
			     int              width,
604
			     int              height)
605
{
606
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
607
    cairo_status_t status;
608
 
609
    if (unlikely (abstract_surface->status))
610
	return;
611
    if (unlikely (abstract_surface->finished)) {
612
	status = _cairo_surface_set_error (abstract_surface,
613
		                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
614
	return;
615
    }
616
 
617
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
618
	status = _cairo_surface_set_error (abstract_surface,
619
		                           CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
620
	return;
621
    }
622
 
623
    cairo_xcb_surface_set_size (&surface->xcb->base, width, height);
624
    if (unlikely (surface->xcb->base.status)) {
625
	status = _cairo_surface_set_error (abstract_surface,
626
		                           _cairo_error (surface->xcb->base.status));
627
    }
628
}
629
 
630
void
631
cairo_xlib_surface_set_drawable (cairo_surface_t   *abstract_surface,
632
				 Drawable	    drawable,
633
				 int		    width,
634
				 int		    height)
635
{
636
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *)abstract_surface;
637
    cairo_status_t status;
638
 
639
    if (unlikely (abstract_surface->status))
640
	return;
641
    if (unlikely (abstract_surface->finished)) {
642
	status = _cairo_surface_set_error (abstract_surface,
643
		                           _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
644
	return;
645
    }
646
 
647
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
648
	status = _cairo_surface_set_error (abstract_surface,
649
		                           CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
650
	return;
651
    }
652
 
653
    cairo_xcb_surface_set_drawable (&surface->xcb->base, drawable, width, height);
654
    if (unlikely (surface->xcb->base.status)) {
655
	status = _cairo_surface_set_error (abstract_surface,
656
		                           _cairo_error (surface->xcb->base.status));
657
    }
658
}
659
 
660
Display *
661
cairo_xlib_surface_get_display (cairo_surface_t *abstract_surface)
662
{
663
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
664
 
665
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
666
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
667
	return NULL;
668
    }
669
 
670
    return surface->display;
671
}
672
 
673
Drawable
674
cairo_xlib_surface_get_drawable (cairo_surface_t *abstract_surface)
675
{
676
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
677
 
678
    if (unlikely (abstract_surface->finished)) {
679
	_cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
680
	return 0;
681
    }
682
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
683
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
684
	return 0;
685
    }
686
    /* This can happen when e.g. create_similar falls back to an image surface
687
     * because we don't have the RENDER extension. */
688
    if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
689
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
690
	return 0;
691
    }
692
 
693
    return surface->xcb->drawable;
694
}
695
 
696
Screen *
697
cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
698
{
699
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
700
 
701
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
702
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
703
	return NULL;
704
    }
705
 
706
    return surface->screen;
707
}
708
 
709
Visual *
710
cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface)
711
{
712
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
713
 
714
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
715
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
716
	return NULL;
717
    }
718
 
719
    return surface->visual;
720
}
721
 
722
int
723
cairo_xlib_surface_get_depth (cairo_surface_t *abstract_surface)
724
{
725
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
726
 
727
    if (unlikely (abstract_surface->finished)) {
728
	_cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
729
	return 0;
730
    }
731
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
732
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
733
	return 0;
734
    }
735
    /* This can happen when e.g. create_similar falls back to an image surface
736
     * because we don't have the RENDER extension. */
737
    if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
738
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
739
	return 0;
740
    }
741
 
742
    return surface->xcb->depth;
743
}
744
 
745
int
746
cairo_xlib_surface_get_width (cairo_surface_t *abstract_surface)
747
{
748
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
749
 
750
    if (unlikely (abstract_surface->finished)) {
751
	_cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
752
	return 0;
753
    }
754
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
755
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
756
	return 0;
757
    }
758
    /* This can happen when e.g. create_similar falls back to an image surface
759
     * because we don't have the RENDER extension. */
760
    if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
761
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
762
	return 0;
763
    }
764
 
765
    return surface->xcb->width;
766
}
767
 
768
int
769
cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
770
{
771
    cairo_xlib_xcb_surface_t *surface = (cairo_xlib_xcb_surface_t *) abstract_surface;
772
 
773
    if (unlikely (abstract_surface->finished)) {
774
	_cairo_error_throw (CAIRO_STATUS_SURFACE_FINISHED);
775
	return 0;
776
    }
777
    if (surface->base.type != CAIRO_SURFACE_TYPE_XLIB) {
778
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
779
	return 0;
780
    }
781
    /* This can happen when e.g. create_similar falls back to an image surface
782
     * because we don't have the RENDER extension. */
783
    if (surface->xcb->base.type != CAIRO_SURFACE_TYPE_XCB) {
784
	_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
785
	return 0;
786
    }
787
 
788
    return surface->xcb->height;
789
}
790
 
791
void
792
cairo_xlib_device_debug_cap_xrender_version (cairo_device_t *device,
793
					     int major, int minor)
794
{
795
    cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
796
 
797
    if (device == NULL || device->status)
798
	return;
799
 
800
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB)
801
	return;
802
 
803
    cairo_xcb_device_debug_cap_xrender_version (display->xcb_device,
804
						major, minor);
805
}
806
 
807
void
808
cairo_xlib_device_debug_set_precision (cairo_device_t *device,
809
				       int precision)
810
{
811
    cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
812
 
813
    if (device == NULL || device->status)
814
	return;
815
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
816
	cairo_status_t status;
817
 
818
	status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
819
	(void) status;
820
	return;
821
    }
822
 
823
    cairo_xcb_device_debug_set_precision (display->xcb_device, precision);
824
}
825
 
826
int
827
cairo_xlib_device_debug_get_precision (cairo_device_t *device)
828
{
829
    cairo_xlib_xcb_display_t *display = (cairo_xlib_xcb_display_t *) device;
830
 
831
    if (device == NULL || device->status)
832
	return -1;
833
    if (device->backend->type != CAIRO_DEVICE_TYPE_XLIB) {
834
	cairo_status_t status;
835
 
836
	status = _cairo_device_set_error (device, CAIRO_STATUS_DEVICE_TYPE_MISMATCH);
837
	(void) status;
838
	return -1;
839
    }
840
 
841
    return cairo_xcb_device_debug_get_precision (display->xcb_device);
842
}
843
 
844
#endif /* CAIRO_HAS_XLIB_XCB_FUNCTIONS */