Subversion Repositories Kolibri OS

Rev

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
 *	Behdad Esfahbod 
36
 *	Carl D. Worth 
37
 *	Chris Wilson 
38
 *	Karl Tomlinson , Mozilla Corporation
39
 */
40
 
41
#include "cairoint.h"
42
 
43
#include "cairo-xcb.h"
44
#include "cairo-xcb-private.h"
45
 
46
#include "cairo-composite-rectangles-private.h"
47
#include "cairo-default-context-private.h"
48
#include "cairo-image-surface-inline.h"
49
#include "cairo-list-inline.h"
50
#include "cairo-surface-backend-private.h"
51
#include "cairo-compositor-private.h"
52
 
53
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
54
slim_hidden_proto (cairo_xcb_surface_create);
55
slim_hidden_proto (cairo_xcb_surface_create_for_bitmap);
56
slim_hidden_proto (cairo_xcb_surface_create_with_xrender_format);
57
#endif
58
 
59
/**
60
 * SECTION:cairo-xcb
61
 * @Title: XCB Surfaces
62
 * @Short_Description: X Window System rendering using the XCB library
63
 * @See_Also: #cairo_surface_t
64
 *
65
 * The XCB surface is used to render cairo graphics to X Window System
66
 * windows and pixmaps using the XCB library.
67
 *
68
 * Note that the XCB surface automatically takes advantage of the X render
69
 * extension if it is available.
70
 **/
71
 
72
/**
73
 * CAIRO_HAS_XCB_SURFACE:
74
 *
75
 * Defined if the xcb surface backend is available.
76
 * This macro can be used to conditionally compile backend-specific code.
77
 *
78
 * Since: 1.12
79
 **/
80
 
81
cairo_surface_t *
82
_cairo_xcb_surface_create_similar (void			*abstract_other,
83
				   cairo_content_t	 content,
84
				   int			 width,
85
				   int			 height)
86
{
87
    cairo_xcb_surface_t *other = abstract_other;
88
    cairo_xcb_surface_t *surface;
89
    cairo_xcb_connection_t *connection;
90
    xcb_pixmap_t pixmap;
91
    cairo_status_t status;
92
 
93
    if (unlikely(width  > XLIB_COORD_MAX ||
94
		 height > XLIB_COORD_MAX ||
95
		 width  <= 0 ||
96
		 height <= 0))
97
	return cairo_image_surface_create (_cairo_format_from_content (content),
98
					   width, height);
99
 
100
    if ((other->connection->flags & CAIRO_XCB_HAS_RENDER) == 0)
101
	return _cairo_xcb_surface_create_similar_image (other,
102
							_cairo_format_from_content (content),
103
							width, height);
104
 
105
    connection = other->connection;
106
    status = _cairo_xcb_connection_acquire (connection);
107
    if (unlikely (status))
108
	return _cairo_surface_create_in_error (status);
109
 
110
    if (content == other->base.content) {
111
	pixmap = _cairo_xcb_connection_create_pixmap (connection,
112
						      other->depth,
113
						      other->drawable,
114
						      width, height);
115
 
116
	surface = (cairo_xcb_surface_t *)
117
	    _cairo_xcb_surface_create_internal (other->screen,
118
						pixmap, TRUE,
119
						other->pixman_format,
120
						other->xrender_format,
121
						width, height);
122
    } else {
123
	cairo_format_t format;
124
	pixman_format_code_t pixman_format;
125
 
126
	/* XXX find a compatible xrender format */
127
	switch (content) {
128
	case CAIRO_CONTENT_ALPHA:
129
	    pixman_format = PIXMAN_a8;
130
	    format = CAIRO_FORMAT_A8;
131
	    break;
132
	case CAIRO_CONTENT_COLOR:
133
	    pixman_format = PIXMAN_x8r8g8b8;
134
	    format = CAIRO_FORMAT_RGB24;
135
	    break;
136
	default:
137
	    ASSERT_NOT_REACHED;
138
	case CAIRO_CONTENT_COLOR_ALPHA:
139
	    pixman_format = PIXMAN_a8r8g8b8;
140
	    format = CAIRO_FORMAT_ARGB32;
141
	    break;
142
	}
143
 
144
	pixmap = _cairo_xcb_connection_create_pixmap (connection,
145
						      PIXMAN_FORMAT_DEPTH (pixman_format),
146
						      other->drawable,
147
						      width, height);
148
 
149
	surface = (cairo_xcb_surface_t *)
150
	    _cairo_xcb_surface_create_internal (other->screen,
151
						pixmap, TRUE,
152
						pixman_format,
153
						connection->standard_formats[format],
154
						width, height);
155
    }
156
 
157
    if (unlikely (surface->base.status))
158
	_cairo_xcb_connection_free_pixmap (connection, pixmap);
159
 
160
    _cairo_xcb_connection_release (connection);
161
 
162
    return &surface->base;
163
}
164
 
165
cairo_surface_t *
166
_cairo_xcb_surface_create_similar_image (void			*abstract_other,
167
					 cairo_format_t		 format,
168
					 int			 width,
169
					 int			 height)
170
{
171
    cairo_xcb_surface_t *other = abstract_other;
172
    cairo_xcb_connection_t *connection = other->connection;
173
 
174
    cairo_xcb_shm_info_t *shm_info;
175
    cairo_image_surface_t *image;
176
    cairo_status_t status;
177
    pixman_format_code_t pixman_format;
178
 
179
    if (unlikely(width  > XLIB_COORD_MAX ||
180
		 height > XLIB_COORD_MAX ||
181
		 width  <= 0 ||
182
		 height <= 0))
183
	return NULL;
184
 
185
    pixman_format = _cairo_format_to_pixman_format_code (format);
186
 
187
    status = _cairo_xcb_shm_image_create (connection, pixman_format,
188
					  width, height, &image,
189
					  &shm_info);
190
    if (unlikely (status))
191
	return _cairo_surface_create_in_error (status);
192
 
193
    if (! image->base.is_clear) {
194
	memset (image->data, 0, image->stride * image->height);
195
	image->base.is_clear = TRUE;
196
    }
197
 
198
    return &image->base;
199
}
200
 
201
static cairo_status_t
202
_cairo_xcb_surface_finish (void *abstract_surface)
203
{
204
    cairo_xcb_surface_t *surface = abstract_surface;
205
    cairo_status_t status;
206
 
207
    if (surface->fallback != NULL) {
208
	cairo_surface_finish (&surface->fallback->base);
209
	cairo_surface_destroy (&surface->fallback->base);
210
    }
211
    _cairo_boxes_fini (&surface->fallback_damage);
212
 
213
    cairo_list_del (&surface->link);
214
 
215
    status = _cairo_xcb_connection_acquire (surface->connection);
216
    if (status == CAIRO_STATUS_SUCCESS) {
217
	if (surface->picture != XCB_NONE) {
218
	    _cairo_xcb_connection_render_free_picture (surface->connection,
219
						       surface->picture);
220
	}
221
 
222
	if (surface->owns_pixmap)
223
	    _cairo_xcb_connection_free_pixmap (surface->connection, surface->drawable);
224
	_cairo_xcb_connection_release (surface->connection);
225
    }
226
 
227
    _cairo_xcb_connection_destroy (surface->connection);
228
 
229
    return status;
230
}
231
 
