Tizen 2.0 Release
[profile/ivi/cairo.git] / src / cairo-xcb-surface-render.c
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-xcb-private.h"
35
36 #include "cairo-boxes-private.h"
37 #include "cairo-clip-inline.h"
38 #include "cairo-clip-private.h"
39 #include "cairo-composite-rectangles-private.h"
40 #include "cairo-image-surface-private.h"
41 #include "cairo-list-inline.h"
42 #include "cairo-region-private.h"
43 #include "cairo-surface-offset-private.h"
44 #include "cairo-surface-snapshot-inline.h"
45 #include "cairo-surface-subsurface-private.h"
46 #include "cairo-traps-private.h"
47 #include "cairo-recording-surface-inline.h"
48 #include "cairo-paginated-private.h"
49 #include "cairo-pattern-inline.h"
50
51 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
52
53 static cairo_status_t
54 _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
55                            cairo_operator_t op,
56                            const cairo_pattern_t *src,
57                            cairo_boxes_t *boxes,
58                            cairo_composite_rectangles_t *extents);
59
60 static inline cairo_xcb_connection_t *
61 _picture_to_connection (cairo_xcb_picture_t *picture)
62 {
63     return (cairo_xcb_connection_t *) picture->base.device;
64 }
65
66 static void
67 _cairo_xcb_surface_ensure_picture (cairo_xcb_surface_t *surface);
68
69 static uint32_t
70 hars_petruska_f54_1_random (void)
71 {
72 #define rol(x,k) ((x << k) | (x >> (32-k)))
73     static uint32_t x;
74     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
75 #undef rol
76 }
77
78 static cairo_status_t
79 _cairo_xcb_picture_finish (void *abstract_surface)
80 {
81     cairo_xcb_picture_t *surface = abstract_surface;
82     cairo_xcb_connection_t *connection = _picture_to_connection (surface);
83     cairo_status_t status;
84
85     status = _cairo_xcb_connection_acquire (connection);
86     cairo_list_del (&surface->link);
87     if (unlikely (status))
88         return status;
89
90     _cairo_xcb_connection_render_free_picture (connection, surface->picture);
91
92     _cairo_xcb_connection_release (connection);
93
94     return CAIRO_STATUS_SUCCESS;
95 }
96
97 static const cairo_surface_backend_t _cairo_xcb_picture_backend = {
98     CAIRO_SURFACE_TYPE_XCB,
99     _cairo_xcb_picture_finish,
100 };
101
102 static const struct xcb_render_transform_t identity_transform = {
103     1 << 16, 0, 0,
104     0, 1 << 16, 0,
105     0, 0, 1 << 16,
106 };
107
108 static cairo_xcb_picture_t *
109 _cairo_xcb_picture_create (cairo_xcb_screen_t *screen,
110                            pixman_format_code_t pixman_format,
111                            xcb_render_pictformat_t xrender_format,
112                            int width, int height)
113 {
114     cairo_xcb_picture_t *surface;
115
116     surface = malloc (sizeof (cairo_xcb_picture_t));
117     if (unlikely (surface == NULL))
118         return (cairo_xcb_picture_t *)
119             _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
120
121     _cairo_surface_init (&surface->base,
122                          &_cairo_xcb_picture_backend,
123                          &screen->connection->device,
124                          _cairo_content_from_pixman_format (pixman_format));
125
126     cairo_list_add (&surface->link, &screen->pictures);
127
128     surface->screen = screen;
129     surface->picture = _cairo_xcb_connection_get_xid (screen->connection);
130     surface->pixman_format = pixman_format;
131     surface->xrender_format = xrender_format;
132
133     surface->x0 = surface->y0 = 0;
134     surface->x = surface->y = 0;
135     surface->width = width;
136     surface->height = height;
137
138     surface->transform = identity_transform;
139     surface->extend = CAIRO_EXTEND_NONE;
140     surface->filter = CAIRO_FILTER_NEAREST;
141     surface->has_component_alpha = FALSE;
142
143     return surface;
144 }
145
146 static inline cairo_bool_t
147 _operator_is_supported (uint32_t flags, cairo_operator_t op)
148 {
149     if (op <= CAIRO_OPERATOR_SATURATE)
150         return TRUE;
151
152     /* Can we use PDF operators? */
153 #if CAIRO_XCB_RENDER_AT_LEAST(0, 11)
154     if (op <= CAIRO_OPERATOR_HSL_LUMINOSITY)
155         return flags & CAIRO_XCB_RENDER_HAS_PDF_OPERATORS;
156 #endif
157
158     return FALSE;
159 }
160
161 static int
162 _render_operator (cairo_operator_t op)
163 {
164 #define C(x,y) case CAIRO_OPERATOR_##x: return XCB_RENDER_PICT_OP_##y
165     switch (op) {
166     C(CLEAR, CLEAR);
167     C(SOURCE, SRC);
168
169     C(OVER, OVER);
170     C(IN, IN);
171     C(OUT, OUT);
172     C(ATOP, ATOP);
173
174     C(DEST, DST);
175     C(DEST_OVER, OVER_REVERSE);
176     C(DEST_IN, IN_REVERSE);
177     C(DEST_OUT, OUT_REVERSE);
178     C(DEST_ATOP, ATOP_REVERSE);
179
180     C(XOR, XOR);
181     C(ADD, ADD);
182     C(SATURATE, SATURATE);
183
184     /* PDF operators were added in RENDER 0.11, check if the xcb headers have
185      * the defines, else fall through to the default case. */
186 #if CAIRO_XCB_RENDER_AT_LEAST(0, 11)
187 #define BLEND(x,y) C(x,y)
188 #else
189 #define BLEND(x,y) case CAIRO_OPERATOR_##x:
190 #endif
191     BLEND(MULTIPLY, MULTIPLY);
192     BLEND(SCREEN, SCREEN);
193     BLEND(OVERLAY, OVERLAY);
194     BLEND(DARKEN, DARKEN);
195     BLEND(LIGHTEN, LIGHTEN);
196     BLEND(COLOR_DODGE, COLOR_DODGE);
197     BLEND(COLOR_BURN, COLOR_BURN);
198     BLEND(HARD_LIGHT, HARD_LIGHT);
199     BLEND(SOFT_LIGHT, SOFT_LIGHT);
200     BLEND(DIFFERENCE, DIFFERENCE);
201     BLEND(EXCLUSION, EXCLUSION);
202     BLEND(HSL_HUE, HSL_HUE);
203     BLEND(HSL_SATURATION, HSL_SATURATION);
204     BLEND(HSL_COLOR, HSL_COLOR);
205     BLEND(HSL_LUMINOSITY, HSL_LUMINOSITY);
206
207     default:
208         ASSERT_NOT_REACHED;
209         return XCB_RENDER_PICT_OP_OVER;
210     }
211 }
212
213 static cairo_status_t
214 _cairo_xcb_surface_set_clip_region (cairo_xcb_surface_t *surface,
215                                     cairo_region_t      *region)
216 {
217     xcb_rectangle_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
218     xcb_rectangle_t *rects = stack_rects;
219     int i, num_rects;
220
221     num_rects = cairo_region_num_rectangles (region);
222
223     if (num_rects > ARRAY_LENGTH (stack_rects)) {
224         rects = _cairo_malloc_ab (num_rects, sizeof (xcb_rectangle_t));
225         if (unlikely (rects == NULL)) {
226             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
227         }
228     }
229
230     for (i = 0; i < num_rects; i++) {
231         cairo_rectangle_int_t rect;
232
233         cairo_region_get_rectangle (region, i, &rect);
234
235         rects[i].x = rect.x;
236         rects[i].y = rect.y;
237         rects[i].width  = rect.width;
238         rects[i].height = rect.height;
239     }
240
241     _cairo_xcb_connection_render_set_picture_clip_rectangles (surface->connection,
242                                                               surface->picture,
243                                                               0, 0,
244                                                               num_rects, rects);
245
246     if (rects != stack_rects)
247         free (rects);
248
249     return CAIRO_STATUS_SUCCESS;
250 }
251
252 static void
253 _cairo_xcb_surface_clear_clip_region (cairo_xcb_surface_t *surface)
254 {
255     uint32_t values[] = { XCB_NONE };
256     _cairo_xcb_connection_render_change_picture (surface->connection,
257                                                  surface->picture,
258                                                  XCB_RENDER_CP_CLIP_MASK,
259                                                  values);
260 }
261
262 static void
263 _cairo_xcb_surface_set_precision (cairo_xcb_surface_t   *surface,
264                                   cairo_antialias_t      antialias)
265 {
266     cairo_xcb_connection_t *connection = surface->connection;
267     uint32_t precision;
268
269     if (connection->force_precision != -1)
270             precision = connection->force_precision;
271     else switch (antialias) {
272     default:
273     case CAIRO_ANTIALIAS_DEFAULT:
274     case CAIRO_ANTIALIAS_GRAY:
275     case CAIRO_ANTIALIAS_NONE:
276     case CAIRO_ANTIALIAS_FAST:
277     case CAIRO_ANTIALIAS_GOOD:
278         precision = XCB_RENDER_POLY_MODE_IMPRECISE;
279         break;
280     case CAIRO_ANTIALIAS_SUBPIXEL:
281     case CAIRO_ANTIALIAS_BEST:
282         precision = XCB_RENDER_POLY_MODE_PRECISE;
283         break;
284     }
285
286     if (surface->precision != precision) {
287         _cairo_xcb_connection_render_change_picture (connection,
288                                                      surface->picture,
289                                                      XCB_RENDER_CP_POLY_MODE,
290                                                      &precision);
291         surface->precision = precision;
292     }
293 }
294
295
296 static void
297 _cairo_xcb_surface_ensure_picture (cairo_xcb_surface_t *surface)
298 {
299     assert (surface->fallback == NULL);
300     if (surface->picture == XCB_NONE) {
301         uint32_t values[1];
302         uint32_t flags = 0;
303
304         if (surface->precision != XCB_RENDER_POLY_MODE_PRECISE) {
305             flags |= XCB_RENDER_CP_POLY_MODE;
306             values[0] = surface->precision;
307         }
308
309         surface->picture = _cairo_xcb_connection_get_xid (surface->connection);
310         _cairo_xcb_connection_render_create_picture (surface->connection,
311                                                      surface->picture,
312                                                      surface->drawable,
313                                                      surface->xrender_format,
314                                                      flags, values);
315     }
316 }
317
318 static cairo_xcb_picture_t *
319 _picture_from_image (cairo_xcb_surface_t *target,
320                      xcb_render_pictformat_t format,
321                      cairo_image_surface_t *image,
322                      cairo_xcb_shm_info_t *shm_info)
323 {
324     xcb_pixmap_t pixmap;
325     xcb_gcontext_t gc;
326     cairo_xcb_picture_t *picture;
327
328     pixmap = _cairo_xcb_connection_create_pixmap (target->connection,
329                                                   image->depth,
330                                                   target->drawable,
331                                                   image->width, image->height);
332
333     gc = _cairo_xcb_screen_get_gc (target->screen, pixmap, image->depth);
334
335     if (shm_info != NULL) {
336         _cairo_xcb_connection_shm_put_image (target->connection,
337                                              pixmap, gc,
338                                              image->width, image->height,
339                                              0, 0,
340                                              image->width, image->height,
341                                              0, 0,
342                                              image->depth,
343                                              shm_info->shm,
344                                              shm_info->offset);
345     } else {
346         int len;
347
348         /* Do we need to trim the image? */
349         len = CAIRO_STRIDE_FOR_WIDTH_BPP (image->width, PIXMAN_FORMAT_BPP (image->pixman_format));
350         if (len == image->stride) {
351             _cairo_xcb_connection_put_image (target->connection,
352                                              pixmap, gc,
353                                              image->width, image->height,
354                                              0, 0,
355                                              image->depth,
356                                              image->stride,
357                                              image->data);
358         } else {
359             _cairo_xcb_connection_put_subimage (target->connection,
360                                                 pixmap, gc,
361                                                 0, 0,
362                                                 image->width, image->height,
363                                                 PIXMAN_FORMAT_BPP (image->pixman_format) / 8,
364                                                 image->stride,
365                                                 0, 0,
366                                                 image->depth,
367                                                 image->data);
368
369         }
370     }
371
372     _cairo_xcb_screen_put_gc (target->screen, image->depth, gc);
373
374     picture = _cairo_xcb_picture_create (target->screen,
375                                          image->pixman_format, format,
376                                          image->width, image->height);
377     if (likely (picture->base.status == CAIRO_STATUS_SUCCESS)) {
378         _cairo_xcb_connection_render_create_picture (target->connection,
379                                                      picture->picture, pixmap, format,
380                                                      0, 0);
381     }
382
383     _cairo_xcb_connection_free_pixmap (target->connection, pixmap);
384
385     return picture;
386 }
387
388 static cairo_bool_t
389 _pattern_is_supported (uint32_t flags,
390                        const cairo_pattern_t *pattern)
391
392 {
393     if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
394         return TRUE;
395
396     if (! _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL)) {
397         if ((flags & CAIRO_XCB_RENDER_HAS_PICTURE_TRANSFORM) == 0)
398             return FALSE;
399     }
400
401     switch (pattern->extend) {
402     default:
403         ASSERT_NOT_REACHED;
404     case CAIRO_EXTEND_NONE:
405     case CAIRO_EXTEND_REPEAT:
406         break;
407     case CAIRO_EXTEND_PAD:
408     case CAIRO_EXTEND_REFLECT:
409         if ((flags & CAIRO_XCB_RENDER_HAS_EXTENDED_REPEAT) == 0)
410             return FALSE;
411     }
412
413     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
414         cairo_filter_t filter;
415
416         filter = pattern->filter;
417         if (_cairo_matrix_has_unity_scale (&pattern->matrix) &&
418             _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
419         {
420             filter = CAIRO_FILTER_NEAREST;
421         }
422
423         if (! (filter == CAIRO_FILTER_NEAREST || filter == CAIRO_FILTER_FAST)) {
424             if ((flags & CAIRO_XCB_RENDER_HAS_FILTERS) == 0)
425                 return FALSE;
426         }
427     } else { /* gradient */
428         if ((flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) == 0)
429             return FALSE;
430
431         /* The RENDER specification says that the inner circle has to be
432          * completely contained inside the outer one. */
433         if (pattern->type == CAIRO_PATTERN_TYPE_RADIAL &&
434             ! _cairo_radial_pattern_focus_is_inside ((cairo_radial_pattern_t *) pattern))
435         {
436             return FALSE;
437         }
438     }
439
440     return pattern->type != CAIRO_PATTERN_TYPE_MESH;
441 }
442
443 static void
444 _cairo_xcb_picture_set_matrix (cairo_xcb_picture_t *picture,
445                                const cairo_matrix_t *matrix,
446                                cairo_filter_t filter,
447                                double xc, double yc)
448 {
449     xcb_render_transform_t transform;
450     pixman_transform_t *pixman_transform;
451     cairo_int_status_t ignored;
452
453     /* Casting between pixman_transform_t and xcb_render_transform_t is safe
454      * because they happen to be the exact same type.
455      */
456     pixman_transform = (pixman_transform_t *) &transform;
457
458     picture->x = picture->x0;
459     picture->y = picture->y0;
460     ignored = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
461                                                      pixman_transform,
462                                                      &picture->x, &picture->y);
463     (void) ignored;
464
465     if (memcmp (&picture->transform, &transform, sizeof (xcb_render_transform_t))) {
466         _cairo_xcb_connection_render_set_picture_transform (_picture_to_connection (picture),
467                                                             picture->picture,
468                                                             &transform);
469
470         picture->transform = transform;
471     }
472 }
473
474 static void
475 _cairo_xcb_picture_set_filter (cairo_xcb_picture_t *picture,
476                                cairo_filter_t filter)
477 {
478     const char *render_filter;
479     int len;
480
481     if (picture->filter == filter)
482         return;
483
484     switch (filter) {
485     case CAIRO_FILTER_FAST:
486         render_filter = "fast";
487         len = strlen ("fast");
488         break;
489
490     case CAIRO_FILTER_GOOD:
491         render_filter = "good";
492         len = strlen ("good");
493         break;
494
495     case CAIRO_FILTER_BEST:
496         render_filter = "best";
497         len = strlen ("best");
498         break;
499
500     case CAIRO_FILTER_NEAREST:
501         render_filter = "nearest";
502         len = strlen ("nearest");
503         break;
504
505     case CAIRO_FILTER_BILINEAR:
506         render_filter = "bilinear";
507         len = strlen ("bilinear");
508         break;
509
510     default:
511         ASSERT_NOT_REACHED;
512     case CAIRO_FILTER_GAUSSIAN:
513         render_filter = "best";
514         len = strlen ("best");
515         break;
516     }
517
518     _cairo_xcb_connection_render_set_picture_filter (_picture_to_connection (picture),
519                                                      picture->picture,
520                                                      len, (char *) render_filter);
521     picture->filter = filter;
522 }
523
524 static void
525 _cairo_xcb_picture_set_extend (cairo_xcb_picture_t *picture,
526                                cairo_extend_t extend)
527 {
528     uint32_t pa[1];
529
530     if (picture->extend == extend)
531         return;
532
533     switch (extend) {
534     default:
535         ASSERT_NOT_REACHED;
536     case CAIRO_EXTEND_NONE:
537         pa[0] = XCB_RENDER_REPEAT_NONE;
538         break;
539
540     case CAIRO_EXTEND_REPEAT:
541         pa[0] = XCB_RENDER_REPEAT_NORMAL;
542         break;
543
544     case CAIRO_EXTEND_REFLECT:
545         pa[0] = XCB_RENDER_REPEAT_REFLECT;
546         break;
547
548     case CAIRO_EXTEND_PAD:
549         pa[0] = XCB_RENDER_REPEAT_PAD;
550         break;
551     }
552
553     _cairo_xcb_connection_render_change_picture (_picture_to_connection (picture),
554                                                  picture->picture,
555                                                  XCB_RENDER_CP_REPEAT, pa);
556     picture->extend = extend;
557 }
558
559 static void
560 _cairo_xcb_picture_set_component_alpha (cairo_xcb_picture_t *picture,
561                                         cairo_bool_t ca)
562 {
563     uint32_t pa[1];
564
565     if (picture->has_component_alpha == ca)
566         return;
567
568     pa[0] = ca;
569
570     _cairo_xcb_connection_render_change_picture (_picture_to_connection (picture),
571                                                  picture->picture,
572                                                  XCB_RENDER_CP_COMPONENT_ALPHA,
573                                                  pa);
574     picture->has_component_alpha = ca;
575 }
576
577 static cairo_xcb_picture_t *
578 _solid_picture (cairo_xcb_surface_t *target,
579                 const cairo_color_t *color)
580 {
581     xcb_render_color_t xcb_color;
582     xcb_render_pictformat_t xrender_format;
583     cairo_xcb_picture_t *picture;
584
585     xcb_color.red   = color->red_short;
586     xcb_color.green = color->green_short;
587     xcb_color.blue  = color->blue_short;
588     xcb_color.alpha = color->alpha_short;
589
590     xrender_format = target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32];
591     picture = _cairo_xcb_picture_create (target->screen,
592                                          PIXMAN_a8r8g8b8,
593                                          xrender_format,
594                                          -1, -1);
595     if (unlikely (picture->base.status))
596         return picture;
597
598     if (target->connection->flags & CAIRO_XCB_RENDER_HAS_GRADIENTS) {
599         _cairo_xcb_connection_render_create_solid_fill (target->connection,
600                                                         picture->picture,
601                                                         xcb_color);
602     } else {
603         xcb_pixmap_t pixmap;
604         uint32_t values[] = { XCB_RENDER_REPEAT_NORMAL };
605
606         pixmap = _cairo_xcb_connection_create_pixmap (target->connection,
607                                                       32, target->drawable, 1, 1);
608         _cairo_xcb_connection_render_create_picture (target->connection,
609                                                      picture->picture,
610                                                      pixmap,
611                                                      xrender_format,
612                                                      XCB_RENDER_CP_REPEAT,
613                                                      values);
614         if (target->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
615             xcb_rectangle_t rect;
616
617             rect.x = rect.y = 0;
618             rect.width = rect.height = 1;
619
620             _cairo_xcb_connection_render_fill_rectangles (_picture_to_connection (picture),
621                                                           XCB_RENDER_PICT_OP_SRC,
622                                                           picture->picture,
623                                                           xcb_color, 1, &rect);
624         } else {
625             xcb_gcontext_t gc;
626             uint32_t pixel;
627
628             gc = _cairo_xcb_screen_get_gc (target->screen, pixmap, 32);
629
630             /* XXX byte ordering? */
631             pixel = ((color->alpha_short >> 8) << 24) |
632                     ((color->red_short   >> 8) << 16) |
633                     ((color->green_short >> 8) << 8) |
634                     ((color->blue_short  >> 8) << 0);
635
636             _cairo_xcb_connection_put_image (target->connection,
637                                              pixmap, gc,
638                                              1, 1, 0, 0,
639                                              32, 4, &pixel);
640
641             _cairo_xcb_screen_put_gc (target->screen, 32, gc);
642         }
643
644         _cairo_xcb_connection_free_pixmap (target->connection, pixmap);
645     }
646
647     return picture;
648 }
649
650 static cairo_xcb_picture_t *
651 _cairo_xcb_transparent_picture (cairo_xcb_surface_t *target)
652 {
653     cairo_xcb_picture_t *picture;
654
655     picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_TRANSPARENT];
656     if (picture == NULL) {
657         picture = _solid_picture (target, CAIRO_COLOR_TRANSPARENT);
658         target->screen->stock_colors[CAIRO_STOCK_TRANSPARENT] = &picture->base;
659     }
660
661     return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
662 }
663
664 static cairo_xcb_picture_t *
665 _cairo_xcb_black_picture (cairo_xcb_surface_t *target)
666 {
667     cairo_xcb_picture_t *picture;
668
669     picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_BLACK];
670     if (picture == NULL) {
671         picture = _solid_picture (target, CAIRO_COLOR_BLACK);
672         target->screen->stock_colors[CAIRO_STOCK_BLACK] = &picture->base;
673     }
674
675     return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
676 }
677
678 static cairo_xcb_picture_t *
679 _cairo_xcb_white_picture (cairo_xcb_surface_t *target)
680 {
681     cairo_xcb_picture_t *picture;
682
683     picture = (cairo_xcb_picture_t *) target->screen->stock_colors[CAIRO_STOCK_WHITE];
684     if (picture == NULL) {
685         picture = _solid_picture (target, CAIRO_COLOR_WHITE);
686         target->screen->stock_colors[CAIRO_STOCK_WHITE] = &picture->base;
687     }
688
689     return (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
690 }
691
692 static cairo_xcb_picture_t *
693 _cairo_xcb_solid_picture (cairo_xcb_surface_t *target,
694                           const cairo_solid_pattern_t *pattern)
695 {
696     cairo_xcb_picture_t *picture;
697     cairo_xcb_screen_t *screen;
698     int i, n_cached;
699
700     if (pattern->color.alpha_short <= 0x00ff)
701         return _cairo_xcb_transparent_picture (target);
702
703     if (pattern->color.alpha_short >= 0xff00) {
704         if (pattern->color.red_short <= 0x00ff &&
705             pattern->color.green_short <= 0x00ff &&
706             pattern->color.blue_short <= 0x00ff)
707         {
708             return _cairo_xcb_black_picture (target);
709         }
710
711         if (pattern->color.red_short >= 0xff00 &&
712             pattern->color.green_short >= 0xff00 &&
713             pattern->color.blue_short >= 0xff00)
714         {
715             return _cairo_xcb_white_picture (target);
716         }
717     }
718
719     screen = target->screen;
720     n_cached = screen->solid_cache_size;
721     for (i = 0; i < n_cached; i++) {
722         if (_cairo_color_equal (&screen->solid_cache[i].color, &pattern->color)) {
723             return (cairo_xcb_picture_t *) cairo_surface_reference (screen->solid_cache[i].picture);
724         }
725     }
726
727     picture = _solid_picture (target, &pattern->color);
728     if (unlikely (picture->base.status))
729         return picture;
730
731     if (screen->solid_cache_size < ARRAY_LENGTH (screen->solid_cache)) {
732         i = screen->solid_cache_size++;
733     } else {
734         i = hars_petruska_f54_1_random () % ARRAY_LENGTH (screen->solid_cache);
735         cairo_surface_destroy (screen->solid_cache[i].picture);
736     }
737     screen->solid_cache[i].picture = cairo_surface_reference (&picture->base);
738     screen->solid_cache[i].color = pattern->color;
739
740     return picture;
741 }
742
743 static cairo_xcb_picture_t *
744 _render_to_picture (cairo_xcb_surface_t *target,
745                     const cairo_pattern_t *pattern,
746                     const cairo_rectangle_int_t *extents)
747 {
748     cairo_image_surface_t *image;
749     cairo_xcb_shm_info_t *shm_info;
750     cairo_pattern_union_t copy;
751     cairo_status_t status;
752     cairo_xcb_picture_t *picture;
753     pixman_format_code_t pixman_format;
754     xcb_render_pictformat_t xrender_format;
755
756     /* XXX handle extend modes via tiling? */
757     /* XXX alpha-only masks? */
758
759     pixman_format = PIXMAN_a8r8g8b8;
760     xrender_format = target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32];
761
762     status = _cairo_xcb_shm_image_create (target->screen->connection,
763                                           pixman_format,
764                                           extents->width, extents->height,
765                                           &image, &shm_info);
766     if (unlikely (status))
767         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
768
769     _cairo_pattern_init_static_copy (&copy.base, pattern);
770     cairo_matrix_translate (&copy.base.matrix, extents->x, extents->y);
771     status = _cairo_surface_paint (&image->base,
772                                    CAIRO_OPERATOR_SOURCE,
773                                    &copy.base,
774                                    NULL);
775     if (unlikely (status)) {
776         cairo_surface_destroy (&image->base);
777         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
778     }
779
780     picture = _picture_from_image (target, xrender_format, image, shm_info);
781     cairo_surface_destroy (&image->base);
782
783     if (unlikely (picture->base.status))
784         return picture;
785
786     _cairo_xcb_picture_set_component_alpha (picture, pattern->has_component_alpha);
787     picture->x = -extents->x;
788     picture->y = -extents->y;
789
790     return picture;
791 }
792
793 static xcb_render_fixed_t *
794 _gradient_to_xcb (const cairo_gradient_pattern_t *gradient,
795                   unsigned int *n_stops,
796                   char *buf, unsigned int buflen)
797 {
798     xcb_render_fixed_t *stops;
799     xcb_render_color_t *colors;
800     unsigned int i;
801
802     assert (gradient->n_stops > 0);
803     *n_stops = MAX (gradient->n_stops, 2);
804
805     if (*n_stops * (sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t)) < buflen)
806     {
807         stops = (xcb_render_fixed_t *) buf;
808     }
809     else
810     {
811         stops =
812             _cairo_malloc_ab (*n_stops,
813                               sizeof (xcb_render_fixed_t) + sizeof (xcb_render_color_t));
814         if (unlikely (stops == NULL))
815             return NULL;
816     }
817
818     colors = (xcb_render_color_t *) (stops + *n_stops);
819     for (i = 0; i < gradient->n_stops; i++) {
820         stops[i] =
821             _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
822
823         colors[i].red   = gradient->stops[i].color.red_short;
824         colors[i].green = gradient->stops[i].color.green_short;
825         colors[i].blue  = gradient->stops[i].color.blue_short;
826         colors[i].alpha = gradient->stops[i].color.alpha_short;
827     }
828
829     /* RENDER does not support gradients with less than 2 stops. If a
830      * gradient has only a single stop, duplicate it to make RENDER
831      * happy. */
832     if (gradient->n_stops == 1) {
833         stops[1] = _cairo_fixed_16_16_from_double (gradient->stops[0].offset);
834
835         colors[1].red   = gradient->stops[0].color.red_short;
836         colors[1].green = gradient->stops[0].color.green_short;
837         colors[1].blue  = gradient->stops[0].color.blue_short;
838         colors[1].alpha = gradient->stops[0].color.alpha_short;
839     }
840
841     return stops;
842 }
843
844 static cairo_xcb_picture_t *
845 _cairo_xcb_linear_picture (cairo_xcb_surface_t *target,
846                            const cairo_linear_pattern_t *pattern,
847                            const cairo_rectangle_int_t *extents)
848 {
849     char buf[CAIRO_STACK_BUFFER_SIZE];
850     xcb_render_fixed_t *stops;
851     xcb_render_color_t *colors;
852     xcb_render_pointfix_t p1, p2;
853     cairo_matrix_t matrix;
854     cairo_circle_double_t extremes[2];
855     cairo_xcb_picture_t *picture;
856     cairo_status_t status;
857     unsigned int n_stops;
858
859     _cairo_gradient_pattern_fit_to_range (&pattern->base, PIXMAN_MAX_INT >> 1, &matrix, extremes);
860
861     picture = (cairo_xcb_picture_t *)
862         _cairo_xcb_screen_lookup_linear_picture (target->screen, pattern);
863     if (picture != NULL)
864         goto setup_picture;
865
866     stops = _gradient_to_xcb (&pattern->base, &n_stops, buf, sizeof (buf));
867     if (unlikely (stops == NULL))
868         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
869
870     picture = _cairo_xcb_picture_create (target->screen,
871                                          target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32],
872                                          PIXMAN_a8r8g8b8,
873                                          -1, -1);
874     if (unlikely (picture->base.status)) {
875         if (stops != (xcb_render_fixed_t *) buf)
876             free (stops);
877         return picture;
878     }
879     picture->filter = CAIRO_FILTER_DEFAULT;
880
881     colors = (xcb_render_color_t *) (stops + n_stops);
882
883     p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
884     p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
885     p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
886     p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
887
888     _cairo_xcb_connection_render_create_linear_gradient (target->connection,
889                                                          picture->picture,
890                                                          p1, p2,
891                                                          n_stops,
892                                                          stops, colors);
893
894     if (stops != (xcb_render_fixed_t *) buf)
895         free (stops);
896
897     status = _cairo_xcb_screen_store_linear_picture (target->screen,
898                                                      pattern,
899                                                      &picture->base);
900     if (unlikely (status)) {
901         cairo_surface_destroy (&picture->base);
902         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
903     }
904
905 setup_picture:
906     _cairo_xcb_picture_set_matrix (picture, &matrix,
907                                    pattern->base.base.filter,
908                                    extents->x + extents->width/2.,
909                                    extents->y + extents->height/2.);
910     _cairo_xcb_picture_set_filter (picture, pattern->base.base.filter);
911     _cairo_xcb_picture_set_extend (picture, pattern->base.base.extend);
912     _cairo_xcb_picture_set_component_alpha (picture,
913                                             pattern->base.base.has_component_alpha);
914
915     return picture;
916 }
917
918 static cairo_xcb_picture_t *
919 _cairo_xcb_radial_picture (cairo_xcb_surface_t *target,
920                            const cairo_radial_pattern_t *pattern,
921                            const cairo_rectangle_int_t *extents)
922 {
923     char buf[CAIRO_STACK_BUFFER_SIZE];
924     xcb_render_fixed_t *stops;
925     xcb_render_color_t *colors;
926     xcb_render_pointfix_t p1, p2;
927     xcb_render_fixed_t r1, r2;
928     cairo_matrix_t matrix;
929     cairo_circle_double_t extremes[2];
930     cairo_xcb_picture_t *picture;
931     cairo_status_t status;
932     unsigned int n_stops;
933
934     _cairo_gradient_pattern_fit_to_range (&pattern->base, PIXMAN_MAX_INT >> 1, &matrix, extremes);
935
936     picture = (cairo_xcb_picture_t *)
937         _cairo_xcb_screen_lookup_radial_picture (target->screen, pattern);
938     if (picture != NULL)
939         goto setup_picture;
940
941     stops = _gradient_to_xcb (&pattern->base, &n_stops, buf, sizeof (buf));
942     if (unlikely (stops == NULL))
943         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
944
945     picture = _cairo_xcb_picture_create (target->screen,
946                                          target->screen->connection->standard_formats[CAIRO_FORMAT_ARGB32],
947                                          PIXMAN_a8r8g8b8,
948                                          -1, -1);
949     if (unlikely (picture->base.status)) {
950         if (stops != (xcb_render_fixed_t *) buf)
951             free (stops);
952         return picture;
953     }
954     picture->filter = CAIRO_FILTER_DEFAULT;
955
956     colors = (xcb_render_color_t *) (stops + n_stops);
957
958     p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
959     p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
960     p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
961     p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
962
963     r1 = _cairo_fixed_16_16_from_double (extremes[0].radius);
964     r2 = _cairo_fixed_16_16_from_double (extremes[1].radius);
965
966     _cairo_xcb_connection_render_create_radial_gradient (target->connection,
967                                                          picture->picture,
968                                                          p1, p2, r1, r2,
969                                                          n_stops,
970                                                          stops, colors);
971
972     if (stops != (xcb_render_fixed_t *) buf)
973         free (stops);
974
975     status = _cairo_xcb_screen_store_radial_picture (target->screen,
976                                                      pattern,
977                                                      &picture->base);
978     if (unlikely (status)) {
979         cairo_surface_destroy (&picture->base);
980         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
981     }
982
983 setup_picture:
984     _cairo_xcb_picture_set_matrix (picture, &matrix,
985                                    pattern->base.base.filter,
986                                    extents->x + extents->width/2.,
987                                    extents->y + extents->height/2.);
988     _cairo_xcb_picture_set_filter (picture, pattern->base.base.filter);
989     _cairo_xcb_picture_set_extend (picture, pattern->base.base.extend);
990     _cairo_xcb_picture_set_component_alpha (picture,
991                                             pattern->base.base.has_component_alpha);
992
993     return picture;
994 }
995
996 static cairo_xcb_picture_t *
997 _copy_to_picture (cairo_xcb_surface_t *source)
998 {
999     cairo_xcb_picture_t *picture;
1000     uint32_t values[] = { 0, 1 };
1001
1002     if (source->deferred_clear) {
1003         cairo_status_t status = _cairo_xcb_surface_clear (source);
1004         if (unlikely (status))
1005             return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
1006     }
1007
1008     picture = _cairo_xcb_picture_create (source->screen,
1009                                          source->xrender_format,
1010                                          source->pixman_format,
1011                                          source->width,
1012                                          source->height);
1013     if (unlikely (picture->base.status))
1014         return picture;
1015
1016     _cairo_xcb_connection_render_create_picture (source->connection,
1017                                                  picture->picture,
1018                                                  source->drawable,
1019                                                  source->xrender_format,
1020                                                  XCB_RENDER_CP_GRAPHICS_EXPOSURE |
1021                                                  XCB_RENDER_CP_SUBWINDOW_MODE,
1022                                                  values);
1023
1024     return picture;
1025 }
1026
1027 static void
1028 _cairo_xcb_surface_setup_surface_picture(cairo_xcb_picture_t *picture,
1029                                          const cairo_surface_pattern_t *pattern,
1030                                          const cairo_rectangle_int_t *extents)
1031 {
1032     cairo_filter_t filter;
1033
1034     filter = pattern->base.filter;
1035     if (filter != CAIRO_FILTER_NEAREST &&
1036         _cairo_matrix_has_unity_scale (&pattern->base.matrix) &&
1037         _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.x0)) &&
1038         _cairo_fixed_is_integer (_cairo_fixed_from_double (pattern->base.matrix.y0)))
1039     {
1040         filter = CAIRO_FILTER_NEAREST;
1041     }
1042     _cairo_xcb_picture_set_filter (picture, filter);
1043
1044     _cairo_xcb_picture_set_matrix (picture,
1045                                    &pattern->base.matrix, filter,
1046                                    extents->x + extents->width/2.,
1047                                    extents->y + extents->height/2.);
1048
1049
1050     _cairo_xcb_picture_set_extend (picture, pattern->base.extend);
1051     _cairo_xcb_picture_set_component_alpha (picture, pattern->base.has_component_alpha);
1052 }
1053
1054 static cairo_xcb_picture_t *
1055 record_to_picture (cairo_surface_t *target,
1056                    const cairo_surface_pattern_t *pattern,
1057                    const cairo_rectangle_int_t *extents)
1058 {
1059     cairo_surface_pattern_t tmp_pattern;
1060     cairo_xcb_picture_t *picture;
1061     cairo_status_t status;
1062     cairo_matrix_t matrix;
1063     cairo_surface_t *tmp;
1064     cairo_surface_t *source;
1065     cairo_rectangle_int_t limit;
1066     cairo_extend_t extend;
1067
1068     /* XXX: The following was once more or less copied from cairo-xlibs-ource.c,
1069      * record_source() and recording_pattern_get_surface(), can we share a
1070      * single version?
1071      */
1072
1073     /* First get the 'real' recording surface and figure out the size for tmp */
1074     source = _cairo_pattern_get_source (pattern, &limit);
1075     assert (_cairo_surface_is_recording (source));
1076
1077     if (! _cairo_matrix_is_identity (&pattern->base.matrix)) {
1078         double x1, y1, x2, y2;
1079
1080         matrix = pattern->base.matrix;
1081         status = cairo_matrix_invert (&matrix);
1082         assert (status == CAIRO_STATUS_SUCCESS);
1083
1084         x1 = limit.x;
1085         y1 = limit.y;
1086         x2 = limit.x + limit.width;
1087         y2 = limit.y + limit.height;
1088
1089         _cairo_matrix_transform_bounding_box (&matrix,
1090                                               &x1, &y1, &x2, &y2, NULL);
1091
1092         limit.x = floor (x1);
1093         limit.y = floor (y1);
1094         limit.width  = ceil (x2) - limit.x;
1095         limit.height = ceil (y2) - limit.y;
1096     }
1097     extend = pattern->base.extend;
1098     if (_cairo_rectangle_contains_rectangle (&limit, extents))
1099         extend = CAIRO_EXTEND_NONE;
1100     if (extend == CAIRO_EXTEND_NONE && ! _cairo_rectangle_intersect (&limit, extents))
1101         return _cairo_xcb_transparent_picture ((cairo_xcb_surface_t *) target);
1102
1103     /* Now draw the recording surface to an xcb surface */
1104     tmp = _cairo_surface_create_similar_scratch (target,
1105                                                  source->content,
1106                                                  limit.width,
1107                                                  limit.height);
1108     if (tmp->status != CAIRO_STATUS_SUCCESS) {
1109         return (cairo_xcb_picture_t *) tmp;
1110     }
1111
1112     cairo_matrix_init_translate (&matrix, limit.x, limit.y);
1113     cairo_matrix_multiply (&matrix, &matrix, &pattern->base.matrix);
1114
1115     status = _cairo_recording_surface_replay_with_clip (source,
1116                                                         &matrix, tmp,
1117                                                         NULL);
1118     if (unlikely (status)) {
1119         cairo_surface_destroy (tmp);
1120         return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
1121     }
1122
1123     /* Now that we have drawn this to an xcb surface, try again with that */
1124     _cairo_pattern_init_static_copy (&tmp_pattern.base, &pattern->base);
1125     tmp_pattern.surface = tmp;
1126     cairo_matrix_init_translate (&tmp_pattern.base.matrix, -limit.x, -limit.y);
1127
1128     picture = _copy_to_picture ((cairo_xcb_surface_t *) tmp);
1129     if (picture->base.status == CAIRO_STATUS_SUCCESS)
1130         _cairo_xcb_surface_setup_surface_picture (picture, &tmp_pattern, extents);
1131     cairo_surface_destroy (tmp);
1132     return picture;
1133 }
1134
1135 static cairo_xcb_picture_t *
1136 _cairo_xcb_surface_picture (cairo_xcb_surface_t *target,
1137                             const cairo_surface_pattern_t *pattern,
1138                             const cairo_rectangle_int_t *extents)
1139 {
1140     cairo_surface_t *source = pattern->surface;
1141     cairo_xcb_picture_t *picture;
1142
1143     picture = (cairo_xcb_picture_t *)
1144         _cairo_surface_has_snapshot (source, &_cairo_xcb_picture_backend);
1145     if (picture != NULL) {
1146         if (picture->screen == target->screen) {
1147             picture = (cairo_xcb_picture_t *) cairo_surface_reference (&picture->base);
1148             _cairo_xcb_surface_setup_surface_picture (picture, pattern, extents);
1149             return picture;
1150         }
1151         picture = NULL;
1152     }
1153
1154     if (source->type == CAIRO_SURFACE_TYPE_XCB)
1155     {
1156         if (source->backend->type == CAIRO_SURFACE_TYPE_XCB) {
1157             cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) source;
1158             if (xcb->screen == target->screen && xcb->fallback == NULL) {
1159                 picture = _copy_to_picture ((cairo_xcb_surface_t *) source);
1160                 if (unlikely (picture->base.status))
1161                     return picture;
1162             }
1163         } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1164             cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1165             cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) sub->target;
1166
1167             /* XXX repeat interval with source clipping? */
1168             if (FALSE && xcb->screen == target->screen && xcb->fallback == NULL) {
1169                 xcb_rectangle_t rect;
1170
1171                 picture = _copy_to_picture (xcb);
1172                 if (unlikely (picture->base.status))
1173                     return picture;
1174
1175                 rect.x = sub->extents.x;
1176                 rect.y = sub->extents.y;
1177                 rect.width  = sub->extents.width;
1178                 rect.height = sub->extents.height;
1179
1180                 _cairo_xcb_connection_render_set_picture_clip_rectangles (xcb->connection,
1181                                                                           picture->picture,
1182                                                                           0, 0,
1183                                                                           1, &rect);
1184                 picture->x0 = rect.x;
1185                 picture->y0 = rect.y;
1186                 picture->width  = rect.width;
1187                 picture->height = rect.height;
1188             }
1189         } else if (_cairo_surface_is_snapshot (source)) {
1190             cairo_surface_snapshot_t *snap = (cairo_surface_snapshot_t *) source;
1191             cairo_xcb_surface_t *xcb = (cairo_xcb_surface_t *) snap->target;
1192
1193             if (xcb->screen == target->screen && xcb->fallback == NULL) {
1194                 picture = _copy_to_picture (xcb);
1195                 if (unlikely (picture->base.status))
1196                     return picture;
1197             }
1198         }
1199     }
1200 #if CAIRO_HAS_XLIB_XCB_FUNCTIONS
1201     else if (source->type == CAIRO_SURFACE_TYPE_XLIB)
1202     {
1203         if (source->backend->type == CAIRO_SURFACE_TYPE_XLIB) {
1204             cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) source)->xcb;
1205             if (xcb->screen == target->screen && xcb->fallback == NULL) {
1206                 picture = _copy_to_picture (xcb);
1207                 if (unlikely (picture->base.status))
1208                     return picture;
1209             }
1210         } else if (source->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
1211             cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) source;
1212             cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) sub->target)->xcb;
1213
1214             if (FALSE && xcb->screen == target->screen && xcb->fallback == NULL) {
1215                 xcb_rectangle_t rect;
1216
1217                 picture = _copy_to_picture (xcb);
1218                 if (unlikely (picture->base.status))
1219                     return picture;
1220
1221                 rect.x = sub->extents.x;
1222                 rect.y = sub->extents.y;
1223                 rect.width  = sub->extents.width;
1224                 rect.height = sub->extents.height;
1225
1226                 _cairo_xcb_connection_render_set_picture_clip_rectangles (xcb->connection,
1227                                                                           picture->picture,
1228                                                                           0, 0,
1229                                                                           1, &rect);
1230                 picture->x0 = rect.x;
1231                 picture->y0 = rect.y;
1232                 picture->width  = rect.width;
1233                 picture->height = rect.height;
1234             }
1235         } else if (_cairo_surface_is_snapshot (source)) {
1236             cairo_surface_snapshot_t *snap = (cairo_surface_snapshot_t *) source;
1237             cairo_xcb_surface_t *xcb = ((cairo_xlib_xcb_surface_t *) snap->target)->xcb;
1238
1239             if (xcb->screen == target->screen && xcb->fallback == NULL) {
1240                 picture = _copy_to_picture (xcb);
1241                 if (unlikely (picture->base.status))
1242                     return picture;
1243             }
1244         }
1245     }
1246 #endif
1247 #if CAIRO_HAS_GL_FUNCTIONS
1248     else if (source->type == CAIRO_SURFACE_TYPE_GL)
1249     {
1250         /* pixmap from texture */
1251     }
1252 #endif
1253     else if (source->type == CAIRO_SURFACE_TYPE_RECORDING)
1254     {
1255         /* We have to skip the call to attach_snapshot() because we possibly
1256          * only drew part of the recording surface.
1257          * TODO: When can we safely attach a snapshot?
1258          */
1259         return record_to_picture(&target->base, pattern, extents);
1260     }
1261
1262     if (picture == NULL) {
1263         cairo_image_surface_t *image;
1264         void *image_extra;
1265         cairo_status_t status;
1266
1267         status = _cairo_surface_acquire_source_image (source, &image, &image_extra);
1268         if (unlikely (status))
1269             return (cairo_xcb_picture_t *) _cairo_surface_create_in_error (status);
1270
1271         if (image->format != CAIRO_FORMAT_INVALID) {
1272             xcb_render_pictformat_t format;
1273
1274             format = target->screen->connection->standard_formats[image->format];
1275
1276             picture = _picture_from_image (target, format, image, NULL);
1277             _cairo_surface_release_source_image (source, image, image_extra);
1278         } else {
1279             cairo_image_surface_t *conv;
1280             xcb_render_pictformat_t render_format;
1281
1282             /* XXX XRenderPutImage! */
1283
1284             conv = _cairo_image_surface_coerce (image);
1285             _cairo_surface_release_source_image (source, image, image_extra);
1286             if (unlikely (conv->base.status))
1287                 return (cairo_xcb_picture_t *) conv;
1288
1289             render_format = target->screen->connection->standard_formats[conv->format];
1290             picture = _picture_from_image (target, render_format, conv, NULL);
1291             cairo_surface_destroy (&conv->base);
1292         }
1293
1294         if (unlikely (picture->base.status))
1295             return picture;
1296     }
1297
1298     _cairo_surface_attach_snapshot (source,
1299                                     &picture->base,
1300                                     NULL);
1301
1302     _cairo_xcb_surface_setup_surface_picture (picture, pattern, extents);
1303     return picture;
1304 }
1305
1306 static cairo_xcb_picture_t *
1307 _cairo_xcb_picture_for_pattern (cairo_xcb_surface_t *target,
1308                                 const cairo_pattern_t *pattern,
1309                                 const cairo_rectangle_int_t *extents)
1310 {
1311     if (pattern == NULL)
1312         return _cairo_xcb_white_picture (target);
1313
1314     if (! _pattern_is_supported (target->connection->flags, pattern))
1315         return _render_to_picture (target, pattern, extents);
1316
1317     switch (pattern->type) {
1318     case CAIRO_PATTERN_TYPE_SOLID:
1319         return _cairo_xcb_solid_picture (target, (cairo_solid_pattern_t *) pattern);
1320
1321     case CAIRO_PATTERN_TYPE_LINEAR:
1322         return _cairo_xcb_linear_picture (target,
1323                                           (cairo_linear_pattern_t *) pattern,
1324                                           extents);
1325
1326     case CAIRO_PATTERN_TYPE_RADIAL:
1327         return _cairo_xcb_radial_picture (target,
1328                                           (cairo_radial_pattern_t *) pattern,
1329                                           extents);
1330
1331     case CAIRO_PATTERN_TYPE_SURFACE:
1332         return _cairo_xcb_surface_picture (target,
1333                                            (cairo_surface_pattern_t *) pattern,
1334                                            extents);
1335     default:
1336         ASSERT_NOT_REACHED;
1337     case CAIRO_PATTERN_TYPE_MESH:
1338     case CAIRO_PATTERN_TYPE_RASTER_SOURCE:
1339         return _render_to_picture (target, pattern, extents);
1340     }
1341 }
1342
1343 COMPILE_TIME_ASSERT (sizeof (xcb_rectangle_t) <= sizeof (cairo_box_t));
1344
1345 static cairo_status_t
1346 _render_fill_boxes (void                        *abstract_dst,
1347                     cairo_operator_t             op,
1348                     const cairo_color_t         *color,
1349                     cairo_boxes_t               *boxes)
1350 {
1351     cairo_xcb_surface_t *dst = abstract_dst;
1352     xcb_rectangle_t stack_xrects[CAIRO_STACK_ARRAY_LENGTH (sizeof (xcb_rectangle_t))];
1353     xcb_rectangle_t *xrects = stack_xrects;
1354     xcb_render_color_t render_color;
1355     int render_op = _render_operator (op);
1356     struct _cairo_boxes_chunk *chunk;
1357     int max_count;
1358
1359     render_color.red   = color->red_short;
1360     render_color.green = color->green_short;
1361     render_color.blue  = color->blue_short;
1362     render_color.alpha = color->alpha_short;
1363
1364     max_count = 0;
1365     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1366         if (chunk->count > max_count)
1367             max_count = chunk->count;
1368     }
1369     if (max_count > ARRAY_LENGTH (stack_xrects)) {
1370         xrects = _cairo_malloc_ab (max_count, sizeof (xcb_rectangle_t));
1371         if (unlikely (xrects == NULL))
1372             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1373     }
1374
1375     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1376         int i, j;
1377
1378         for (i = j = 0; i < chunk->count; i++) {
1379             int x1 = _cairo_fixed_integer_round_down (chunk->base[i].p1.x);
1380             int y1 = _cairo_fixed_integer_round_down (chunk->base[i].p1.y);
1381             int x2 = _cairo_fixed_integer_round_down (chunk->base[i].p2.x);
1382             int y2 = _cairo_fixed_integer_round_down (chunk->base[i].p2.y);
1383
1384             if (x2 > x1 && y2 > y1) {
1385                 xrects[j].x = x1;
1386                 xrects[j].y = y1;
1387                 xrects[j].width  = x2 - x1;
1388                 xrects[j].height = y2 - y1;
1389                 j++;
1390             }
1391         }
1392
1393         if (j) {
1394             _cairo_xcb_connection_render_fill_rectangles
1395                 (dst->connection,
1396                  render_op, dst->picture,
1397                  render_color, j, xrects);
1398         }
1399     }
1400
1401     if (xrects != stack_xrects)
1402         free (xrects);
1403
1404     return CAIRO_STATUS_SUCCESS;
1405 }
1406
1407 /* pixel aligned, non-overlapping boxes */
1408 static cairo_int_status_t
1409 _render_composite_boxes (cairo_xcb_surface_t    *dst,
1410                          cairo_operator_t        op,
1411                          const cairo_pattern_t  *src_pattern,
1412                          const cairo_pattern_t  *mask_pattern,
1413                          const cairo_rectangle_int_t *extents,
1414                          const cairo_boxes_t *boxes)
1415 {
1416     cairo_xcb_picture_t *src, *mask;
1417     const struct _cairo_boxes_chunk *chunk;
1418     xcb_rectangle_t stack_boxes[CAIRO_STACK_ARRAY_LENGTH (xcb_rectangle_t)];
1419     xcb_rectangle_t *clip_boxes;
1420     cairo_rectangle_int_t stack_extents;
1421     cairo_status_t status;
1422     int num_boxes;
1423     int render_op;
1424
1425     render_op = _render_operator (op);
1426
1427     if (src_pattern == NULL) {
1428         src_pattern = mask_pattern;
1429         mask_pattern = NULL;
1430     }
1431
1432     /* amalgamate into a single Composite call by setting a clip region */
1433     clip_boxes = stack_boxes;
1434     if (boxes->num_boxes > ARRAY_LENGTH (stack_boxes)) {
1435         clip_boxes = _cairo_malloc_ab (boxes->num_boxes, sizeof (xcb_rectangle_t));
1436         if (unlikely (clip_boxes == NULL))
1437             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1438     }
1439
1440     src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
1441     status = src->base.status;
1442     if (unlikely (status))
1443         goto cleanup_boxes;
1444
1445     num_boxes = 0;
1446     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
1447         const cairo_box_t *box = chunk->base;
1448         int i;
1449
1450         for (i = 0; i < chunk->count; i++) {
1451             int x = _cairo_fixed_integer_round_down (box[i].p1.x);
1452             int y = _cairo_fixed_integer_round_down (box[i].p1.y);
1453             int width  = _cairo_fixed_integer_round_down (box[i].p2.x) - x;
1454             int height = _cairo_fixed_integer_round_down (box[i].p2.y) - y;
1455
1456             if (width && height) {
1457                 clip_boxes[num_boxes].x = x;
1458                 clip_boxes[num_boxes].y = y;
1459                 clip_boxes[num_boxes].width = width;
1460                 clip_boxes[num_boxes].height = height;
1461                 num_boxes++;
1462             }
1463         }
1464     }
1465
1466     if (num_boxes) {
1467         if (num_boxes > 1) {
1468             _cairo_xcb_connection_render_set_picture_clip_rectangles (dst->connection,
1469                                                                       dst->picture,
1470                                                                       0, 0,
1471                                                                       num_boxes,
1472                                                                       clip_boxes);
1473         } else {
1474             stack_extents.x = clip_boxes[0].x;
1475             stack_extents.y = clip_boxes[0].y;
1476             stack_extents.width  = clip_boxes[0].width;
1477             stack_extents.height = clip_boxes[0].height;
1478             extents = &stack_extents;
1479         }
1480
1481         if (mask_pattern != NULL) {
1482             mask = _cairo_xcb_picture_for_pattern (dst, mask_pattern, extents);
1483             status = mask->base.status;
1484             if (unlikely (status))
1485                 goto cleanup_clip;
1486
1487             _cairo_xcb_connection_render_composite (dst->connection,
1488                                                     render_op,
1489                                                     src->picture,
1490                                                     mask->picture,
1491                                                     dst->picture,
1492                                                     src->x + extents->x, src->y + extents->y,
1493                                                     mask->x + extents->x, mask->y + extents->y,
1494                                                     extents->x, extents->y,
1495                                                     extents->width, extents->height);
1496
1497             cairo_surface_destroy (&mask->base);
1498         } else {
1499             _cairo_xcb_connection_render_composite (dst->connection,
1500                                                     render_op,
1501                                                     src->picture,
1502                                                     XCB_NONE,
1503                                                     dst->picture,
1504                                                     src->x + extents->x, src->y + extents->y,
1505                                                     0, 0,
1506                                                     extents->x, extents->y,
1507                                                     extents->width, extents->height);
1508         }
1509
1510 cleanup_clip:
1511
1512         if (num_boxes > 1)
1513             _cairo_xcb_surface_clear_clip_region (dst);
1514     }
1515
1516     cairo_surface_destroy (&src->base);
1517
1518 cleanup_boxes:
1519
1520     if (clip_boxes != stack_boxes)
1521         free (clip_boxes);
1522
1523     return status;
1524 }
1525
1526
1527 #define CAIRO_FIXED_16_16_MIN _cairo_fixed_from_int (-32768)
1528 #define CAIRO_FIXED_16_16_MAX _cairo_fixed_from_int (32767)
1529
1530 static cairo_bool_t
1531 _line_exceeds_16_16 (const cairo_line_t *line)
1532 {
1533     return
1534         line->p1.x <= CAIRO_FIXED_16_16_MIN ||
1535         line->p1.x >= CAIRO_FIXED_16_16_MAX ||
1536
1537         line->p2.x <= CAIRO_FIXED_16_16_MIN ||
1538         line->p2.x >= CAIRO_FIXED_16_16_MAX ||
1539
1540         line->p1.y <= CAIRO_FIXED_16_16_MIN ||
1541         line->p1.y >= CAIRO_FIXED_16_16_MAX ||
1542
1543         line->p2.y <= CAIRO_FIXED_16_16_MIN ||
1544         line->p2.y >= CAIRO_FIXED_16_16_MAX;
1545 }
1546
1547 static void
1548 _project_line_x_onto_16_16 (const cairo_line_t *line,
1549                             cairo_fixed_t top,
1550                             cairo_fixed_t bottom,
1551                             xcb_render_linefix_t *out)
1552 {
1553     cairo_point_double_t p1, p2;
1554     double m;
1555
1556     p1.x = _cairo_fixed_to_double (line->p1.x);
1557     p1.y = _cairo_fixed_to_double (line->p1.y);
1558
1559     p2.x = _cairo_fixed_to_double (line->p2.x);
1560     p2.y = _cairo_fixed_to_double (line->p2.y);
1561
1562     m = (p2.x - p1.x) / (p2.y - p1.y);
1563     out->p1.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (top - line->p1.y));
1564     out->p2.x = _cairo_fixed_16_16_from_double (p1.x + m * _cairo_fixed_to_double (bottom - line->p1.y));
1565 }
1566
1567 typedef struct {
1568     cairo_traps_t traps;
1569     cairo_antialias_t antialias;
1570 } composite_traps_info_t;
1571
1572 COMPILE_TIME_ASSERT (sizeof (xcb_render_trapezoid_t) <= sizeof (cairo_trapezoid_t));
1573
1574 static cairo_int_status_t
1575 _composite_traps (void *closure,
1576                   cairo_xcb_surface_t   *dst,
1577                   cairo_operator_t       op,
1578                   const cairo_pattern_t *pattern,
1579                   int dst_x, int dst_y,
1580                   const cairo_rectangle_int_t *extents,
1581                   cairo_clip_t          *clip)
1582 {
1583     composite_traps_info_t *info = closure;
1584     const cairo_traps_t *traps = &info->traps;
1585     cairo_xcb_picture_t *src;
1586     cairo_format_t format;
1587     xcb_render_pictformat_t xrender_format;
1588     xcb_render_trapezoid_t *xtraps;
1589     int render_reference_x, render_reference_y;
1590     cairo_status_t status;
1591     int i;
1592
1593     if (dst->deferred_clear) {
1594         status = _cairo_xcb_surface_clear (dst);
1595         if (unlikely (status))
1596                 return status;
1597     }
1598
1599     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
1600     if (unlikely (src->base.status))
1601         return src->base.status;
1602
1603     if (info->antialias == CAIRO_ANTIALIAS_NONE)
1604         format = CAIRO_FORMAT_A1;
1605     else
1606         format = CAIRO_FORMAT_A8;
1607     xrender_format = dst->screen->connection->standard_formats[format];
1608
1609     xtraps = (xcb_render_trapezoid_t *) traps->traps;
1610     for (i = 0; i < traps->num_traps; i++) {
1611         cairo_trapezoid_t t = traps->traps[i];
1612
1613         /* top/bottom will be clamped to surface bounds */
1614         xtraps[i].top = _cairo_fixed_to_16_16 (t.top);
1615         xtraps[i].top -= dst_y << 16;
1616         xtraps[i].bottom = _cairo_fixed_to_16_16 (t.bottom);
1617         xtraps[i].bottom -= dst_y << 16;
1618
1619         /* However, all the other coordinates will have been left untouched so
1620          * as not to introduce numerical error. Recompute them if they
1621          * exceed the 16.16 limits.
1622          */
1623         if (unlikely (_line_exceeds_16_16 (&t.left))) {
1624             _project_line_x_onto_16_16 (&t.left,
1625                                         t.top,
1626                                         t.bottom,
1627                                         &xtraps[i].left);
1628             xtraps[i].left.p1.y = xtraps[i].top;
1629             xtraps[i].left.p2.y = xtraps[i].bottom;
1630         } else {
1631             xtraps[i].left.p1.x = _cairo_fixed_to_16_16 (t.left.p1.x);
1632             xtraps[i].left.p1.y = _cairo_fixed_to_16_16 (t.left.p1.y);
1633             xtraps[i].left.p2.x = _cairo_fixed_to_16_16 (t.left.p2.x);
1634             xtraps[i].left.p2.y = _cairo_fixed_to_16_16 (t.left.p2.y);
1635         }
1636         xtraps[i].left.p1.x -= dst_x << 16;
1637         xtraps[i].left.p1.y -= dst_y << 16;
1638         xtraps[i].left.p2.x -= dst_x << 16;
1639         xtraps[i].left.p2.y -= dst_y << 16;
1640
1641         if (unlikely (_line_exceeds_16_16 (&t.right))) {
1642             _project_line_x_onto_16_16 (&t.right,
1643                                         t.top,
1644                                         t.bottom,
1645                                         &xtraps[i].right);
1646             xtraps[i].right.p1.y = xtraps[i].top;
1647             xtraps[i].right.p2.y = xtraps[i].bottom;
1648         } else {
1649             xtraps[i].right.p1.x = _cairo_fixed_to_16_16 (t.right.p1.x);
1650             xtraps[i].right.p1.y = _cairo_fixed_to_16_16 (t.right.p1.y);
1651             xtraps[i].right.p2.x = _cairo_fixed_to_16_16 (t.right.p2.x);
1652             xtraps[i].right.p2.y = _cairo_fixed_to_16_16 (t.right.p2.y);
1653         }
1654         xtraps[i].right.p1.x -= dst_x << 16;
1655         xtraps[i].right.p1.y -= dst_y << 16;
1656         xtraps[i].right.p2.x -= dst_x << 16;
1657         xtraps[i].right.p2.y -= dst_y << 16;
1658     }
1659
1660     if (xtraps[0].left.p1.y < xtraps[0].left.p2.y) {
1661         render_reference_x = xtraps[0].left.p1.x >> 16;
1662         render_reference_y = xtraps[0].left.p1.y >> 16;
1663     } else {
1664         render_reference_x = xtraps[0].left.p2.x >> 16;
1665         render_reference_y = xtraps[0].left.p2.y >> 16;
1666     }
1667     render_reference_x += src->x + dst_x;
1668     render_reference_y += src->y + dst_y;
1669
1670     _cairo_xcb_surface_set_precision (dst, info->antialias);
1671     _cairo_xcb_connection_render_trapezoids (dst->connection,
1672                                              _render_operator (op),
1673                                              src->picture,
1674                                              dst->picture,
1675                                              xrender_format,
1676                                              render_reference_x,
1677                                              render_reference_y,
1678                                              traps->num_traps, xtraps);
1679
1680     cairo_surface_destroy (&src->base);
1681
1682     return CAIRO_STATUS_SUCCESS;
1683 }
1684
1685 /* low-level composite driver */
1686
1687 static cairo_xcb_surface_t *
1688 get_clip_surface (const cairo_clip_t *clip,
1689                   cairo_xcb_surface_t *target,
1690                   int *tx, int *ty)
1691 {
1692     cairo_surface_t *surface;
1693     cairo_status_t status;
1694
1695     surface = _cairo_surface_create_similar_solid (&target->base,
1696                                                    CAIRO_CONTENT_ALPHA,
1697                                                    clip->extents.width,
1698                                                    clip->extents.height,
1699                                                    CAIRO_COLOR_WHITE);
1700     if (unlikely (surface->status))
1701         return (cairo_xcb_surface_t *) surface;
1702
1703     assert (surface->backend == &_cairo_xcb_surface_backend);
1704     status = _cairo_clip_combine_with_surface (clip, surface,
1705                                                clip->extents.x, clip->extents.y);
1706     if (unlikely (status)) {
1707         cairo_surface_destroy (surface);
1708         surface = _cairo_surface_create_in_error (status);
1709     }
1710
1711     *tx = clip->extents.x;
1712     *ty = clip->extents.y;
1713
1714     return (cairo_xcb_surface_t *) surface;
1715 }
1716
1717 typedef cairo_int_status_t
1718 (*xcb_draw_func_t) (void                                *closure,
1719                     cairo_xcb_surface_t                 *dst,
1720                     cairo_operator_t                     op,
1721                     const cairo_pattern_t               *src,
1722                     int                                  dst_x,
1723                     int                                  dst_y,
1724                     const cairo_rectangle_int_t         *extents,
1725                     cairo_clip_t                        *clip);
1726
1727 static void do_unaligned_row(void (*blt)(void *closure,
1728                                          int16_t x, int16_t y,
1729                                          int16_t w, int16_t h,
1730                                          uint16_t coverage),
1731                              void *closure,
1732                              const cairo_box_t *b,
1733                              int tx, int y, int h,
1734                              uint16_t coverage)
1735 {
1736     int x1 = _cairo_fixed_integer_part (b->p1.x) - tx;
1737     int x2 = _cairo_fixed_integer_part (b->p2.x) - tx;
1738     if (x2 > x1) {
1739         if (! _cairo_fixed_is_integer (b->p1.x)) {
1740             blt(closure, x1, y, 1, h,
1741                 coverage * (256 - _cairo_fixed_fractional_part (b->p1.x)));
1742             x1++;
1743         }
1744
1745         if (x2 > x1)
1746             blt(closure, x1, y, x2-x1, h, (coverage << 8) - (coverage >> 8));
1747
1748         if (! _cairo_fixed_is_integer (b->p2.x))
1749             blt(closure, x2, y, 1, h,
1750                 coverage * _cairo_fixed_fractional_part (b->p2.x));
1751     } else
1752         blt(closure, x1, y, 1, h,
1753             coverage * (b->p2.x - b->p1.x));
1754 }
1755
1756 static void do_unaligned_box(void (*blt)(void *closure,
1757                                          int16_t x, int16_t y,
1758                                          int16_t w, int16_t h,
1759                                          uint16_t coverage),
1760                              void *closure,
1761                              const cairo_box_t *b, int tx, int ty)
1762 {
1763     int y1 = _cairo_fixed_integer_part (b->p1.y) - ty;
1764     int y2 = _cairo_fixed_integer_part (b->p2.y) - ty;
1765     if (y2 > y1) {
1766         if (! _cairo_fixed_is_integer (b->p1.y)) {
1767             do_unaligned_row(blt, closure, b, tx, y1, 1,
1768                              256 - _cairo_fixed_fractional_part (b->p1.y));
1769             y1++;
1770         }
1771
1772         if (y2 > y1)
1773             do_unaligned_row(blt, closure, b, tx, y1, y2-y1, 256);
1774
1775         if (! _cairo_fixed_is_integer (b->p2.y))
1776             do_unaligned_row(blt, closure, b, tx, y2, 1,
1777                              _cairo_fixed_fractional_part (b->p2.y));
1778     } else
1779         do_unaligned_row(blt, closure, b, tx, y1, 1,
1780                          b->p2.y - b->p1.y);
1781 }
1782
1783
1784 static void blt_in(void *closure,
1785                    int16_t x, int16_t y,
1786                    int16_t w, int16_t h,
1787                    uint16_t coverage)
1788 {
1789     cairo_xcb_surface_t *mask = closure;
1790     xcb_render_color_t color;
1791     xcb_rectangle_t rect;
1792
1793     if (coverage == 0xffff)
1794         return;
1795
1796     color.red = color.green = color.blue = 0;
1797     color.alpha = coverage;
1798
1799     rect.x = x;
1800     rect.y = y;
1801     rect.width  = w;
1802     rect.height = h;
1803
1804     _cairo_xcb_connection_render_fill_rectangles (mask->connection,
1805                                                   XCB_RENDER_PICT_OP_IN,
1806                                                   mask->picture,
1807                                                   color, 1, &rect);
1808 }
1809
1810 static cairo_xcb_surface_t *
1811 _create_composite_mask (cairo_clip_t            *clip,
1812                         xcb_draw_func_t          draw_func,
1813                         xcb_draw_func_t          mask_func,
1814                         void                    *draw_closure,
1815                         cairo_xcb_surface_t     *dst,
1816                         const cairo_rectangle_int_t*extents)
1817 {
1818     cairo_xcb_surface_t *surface;
1819     cairo_bool_t need_clip_combine;
1820     cairo_int_status_t status;
1821
1822     surface = (cairo_xcb_surface_t *)
1823         _cairo_xcb_surface_create_similar (dst, CAIRO_CONTENT_ALPHA,
1824                                            extents->width, extents->height);
1825     if (unlikely (surface->base.status))
1826         return surface;
1827
1828     _cairo_xcb_surface_ensure_picture (surface);
1829
1830     surface->deferred_clear_color = *CAIRO_COLOR_TRANSPARENT;
1831     surface->deferred_clear = TRUE;
1832     surface->base.is_clear = TRUE;
1833
1834     if (mask_func) {
1835         status = mask_func (draw_closure, surface,
1836                             CAIRO_OPERATOR_ADD, NULL,
1837                             extents->x, extents->y,
1838                             extents, clip);
1839         if (likely (status != CAIRO_INT_STATUS_UNSUPPORTED))
1840             return surface;
1841     }
1842
1843     /* Is it worth setting the clip region here? */
1844     status = draw_func (draw_closure, surface,
1845                         CAIRO_OPERATOR_ADD, NULL,
1846                         extents->x, extents->y,
1847                         extents, NULL);
1848     if (unlikely (status)) {
1849         cairo_surface_destroy (&surface->base);
1850         return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
1851     }
1852
1853     if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
1854         int i;
1855
1856         for (i = 0; i < clip->num_boxes; i++) {
1857             cairo_box_t *b = &clip->boxes[i];
1858
1859             if (! _cairo_fixed_is_integer (b->p1.x) ||
1860                 ! _cairo_fixed_is_integer (b->p1.y) ||
1861                 ! _cairo_fixed_is_integer (b->p2.x) ||
1862                 ! _cairo_fixed_is_integer (b->p2.y))
1863             {
1864                 do_unaligned_box(blt_in, surface, b, extents->x, extents->y);
1865             }
1866         }
1867
1868         need_clip_combine = clip->path != NULL;
1869     } else
1870         need_clip_combine = ! _cairo_clip_is_region (clip);
1871
1872     if (need_clip_combine) {
1873         status = _cairo_clip_combine_with_surface (clip, &surface->base,
1874                                                    extents->x, extents->y);
1875         if (unlikely (status)) {
1876             cairo_surface_destroy (&surface->base);
1877             return (cairo_xcb_surface_t *) _cairo_surface_create_in_error (status);
1878         }
1879     }
1880
1881     return surface;
1882 }
1883
1884 /* Handles compositing with a clip surface when the operator allows
1885  * us to combine the clip with the mask
1886  */
1887 static cairo_status_t
1888 _clip_and_composite_with_mask (cairo_clip_t             *clip,
1889                                cairo_operator_t          op,
1890                                const cairo_pattern_t    *pattern,
1891                                xcb_draw_func_t           draw_func,
1892                                xcb_draw_func_t           mask_func,
1893                                void                     *draw_closure,
1894                                cairo_xcb_surface_t      *dst,
1895                                const cairo_rectangle_int_t*extents)
1896 {
1897     cairo_xcb_surface_t *mask;
1898     cairo_xcb_picture_t *src;
1899
1900     mask = _create_composite_mask (clip,
1901                                    draw_func, mask_func, draw_closure,
1902                                    dst, extents);
1903     if (unlikely (mask->base.status))
1904         return mask->base.status;
1905
1906     if (pattern != NULL || dst->base.content != CAIRO_CONTENT_ALPHA) {
1907         src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
1908         if (unlikely (src->base.status)) {
1909             cairo_surface_destroy (&mask->base);
1910             return src->base.status;
1911         }
1912
1913         _cairo_xcb_connection_render_composite (dst->connection,
1914                                                 _render_operator (op),
1915                                                 src->picture,
1916                                                 mask->picture,
1917                                                 dst->picture,
1918                                                 extents->x + src->x, extents->y + src->y,
1919                                                 0, 0,
1920                                                 extents->x,      extents->y,
1921                                                 extents->width,  extents->height);
1922
1923         cairo_surface_destroy (&src->base);
1924     } else {
1925         _cairo_xcb_connection_render_composite (dst->connection,
1926                                                 _render_operator (op),
1927                                                 mask->picture,
1928                                                 XCB_NONE,
1929                                                 dst->picture,
1930                                                 0, 0,
1931                                                 0, 0,
1932                                                 extents->x,      extents->y,
1933                                                 extents->width,  extents->height);
1934     }
1935     cairo_surface_destroy (&mask->base);
1936
1937     return CAIRO_STATUS_SUCCESS;
1938 }
1939
1940 /* Handles compositing with a clip surface when we have to do the operation
1941  * in two pieces and combine them together.
1942  */
1943 static cairo_status_t
1944 _clip_and_composite_combine (cairo_clip_t               *clip,
1945                              cairo_operator_t            op,
1946                              const cairo_pattern_t      *pattern,
1947                              xcb_draw_func_t             draw_func,
1948                              void                       *draw_closure,
1949                              cairo_xcb_surface_t        *dst,
1950                              const cairo_rectangle_int_t*extents)
1951 {
1952     cairo_xcb_surface_t *tmp;
1953     cairo_xcb_surface_t *clip_surface;
1954     int clip_x, clip_y;
1955     xcb_render_picture_t clip_picture;
1956     cairo_status_t status;
1957
1958     tmp = (cairo_xcb_surface_t *)
1959         _cairo_xcb_surface_create_similar (dst, dst->base.content,
1960                                            extents->width, extents->height);
1961     if (unlikely (tmp->base.status))
1962         return tmp->base.status;
1963
1964     /* create_similar() could have done a fallback to an image surface */
1965     assert (tmp->base.backend == &_cairo_xcb_surface_backend);
1966
1967     _cairo_xcb_surface_ensure_picture (tmp);
1968
1969     if (pattern == NULL) {
1970         status = (*draw_func) (draw_closure, tmp,
1971                                CAIRO_OPERATOR_ADD, NULL,
1972                                extents->x, extents->y,
1973                                extents, NULL);
1974     } else {
1975         /* Initialize the temporary surface from the destination surface */
1976         if (! dst->base.is_clear ||
1977             (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) == 0)
1978         {
1979             /* XCopyArea may actually be quicker here.
1980              * A good driver should translate if appropriate.
1981              */
1982             _cairo_xcb_connection_render_composite (dst->connection,
1983                                                     XCB_RENDER_PICT_OP_SRC,
1984                                                     dst->picture,
1985                                                     XCB_NONE,
1986                                                     tmp->picture,
1987                                                     extents->x,      extents->y,
1988                                                     0, 0,
1989                                                     0, 0,
1990                                                     extents->width,  extents->height);
1991         }
1992         else
1993         {
1994             xcb_render_color_t clear;
1995             xcb_rectangle_t xrect;
1996
1997             clear.red = clear.green = clear.blue = clear.alpha = 0;
1998
1999             xrect.x = xrect.y = 0;
2000             xrect.width  = extents->width;
2001             xrect.height = extents->height;
2002
2003             _cairo_xcb_connection_render_fill_rectangles (dst->connection,
2004                                                           XCB_RENDER_PICT_OP_CLEAR,
2005                                                           dst->picture,
2006                                                           clear, 1, &xrect);
2007         }
2008
2009         status = (*draw_func) (draw_closure, tmp, op, pattern,
2010                                extents->x, extents->y,
2011                                extents, NULL);
2012     }
2013     if (unlikely (status))
2014         goto CLEANUP_SURFACE;
2015
2016     clip_surface = get_clip_surface (clip, dst, &clip_x, &clip_y);
2017     status = clip_surface->base.status;
2018     if (unlikely (status))
2019         goto CLEANUP_SURFACE;
2020
2021     assert (clip_surface->base.backend == &_cairo_xcb_surface_backend);
2022     clip_picture = clip_surface->picture;
2023     assert (clip_picture != XCB_NONE);
2024
2025     if (dst->base.is_clear) {
2026         _cairo_xcb_connection_render_composite (dst->connection,
2027                                                 XCB_RENDER_PICT_OP_SRC,
2028                                                 tmp->picture, clip_picture, dst->picture,
2029                                                 0, 0,
2030                                                 0, 0,
2031                                                 extents->x,      extents->y,
2032                                                 extents->width,  extents->height);
2033     } else {
2034         /* Punch the clip out of the destination */
2035         _cairo_xcb_connection_render_composite (dst->connection,
2036                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
2037                                                 clip_picture, XCB_NONE, dst->picture,
2038                                                 extents->x - clip_x,
2039                                                 extents->y - clip_y,
2040                                                 0, 0,
2041                                                 extents->x,     extents->y,
2042                                                 extents->width, extents->height);
2043
2044         /* Now add the two results together */
2045         _cairo_xcb_connection_render_composite (dst->connection,
2046                                                 XCB_RENDER_PICT_OP_ADD,
2047                                                 tmp->picture, clip_picture, dst->picture,
2048                                                 0, 0,
2049                                                 extents->x - clip_x,
2050                                                 extents->y - clip_y,
2051                                                 extents->x,     extents->y,
2052                                                 extents->width, extents->height);
2053     }
2054     cairo_surface_destroy (&clip_surface->base);
2055
2056  CLEANUP_SURFACE:
2057     cairo_surface_destroy (&tmp->base);
2058
2059     return status;
2060 }
2061
2062 /* Handles compositing for %CAIRO_OPERATOR_SOURCE, which is special; it's
2063  * defined as (src IN mask IN clip) ADD (dst OUT (mask IN clip))
2064  */
2065 static cairo_status_t
2066 _clip_and_composite_source (cairo_clip_t                *clip,
2067                             const cairo_pattern_t       *pattern,
2068                             xcb_draw_func_t              draw_func,
2069                             xcb_draw_func_t              mask_func,
2070                             void                        *draw_closure,
2071                             cairo_xcb_surface_t         *dst,
2072                             const cairo_rectangle_int_t *extents)
2073 {
2074     cairo_xcb_surface_t *mask;
2075     cairo_xcb_picture_t *src;
2076
2077     /* Create a surface that is mask IN clip */
2078     mask = _create_composite_mask (clip,
2079                                    draw_func, mask_func, draw_closure,
2080                                    dst, extents);
2081     if (unlikely (mask->base.status))
2082         return mask->base.status;
2083
2084     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
2085     if (unlikely (src->base.status)) {
2086         cairo_surface_destroy (&mask->base);
2087         return src->base.status;
2088     }
2089
2090     if (dst->base.is_clear) {
2091         _cairo_xcb_connection_render_composite (dst->connection,
2092                                                 XCB_RENDER_PICT_OP_SRC,
2093                                                 src->picture,
2094                                                 mask->picture,
2095                                                 dst->picture,
2096                                                 extents->x + src->x, extents->y + src->y,
2097                                                 0, 0,
2098                                                 extents->x,      extents->y,
2099                                                 extents->width,  extents->height);
2100     } else {
2101         /* Compute dest' = dest OUT (mask IN clip) */
2102         _cairo_xcb_connection_render_composite (dst->connection,
2103                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
2104                                                 mask->picture,
2105                                                 XCB_NONE,
2106                                                 dst->picture,
2107                                                 0, 0, 0, 0,
2108                                                 extents->x,     extents->y,
2109                                                 extents->width, extents->height);
2110
2111         /* Now compute (src IN (mask IN clip)) ADD dest' */
2112         _cairo_xcb_connection_render_composite (dst->connection,
2113                                                 XCB_RENDER_PICT_OP_ADD,
2114                                                 src->picture,
2115                                                 mask->picture,
2116                                                 dst->picture,
2117                                                 extents->x + src->x, extents->y + src->y,
2118                                                 0, 0,
2119                                                 extents->x,     extents->y,
2120                                                 extents->width, extents->height);
2121     }
2122
2123     cairo_surface_destroy (&src->base);
2124     cairo_surface_destroy (&mask->base);
2125
2126     return CAIRO_STATUS_SUCCESS;
2127 }
2128
2129 static cairo_bool_t
2130 can_reduce_alpha_op (cairo_operator_t op)
2131 {
2132     int iop = op;
2133     switch (iop) {
2134     case CAIRO_OPERATOR_OVER:
2135     case CAIRO_OPERATOR_SOURCE:
2136     case CAIRO_OPERATOR_ADD:
2137         return TRUE;
2138     default:
2139         return FALSE;
2140     }
2141 }
2142
2143 static cairo_bool_t
2144 reduce_alpha_op (cairo_surface_t *dst,
2145                  cairo_operator_t op,
2146                  const cairo_pattern_t *pattern)
2147 {
2148     return dst->is_clear &&
2149            dst->content == CAIRO_CONTENT_ALPHA &&
2150            _cairo_pattern_is_opaque_solid (pattern) &&
2151            can_reduce_alpha_op (op);
2152 }
2153
2154 static cairo_status_t
2155 _cairo_xcb_surface_fixup_unbounded (cairo_xcb_surface_t *dst,
2156                                     const cairo_composite_rectangles_t *rects)
2157 {
2158     xcb_rectangle_t xrects[4];
2159     int n;
2160
2161     if (rects->bounded.width  == rects->unbounded.width &&
2162         rects->bounded.height == rects->unbounded.height)
2163     {
2164         return CAIRO_STATUS_SUCCESS;
2165     }
2166
2167     n = 0;
2168     if (rects->bounded.width == 0 || rects->bounded.height == 0) {
2169         xrects[n].x = rects->unbounded.x;
2170         xrects[n].width = rects->unbounded.width;
2171         xrects[n].y = rects->unbounded.y;
2172         xrects[n].height = rects->unbounded.height;
2173         n++;
2174     } else {
2175         /* top */
2176         if (rects->bounded.y != rects->unbounded.y) {
2177             xrects[n].x = rects->unbounded.x;
2178             xrects[n].width = rects->unbounded.width;
2179             xrects[n].y = rects->unbounded.y;
2180             xrects[n].height = rects->bounded.y - rects->unbounded.y;
2181             n++;
2182         }
2183         /* left */
2184         if (rects->bounded.x != rects->unbounded.x) {
2185             xrects[n].x = rects->unbounded.x;
2186             xrects[n].width = rects->bounded.x - rects->unbounded.x;
2187             xrects[n].y = rects->bounded.y;
2188             xrects[n].height = rects->bounded.height;
2189             n++;
2190         }
2191         /* right */
2192         if (rects->bounded.x + rects->bounded.width != rects->unbounded.x + rects->unbounded.width) {
2193             xrects[n].x = rects->bounded.x + rects->bounded.width;
2194             xrects[n].width = rects->unbounded.x + rects->unbounded.width - xrects[n].x;
2195             xrects[n].y = rects->bounded.y;
2196             xrects[n].height = rects->bounded.height;
2197             n++;
2198         }
2199         /* bottom */
2200         if (rects->bounded.y + rects->bounded.height != rects->unbounded.y + rects->unbounded.height) {
2201             xrects[n].x = rects->unbounded.x;
2202             xrects[n].width = rects->unbounded.width;
2203             xrects[n].y = rects->bounded.y + rects->bounded.height;
2204             xrects[n].height = rects->unbounded.y + rects->unbounded.height - xrects[n].y;
2205             n++;
2206         }
2207     }
2208
2209     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
2210         xcb_render_color_t color;
2211
2212         color.red   = 0;
2213         color.green = 0;
2214         color.blue  = 0;
2215         color.alpha = 0;
2216
2217         _cairo_xcb_connection_render_fill_rectangles (dst->connection,
2218                                                       XCB_RENDER_PICT_OP_CLEAR,
2219                                                       dst->picture,
2220                                                       color, n, xrects);
2221     } else {
2222         int i;
2223         cairo_xcb_picture_t *src;
2224
2225         src = _cairo_xcb_transparent_picture (dst);
2226         if (unlikely (src->base.status))
2227             return src->base.status;
2228
2229         for (i = 0; i < n; i++) {
2230             _cairo_xcb_connection_render_composite (dst->connection,
2231                                                     XCB_RENDER_PICT_OP_CLEAR,
2232                                                     src->picture, XCB_NONE, dst->picture,
2233                                                     0, 0,
2234                                                     0, 0,
2235                                                     xrects[i].x, xrects[i].y,
2236                                                     xrects[i].width, xrects[i].height);
2237         }
2238         cairo_surface_destroy (&src->base);
2239     }
2240
2241     return CAIRO_STATUS_SUCCESS;
2242 }
2243
2244 static cairo_status_t
2245 _cairo_xcb_surface_fixup_unbounded_with_mask (cairo_xcb_surface_t *dst,
2246                                               const cairo_composite_rectangles_t *rects,
2247                                               cairo_clip_t *clip)
2248 {
2249     cairo_xcb_surface_t *mask;
2250     int mask_x, mask_y;
2251
2252     mask = get_clip_surface (clip, dst, &mask_x, &mask_y);
2253     if (unlikely (mask->base.status))
2254         return mask->base.status;
2255
2256     /* top */
2257     if (rects->bounded.y != rects->unbounded.y) {
2258         int x = rects->unbounded.x;
2259         int y = rects->unbounded.y;
2260         int width = rects->unbounded.width;
2261         int height = rects->bounded.y - y;
2262
2263         _cairo_xcb_connection_render_composite (dst->connection,
2264                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
2265                                                 mask->picture, XCB_NONE, dst->picture,
2266                                                 x - mask_x, y - mask_y,
2267                                                 0, 0,
2268                                                 x, y,
2269                                                 width, height);
2270     }
2271
2272     /* left */
2273     if (rects->bounded.x != rects->unbounded.x) {
2274         int x = rects->unbounded.x;
2275         int y = rects->bounded.y;
2276         int width = rects->bounded.x - x;
2277         int height = rects->bounded.height;
2278
2279         _cairo_xcb_connection_render_composite (dst->connection,
2280                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
2281                                                 mask->picture, XCB_NONE, dst->picture,
2282                                                 x - mask_x, y - mask_y,
2283                                                 0, 0,
2284                                                 x, y,
2285                                                 width, height);
2286     }
2287
2288     /* right */
2289     if (rects->bounded.x + rects->bounded.width != rects->unbounded.x + rects->unbounded.width) {
2290         int x = rects->bounded.x + rects->bounded.width;
2291         int y = rects->bounded.y;
2292         int width = rects->unbounded.x + rects->unbounded.width - x;
2293         int height = rects->bounded.height;
2294
2295         _cairo_xcb_connection_render_composite (dst->connection,
2296                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
2297                                                 mask->picture, XCB_NONE, dst->picture,
2298                                                 x - mask_x, y - mask_y,
2299                                                 0, 0,
2300                                                 x, y,
2301                                                 width, height);
2302     }
2303
2304     /* bottom */
2305     if (rects->bounded.y + rects->bounded.height != rects->unbounded.y + rects->unbounded.height) {
2306         int x = rects->unbounded.x;
2307         int y = rects->bounded.y + rects->bounded.height;
2308         int width = rects->unbounded.width;
2309         int height = rects->unbounded.y + rects->unbounded.height - y;
2310
2311         _cairo_xcb_connection_render_composite (dst->connection,
2312                                                 XCB_RENDER_PICT_OP_OUT_REVERSE,
2313                                                 mask->picture, XCB_NONE, dst->picture,
2314                                                 x - mask_x, y - mask_y,
2315                                                 0, 0,
2316                                                 x, y,
2317                                                 width, height);
2318     }
2319
2320     cairo_surface_destroy (&mask->base);
2321
2322     return CAIRO_STATUS_SUCCESS;
2323 }
2324
2325 static cairo_status_t
2326 _cairo_xcb_surface_fixup_unbounded_boxes (cairo_xcb_surface_t *dst,
2327                                           const cairo_composite_rectangles_t *extents,
2328                                           cairo_clip_t *clip,
2329                                           cairo_boxes_t *boxes)
2330 {
2331     cairo_boxes_t clear;
2332     cairo_box_t box;
2333     cairo_status_t status;
2334     struct _cairo_boxes_chunk *chunk;
2335     int i;
2336
2337     if (boxes->num_boxes <= 1 && clip == NULL)
2338         return _cairo_xcb_surface_fixup_unbounded (dst, extents);
2339
2340     _cairo_boxes_init (&clear);
2341
2342     box.p1.x = _cairo_fixed_from_int (extents->unbounded.x + extents->unbounded.width);
2343     box.p1.y = _cairo_fixed_from_int (extents->unbounded.y);
2344     box.p2.x = _cairo_fixed_from_int (extents->unbounded.x);
2345     box.p2.y = _cairo_fixed_from_int (extents->unbounded.y + extents->unbounded.height);
2346
2347     if (clip == NULL) {
2348         cairo_boxes_t tmp;
2349
2350         _cairo_boxes_init (&tmp);
2351
2352         status = _cairo_boxes_add (&tmp, CAIRO_ANTIALIAS_DEFAULT, &box);
2353         assert (status == CAIRO_STATUS_SUCCESS);
2354
2355         tmp.chunks.next = &boxes->chunks;
2356         tmp.num_boxes += boxes->num_boxes;
2357
2358         status = _cairo_bentley_ottmann_tessellate_boxes (&tmp,
2359                                                           CAIRO_FILL_RULE_WINDING,
2360                                                           &clear);
2361
2362         tmp.chunks.next = NULL;
2363     } else {
2364         _cairo_boxes_init_with_clip (&clear, clip);
2365
2366         status = _cairo_boxes_add (&clear, CAIRO_ANTIALIAS_DEFAULT, &box);
2367         assert (status == CAIRO_STATUS_SUCCESS);
2368
2369         for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2370             for (i = 0; i < chunk->count; i++) {
2371                 status = _cairo_boxes_add (&clear,
2372                                            CAIRO_ANTIALIAS_DEFAULT,
2373                                            &chunk->base[i]);
2374                 if (unlikely (status)) {
2375                     _cairo_boxes_fini (&clear);
2376                     return status;
2377                 }
2378             }
2379         }
2380
2381         status = _cairo_bentley_ottmann_tessellate_boxes (&clear,
2382                                                           CAIRO_FILL_RULE_WINDING,
2383                                                           &clear);
2384     }
2385
2386     if (likely (status == CAIRO_STATUS_SUCCESS)) {
2387         if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES)
2388             status = _render_fill_boxes (dst,
2389                                          CAIRO_OPERATOR_CLEAR,
2390                                          CAIRO_COLOR_TRANSPARENT,
2391                                          &clear);
2392         else
2393             status = _cairo_xcb_surface_core_fill_boxes (dst,
2394                                                          CAIRO_COLOR_TRANSPARENT,
2395                                                          &clear);
2396     }
2397
2398     _cairo_boxes_fini (&clear);
2399
2400     return status;
2401 }
2402
2403 cairo_status_t
2404 _cairo_xcb_surface_clear (cairo_xcb_surface_t *dst)
2405 {
2406     xcb_gcontext_t gc;
2407     xcb_rectangle_t rect;
2408     cairo_status_t status;
2409
2410     status = _cairo_xcb_connection_acquire (dst->connection);
2411     if (unlikely (status))
2412         return status;
2413
2414     rect.x = rect.y = 0;
2415     rect.width  = dst->width;
2416     rect.height = dst->height;
2417
2418     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES) {
2419         xcb_render_color_t color;
2420         uint8_t op;
2421
2422         color.red   = dst->deferred_clear_color.red_short;
2423         color.green = dst->deferred_clear_color.green_short;
2424         color.blue  = dst->deferred_clear_color.blue_short;
2425         color.alpha = dst->deferred_clear_color.alpha_short;
2426
2427         if (color.alpha == 0)
2428             op = XCB_RENDER_PICT_OP_CLEAR;
2429         else
2430             op = XCB_RENDER_PICT_OP_SRC;
2431
2432         _cairo_xcb_surface_ensure_picture (dst);
2433         _cairo_xcb_connection_render_fill_rectangles (dst->connection,
2434                                                       op, dst->picture, color,
2435                                                       1, &rect);
2436     } else {
2437         gc = _cairo_xcb_screen_get_gc (dst->screen, dst->drawable, dst->depth);
2438
2439         /* XXX color */
2440         _cairo_xcb_connection_poly_fill_rectangle (dst->connection,
2441                                                    dst->drawable, gc,
2442                                                    1, &rect);
2443
2444         _cairo_xcb_screen_put_gc (dst->screen, dst->depth, gc);
2445     }
2446
2447     _cairo_xcb_connection_release (dst->connection);
2448
2449     dst->deferred_clear = FALSE;
2450     return CAIRO_STATUS_SUCCESS;
2451 }
2452
2453 enum {
2454     NEED_CLIP_REGION = 0x1,
2455     NEED_CLIP_SURFACE = 0x2,
2456     FORCE_CLIP_REGION = 0x4,
2457 };
2458
2459 static cairo_bool_t
2460 need_bounded_clip (cairo_composite_rectangles_t *extents)
2461 {
2462     unsigned int flags = NEED_CLIP_REGION;
2463     if (! _cairo_clip_is_region (extents->clip))
2464         flags |= NEED_CLIP_SURFACE;
2465     return flags;
2466 }
2467
2468 static cairo_bool_t
2469 need_unbounded_clip (cairo_composite_rectangles_t *extents)
2470 {
2471     unsigned int flags = 0;
2472     if (! extents->is_bounded) {
2473         flags |= NEED_CLIP_REGION;
2474         if (! _cairo_clip_is_region (extents->clip))
2475             flags |= NEED_CLIP_SURFACE;
2476     }
2477     if (extents->clip->path != NULL)
2478         flags |= NEED_CLIP_SURFACE;
2479     return flags;
2480 }
2481
2482 static cairo_status_t
2483 _clip_and_composite (cairo_xcb_surface_t        *dst,
2484                      cairo_operator_t            op,
2485                      const cairo_pattern_t      *src,
2486                      xcb_draw_func_t             draw_func,
2487                      xcb_draw_func_t             mask_func,
2488                      void                       *draw_closure,
2489                      cairo_composite_rectangles_t*extents,
2490                      unsigned int need_clip)
2491 {
2492     cairo_region_t *clip_region = NULL;
2493     cairo_status_t status;
2494
2495     status = _cairo_xcb_connection_acquire (dst->connection);
2496     if (unlikely (status))
2497         return status;
2498
2499     if (dst->deferred_clear) {
2500         status = _cairo_xcb_surface_clear (dst);
2501         if (unlikely (status)) {
2502             _cairo_xcb_connection_release (dst->connection);
2503             return status;
2504         }
2505     }
2506
2507     _cairo_xcb_surface_ensure_picture (dst);
2508
2509     if (need_clip & NEED_CLIP_REGION) {
2510         clip_region = _cairo_clip_get_region (extents->clip);
2511         if ((need_clip & FORCE_CLIP_REGION) == 0 && clip_region != NULL &&
2512             cairo_region_contains_rectangle (clip_region,
2513                                              &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
2514             clip_region = NULL;
2515         if (clip_region != NULL) {
2516             status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
2517             if (unlikely (status)) {
2518                 _cairo_xcb_connection_release (dst->connection);
2519                 return status;
2520             }
2521         }
2522     }
2523
2524     if (reduce_alpha_op (&dst->base, op, src)) {
2525         op = CAIRO_OPERATOR_ADD;
2526         src = NULL;
2527     }
2528
2529     if (extents->bounded.width != 0 && extents->bounded.height != 0) {
2530         if (op == CAIRO_OPERATOR_SOURCE) {
2531             status = _clip_and_composite_source (extents->clip, src,
2532                                                  draw_func, mask_func, draw_closure,
2533                                                  dst, &extents->bounded);
2534         } else {
2535             if (op == CAIRO_OPERATOR_CLEAR) {
2536                 op = CAIRO_OPERATOR_DEST_OUT;
2537                 src = NULL;
2538             }
2539
2540             if (need_clip & NEED_CLIP_SURFACE) {
2541                 if (extents->is_bounded) {
2542                     status = _clip_and_composite_with_mask (extents->clip, op, src,
2543                                                             draw_func,
2544                                                             mask_func,
2545                                                             draw_closure,
2546                                                             dst, &extents->bounded);
2547                 } else {
2548                     status = _clip_and_composite_combine (extents->clip, op, src,
2549                                                           draw_func, draw_closure,
2550                                                           dst, &extents->bounded);
2551                 }
2552             } else {
2553                 status = draw_func (draw_closure,
2554                                     dst, op, src,
2555                                     0, 0,
2556                                     &extents->bounded,
2557                                     extents->clip);
2558             }
2559         }
2560     }
2561
2562     if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
2563         if (need_clip & NEED_CLIP_SURFACE)
2564             status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst, extents, extents->clip);
2565         else
2566             status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
2567     }
2568
2569     if (clip_region)
2570         _cairo_xcb_surface_clear_clip_region (dst);
2571
2572     _cairo_xcb_connection_release (dst->connection);
2573
2574     return status;
2575 }
2576
2577 static cairo_status_t
2578 _core_boxes (cairo_xcb_surface_t *dst,
2579              cairo_operator_t op,
2580              const cairo_pattern_t *src,
2581              cairo_boxes_t *boxes,
2582              const cairo_composite_rectangles_t *extents)
2583 {
2584     if (! boxes->is_pixel_aligned)
2585         return CAIRO_INT_STATUS_UNSUPPORTED;
2586
2587     if (! _cairo_clip_is_region (extents->clip))
2588         return CAIRO_INT_STATUS_UNSUPPORTED;
2589
2590     if (op == CAIRO_OPERATOR_CLEAR)
2591         return _cairo_xcb_surface_core_fill_boxes (dst, CAIRO_COLOR_TRANSPARENT, boxes);
2592
2593     if (op == CAIRO_OPERATOR_OVER) {
2594         if (dst->base.is_clear || _cairo_pattern_is_opaque (src, &extents->bounded))
2595             op = CAIRO_OPERATOR_SOURCE;
2596     }
2597     if (op != CAIRO_OPERATOR_SOURCE)
2598         return CAIRO_INT_STATUS_UNSUPPORTED;
2599
2600     if (src->type == CAIRO_PATTERN_TYPE_SOLID) {
2601         return _cairo_xcb_surface_core_fill_boxes (dst,
2602                                                    &((cairo_solid_pattern_t *) src)->color,
2603                                                    boxes);
2604     }
2605
2606     return _cairo_xcb_surface_core_copy_boxes (dst, src, &extents->bounded, boxes);
2607 }
2608
2609 static cairo_status_t
2610 _composite_boxes (cairo_xcb_surface_t *dst,
2611                   cairo_operator_t op,
2612                   const cairo_pattern_t *src,
2613                   cairo_boxes_t *boxes,
2614                   const cairo_composite_rectangles_t *extents)
2615 {
2616     cairo_clip_t *clip = extents->clip;
2617     cairo_bool_t need_clip_mask = ! _cairo_clip_is_region (clip);
2618     cairo_status_t status;
2619
2620     /* If the boxes are not pixel-aligned, we will need to compute a real mask */
2621     if (! boxes->is_pixel_aligned)
2622         return CAIRO_INT_STATUS_UNSUPPORTED;
2623
2624     if (need_clip_mask &&
2625         (! extents->is_bounded || op == CAIRO_OPERATOR_SOURCE))
2626     {
2627         return CAIRO_INT_STATUS_UNSUPPORTED;
2628     }
2629
2630     status = _cairo_xcb_connection_acquire (dst->connection);
2631     if (unlikely (status))
2632         return status;
2633
2634     _cairo_xcb_surface_ensure_picture (dst);
2635     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_FILL_RECTANGLES && ! need_clip_mask &&
2636         (op == CAIRO_OPERATOR_CLEAR || src->type == CAIRO_PATTERN_TYPE_SOLID))
2637     {
2638         const cairo_color_t *color;
2639
2640         if (op == CAIRO_OPERATOR_CLEAR)
2641             color = CAIRO_COLOR_TRANSPARENT;
2642         else
2643             color = &((cairo_solid_pattern_t *) src)->color;
2644
2645         status = _render_fill_boxes (dst, op, color, boxes);
2646     }
2647     else
2648     {
2649         cairo_surface_pattern_t mask;
2650
2651         if (need_clip_mask) {
2652             cairo_xcb_surface_t *clip_surface;
2653             int clip_x, clip_y;
2654
2655             clip_surface = get_clip_surface (extents->clip, dst,
2656                                              &clip_x, &clip_y);
2657             if (unlikely (clip_surface->base.status))
2658                 return clip_surface->base.status;
2659
2660             _cairo_pattern_init_for_surface (&mask, &clip_surface->base);
2661             mask.base.filter = CAIRO_FILTER_NEAREST;
2662             cairo_matrix_init_translate (&mask.base.matrix,
2663                                          -clip_x,
2664                                          -clip_y);
2665             cairo_surface_destroy (&clip_surface->base);
2666
2667             if (op == CAIRO_OPERATOR_CLEAR) {
2668                 src = NULL;
2669                 op = CAIRO_OPERATOR_DEST_OUT;
2670             }
2671         }
2672
2673         status = _render_composite_boxes (dst, op, src,
2674                                           need_clip_mask ? &mask.base : NULL,
2675                                           &extents->bounded, boxes);
2676
2677         if (need_clip_mask)
2678             _cairo_pattern_fini (&mask.base);
2679     }
2680
2681     if (status == CAIRO_STATUS_SUCCESS && ! extents->is_bounded) {
2682         status =
2683             _cairo_xcb_surface_fixup_unbounded_boxes (dst, extents,
2684                                                       clip, boxes);
2685     }
2686
2687     _cairo_xcb_connection_release (dst->connection);
2688
2689     return status;
2690 }
2691
2692 static cairo_bool_t
2693 cairo_boxes_for_each_box (cairo_boxes_t *boxes,
2694                           cairo_bool_t (*func) (cairo_box_t *box,
2695                                                 void *data),
2696                           void *data)
2697 {
2698     struct _cairo_boxes_chunk *chunk;
2699     int i;
2700
2701     for (chunk = &boxes->chunks; chunk != NULL; chunk = chunk->next) {
2702         for (i = 0; i < chunk->count; i++)
2703             if (! func (&chunk->base[i], data))
2704                 return FALSE;
2705     }
2706
2707     return TRUE;
2708 }
2709
2710 struct _image_contains_box {
2711     int width, height;
2712     int tx, ty;
2713 };
2714
2715 static cairo_bool_t image_contains_box (cairo_box_t *box, void *closure)
2716 {
2717     struct _image_contains_box *data = closure;
2718
2719     /* The box is pixel-aligned so the truncation is safe. */
2720     return
2721         _cairo_fixed_integer_part (box->p1.x) + data->tx >= 0 &&
2722         _cairo_fixed_integer_part (box->p1.y) + data->ty >= 0 &&
2723         _cairo_fixed_integer_part (box->p2.x) + data->tx <= data->width &&
2724         _cairo_fixed_integer_part (box->p2.y) + data->ty <= data->height;
2725 }
2726
2727 struct _image_upload_box {
2728     cairo_xcb_surface_t *surface;
2729     cairo_image_surface_t *image;
2730     xcb_gcontext_t gc;
2731     int tx, ty;
2732 };
2733
2734 static cairo_bool_t image_upload_box (cairo_box_t *box, void *closure)
2735 {
2736     const struct _image_upload_box *iub = closure;
2737     /* The box is pixel-aligned so the truncation is safe. */
2738     int x = _cairo_fixed_integer_part (box->p1.x);
2739     int y = _cairo_fixed_integer_part (box->p1.y);
2740     int width  = _cairo_fixed_integer_part (box->p2.x - box->p1.x);
2741     int height = _cairo_fixed_integer_part (box->p2.y - box->p1.y);
2742     int bpp = PIXMAN_FORMAT_BPP (iub->image->pixman_format);
2743     int len = CAIRO_STRIDE_FOR_WIDTH_BPP (width, bpp);
2744     if (len == iub->image->stride) {
2745         _cairo_xcb_connection_put_image (iub->surface->connection,
2746                                          iub->surface->drawable,
2747                                          iub->gc,
2748                                          width, height,
2749                                          x, y,
2750                                          iub->image->depth,
2751                                          iub->image->stride,
2752                                          iub->image->data +
2753                                          (y + iub->ty) * iub->image->stride +
2754                                          (x + iub->tx) * bpp/8);
2755     } else {
2756         _cairo_xcb_connection_put_subimage (iub->surface->connection,
2757                                             iub->surface->drawable,
2758                                             iub->gc,
2759                                             x + iub->tx,
2760                                             y + iub->ty,
2761                                             width, height,
2762                                             bpp / 8,
2763                                             iub->image->stride,
2764                                             x, y,
2765                                             iub->image->depth,
2766                                             iub->image->data);
2767     }
2768
2769     return TRUE;
2770 }
2771
2772 static cairo_status_t
2773 _upload_image_inplace (cairo_xcb_surface_t *surface,
2774                        const cairo_pattern_t *source,
2775                        cairo_boxes_t *boxes)
2776 {
2777     const cairo_surface_pattern_t *pattern;
2778     struct _image_contains_box icb;
2779     struct _image_upload_box iub;
2780     cairo_image_surface_t *image;
2781     cairo_status_t status;
2782     int tx, ty;
2783
2784     if (! boxes->is_pixel_aligned)
2785         return CAIRO_INT_STATUS_UNSUPPORTED;
2786
2787     if (source->type != CAIRO_PATTERN_TYPE_SURFACE)
2788         return CAIRO_INT_STATUS_UNSUPPORTED;
2789
2790     pattern = (const cairo_surface_pattern_t *) source;
2791     if (pattern->surface->type != CAIRO_SURFACE_TYPE_IMAGE)
2792         return CAIRO_INT_STATUS_UNSUPPORTED;
2793
2794     /* Have we already upload this image to a pixmap? */
2795     {
2796         cairo_xcb_picture_t *snapshot;
2797
2798         snapshot = (cairo_xcb_picture_t *)
2799             _cairo_surface_has_snapshot (pattern->surface, &_cairo_xcb_picture_backend);
2800         if (snapshot != NULL) {
2801             if (snapshot->screen == surface->screen)
2802                 return CAIRO_INT_STATUS_UNSUPPORTED;
2803         }
2804     }
2805
2806     image = (cairo_image_surface_t *) pattern->surface;
2807     if (image->format == CAIRO_FORMAT_INVALID)
2808         return CAIRO_INT_STATUS_UNSUPPORTED;
2809
2810     if (image->depth != surface->depth)
2811         return CAIRO_INT_STATUS_UNSUPPORTED;
2812
2813     if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
2814         return CAIRO_INT_STATUS_UNSUPPORTED;
2815
2816     /* Check that the data is entirely within the image */
2817     icb.width = image->width;
2818     icb.height = image->height;
2819     icb.tx = tx;
2820     icb.ty = ty;
2821     if (! cairo_boxes_for_each_box (boxes, image_contains_box, &icb))
2822         return CAIRO_INT_STATUS_UNSUPPORTED;
2823
2824     if (surface->deferred_clear) {
2825         status = _cairo_xcb_surface_clear (surface);
2826         if (unlikely (status))
2827             return status;
2828     }
2829
2830     status = _cairo_xcb_connection_acquire (surface->connection);
2831     if (unlikely (status))
2832         return status;
2833
2834     iub.surface = surface;
2835     iub.image = image;
2836     iub.gc = _cairo_xcb_screen_get_gc (surface->screen,
2837                                        surface->drawable,
2838                                        image->depth);
2839     iub.tx = tx;
2840     iub.ty = ty;
2841     cairo_boxes_for_each_box (boxes, image_upload_box, &iub);
2842
2843     _cairo_xcb_screen_put_gc (surface->screen, image->depth, iub.gc);
2844     _cairo_xcb_connection_release (surface->connection);
2845
2846     return CAIRO_STATUS_SUCCESS;
2847 }
2848
2849 static cairo_int_status_t
2850 trim_extents_to_traps (cairo_composite_rectangles_t *extents,
2851                        cairo_traps_t *traps)
2852 {
2853     cairo_box_t box;
2854
2855     /* X trims the affected area to the extents of the trapezoids, so
2856      * we need to compensate when fixing up the unbounded area.
2857     */
2858     _cairo_traps_extents (traps, &box);
2859     return _cairo_composite_rectangles_intersect_mask_extents (extents, &box);
2860 }
2861
2862 static cairo_bool_t
2863 _mono_edge_is_vertical (const cairo_line_t *line)
2864 {
2865     return _cairo_fixed_integer_round_down (line->p1.x) == _cairo_fixed_integer_round_down (line->p2.x);
2866 }
2867
2868 static cairo_bool_t
2869 _traps_are_pixel_aligned (cairo_traps_t *traps,
2870                           cairo_antialias_t antialias)
2871 {
2872     int i;
2873
2874     if (antialias == CAIRO_ANTIALIAS_NONE) {
2875         for (i = 0; i < traps->num_traps; i++) {
2876             if (! _mono_edge_is_vertical (&traps->traps[i].left)   ||
2877                 ! _mono_edge_is_vertical (&traps->traps[i].right))
2878             {
2879                 traps->maybe_region = FALSE;
2880                 return FALSE;
2881             }
2882         }
2883     } else {
2884         for (i = 0; i < traps->num_traps; i++) {
2885             if (traps->traps[i].left.p1.x != traps->traps[i].left.p2.x   ||
2886                 traps->traps[i].right.p1.x != traps->traps[i].right.p2.x ||
2887                 ! _cairo_fixed_is_integer (traps->traps[i].top)          ||
2888                 ! _cairo_fixed_is_integer (traps->traps[i].bottom)       ||
2889                 ! _cairo_fixed_is_integer (traps->traps[i].left.p1.x)    ||
2890                 ! _cairo_fixed_is_integer (traps->traps[i].right.p1.x))
2891             {
2892                 traps->maybe_region = FALSE;
2893                 return FALSE;
2894             }
2895         }
2896     }
2897
2898     return TRUE;
2899 }
2900
2901 static void
2902 _boxes_for_traps (cairo_boxes_t *boxes,
2903                   cairo_traps_t *traps,
2904                   cairo_antialias_t antialias)
2905 {
2906     int i;
2907
2908     _cairo_boxes_init (boxes);
2909
2910     boxes->num_boxes    = traps->num_traps;
2911     boxes->chunks.base  = (cairo_box_t *) traps->traps;
2912     boxes->chunks.count = traps->num_traps;
2913     boxes->chunks.size  = traps->num_traps;
2914
2915     if (antialias != CAIRO_ANTIALIAS_NONE) {
2916         for (i = 0; i < traps->num_traps; i++) {
2917             /* Note the traps and boxes alias so we need to take the local copies first. */
2918             cairo_fixed_t x1 = traps->traps[i].left.p1.x;
2919             cairo_fixed_t x2 = traps->traps[i].right.p1.x;
2920             cairo_fixed_t y1 = traps->traps[i].top;
2921             cairo_fixed_t y2 = traps->traps[i].bottom;
2922
2923             boxes->chunks.base[i].p1.x = x1;
2924             boxes->chunks.base[i].p1.y = y1;
2925             boxes->chunks.base[i].p2.x = x2;
2926             boxes->chunks.base[i].p2.y = y2;
2927
2928             if (boxes->is_pixel_aligned) {
2929                 boxes->is_pixel_aligned =
2930                     _cairo_fixed_is_integer (x1) && _cairo_fixed_is_integer (y1) &&
2931                     _cairo_fixed_is_integer (x2) && _cairo_fixed_is_integer (y2);
2932             }
2933         }
2934     } else {
2935         boxes->is_pixel_aligned = TRUE;
2936
2937         for (i = 0; i < traps->num_traps; i++) {
2938             /* Note the traps and boxes alias so we need to take the local copies first. */
2939             cairo_fixed_t x1 = traps->traps[i].left.p1.x;
2940             cairo_fixed_t x2 = traps->traps[i].right.p1.x;
2941             cairo_fixed_t y1 = traps->traps[i].top;
2942             cairo_fixed_t y2 = traps->traps[i].bottom;
2943
2944             /* round down here to match Pixman's behavior when using traps. */
2945             boxes->chunks.base[i].p1.x = _cairo_fixed_round_down (x1);
2946             boxes->chunks.base[i].p1.y = _cairo_fixed_round_down (y1);
2947             boxes->chunks.base[i].p2.x = _cairo_fixed_round_down (x2);
2948             boxes->chunks.base[i].p2.y = _cairo_fixed_round_down (y2);
2949         }
2950     }
2951 }
2952
2953 static cairo_status_t
2954 _composite_polygon (cairo_xcb_surface_t *dst,
2955                     cairo_operator_t op,
2956                     const cairo_pattern_t *source,
2957                     cairo_polygon_t *polygon,
2958                     cairo_antialias_t antialias,
2959                     cairo_fill_rule_t fill_rule,
2960                     cairo_composite_rectangles_t *extents)
2961 {
2962     composite_traps_info_t traps;
2963     cairo_bool_t clip_surface = ! _cairo_clip_is_region (extents->clip);
2964     cairo_region_t *clip_region = _cairo_clip_get_region (extents->clip);
2965     cairo_status_t status;
2966
2967     if (polygon->num_edges == 0) {
2968         status = CAIRO_STATUS_SUCCESS;
2969
2970         if (! extents->is_bounded) {
2971             if (cairo_region_contains_rectangle (clip_region, &extents->unbounded) == CAIRO_REGION_OVERLAP_IN)
2972                 clip_region = NULL;
2973
2974             if (clip_surface == FALSE) {
2975                 if (clip_region != NULL) {
2976                     status = _cairo_xcb_surface_set_clip_region (dst, clip_region);
2977                     if (unlikely (status))
2978                         return status;
2979                 }
2980
2981                 status = _cairo_xcb_surface_fixup_unbounded (dst, extents);
2982
2983                 if (clip_region != NULL)
2984                     _cairo_xcb_surface_clear_clip_region (dst);
2985             } else {
2986                 status = _cairo_xcb_surface_fixup_unbounded_with_mask (dst,
2987                                                                        extents,
2988                                                                        extents->clip);
2989             }
2990         }
2991
2992         return status;
2993     }
2994
2995     if (extents->clip->path != NULL && extents->is_bounded) {
2996         cairo_polygon_t clipper;
2997         cairo_fill_rule_t clipper_fill_rule;
2998         cairo_antialias_t clipper_antialias;
2999
3000         status = _cairo_clip_get_polygon (extents->clip,
3001                                           &clipper,
3002                                           &clipper_fill_rule,
3003                                           &clipper_antialias);
3004         if (likely (status == CAIRO_STATUS_SUCCESS)) {
3005             if (clipper_antialias == antialias) {
3006                 status = _cairo_polygon_intersect (polygon, fill_rule,
3007                                                    &clipper, clipper_fill_rule);
3008                 if (likely (status == CAIRO_STATUS_SUCCESS)) {
3009                     cairo_clip_t * clip = _cairo_clip_copy_region (extents->clip);
3010                     _cairo_clip_destroy (extents->clip);
3011                     extents->clip = clip;
3012
3013                     fill_rule = CAIRO_FILL_RULE_WINDING;
3014                 }
3015                 _cairo_polygon_fini (&clipper);
3016             }
3017         }
3018     }
3019
3020     _cairo_traps_init (&traps.traps);
3021
3022     status = _cairo_bentley_ottmann_tessellate_polygon (&traps.traps, polygon, fill_rule);
3023     if (unlikely (status))
3024         goto CLEANUP_TRAPS;
3025
3026     if (traps.traps.has_intersections) {
3027         if (traps.traps.is_rectangular)
3028             status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
3029         else if (traps.traps.is_rectilinear)
3030             status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
3031         else
3032             status = _cairo_bentley_ottmann_tessellate_traps (&traps.traps, CAIRO_FILL_RULE_WINDING);
3033         if (unlikely (status))
3034             goto CLEANUP_TRAPS;
3035     }
3036
3037     /* Use a fast path if the trapezoids consist of a simple region,
3038      * but we can only do this if we do not have a clip surface, or can
3039      * substitute the mask with the clip.
3040      */
3041     if (traps.traps.maybe_region &&
3042         _traps_are_pixel_aligned (&traps.traps, antialias) &&
3043         (! clip_surface ||
3044          (extents->is_bounded && op != CAIRO_OPERATOR_SOURCE)))
3045     {
3046         cairo_boxes_t boxes;
3047
3048         _boxes_for_traps (&boxes, &traps.traps, antialias);
3049         status = _clip_and_composite_boxes (dst, op, source, &boxes, extents);
3050     }
3051     else
3052     {
3053         /* Otherwise render the trapezoids to a mask and composite in the usual
3054          * fashion.
3055          */
3056         traps.antialias = antialias;
3057         status = trim_extents_to_traps (extents, &traps.traps);
3058         if (likely (status == CAIRO_STATUS_SUCCESS)) {
3059             unsigned int flags = 0;
3060
3061             /* For unbounded operations, the X11 server will estimate the
3062              * affected rectangle and apply the operation to that. However,
3063              * there are cases where this is an overestimate (e.g. the
3064              * clip-fill-{eo,nz}-unbounded test).
3065              *
3066              * The clip will trim that overestimate to our expectations.
3067              */
3068             if (! extents->is_bounded)
3069                 flags |= FORCE_CLIP_REGION;
3070
3071             status = _clip_and_composite (dst, op, source, _composite_traps,
3072                                           NULL, &traps, extents,
3073                                           need_unbounded_clip (extents) | flags);
3074         }
3075     }
3076
3077 CLEANUP_TRAPS:
3078     _cairo_traps_fini (&traps.traps);
3079
3080     return status;
3081 }
3082
3083 static cairo_status_t
3084 _clip_and_composite_boxes (cairo_xcb_surface_t *dst,
3085                            cairo_operator_t op,
3086                            const cairo_pattern_t *src,
3087                            cairo_boxes_t *boxes,
3088                            cairo_composite_rectangles_t *extents)
3089 {
3090     composite_traps_info_t info;
3091     cairo_int_status_t status;
3092
3093     if (boxes->num_boxes == 0 && extents->is_bounded)
3094         return CAIRO_STATUS_SUCCESS;
3095
3096     if (boxes->is_pixel_aligned && _cairo_clip_is_region (extents->clip) &&
3097         (op == CAIRO_OPERATOR_SOURCE ||
3098          (dst->base.is_clear && (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD))))
3099     {
3100         if (boxes->num_boxes == 1 &&
3101             extents->bounded.width  == dst->width &&
3102             extents->bounded.height == dst->height)
3103         {
3104             op = CAIRO_OPERATOR_SOURCE;
3105             dst->deferred_clear = FALSE;
3106         }
3107
3108         status = _upload_image_inplace (dst, src, boxes);
3109         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3110             return status;
3111     }
3112
3113     /* Can we reduce drawing through a clip-mask to simply drawing the clip? */
3114     if (dst->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS &&
3115             extents->clip->path != NULL && extents->is_bounded) {
3116         cairo_polygon_t polygon;
3117         cairo_fill_rule_t fill_rule;
3118         cairo_antialias_t antialias;
3119         cairo_clip_t *clip;
3120
3121         clip = _cairo_clip_copy (extents->clip);
3122         clip = _cairo_clip_intersect_boxes (clip, boxes);
3123         status = _cairo_clip_get_polygon (clip, &polygon,
3124                                           &fill_rule, &antialias);
3125         _cairo_clip_path_destroy (clip->path);
3126         clip->path = NULL;
3127         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
3128             cairo_clip_t *saved_clip = extents->clip;
3129             extents->clip = clip;
3130             status = _composite_polygon (dst, op, src,
3131                                          &polygon,
3132                                          antialias,
3133                                          fill_rule,
3134                                          extents);
3135             if (extents->clip != clip)
3136                 clip = NULL;
3137             extents->clip = saved_clip;
3138             _cairo_polygon_fini (&polygon);
3139         }
3140         if (clip)
3141             _cairo_clip_destroy (clip);
3142
3143         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3144             return status;
3145     }
3146
3147     if (dst->deferred_clear) {
3148         status = _cairo_xcb_surface_clear (dst);
3149         if (unlikely (status))
3150             return status;
3151     }
3152
3153     if (boxes->is_pixel_aligned &&
3154         _cairo_clip_is_region (extents->clip) &&
3155         op == CAIRO_OPERATOR_SOURCE) {
3156         status = _upload_image_inplace (dst, src, boxes);
3157         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3158             return status;
3159     }
3160
3161     if ((dst->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
3162         return _core_boxes (dst, op, src, boxes, extents);
3163
3164     /* Use a fast path if the boxes are pixel aligned */
3165     status = _composite_boxes (dst, op, src, boxes, extents);
3166     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3167         return status;
3168
3169     if ((dst->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) == 0)
3170         return CAIRO_INT_STATUS_UNSUPPORTED;
3171
3172     /* Otherwise render via a mask and composite in the usual fashion.  */
3173     status = _cairo_traps_init_boxes (&info.traps, boxes);
3174     if (unlikely (status))
3175         return status;
3176
3177     info.antialias = CAIRO_ANTIALIAS_DEFAULT;
3178     status = trim_extents_to_traps (extents, &info.traps);
3179     if (status == CAIRO_INT_STATUS_SUCCESS) {
3180         status = _clip_and_composite (dst, op, src,
3181                                       _composite_traps, NULL, &info,
3182                                       extents, need_unbounded_clip (extents));
3183     }
3184
3185     _cairo_traps_fini (&info.traps);
3186     return status;
3187 }
3188
3189 static cairo_int_status_t
3190 _composite_mask (void                           *closure,
3191                  cairo_xcb_surface_t            *dst,
3192                  cairo_operator_t                op,
3193                  const cairo_pattern_t          *src_pattern,
3194                  int                             dst_x,
3195                  int                             dst_y,
3196                  const cairo_rectangle_int_t    *extents,
3197                  cairo_clip_t                   *clip)
3198 {
3199     const cairo_pattern_t *mask_pattern = closure;
3200     cairo_xcb_picture_t *src, *mask = NULL;
3201     cairo_status_t status;
3202
3203     if (dst->base.is_clear) {
3204         if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)
3205             op = CAIRO_OPERATOR_SOURCE;
3206     }
3207
3208     if (op == CAIRO_OPERATOR_SOURCE && clip == NULL)
3209         dst->deferred_clear = FALSE;
3210
3211     if (dst->deferred_clear) {
3212         status = _cairo_xcb_surface_clear (dst);
3213         if (unlikely (status))
3214                 return status;
3215     }
3216
3217     if (src_pattern != NULL) {
3218         src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
3219         if (unlikely (src->base.status))
3220             return src->base.status;
3221
3222         mask = _cairo_xcb_picture_for_pattern (dst, mask_pattern, extents);
3223         if (unlikely (mask->base.status)) {
3224             cairo_surface_destroy (&src->base);
3225             return mask->base.status;
3226         }
3227
3228         _cairo_xcb_connection_render_composite (dst->connection,
3229                                                 _render_operator (op),
3230                                                 src->picture,
3231                                                 mask->picture,
3232                                                 dst->picture,
3233                                                 extents->x + src->x,  extents->y + src->y,
3234                                                 extents->x + mask->x, extents->y + mask->y,
3235                                                 extents->x - dst_x,   extents->y - dst_y,
3236                                                 extents->width,       extents->height);
3237         cairo_surface_destroy (&mask->base);
3238         cairo_surface_destroy (&src->base);
3239     } else {
3240         src = _cairo_xcb_picture_for_pattern (dst, mask_pattern, extents);
3241         if (unlikely (src->base.status))
3242             return src->base.status;
3243
3244         _cairo_xcb_connection_render_composite (dst->connection,
3245                                                 _render_operator (op),
3246                                                 src->picture,
3247                                                 XCB_NONE,
3248                                                 dst->picture,
3249                                                 extents->x + src->x,  extents->y + src->y,
3250                                                 0, 0,
3251                                                 extents->x - dst_x,   extents->y - dst_y,
3252                                                 extents->width,       extents->height);
3253         cairo_surface_destroy (&src->base);
3254     }
3255
3256     return CAIRO_STATUS_SUCCESS;
3257 }
3258
3259 struct composite_box_info {
3260     cairo_xcb_surface_t *dst;
3261     cairo_xcb_picture_t *src;
3262     uint8_t op;
3263 };
3264
3265 static void composite_box(void *closure,
3266                           int16_t x, int16_t y,
3267                           int16_t w, int16_t h,
3268                           uint16_t coverage)
3269 {
3270     struct composite_box_info *info = closure;
3271
3272     if (coverage < 0xff00) {
3273         cairo_xcb_picture_t *mask;
3274         cairo_color_t color;
3275
3276         color.red_short = color.green_short = color.blue_short = 0;
3277         color.alpha_short = coverage;
3278
3279         mask = _solid_picture (info->dst, &color);
3280         if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) {
3281             _cairo_xcb_connection_render_composite (info->dst->connection,
3282                                                     info->op,
3283                                                     info->src->picture,
3284                                                     mask->picture,
3285                                                     info->dst->picture,
3286                                                     x + info->src->x,  y + info->src->y,
3287                                                     0,                 0,
3288                                                     x,                 y,
3289                                                     w,                 h);
3290         }
3291         cairo_surface_destroy (&mask->base);
3292     } else {
3293         _cairo_xcb_connection_render_composite (info->dst->connection,
3294                                                 info->op,
3295                                                 info->src->picture,
3296                                                 XCB_NONE,
3297                                                 info->dst->picture,
3298                                                 x + info->src->x,  y + info->src->y,
3299                                                 0,                 0,
3300                                                 x,                 y,
3301                                                 w,                 h);
3302     }
3303 }
3304
3305 static cairo_int_status_t
3306 _composite_mask_clip_boxes (void                        *closure,
3307                             cairo_xcb_surface_t         *dst,
3308                             cairo_operator_t             op,
3309                             const cairo_pattern_t       *src_pattern,
3310                             int                          dst_x,
3311                             int                          dst_y,
3312                             const cairo_rectangle_int_t *extents,
3313                             cairo_clip_t                *clip)
3314 {
3315     struct composite_box_info info;
3316     cairo_status_t status;
3317     int i;
3318
3319     assert (src_pattern == NULL);
3320     assert (op == CAIRO_OPERATOR_ADD);
3321     assert (dst->base.is_clear);
3322
3323     if (clip->num_boxes > 1) {
3324         status = _cairo_xcb_surface_clear (dst);
3325         if (unlikely (status))
3326             return status;
3327     }
3328
3329     info.op = XCB_RENDER_PICT_OP_SRC;
3330     info.dst = dst;
3331     info.src = _cairo_xcb_picture_for_pattern (dst, closure, extents);
3332     if (unlikely (info.src->base.status))
3333         return info.src->base.status;
3334
3335     info.src->x += dst_x;
3336     info.src->y += dst_y;
3337
3338     for (i = 0; i < clip->num_boxes; i++)
3339         do_unaligned_box(composite_box, &info, &clip->boxes[i], dst_x, dst_y);
3340     cairo_surface_destroy (&info.src->base);
3341
3342     return CAIRO_STATUS_SUCCESS;
3343 }
3344
3345 static cairo_int_status_t
3346 _composite_mask_clip (void                              *closure,
3347                       cairo_xcb_surface_t               *dst,
3348                       cairo_operator_t                   op,
3349                       const cairo_pattern_t             *src_pattern,
3350                       int                                dst_x,
3351                       int                                dst_y,
3352                       const cairo_rectangle_int_t       *extents,
3353                       cairo_clip_t                      *clip)
3354 {
3355     const cairo_pattern_t *mask_pattern = closure;
3356     cairo_polygon_t polygon;
3357     cairo_fill_rule_t fill_rule;
3358     composite_traps_info_t info;
3359     cairo_status_t status;
3360
3361     assert (src_pattern == NULL);
3362     assert (op == CAIRO_OPERATOR_ADD);
3363     assert (dst->base.is_clear);
3364
3365     status = _cairo_clip_get_polygon (clip, &polygon,
3366                                       &fill_rule, &info.antialias);
3367     if (unlikely (status))
3368         return status;
3369
3370     _cairo_traps_init (&info.traps);
3371     status = _cairo_bentley_ottmann_tessellate_polygon (&info.traps,
3372                                                         &polygon,
3373                                                         fill_rule);
3374     _cairo_polygon_fini (&polygon);
3375     if (unlikely (status))
3376         return status;
3377
3378     if (info.traps.has_intersections) {
3379         if (info.traps.is_rectangular)
3380             status = _cairo_bentley_ottmann_tessellate_rectangular_traps (&info.traps, CAIRO_FILL_RULE_WINDING);
3381         else if (info.traps.is_rectilinear)
3382             status = _cairo_bentley_ottmann_tessellate_rectilinear_traps (&info.traps, CAIRO_FILL_RULE_WINDING);
3383         else
3384             status = _cairo_bentley_ottmann_tessellate_traps (&info.traps, CAIRO_FILL_RULE_WINDING);
3385         if (unlikely (status)) {
3386             _cairo_traps_fini (&info.traps);
3387             return status;
3388         }
3389     }
3390
3391     dst->deferred_clear = FALSE; /* assert(trap extents == extents); */
3392
3393     status = _composite_traps (&info,
3394                                dst, CAIRO_OPERATOR_SOURCE, mask_pattern,
3395                                dst_x, dst_y,
3396                                extents, NULL);
3397     _cairo_traps_fini (&info.traps);
3398
3399     return status;
3400 }
3401
3402 struct composite_opacity_info {
3403     uint8_t op;
3404     cairo_xcb_surface_t *dst;
3405     cairo_xcb_picture_t *src;
3406     double opacity;
3407 };
3408
3409 static void composite_opacity(void *closure,
3410                               int16_t x, int16_t y,
3411                               int16_t w, int16_t h,
3412                               uint16_t coverage)
3413 {
3414     struct composite_opacity_info *info = closure;
3415     cairo_xcb_picture_t *mask;
3416     cairo_color_t color;
3417
3418     color.red_short = color.green_short = color.blue_short = 0;
3419     color.alpha_short = info->opacity * coverage;
3420
3421     mask = _solid_picture (info->dst, &color);
3422     if (likely (mask->base.status == CAIRO_STATUS_SUCCESS)) {
3423         if (info->src) {
3424             _cairo_xcb_connection_render_composite (info->dst->connection,
3425                                                     info->op,
3426                                                     info->src->picture,
3427                                                     mask->picture,
3428                                                     info->dst->picture,
3429                                                     x + info->src->x,  y + info->src->y,
3430                                                     0,                 0,
3431                                                     x,                 y,
3432                                                     w,                 h);
3433         } else {
3434             _cairo_xcb_connection_render_composite (info->dst->connection,
3435                                                     info->op,
3436                                                     mask->picture,
3437                                                     XCB_NONE,
3438                                                     info->dst->picture,
3439                                                     0,                 0,
3440                                                     0,                 0,
3441                                                     x,                 y,
3442                                                     w,                 h);
3443         }
3444     }
3445
3446     cairo_surface_destroy (&mask->base);
3447 }
3448
3449 static cairo_int_status_t
3450 _composite_opacity_boxes (void                          *closure,
3451                           cairo_xcb_surface_t           *dst,
3452                           cairo_operator_t               op,
3453                           const cairo_pattern_t         *src_pattern,
3454                           int                            dst_x,
3455                           int                            dst_y,
3456                           const cairo_rectangle_int_t   *extents,
3457                           cairo_clip_t                  *clip)
3458 {
3459     const cairo_solid_pattern_t *mask_pattern = closure;
3460     struct composite_opacity_info info;
3461     cairo_status_t status;
3462     int i;
3463
3464     if (dst->base.is_clear) {
3465         if (op == CAIRO_OPERATOR_OVER || op == CAIRO_OPERATOR_ADD)
3466             op = CAIRO_OPERATOR_SOURCE;
3467     }
3468
3469     if (op == CAIRO_OPERATOR_SOURCE &&
3470         (clip == NULL ||
3471          (clip->extents.width >= extents->width &&
3472           clip->extents.height >= extents->height)))
3473         dst->deferred_clear = FALSE;
3474
3475     if (dst->deferred_clear) {
3476         status = _cairo_xcb_surface_clear (dst);
3477         if (unlikely (status))
3478             return status;
3479     }
3480
3481     info.op = _render_operator (op);
3482     info.dst = dst;
3483
3484     if (src_pattern != NULL) {
3485         info.src = _cairo_xcb_picture_for_pattern (dst, src_pattern, extents);
3486         if (unlikely (info.src->base.status))
3487             return info.src->base.status;
3488     } else
3489         info.src = NULL;
3490
3491     info.opacity = mask_pattern->color.alpha;
3492
3493     /* XXX for lots of boxes create a clip region for the fully opaque areas */
3494     if (clip) {
3495         for (i = 0; i < clip->num_boxes; i++)
3496             do_unaligned_box(composite_opacity, &info,
3497                              &clip->boxes[i], dst_x, dst_y);
3498     } else {
3499         composite_opacity(&info,
3500                           extents->x - dst_x,
3501                           extents->y - dst_y,
3502                           extents->width,
3503                           extents->height,
3504                           0xffff);
3505     }
3506     cairo_surface_destroy (&info.src->base);
3507
3508     return CAIRO_STATUS_SUCCESS;
3509 }
3510
3511 /* high level rasteriser -> compositor */
3512
3513 cairo_int_status_t
3514 _cairo_xcb_render_compositor_paint (const cairo_compositor_t     *compositor,
3515                                     cairo_composite_rectangles_t *composite)
3516 {
3517     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
3518     cairo_operator_t op = composite->op;
3519     cairo_pattern_t *source = &composite->source_pattern.base;
3520     cairo_boxes_t boxes;
3521     cairo_status_t status;
3522
3523     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
3524         return CAIRO_INT_STATUS_UNSUPPORTED;
3525
3526     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
3527                                        CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
3528     {
3529         return CAIRO_INT_STATUS_UNSUPPORTED;
3530     }
3531
3532     if (composite->clip == NULL &&
3533         source->type == CAIRO_PATTERN_TYPE_SOLID &&
3534         (op == CAIRO_OPERATOR_SOURCE ||
3535          op == CAIRO_OPERATOR_CLEAR ||
3536          (surface->base.is_clear &&
3537           (op == CAIRO_OPERATOR_ADD || op == CAIRO_OPERATOR_OVER))))
3538     {
3539         surface->deferred_clear = TRUE;
3540         surface->deferred_clear_color = composite->source_pattern.solid.color;
3541         return CAIRO_STATUS_SUCCESS;
3542     }
3543
3544      _cairo_clip_steal_boxes(composite->clip, &boxes);
3545      status = _clip_and_composite_boxes (surface, op, source, &boxes, composite);
3546      _cairo_clip_unsteal_boxes (composite->clip, &boxes);
3547
3548     return status;
3549 }
3550
3551 cairo_int_status_t
3552 _cairo_xcb_render_compositor_mask (const cairo_compositor_t     *compositor,
3553                                    cairo_composite_rectangles_t *composite)
3554 {
3555     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
3556     cairo_operator_t op = composite->op;
3557     cairo_pattern_t *source = &composite->source_pattern.base;
3558     cairo_pattern_t *mask = &composite->mask_pattern.base;
3559     cairo_status_t status;
3560
3561     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
3562         return CAIRO_INT_STATUS_UNSUPPORTED;
3563
3564     if ((surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) == 0)
3565         return CAIRO_INT_STATUS_UNSUPPORTED;
3566
3567     if (mask->type == CAIRO_PATTERN_TYPE_SOLID &&
3568         composite->clip->path == NULL &&
3569         ! _cairo_clip_is_region (composite->clip)) {
3570         status = _clip_and_composite (surface, op, source,
3571                                       _composite_opacity_boxes,
3572                                       _composite_opacity_boxes,
3573                                       (void *) mask,
3574                                       composite, need_unbounded_clip (composite));
3575     } else {
3576         xcb_draw_func_t mask_func = NULL;
3577         if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS)
3578             mask_func = composite->clip->path ? _composite_mask_clip : _composite_mask_clip_boxes;
3579         status = _clip_and_composite (surface, op, source,
3580                                       _composite_mask, mask_func,
3581                                       (void *) mask,
3582                                       composite, need_bounded_clip (composite));
3583     }
3584
3585     return status;
3586 }
3587
3588 static cairo_int_status_t
3589 _cairo_xcb_surface_render_stroke_as_polygon (cairo_xcb_surface_t        *dst,
3590                                              cairo_operator_t            op,
3591                                              const cairo_pattern_t      *source,
3592                                              const cairo_path_fixed_t           *path,
3593                                              const cairo_stroke_style_t *stroke_style,
3594                                              const cairo_matrix_t       *ctm,
3595                                              const cairo_matrix_t       *ctm_inverse,
3596                                              double                      tolerance,
3597                                              cairo_antialias_t           antialias,
3598                                              cairo_composite_rectangles_t *extents)
3599 {
3600     cairo_polygon_t polygon;
3601     cairo_status_t status;
3602
3603     _cairo_polygon_init_with_clip (&polygon, extents->clip);
3604     status = _cairo_path_fixed_stroke_to_polygon (path,
3605                                                   stroke_style,
3606                                                   ctm, ctm_inverse,
3607                                                   tolerance,
3608                                                   &polygon);
3609     if (likely (status == CAIRO_STATUS_SUCCESS)) {
3610         status = _composite_polygon (dst, op, source,
3611                                      &polygon, antialias,
3612                                      CAIRO_FILL_RULE_WINDING,
3613                                      extents);
3614     }
3615     _cairo_polygon_fini (&polygon);
3616
3617     return status;
3618 }
3619
3620 static cairo_status_t
3621 _cairo_xcb_surface_render_stroke_via_mask (cairo_xcb_surface_t          *dst,
3622                                            cairo_operator_t              op,
3623                                            const cairo_pattern_t        *source,
3624                                            const cairo_path_fixed_t             *path,
3625                                            const cairo_stroke_style_t   *stroke_style,
3626                                            const cairo_matrix_t         *ctm,
3627                                            const cairo_matrix_t         *ctm_inverse,
3628                                            double                        tolerance,
3629                                            cairo_antialias_t             antialias,
3630                                            cairo_composite_rectangles_t *extents)
3631 {
3632     cairo_surface_t *image;
3633     cairo_status_t status;
3634     cairo_clip_t *clip;
3635     int x, y;
3636
3637     x = extents->bounded.x;
3638     y = extents->bounded.y;
3639     image = _cairo_xcb_surface_create_similar_image (dst, CAIRO_FORMAT_A8,
3640                                                      extents->bounded.width,
3641                                                      extents->bounded.height);
3642     if (unlikely (image->status))
3643         return image->status;
3644
3645     clip = _cairo_clip_copy_region (extents->clip);
3646     status = _cairo_surface_offset_stroke (image, x, y,
3647                                            CAIRO_OPERATOR_ADD,
3648                                            &_cairo_pattern_white.base,
3649                                            path, stroke_style,
3650                                            ctm, ctm_inverse,
3651                                            tolerance, antialias,
3652                                            clip);
3653     _cairo_clip_destroy (clip);
3654     if (likely (status == CAIRO_STATUS_SUCCESS)) {
3655         cairo_surface_pattern_t mask;
3656
3657         _cairo_pattern_init_for_surface (&mask, image);
3658         mask.base.filter = CAIRO_FILTER_NEAREST;
3659
3660         cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
3661         status = _clip_and_composite (dst, op, source,
3662                                       _composite_mask, NULL, &mask.base,
3663                                       extents, need_bounded_clip (extents));
3664         _cairo_pattern_fini (&mask.base);
3665     }
3666
3667     cairo_surface_finish (image);
3668     cairo_surface_destroy (image);
3669
3670     return status;
3671 }
3672
3673 cairo_int_status_t
3674 _cairo_xcb_render_compositor_stroke (const cairo_compositor_t     *compositor,
3675                                      cairo_composite_rectangles_t *composite,
3676                                      const cairo_path_fixed_t     *path,
3677                                      const cairo_stroke_style_t   *style,
3678                                      const cairo_matrix_t         *ctm,
3679                                      const cairo_matrix_t         *ctm_inverse,
3680                                      double                        tolerance,
3681                                      cairo_antialias_t             antialias)
3682 {
3683     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
3684     cairo_operator_t op = composite->op;
3685     cairo_pattern_t *source = &composite->source_pattern.base;
3686     cairo_int_status_t status;
3687
3688     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
3689         return CAIRO_INT_STATUS_UNSUPPORTED;
3690
3691     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
3692                            CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
3693     {
3694         return CAIRO_INT_STATUS_UNSUPPORTED;
3695     }
3696
3697     status = CAIRO_INT_STATUS_UNSUPPORTED;
3698     if (_cairo_path_fixed_stroke_is_rectilinear (path)) {
3699         cairo_boxes_t boxes;
3700
3701         _cairo_boxes_init_with_clip (&boxes, composite->clip);
3702         status = _cairo_path_fixed_stroke_rectilinear_to_boxes (path,
3703                                                                 style,
3704                                                                 ctm,
3705                                                                 antialias,
3706                                                                 &boxes);
3707         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
3708             status = _clip_and_composite_boxes (surface, op, source,
3709                                                 &boxes, composite);
3710         }
3711         _cairo_boxes_fini (&boxes);
3712     }
3713
3714     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
3715         if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) {
3716             status = _cairo_xcb_surface_render_stroke_as_polygon (surface, op, source,
3717                                                                   path, style,
3718                                                                   ctm, ctm_inverse,
3719                                                                   tolerance, antialias,
3720                                                                   composite);
3721         } else if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
3722             status = _cairo_xcb_surface_render_stroke_via_mask (surface, op, source,
3723                                                                 path, style,
3724                                                                 ctm, ctm_inverse,
3725                                                                 tolerance, antialias,
3726                                                                 composite);
3727         } else {
3728             ASSERT_NOT_REACHED;
3729         }
3730     }
3731
3732     return status;
3733 }
3734
3735 static cairo_status_t
3736 _cairo_xcb_surface_render_fill_as_polygon (cairo_xcb_surface_t  *dst,
3737                                            cairo_operator_t      op,
3738                                            const cairo_pattern_t*source,
3739                                            const cairo_path_fixed_t     *path,
3740                                            cairo_fill_rule_t     fill_rule,
3741                                            double                tolerance,
3742                                            cairo_antialias_t     antialias,
3743                                            cairo_composite_rectangles_t *extents)
3744 {
3745     cairo_polygon_t polygon;
3746     cairo_status_t status;
3747
3748     _cairo_polygon_init_with_clip (&polygon, extents->clip);
3749     status = _cairo_path_fixed_fill_to_polygon (path, tolerance, &polygon);
3750     if (likely (status == CAIRO_STATUS_SUCCESS)) {
3751         status = _composite_polygon (dst, op, source,
3752                                      &polygon,
3753                                      antialias,
3754                                      fill_rule,
3755                                      extents);
3756     }
3757     _cairo_polygon_fini (&polygon);
3758
3759     return status;
3760 }
3761
3762 static cairo_status_t
3763 _cairo_xcb_surface_render_fill_via_mask (cairo_xcb_surface_t    *dst,
3764                                          cairo_operator_t        op,
3765                                          const cairo_pattern_t  *source,
3766                                          const cairo_path_fixed_t       *path,
3767                                          cairo_fill_rule_t       fill_rule,
3768                                          double                  tolerance,
3769                                          cairo_antialias_t       antialias,
3770                                          cairo_composite_rectangles_t *extents)
3771 {
3772     cairo_surface_t *image;
3773     cairo_status_t status;
3774     cairo_clip_t *clip;
3775     int x, y;
3776
3777     x = extents->bounded.x;
3778     y = extents->bounded.y;
3779     image = _cairo_xcb_surface_create_similar_image (dst, CAIRO_FORMAT_A8,
3780                                                      extents->bounded.width,
3781                                                      extents->bounded.height);
3782     if (unlikely (image->status))
3783         return image->status;
3784
3785     clip = _cairo_clip_copy_region (extents->clip);
3786     status = _cairo_surface_offset_fill (image, x, y,
3787                                          CAIRO_OPERATOR_ADD,
3788                                          &_cairo_pattern_white.base,
3789                                          path, fill_rule, tolerance, antialias,
3790                                          clip);
3791     _cairo_clip_destroy (clip);
3792     if (likely (status == CAIRO_STATUS_SUCCESS)) {
3793         cairo_surface_pattern_t mask;
3794
3795         _cairo_pattern_init_for_surface (&mask, image);
3796         mask.base.filter = CAIRO_FILTER_NEAREST;
3797
3798         cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
3799         status = _clip_and_composite (dst, op, source,
3800                                       _composite_mask, NULL, &mask.base,
3801                                       extents, need_bounded_clip (extents));
3802
3803         _cairo_pattern_fini (&mask.base);
3804     }
3805
3806     cairo_surface_finish (image);
3807     cairo_surface_destroy (image);
3808
3809     return status;
3810 }
3811
3812 cairo_int_status_t
3813 _cairo_xcb_render_compositor_fill (const cairo_compositor_t     *compositor,
3814                                    cairo_composite_rectangles_t *composite,
3815                                    const cairo_path_fixed_t     *path,
3816                                    cairo_fill_rule_t             fill_rule,
3817                                    double                        tolerance,
3818                                    cairo_antialias_t             antialias)
3819 {
3820     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
3821     cairo_operator_t op = composite->op;
3822     cairo_pattern_t *source = &composite->source_pattern.base;
3823     cairo_int_status_t status;
3824
3825     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
3826         return CAIRO_INT_STATUS_UNSUPPORTED;
3827
3828     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS |
3829                                        CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
3830     {
3831         return CAIRO_INT_STATUS_UNSUPPORTED;
3832     }
3833
3834     status = CAIRO_INT_STATUS_UNSUPPORTED;
3835     if (_cairo_path_fixed_fill_is_rectilinear (path)) {
3836         cairo_boxes_t boxes;
3837
3838         _cairo_boxes_init_with_clip (&boxes, composite->clip);
3839         status = _cairo_path_fixed_fill_rectilinear_to_boxes (path,
3840                                                               fill_rule,
3841                                                               antialias,
3842                                                               &boxes);
3843         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
3844             status = _clip_and_composite_boxes (surface, op, source,
3845                                                 &boxes, composite);
3846         }
3847         _cairo_boxes_fini (&boxes);
3848     }
3849
3850     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
3851         if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_TRAPEZOIDS) {
3852             status = _cairo_xcb_surface_render_fill_as_polygon (surface, op, source, path,
3853                                                                 fill_rule, tolerance, antialias,
3854                                                                 composite);
3855         } else if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE) {
3856             status = _cairo_xcb_surface_render_fill_via_mask (surface, op, source, path,
3857                                                               fill_rule, tolerance, antialias,
3858                                                               composite);
3859         } else {
3860             ASSERT_NOT_REACHED;
3861         }
3862     }
3863
3864     return status;
3865 }
3866
3867 static cairo_status_t
3868 _cairo_xcb_surface_render_glyphs_via_mask (cairo_xcb_surface_t          *dst,
3869                                            cairo_operator_t              op,
3870                                            const cairo_pattern_t        *source,
3871                                            cairo_scaled_font_t          *scaled_font,
3872                                            cairo_glyph_t                *glyphs,
3873                                            int                           num_glyphs,
3874                                            cairo_composite_rectangles_t *extents)
3875 {
3876     cairo_surface_t *image;
3877     cairo_content_t content;
3878     cairo_status_t status;
3879     cairo_clip_t *clip;
3880     int x, y;
3881
3882     content = CAIRO_CONTENT_ALPHA;
3883     if (scaled_font->options.antialias == CAIRO_ANTIALIAS_SUBPIXEL)
3884         content = CAIRO_CONTENT_COLOR_ALPHA;
3885
3886     x = extents->bounded.x;
3887     y = extents->bounded.y;
3888     image = _cairo_xcb_surface_create_similar_image (dst,
3889                                                      _cairo_format_from_content (content),
3890                                                      extents->bounded.width,
3891                                                      extents->bounded.height);
3892     if (unlikely (image->status))
3893         return image->status;
3894
3895     clip = _cairo_clip_copy_region (extents->clip);
3896     status = _cairo_surface_offset_glyphs (image, x, y,
3897                                            CAIRO_OPERATOR_ADD,
3898                                            &_cairo_pattern_white.base,
3899                                            scaled_font, glyphs, num_glyphs,
3900                                            clip);
3901     _cairo_clip_destroy (clip);
3902     if (likely (status == CAIRO_STATUS_SUCCESS)) {
3903         cairo_surface_pattern_t mask;
3904
3905         _cairo_pattern_init_for_surface (&mask, image);
3906         mask.base.filter = CAIRO_FILTER_NEAREST;
3907         if (content & CAIRO_CONTENT_COLOR)
3908             mask.base.has_component_alpha = TRUE;
3909
3910         cairo_matrix_init_translate (&mask.base.matrix, -x, -y);
3911         status = _clip_and_composite (dst, op, source,
3912                                       _composite_mask, NULL, &mask.base,
3913                                       extents, need_bounded_clip (extents));
3914
3915         _cairo_pattern_fini (&mask.base);
3916     }
3917
3918     cairo_surface_finish (image);
3919     cairo_surface_destroy (image);
3920
3921     return status;
3922 }
3923
3924 /* Build a struct of the same size of #cairo_glyph_t that can be used both as
3925  * an input glyph with double coordinates, and as "working" glyph with
3926  * integer from-current-point offsets. */
3927 typedef union {
3928     cairo_glyph_t d;
3929     unsigned long index;
3930     struct {
3931         unsigned long index;
3932         int x;
3933         int y;
3934     } i;
3935 } cairo_xcb_glyph_t;
3936
3937 /* compile-time assert that #cairo_xcb_glyph_t is the same size as #cairo_glyph_t */
3938 COMPILE_TIME_ASSERT (sizeof (cairo_xcb_glyph_t) == sizeof (cairo_glyph_t));
3939
3940 typedef struct {
3941     cairo_scaled_font_t *font;
3942     cairo_xcb_glyph_t *glyphs;
3943     int num_glyphs;
3944     cairo_bool_t use_mask;
3945 } composite_glyphs_info_t;
3946
3947 static cairo_status_t
3948 _can_composite_glyphs (cairo_xcb_surface_t *dst,
3949                        cairo_rectangle_int_t *extents,
3950                        cairo_scaled_font_t *scaled_font,
3951                        cairo_glyph_t *glyphs,
3952                        int *num_glyphs)
3953 {
3954 #define GLYPH_CACHE_SIZE 64
3955     cairo_box_t bbox_cache[GLYPH_CACHE_SIZE];
3956     unsigned long glyph_cache[GLYPH_CACHE_SIZE];
3957 #undef GLYPH_CACHE_SIZE
3958     cairo_status_t status = CAIRO_STATUS_SUCCESS;
3959     cairo_glyph_t *glyphs_end, *valid_glyphs;
3960     const int max_glyph_size = dst->connection->maximum_request_length - 64;
3961
3962     /* We must initialize the cache with values that cannot match the
3963      * "hash" to guarantee that when compared for the first time they
3964      * will result in a mismatch. The hash function is simply modulus,
3965      * so we cannot use 0 in glyph_cache[0], but we can use it in all
3966      * other array cells.
3967      */
3968     memset (glyph_cache, 0, sizeof (glyph_cache));
3969     glyph_cache[0] = 1;
3970
3971     /* Scan for oversized glyphs or glyphs outside the representable
3972      * range and fallback in that case, discard glyphs outside of the
3973      * image.
3974      */
3975     valid_glyphs = glyphs;
3976     for (glyphs_end = glyphs + *num_glyphs; glyphs != glyphs_end; glyphs++) {
3977         double x1, y1, x2, y2;
3978         cairo_scaled_glyph_t *glyph;
3979         cairo_box_t *bbox;
3980         int width, height, len;
3981         int g;
3982
3983         g = glyphs->index % ARRAY_LENGTH (glyph_cache);
3984         if (glyph_cache[g] != glyphs->index) {
3985             status = _cairo_scaled_glyph_lookup (scaled_font,
3986                                                  glyphs->index,
3987                                                  CAIRO_SCALED_GLYPH_INFO_METRICS,
3988                                                  &glyph);
3989             if (unlikely (status))
3990                 break;
3991
3992             glyph_cache[g] = glyphs->index;
3993             bbox_cache[g] = glyph->bbox;
3994         }
3995         bbox = &bbox_cache[g];
3996
3997         /* Drop glyphs outside the clipping */
3998         x1 = _cairo_fixed_to_double (bbox->p1.x);
3999         y1 = _cairo_fixed_to_double (bbox->p1.y);
4000         y2 = _cairo_fixed_to_double (bbox->p2.y);
4001         x2 = _cairo_fixed_to_double (bbox->p2.x);
4002         if (unlikely (glyphs->x + x2 <= extents->x ||
4003                       glyphs->y + y2 <= extents->y ||
4004                       glyphs->x + x1 >= extents->x + extents->width ||
4005                       glyphs->y + y1 >= extents->y + extents->height))
4006         {
4007             (*num_glyphs)--;
4008             continue;
4009         }
4010
4011         /* XRenderAddGlyph does not handle a glyph surface larger than
4012          * the extended maximum XRequest size.
4013          */
4014         width  = _cairo_fixed_integer_ceil (bbox->p2.x - bbox->p1.x);
4015         height = _cairo_fixed_integer_ceil (bbox->p2.y - bbox->p1.y);
4016         len = CAIRO_STRIDE_FOR_WIDTH_BPP (width, 32) * height;
4017         if (unlikely (len >= max_glyph_size)) {
4018             status = CAIRO_INT_STATUS_UNSUPPORTED;
4019             break;
4020         }
4021
4022         /* The glyph coordinates must be representable in an int16_t.
4023          * When possible, they will be expressed as an offset from the
4024          * previous glyph, otherwise they will be an offset from the
4025          * operation extents or from the surface origin. If the last
4026          * two options are not valid, fallback.
4027          */
4028         if (unlikely (glyphs->x > INT16_MAX ||
4029                       glyphs->y > INT16_MAX ||
4030                       glyphs->x - extents->x < INT16_MIN ||
4031                       glyphs->y - extents->y < INT16_MIN))
4032         {
4033             status = CAIRO_INT_STATUS_UNSUPPORTED;
4034             break;
4035         }
4036
4037
4038         if (unlikely (valid_glyphs != glyphs))
4039             *valid_glyphs = *glyphs;
4040         valid_glyphs++;
4041     }
4042
4043     if (unlikely (valid_glyphs != glyphs)) {
4044         for (; glyphs != glyphs_end; glyphs++) {
4045             *valid_glyphs = *glyphs;
4046             valid_glyphs++;
4047         }
4048     }
4049
4050     return status;
4051 }
4052
4053 /* Start a new element for the first glyph,
4054  * or for any glyph that has unexpected position,
4055  * or if current element has too many glyphs
4056  * (Xrender limits each element to 252 glyphs, we limit them to 128)
4057  *
4058  * These same conditions need to be mirrored between
4059  * _cairo_xcb_surface_emit_glyphs and _emit_glyph_chunks
4060  */
4061 #define _start_new_glyph_elt(count, glyph) \
4062     (((count) & 127) == 0 || (glyph)->i.x || (glyph)->i.y)
4063
4064 /* sz_xGlyphtElt required alignment to a 32-bit boundary, so ensure we have
4065  * enough room for padding */
4066 typedef struct {
4067     uint8_t   len;
4068     uint8_t   pad1;
4069     uint16_t  pad2;
4070     int16_t   deltax;
4071     int16_t   deltay;
4072 } x_glyph_elt_t;
4073 #define _cairo_sz_x_glyph_elt_t (sizeof (x_glyph_elt_t) + 4)
4074
4075 static void
4076 _cairo_xcb_font_destroy (cairo_xcb_font_t *font)
4077 {
4078     int i;
4079
4080     for (i = 0; i < NUM_GLYPHSETS; i++) {
4081         cairo_xcb_font_glyphset_info_t *info;
4082
4083         info = &font->glyphset_info[i];
4084         free (info->pending_free_glyphs);
4085     }
4086
4087     cairo_list_del (&font->base.link);
4088     cairo_list_del (&font->link);
4089
4090     _cairo_xcb_connection_destroy (font->connection);
4091
4092     free (font);
4093 }
4094
4095 static void
4096 _cairo_xcb_font_fini (cairo_scaled_font_private_t *abstract_private,
4097                       cairo_scaled_font_t *scaled_font)
4098 {
4099     cairo_xcb_font_t *font_private = (cairo_xcb_font_t *)abstract_private;
4100     cairo_xcb_connection_t *connection;
4101     cairo_bool_t have_connection;
4102     cairo_status_t status;
4103     int i;
4104
4105     connection = font_private->connection;
4106
4107     status = _cairo_xcb_connection_acquire (connection);
4108     have_connection = status == CAIRO_STATUS_SUCCESS;
4109
4110     for (i = 0; i < NUM_GLYPHSETS; i++) {
4111         cairo_xcb_font_glyphset_info_t *info;
4112
4113         info = &font_private->glyphset_info[i];
4114         if (info->glyphset && status == CAIRO_STATUS_SUCCESS) {
4115             _cairo_xcb_connection_render_free_glyph_set (connection,
4116                                                          info->glyphset);
4117         }
4118     }
4119
4120     if (have_connection)
4121         _cairo_xcb_connection_release (connection);
4122
4123     _cairo_xcb_font_destroy (font_private);
4124 }
4125
4126
4127 static cairo_xcb_font_t *
4128 _cairo_xcb_font_create (cairo_xcb_connection_t *connection,
4129                         cairo_scaled_font_t  *font)
4130 {
4131     cairo_xcb_font_t    *priv;
4132     int i;
4133
4134     priv = malloc (sizeof (cairo_xcb_font_t));
4135     if (unlikely (priv == NULL))
4136         return NULL;
4137
4138     _cairo_scaled_font_attach_private (font, &priv->base, connection,
4139                                        _cairo_xcb_font_fini);
4140
4141     priv->scaled_font = font;
4142     priv->connection = _cairo_xcb_connection_reference (connection);
4143     cairo_list_add (&priv->link, &connection->fonts);
4144
4145     for (i = 0; i < NUM_GLYPHSETS; i++) {
4146         cairo_xcb_font_glyphset_info_t *info = &priv->glyphset_info[i];
4147         switch (i) {
4148         case GLYPHSET_INDEX_ARGB32: info->format = CAIRO_FORMAT_ARGB32; break;
4149         case GLYPHSET_INDEX_A8:     info->format = CAIRO_FORMAT_A8;     break;
4150         case GLYPHSET_INDEX_A1:     info->format = CAIRO_FORMAT_A1;     break;
4151         default:                    ASSERT_NOT_REACHED;                          break;
4152         }
4153         info->xrender_format = 0;
4154         info->glyphset = XCB_NONE;
4155         info->pending_free_glyphs = NULL;
4156     }
4157
4158     return priv;
4159 }
4160
4161 void
4162 _cairo_xcb_font_close (cairo_xcb_font_t *font)
4163 {
4164     cairo_scaled_font_t *scaled_font;
4165
4166     scaled_font = font->scaled_font;
4167
4168     CAIRO_MUTEX_LOCK (scaled_font->mutex);
4169     //scaled_font->surface_private = NULL;
4170     _cairo_scaled_font_reset_cache (scaled_font);
4171     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
4172
4173     _cairo_xcb_font_destroy (font);
4174 }
4175
4176 static void
4177 _cairo_xcb_render_free_glyphs (cairo_xcb_connection_t *connection,
4178                                cairo_xcb_font_glyphset_free_glyphs_t *to_free)
4179 {
4180     _cairo_xcb_connection_render_free_glyphs (connection,
4181                                               to_free->glyphset,
4182                                               to_free->glyph_count,
4183                                               to_free->glyph_indices);
4184 }
4185
4186 static int
4187 _cairo_xcb_get_glyphset_index_for_format (cairo_format_t format)
4188 {
4189     if (format == CAIRO_FORMAT_A8)
4190         return GLYPHSET_INDEX_A8;
4191     if (format == CAIRO_FORMAT_A1)
4192         return GLYPHSET_INDEX_A1;
4193
4194     assert (format == CAIRO_FORMAT_ARGB32);
4195     return GLYPHSET_INDEX_ARGB32;
4196 }
4197
4198
4199
4200 static inline cairo_xcb_font_t *
4201 _cairo_xcb_font_get (const cairo_xcb_connection_t *c,
4202                      cairo_scaled_font_t *font)
4203 {
4204     return (cairo_xcb_font_t *)_cairo_scaled_font_find_private (font, c);
4205 }
4206
4207
4208 static cairo_xcb_font_glyphset_info_t *
4209 _cairo_xcb_scaled_font_get_glyphset_info_for_format (cairo_xcb_connection_t *c,
4210                                                      cairo_scaled_font_t *font,
4211                                                      cairo_format_t       format)
4212 {
4213     cairo_xcb_font_t *priv;
4214     cairo_xcb_font_glyphset_info_t *info;
4215     int glyphset_index;
4216
4217     glyphset_index = _cairo_xcb_get_glyphset_index_for_format (format);
4218
4219     priv = _cairo_xcb_font_get (c, font);
4220     if (priv == NULL) {
4221         priv = _cairo_xcb_font_create (c, font);
4222         if (priv == NULL)
4223             return NULL;
4224     }
4225
4226     info = &priv->glyphset_info[glyphset_index];
4227     if (info->glyphset == XCB_NONE) {
4228         info->glyphset = _cairo_xcb_connection_get_xid (c);
4229         info->xrender_format = c->standard_formats[info->format];
4230
4231         _cairo_xcb_connection_render_create_glyph_set (c,
4232                                                        info->glyphset,
4233                                                        info->xrender_format);
4234     }
4235
4236     return info;
4237 }
4238
4239 static cairo_bool_t
4240 _cairo_xcb_glyphset_info_has_pending_free_glyph (
4241                                 cairo_xcb_font_glyphset_info_t *info,
4242                                 unsigned long glyph_index)
4243 {
4244     if (info->pending_free_glyphs != NULL) {
4245         cairo_xcb_font_glyphset_free_glyphs_t *to_free;
4246         int i;
4247
4248         to_free = info->pending_free_glyphs;
4249         for (i = 0; i < to_free->glyph_count; i++) {
4250             if (to_free->glyph_indices[i] == glyph_index) {
4251                 to_free->glyph_count--;
4252                 memmove (&to_free->glyph_indices[i],
4253                          &to_free->glyph_indices[i+1],
4254                          (to_free->glyph_count - i) * sizeof (to_free->glyph_indices[0]));
4255                 return TRUE;
4256             }
4257         }
4258     }
4259
4260     return FALSE;
4261 }
4262
4263 typedef struct {
4264     cairo_scaled_glyph_private_t base;
4265
4266     cairo_xcb_font_glyphset_info_t *glyphset;
4267 } cairo_xcb_glyph_private_t;
4268
4269 static cairo_xcb_font_glyphset_info_t *
4270 _cairo_xcb_scaled_font_get_glyphset_info_for_pending_free_glyph (cairo_xcb_connection_t *c,
4271                                                cairo_scaled_font_t *font,
4272                                                unsigned long glyph_index,
4273                                                cairo_image_surface_t *surface)
4274 {
4275     cairo_xcb_font_t *priv;
4276     int i;
4277
4278     priv = _cairo_xcb_font_get (c, font);
4279     if (priv == NULL)
4280         return NULL;
4281
4282     if (surface != NULL) {
4283         i = _cairo_xcb_get_glyphset_index_for_format (surface->format);
4284
4285         if (_cairo_xcb_glyphset_info_has_pending_free_glyph (
4286                                                 &priv->glyphset_info[i],
4287                                                 glyph_index))
4288         {
4289             return &priv->glyphset_info[i];
4290         }
4291     } else {
4292         for (i = 0; i < NUM_GLYPHSETS; i++) {
4293             if (_cairo_xcb_glyphset_info_has_pending_free_glyph (
4294                                                 &priv->glyphset_info[i],
4295                                                 glyph_index))
4296             {
4297                 return &priv->glyphset_info[i];
4298             }
4299         }
4300     }
4301
4302     return NULL;
4303 }
4304
4305 static void
4306 _cairo_xcb_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
4307                        cairo_scaled_glyph_t *glyph,
4308                        cairo_scaled_font_t  *font)
4309 {
4310     cairo_xcb_glyph_private_t *priv = (cairo_xcb_glyph_private_t *)glyph_private;
4311
4312     if (! font->finished) {
4313         cairo_xcb_font_glyphset_info_t *info = priv->glyphset;
4314         cairo_xcb_font_glyphset_free_glyphs_t *to_free;
4315         cairo_xcb_font_t *font_private;
4316
4317         font_private = _cairo_xcb_font_get (glyph_private->key, font);
4318         assert (font_private);
4319
4320         to_free = info->pending_free_glyphs;
4321         if (to_free != NULL &&
4322             to_free->glyph_count == ARRAY_LENGTH (to_free->glyph_indices))
4323         {
4324             _cairo_xcb_render_free_glyphs (font_private->connection, to_free);
4325             to_free = info->pending_free_glyphs = NULL;
4326         }
4327
4328         if (to_free == NULL) {
4329             to_free = malloc (sizeof (cairo_xcb_font_glyphset_free_glyphs_t));
4330             if (unlikely (to_free == NULL)) {
4331                 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
4332                 return; /* XXX cannot propagate failure */
4333             }
4334
4335             to_free->glyphset = info->glyphset;
4336             to_free->glyph_count = 0;
4337             info->pending_free_glyphs = to_free;
4338         }
4339
4340         to_free->glyph_indices[to_free->glyph_count++] =
4341             _cairo_scaled_glyph_index (glyph);
4342     }
4343
4344     cairo_list_del (&glyph_private->link);
4345     free (glyph_private);
4346 }
4347
4348
4349 static cairo_status_t
4350 _cairo_xcb_glyph_attach (cairo_xcb_connection_t  *c,
4351                          cairo_scaled_glyph_t  *glyph,
4352                          cairo_xcb_font_glyphset_info_t *info)
4353 {
4354     cairo_xcb_glyph_private_t *priv;
4355
4356     priv = malloc (sizeof (*priv));
4357     if (unlikely (priv == NULL))
4358         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4359
4360     _cairo_scaled_glyph_attach_private (glyph, &priv->base, c,
4361                                         _cairo_xcb_glyph_fini);
4362     priv->glyphset = info;
4363
4364     glyph->dev_private = info;
4365     glyph->dev_private_key = c;
4366     return CAIRO_STATUS_SUCCESS;
4367 }
4368
4369 static cairo_status_t
4370 _cairo_xcb_surface_add_glyph (cairo_xcb_connection_t *connection,
4371                                cairo_scaled_font_t   *font,
4372                                cairo_scaled_glyph_t **scaled_glyph_out)
4373 {
4374     xcb_render_glyphinfo_t glyph_info;
4375     uint32_t glyph_index;
4376     uint8_t *data;
4377     cairo_status_t status = CAIRO_STATUS_SUCCESS;
4378     cairo_scaled_glyph_t *scaled_glyph = *scaled_glyph_out;
4379     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
4380     cairo_bool_t already_had_glyph_surface;
4381     cairo_xcb_font_glyphset_info_t *info;
4382
4383     glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
4384
4385     /* check to see if we have a pending XRenderFreeGlyph for this glyph */
4386     info = _cairo_xcb_scaled_font_get_glyphset_info_for_pending_free_glyph (connection, font, glyph_index, glyph_surface);
4387     if (info != NULL)
4388         return _cairo_xcb_glyph_attach (connection, scaled_glyph, info);
4389
4390     if (glyph_surface == NULL) {
4391         status = _cairo_scaled_glyph_lookup (font,
4392                                              glyph_index,
4393                                              CAIRO_SCALED_GLYPH_INFO_METRICS |
4394                                              CAIRO_SCALED_GLYPH_INFO_SURFACE,
4395                                              scaled_glyph_out);
4396         if (unlikely (status))
4397             return status;
4398
4399         scaled_glyph = *scaled_glyph_out;
4400         glyph_surface = scaled_glyph->surface;
4401         already_had_glyph_surface = FALSE;
4402     } else {
4403         already_had_glyph_surface = TRUE;
4404     }
4405
4406     info = _cairo_xcb_scaled_font_get_glyphset_info_for_format (connection,
4407                                                                 font,
4408                                                                 glyph_surface->format);
4409     if (unlikely (info == NULL)) {
4410         status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
4411         goto BAIL;
4412     }
4413
4414 #if 0
4415     /* If the glyph surface has zero height or width, we create
4416      * a clear 1x1 surface, to avoid various X server bugs.
4417      */
4418     if (glyph_surface->width == 0 || glyph_surface->height == 0) {
4419         cairo_surface_t *tmp_surface;
4420
4421         tmp_surface = cairo_image_surface_create (info->format, 1, 1);
4422         status = tmp_surface->status;
4423         if (unlikely (status))
4424             goto BAIL;
4425
4426         tmp_surface->device_transform = glyph_surface->base.device_transform;
4427         tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
4428
4429         glyph_surface = (cairo_image_surface_t *) tmp_surface;
4430     }
4431 #endif
4432
4433     /* If the glyph format does not match the font format, then we
4434      * create a temporary surface for the glyph image with the font's
4435      * format.
4436      */
4437     if (glyph_surface->format != info->format) {
4438         glyph_surface = _cairo_image_surface_coerce_to_format (glyph_surface,
4439                                                                info->format);
4440         status = glyph_surface->base.status;
4441         if (unlikely (status))
4442             goto BAIL;
4443     }
4444
4445     /* XXX: FRAGILE: We're ignore device_transform scaling here. A bug? */
4446     glyph_info.x = _cairo_lround (glyph_surface->base.device_transform.x0);
4447     glyph_info.y = _cairo_lround (glyph_surface->base.device_transform.y0);
4448     glyph_info.width  = glyph_surface->width;
4449     glyph_info.height = glyph_surface->height;
4450     glyph_info.x_off = scaled_glyph->x_advance;
4451     glyph_info.y_off = scaled_glyph->y_advance;
4452
4453     data = glyph_surface->data;
4454
4455     /* flip formats around */
4456     switch (_cairo_xcb_get_glyphset_index_for_format (scaled_glyph->surface->format)) {
4457     case GLYPHSET_INDEX_A1:
4458         /* local bitmaps are always stored with bit == byte */
4459         if (_cairo_is_little_endian() != (connection->root->bitmap_format_bit_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
4460             int             c = glyph_surface->stride * glyph_surface->height;
4461             const uint8_t *d;
4462             uint8_t *new, *n;
4463
4464             new = malloc (c);
4465             if (unlikely (new == NULL)) {
4466                 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
4467                 goto BAIL;
4468             }
4469
4470             n = new;
4471             d = data;
4472             do {
4473                 uint8_t b = *d++;
4474                 b = ((b << 1) & 0xaa) | ((b >> 1) & 0x55);
4475                 b = ((b << 2) & 0xcc) | ((b >> 2) & 0x33);
4476                 b = ((b << 4) & 0xf0) | ((b >> 4) & 0x0f);
4477                 *n++ = b;
4478             } while (--c);
4479             data = new;
4480         }
4481         break;
4482
4483     case GLYPHSET_INDEX_A8:
4484         break;
4485
4486     case GLYPHSET_INDEX_ARGB32:
4487         if (_cairo_is_little_endian() != (connection->root->image_byte_order == XCB_IMAGE_ORDER_LSB_FIRST)) {
4488             unsigned int c = glyph_surface->stride * glyph_surface->height / 4;
4489             const uint32_t *d;
4490             uint32_t *new, *n;
4491
4492             new = malloc (4 * c);
4493             if (unlikely (new == NULL)) {
4494                 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
4495                 goto BAIL;
4496             }
4497
4498             n = new;
4499             d = (uint32_t *) data;
4500             do {
4501                 *n++ = bswap_32 (*d);
4502                 d++;
4503             } while (--c);
4504             data = (uint8_t *) new;
4505         }
4506         break;
4507
4508     default:
4509         ASSERT_NOT_REACHED;
4510         break;
4511     }
4512     /* XXX assume X server wants pixman padding. Xft assumes this as well */
4513
4514     _cairo_xcb_connection_render_add_glyphs (connection,
4515                                              info->glyphset,
4516                                              1, &glyph_index, &glyph_info,
4517                                              glyph_surface->stride * glyph_surface->height,
4518                                              data);
4519
4520     if (data != glyph_surface->data)
4521         free (data);
4522
4523     status = _cairo_xcb_glyph_attach (connection, scaled_glyph, info);
4524
4525  BAIL:
4526     if (glyph_surface != scaled_glyph->surface)
4527         cairo_surface_destroy (&glyph_surface->base);
4528
4529     /* If the scaled glyph didn't already have a surface attached
4530      * to it, release the created surface now that we have it
4531      * uploaded to the X server.  If the surface has already been
4532      * there (e.g. because image backend requested it), leave it in
4533      * the cache
4534      */
4535     if (! already_had_glyph_surface)
4536         _cairo_scaled_glyph_set_surface (scaled_glyph, font, NULL);
4537
4538     return status;
4539 }
4540
4541 typedef void (*cairo_xcb_render_composite_text_func_t)
4542               (cairo_xcb_connection_t       *connection,
4543                uint8_t                          op,
4544                xcb_render_picture_t src,
4545                xcb_render_picture_t dst,
4546                xcb_render_pictformat_t mask_format,
4547                xcb_render_glyphset_t glyphset,
4548                int16_t                          src_x,
4549                int16_t                          src_y,
4550                uint32_t                          len,
4551                uint8_t                        *cmd);
4552
4553
4554 static cairo_status_t
4555 _emit_glyphs_chunk (cairo_xcb_surface_t *dst,
4556                     cairo_operator_t op,
4557                     cairo_xcb_picture_t *src,
4558                     /* info for this chunk */
4559                     cairo_xcb_glyph_t *glyphs,
4560                     int num_glyphs,
4561                     int width,
4562                     int estimated_req_size,
4563                     cairo_xcb_font_glyphset_info_t *info,
4564                     xcb_render_pictformat_t mask_format)
4565 {
4566     cairo_xcb_render_composite_text_func_t composite_text_func;
4567     uint8_t stack_buf[CAIRO_STACK_BUFFER_SIZE];
4568     uint8_t *buf = stack_buf;
4569     x_glyph_elt_t *elt = NULL; /* silence compiler */
4570     uint32_t len;
4571     int i;
4572
4573     if (estimated_req_size > ARRAY_LENGTH (stack_buf)) {
4574         buf = malloc (estimated_req_size);
4575         if (unlikely (buf == NULL))
4576             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4577     }
4578
4579     len = 0;
4580     for (i = 0; i < num_glyphs; i++) {
4581       if (_start_new_glyph_elt (i, &glyphs[i])) {
4582           if (len & 3)
4583               len += 4 - (len & 3);
4584
4585           elt = (x_glyph_elt_t *) (buf + len);
4586           elt->len = 0;
4587           elt->deltax = glyphs[i].i.x;
4588           elt->deltay = glyphs[i].i.y;
4589           len += sizeof (x_glyph_elt_t);
4590       }
4591
4592       switch (width) {
4593       case 1: *(uint8_t *) (buf + len) = glyphs[i].index; break;
4594       case 2: *(uint16_t *) (buf + len) = glyphs[i].index; break;
4595       default:
4596       case 4: *(uint32_t *) (buf + len) = glyphs[i].index; break;
4597       }
4598       len += width;
4599       elt->len++;
4600     }
4601     if (len & 3)
4602         len += 4 - (len & 3);
4603
4604     switch (width) {
4605     case 1:
4606         composite_text_func = _cairo_xcb_connection_render_composite_glyphs_8;
4607         break;
4608     case 2:
4609         composite_text_func = _cairo_xcb_connection_render_composite_glyphs_16;
4610         break;
4611     default:
4612     case 4:
4613         composite_text_func = _cairo_xcb_connection_render_composite_glyphs_32;
4614         break;
4615     }
4616     composite_text_func (dst->connection,
4617                          _render_operator (op),
4618                          src->picture,
4619                          dst->picture,
4620                          mask_format,
4621                          info->glyphset,
4622                          src->x + glyphs[0].i.x,
4623                          src->y + glyphs[0].i.y,
4624                          len, buf);
4625
4626     if (buf != stack_buf)
4627       free (buf);
4628
4629     return CAIRO_STATUS_SUCCESS;
4630 }
4631
4632 static cairo_int_status_t
4633 _composite_glyphs (void                         *closure,
4634                   cairo_xcb_surface_t           *dst,
4635                   cairo_operator_t               op,
4636                   const cairo_pattern_t         *pattern,
4637                   int                            dst_x,
4638                   int                            dst_y,
4639                   const cairo_rectangle_int_t   *extents,
4640                   cairo_clip_t                  *clip)
4641 {
4642     composite_glyphs_info_t *info = closure;
4643     cairo_scaled_glyph_t *glyph_cache[64];
4644     cairo_status_t status = CAIRO_STATUS_SUCCESS;
4645     cairo_fixed_t x = 0, y = 0;
4646     cairo_xcb_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info;
4647     const unsigned int max_request_size = dst->connection->maximum_request_length - 64;
4648     cairo_xcb_picture_t *src;
4649
4650     unsigned long max_index = 0;
4651     int width = 1;
4652
4653     unsigned int request_size = 0;
4654     int i;
4655
4656     if (dst->deferred_clear) {
4657         status = _cairo_xcb_surface_clear (dst);
4658         if (unlikely (status))
4659                 return status;
4660     }
4661
4662     src = _cairo_xcb_picture_for_pattern (dst, pattern, extents);
4663     if (unlikely (src->base.status))
4664         return src->base.status;
4665
4666     memset (glyph_cache, 0, sizeof (glyph_cache));
4667
4668     for (i = 0; i < info->num_glyphs; i++) {
4669         cairo_scaled_glyph_t *glyph;
4670         unsigned long glyph_index = info->glyphs[i].index;
4671         int cache_index = glyph_index % ARRAY_LENGTH (glyph_cache);
4672         int old_width = width;
4673         int this_x, this_y;
4674
4675         glyph = glyph_cache[cache_index];
4676         if (glyph == NULL ||
4677             _cairo_scaled_glyph_index (glyph) != glyph_index)
4678         {
4679             status = _cairo_scaled_glyph_lookup (info->font,
4680                                                  glyph_index,
4681                                                  CAIRO_SCALED_GLYPH_INFO_METRICS,
4682                                                  &glyph);
4683             if (unlikely (status)) {
4684                 cairo_surface_destroy (&src->base);
4685                 return status;
4686             }
4687
4688             /* Send unseen glyphs to the server */
4689             if (glyph->dev_private_key != dst->connection) {
4690                 status = _cairo_xcb_surface_add_glyph (dst->connection,
4691                                                        info->font,
4692                                                        &glyph);
4693                 if (unlikely (status)) {
4694                     cairo_surface_destroy (&src->base);
4695                     return status;
4696                 }
4697             }
4698
4699             glyph_cache[cache_index] = glyph;
4700         }
4701
4702         this_x = _cairo_lround (info->glyphs[i].d.x) - dst_x;
4703         this_y = _cairo_lround (info->glyphs[i].d.y) - dst_y;
4704
4705         this_glyphset_info = glyph->dev_private;
4706         if (glyphset_info == NULL)
4707             glyphset_info = this_glyphset_info;
4708
4709         /* Update max glyph index */
4710         if (glyph_index > max_index) {
4711             max_index = glyph_index;
4712             if (max_index >= 65536)
4713                 width = 4;
4714             else if (max_index >= 256)
4715                 width = 2;
4716             if (width != old_width)
4717                 request_size += (width - old_width) * i;
4718         }
4719
4720         /* If we will pass the max request size by adding this glyph,
4721          * flush current glyphs.  Note that we account for a
4722          * possible element being added below.
4723          *
4724          * Also flush if changing glyphsets, as Xrender limits one mask
4725          * format per request, so we can either break up, or use a
4726          * wide-enough mask format.  We do the former.  One reason to
4727          * prefer the latter is the fact that Xserver ADDs all glyphs
4728          * to the mask first, and then composes that to final surface,
4729          * though it's not a big deal.
4730          *
4731          * If the glyph has a coordinate which cannot be represented
4732          * as a 16-bit offset from the previous glyph, flush the
4733          * current chunk. The current glyph will be the first one in
4734          * the next chunk, thus its coordinates will be an offset from
4735          * the destination origin. This offset is guaranteed to be
4736          * representable as 16-bit offset in _can_composite_glyphs().
4737          */
4738         if (request_size + width > max_request_size - _cairo_sz_x_glyph_elt_t ||
4739             this_x - x > INT16_MAX || this_x - x < INT16_MIN ||
4740             this_y - y > INT16_MAX || this_y - y < INT16_MIN ||
4741             this_glyphset_info != glyphset_info)
4742         {
4743             status = _emit_glyphs_chunk (dst, op, src,
4744                                          info->glyphs, i,
4745                                          old_width, request_size,
4746                                          glyphset_info,
4747                                          info->use_mask ? glyphset_info->xrender_format : 0);
4748             if (unlikely (status)) {
4749                 cairo_surface_destroy (&src->base);
4750                 return status;
4751             }
4752
4753             info->glyphs += i;
4754             info->num_glyphs -= i;
4755             i = 0;
4756
4757             max_index = info->glyphs[0].index;
4758             width = max_index < 256 ? 1 : max_index < 65536 ? 2 : 4;
4759
4760             request_size = 0;
4761
4762             x = y = 0;
4763             glyphset_info = this_glyphset_info;
4764         }
4765
4766         /* Convert absolute glyph position to relative-to-current-point
4767          * position */
4768         info->glyphs[i].i.x = this_x - x;
4769         info->glyphs[i].i.y = this_y - y;
4770
4771         /* Start a new element for the first glyph,
4772          * or for any glyph that has unexpected position,
4773          * or if current element has too many glyphs.
4774          *
4775          * These same conditions are mirrored in _emit_glyphs_chunk().
4776          */
4777       if (_start_new_glyph_elt (i, &info->glyphs[i]))
4778             request_size += _cairo_sz_x_glyph_elt_t;
4779
4780         /* adjust current-position */
4781         x = this_x + glyph->x_advance;
4782         y = this_y + glyph->y_advance;
4783
4784         request_size += width;
4785     }
4786
4787     if (i) {
4788         status = _emit_glyphs_chunk (dst, op, src,
4789                                      info->glyphs, i,
4790                                      width, request_size,
4791                                      glyphset_info,
4792                                      info->use_mask ? glyphset_info->xrender_format : 0);
4793     }
4794
4795     cairo_surface_destroy (&src->base);
4796
4797     return status;
4798 }
4799
4800 cairo_int_status_t
4801 _cairo_xcb_render_compositor_glyphs (const cairo_compositor_t     *compositor,
4802                                      cairo_composite_rectangles_t *composite,
4803                                      cairo_scaled_font_t          *scaled_font,
4804                                      cairo_glyph_t                *glyphs,
4805                                      int                           num_glyphs,
4806                                      cairo_bool_t                  overlap)
4807 {
4808     cairo_xcb_surface_t *surface = (cairo_xcb_surface_t *) composite->surface;
4809     cairo_operator_t op = composite->op;
4810     cairo_pattern_t *source = &composite->source_pattern.base;
4811     cairo_int_status_t status;
4812
4813     if (unlikely (! _operator_is_supported (surface->connection->flags, op)))
4814         return CAIRO_INT_STATUS_UNSUPPORTED;
4815
4816     if ((surface->connection->flags & (CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS | CAIRO_XCB_RENDER_HAS_COMPOSITE)) == 0)
4817         return CAIRO_INT_STATUS_UNSUPPORTED;
4818
4819     status = CAIRO_INT_STATUS_UNSUPPORTED;
4820     if (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE_GLYPHS) {
4821         _cairo_scaled_font_freeze_cache (scaled_font);
4822
4823         status = _can_composite_glyphs (surface, &composite->bounded,
4824                                         scaled_font, glyphs, &num_glyphs);
4825         if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
4826             composite_glyphs_info_t info;
4827             unsigned flags = 0;
4828
4829             info.font = scaled_font;
4830             info.glyphs = (cairo_xcb_glyph_t *) glyphs;
4831             info.num_glyphs = num_glyphs;
4832             info.use_mask =
4833                 overlap ||
4834                 ! composite->is_bounded ||
4835                 ! _cairo_clip_is_region(composite->clip);
4836
4837             if (composite->mask.width  > composite->unbounded.width ||
4838                 composite->mask.height > composite->unbounded.height)
4839             {
4840                 /* Glyphs are tricky since we do not directly control the
4841                  * geometry and their inked extents depend on the
4842                  * individual glyph-surface size. We must set a clip region
4843                  * so that the X server can trim the glyphs appropriately.
4844                  */
4845                 flags |= FORCE_CLIP_REGION;
4846             }
4847             status = _clip_and_composite (surface, op, source,
4848                                           _composite_glyphs, NULL,
4849                                           &info, composite,
4850                                           need_bounded_clip (composite) |
4851                                           flags);
4852         }
4853
4854         _cairo_scaled_font_thaw_cache (scaled_font);
4855     }
4856
4857     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
4858         assert (surface->connection->flags & CAIRO_XCB_RENDER_HAS_COMPOSITE);
4859         status =
4860             _cairo_xcb_surface_render_glyphs_via_mask (surface, op, source,
4861                                                        scaled_font, glyphs, num_glyphs,
4862                                                        composite);
4863     }
4864
4865     return status;
4866 }