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 © 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 
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
	_cairo_xcb_connection_free_pixmap (surface->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 = malloc (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
 
98
    surface->connection = target->connection;
99
    surface->screen = target->screen;
100
    surface->owner = NULL;
101
    surface->width = width;
102
    surface->height = height;
103
    surface->depth = target->depth;
104
    surface->x0 = surface->y0 = 0;
105
    surface->repeat = FALSE;
106
 
107
    surface->pixmap =
108
	_cairo_xcb_connection_create_pixmap (surface->connection,
109
					     surface->depth,
110
					     target->drawable,
111
					     width, height);
112
 
113
    return surface;
114
}
115
 
116
static cairo_xcb_pixmap_t *
117
_cairo_xcb_pixmap_copy (cairo_xcb_surface_t *target)
118
{
119
    cairo_xcb_pixmap_t *surface;
120
 
121
    surface = malloc (sizeof (cairo_xcb_pixmap_t));
122
    if (unlikely (surface == NULL))
123
	return (cairo_xcb_pixmap_t *)
124
	    _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
125
 
126
    _cairo_surface_init (&surface->base,
127
			 &_cairo_xcb_pixmap_backend,
128
			 NULL,
129
			 target->base.content);
130
 
131
    surface->connection = target->connection;
132
    surface->screen = target->screen;
133
    surface->pixmap = target->drawable;
134
    surface->owner = cairo_surface_reference (&target->base);
135
    surface->width = target->width;
136
    surface->height = target->height;
137
    surface->depth = target->depth;
138
    surface->x0 = surface->y0 = 0;
139
    surface->repeat = FALSE;
140
 
141
    return surface;
142
}
143
 
144
#if CAIRO_HAS_XCB_SHM_FUNCTIONS
145
static cairo_status_t
146
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
147
				 pixman_format_code_t pixman_format,
148
				 int width, int height,
149
				 cairo_image_surface_t **image_out,
150
				 cairo_xcb_shm_info_t **shm_info_out)
151
{
152
    cairo_surface_t *image = NULL;
153
    cairo_xcb_shm_info_t *shm_info = NULL;
154
    cairo_status_t status;
155
    size_t size, stride;
156
 
157
    if (! (connection->flags & CAIRO_XCB_HAS_SHM))
158
	return CAIRO_INT_STATUS_UNSUPPORTED;
159
 
160
    if (unlikely (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX))
161
	return CAIRO_INT_STATUS_UNSUPPORTED;
162
 
163
    stride = CAIRO_STRIDE_FOR_WIDTH_BPP (width, PIXMAN_FORMAT_BPP (pixman_format));
164
    size = stride * height;
165
    if (size <= CAIRO_XCB_SHM_SMALL_IMAGE)
166
	return CAIRO_INT_STATUS_UNSUPPORTED;
167
 
168
    status = _cairo_xcb_connection_allocate_shm_info (connection, size,
169
						      FALSE, &shm_info);
170
    if (unlikely (status))
171
	return status;
172
 
173
    image = _cairo_image_surface_create_with_pixman_format (shm_info->mem,
174
							    pixman_format,
175
							    width, height,
176
							    stride);
177
    status = image->status;
178
    if (unlikely (status)) {
179
	_cairo_xcb_shm_info_destroy (shm_info);
180
	return status;
181
    }
182
 
183
    status = _cairo_user_data_array_set_data (&image->user_data,
184
					      (const cairo_user_data_key_t *) connection,
185
					      shm_info,
186
					      (cairo_destroy_func_t) _cairo_xcb_shm_info_destroy);
187
 
188
    if (unlikely (status)) {
189
	cairo_surface_destroy (image);
190
	_cairo_xcb_shm_info_destroy (shm_info);
191
	return status;
192
    }
193
 
194
    *image_out = (cairo_image_surface_t *) image;
195
    *shm_info_out = shm_info;
196
    return CAIRO_STATUS_SUCCESS;
197
}
198
#else
199
static cairo_status_t
200
_cairo_xcb_shm_image_create_shm (cairo_xcb_connection_t *connection,
201
				 pixman_format_code_t pixman_format,
202
				 int width, int height,
203
				 cairo_image_surface_t **image_out,
204
				 cairo_xcb_shm_info_t **shm_info_out)