232
static void
233
_destroy_image (pixman_image_t *image, void *data)
234
{
235
    free (data);
236
}
237
 
238
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
239
static cairo_surface_t *
240
_cairo_xcb_surface_create_shm_image (cairo_xcb_connection_t *connection,
241
				     pixman_format_code_t pixman_format,
242
				     int width, int height,
243
				     cairo_bool_t might_reuse,
244
				     cairo_xcb_shm_info_t **shm_info_out)
245
{
246
    cairo_surface_t *image;
247
    cairo_xcb_shm_info_t *shm_info;
248
    cairo_int_status_t status;
249
    size_t stride;
250
 
251
    *shm_info_out = NULL;
252
 
253
    stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width,
254
					 PIXMAN_FORMAT_BPP (pixman_format));
255
    status = _cairo_xcb_connection_allocate_shm_info (connection,
256
						      stride * height,
257
						      might_reuse,
258
						      &shm_info);
259
    if (unlikely (status)) {
260
	if (status == CAIRO_INT_STATUS_UNSUPPORTED)
261
	    return NULL;
262
 
263
	return _cairo_surface_create_in_error (status);
264
    }
265
 
266
    image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
267
							    pixman_format,
268
							    width, height,
269
							    stride);
270
    if (unlikely (image->status)) {
271
	_cairo_xcb_shm_info_destroy (shm_info);
272
	return image;
273
    }
274
 
275
    status = _cairo_user_data_array_set_data (&image->user_data,
276
					      (const cairo_user_data_key_t *) connection,
277
					      shm_info,
278
					      (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
279
    if (unlikely (status)) {
280
	cairo_surface_destroy (image);
281
	_cairo_xcb_shm_info_destroy (shm_info);
282
	return _cairo_surface_create_in_error (status);
283
    }
284
 
285
    *shm_info_out = shm_info;
286
    return image;
287
}
288
#endif
289
 
290
static cairo_surface_t *
291
_get_shm_image (cairo_xcb_surface_t *surface,
292
		int x, int y,
293
		int width, int height)
294
{
295
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
296
    cairo_xcb_shm_info_t *shm_info;
297
    cairo_surface_t *image;
298
    cairo_status_t status;
299
 
300
    if ((surface->connection->flags & CAIRO_XCB_HAS_SHM) == 0)
301
	return NULL;
302
 
303
    image = _cairo_xcb_surface_create_shm_image (surface->connection,
304
						 surface->pixman_format,
305
						 width, height,
306
						 TRUE,
307
						 &shm_info);
308
    if (unlikely (image == NULL || image->status))
309
	goto done;
310
 
311
    status = _cairo_xcb_connection_shm_get_image (surface->connection,
312
						  surface->drawable,
313
						  x, y,
314
						  width, height,
315
						  shm_info->shm,
316
						  shm_info->offset);
317
    if (unlikely (status)) {
318
	cairo_surface_destroy (image);
319
	image = _cairo_surface_create_in_error (status);
320
    }
321
 
322
done:
323
    return image;
324
#else
325
    return NULL;
326
#endif
327
}
328
 
329
static cairo_surface_t *
330
_get_image (cairo_xcb_surface_t		 *surface,
331
	    cairo_bool_t		  use_shm,
332
	    int x, int y,
333
	    int width, int height)
334
{
335
    cairo_surface_t *image;
336
    cairo_xcb_connection_t *connection;
337
    xcb_get_image_reply_t *reply;
338
    cairo_int_status_t status;
339
 
340
    assert (surface->fallback == NULL);
341
    assert (x >= 0);
342
    assert (y >= 0);
343
    assert (x + width <= surface->width);
344
    assert (y + height <= surface->height);
345
 
346
    if (surface->deferred_clear) {
347
	image =
348
	    _cairo_image_surface_create_with_pixman_format (NULL,
349
							    surface->pixman_format,
350
							    width, height,
351
							    0);
352
	if (surface->deferred_clear_color.alpha_short > 0x00ff) {
353
	    cairo_solid_pattern_t solid;
354
 
355
	    _cairo_pattern_init_solid (&solid, &surface->deferred_clear_color);
356
	    status = _cairo_surface_paint (image,
357
					   CAIRO_OPERATOR_SOURCE,
358
					   &solid.base,
359
					   NULL);
360
	    if (unlikely (status)) {
361
		cairo_surface_destroy (image);
362
		image = _cairo_surface_create_in_error (status);
363
	    }
364
	}
365
	return image;
366
    }
367
 
368
    connection = surface->connection;
369
 
370
    status = _cairo_xcb_connection_acquire (connection);
371
    if (unlikely (status))
372
	return _cairo_surface_create_in_error (status);
373
 
374
    if (use_shm) {
375
	image = _get_shm_image (surface, x, y, width, height);
376
	if (image) {
377
	    if (image->status == CAIRO_STATUS_SUCCESS) {
378
		_cairo_xcb_connection_release (connection);
379
		return image;
380
	    }
381
	    cairo_surface_destroy (image);
382
	}
383
    }
384
 
385
    status = _cairo_xcb_connection_get_image (connection,
386
					      surface->drawable,
387
					      x, y,
388
					      width, height,
389
					      &reply);
390
    if (unlikely (status))
391
	goto FAIL;
392
 
393
    if (reply == NULL && ! surface->owns_pixmap) {
394
	/* xcb_get_image_t from a window is dangerous because it can
395
	 * produce errors if the window is unmapped or partially
396
	 * outside the screen. We could check for errors and
397
	 * retry, but to keep things simple, we just create a
398
	 * temporary pixmap
399
	 *
400
	 * If we hit this fallback too often, we should remember so and
401
	 * skip the round-trip from the above GetImage request,
402
	 * similar to what cairo-xlib does.
403
	 */
404
	xcb_pixmap_t pixmap;
405
	xcb_gcontext_t gc;
406
 
407
	gc = _cairo_xcb_screen_get_gc (surface->screen,
408
				       surface->drawable,
409
				       surface->depth);
410
	pixmap = _cairo_xcb_connection_create_pixmap (connection,
411
						      surface->depth,
412
						      surface->drawable,
413
						      width, height);
414
 
415
	/* XXX IncludeInferiors? */
416
	_cairo_xcb_connection_copy_area (connection,
417
					 surface->drawable,
418
					 pixmap, gc,
419
					 x, y,
420
					 0, 0,
421
					 width, height);
422
 
423
	_cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
424
 
425
	status = _cairo_xcb_connection_get_image (connection,
426
						  pixmap,
427
						  0, 0,
428
						  width, height,
429
						  &reply);
430
	_cairo_xcb_connection_free_pixmap (connection, pixmap);
431
 
432
	if (unlikely (status))
433
	    goto FAIL;
434
    }
435
 
436
    if (unlikely (reply == NULL)) {
437
	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
438
	goto FAIL;
439
    }
440
 
441
    /* XXX byte swap */
442
    /* XXX format conversion */
443
    assert (reply->depth == surface->depth);
444
 
445
    image = _cairo_image_surface_create_with_pixman_format
446
	(xcb_get_image_data (reply),
447
	 surface->pixman_format,
448
	 width, height,
449
	 CAIRO_STRIDE_FOR_WIDTH_BPP (width,
450
				     PIXMAN_FORMAT_BPP (surface->pixman_format)));
451
    status = image->status;
452
    if (unlikely (status)) {
453
	free (reply);
454
	goto FAIL;
455
    }
456
 
457
    /* XXX */
458
    pixman_image_set_destroy_function (((cairo_image_surface_t *)image)->pixman_image, _destroy_image, reply);
459
 
460
    _cairo_xcb_connection_release (connection);
461
 
462
    return image;
463
 
464
FAIL:
465
    _cairo_xcb_connection_release (connection);
466
    return _cairo_surface_create_in_error (status);
467
}
468
 
469
static cairo_surface_t *
470
_cairo_xcb_surface_source (void *abstract_surface,
471
			   cairo_rectangle_int_t *extents)
472
{
473
    cairo_xcb_surface_t *surface = abstract_surface;
474
 
475
    if (extents) {
476
	extents->x = extents->y = 0;
477
	extents->width  = surface->width;
478
	extents->height = surface->height;
479
    }
480
 
481
    return &surface->base;
482
}
483
 
484
static cairo_status_t
485
_cairo_xcb_surface_acquire_source_image (void *abstract_surface,
486
					 cairo_image_surface_t **image_out,
487
					 void **image_extra)
488
{
489
    cairo_xcb_surface_t *surface = abstract_surface;
490
    cairo_surface_t *image;
491
 
492
    if (surface->fallback != NULL) {
493
	image = cairo_surface_reference (&surface->fallback->base);
494
	goto DONE;
495
    }
496
 
497
    image = _cairo_surface_has_snapshot (&surface->base,
498
					 &_cairo_image_surface_backend);
499
    if (image != NULL) {
500
	image = cairo_surface_reference (image);
501
	goto DONE;
502
    }
503
 
504
    image = _get_image (surface, FALSE, 0, 0, surface->width, surface->height);
505
    if (unlikely (image->status))
506
	return image->status;
507
 
508
    _cairo_surface_attach_snapshot (&surface->base, image, NULL);
509
 
510
DONE:
511
    *image_out = (cairo_image_surface_t *) image;
512
    *image_extra = NULL;
513
    return CAIRO_STATUS_SUCCESS;
514
}
515
 
516
static void
517
_cairo_xcb_surface_release_source_image (void *abstract_surface,
518
					 cairo_image_surface_t *image,
519
					 void *image_extra)
520
{
521
    cairo_surface_destroy (&image->base);
522
}
523
 
524
cairo_bool_t
525
_cairo_xcb_surface_get_extents (void *abstract_surface,
526
				cairo_rectangle_int_t *extents)
527
{
528
    cairo_xcb_surface_t *surface = abstract_surface;
529
 
530
    extents->x = extents->y = 0;
531
    extents->width  = surface->width;
532
    extents->height = surface->height;
533
    return TRUE;
534
}
535
 
536
static void
537
_cairo_xcb_surface_get_font_options (void *abstract_surface,
538
				     cairo_font_options_t *options)
539
{
540
    /* XXX  copy from xlib */
541
    _cairo_font_options_init_default (options);
542
    _cairo_font_options_set_round_glyph_positions (options, CAIRO_ROUND_GLYPH_POS_ON);
543
}
544
 
545
static cairo_status_t
546
_put_shm_image (cairo_xcb_surface_t    *surface,
547
		xcb_gcontext_t		gc,
548
		cairo_image_surface_t  *image)
549
{
550
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
551
    cairo_xcb_shm_info_t *shm_info;
552
 
553
    shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
554
						(const cairo_user_data_key_t *) surface->connection);
555
    if (shm_info == NULL)
556
	return CAIRO_INT_STATUS_UNSUPPORTED;
557
 
558
    _cairo_xcb_connection_shm_put_image (surface->connection,
559
					 surface->drawable,
560
					 gc,
561
					 surface->width, surface->height,
562
					 0, 0,
563
					 image->width, image->height,
564
					 image->base.device_transform_inverse.x0,
565
					 image->base.device_transform_inverse.y0,
566
					 image->depth,
567
					 shm_info->shm,
568
					 shm_info->offset);
569
 
570
    return CAIRO_STATUS_SUCCESS;
571
#else
572
    return CAIRO_INT_STATUS_UNSUPPORTED;
573
#endif
574
}
575
 
576
static cairo_status_t
577
_put_image (cairo_xcb_surface_t    *surface,
578
	    cairo_image_surface_t  *image)
579
{
580
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
581
 
582
    /* XXX track damaged region? */
583
 
584
    status = _cairo_xcb_connection_acquire (surface->connection);
585
    if (unlikely (status))
586
	return status;
587
 
588
    if (image->pixman_format == surface->pixman_format) {
589
	xcb_gcontext_t gc;
590
 
591
	assert (image->depth == surface->depth);
592
	assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
593
 
594
	gc = _cairo_xcb_screen_get_gc (surface->screen,
595
				       surface->drawable,
596
				       surface->depth);
597
 
598
	status = _put_shm_image (surface, gc, image);
599
	if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
600
	    _cairo_xcb_connection_put_image (surface->connection,
601
					     surface->drawable, gc,
602
					     image->width, image->height,
603
					     image->base.device_transform_inverse.x0,
604
					     image->base.device_transform_inverse.y0,
605
					     image->depth,
606
					     image->stride,
607
					     image->data);
608
	    status = CAIRO_STATUS_SUCCESS;
609
	}
610
 
611
	_cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
612
    } else {
613
	ASSERT_NOT_REACHED;
614
    }
615
 
616
    _cairo_xcb_connection_release (surface->connection);
617
    return status;
618
}
619
 
620
static cairo_int_status_t
621
_put_shm_image_boxes (cairo_xcb_surface_t    *surface,
622
		      cairo_image_surface_t  *image,
623
		      xcb_gcontext_t gc,
624
		      cairo_boxes_t *boxes)
