f8dac70b333ebd6819b211bf90228fe88ea2f8c0
[framework/graphics/cairo.git] / src / cairo-xlib-source.c
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /* cairo - a vector graphics library with display and print output
3  *
4  * Copyright © 2002 University of Southern California
5  * Copyright © 2005 Red Hat, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it either under the terms of the GNU Lesser General Public
9  * License version 2.1 as published by the Free Software Foundation
10  * (the "LGPL") or, at your option, under the terms of the Mozilla
11  * Public License Version 1.1 (the "MPL"). If you do not alter this
12  * notice, a recipient may use your version of this file under either
13  * the MPL or the LGPL.
14  *
15  * You should have received a copy of the LGPL along with this library
16  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18  * You should have received a copy of the MPL along with this library
19  * in the file COPYING-MPL-1.1
20  *
21  * The contents of this file are subject to the Mozilla Public License
22  * Version 1.1 (the "License"); you may not use this file except in
23  * compliance with the License. You may obtain a copy of the License at
24  * http://www.mozilla.org/MPL/
25  *
26  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28  * the specific language governing rights and limitations.
29  *
30  * The Original Code is the cairo graphics library.
31  *
32  * The Initial Developer of the Original Code is University of Southern
33  * California.
34  *
35  * Contributor(s):
36  *      Carl D. Worth <cworth@cworth.org>
37  *      Behdad Esfahbod <behdad@behdad.org>
38  *      Chris Wilson <chris@chris-wilson.co.uk>
39  *      Karl Tomlinson <karlt+@karlt.net>, Mozilla Corporation
40  */
41 #include "cairoint.h"
42
43 #if !CAIRO_HAS_XLIB_XCB_FUNCTIONS
44
45 #include "cairo-xlib-private.h"
46 #include "cairo-xlib-surface-private.h"
47
48 #include "cairo-error-private.h"
49 #include "cairo-image-surface-private.h"
50 #include "cairo-paginated-private.h"
51 #include "cairo-pattern-inline.h"
52 #include "cairo-recording-surface-private.h"
53 #include "cairo-surface-backend-private.h"
54 #include "cairo-surface-offset-private.h"
55 #include "cairo-surface-observer-private.h"
56 #include "cairo-surface-snapshot-inline.h"
57 #include "cairo-surface-subsurface-inline.h"
58
59 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
60
61 static cairo_xlib_surface_t *
62 unwrap_source (const cairo_surface_pattern_t *pattern)
63 {
64     cairo_rectangle_int_t limits;
65     return (cairo_xlib_surface_t *)_cairo_pattern_get_source (pattern, &limits);
66 }
67
68 static cairo_status_t
69 _cairo_xlib_source_finish (void *abstract_surface)
70 {
71     cairo_xlib_source_t *source = abstract_surface;
72
73     XRenderFreePicture (source->dpy, source->picture);
74     return CAIRO_STATUS_SUCCESS;
75 }
76
77 static const cairo_surface_backend_t cairo_xlib_source_backend = {
78     CAIRO_SURFACE_TYPE_IMAGE,
79     _cairo_xlib_source_finish,
80     NULL, /* read-only wrapper */
81 };
82
83 static cairo_surface_t *
84 source (cairo_xlib_surface_t *dst, Picture picture)
85 {
86     cairo_xlib_source_t *source;
87
88     if (picture == None)
89         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
90
91     source = malloc (sizeof (cairo_image_surface_t));
92     if (unlikely (source == NULL)) {
93         XRenderFreePicture (dst->display->display, picture);
94         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
95     }
96
97     _cairo_surface_init (&source->base,
98                          &cairo_xlib_source_backend,
99                          NULL, /* device */
100                          CAIRO_CONTENT_COLOR_ALPHA);
101
102     /* The source exists only within an operation */
103     source->picture = picture;
104     source->dpy = dst->display->display;
105
106     return &source->base;
107 }
108
109 static uint32_t
110 hars_petruska_f54_1_random (void)
111 {
112 #define rol(x,k) ((x << k) | (x >> (32-k)))
113     static uint32_t x;
114     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
115 #undef rol
116 }
117
118 static const XTransform identity = {
119     {
120         { 1 << 16, 0x00000, 0x00000 },
121         { 0x00000, 1 << 16, 0x00000 },
122         { 0x00000, 0x00000, 1 << 16 },
123     }
124 };
125
126 static cairo_bool_t
127 picture_set_matrix (cairo_xlib_display_t *display,
128                     Picture picture,
129                     const cairo_matrix_t *matrix,
130                     cairo_filter_t        filter,
131                     double                xc,
132                     double                yc,
133                     int                  *x_offset,
134                     int                  *y_offset)
135 {
136     XTransform xtransform;
137     pixman_transform_t *pixman_transform;
138     cairo_int_status_t status;
139
140     /* Casting between pixman_transform_t and XTransform is safe because
141      * they happen to be the exact same type.
142      */
143     pixman_transform = (pixman_transform_t *) &xtransform;
144     status = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
145                                                     pixman_transform,
146                                                     x_offset, y_offset);
147     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
148         return TRUE;
149     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
150         return FALSE;
151
152     if (memcmp (&xtransform, &identity, sizeof (XTransform)) == 0)
153         return TRUE;
154
155     /* a late check in case we perturb the matrix too far */
156     if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display))
157         return FALSE;
158
159     XRenderSetPictureTransform (display->display, picture, &xtransform);
160     return TRUE;
161 }
162
163 static cairo_status_t
164 picture_set_filter (Display *dpy,
165                     Picture picture,
166                     cairo_filter_t filter)
167 {
168     const char *render_filter;
169
170     switch (filter) {
171     case CAIRO_FILTER_FAST:
172         render_filter = FilterFast;
173         break;
174     case CAIRO_FILTER_GOOD:
175         render_filter = FilterGood;
176         break;
177     case CAIRO_FILTER_BEST:
178         render_filter = FilterBest;
179         break;
180     case CAIRO_FILTER_NEAREST:
181         render_filter = FilterNearest;
182         break;
183     case CAIRO_FILTER_BILINEAR:
184         render_filter = FilterBilinear;
185         break;
186     case CAIRO_FILTER_GAUSSIAN:
187         /* XXX: The GAUSSIAN value has no implementation in cairo
188          * whatsoever, so it was really a mistake to have it in the
189          * API. We could fix this by officially deprecating it, or
190          * else inventing semantics and providing an actual
191          * implementation for it. */
192     default:
193         render_filter = FilterBest;
194         break;
195     }
196
197     XRenderSetPictureFilter (dpy, picture, (char *) render_filter, NULL, 0);
198     return CAIRO_STATUS_SUCCESS;
199 }
200
201 static int
202 extend_to_repeat (cairo_extend_t extend)
203 {
204     switch (extend) {
205     default:
206         ASSERT_NOT_REACHED;
207     case CAIRO_EXTEND_NONE:
208         return RepeatNone;
209     case CAIRO_EXTEND_REPEAT:
210         return RepeatNormal;
211     case CAIRO_EXTEND_REFLECT:
212         return RepeatReflect;
213     case CAIRO_EXTEND_PAD:
214         return RepeatPad;
215     }
216 }
217
218 static cairo_bool_t
219 picture_set_properties (cairo_xlib_display_t *display,
220                         Picture picture,
221                         const cairo_pattern_t *pattern,
222                         const cairo_matrix_t *matrix,
223                         const cairo_rectangle_int_t *extents,
224                         int *x_off, int *y_off)
225 {
226     XRenderPictureAttributes pa;
227     int mask = 0;
228
229     if (! picture_set_matrix (display, picture, matrix, pattern->filter,
230                               extents->x + extents->width / 2,
231                               extents->y + extents->height / 2,
232                               x_off, y_off))
233         return FALSE;
234
235     picture_set_filter (display->display, picture, pattern->filter);
236
237     if (pattern->has_component_alpha) {
238         pa.component_alpha = 1;
239         mask |= CPComponentAlpha;
240     }
241
242     if (pattern->extend != CAIRO_EXTEND_NONE) {
243         pa.repeat = extend_to_repeat (pattern->extend);
244         mask |= CPRepeat;
245     }
246
247     if (mask)
248         XRenderChangePicture (display->display, picture, mask, &pa);
249
250     return TRUE;
251 }
252
253 static cairo_surface_t *
254 render_pattern (cairo_xlib_surface_t *dst,
255                 const cairo_pattern_t *pattern,
256                 cairo_bool_t is_mask,
257                 const cairo_rectangle_int_t *extents,
258                 int *src_x, int *src_y)
259 {
260     Display *dpy = dst->display->display;
261     cairo_xlib_surface_t *src;
262     cairo_surface_t *image;
263     cairo_status_t status;
264
265     src = (cairo_xlib_surface_t *)
266         _cairo_surface_create_similar_scratch (&dst->base,
267                                                is_mask ? CAIRO_CONTENT_ALPHA : CAIRO_CONTENT_COLOR_ALPHA,
268                                                extents->width,
269                                                extents->height);
270     if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
271         cairo_surface_destroy (&src->base);
272         return None;
273     }
274
275     image = cairo_surface_map_to_image (&src->base, NULL);
276     status = _cairo_surface_offset_paint (image, extents->x, extents->y,
277                                           CAIRO_OPERATOR_SOURCE, pattern,
278                                           NULL);
279     cairo_surface_unmap_image (&src->base, image);
280     if (unlikely (status)) {
281         cairo_surface_destroy (&src->base);
282         return _cairo_surface_create_in_error (status);
283     }
284
285     src->picture = XRenderCreatePicture (dpy,
286                                          src->drawable, src->xrender_format,
287                                          0, NULL);
288
289     *src_x = -extents->x;
290     *src_y = -extents->y;
291     return &src->base;
292 }
293
294
295 static cairo_surface_t *
296 gradient_source (cairo_xlib_surface_t *dst,
297                  const cairo_gradient_pattern_t *gradient,
298                  cairo_bool_t is_mask,
299                  const cairo_rectangle_int_t *extents,
300                  int *src_x, int *src_y)
301 {
302     cairo_xlib_display_t *display = dst->display;
303     cairo_matrix_t matrix = gradient->base.matrix;
304     char buf[CAIRO_STACK_BUFFER_SIZE];
305     cairo_circle_double_t extremes[2];
306     XFixed *stops;
307     XRenderColor *colors;
308     Picture picture;
309     unsigned int i, n_stops;
310
311     /* The RENDER specification says that the inner circle has
312      * to be completely contained inside the outer one. */
313     if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL &&
314         ! _cairo_radial_pattern_focus_is_inside ((cairo_radial_pattern_t *) gradient))
315         return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
316
317     assert (gradient->n_stops > 0);
318     n_stops = MAX (gradient->n_stops, 2);
319
320     if (n_stops < sizeof (buf) / (sizeof (XFixed) + sizeof (XRenderColor)))
321     {
322         stops = (XFixed *) buf;
323     }
324     else
325     {
326         stops =
327             _cairo_malloc_ab (n_stops,
328                               sizeof (XFixed) + sizeof (XRenderColor));
329         if (unlikely (stops == NULL))
330             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
331     }
332
333     colors = (XRenderColor *) (stops + n_stops);
334     for (i = 0; i < gradient->n_stops; i++) {
335         stops[i] =
336             _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
337
338         colors[i].red   = gradient->stops[i].color.red_short;
339         colors[i].green = gradient->stops[i].color.green_short;
340         colors[i].blue  = gradient->stops[i].color.blue_short;
341         colors[i].alpha = gradient->stops[i].color.alpha_short;
342     }
343
344     /* RENDER does not support gradients with less than 2
345      * stops. If a gradient has only a single stop, duplicate
346      * it to make RENDER happy. */
347     if (gradient->n_stops == 1) {
348         stops[1] =
349             _cairo_fixed_16_16_from_double (gradient->stops[0].offset);
350
351         colors[1].red   = gradient->stops[0].color.red_short;
352         colors[1].green = gradient->stops[0].color.green_short;
353         colors[1].blue  = gradient->stops[0].color.blue_short;
354         colors[1].alpha = gradient->stops[0].color.alpha_short;
355     }
356
357 #if 0
358     /* For some weird reason the X server is sometimes getting
359      * CreateGradient requests with bad length. So far I've only seen
360      * XRenderCreateLinearGradient request with 4 stops sometime end up
361      * with length field matching 0 stops at the server side. I've
362      * looked at the libXrender code and I can't see anything that
363      * could cause this behavior. However, for some reason having a
364      * XSync call here seems to avoid the issue so I'll keep it here
365      * until it's solved.
366      */
367     XSync (display->display, False);
368 #endif
369
370     _cairo_gradient_pattern_fit_to_range (gradient, PIXMAN_MAX_INT >> 1, &matrix, extremes);
371
372     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
373         XLinearGradient grad;
374
375         grad.p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
376         grad.p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
377         grad.p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
378         grad.p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
379
380         picture = XRenderCreateLinearGradient (display->display, &grad,
381                                                stops, colors,
382                                                n_stops);
383     } else {
384         XRadialGradient grad;
385
386         grad.inner.x      = _cairo_fixed_16_16_from_double (extremes[0].center.x);
387         grad.inner.y      = _cairo_fixed_16_16_from_double (extremes[0].center.y);
388         grad.inner.radius = _cairo_fixed_16_16_from_double (extremes[0].radius);
389         grad.outer.x      = _cairo_fixed_16_16_from_double (extremes[1].center.x);
390         grad.outer.y      = _cairo_fixed_16_16_from_double (extremes[1].center.y);
391         grad.outer.radius = _cairo_fixed_16_16_from_double (extremes[1].radius);
392
393         picture = XRenderCreateRadialGradient (display->display, &grad,
394                                                stops, colors,
395                                                n_stops);
396     }
397
398     if (stops != (XFixed *) buf)
399         free (stops);
400
401     *src_x = *src_y = 0;
402     if (! picture_set_properties (display, picture,
403                                   &gradient->base, &gradient->base.matrix,
404                                   extents,
405                                   src_x, src_y)) {
406         XRenderFreePicture (display->display, picture);
407         return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
408     }
409
410     return source (dst, picture);
411 }
412
413 static cairo_surface_t *
414 color_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
415 {
416     XRenderColor xrender_color;
417
418     xrender_color.red   = color->red_short;
419     xrender_color.green = color->green_short;
420     xrender_color.blue  = color->blue_short;
421     xrender_color.alpha = color->alpha_short;
422
423     return source (dst,
424                    XRenderCreateSolidFill (dst->display->display,
425                                            &xrender_color));
426 }
427
428 static cairo_surface_t *
429 alpha_source (cairo_xlib_surface_t *dst, uint8_t alpha)
430 {
431     cairo_xlib_display_t *display = dst->display;
432
433     if (display->alpha[alpha] == NULL) {
434         cairo_color_t color;
435
436         color.red_short = color.green_short = color.blue_short = 0;
437         color.alpha_short = alpha << 8 | alpha;
438
439         display->alpha[alpha] = color_source (dst, &color);
440     }
441
442     return cairo_surface_reference (display->alpha[alpha]);
443 }
444
445 static cairo_surface_t *
446 white_source (cairo_xlib_surface_t *dst)
447 {
448     cairo_xlib_display_t *display = dst->display;
449
450     if (display->white == NULL)
451         display->white = color_source (dst, CAIRO_COLOR_WHITE);
452
453     return cairo_surface_reference (display->white);
454 }
455
456 static cairo_surface_t *
457 opaque_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
458 {
459     cairo_xlib_display_t *display = dst->display;
460     uint32_t pixel =
461         0xff000000 |
462         color->red_short   >> 8 << 16 |
463         color->green_short >> 8 << 8 |
464         color->blue_short  >> 8 << 0;
465     int i;
466
467     if (display->last_solid_cache[0].color == pixel)
468         return cairo_surface_reference (display->solid[display->last_solid_cache[0].index]);
469
470     for (i = 0; i < 16; i++) {
471         if (display->solid_cache[i] == pixel)
472             goto done;
473     }
474
475     i = hars_petruska_f54_1_random () % 16;
476     cairo_surface_destroy (display->solid[i]);
477
478     display->solid[i] = color_source (dst, color);
479     display->solid_cache[i] = pixel;
480
481 done:
482     display->last_solid_cache[0].color = pixel;
483     display->last_solid_cache[0].index = i;
484     return cairo_surface_reference (display->solid[i]);
485 }
486
487 static cairo_surface_t *
488 transparent_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
489 {
490     cairo_xlib_display_t *display = dst->display;
491     uint32_t pixel =
492         color->alpha_short >> 8 << 24 |
493         color->red_short   >> 8 << 16 |
494         color->green_short >> 8 << 8 |
495         color->blue_short  >> 8 << 0;
496     int i;
497
498     if (display->last_solid_cache[1].color == pixel) {
499     assert (display->solid[display->last_solid_cache[1].index]);
500         return cairo_surface_reference (display->solid[display->last_solid_cache[1].index]);
501     }
502
503     for (i = 16; i < 32; i++) {
504         if (display->solid_cache[i] == pixel)
505             goto done;
506     }
507
508     i = 16 + (hars_petruska_f54_1_random () % 16);
509     cairo_surface_destroy (display->solid[i]);
510
511     display->solid[i] = color_source (dst, color);
512     display->solid_cache[i] = pixel;
513
514 done:
515     display->last_solid_cache[1].color = pixel;
516     display->last_solid_cache[1].index = i;
517     assert (display->solid[i]);
518     return cairo_surface_reference (display->solid[i]);
519 }
520
521 static cairo_surface_t *
522 solid_source (cairo_xlib_surface_t *dst,
523               const cairo_color_t *color)
524 {
525     if ((color->red_short | color->green_short | color->blue_short) <= 0xff)
526         return alpha_source (dst, color->alpha_short >> 8);
527
528     if (CAIRO_ALPHA_SHORT_IS_OPAQUE (color->alpha_short)) {
529         if (color->red_short >= 0xff00 && color->green_short >= 0xff00 && color->blue_short >= 0xff00)
530             return white_source (dst);
531
532         return opaque_source (dst, color);
533     } else
534         return transparent_source (dst, color);
535 }
536
537 static cairo_surface_t *
538 embedded_source (cairo_xlib_surface_t *dst,
539                  const cairo_surface_pattern_t *pattern,
540                  cairo_xlib_surface_t *src,
541                  const cairo_rectangle_int_t *extents,
542                  int *src_x, int *src_y)
543 {
544     cairo_xlib_source_t *source;
545     Display *dpy = dst->display->display;
546     cairo_int_status_t status;
547     XTransform xtransform;
548     XRenderPictureAttributes pa;
549     unsigned mask = 0;
550
551     /* As these are frequent and meant to be fast, we track pictures for
552      * native surface and minimise update requests.
553      */
554     source = &src->embedded_source;
555     if (source->picture == None) {
556         XRenderPictureAttributes pa;
557
558         _cairo_surface_init (&source->base,
559                              &cairo_xlib_source_backend,
560                              NULL, /* device */
561                              CAIRO_CONTENT_COLOR_ALPHA);
562
563         pa.subwindow_mode = IncludeInferiors;
564         source->picture = XRenderCreatePicture (dpy,
565                                                 src->drawable,
566                                                 src->xrender_format,
567                                                 CPSubwindowMode, &pa);
568
569         source->has_component_alpha = 0;
570         source->has_matrix = 0;
571         source->filter = CAIRO_FILTER_NEAREST;
572         source->extend = CAIRO_EXTEND_NONE;
573     }
574
575     status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
576                                                     pattern->base.filter,
577                                                     extents->x + extents->width / 2,
578                                                     extents->y + extents->height / 2,
579                                                     (pixman_transform_t *)&xtransform,
580                                                     src_x, src_y);
581
582     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
583         if (source->has_matrix) {
584             source->has_matrix = 0;
585             memcpy (&xtransform, &identity, sizeof (identity));
586             status = CAIRO_INT_STATUS_SUCCESS;
587         }
588     } else
589         source->has_matrix = 1;
590     if (status == CAIRO_INT_STATUS_SUCCESS)
591         XRenderSetPictureTransform (dpy, source->picture, &xtransform);
592
593     if (source->filter != pattern->base.filter) {
594         picture_set_filter (dpy, source->picture, pattern->base.filter);
595         source->filter = pattern->base.filter;
596     }
597
598     if (source->has_component_alpha != pattern->base.has_component_alpha) {
599         pa.component_alpha = pattern->base.has_component_alpha;
600         mask |= CPComponentAlpha;
601         source->has_component_alpha = pattern->base.has_component_alpha;
602     }
603
604     if (source->extend != pattern->base.extend) {
605         pa.repeat = extend_to_repeat (pattern->base.extend);
606         mask |= CPRepeat;
607         source->extend = pattern->base.extend;
608     }
609
610     if (mask)
611         XRenderChangePicture (dpy, source->picture, mask, &pa);
612
613     return cairo_surface_reference (&source->base);
614 }
615
616 static cairo_surface_t *
617 subsurface_source (cairo_xlib_surface_t *dst,
618                    const cairo_surface_pattern_t *pattern,
619                    cairo_bool_t is_mask,
620                    const cairo_rectangle_int_t *extents,
621                    const cairo_rectangle_int_t *sample,
622                    int *src_x, int *src_y)
623 {
624     cairo_surface_subsurface_t *sub;
625     cairo_xlib_surface_t *src;
626     cairo_xlib_source_t *source;
627     Display *dpy = dst->display->display;
628     cairo_int_status_t status;
629     cairo_surface_pattern_t local_pattern;
630     XTransform xtransform;
631     XRenderPictureAttributes pa;
632     unsigned mask = 0;
633
634     sub = (cairo_surface_subsurface_t *) pattern->surface;
635
636     if (sample->x >= 0 && sample->y >= 0 &&
637         sample->x + sample->width  <= sub->extents.width &&
638         sample->y + sample->height <= sub->extents.height)
639     {
640         src = (cairo_xlib_surface_t *) sub->target;
641
642         if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
643             _cairo_matrix_is_translation (&pattern->base.matrix))
644         {
645             *src_x += pattern->base.matrix.x0 + sub->extents.x;
646             *src_y += pattern->base.matrix.y0 + sub->extents.y;
647
648             _cairo_xlib_surface_ensure_picture (src);
649             return cairo_surface_reference (&src->base);
650         }
651         else
652         {
653             cairo_surface_pattern_t local_pattern = *pattern;
654             local_pattern.base.matrix.x0 += sub->extents.x;
655             local_pattern.base.matrix.y0 += sub->extents.y;
656             local_pattern.base.extend = CAIRO_EXTEND_NONE;
657             return embedded_source (dst, &local_pattern, src, extents,
658                                     src_x, src_y);
659         }
660     }
661
662     if (sub->snapshot && sub->snapshot->type == CAIRO_SURFACE_TYPE_XLIB) {
663         src = (cairo_xlib_surface_t *) cairo_surface_reference (sub->snapshot);
664         source = &src->embedded_source;
665     } else {
666         src = (cairo_xlib_surface_t *)
667             _cairo_surface_create_similar_scratch (&dst->base,
668                                                    sub->base.content,
669                                                    sub->extents.width,
670                                                    sub->extents.height);
671         if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
672             cairo_surface_destroy (&src->base);
673             return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
674         }
675
676         _cairo_pattern_init_for_surface (&local_pattern, sub->target);
677         cairo_matrix_init_translate (&local_pattern.base.matrix,
678                                      sub->extents.x, sub->extents.y);
679         local_pattern.base.filter = CAIRO_FILTER_NEAREST;
680         status = _cairo_surface_paint (&src->base,
681                                        CAIRO_OPERATOR_SOURCE,
682                                        &local_pattern.base,
683                                        NULL);
684         _cairo_pattern_fini (&local_pattern.base);
685
686         if (unlikely (status)) {
687             cairo_surface_destroy (&src->base);
688             return _cairo_surface_create_in_error (status);
689         }
690
691         _cairo_xlib_surface_ensure_picture (src);
692         _cairo_surface_subsurface_set_snapshot (&sub->base, &src->base);
693
694         source = &src->embedded_source;
695         source->has_component_alpha = 0;
696         source->has_matrix = 0;
697         source->filter = CAIRO_FILTER_NEAREST;
698         source->extend = CAIRO_EXTEND_NONE;
699     }
700
701     status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
702                                                     pattern->base.filter,
703                                                     extents->x + extents->width / 2,
704                                                     extents->y + extents->height / 2,
705                                                     (pixman_transform_t *)&xtransform,
706                                                     src_x, src_y);
707     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
708         if (source->has_matrix) {
709             source->has_matrix = 0;
710             memcpy (&xtransform, &identity, sizeof (identity));
711             status = CAIRO_INT_STATUS_SUCCESS;
712         }
713     } else
714         source->has_matrix = 1;
715     if (status == CAIRO_INT_STATUS_SUCCESS)
716         XRenderSetPictureTransform (dpy, src->picture, &xtransform);
717
718     if (source->filter != pattern->base.filter) {
719         picture_set_filter (dpy, src->picture, pattern->base.filter);
720         source->filter = pattern->base.filter;
721     }
722
723     if (source->has_component_alpha != pattern->base.has_component_alpha) {
724         pa.component_alpha = pattern->base.has_component_alpha;
725         mask |= CPComponentAlpha;
726         source->has_component_alpha = pattern->base.has_component_alpha;
727     }
728
729     if (source->extend != pattern->base.extend) {
730         pa.repeat = extend_to_repeat (pattern->base.extend);
731         mask |= CPRepeat;
732         source->extend = pattern->base.extend;
733     }
734
735     if (mask)
736         XRenderChangePicture (dpy, src->picture, mask, &pa);
737
738     return &src->base;
739 }
740
741 static cairo_surface_t *
742 native_source (cairo_xlib_surface_t *dst,
743                const cairo_surface_pattern_t *pattern,
744                cairo_bool_t is_mask,
745                const cairo_rectangle_int_t *extents,
746                const cairo_rectangle_int_t *sample,
747                int *src_x, int *src_y)
748 {
749     cairo_xlib_surface_t *src = (cairo_xlib_surface_t *) pattern->surface;
750
751     if (_cairo_surface_is_subsurface (pattern->surface))
752         return subsurface_source (dst, pattern, is_mask,
753                                   extents, sample,
754                                   src_x, src_y);
755
756     src = unwrap_source (pattern);
757
758     if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
759         sample->x >= 0 && sample->y >= 0 &&
760         sample->x + sample->width  <= src->width &&
761         sample->y + sample->height <= src->height &&
762         _cairo_matrix_is_translation (&pattern->base.matrix))
763     {
764         *src_x += pattern->base.matrix.x0;
765         *src_y += pattern->base.matrix.y0;
766         _cairo_xlib_surface_ensure_picture (src);
767         return cairo_surface_reference (&src->base);
768     }
769
770     return embedded_source (dst, pattern, src, extents, src_x, src_y);
771 }
772
773 #if 0
774 /* It is general quicker if we let the application choose which images
775  * to cache for itself and only upload the fragments required for this
776  * operation.
777  */
778 static cairo_surface_t *
779 image_source (cairo_xlib_surface_t *dst,
780               const cairo_surface_pattern_t *pattern,
781               const cairo_rectangle_int_t *extents,
782               int *src_x, int *src_y)
783 {
784     cairo_image_surface_t *src = (cairo_image_surface_t *) pattern->surface;
785     cairo_xlib_surface_t *snapshot;
786     cairo_surface_pattern_t local_pattern;
787     cairo_status_t status;
788
789     snapshot = (cairo_xlib_surface_t *)
790         _cairo_surface_has_snapshot (&src->base, dst->base.backend);
791     if (snapshot == NULL || snapshot->screen != dst->screen) {
792         if (snapshot)
793             _cairo_surface_detach_snapshot (&snapshot->base);
794
795         snapshot = (cairo_xlib_surface_t *)
796             _cairo_surface_create_similar_scratch (&dst->base,
797                                                    src->base.content,
798                                                    src->width,
799                                                    src->height);
800         if (snapshot->base.type != CAIRO_SURFACE_TYPE_XLIB) {
801             cairo_surface_destroy (&snapshot->base);
802             return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
803         }
804
805         status = _cairo_xlib_surface_draw_image (snapshot, src,
806                                                  0, 0,
807                                                  src->width, src->height,
808                                                  0, 0);
809         if (unlikely (status)) {
810             cairo_surface_destroy (&snapshot->base);
811             return _cairo_surface_create_in_error (status);
812         }
813
814         _cairo_surface_attach_snapshot (&src->base,
815                                         &snapshot->base,
816                                         cairo_surface_finish);
817
818         /* reference remains held by the snapshot from image */
819         cairo_surface_destroy (&snapshot->base);
820     }
821
822     local_pattern = *pattern;
823     local_pattern.surface = &snapshot->base;
824
825     return native_source (dst, &local_pattern, extents, src_x, src_y);
826 }
827 #endif
828
829 static cairo_surface_t *
830 recording_pattern_get_surface (const cairo_pattern_t *pattern)
831 {
832     cairo_surface_t *surface;
833
834     surface = ((const cairo_surface_pattern_t *) pattern)->surface;
835     if (_cairo_surface_is_paginated (surface))
836         surface = _cairo_paginated_surface_get_recording (surface);
837     if (_cairo_surface_is_snapshot (surface))
838         surface = _cairo_surface_snapshot_get_target (surface);
839     return surface;
840 }
841
842 static cairo_surface_t *
843 record_source (cairo_xlib_surface_t *dst,
844                const cairo_surface_pattern_t *pattern,
845                cairo_bool_t is_mask,
846                const cairo_rectangle_int_t *extents,
847                const cairo_rectangle_int_t *sample,
848                int *src_x, int *src_y)
849 {
850     cairo_xlib_surface_t *src;
851     cairo_matrix_t matrix, m;
852     cairo_status_t status;
853     cairo_rectangle_int_t upload, limit;
854
855     upload = *sample;
856     if (_cairo_surface_get_extents (pattern->surface, &limit) &&
857         ! _cairo_rectangle_intersect (&upload, &limit))
858     {
859         if (pattern->base.extend == CAIRO_EXTEND_NONE)
860             return alpha_source (dst, 0);
861
862         upload = limit;
863     }
864
865     src = (cairo_xlib_surface_t *)
866         _cairo_surface_create_similar_scratch (&dst->base,
867                                                pattern->surface->content,
868                                                upload.width,
869                                                upload.height);
870     if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
871         cairo_surface_destroy (&src->base);
872         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
873     }
874
875     cairo_matrix_init_translate (&matrix, upload.x, upload.y);
876     status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (&pattern->base),
877                                                         &matrix, &src->base,
878                                                         NULL);
879     if (unlikely (status)) {
880         cairo_surface_destroy (&src->base);
881         return _cairo_surface_create_in_error (status);
882     }
883
884     matrix = pattern->base.matrix;
885     if (upload.x | upload.y) {
886         cairo_matrix_init_translate (&m, -upload.x, -upload.y);
887         cairo_matrix_multiply (&matrix, &matrix, &m);
888     }
889
890     _cairo_xlib_surface_ensure_picture (src);
891     if (! picture_set_properties (src->display, src->picture,
892                                   &pattern->base, &matrix, extents,
893                                   src_x, src_y))
894     {
895         cairo_surface_destroy (&src->base);
896         return render_pattern (dst, &pattern->base, is_mask,
897                                extents, src_x, src_y);
898     }
899
900     return &src->base;
901 }
902
903 static cairo_surface_t *
904 surface_source (cairo_xlib_surface_t *dst,
905                 const cairo_surface_pattern_t *pattern,
906                 cairo_bool_t is_mask,
907                 const cairo_rectangle_int_t *extents,
908                 const cairo_rectangle_int_t *sample,
909                 int *src_x, int *src_y)
910 {
911     cairo_xlib_surface_t *src;
912     cairo_surface_t *image;
913     cairo_surface_pattern_t local_pattern;
914     cairo_status_t status;
915     cairo_rectangle_int_t upload, limit;
916     cairo_matrix_t m;
917
918     upload = *sample;
919     if (_cairo_surface_get_extents (pattern->surface, &limit) &&
920         ! _cairo_rectangle_intersect (&upload, &limit))
921     {
922         if (pattern->base.extend == CAIRO_EXTEND_NONE)
923             return alpha_source (dst, 0);
924
925         upload = limit;
926     }
927
928     src = (cairo_xlib_surface_t *)
929         _cairo_surface_create_similar_scratch (&dst->base,
930                                                pattern->surface->content,
931                                                upload.width,
932                                                upload.height);
933     if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
934         cairo_surface_destroy (&src->base);
935         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
936     }
937
938     _cairo_pattern_init_for_surface (&local_pattern, pattern->surface);
939     cairo_matrix_init_translate (&local_pattern.base.matrix,
940                                  upload.x, upload.y);
941
942     image = cairo_surface_map_to_image (&src->base, NULL);
943     status = _cairo_surface_paint (image,
944                                    CAIRO_OPERATOR_SOURCE,
945                                    &local_pattern.base,
946                                    NULL);
947     cairo_surface_unmap_image (&src->base, image);
948     _cairo_pattern_fini (&local_pattern.base);
949
950     if (unlikely (status)) {
951         cairo_surface_destroy (&src->base);
952         return _cairo_surface_create_in_error (status);
953     }
954
955     local_pattern.base.matrix = pattern->base.matrix;
956     if (upload.x | upload.y) {
957         cairo_matrix_init_translate (&m, -upload.x, -upload.y);
958         cairo_matrix_multiply (&local_pattern.base.matrix,
959                                &local_pattern.base.matrix,
960                                &m);
961     }
962
963     *src_x = *src_y = 0;
964     _cairo_xlib_surface_ensure_picture (src);
965     if (! picture_set_properties (src->display,
966                                   src->picture,
967                                   &pattern->base,
968                                   &local_pattern.base.matrix,
969                                   extents,
970                                   src_x, src_y))
971     {
972         cairo_surface_destroy (&src->base);
973         return render_pattern (dst, &pattern->base,
974                                is_mask, extents,
975                                src_x, src_y);
976     }
977
978     return &src->base;
979 }
980
981 static cairo_bool_t
982 pattern_is_supported (cairo_xlib_display_t *display,
983                       const cairo_pattern_t *pattern)
984 {
985     if (pattern->type == CAIRO_PATTERN_TYPE_MESH)
986         return FALSE;
987
988     if (display->buggy_pad_reflect) {
989         if (pattern->extend == CAIRO_EXTEND_REPEAT || pattern->extend == CAIRO_EXTEND_PAD)
990             return FALSE;
991     }
992
993     if (display->buggy_gradients) {
994         if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
995             return FALSE;
996     }
997
998     if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display)) {
999         if (!_cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
1000             return FALSE;
1001     }
1002
1003     if (! CAIRO_RENDER_HAS_FILTERS (display)) {
1004             /* No filters implies no transforms, so we optimise away BILINEAR */
1005     }
1006
1007     return TRUE;
1008 }
1009 cairo_surface_t *
1010 _cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst,
1011                                        const cairo_pattern_t *pattern,
1012                                        cairo_bool_t is_mask,
1013                                        const cairo_rectangle_int_t *extents,
1014                                        const cairo_rectangle_int_t *sample,
1015                                        int *src_x, int *src_y)
1016 {
1017     cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)_dst;
1018
1019     *src_x = *src_y = 0;
1020
1021     if (pattern == NULL || pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1022         if (pattern == NULL)
1023             pattern = &_cairo_pattern_white.base;
1024
1025         return solid_source (dst, &((cairo_solid_pattern_t *)pattern)->color);
1026     }
1027
1028     if (pattern_is_supported (dst->display, pattern)) {
1029         if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
1030             cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *)pattern;
1031             if (spattern->surface->type == CAIRO_SURFACE_TYPE_XLIB &&
1032                 _cairo_xlib_surface_same_screen (dst,
1033                                                  unwrap_source (spattern)))
1034                 return native_source (dst, spattern, is_mask,
1035                                       extents, sample,
1036                                       src_x, src_y);
1037
1038             if (spattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
1039                 return record_source (dst, spattern, is_mask,
1040                                       extents, sample,
1041                                       src_x, src_y);
1042 #if 0
1043             if (spattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE)
1044                 return image_source (dst, spattern, extents, src_x, src_y);
1045 #endif
1046
1047             return surface_source (dst, spattern, is_mask,
1048                                    extents, sample,
1049                                    src_x, src_y);
1050         }
1051
1052         if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1053             pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
1054         {
1055             cairo_gradient_pattern_t *gpattern = (cairo_gradient_pattern_t *)pattern;
1056             return gradient_source (dst, gpattern, is_mask, extents, src_x, src_y);
1057         }
1058     }
1059
1060     return render_pattern (dst, pattern, is_mask, extents, src_x, src_y);
1061 }
1062
1063 #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */