1
/* cairo - a vector graphics library with display and print output
2
 *
3
 * Copyright © 2009 Intel Corporation
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
 * Contributor(s):
29
 *	Chris Wilson <chris@chris-wilson.co.uk>
30
 */
31

            
32
#include "cairoint.h"
33

            
34
#include "cairo-boxes-private.h"
35
#include "cairo-xcb-private.h"
36
#include "cairo-image-surface-private.h"
37
#include "cairo-surface-backend-private.h"
38

            
39
/* XXX dithering */
40

            
41
typedef struct _cairo_xcb_pixmap {
42
    cairo_surface_t base;
43

            
44
    cairo_xcb_connection_t *connection;
45
    cairo_xcb_screen_t *screen;
46

            
47
    cairo_surface_t *owner;
48
    xcb_pixmap_t pixmap;
49
    int width;
50
    int height;
51
    int depth;
52
    int x0, y0;
53
    cairo_bool_t repeat;
54
} cairo_xcb_pixmap_t;
55

            
56
static cairo_status_t
57
_cairo_xcb_pixmap_finish (void *abstract_surface)
58
{
59
    cairo_xcb_pixmap_t *surface = abstract_surface;
60
    cairo_status_t status;
61

            
62
    if (surface->owner != NULL) {
63
	cairo_surface_destroy (surface->owner);
64
    } else {
65
	status = _cairo_xcb_connection_acquire (surface->connection);
66
	if (unlikely (status))
67
	    return status;
68

            
69
	xcb_free_pixmap (surface->connection->xcb_connection,
70
					   surface->pixmap);
71
	_cairo_xcb_connection_release (surface->connection);
72
    }
73

            
74
    return CAIRO_STATUS_SUCCESS;
75
}
76

            
77
static const cairo_surface_backend_t _cairo_xcb_pixmap_backend = {
78
    CAIRO_SURFACE_TYPE_XCB,
79
    _cairo_xcb_pixmap_finish,
80
};
81

            
82
static cairo_xcb_pixmap_t *
83
_cairo_xcb_pixmap_create (cairo_xcb_surface_t *target,
84
			  int width, int height)
85
{
86
    cairo_xcb_pixmap_t *surface;
87

            
88
    surface = _cairo_calloc (sizeof (cairo_xcb_pixmap_t));
89
    if (unlikely (surface == NULL))
90
	return (cairo_xcb_pixmap_t *)
91
	    _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
92

            
93
    _cairo_surface_init (&surface->base,
94
			 &_cairo_xcb_pixmap_backend,
95
			 NULL,
96
			 target->base.content,
97
			 FALSE); /* is_vector */
98

            
99
    surface->connection = target->connection;
100
    surface->screen = target->screen;
101
    surface->owner = NULL;
102
    surface->width = width;
103
    surface->height = height;
104
    surface->depth = target->depth;
105
    surface->x0 = surface->y0 = 0;
106
    surface->repeat = FALSE;
107

            
108
    surface->pixmap =
109
	_cairo_xcb_connection_create_pixmap (surface->connection,
110
					     surface->depth,
111
					     target->drawable,
112
					     width, height);
113

            
114
    return surface;
115
}
116

            
117
static cairo_xcb_pixmap_t *
118
_cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target)
119
{
120
    cairo_xcb_pixmap_t *surface;
121

            
122
    surface = _cairo_calloc (sizeof (cairo_xcb_pixmap_t));
123
    if (unlikely (surface == NULL))
124
	return (cairo_xcb_pixmap_t *)
125
	    _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
126

            
127
    _cairo_surface_init (&surface->base,
128
			 &_cairo_xcb_pixmap_backend,
129
			 NULL,
130
			 target->base.content,
131
			 FALSE); /* is_vector */
132

            
133
    surface->connection = target->connection;
134
    surface->screen = target->screen;
135
    surface->pixmap = target->drawable;
136
    surface->owner = cairo_surface_reference (&target->base);
137
    surface->width = target->width;
138
    surface->height = target->height;
139
    surface->depth = target->depth;
140
    surface->x0 = surface->y0 = 0;
141
    surface->repeat = FALSE;
142

            
143
    return surface;
144
}
145

            
146
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
147
static cairo_status_t
148
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
149
				 pixman_format_code_t pixman_format,
150
				 int width, int height,
151
				 cairo_image_surface_t **image_out,
152
				 cairo_xcb_shm_info_t **shm_info_out)