625
{
626
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
627
    cairo_xcb_shm_info_t *shm_info;
628
 
629
    shm_info = _cairo_user_data_array_get_data (&image->base.user_data,
630
						(const cairo_user_data_key_t *) surface->connection);
631
    if (shm_info != NULL) {
632
	struct _cairo_boxes_chunk *chunk;
633
 
634
	for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
635
	    int i;
636
 
637
	    for (i = 0; i < chunk->count; i++) {
638
		cairo_box_t *b = &chunk->base[i];
639
		int x = _cairo_fixed_integer_part (b->p1.x);
640
		int y = _cairo_fixed_integer_part (b->p1.y);
641
		int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
642
		int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
643
 
644
		_cairo_xcb_connection_shm_put_image (surface->connection,
645
						     surface->drawable,
646
						     gc,
647
						     surface->width, surface->height,
648
						     x, y,
649
						     width, height,
650
						     x, y,
651
						     image->depth,
652
						     shm_info->shm,
653
						     shm_info->offset);
654
	    }
655
	}
656
    }
657
 
658
    return CAIRO_INT_STATUS_SUCCESS;
659
#endif
660
 
661
    return CAIRO_INT_STATUS_UNSUPPORTED;
662
}
663
 
664
static cairo_status_t
665
_put_image_boxes (cairo_xcb_surface_t    *surface,
666
		  cairo_image_surface_t  *image,
667
		  cairo_boxes_t *boxes)
668
{
669
    cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
670
    xcb_gcontext_t gc;
671
 
672
    if (boxes->num_boxes == 0)
673
	    return CAIRO_STATUS_SUCCESS;
674
 
675
    /* XXX track damaged region? */
676
 
677
    status = _cairo_xcb_connection_acquire (surface->connection);
678
    if (unlikely (status))
679
	return status;
680
 
681
    assert (image->pixman_format == surface->pixman_format);
682
    assert (image->depth == surface->depth);
683
    assert (image->stride == (int) CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format)));
684
 
685
    gc = _cairo_xcb_screen_get_gc (surface->screen,
686
				   surface->drawable,
687
				   surface->depth);
688
 
689
    status = _put_shm_image_boxes (surface, image, gc, boxes);
690
    if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
691
	    struct _cairo_boxes_chunk *chunk;
692
 
693
	    for (chunk = &boxes->chunks; chunk; chunk = chunk->next) {
694
		    int i;
695
 
696
		    for (i = 0; i < chunk->count; i++) {
697
			    cairo_box_t *b = &chunk->base[i];
698
			    int x = _cairo_fixed_integer_part (b->p1.x);
699
			    int y = _cairo_fixed_integer_part (b->p1.y);
700
			    int width = _cairo_fixed_integer_part (b->p2.x - b->p1.x);
701
			    int height = _cairo_fixed_integer_part (b->p2.y - b->p1.y);
702
			    _cairo_xcb_connection_put_image (surface->connection,
703
							     surface->drawable, gc,
704
							     width, height,
705
							     x, y,
706
							     image->depth,
707
							     image->stride,
708
							     image->data +
709
							     x * PIXMAN_FORMAT_BPP (image->pixman_format) / 8 +
710
							     y * image->stride);
711
 
712
		    }
713
	    }
714
	    status = CAIRO_STATUS_SUCCESS;
715
    }
716
 
717
    _cairo_xcb_screen_put_gc (surface->screen, surface->depth, gc);
718
    _cairo_xcb_connection_release (surface->connection);
719
    return status;
720
}
721
 
722
static cairo_status_t
723
_cairo_xcb_surface_flush (void *abstract_surface,
724
			  unsigned flags)
725
{
726
    cairo_xcb_surface_t *surface = abstract_surface;
727
    cairo_status_t status;
728
 
729
    if (flags)
730
	return CAIRO_STATUS_SUCCESS;
731
 
732
    if (likely (surface->fallback == NULL)) {
733
	status = CAIRO_STATUS_SUCCESS;
734
	if (! surface->base.finished && surface->deferred_clear)
735
	    status = _cairo_xcb_surface_clear (surface);
736
 
737
	return status;
738
    }
739
 
740
    status = surface->base.status;
741
    if (status == CAIRO_STATUS_SUCCESS &&
742
	(! surface->base._finishing || ! surface->owns_pixmap)) {
743
	status = cairo_surface_status (&surface->fallback->base);
744
 
745
	if (status == CAIRO_STATUS_SUCCESS)
746
		status = _cairo_bentley_ottmann_tessellate_boxes (&surface->fallback_damage,
747
								  CAIRO_FILL_RULE_WINDING,
748
								  &surface->fallback_damage);
749
 
750
	if (status == CAIRO_STATUS_SUCCESS)
751
	    status = _put_image_boxes (surface,
752
				       surface->fallback,
753
				       &surface->fallback_damage);
754
 
755
	if (status == CAIRO_STATUS_SUCCESS && ! surface->base._finishing) {
756
	    _cairo_surface_attach_snapshot (&surface->base,
757
					    &surface->fallback->base,
758
					    cairo_surface_finish);
759
	}
760
    }
761
 
762
    _cairo_boxes_clear (&surface->fallback_damage);
763
    cairo_surface_destroy (&surface->fallback->base);
764
    surface->fallback = NULL;
765
 
766
    return status;
767
}
768
 
769
static cairo_image_surface_t *
770
_cairo_xcb_surface_map_to_image (void *abstract_surface,
771
				 const cairo_rectangle_int_t *extents)
772
{
773
    cairo_xcb_surface_t *surface = abstract_surface;
774
    cairo_surface_t *image;
775
    cairo_status_t status;
776
 
777
    if (surface->fallback)
778
	return _cairo_surface_map_to_image (&surface->fallback->base, extents);
779
 
780
    image = _get_image (surface, TRUE,
781
			extents->x, extents->y,
782
			extents->width, extents->height);
783
    status = cairo_surface_status (image);
784
    if (unlikely (status)) {
785
	cairo_surface_destroy(image);
786
	return _cairo_image_surface_create_in_error (status);
787
    }
788
 
789
    /* Do we have a deferred clear and this image surface does NOT cover the
790
     * whole xcb surface? Have to apply the clear in that case, else
791
     * uploading the image will handle the problem for us.
792
     */
793
    if (surface->deferred_clear &&
794
	! (extents->width == surface->width &&
795
	   extents->height == surface->height)) {
796
	status = _cairo_xcb_surface_clear (surface);
797
	if (unlikely (status)) {
798
	    cairo_surface_destroy(image);
799
	    return _cairo_image_surface_create_in_error (status);
800
	}
801
    }
802
    surface->deferred_clear = FALSE;
803
 
804
    cairo_surface_set_device_offset (image, -extents->x, -extents->y);
805
    return (cairo_image_surface_t *) image;
806
}
807
 
808
static cairo_int_status_t
809
_cairo_xcb_surface_unmap (void *abstract_surface,
810
			  cairo_image_surface_t *image)
811
{
812
    cairo_xcb_surface_t *surface = abstract_surface;
813
    cairo_int_status_t status;
814
 
815
    if (surface->fallback)
816
	return _cairo_surface_unmap_image (&surface->fallback->base, image);
817
 
818
    status = _put_image (abstract_surface, image);
819
 
820
    cairo_surface_finish (&image->base);
821
    cairo_surface_destroy (&image->base);
822
 
823
    return status;
824
}
825
 
826
static cairo_surface_t *
827
_cairo_xcb_surface_fallback (cairo_xcb_surface_t *surface,
828
			     cairo_composite_rectangles_t *composite)
829
{
830
    cairo_image_surface_t *image;
831
    cairo_status_t status;
832
 
833
    status = _cairo_composite_rectangles_add_to_damage (composite,
834
							&surface->fallback_damage);
835
    if (unlikely (status))
836
	    return _cairo_surface_create_in_error (status);
837
 
838
    if (surface->fallback)
839
	return &surface->fallback->base;
840
 
841
    image = (cairo_image_surface_t *)
842
	    _get_image (surface, TRUE, 0, 0, surface->width, surface->height);
843
 
844
    /* If there was a deferred clear, _get_image applied it */
845
    if (image->base.status == CAIRO_STATUS_SUCCESS) {
846
	surface->deferred_clear = FALSE;
847
 
848
	surface->fallback = image;
849
    }
850
 
851
    return &surface->fallback->base;
852
}
853
 
854
static cairo_int_status_t
855
_cairo_xcb_fallback_compositor_paint (const cairo_compositor_t     *compositor,
856
				      cairo_composite_rectangles_t *extents)
857
{
858
    cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
859
    cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
860
 
861
    return _cairo_surface_paint (fallback, extents->op,
862
				 &extents->source_pattern.base,
863
				 extents->clip);
864
}
865
 
866
static cairo_int_status_t
867
_cairo_xcb_fallback_compositor_mask (const cairo_compositor_t     *compositor,
868
				     cairo_composite_rectangles_t *extents)
869
{
870
    cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
871
    cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
872
 
873
    return _cairo_surface_mask (fallback, extents->op,
874
				 &extents->source_pattern.base,
875
				 &extents->mask_pattern.base,
876
				 extents->clip);
877
}
878
 
879
static cairo_int_status_t
880
_cairo_xcb_fallback_compositor_stroke (const cairo_compositor_t     *compositor,
881
				       cairo_composite_rectangles_t *extents,
882
				       const cairo_path_fixed_t     *path,
883
				       const cairo_stroke_style_t   *style,
884
				       const cairo_matrix_t         *ctm,
885
				       const cairo_matrix_t         *ctm_inverse,
886
				       double                        tolerance,
887
				       cairo_antialias_t             antialias)
888
{
889
    cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
890
    cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
891
 
892
    return _cairo_surface_stroke (fallback, extents->op,
893
				  &extents->source_pattern.base,
894
				  path, style, ctm, ctm_inverse,
895
				  tolerance, antialias,
896
				  extents->clip);
897
}
898
 
899
static cairo_int_status_t
900
_cairo_xcb_fallback_compositor_fill (const cairo_compositor_t     *compositor,
901
				     cairo_composite_rectangles_t *extents,
902
				     const cairo_path_fixed_t     *path,
903
				     cairo_fill_rule_t             fill_rule,
904
				     double                        tolerance,
905
				     cairo_antialias_t             antialias)
906
{
907
    cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
908
    cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
909
 
910
    return _cairo_surface_fill (fallback, extents->op,
911
				&extents->source_pattern.base,
912
				path, fill_rule, tolerance,
913
				antialias, extents->clip);
914
}
915
 
916
static cairo_int_status_t
917
_cairo_xcb_fallback_compositor_glyphs (const cairo_compositor_t     *compositor,
918
				       cairo_composite_rectangles_t *extents,
919
				       cairo_scaled_font_t          *scaled_font,
920
				       cairo_glyph_t                *glyphs,
921
				       int                           num_glyphs,
922
				       cairo_bool_t                  overlap)
923
{
924
    cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) extents->surface;
925
    cairo_surface_t *fallback = _cairo_xcb_surface_fallback (surface, extents);
926
 
927
    return _cairo_surface_show_text_glyphs (fallback, extents->op,
928
					    &extents->source_pattern.base,
929
					    NULL, 0, glyphs, num_glyphs,
930
					    NULL, 0, 0,
931
					    scaled_font, extents->clip);
932
}
933
 
934
static const cairo_compositor_t _cairo_xcb_fallback_compositor = {
935
    &__cairo_no_compositor,
936
 
937
    _cairo_xcb_fallback_compositor_paint,
938
    _cairo_xcb_fallback_compositor_mask,
939
    _cairo_xcb_fallback_compositor_stroke,
940
    _cairo_xcb_fallback_compositor_fill,
941
    _cairo_xcb_fallback_compositor_glyphs,
942
};
943
 
944
static const cairo_compositor_t _cairo_xcb_render_compositor = {
945
    &_cairo_xcb_fallback_compositor,
946
 
947
    _cairo_xcb_render_compositor_paint,
948
    _cairo_xcb_render_compositor_mask,
949
    _cairo_xcb_render_compositor_stroke,
950
    _cairo_xcb_render_compositor_fill,
951
    _cairo_xcb_render_compositor_glyphs,
952
};
953
 
954
static inline const cairo_compositor_t *
955
get_compositor (cairo_surface_t **s)
956
{
957
    cairo_xcb_surface_t *surface = (cairo_xcb_surface_t * )*s;
958
    if (surface->fallback) {
959
	*s = &surface->fallback->base;
960
	return ((cairo_image_surface_t *) *s)->compositor;
961
    }
962
 
963
    return &_cairo_xcb_render_compositor;
964
}
965
 
966
static cairo_int_status_t
967
_cairo_xcb_surface_paint (void			*abstract_surface,
968
			  cairo_operator_t	 op,
969
			  const cairo_pattern_t	*source,
970
			  const cairo_clip_t	*clip)
971
{
972
    cairo_surface_t *surface = abstract_surface;
973
    const cairo_compositor_t *compositor = get_compositor (&surface);
974
    return _cairo_compositor_paint (compositor, surface, op, source, clip);
975
}
976
 
977
static cairo_int_status_t
978
_cairo_xcb_surface_mask (void			*abstract_surface,
979
			 cairo_operator_t	 op,
980
			 const cairo_pattern_t	*source,
981
			 const cairo_pattern_t	*mask,
982
			 const cairo_clip_t	*clip)
983
{
984
    cairo_surface_t *surface = abstract_surface;
985
    const cairo_compositor_t *compositor = get_compositor (&surface);
986
    return _cairo_compositor_mask (compositor, surface, op, source, mask, clip);
987
}
988
 
989
static cairo_int_status_t
990
_cairo_xcb_surface_stroke (void				*abstract_surface,
991
			   cairo_operator_t		 op,
992
			   const cairo_pattern_t	*source,
993
			   const cairo_path_fixed_t	*path,
994
			   const cairo_stroke_style_t	*style,
995
			   const cairo_matrix_t		*ctm,
996
			   const cairo_matrix_t		*ctm_inverse,
997
			   double			 tolerance,
998
			   cairo_antialias_t		 antialias,
999
			   const cairo_clip_t		*clip)