205
{
206
    return CAIRO_INT_STATUS_UNSUPPORTED;
207
}
208
#endif
209
 
210
cairo_status_t
211
_cairo_xcb_shm_image_create (cairo_xcb_connection_t *connection,
212
			     pixman_format_code_t pixman_format,
213
			     int width, int height,
214
			     cairo_image_surface_t **image_out,
215
			     cairo_xcb_shm_info_t **shm_info_out)
216
{
217
    cairo_surface_t *image = NULL;
218
    cairo_xcb_shm_info_t *shm_info = NULL;
219
    cairo_status_t status;
220
 
221
    status = _cairo_xcb_shm_image_create_shm (connection,
222
					      pixman_format,
223
					      width,
224
					      height,
225
					      image_out,
226
					      shm_info_out);
227
 
228
    if (status != CAIRO_STATUS_SUCCESS) {
229
	image = _cairo_image_surface_create_with_pixman_format (NULL,
230
								pixman_format,
231
								width, height,
232
								0);
233
	status = image->status;
234
	if (unlikely (status))
235
	    return status;
236
 
237
	*image_out = (cairo_image_surface_t *) image;
238
	*shm_info_out = shm_info;
239
    }
240
 
241
    return CAIRO_STATUS_SUCCESS;
242
}
243
 
244
static cairo_xcb_pixmap_t *
245
_pixmap_from_image (cairo_xcb_surface_t *target,
246
		    xcb_render_pictformat_t format,
247
		    cairo_image_surface_t *image,
248
		    cairo_xcb_shm_info_t *shm_info)
249
{
250
    xcb_gcontext_t gc;
251
    cairo_xcb_pixmap_t *pixmap;
252
 
253
    pixmap = _cairo_xcb_pixmap_create (target,
254
				       image->width,
255
				       image->height);
256
    if (unlikely (pixmap->base.status))
257
	return pixmap;
258
 
259
    gc = _cairo_xcb_screen_get_gc (target->screen, pixmap->pixmap, image->depth);
260
 
261
    if (shm_info != NULL) {
262
	_cairo_xcb_connection_shm_put_image (target->connection,
263
					     pixmap->pixmap, gc,
264
					     image->width, image->height,
265
					     0, 0,
266
					     image->width, image->height,
267
					     0, 0,
268
					     image->depth,
269
					     shm_info->shm,
270
					     shm_info->offset);
271
    } else {
272
	int len;
273
 
274
	/* Do we need to trim the image? */
275
	len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width,
276
					  PIXMAN_FORMAT_BPP (image->pixman_format));
277
	if (len == image->stride) {
278
	    _cairo_xcb_connection_put_image (target->connection,
279
					     pixmap->pixmap, gc,
280
					     image->width, image->height,
281
					     0, 0,
282
					     image->depth,
283
					     image->stride,
284
					     image->data);
285
	} else {
286
	    _cairo_xcb_connection_put_subimage (target->connection,
287
						pixmap->pixmap, gc,
288
						0, 0,
289
						image->width, image->height,
290
						PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
291
						image->stride,
292
						0, 0,
293
						image->depth,
294
						image->data);
295
 
296
	}
297
    }
298
 
299
    _cairo_xcb_screen_put_gc (target->screen, image->depth, gc);
300
 
301
    return pixmap;
302
}
303
 
304
static cairo_xcb_pixmap_t *
305
_render_to_pixmap (cairo_xcb_surface_t *target,
306
		   const cairo_pattern_t *pattern,
307
		   const cairo_rectangle_int_t *extents)