153
{
154
    cairo_surface_t *image = NULL;
155
    cairo_xcb_shm_info_t *shm_info = NULL;
156
    cairo_status_t status;
157
    size_t size, stride;
158

            
159
    if (! (connection->flags & CAIRO_XCB_HAS_SHM))
160
	return CAIRO_INT_STATUS_UNSUPPORTED;
161

            
162
    if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
163
	return CAIRO_INT_STATUS_UNSUPPORTED;
164

            
165
    stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format));
166
    size = stride * height;
167
    if (size <= CAIRO_XCB_SHM_SMALL_IMAGE)
168
	return CAIRO_INT_STATUS_UNSUPPORTED;
169

            
170
    status = _cairo_xcb_connection_allocate_shm_info (connection, size,
171
						      FALSE, &shm_info);
172
    if (unlikely (status))
173
	return status;
174

            
175
    image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
176
							    pixman_format,
177
							    width, height,
178
							    stride);
179
    status = image->status;
180
    if (unlikely (status)) {
181
	_cairo_xcb_shm_info_destroy (shm_info);
182
	return status;
183
    }
184

            
185
    status = _cairo_user_data_array_set_data (&image->user_data,
186
					      (const cairo_user_data_key_t *) connection,
187
					      shm_info,
188
					      (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
189

            
190
    if (unlikely (status)) {
191
	cairo_surface_destroy (image);
192
	_cairo_xcb_shm_info_destroy (shm_info);
193
	return status;
194
    }
195

            
196
    *image_out = (cairo_image_surface_t *) image;
197
    *shm_info_out = shm_info;
198
    return CAIRO_STATUS_SUCCESS;
199
}
200
#else
201
static cairo_status_t
202
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
203
				 pixman_format_code_t pixman_format,
204
				 int width, int height,
205
				 cairo_image_surface_t **image_out,
206
				 cairo_xcb_shm_info_t **shm_info_out)
207
{
208
    return CAIRO_INT_STATUS_UNSUPPORTED;
209
}
210
#endif
211

            
212
cairo_status_t
213
_cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
214
			     pixman_format_code_t pixman_format,
215
			     int width, int height,
216
			     cairo_image_surface_t **image_out,
217
			     cairo_xcb_shm_info_t **shm_info_out)
218
{
219
    cairo_surface_t *image = NULL;
220
    cairo_xcb_shm_info_t *shm_info = NULL;
221
    cairo_status_t status;
222

            
223
    status = _cairo_xcb_shm_image_create_shm (connection,
224
					      pixman_format,
225
					      width,
226
					      height,
227
					      image_out,
228
					      shm_info_out);
229

            
230
    if (status != CAIRO_STATUS_SUCCESS) {
231
	image = _cairo_image_surface_create_with_pixman_format (NULL,
232
								pixman_format,
233
								width, height,
234
								0);
235
	status = image->status;
236
	if (unlikely (status))
237
	    return status;
238

            
239
	*image_out = (cairo_image_surface_t *) image;
240
	*shm_info_out = shm_info;
241
    }
242

            
243
    return CAIRO_STATUS_SUCCESS;
244
}
245

            
246
static cairo_xcb_pixmap_t *
247
_pixmap_from_image (cairo_xcb_surface_t *target,
248
		    xcb_render_pictformat_t format,
249
		    cairo_image_surface_t *image,
250
		    cairo_xcb_shm_info_t *shm_info)
251
{
252
    xcb_gcontext_t gc;
253
    cairo_xcb_pixmap_t *pixmap;
254

            
255
    pixmap = _cairo_xcb_pixmap_create (target,
256
				       image->width,
257
				       image->height);
258
    if (unlikely (pixmap->base.status))
259
	return pixmap;
260

            
261
    gc = _cairo_xcb_screen_get_gc (target->screen, pixmap->pixmap, image->depth);
262

            
263
    if (shm_info != NULL) {
264
	_cairo_xcb_connection_shm_put_image (target->connection,
265
					     pixmap->pixmap, gc,
266
					     image->width, image->height,
267
					     0, 0,
268
					     image->width, image->height,
269
					     0, 0,
270
					     image->depth,
271
					     shm_info->shm,
272
					     shm_info->offset);
273
    } else {
274
	int len;
275

            
276
	/* Do we need to trim the image? */
277
	len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width,
278
					  PIXMAN_FORMAT_BPP (image->pixman_format));
279
	if (len == image->stride) {
280
	    _cairo_xcb_connection_put_image (target->connection,
281
					     pixmap->pixmap, gc,
282
					     image->width, image->height,
283
					     0, 0,
284
					     image->depth,
285
					     image->stride,
286
					     image->data);
287
	} else {
288
	    _cairo_xcb_connection_put_subimage (target->connection,
289
						pixmap->pixmap, gc,
290
						0, 0,
291
						image->width, image->height,
292
						PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
293
						image->stride,
294
						0, 0,
295
						image->depth,
296
						image->data);
297

            
298
	}
299
    }