1000
{
1001
    cairo_surface_t *surface = abstract_surface;
1002
    const cairo_compositor_t *compositor = get_compositor (&surface);
1003
    return _cairo_compositor_stroke (compositor, surface, op, source,
1004
				     path, style, ctm, ctm_inverse,
1005
				     tolerance, antialias, clip);
1006
}
1007
 
1008
static cairo_int_status_t
1009
_cairo_xcb_surface_fill (void			*abstract_surface,
1010
			 cairo_operator_t	 op,
1011
			 const cairo_pattern_t	*source,
1012
			 const cairo_path_fixed_t*path,
1013
			 cairo_fill_rule_t	 fill_rule,
1014
			 double			 tolerance,
1015
			 cairo_antialias_t	 antialias,
1016
			 const cairo_clip_t	*clip)
1017
{
1018
    cairo_surface_t *surface = abstract_surface;
1019
    const cairo_compositor_t *compositor = get_compositor (&surface);
1020
    return _cairo_compositor_fill (compositor, surface, op,
1021
				   source, path, fill_rule,
1022
				   tolerance, antialias, clip);
1023
}
1024
 
1025
static cairo_int_status_t
1026
_cairo_xcb_surface_glyphs (void				*abstract_surface,
1027
			   cairo_operator_t		 op,
1028
			   const cairo_pattern_t	*source,
1029
			   cairo_glyph_t		*glyphs,
1030
			   int				 num_glyphs,
1031
			   cairo_scaled_font_t		*scaled_font,
1032
			   const cairo_clip_t		*clip)
1033
{
1034
    cairo_surface_t *surface = abstract_surface;
1035
    const cairo_compositor_t *compositor = get_compositor (&surface);
1036
    return _cairo_compositor_glyphs (compositor, surface, op,
1037
				     source, glyphs, num_glyphs,
1038
				     scaled_font, clip);
1039
}
1040
 
1041
const cairo_surface_backend_t _cairo_xcb_surface_backend = {
1042
    CAIRO_SURFACE_TYPE_XCB,
1043
    _cairo_xcb_surface_finish,
1044
    _cairo_default_context_create,
1045
 
1046
    _cairo_xcb_surface_create_similar,
1047
    _cairo_xcb_surface_create_similar_image,
1048
    _cairo_xcb_surface_map_to_image,
1049
    _cairo_xcb_surface_unmap,
1050
 
1051
    _cairo_xcb_surface_source,
1052
    _cairo_xcb_surface_acquire_source_image,
1053
    _cairo_xcb_surface_release_source_image,
1054
    NULL, /* snapshot */
1055
 
1056
 
1057
    NULL, /* copy_page */
1058
    NULL, /* show_page */
1059
 
1060
    _cairo_xcb_surface_get_extents,
1061
    _cairo_xcb_surface_get_font_options,
1062
 
1063
    _cairo_xcb_surface_flush,
1064
    NULL,
1065
 
1066
    _cairo_xcb_surface_paint,
1067
    _cairo_xcb_surface_mask,
1068
    _cairo_xcb_surface_stroke,
1069
    _cairo_xcb_surface_fill,
1070
    NULL, /* fill-stroke */
1071
    _cairo_xcb_surface_glyphs,
1072
};
1073
 
1074
cairo_surface_t *
1075
_cairo_xcb_surface_create_internal (cairo_xcb_screen_t		*screen,
1076
				    xcb_drawable_t		 drawable,
1077
				    cairo_bool_t		 owns_pixmap,
1078
				    pixman_format_code_t	 pixman_format,
1079
				    xcb_render_pictformat_t	 xrender_format,
1080
				    int				 width,
1081
				    int				 height)
1082
{
1083
    cairo_xcb_surface_t *surface;
1084
 
1085
    surface = malloc (sizeof (cairo_xcb_surface_t));
1086
    if (unlikely (surface == NULL))
1087
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1088
 
1089
    _cairo_surface_init (&surface->base,
1090
			 &_cairo_xcb_surface_backend,
1091
			 &screen->connection->device,
1092
			 _cairo_content_from_pixman_format (pixman_format));
1093
 
1094
    surface->connection = _cairo_xcb_connection_reference (screen->connection);
1095
    surface->screen = screen;
1096
    cairo_list_add (&surface->link, &screen->surfaces);
1097
 
1098
    surface->drawable = drawable;
1099
    surface->owns_pixmap = owns_pixmap;
1100
 
1101
    surface->deferred_clear = FALSE;
1102
    surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
1103
 
1104
    surface->width  = width;
1105
    surface->height = height;
1106
    surface->depth  = PIXMAN_FORMAT_DEPTH (pixman_format);
1107
 
1108
    surface->picture = XCB_NONE;
1109
    if (screen->connection->force_precision != -1)
1110
	surface->precision = screen->connection->force_precision;
1111
    else
1112
	surface->precision = XCB_RENDER_POLY_MODE_IMPRECISE;
1113
 
1114
    surface->pixman_format = pixman_format;
1115
    surface->xrender_format = xrender_format;
1116
 
1117
    surface->fallback = NULL;
1118
    _cairo_boxes_init (&surface->fallback_damage);
1119
 
1120
    return &surface->base;
1121
}
1122
 
1123
static xcb_screen_t *
1124
_cairo_xcb_screen_from_visual (xcb_connection_t *connection,
1125
			       xcb_visualtype_t *visual,
1126
			       int *depth)
1127
{
1128
    xcb_depth_iterator_t d;
1129
    xcb_screen_iterator_t s;
1130
 
1131
    s = xcb_setup_roots_iterator (xcb_get_setup (connection));
1132
    for (; s.rem; xcb_screen_next (&s)) {
1133
	if (s.data->root_visual == visual->visual_id) {
1134
	    *depth = s.data->root_depth;
1135
	    return s.data;
1136
	}
1137
 
1138
	d = xcb_screen_allowed_depths_iterator(s.data);
1139
	for (; d.rem; xcb_depth_next (&d)) {
1140
	    xcb_visualtype_iterator_t v = xcb_depth_visuals_iterator (d.data);
1141
 
1142
	    for (; v.rem; xcb_visualtype_next (&v)) {
1143
		if (v.data->visual_id == visual->visual_id) {
1144
		    *depth = d.data->depth;
1145
		    return s.data;
1146
		}
1147
	    }
1148
	}
1149
    }
1150
 
1151
    return NULL;
1152
}
1153
 