308
{
309
    cairo_image_surface_t *image;
310
    cairo_xcb_shm_info_t *shm_info;
311
    cairo_pattern_union_t copy;
312
    cairo_status_t status;
313
    cairo_xcb_pixmap_t *pixmap;
314
 
315
    status = _cairo_xcb_shm_image_create (target->screen->connection,
316
					  target->pixman_format,
317
					  extents->width, extents->height,
318
					  &image, &shm_info);
319
    if (unlikely (status))
320
	return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
321
 
322
    _cairo_pattern_init_static_copy (©.base, pattern);
323
    cairo_matrix_translate (©.base.matrix, -extents->x, -extents->y);
324
    status = _cairo_surface_paint (&image->base,
325
				   CAIRO_OPERATOR_SOURCE,
326
				   ©.base,
327
				   NULL);
328
    if (unlikely (status)) {
329
	cairo_surface_destroy (&image->base);
330
	return (cairo_xcb_pixmap_t *) _cairo_surface_create_in_error (status);
331
    }
332
 
333
    pixmap = _pixmap_from_image (target, target->xrender_format, image, shm_info);
334
    cairo_surface_destroy (&image->base);
335
 
336
    if (unlikely (pixmap->base.status))
337
	return pixmap;
338
 
339
    pixmap->x0 = -extents->x;
340
    pixmap->y0 = -extents->y;
341
    return pixmap;
342
}
343
 
344
static cairo_xcb_pixmap_t *
345
_copy_to_pixmap (cairo_xcb_surface_t *source)
346
{
347
    cairo_xcb_pixmap_t *pixmap;
348
 
349
    /* If the source may be a window, we need to copy it and its children
350
     * via a temporary pixmap so that we can IncludeInferiors on the source
351
     * and use ClipByChildren on the destination.
352
     */
353
    if (source->owns_pixmap) {
354
	pixmap = _cairo_xcb_pixmap_copy (source);
355
	if (unlikely (pixmap->base.status))
356
	    return pixmap;
357
    } else {
358
	uint32_t values[1];
359
	xcb_gcontext_t gc;
360
 
361
	pixmap = _cairo_xcb_pixmap_create (source,
362
					   source->width,
363
					   source->height);
364
	if (unlikely (pixmap->base.status))
365
	    return pixmap;
366
 
367
	gc = _cairo_xcb_screen_get_gc (source->screen,
368
				       pixmap->pixmap,
369
				       pixmap->depth);
370
 
371
	values[0] = TRUE;
372
	_cairo_xcb_connection_change_gc (pixmap->connection, gc,
373
					 XCB_GC_SUBWINDOW_MODE, values);
374
 
375
	_cairo_xcb_connection_copy_area (pixmap->connection,
376
					 source->drawable,
377
					 pixmap->pixmap, gc,
378
					 0, 0,
379
					 0, 0,
380
					 source->width,
381
					 source->height);
382
 
383
	values[0] = FALSE;
384
	_cairo_xcb_connection_change_gc (pixmap->connection, gc,
385
					 XCB_GC_SUBWINDOW_MODE, values);
386
 
387
	_cairo_xcb_screen_put_gc (source->screen,
388
				  pixmap->depth,
389
				  gc);
390
    }
391
 
392
    return pixmap;
393
}
394
static cairo_xcb_pixmap_t *
395
_cairo_xcb_surface_pixmap (cairo_xcb_surface_t *target,
396
			   const cairo_surface_pattern_t *pattern,
397
			   const cairo_rectangle_int_t *extents,
398
			   int tx, int ty)