300

            
301
    _cairo_xcb_screen_put_gc (target->screen, image->depth, gc);
302

            
303
    return pixmap;
304
}
305

            
306
static cairo_xcb_pixmap_t *
307
_render_to_pixmap (cairo_xcb_surface_t *target,
308
		   const cairo_pattern_t *pattern,
309
		   const cairo_rectangle_int_t *extents)
310
{
311
    cairo_image_surface_t *image;
312
    cairo_xcb_shm_info_t *shm_info;
313
    cairo_pattern_union_t copy;
314
    cairo_status_t status;
315
    cairo_xcb_pixmap_t *pixmap;
316

            
317
    status = _cairo_xcb_shm_image_create (target->screen->connection,
318
					  target->pixman_format,
319
					  extents->width, extents->height,
320
					  &image, &shm_info);
321
    if (unlikely (status))
322
	return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
323

            
324
    _cairo_pattern_init_static_copy (&copy.base, pattern);
325
    cairo_matrix_translate (&copy.base.matrix, -extents->x, -extents->y);
326
    status = _cairo_surface_paint (&image->base,
327
				   CAIRO_OPERATOR_SOURCE,
328
				   &copy.base,
329
				   NULL);
330
    if (unlikely (status)) {
331
	cairo_surface_destroy (&image->base);
332
	return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
333
    }
334

            
335
    pixmap = _pixmap_from_image (target, target->xrender_format, image, shm_info);
336
    cairo_surface_destroy (&image->base);
337

            
338
    if (unlikely (pixmap->base.status))
339
	return pixmap;
340

            
341
    pixmap->x0 = -extents->x;
342
    pixmap->y0 = -extents->y;
343
    return pixmap;
344
}
345

            
346
static cairo_xcb_pixmap_t *
347
_copy_to_pixmap (cairo_xcb_surface_t *source)
348
{
349
    cairo_xcb_pixmap_t *pixmap;
350

            
351
    /* If the source may be a window, we need to copy it and its children
352
     * via a temporary pixmap so that we can IncludeInferiors on the source
353
     * and use ClipByChildren on the destination.
354
     */
355
    if (source->owns_pixmap) {
356
	pixmap = _cairo_xcb_pixmap_copy (source);
357
	if (unlikely (pixmap->base.status))
358
	    return pixmap;
359
    } else {
360
	uint32_t values[1];
361
	xcb_gcontext_t gc;
362

            
363
	pixmap = _cairo_xcb_pixmap_create (source,
364
					   source->width,
365
					   source->height);
366
	if (unlikely (pixmap->base.status))
367
	    return pixmap;
368

            
369
	gc = _cairo_xcb_screen_get_gc (source->screen,
370
				       pixmap->pixmap,
371
				       pixmap->depth);
372

            
373
	values[0] = TRUE;
374
	_cairo_xcb_connection_change_gc (pixmap->connection, gc,
375
					 XCB_GC_SUBWINDOW_MODE, values);
376

            
377
	_cairo_xcb_connection_copy_area (pixmap->connection,
378
					 source->drawable,
379
					 pixmap->pixmap, gc,
380
					 0, 0,
381
					 0, 0,
382
					 source->width,
383
					 source->height);
384

            
385
	values[0] = FALSE;
386
	_cairo_xcb_connection_change_gc (pixmap->connection, gc,
387
					 XCB_GC_SUBWINDOW_MODE, values);
388

            
389
	_cairo_xcb_screen_put_gc (source->screen,
390
				  pixmap->depth,
391
				  gc);
392
    }
393

            
394
    return pixmap;
395
}
396
static cairo_xcb_pixmap_t *
397
_cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target,
398
			   const cairo_surface_pattern_t *pattern,
399
			   const cairo_rectangle_int_t *extents,
400
			   int tx, int ty)
401
{
402
    cairo_surface_t *source;
403
    cairo_xcb_pixmap_t *pixmap;
404

            
405
    source =  pattern->surface;
406
    pixmap = (cairo_xcb_pixmap_t *)
407
	_cairo_surface_has_snapshot (source, &_cairo_xcb_pixmap_backend);
408
    if (pixmap != NULL && pixmap->screen == target->screen)
409
	return (cairo_xcb_pixmap_t *) cairo_surface_reference (&pixmap->base);
410

            
411
    if (_cairo_surface_is_xcb(source) &&
412
	((cairo_xcb_surface_t *) source)->screen == target->screen)
413
    {
414
	cairo_xcb_surface_t *xcb_source = (cairo_xcb_surface_t *) source;
415

            
416
	if (xcb_source->depth == target->depth)
417
	    pixmap = _copy_to_pixmap (xcb_source);
418
    }
419
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
420
    else if (source->type == CAIRO_SURFACE_TYPE_XLIB &&
421
	     ((cairo_xlib_xcb_surface_t *) source)->xcb->screen == target->screen)
422
    {
423
	cairo_xcb_surface_t *xcb_source = ((cairo_xlib_xcb_surface_t *) source)->xcb;
424

            
425
	if (xcb_source->depth == target->depth)
426
	    pixmap = _copy_to_pixmap (xcb_source);
427
    }
428
#endif
429

            
430
    if (pixmap == NULL) {
431
	cairo_rectangle_int_t rect;
432

            
433
	if (! _cairo_surface_get_extents (source, &rect)) {
434
	    rect.x = rect.y = 0;
435
	    rect.width  = target->width;
436
	    rect.height = target->height;
437
	}
438

            
439
	pixmap = _render_to_pixmap (target, &pattern->base, &rect);
440
    }
441

            
442
    if (unlikely (pixmap->base.status))
443
	return pixmap;
444

            
445
    _cairo_surface_attach_snapshot (source, &pixmap->base, NULL);
446

            
447
    if (pattern->base.extend != CAIRO_EXTEND_NONE) {
448
	if (extents->x < 0 || extents->y < 0 ||
449
	    extents->x + extents->width  > pixmap->width ||
450
	    extents->y + extents->height > pixmap->height)
451
	{
452
	    pixmap->repeat = TRUE;
453
	}
454
    }
455

            
456
    pixmap->x0 += tx;
457
    pixmap->y0 += ty;
458

            
459
    return pixmap;
460
}
461

            
462
static cairo_xcb_pixmap_t *
463
_cairo_xcb_pixmap_for_pattern (cairo_xcb_surface_t *target,
464
			       const cairo_pattern_t *pattern,
465
			       const cairo_rectangle_int_t *extents)
466
{
467
    int tx, ty;
468

            
469
    switch (pattern->type) {
470
    case CAIRO_PATTERN_TYPE_SURFACE:
471
	/* Core can only perform a native, unscaled blit, but can handle tiles */
472
	if (_cairo_matrix_is_integer_translation (&pattern->matrix, &tx, &ty)) {
473
	    switch (pattern->extend) {
474
	    case CAIRO_EXTEND_NONE:
475
	    case CAIRO_EXTEND_REPEAT:
476
		return _cairo_xcb_surface_pixmap (target,
477
						  (cairo_surface_pattern_t *) pattern,
478
						  extents, tx, ty);
479

            
480
	    default:
481
	    case CAIRO_EXTEND_PAD:
482
	    case CAIRO_EXTEND_REFLECT:
483
		break;
484
	    }
485
	}
486
	/* fallthrough */
487
    case CAIRO_PATTERN_TYPE_LINEAR:
488
    case CAIRO_PATTERN_TYPE_RADIAL:
489
    case CAIRO_PATTERN_TYPE_MESH:
490
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
491
	return _render_to_pixmap (target, pattern, extents);
492

            
493
    default:
494
    case CAIRO_PATTERN_TYPE_SOLID:
495
	ASSERT_NOT_REACHED;
496
	return NULL;
497
    }
498
}
499

            
500
cairo_status_t
501
_cairo_xcb_surface_core_copy_boxes (cairo_xcb_surface_t		*dst,
502
				   const cairo_pattern_t	*src_pattern,
503
				   const cairo_rectangle_int_t	*extents,
504
				   const cairo_boxes_t		*boxes)