1154
/**
1155
 * cairo_xcb_surface_create:
1156
 * @connection: an XCB connection
1157
 * @drawable: an XCB drawable
1158
 * @visual: the visual to use for drawing to @drawable. The depth
1159
 *          of the visual must match the depth of the drawable.
1160
 *          Currently, only TrueColor visuals are fully supported.
1161
 * @width: the current width of @drawable
1162
 * @height: the current height of @drawable
1163
 *
1164
 * Creates an XCB surface that draws to the given drawable.
1165
 * The way that colors are represented in the drawable is specified
1166
 * by the provided visual.
1167
 *
1168
 * Note: If @drawable is a Window, then the function
1169
 * cairo_xcb_surface_set_size() must be called whenever the size of the
1170
 * window changes.
1171
 *
1172
 * When @drawable is a Window containing child windows then drawing to
1173
 * the created surface will be clipped by those child windows.  When
1174
 * the created surface is used as a source, the contents of the
1175
 * children will be included.
1176
 *
1177
 * Return value: a pointer to the newly created surface. The caller
1178
 * owns the surface and should call cairo_surface_destroy() when done
1179
 * with it.
1180
 *
1181
 * This function always returns a valid pointer, but it will return a
1182
 * pointer to a "nil" surface if an error such as out of memory
1183
 * occurs. You can use cairo_surface_status() to check for this.
1184
 *
1185
 * Since: 1.12
1186
 **/
1187
cairo_surface_t *
1188
cairo_xcb_surface_create (xcb_connection_t  *connection,
1189
			  xcb_drawable_t     drawable,
1190
			  xcb_visualtype_t  *visual,
1191
			  int		     width,
1192
			  int		     height)
1193
{
1194
    cairo_xcb_screen_t *screen;
1195
    xcb_screen_t *xcb_screen;
1196
    cairo_format_masks_t image_masks;
1197
    pixman_format_code_t pixman_format;
1198
    xcb_render_pictformat_t xrender_format;
1199
    int depth;
1200
 
1201
    if (xcb_connection_has_error (connection))
1202
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1203
 
1204
    if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
1205
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1206
    if (unlikely (width <= 0 || height <= 0))
1207
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1208
 
1209
    xcb_screen = _cairo_xcb_screen_from_visual (connection, visual, &depth);
1210
    if (unlikely (xcb_screen == NULL))
1211
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
1212
 
1213
    image_masks.alpha_mask = 0;
1214
    image_masks.red_mask   = visual->red_mask;
1215
    image_masks.green_mask = visual->green_mask;
1216
    image_masks.blue_mask  = visual->blue_mask;
1217
    if (depth == 32) /* XXX visuals have no alpha! */
1218
	image_masks.alpha_mask =
1219
	    0xffffffff & ~(visual->red_mask | visual->green_mask | visual->blue_mask);
1220
    if (depth > 16)
1221
	image_masks.bpp = 32;
1222
    else if (depth > 8)
1223
	image_masks.bpp = 16;
1224
    else if (depth > 1)
1225
	image_masks.bpp = 8;
1226
    else
1227
	image_masks.bpp = 1;
1228
 
1229
    if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1230
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1231
 
1232
    screen = _cairo_xcb_screen_get (connection, xcb_screen);
1233
    if (unlikely (screen == NULL))
1234
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1235
 
1236
    xrender_format =
1237
	_cairo_xcb_connection_get_xrender_format_for_visual (screen->connection,
1238
							     visual->visual_id);
1239
 
1240
    return _cairo_xcb_surface_create_internal (screen, drawable, FALSE,
1241
					       pixman_format,
1242
					       xrender_format,
1243
					       width, height);
1244
}
1245
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1246
slim_hidden_def (cairo_xcb_surface_create);
1247
#endif
1248
 
1249
/**
1250
 * cairo_xcb_surface_create_for_bitmap:
1251
 * @connection: an XCB connection
1252
 * @screen: the XCB screen associated with @bitmap
1253
 * @bitmap: an XCB drawable (a Pixmap with depth 1)
1254
 * @width: the current width of @bitmap
1255
 * @height: the current height of @bitmap
1256
 *
1257
 * Creates an XCB surface that draws to the given bitmap.
1258
 * This will be drawn to as a %CAIRO_FORMAT_A1 object.
1259
 *
1260
 * Return value: a pointer to the newly created surface. The caller
1261
 * owns the surface and should call cairo_surface_destroy() when done
1262
 * with it.
1263
 *
1264
 * This function always returns a valid pointer, but it will return a
1265
 * pointer to a "nil" surface if an error such as out of memory
1266
 * occurs. You can use cairo_surface_status() to check for this.
1267
 *
1268
 * Since: 1.12
1269
 **/
1270
cairo_surface_t *
1271
cairo_xcb_surface_create_for_bitmap (xcb_connection_t	*connection,
1272
				     xcb_screen_t	*screen,
1273
				     xcb_pixmap_t	 bitmap,
1274
				     int		 width,
1275
				     int		 height)
1276
{
1277
    cairo_xcb_screen_t *cairo_xcb_screen;
1278
 
1279
    if (xcb_connection_has_error (connection))
1280
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1281
 
1282
    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1283
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1284
    if (unlikely (width <= 0 || height <= 0))
1285
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1286
 
1287
    cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1288
    if (unlikely (cairo_xcb_screen == NULL))
1289
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1290
 
1291
    return _cairo_xcb_surface_create_internal (cairo_xcb_screen, bitmap, FALSE,
1292
					       PIXMAN_a1,
1293
					       cairo_xcb_screen->connection->standard_formats[CAIRO_FORMAT_A1],
1294
					       width, height);
1295
}
1296
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1297
slim_hidden_def (cairo_xcb_surface_create_for_bitmap);
1298
#endif
1299
 
1300
/**
1301
 * cairo_xcb_surface_create_with_xrender_format:
1302
 * @connection: an XCB connection
1303
 * @drawable: an XCB drawable
1304
 * @screen: the XCB screen associated with @drawable
1305
 * @format: the picture format to use for drawing to @drawable. The
1306
 *          depth of @format mush match the depth of the drawable.
1307
 * @width: the current width of @drawable
1308
 * @height: the current height of @drawable
1309
 *
1310
 * Creates an XCB surface that draws to the given drawable.
1311
 * The way that colors are represented in the drawable is specified
1312
 * by the provided picture format.
1313
 *
1314
 * Note: If @drawable is a Window, then the function
1315
 * cairo_xcb_surface_set_size() must be called whenever the size of the
1316
 * window changes.
1317
 *
1318
 * When @drawable is a Window containing child windows then drawing to
1319
 * the created surface will be clipped by those child windows.  When
1320
 * the created surface is used as a source, the contents of the
1321
 * children will be included.
1322
 *
1323
 * Return value: a pointer to the newly created surface. The caller
1324
 * owns the surface and should call cairo_surface_destroy() when done
1325
 * with it.
1326
 *
1327
 * This function always returns a valid pointer, but it will return a
1328
 * pointer to a "nil" surface if an error such as out of memory
1329
 * occurs. You can use cairo_surface_status() to check for this.
1330
 *
1331
 * Since: 1.12
1332
 **/
1333
cairo_surface_t *
1334
cairo_xcb_surface_create_with_xrender_format (xcb_connection_t	    *connection,
1335
					      xcb_screen_t	    *screen,
1336
					      xcb_drawable_t	     drawable,
1337
					      xcb_render_pictforminfo_t *format,
1338
					      int		     width,
1339
					      int		     height)