399
{
400
    cairo_surface_t *source;
401
    cairo_xcb_pixmap_t *pixmap;
402
 
403
    source =  pattern->surface;
404
    pixmap = (cairo_xcb_pixmap_t *)
405
	_cairo_surface_has_snapshot (source, &_cairo_xcb_pixmap_backend);
406
    if (pixmap != NULL && pixmap->screen == target->screen)
407
	return (cairo_xcb_pixmap_t *) cairo_surface_reference (&pixmap->base);
408
 
409
    if (source->type == CAIRO_SURFACE_TYPE_XCB &&
410
	((cairo_xcb_surface_t *) source)->screen == target->screen)
411
    {
412
	cairo_xcb_surface_t *xcb_source = (cairo_xcb_surface_t *) source;
413
 
414
	if (xcb_source->depth == target->depth)
415
	    pixmap = _copy_to_pixmap (xcb_source);
416
    }
417
#if CAIRO_HAS_XLIB_XCB_FUNCTIONS
418
    else if (source->type == CAIRO_SURFACE_TYPE_XLIB &&
419
	     ((cairo_xlib_xcb_surface_t *) source)->xcb->screen == target->screen)
420
    {
421
	cairo_xcb_surface_t *xcb_source = ((cairo_xlib_xcb_surface_t *) source)->xcb;
422
 
423
	if (xcb_source->depth == target->depth)
424
	    pixmap = _copy_to_pixmap (xcb_source);
425
    }
426
#endif
427
 
428
    if (pixmap == NULL) {
429
	cairo_rectangle_int_t rect;
430
 
431
	if (! _cairo_surface_get_extents (source, &rect)) {
432
	    rect.x = rect.y = 0;
433
	    rect.width  = target->width;
434
	    rect.height = target->height;
435
	}
436
 
437
	pixmap = _render_to_pixmap (target, &pattern->base, &rect);
438
    }
439
 
440
    if (unlikely (pixmap->base.status))
441
	return pixmap;
442
 
443
    _cairo_surface_attach_snapshot (source, &pixmap->base, NULL);
444
 
445
    if (pattern->base.extend != CAIRO_EXTEND_NONE) {
446
	if (extents->x < 0 || extents->y < 0 ||
447
	    extents->x + extents->width  > pixmap->width ||
448
	    extents->y + extents->height > pixmap->height)
449
	{
450
	    pixmap->repeat = TRUE;
451
	}
452
    }
453
 
454
    pixmap->x0 += tx;
455
    pixmap->y0 += ty;
456
 
457
    return pixmap;
458
}
459
 
460
static cairo_xcb_pixmap_t *
461
_cairo_xcb_pixmap_for_pattern (cairo_xcb_surface_t *target,
462
			       const cairo_pattern_t *pattern,
463
			       const cairo_rectangle_int_t *extents)
464
{
465
    int tx, ty;
466
 
467
    switch (pattern->type) {
468
    case CAIRO_PATTERN_TYPE_SURFACE:
469
	/* Core can only perform a native, unscaled blit, but can handle tiles */
470
	if (_cairo_matrix_is_integer_translation (&pattern->matrix, &tx, &ty)) {
471
	    switch (pattern->extend) {
472
	    case CAIRO_EXTEND_NONE:
473
	    case CAIRO_EXTEND_REPEAT:
474
		return _cairo_xcb_surface_pixmap (target,
475
						  (cairo_surface_pattern_t *) pattern,
476
						  extents, tx, ty);
477
 
478
	    default:
479
	    case CAIRO_EXTEND_PAD:
480
	    case CAIRO_EXTEND_REFLECT:
481
		break;
482
	    }
483
	}
484
	/* fallthrough */
485
    case CAIRO_PATTERN_TYPE_LINEAR:
486
    case CAIRO_PATTERN_TYPE_RADIAL:
487
    case CAIRO_PATTERN_TYPE_MESH:
488
    case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
489
	return _render_to_pixmap (target, pattern, extents);
490
 
491
    default:
492
    case CAIRO_PATTERN_TYPE_SOLID:
493
	ASSERT_NOT_REACHED;
494
	return NULL;
495
    }
496
}
497
 
498
cairo_status_t
499
_cairo_xcb_surface_core_copy_boxes (cairo_xcb_surface_t		*dst,
500
				   const cairo_pattern_t	*src_pattern,
501
				   const cairo_rectangle_int_t	*extents,
502
				   const cairo_boxes_t		*boxes)