505
{
506
    cairo_xcb_pixmap_t *src;
507
    const struct _cairo_boxes_chunk *chunk;
508
    xcb_gcontext_t gc;
509
    cairo_status_t status;
510

            
511
    status = _cairo_xcb_connection_acquire (dst->connection);
512
    if (unlikely (status))
513
	return status;
514

            
515
    src = _cairo_xcb_pixmap_for_pattern (dst, src_pattern, extents);
516
    status = src->base.status;
517
    if (unlikely (status))
518
	goto CLEANUP_CONNECTION;
519

            
520
    assert (src->depth == dst->depth);
521

            
522
    gc = _cairo_xcb_screen_get_gc (dst->screen, src->pixmap, src->depth);
523

            
524
    if (src->repeat) {
525
	uint32_t mask =
526
	    XCB_GC_FILL_STYLE |
527
	    XCB_GC_TILE |
528
	    XCB_GC_TILE_STIPPLE_ORIGIN_X |
529
	    XCB_GC_TILE_STIPPLE_ORIGIN_Y;
530
	uint32_t values[] = {
531
	    XCB_FILL_STYLE_TILED,
532
	    src->pixmap,
533
	    - src->x0, - src->y0,
534
	};
535
	xcb_rectangle_t *xcb_rects;
536

            
537
	_cairo_xcb_connection_change_gc (dst->connection, gc, mask, values);
538

            
539
	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
540
	    int i;
541

            
542
	    xcb_rects = (xcb_rectangle_t *) chunk->base;
543

            
544
	    for (i = 0; i < chunk->count; i++) {
545
		int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
546
		int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
547
		int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
548
		int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
549

            
550
		xcb_rects[i].x = x1;
551
		xcb_rects[i].y = y1;
552
		xcb_rects[i].width  = x2 - x1;
553
		xcb_rects[i].height = y2 - y1;
554
	    }
555
	    _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
556
						       dst->drawable,
557
						       gc, chunk->count, xcb_rects);
558
	}
559

            
560
	values[0] = 0;
561
	_cairo_xcb_connection_change_gc (dst->connection, gc, XCB_GC_FILL_STYLE, values);
562
    } else {
563
	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
564
	    int i;
565

            
566
	    for (i = 0; i < chunk->count; i++) {
567
		int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
568
		int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
569
		int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
570
		int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
571

            
572
		_cairo_xcb_connection_copy_area (dst->connection,
573
						 src->pixmap,
574
						 dst->drawable, gc,
575
						 src->x0 + x1,
576
						 src->y0 + y1,
577
						 x1, y1,
578
						 x2 - x1, y2 - y1);
579
	    }
580
	}
581
    }
582

            
583
    _cairo_xcb_screen_put_gc (dst->screen, src->depth, gc);
584
    cairo_surface_destroy (&src->base);
585

            
586
  CLEANUP_CONNECTION:
587
    _cairo_xcb_connection_release (dst->connection);
588

            
589
    return status;
590
}
591

            
592
cairo_status_t
593
_cairo_xcb_surface_core_fill_boxes (cairo_xcb_surface_t *dst,
594
				    const cairo_color_t	*color,
595
				    cairo_boxes_t *boxes)
596
{
597
    struct _cairo_boxes_chunk *chunk;
598
    xcb_gcontext_t gc;
599
    cairo_status_t status;
600

            
601
    status = _cairo_xcb_connection_acquire (dst->connection);
602
    if (unlikely (status))
603
	return status;
604

            
605
    gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
606

            
607
#if 0
608
    xcb_pixmap_t source;
609

            
610
    source = _dither_source (dst, color);
611
    XSetTSOrigin (surface->dpy, gc, 0, 0);
612
    XSetTile (surface->dpy, gc, source);
613
#endif
614

            
615
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
616
	xcb_rectangle_t *xcb_rects;
617
	int i;
618

            
619
	xcb_rects = (xcb_rectangle_t *) chunk->base;
620
	for (i = 0; i < chunk->count; i++) {
621
	    int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
622
	    int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
623
	    int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
624
	    int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
625

            
626
	    xcb_rects[i].x = x1;
627
	    xcb_rects[i].y = y1;
628
	    xcb_rects[i].width  = x2 - x1;
629
	    xcb_rects[i].height = y2 - y1;
630
	}
631

            
632
	_cairo_xcb_connection_poly_fill_rectangle (dst->connection,
633
						   dst->drawable, gc,
634
						   chunk->count, xcb_rects);
635
    }
636

            
637
    _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc);
638
    _cairo_xcb_connection_release (dst->connection);
639

            
640
    return CAIRO_STATUS_SUCCESS;
641
}