1340
{
1341
    cairo_xcb_screen_t *cairo_xcb_screen;
1342
    cairo_format_masks_t image_masks;
1343
    pixman_format_code_t pixman_format;
1344
 
1345
    if (xcb_connection_has_error (connection))
1346
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_WRITE_ERROR));
1347
 
1348
    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
1349
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1350
    if (unlikely (width <= 0 || height <= 0))
1351
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
1352
 
1353
    image_masks.alpha_mask =
1354
	(unsigned long) format->direct.alpha_mask << format->direct.alpha_shift;
1355
    image_masks.red_mask =
1356
	(unsigned long) format->direct.red_mask << format->direct.red_shift;
1357
    image_masks.green_mask =
1358
	(unsigned long) format->direct.green_mask << format->direct.green_shift;
1359
    image_masks.blue_mask =
1360
	(unsigned long) format->direct.blue_mask << format->direct.blue_shift;
1361
#if 0
1362
    image_masks.bpp = format->depth;
1363
#else
1364
    if (format->depth > 16)
1365
	image_masks.bpp = 32;
1366
    else if (format->depth > 8)
1367
	image_masks.bpp = 16;
1368
    else if (format->depth > 1)
1369
	image_masks.bpp = 8;
1370
    else
1371
	image_masks.bpp = 1;
1372
#endif
1373
 
1374
    if (! _pixman_format_from_masks (&image_masks, &pixman_format))
1375
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
1376
 
1377
    cairo_xcb_screen = _cairo_xcb_screen_get (connection, screen);
1378
    if (unlikely (cairo_xcb_screen == NULL))
1379
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1380
 
1381
    return _cairo_xcb_surface_create_internal (cairo_xcb_screen,
1382
					       drawable,
1383
					       FALSE,
1384
					       pixman_format,
1385
					       format->id,
1386
					       width, height);
1387
}
1388
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1389
slim_hidden_def (cairo_xcb_surface_create_with_xrender_format);
1390
#endif
1391
 
1392
/* This does the necessary fixup when a surface's drawable or size changed. */
1393
static void
1394
_drawable_changed (cairo_xcb_surface_t *surface)
1395
{
1396
    _cairo_surface_set_error (&surface->base,
1397
	    _cairo_surface_begin_modification (&surface->base));
1398
    _cairo_boxes_clear (&surface->fallback_damage);
1399
    cairo_surface_destroy (&surface->fallback->base);
1400
 
1401
    surface->deferred_clear = FALSE;
1402
    surface->fallback = NULL;
1403
}
1404
 
1405
/**
1406
 * cairo_xcb_surface_set_size:
1407
 * @surface: a #cairo_surface_t for the XCB backend
1408
 * @width: the new width of the surface
1409
 * @height: the new height of the surface
1410
 *
1411
 * Informs cairo of the new size of the XCB drawable underlying the
1412
 * surface. For a surface created for a window (rather than a pixmap),
1413
 * this function must be called each time the size of the window
1414
 * changes. (For a subwindow, you are normally resizing the window
1415
 * yourself, but for a toplevel window, it is necessary to listen for
1416
 * ConfigureNotify events.)
1417
 *
1418
 * A pixmap can never change size, so it is never necessary to call
1419
 * this function on a surface created for a pixmap.
1420
 *
1421
 * If cairo_surface_flush() wasn't called, some pending operations
1422
 * might be discarded.
1423
 *
1424
 * Since: 1.12
1425
 **/
1426
void
1427
cairo_xcb_surface_set_size (cairo_surface_t *abstract_surface,
1428
			    int              width,
1429
			    int              height)
1430
{
1431
    cairo_xcb_surface_t *surface;
1432
 
1433
    if (unlikely (abstract_surface->status))
1434
	return;
1435
    if (unlikely (abstract_surface->finished)) {
1436
	_cairo_surface_set_error (abstract_surface,
1437
				  _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1438
	return;
1439
    }
1440
 
1441
 
1442
    if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1443
	_cairo_surface_set_error (abstract_surface,
1444
				  _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1445
	return;
1446
    }
1447
 
1448
    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1449
	_cairo_surface_set_error (abstract_surface,
1450
				  _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1451
	return;
1452
    }
1453
 
1454
    surface = (cairo_xcb_surface_t *) abstract_surface;
1455
 
1456
    _drawable_changed(surface);
1457
    surface->width  = width;
1458
    surface->height = height;
1459
}
1460
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1461
slim_hidden_def (cairo_xcb_surface_set_size);
1462
#endif
1463
 
1464
/**
1465
 * cairo_xcb_surface_set_drawable:
1466
 * @surface: a #cairo_surface_t for the XCB backend
1467
 * @drawable: the new drawable of the surface
1468
 * @width: the new width of the surface
1469
 * @height: the new height of the surface
1470
 *
1471
 * Informs cairo of the new drawable and size of the XCB drawable underlying the
1472
 * surface.
1473
 *
1474
 * If cairo_surface_flush() wasn't called, some pending operations
1475
 * might be discarded.
1476
 *
1477
 * Since: 1.12
1478
 **/
1479
void
1480
cairo_xcb_surface_set_drawable (cairo_surface_t *abstract_surface,
1481
				xcb_drawable_t  drawable,
1482
				int             width,
1483
				int             height)
1484
{
1485
    cairo_xcb_surface_t *surface;
1486
 
1487
    if (unlikely (abstract_surface->status))
1488
	return;
1489
    if (unlikely (abstract_surface->finished)) {
1490
	_cairo_surface_set_error (abstract_surface,
1491
				  _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
1492
	return;
1493
    }
1494
 
1495
 
1496
    if (abstract_surface->type != CAIRO_SURFACE_TYPE_XCB) {
1497
	_cairo_surface_set_error (abstract_surface,
1498
				  _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
1499
	return;
1500
    }
1501
 
1502
    if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX || width <= 0 || height <= 0) {
1503
	_cairo_surface_set_error (abstract_surface,
1504
				  _cairo_error (CAIRO_STATUS_INVALID_SIZE));
1505
	return;
1506
    }
1507
 
1508
    surface = (cairo_xcb_surface_t *) abstract_surface;
1509
 
1510
    /* XXX: and what about this case? */
1511
    if (surface->owns_pixmap)
1512
	    return;
1513
 
1514
    _drawable_changed (surface);
1515
 
1516
    if (surface->drawable != drawable) {
1517
	    cairo_status_t status;
1518
	    status = _cairo_xcb_connection_acquire (surface->connection);
1519
	    if (unlikely (status))
1520
		    return;
1521
 
1522
	    if (surface->picture != XCB_NONE) {
1523
		    _cairo_xcb_connection_render_free_picture (surface->connection,
1524
							       surface->picture);
1525
		    surface->picture = XCB_NONE;
1526
	    }
1527
 
1528
	    _cairo_xcb_connection_release (surface->connection);
1529
 
1530
	    surface->drawable = drawable;
1531
    }
1532
    surface->width  = width;
1533
    surface->height = height;
1534
}
1535
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1536
slim_hidden_def (cairo_xcb_surface_set_drawable);
1537
#endif