503
{
504
    cairo_xcb_pixmap_t *src;
505
    const struct _cairo_boxes_chunk *chunk;
506
    xcb_gcontext_t gc;
507
    cairo_status_t status;
508
 
509
    status = _cairo_xcb_connection_acquire (dst->connection);
510
    if (unlikely (status))
511
	return status;
512
 
513
    src = _cairo_xcb_pixmap_for_pattern (dst, src_pattern, extents);
514
    status = src->base.status;
515
    if (unlikely (status))
516
	goto CLEANUP_CONNECTION;
517
 
518
    assert (src->depth == dst->depth);
519
 
520
    gc = _cairo_xcb_screen_get_gc (dst->screen, src->pixmap, src->depth);
521
 
522
    if (src->repeat) {
523
	uint32_t mask =
524
	    XCB_GC_FILL_STYLE |
525
	    XCB_GC_TILE |
526
	    XCB_GC_TILE_STIPPLE_ORIGIN_X |
527
	    XCB_GC_TILE_STIPPLE_ORIGIN_Y;
528
	uint32_t values[] = {
529
	    XCB_FILL_STYLE_TILED,
530
	    src->pixmap,
531
	    - src->x0, - src->y0,
532
	};
533
	xcb_rectangle_t *xcb_rects;
534
 
535
	_cairo_xcb_connection_change_gc (dst->connection, gc, mask, values);
536
 
537
	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
538
	    int i;
539
 
540
	    xcb_rects = (xcb_rectangle_t *) chunk->base;
541
 
542
	    for (i = 0; i < chunk->count; i++) {
543
		int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
544
		int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
545
		int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
546
		int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
547
 
548
		xcb_rects[i].x = x1;
549
		xcb_rects[i].y = y1;
550
		xcb_rects[i].width  = x2 - x1;
551
		xcb_rects[i].height = y2 - y1;
552
	    }
553
	    _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
554
						       dst->drawable,
555
						       gc, chunk->count, xcb_rects);
556
	}
557
 
558
	values[0] = 0;
559
	_cairo_xcb_connection_change_gc (dst->connection, gc, XCB_GC_FILL_STYLE, values);
560
    } else {
561
	for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
562
	    int i;
563
 
564
	    for (i = 0; i < chunk->count; i++) {
565
		int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
566
		int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
567
		int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
568
		int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
569
 
570
		_cairo_xcb_connection_copy_area (dst->connection,
571
						 src->pixmap,
572
						 dst->drawable, gc,
573
						 src->x0 + x1,
574
						 src->y0 + y1,
575
						 x1, y1,
576
						 x2 - x2, y2 - x2);
577
	    }
578
	}
579
    }
580
 
581
    _cairo_xcb_screen_put_gc (dst->screen, src->depth, gc);
582
    cairo_surface_destroy (&src->base);
583
 
584
  CLEANUP_CONNECTION:
585
    _cairo_xcb_connection_release (dst->connection);
586
 
587
    return status;
588
}
589
 
590
cairo_status_t
591
_cairo_xcb_surface_core_fill_boxes (cairo_xcb_surface_t *dst,
592
				    const cairo_color_t	*color,
593
				    cairo_boxes_t *boxes)
594
{
595
    struct _cairo_boxes_chunk *chunk;
596
    xcb_gcontext_t gc;
597
    cairo_status_t status;
598
 
599
    status = _cairo_xcb_connection_acquire (dst->connection);
600
    if (unlikely (status))
601
	return status;
602
 
603
    gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
604
 
605
#if 0
606
    xcb_pixmap_t source;
607
 
608
    source = _dither_source (dst, color);
609
    XSetTSOrigin (surface->dpy, gc, 0, 0);
610
    XSetTile (surface->dpy, gc, source);
611
#endif
612
 
613
    for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
614
	xcb_rectangle_t *xcb_rects;
615
	int i;
616
 
617
	xcb_rects = (xcb_rectangle_t *) chunk->base;
618
	for (i = 0; i < chunk->count; i++) {
619
	    int x1 = _cairo_fixed_integer_round (chunk->base[i].p1.x);
620
	    int x2 = _cairo_fixed_integer_round (chunk->base[i].p2.x);
621
	    int y1 = _cairo_fixed_integer_round (chunk->base[i].p1.y);
622
	    int y2 = _cairo_fixed_integer_round (chunk->base[i].p2.y);
623
 
624
	    xcb_rects[i].x = x1;
625
	    xcb_rects[i].y = y1;
626
	    xcb_rects[i].width  = x2 - x1;
627
	    xcb_rects[i].height = y2 - y1;
628
	}
629
 
630
	_cairo_xcb_connection_poly_fill_rectangle (dst->connection,
631
						   dst->drawable, gc,
632
						   chunk->count, xcb_rects);
633
    }
634
 
635
    _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc);
636
    _cairo_xcb_connection_release (dst->connection);
637
 
638
    return CAIRO_STATUS_SUCCESS;
639
}