tizen 2.3.1 release
[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-inline.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     if (source->pixmap)
75             XFreePixmap (source->dpy, source->pixmap);
76     return CAIRO_STATUS_SUCCESS;
77 }
78
79 static const cairo_surface_backend_t cairo_xlib_source_backend = {
80     CAIRO_SURFACE_TYPE_XLIB,
81     _cairo_xlib_source_finish,
82     NULL, /* read-only wrapper */
83 };
84
85 static cairo_status_t
86 _cairo_xlib_proxy_finish (void *abstract_surface)
87 {
88     cairo_xlib_proxy_t *proxy = abstract_surface;
89
90     _cairo_xlib_shm_surface_mark_active (proxy->owner);
91     XRenderFreePicture (proxy->source.dpy, proxy->source.picture);
92     if (proxy->source.pixmap)
93             XFreePixmap (proxy->source.dpy, proxy->source.pixmap);
94     cairo_surface_destroy (proxy->owner);
95     return CAIRO_STATUS_SUCCESS;
96 }
97
98 static const cairo_surface_backend_t cairo_xlib_proxy_backend = {
99     CAIRO_SURFACE_TYPE_XLIB,
100     _cairo_xlib_proxy_finish,
101     NULL, /* read-only wrapper */
102 };
103
104 static cairo_surface_t *
105 source (cairo_xlib_surface_t *dst, Picture picture, Pixmap pixmap)
106 {
107     cairo_xlib_source_t *source;
108
109     if (picture == None)
110         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
111
112     source = malloc (sizeof (*source));
113     if (unlikely (source == NULL)) {
114         XRenderFreePicture (dst->display->display, picture);
115         if (pixmap)
116                 XFreePixmap (dst->display->display, pixmap);
117         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
118     }
119
120     _cairo_surface_init (&source->base,
121                          &cairo_xlib_source_backend,
122                          NULL, /* device */
123                          CAIRO_CONTENT_COLOR_ALPHA);
124
125     /* The source exists only within an operation */
126     source->picture = picture;
127     source->pixmap = pixmap;
128     source->dpy = dst->display->display;
129
130     return &source->base;
131 }
132
133 static uint32_t
134 hars_petruska_f54_1_random (void)
135 {
136 #define rol(x,k) ((x << k) | (x >> (32-k)))
137     static uint32_t x;
138     return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
139 #undef rol
140 }
141
142 static const XTransform identity = {
143     {
144         { 1 << 16, 0x00000, 0x00000 },
145         { 0x00000, 1 << 16, 0x00000 },
146         { 0x00000, 0x00000, 1 << 16 },
147     }
148 };
149
150 static cairo_bool_t
151 picture_set_matrix (cairo_xlib_display_t *display,
152                     Picture picture,
153                     const cairo_matrix_t *matrix,
154                     cairo_filter_t        filter,
155                     double                xc,
156                     double                yc,
157                     int                  *x_offset,
158                     int                  *y_offset)
159 {
160     XTransform xtransform;
161     pixman_transform_t *pixman_transform;
162     cairo_int_status_t status;
163
164     /* Casting between pixman_transform_t and XTransform is safe because
165      * they happen to be the exact same type.
166      */
167     pixman_transform = (pixman_transform_t *) &xtransform;
168     status = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
169                                                     pixman_transform,
170                                                     x_offset, y_offset);
171     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
172         return TRUE;
173     if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
174         return FALSE;
175
176     if (memcmp (&xtransform, &identity, sizeof (XTransform)) == 0)
177         return TRUE;
178
179     /* a late check in case we perturb the matrix too far */
180     if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display))
181         return FALSE;
182
183     XRenderSetPictureTransform (display->display, picture, &xtransform);
184     return TRUE;
185 }
186
187 static cairo_status_t
188 picture_set_filter (Display *dpy,
189                     Picture picture,
190                     cairo_filter_t filter)
191 {
192     const char *render_filter;
193
194     switch (filter) {
195     case CAIRO_FILTER_FAST:
196         render_filter = FilterFast;
197         break;
198     case CAIRO_FILTER_GOOD:
199         render_filter = FilterGood;
200         break;
201     case CAIRO_FILTER_BEST:
202         render_filter = FilterBest;
203         break;
204     case CAIRO_FILTER_NEAREST:
205         render_filter = FilterNearest;
206         break;
207     case CAIRO_FILTER_BILINEAR:
208         render_filter = FilterBilinear;
209         break;
210     case CAIRO_FILTER_GAUSSIAN:
211         /* XXX: The GAUSSIAN value has no implementation in cairo
212          * whatsoever, so it was really a mistake to have it in the
213          * API. We could fix this by officially deprecating it, or
214          * else inventing semantics and providing an actual
215          * implementation for it. */
216     default:
217         render_filter = FilterBest;
218         break;
219     }
220
221     XRenderSetPictureFilter (dpy, picture, (char *) render_filter, NULL, 0);
222     return CAIRO_STATUS_SUCCESS;
223 }
224
225 static int
226 extend_to_repeat (cairo_extend_t extend)
227 {
228     switch (extend) {
229     default:
230         ASSERT_NOT_REACHED;
231     case CAIRO_EXTEND_NONE:
232         return RepeatNone;
233     case CAIRO_EXTEND_REPEAT:
234         return RepeatNormal;
235     case CAIRO_EXTEND_REFLECT:
236         return RepeatReflect;
237     case CAIRO_EXTEND_PAD:
238         return RepeatPad;
239     }
240 }
241
242 static cairo_bool_t
243 picture_set_properties (cairo_xlib_display_t *display,
244                         Picture picture,
245                         const cairo_pattern_t *pattern,
246                         const cairo_matrix_t *matrix,
247                         const cairo_rectangle_int_t *extents,
248                         int *x_off, int *y_off)
249 {
250     XRenderPictureAttributes pa;
251     int mask = 0;
252
253     if (! picture_set_matrix (display, picture, matrix, pattern->filter,
254                               extents->x + extents->width / 2,
255                               extents->y + extents->height / 2,
256                               x_off, y_off))
257         return FALSE;
258
259     picture_set_filter (display->display, picture, pattern->filter);
260
261     if (pattern->has_component_alpha) {
262         pa.component_alpha = 1;
263         mask |= CPComponentAlpha;
264     }
265
266     if (pattern->extend != CAIRO_EXTEND_NONE) {
267         pa.repeat = extend_to_repeat (pattern->extend);
268         mask |= CPRepeat;
269     }
270
271     if (mask)
272         XRenderChangePicture (display->display, picture, mask, &pa);
273
274     return TRUE;
275 }
276
277 static cairo_surface_t *
278 render_pattern (cairo_xlib_surface_t *dst,
279                 const cairo_pattern_t *pattern,
280                 cairo_bool_t is_mask,
281                 const cairo_rectangle_int_t *extents,
282                 int *src_x, int *src_y)
283 {
284     Display *dpy = dst->display->display;
285     cairo_xlib_surface_t *src;
286     cairo_image_surface_t *image;
287     cairo_status_t status;
288     cairo_rectangle_int_t map_extents;
289
290     src = (cairo_xlib_surface_t *)
291         _cairo_surface_create_similar_scratch (&dst->base,
292                                                is_mask ? CAIRO_CONTENT_ALPHA : CAIRO_CONTENT_COLOR_ALPHA,
293                                                extents->width,
294                                                extents->height);
295     if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
296         cairo_surface_destroy (&src->base);
297         return None;
298     }
299
300     map_extents = *extents;
301     map_extents.x = map_extents.y = 0;
302
303     image = _cairo_surface_map_to_image (&src->base, &map_extents);
304     status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y,
305                                           CAIRO_OPERATOR_SOURCE, pattern,
306                                           NULL);
307     status = _cairo_surface_unmap_image (&src->base, image);
308     if (unlikely (status)) {
309         cairo_surface_destroy (&src->base);
310         return _cairo_surface_create_in_error (status);
311     }
312
313     status = _cairo_xlib_surface_put_shm (src);
314     if (unlikely (status)) {
315         cairo_surface_destroy (&src->base);
316         return _cairo_surface_create_in_error (status);
317     }
318
319     src->picture = XRenderCreatePicture (dpy,
320                                          src->drawable, src->xrender_format,
321                                          0, NULL);
322
323     *src_x = -extents->x;
324     *src_y = -extents->y;
325     return &src->base;
326 }
327
328 static cairo_surface_t *
329 gradient_source (cairo_xlib_surface_t *dst,
330                  const cairo_gradient_pattern_t *gradient,
331                  cairo_bool_t is_mask,
332                  const cairo_rectangle_int_t *extents,
333                  int *src_x, int *src_y)
334 {
335     cairo_xlib_display_t *display = dst->display;
336     cairo_matrix_t matrix = gradient->base.matrix;
337     char buf[CAIRO_STACK_BUFFER_SIZE];
338     cairo_circle_double_t extremes[2];
339     XFixed *stops;
340     XRenderColor *colors;
341     Picture picture;
342     unsigned int i, n_stops;
343
344     /* The RENDER specification says that the inner circle has
345      * to be completely contained inside the outer one. */
346     if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL &&
347         ! _cairo_radial_pattern_focus_is_inside ((cairo_radial_pattern_t *) gradient))
348         return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
349
350     assert (gradient->n_stops > 0);
351     n_stops = MAX (gradient->n_stops, 2);
352
353     if (n_stops < sizeof (buf) / (sizeof (XFixed) + sizeof (XRenderColor)))
354     {
355         stops = (XFixed *) buf;
356     }
357     else
358     {
359         stops =
360             _cairo_malloc_ab (n_stops,
361                               sizeof (XFixed) + sizeof (XRenderColor));
362         if (unlikely (stops == NULL))
363             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
364     }
365
366     colors = (XRenderColor *) (stops + n_stops);
367     for (i = 0; i < gradient->n_stops; i++) {
368         stops[i] =
369             _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
370
371         colors[i].red   = gradient->stops[i].color.red_short;
372         colors[i].green = gradient->stops[i].color.green_short;
373         colors[i].blue  = gradient->stops[i].color.blue_short;
374         colors[i].alpha = gradient->stops[i].color.alpha_short;
375     }
376
377     /* RENDER does not support gradients with less than 2
378      * stops. If a gradient has only a single stop, duplicate
379      * it to make RENDER happy. */
380     if (gradient->n_stops == 1) {
381         stops[1] =
382             _cairo_fixed_16_16_from_double (gradient->stops[0].offset);
383
384         colors[1].red   = gradient->stops[0].color.red_short;
385         colors[1].green = gradient->stops[0].color.green_short;
386         colors[1].blue  = gradient->stops[0].color.blue_short;
387         colors[1].alpha = gradient->stops[0].color.alpha_short;
388     }
389
390 #if 0
391     /* For some weird reason the X server is sometimes getting
392      * CreateGradient requests with bad length. So far I've only seen
393      * XRenderCreateLinearGradient request with 4 stops sometime end up
394      * with length field matching 0 stops at the server side. I've
395      * looked at the libXrender code and I can't see anything that
396      * could cause this behavior. However, for some reason having a
397      * XSync call here seems to avoid the issue so I'll keep it here
398      * until it's solved.
399      */
400     XSync (display->display, False);
401 #endif
402
403     _cairo_gradient_pattern_fit_to_range (gradient, PIXMAN_MAX_INT >> 1, &matrix, extremes);
404
405     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
406         XLinearGradient grad;
407
408         grad.p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
409         grad.p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
410         grad.p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
411         grad.p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
412
413         picture = XRenderCreateLinearGradient (display->display, &grad,
414                                                stops, colors,
415                                                n_stops);
416     } else {
417         XRadialGradient grad;
418
419         grad.inner.x      = _cairo_fixed_16_16_from_double (extremes[0].center.x);
420         grad.inner.y      = _cairo_fixed_16_16_from_double (extremes[0].center.y);
421         grad.inner.radius = _cairo_fixed_16_16_from_double (extremes[0].radius);
422         grad.outer.x      = _cairo_fixed_16_16_from_double (extremes[1].center.x);
423         grad.outer.y      = _cairo_fixed_16_16_from_double (extremes[1].center.y);
424         grad.outer.radius = _cairo_fixed_16_16_from_double (extremes[1].radius);
425
426         picture = XRenderCreateRadialGradient (display->display, &grad,
427                                                stops, colors,
428                                                n_stops);
429     }
430
431     if (stops != (XFixed *) buf)
432         free (stops);
433
434     *src_x = *src_y = 0;
435     if (! picture_set_properties (display, picture,
436                                   &gradient->base, &gradient->base.matrix,
437                                   extents,
438                                   src_x, src_y)) {
439         XRenderFreePicture (display->display, picture);
440         return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
441     }
442
443     return source (dst, picture, None);
444 }
445
446 static cairo_surface_t *
447 color_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
448 {
449     Display *dpy = dst->display->display;
450     XRenderColor xcolor;
451     Picture picture;
452     Pixmap pixmap = None;
453
454     xcolor.red   = color->red_short;
455     xcolor.green = color->green_short;
456     xcolor.blue  = color->blue_short;
457     xcolor.alpha = color->alpha_short;
458
459     if (CAIRO_RENDER_HAS_GRADIENTS(dst->display)) {
460         picture = XRenderCreateSolidFill (dpy, &xcolor);
461     } else {
462         XRenderPictureAttributes pa;
463         int mask = 0;
464
465         pa.repeat = RepeatNormal;
466         mask |= CPRepeat;
467
468         pixmap = XCreatePixmap (dpy, dst->drawable, 1, 1, 32);
469         picture = XRenderCreatePicture (dpy, pixmap,
470                                         _cairo_xlib_display_get_xrender_format (dst->display, CAIRO_FORMAT_ARGB32),
471                                         mask, &pa);
472
473         if (CAIRO_RENDER_HAS_FILL_RECTANGLES(dst->display)) {
474             XRectangle r = { 0, 0, 1, 1};
475             XRenderFillRectangles (dpy, PictOpSrc, picture, &xcolor, &r, 1);
476         } else {
477             XGCValues gcv;
478             GC gc;
479
480             gc = _cairo_xlib_screen_get_gc (dst->display, dst->screen,
481                                             32, pixmap);
482             if (unlikely (gc == NULL)) {
483                 XFreePixmap (dpy, pixmap);
484                 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
485             }
486
487             gcv.foreground = 0;
488             gcv.foreground |= color->alpha_short >> 8 << 24;
489             gcv.foreground |= color->red_short   >> 8 << 16;
490             gcv.foreground |= color->green_short >> 8 << 8;
491             gcv.foreground |= color->blue_short  >> 8 << 0;
492             gcv.fill_style = FillSolid;
493
494             XChangeGC (dpy, gc, GCFillStyle | GCForeground, &gcv);
495             XFillRectangle (dpy, pixmap, gc, 0, 0, 1, 1);
496
497             _cairo_xlib_screen_put_gc (dst->display, dst->screen, 32, gc);
498         }
499     }
500
501     return source (dst, picture, pixmap);
502 }
503
504 static cairo_surface_t *
505 alpha_source (cairo_xlib_surface_t *dst, uint8_t alpha)
506 {
507     cairo_xlib_display_t *display = dst->display;
508
509     if (display->alpha[alpha] == NULL) {
510         cairo_color_t color;
511
512         color.red_short = color.green_short = color.blue_short = 0;
513         color.alpha_short = alpha << 8 | alpha;
514
515         display->alpha[alpha] = color_source (dst, &color);
516     }
517
518     return cairo_surface_reference (display->alpha[alpha]);
519 }
520
521 static cairo_surface_t *
522 white_source (cairo_xlib_surface_t *dst)
523 {
524     cairo_xlib_display_t *display = dst->display;
525
526     if (display->white == NULL)
527         display->white = color_source (dst, CAIRO_COLOR_WHITE);
528
529     return cairo_surface_reference (display->white);
530 }
531
532 static cairo_surface_t *
533 opaque_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
534 {
535     cairo_xlib_display_t *display = dst->display;
536     uint32_t pixel =
537         0xff000000 |
538         color->red_short   >> 8 << 16 |
539         color->green_short >> 8 << 8 |
540         color->blue_short  >> 8 << 0;
541     int i;
542
543     if (display->last_solid_cache[0].color == pixel)
544         return cairo_surface_reference (display->solid[display->last_solid_cache[0].index]);
545
546     for (i = 0; i < 16; i++) {
547         if (display->solid_cache[i] == pixel)
548             goto done;
549     }
550
551     i = hars_petruska_f54_1_random () % 16;
552     cairo_surface_destroy (display->solid[i]);
553
554     display->solid[i] = color_source (dst, color);
555     display->solid_cache[i] = pixel;
556
557 done:
558     display->last_solid_cache[0].color = pixel;
559     display->last_solid_cache[0].index = i;
560     return cairo_surface_reference (display->solid[i]);
561 }
562
563 static cairo_surface_t *
564 transparent_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
565 {
566     cairo_xlib_display_t *display = dst->display;
567     uint32_t pixel =
568         color->alpha_short >> 8 << 24 |
569         color->red_short   >> 8 << 16 |
570         color->green_short >> 8 << 8 |
571         color->blue_short  >> 8 << 0;
572     int i;
573
574     if (display->last_solid_cache[1].color == pixel) {
575     assert (display->solid[display->last_solid_cache[1].index]);
576         return cairo_surface_reference (display->solid[display->last_solid_cache[1].index]);
577     }
578
579     for (i = 16; i < 32; i++) {
580         if (display->solid_cache[i] == pixel)
581             goto done;
582     }
583
584     i = 16 + (hars_petruska_f54_1_random () % 16);
585     cairo_surface_destroy (display->solid[i]);
586
587     display->solid[i] = color_source (dst, color);
588     display->solid_cache[i] = pixel;
589
590 done:
591     display->last_solid_cache[1].color = pixel;
592     display->last_solid_cache[1].index = i;
593     assert (display->solid[i]);
594     return cairo_surface_reference (display->solid[i]);
595 }
596
597 static cairo_surface_t *
598 solid_source (cairo_xlib_surface_t *dst,
599               const cairo_color_t *color)
600 {
601     if ((color->red_short | color->green_short | color->blue_short) <= 0xff)
602         return alpha_source (dst, color->alpha_short >> 8);
603
604     if (CAIRO_ALPHA_SHORT_IS_OPAQUE (color->alpha_short)) {
605         if (color->red_short >= 0xff00 && color->green_short >= 0xff00 && color->blue_short >= 0xff00)
606             return white_source (dst);
607
608         return opaque_source (dst, color);
609     } else
610         return transparent_source (dst, color);
611 }
612
613 static cairo_xlib_source_t *init_source (cairo_xlib_surface_t *dst,
614                                          cairo_xlib_surface_t *src)
615 {
616     Display *dpy = dst->display->display;
617     cairo_xlib_source_t *source = &src->embedded_source;
618
619     /* As these are frequent and meant to be fast, we track pictures for
620      * native surface and minimise update requests.
621      */
622     if (source->picture == None) {
623         XRenderPictureAttributes pa;
624
625         _cairo_surface_init (&source->base,
626                              &cairo_xlib_source_backend,
627                              NULL, /* device */
628                              CAIRO_CONTENT_COLOR_ALPHA);
629
630         pa.subwindow_mode = IncludeInferiors;
631         source->picture = XRenderCreatePicture (dpy,
632                                                 src->drawable,
633                                                 src->xrender_format,
634                                                 CPSubwindowMode, &pa);
635
636         source->has_component_alpha = 0;
637         source->has_matrix = 0;
638         source->filter = CAIRO_FILTER_NEAREST;
639         source->extend = CAIRO_EXTEND_NONE;
640     }
641
642     return (cairo_xlib_source_t *) cairo_surface_reference (&source->base);
643 }
644
645 static cairo_surface_t *
646 embedded_source (cairo_xlib_surface_t *dst,
647                  const cairo_surface_pattern_t *pattern,
648                  const cairo_rectangle_int_t *extents,
649                  int *src_x, int *src_y,
650                  cairo_xlib_source_t *source)
651 {
652     Display *dpy = dst->display->display;
653     cairo_int_status_t status;
654     XTransform xtransform;
655     XRenderPictureAttributes pa;
656     unsigned mask = 0;
657
658     status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
659                                                     pattern->base.filter,
660                                                     extents->x + extents->width / 2,
661                                                     extents->y + extents->height / 2,
662                                                     (pixman_transform_t *)&xtransform,
663                                                     src_x, src_y);
664
665     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
666         if (source->has_matrix) {
667             source->has_matrix = 0;
668             memcpy (&xtransform, &identity, sizeof (identity));
669             status = CAIRO_INT_STATUS_SUCCESS;
670         }
671     } else
672         source->has_matrix = 1;
673     if (status == CAIRO_INT_STATUS_SUCCESS)
674         XRenderSetPictureTransform (dpy, source->picture, &xtransform);
675
676     if (source->filter != pattern->base.filter) {
677         picture_set_filter (dpy, source->picture, pattern->base.filter);
678         source->filter = pattern->base.filter;
679     }
680
681     if (source->has_component_alpha != pattern->base.has_component_alpha) {
682         pa.component_alpha = pattern->base.has_component_alpha;
683         mask |= CPComponentAlpha;
684         source->has_component_alpha = pattern->base.has_component_alpha;
685     }
686
687     if (source->extend != pattern->base.extend) {
688         pa.repeat = extend_to_repeat (pattern->base.extend);
689         mask |= CPRepeat;
690         source->extend = pattern->base.extend;
691     }
692
693     if (mask)
694         XRenderChangePicture (dpy, source->picture, mask, &pa);
695
696     return &source->base;
697 }
698
699 static cairo_surface_t *
700 subsurface_source (cairo_xlib_surface_t *dst,
701                    const cairo_surface_pattern_t *pattern,
702                    cairo_bool_t is_mask,
703                    const cairo_rectangle_int_t *extents,
704                    const cairo_rectangle_int_t *sample,
705                    int *src_x, int *src_y)
706 {
707     cairo_surface_subsurface_t *sub;
708     cairo_xlib_surface_t *src;
709     cairo_xlib_source_t *source;
710     Display *dpy = dst->display->display;
711     cairo_int_status_t status;
712     cairo_surface_pattern_t local_pattern;
713     XTransform xtransform;
714     XRenderPictureAttributes pa;
715     unsigned mask = 0;
716
717     sub = (cairo_surface_subsurface_t *) pattern->surface;
718
719     if (sample->x >= 0 && sample->y >= 0 &&
720         sample->x + sample->width  <= sub->extents.width &&
721         sample->y + sample->height <= sub->extents.height)
722     {
723         src = (cairo_xlib_surface_t *) sub->target;
724         status = _cairo_surface_flush (&src->base, 0);
725         if (unlikely (status))
726             return _cairo_surface_create_in_error (status);
727
728         if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
729             _cairo_matrix_is_translation (&pattern->base.matrix))
730         {
731             *src_x += pattern->base.matrix.x0 + sub->extents.x;
732             *src_y += pattern->base.matrix.y0 + sub->extents.y;
733
734             _cairo_xlib_surface_ensure_picture (src);
735             return cairo_surface_reference (&src->base);
736         }
737         else
738         {
739             cairo_surface_pattern_t local_pattern = *pattern;
740             local_pattern.base.matrix.x0 += sub->extents.x;
741             local_pattern.base.matrix.y0 += sub->extents.y;
742             local_pattern.base.extend = CAIRO_EXTEND_NONE;
743             return embedded_source (dst, &local_pattern, extents,
744                                     src_x, src_y, init_source (dst, src));
745         }
746     }
747
748     if (sub->snapshot && sub->snapshot->type == CAIRO_SURFACE_TYPE_XLIB) {
749         src = (cairo_xlib_surface_t *) cairo_surface_reference (sub->snapshot);
750         source = &src->embedded_source;
751     } else {
752         src = (cairo_xlib_surface_t *)
753             _cairo_surface_create_similar_scratch (&dst->base,
754                                                    sub->base.content,
755                                                    sub->extents.width,
756                                                    sub->extents.height);
757         if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
758             cairo_surface_destroy (&src->base);
759             return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
760         }
761
762         _cairo_pattern_init_for_surface (&local_pattern, sub->target);
763         cairo_matrix_init_translate (&local_pattern.base.matrix,
764                                      sub->extents.x, sub->extents.y);
765         local_pattern.base.filter = CAIRO_FILTER_NEAREST;
766         status = _cairo_surface_paint (&src->base,
767                                        CAIRO_OPERATOR_SOURCE,
768                                        &local_pattern.base,
769                                        NULL);
770         _cairo_pattern_fini (&local_pattern.base);
771
772         if (unlikely (status)) {
773             cairo_surface_destroy (&src->base);
774             return _cairo_surface_create_in_error (status);
775         }
776
777         _cairo_xlib_surface_ensure_picture (src);
778         _cairo_surface_subsurface_set_snapshot (&sub->base, &src->base);
779
780         source = &src->embedded_source;
781         source->has_component_alpha = 0;
782         source->has_matrix = 0;
783         source->filter = CAIRO_FILTER_NEAREST;
784         source->extend = CAIRO_EXTEND_NONE;
785     }
786
787     status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
788                                                     pattern->base.filter,
789                                                     extents->x + extents->width / 2,
790                                                     extents->y + extents->height / 2,
791                                                     (pixman_transform_t *)&xtransform,
792                                                     src_x, src_y);
793     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
794         if (source->has_matrix) {
795             source->has_matrix = 0;
796             memcpy (&xtransform, &identity, sizeof (identity));
797             status = CAIRO_INT_STATUS_SUCCESS;
798         }
799     } else
800         source->has_matrix = 1;
801     if (status == CAIRO_INT_STATUS_SUCCESS)
802         XRenderSetPictureTransform (dpy, src->picture, &xtransform);
803
804     if (source->filter != pattern->base.filter) {
805         picture_set_filter (dpy, src->picture, pattern->base.filter);
806         source->filter = pattern->base.filter;
807     }
808
809     if (source->has_component_alpha != pattern->base.has_component_alpha) {
810         pa.component_alpha = pattern->base.has_component_alpha;
811         mask |= CPComponentAlpha;
812         source->has_component_alpha = pattern->base.has_component_alpha;
813     }
814
815     if (source->extend != pattern->base.extend) {
816         pa.repeat = extend_to_repeat (pattern->base.extend);
817         mask |= CPRepeat;
818         source->extend = pattern->base.extend;
819     }
820
821     if (mask)
822         XRenderChangePicture (dpy, src->picture, mask, &pa);
823
824     return &src->base;
825 }
826
827 static cairo_surface_t *
828 native_source (cairo_xlib_surface_t *dst,
829                const cairo_surface_pattern_t *pattern,
830                cairo_bool_t is_mask,
831                const cairo_rectangle_int_t *extents,
832                const cairo_rectangle_int_t *sample,
833                int *src_x, int *src_y)
834 {
835     cairo_xlib_surface_t *src;
836     cairo_int_status_t status;
837
838     if (_cairo_surface_is_subsurface (pattern->surface))
839         return subsurface_source (dst, pattern, is_mask,
840                                   extents, sample,
841                                   src_x, src_y);
842
843     src = unwrap_source (pattern);
844     status = _cairo_surface_flush (&src->base, 0);
845     if (unlikely (status))
846         return _cairo_surface_create_in_error (status);
847
848     if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
849         sample->x >= 0 && sample->y >= 0 &&
850         sample->x + sample->width  <= src->width &&
851         sample->y + sample->height <= src->height &&
852         _cairo_matrix_is_translation (&pattern->base.matrix))
853     {
854         *src_x += pattern->base.matrix.x0;
855         *src_y += pattern->base.matrix.y0;
856         _cairo_xlib_surface_ensure_picture (src);
857         return cairo_surface_reference (&src->base);
858     }
859
860     return embedded_source (dst, pattern, extents, src_x, src_y,
861                             init_source (dst, src));
862 }
863
864 static cairo_surface_t *
865 recording_pattern_get_surface (const cairo_pattern_t *pattern)
866 {
867     cairo_surface_t *surface;
868
869     surface = ((const cairo_surface_pattern_t *) pattern)->surface;
870     if (_cairo_surface_is_paginated (surface))
871         surface = _cairo_paginated_surface_get_recording (surface);
872     if (_cairo_surface_is_snapshot (surface))
873         surface = _cairo_surface_snapshot_get_target (surface);
874     return surface;
875 }
876
877 static cairo_surface_t *
878 record_source (cairo_xlib_surface_t *dst,
879                const cairo_surface_pattern_t *pattern,
880                cairo_bool_t is_mask,
881                const cairo_rectangle_int_t *extents,
882                const cairo_rectangle_int_t *sample,
883                int *src_x, int *src_y)
884 {
885     cairo_xlib_surface_t *src;
886     cairo_matrix_t matrix, m;
887     cairo_status_t status;
888     cairo_rectangle_int_t upload, limit;
889
890     upload = *sample;
891     if (_cairo_surface_get_extents (pattern->surface, &limit) &&
892         ! _cairo_rectangle_intersect (&upload, &limit))
893     {
894         if (pattern->base.extend == CAIRO_EXTEND_NONE)
895             return alpha_source (dst, 0);
896
897         upload = limit;
898     }
899
900     src = (cairo_xlib_surface_t *)
901         _cairo_surface_create_similar_scratch (&dst->base,
902                                                pattern->surface->content,
903                                                upload.width,
904                                                upload.height);
905     if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
906         cairo_surface_destroy (&src->base);
907         return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
908     }
909
910     cairo_matrix_init_translate (&matrix, upload.x, upload.y);
911     status = _cairo_recording_surface_replay_with_clip (recording_pattern_get_surface (&pattern->base),
912                                                         &matrix, &src->base,
913                                                         NULL);
914     if (unlikely (status)) {
915         cairo_surface_destroy (&src->base);
916         return _cairo_surface_create_in_error (status);
917     }
918
919     matrix = pattern->base.matrix;
920     if (upload.x | upload.y) {
921         cairo_matrix_init_translate (&m, -upload.x, -upload.y);
922         cairo_matrix_multiply (&matrix, &matrix, &m);
923     }
924
925     _cairo_xlib_surface_ensure_picture (src);
926     if (! picture_set_properties (src->display, src->picture,
927                                   &pattern->base, &matrix, extents,
928                                   src_x, src_y))
929     {
930         cairo_surface_destroy (&src->base);
931         return render_pattern (dst, &pattern->base, is_mask,
932                                extents, src_x, src_y);
933     }
934
935     return &src->base;
936 }
937
938 static cairo_surface_t *
939 surface_source (cairo_xlib_surface_t *dst,
940                 const cairo_surface_pattern_t *pattern,
941                 cairo_bool_t is_mask,
942                 const cairo_rectangle_int_t *extents,
943                 const cairo_rectangle_int_t *sample,
944                 int *src_x, int *src_y)
945 {
946     cairo_surface_t *src;
947     cairo_xlib_surface_t *xsrc;
948     cairo_surface_pattern_t local_pattern;
949     cairo_status_t status;
950     cairo_rectangle_int_t upload, limit;
951     XRenderPictFormat *format = NULL;
952
953     src = pattern->surface;
954     if (src->type == CAIRO_SURFACE_TYPE_IMAGE &&
955         src->device == dst->base.device &&
956         _cairo_xlib_shm_surface_get_pixmap (src)) {
957         cairo_xlib_proxy_t *proxy;
958
959         proxy = malloc (sizeof(*proxy));
960         if (unlikely (proxy == NULL))
961             return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
962
963         _cairo_surface_init (&proxy->source.base,
964                              &cairo_xlib_proxy_backend,
965                              dst->base.device,
966                              src->content);
967
968         proxy->source.dpy = dst->display->display;
969         format = _cairo_xlib_shm_surface_get_xrender_format(src);
970         if (format == NULL) {
971             free (proxy);
972             return _cairo_surface_create_in_error (CAIRO_STATUS_NULL_POINTER);
973         }
974
975         proxy->source.picture = XRenderCreatePicture (proxy->source.dpy,
976                                                       _cairo_xlib_shm_surface_get_pixmap (src),
977                                                       format,
978                                                       0, NULL);
979         proxy->source.pixmap = None;
980
981         proxy->source.has_component_alpha = 0;
982         proxy->source.has_matrix = 0;
983         proxy->source.filter = CAIRO_FILTER_NEAREST;
984         proxy->source.extend = CAIRO_EXTEND_NONE;
985         proxy->owner = cairo_surface_reference (src);
986
987         return embedded_source (dst, pattern, extents, src_x, src_y,
988                                 &proxy->source);
989     }
990
991     upload = *sample;
992     if (_cairo_surface_get_extents (pattern->surface, &limit)) {
993         if (pattern->base.extend == CAIRO_EXTEND_NONE) {
994             if (! _cairo_rectangle_intersect (&upload, &limit))
995                 return alpha_source (dst, 0);
996         } else {
997             if (upload.x < limit.x ||
998                 upload.x + upload.width > limit.x + limit.width ||
999                 upload.y < limit.y ||
1000                 upload.y + upload.height > limit.y + limit.height)
1001             {
1002                 upload = limit;
1003             }
1004         }
1005     }
1006
1007     xsrc = (cairo_xlib_surface_t *)
1008             _cairo_surface_create_similar_scratch (&dst->base,
1009                                                    src->content,
1010                                                    upload.width,
1011                                                    upload.height);
1012     if (xsrc->base.type != CAIRO_SURFACE_TYPE_XLIB) {
1013         cairo_surface_destroy (src);
1014         cairo_surface_destroy (&xsrc->base);
1015         return None;
1016     }
1017
1018     if (_cairo_surface_is_image (src)) {
1019         status = _cairo_xlib_surface_draw_image (xsrc, (cairo_image_surface_t *)src,
1020                                                  upload.x, upload.y,
1021                                                  upload.width, upload.height,
1022                                                  0, 0);
1023     } else {
1024         cairo_image_surface_t *image;
1025         cairo_rectangle_int_t map_extents = { 0,0, upload.width,upload.height };
1026
1027         image = _cairo_surface_map_to_image (&xsrc->base, &map_extents);
1028
1029         _cairo_pattern_init_for_surface (&local_pattern, pattern->surface);
1030         cairo_matrix_init_translate (&local_pattern.base.matrix,
1031                                      upload.x, upload.y);
1032
1033         status = _cairo_surface_paint (&image->base,
1034                                        CAIRO_OPERATOR_SOURCE,
1035                                        &local_pattern.base,
1036                                        NULL);
1037         _cairo_pattern_fini (&local_pattern.base);
1038
1039         status = _cairo_surface_unmap_image (&xsrc->base, image);
1040         if (unlikely (status)) {
1041             cairo_surface_destroy (&xsrc->base);
1042             return _cairo_surface_create_in_error (status);
1043         }
1044
1045         status = _cairo_xlib_surface_put_shm (xsrc);
1046         if (unlikely (status)) {
1047             cairo_surface_destroy (&xsrc->base);
1048             return _cairo_surface_create_in_error (status);
1049         }
1050     }
1051
1052     _cairo_pattern_init_static_copy (&local_pattern.base, &pattern->base);
1053     if (upload.x | upload.y) {
1054         cairo_matrix_t m;
1055         cairo_matrix_init_translate (&m, -upload.x, -upload.y);
1056         cairo_matrix_multiply (&local_pattern.base.matrix,
1057                                &local_pattern.base.matrix,
1058                                &m);
1059     }
1060
1061     *src_x = *src_y = 0;
1062     _cairo_xlib_surface_ensure_picture (xsrc);
1063     if (! picture_set_properties (xsrc->display,
1064                                   xsrc->picture,
1065                                   &local_pattern.base,
1066                                   &local_pattern.base.matrix,
1067                                   extents,
1068                                   src_x, src_y))
1069     {
1070         cairo_surface_destroy (&xsrc->base);
1071         return render_pattern (dst, &pattern->base,
1072                                is_mask, extents,
1073                                src_x, src_y);
1074     }
1075
1076     return &xsrc->base;
1077 }
1078
1079 static cairo_bool_t
1080 pattern_is_supported (cairo_xlib_display_t *display,
1081                       const cairo_pattern_t *pattern)
1082 {
1083     if (pattern->type == CAIRO_PATTERN_TYPE_MESH)
1084         return FALSE;
1085
1086     if (display->buggy_pad_reflect) {
1087         if (pattern->extend == CAIRO_EXTEND_REPEAT || pattern->extend == CAIRO_EXTEND_PAD)
1088             return FALSE;
1089     }
1090
1091     if (display->buggy_gradients) {
1092         if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
1093             return FALSE;
1094     }
1095
1096     if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display)) {
1097         if (!_cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL))
1098             return FALSE;
1099     }
1100
1101     if (! CAIRO_RENDER_HAS_FILTERS (display)) {
1102             /* No filters implies no transforms, so we optimise away BILINEAR */
1103     }
1104
1105     return TRUE;
1106 }
1107 cairo_surface_t *
1108 _cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst,
1109                                        const cairo_pattern_t *pattern,
1110                                        cairo_bool_t is_mask,
1111                                        const cairo_rectangle_int_t *extents,
1112                                        const cairo_rectangle_int_t *sample,
1113                                        int *src_x, int *src_y)
1114 {
1115     cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)_dst;
1116
1117     *src_x = *src_y = 0;
1118
1119     if (pattern == NULL || pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
1120         if (pattern == NULL)
1121             pattern = &_cairo_pattern_white.base;
1122
1123         return solid_source (dst, &((cairo_solid_pattern_t *)pattern)->color);
1124     }
1125
1126     if (pattern_is_supported (dst->display, pattern)) {
1127         if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
1128             cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *)pattern;
1129             if (spattern->surface->type == CAIRO_SURFACE_TYPE_XLIB &&
1130                 _cairo_xlib_surface_same_screen (dst,
1131                                                  unwrap_source (spattern)))
1132                 return native_source (dst, spattern, is_mask,
1133                                       extents, sample,
1134                                       src_x, src_y);
1135
1136             if (spattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
1137                 return record_source (dst, spattern, is_mask,
1138                                       extents, sample,
1139                                       src_x, src_y);
1140
1141             return surface_source (dst, spattern, is_mask,
1142                                    extents, sample,
1143                                    src_x, src_y);
1144         }
1145
1146         if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
1147             pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
1148         {
1149             cairo_gradient_pattern_t *gpattern = (cairo_gradient_pattern_t *)pattern;
1150             return gradient_source (dst, gpattern, is_mask, extents, src_x, src_y);
1151         }
1152     }
1153
1154     return render_pattern (dst, pattern, is_mask, extents, src_x, src_y);
1155 }
1156
1157 #endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */