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 = _cairo_calloc (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
			 FALSE); /* is_vector */
125

            
126
    /* The source exists only within an operation */
127
    source->picture = picture;
128
    source->pixmap = pixmap;
129
    source->dpy = dst->display->display;
130

            
131
    return &source->base;
132
}
133

            
134
static uint32_t
135
hars_petruska_f54_1_random (void)
136
{
137
#define rol(x,k) ((x << k) | (x >> (32-k)))
138
    static uint32_t x;
139
    return x = (x ^ rol (x, 5) ^ rol (x, 24)) + 0x37798849;
140
#undef rol
141
}
142

            
143
static const XTransform identity = {
144
    {
145
	{ 1 << 16, 0x00000, 0x00000 },
146
	{ 0x00000, 1 << 16, 0x00000 },
147
	{ 0x00000, 0x00000, 1 << 16 },
148
    }
149
};
150

            
151
static cairo_bool_t
152
picture_set_matrix (cairo_xlib_display_t *display,
153
		    Picture picture,
154
		    const cairo_matrix_t *matrix,
155
		    cairo_filter_t        filter,
156
		    double                xc,
157
		    double                yc,
158
		    int                  *x_offset,
159
		    int                  *y_offset)
160
{
161
    XTransform xtransform;
162
    pixman_transform_t *pixman_transform;
163
    cairo_int_status_t status;
164

            
165
    /* Casting between pixman_transform_t and XTransform is safe because
166
     * they happen to be the exact same type.
167
     */
168
    pixman_transform = (pixman_transform_t *) &xtransform;
169
    status = _cairo_matrix_to_pixman_matrix_offset (matrix, filter, xc, yc,
170
						    pixman_transform,
171
						    x_offset, y_offset);
172
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
173
	return TRUE;
174
    if (unlikely (status != CAIRO_INT_STATUS_SUCCESS))
175
	return FALSE;
176

            
177
    if (memcmp (&xtransform, &identity, sizeof (XTransform)) == 0)
178
	return TRUE;
179

            
180
    /* a late check in case we perturb the matrix too far */
181
    if (! CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display))
182
	return FALSE;
183

            
184
    XRenderSetPictureTransform (display->display, picture, &xtransform);
185
    return TRUE;
186
}
187

            
188
static cairo_status_t
189
picture_set_filter (Display *dpy,
190
		    Picture picture,
191
		    cairo_filter_t filter)
192
{
193
    const char *render_filter;
194

            
195
    switch (filter) {
196
    case CAIRO_FILTER_FAST:
197
	render_filter = FilterFast;
198
	break;
199
    case CAIRO_FILTER_GOOD:
200
	render_filter = FilterGood;
201
	break;
202
    case CAIRO_FILTER_BEST:
203
	render_filter = FilterBest;
204
	break;
205
    case CAIRO_FILTER_NEAREST:
206
	render_filter = FilterNearest;
207
	break;
208
    case CAIRO_FILTER_BILINEAR:
209
	render_filter = FilterBilinear;
210
	break;
211
    case CAIRO_FILTER_GAUSSIAN:
212
	/* XXX: The GAUSSIAN value has no implementation in cairo
213
	 * whatsoever, so it was really a mistake to have it in the
214
	 * API. We could fix this by officially deprecating it, or
215
	 * else inventing semantics and providing an actual
216
	 * implementation for it. */
217
    default:
218
	render_filter = FilterBest;
219
	break;
220
    }
221

            
222
    XRenderSetPictureFilter (dpy, picture, (char *) render_filter, NULL, 0);
223
    return CAIRO_STATUS_SUCCESS;
224
}
225

            
226
static int
227
extend_to_repeat (cairo_extend_t extend)
228
{
229
    switch (extend) {
230
    default:
231
	ASSERT_NOT_REACHED;
232
    case CAIRO_EXTEND_NONE:
233
	return RepeatNone;
234
    case CAIRO_EXTEND_REPEAT:
235
	return RepeatNormal;
236
    case CAIRO_EXTEND_REFLECT:
237
	return RepeatReflect;
238
    case CAIRO_EXTEND_PAD:
239
	return RepeatPad;
240
    }
241
}
242

            
243
static cairo_bool_t
244
picture_set_properties (cairo_xlib_display_t *display,
245
			Picture picture,
246
			const cairo_pattern_t *pattern,
247
			const cairo_matrix_t *matrix,
248
			const cairo_rectangle_int_t *extents,
249
			int *x_off, int *y_off)
250
{
251
    XRenderPictureAttributes pa;
252
    int mask = 0;
253

            
254
    if (! picture_set_matrix (display, picture, matrix, pattern->filter,
255
			      extents->x + extents->width / 2,
256
			      extents->y + extents->height / 2,
257
			      x_off, y_off))
258
	return FALSE;
259

            
260
    picture_set_filter (display->display, picture, pattern->filter);
261

            
262
    if (pattern->has_component_alpha) {
263
	pa.component_alpha = 1;
264
	mask |= CPComponentAlpha;
265
    }
266

            
267
    if (pattern->extend != CAIRO_EXTEND_NONE) {
268
	pa.repeat = extend_to_repeat (pattern->extend);
269
	mask |= CPRepeat;
270
    }
271

            
272
    if (mask)
273
	XRenderChangePicture (display->display, picture, mask, &pa);
274

            
275
    return TRUE;
276
}
277

            
278
static cairo_surface_t *
279
render_pattern (cairo_xlib_surface_t *dst,
280
		const cairo_pattern_t *pattern,
281
		cairo_bool_t is_mask,
282
		const cairo_rectangle_int_t *extents,
283
		int *src_x, int *src_y)
284
{
285
    Display *dpy = dst->display->display;
286
    cairo_xlib_surface_t *src;
287
    cairo_image_surface_t *image;
288
    cairo_status_t status;
289
    cairo_rectangle_int_t map_extents;
290

            
291
    src = (cairo_xlib_surface_t *)
292
	_cairo_surface_create_scratch (&dst->base,
293
				       is_mask ? CAIRO_CONTENT_ALPHA : CAIRO_CONTENT_COLOR_ALPHA,
294
				       extents->width,
295
				       extents->height,
296
				       NULL);
297
    if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
298
	cairo_surface_destroy (&src->base);
299
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
300
    }
301

            
302
    map_extents = *extents;
303
    map_extents.x = map_extents.y = 0;
304

            
305
    image = _cairo_surface_map_to_image (&src->base, &map_extents);
306
    status = _cairo_surface_offset_paint (&image->base, extents->x, extents->y,
307
					  CAIRO_OPERATOR_SOURCE, pattern,
308
					  NULL);
309
    status = _cairo_surface_unmap_image (&src->base, image);
310
    if (unlikely (status)) {
311
	cairo_surface_destroy (&src->base);
312
	return _cairo_surface_create_in_error (status);
313
    }
314

            
315
    status = _cairo_xlib_surface_put_shm (src);
316
    if (unlikely (status)) {
317
	cairo_surface_destroy (&src->base);
318
	return _cairo_surface_create_in_error (status);
319
    }
320

            
321
    src->picture = XRenderCreatePicture (dpy,
322
					 src->drawable, src->xrender_format,
323
					 0, NULL);
324

            
325
    *src_x = -extents->x;
326
    *src_y = -extents->y;
327
    return &src->base;
328
}
329

            
330
static cairo_surface_t *
331
gradient_source (cairo_xlib_surface_t *dst,
332
		 const cairo_gradient_pattern_t *gradient,
333
		 cairo_bool_t is_mask,
334
		 const cairo_rectangle_int_t *extents,
335
		 int *src_x, int *src_y)
336
{
337
    cairo_xlib_display_t *display = dst->display;
338
    cairo_matrix_t matrix = gradient->base.matrix;
339
    char buf[CAIRO_STACK_BUFFER_SIZE];
340
    cairo_circle_double_t extremes[2];
341
    XFixed *stops;
342
    XRenderColor *colors;
343
    Picture picture;
344
    unsigned int i, n_stops;
345

            
346
    /* The RENDER specification says that the inner circle has
347
     * to be completely contained inside the outer one. */
348
    if (gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL &&
349
	! _cairo_radial_pattern_focus_is_inside ((cairo_radial_pattern_t *) gradient))
350
	return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
351

            
352
    assert (gradient->n_stops > 0);
353
    n_stops = MAX (gradient->n_stops, 2);
354

            
355
    if (n_stops < sizeof (buf) / (sizeof (XFixed) + sizeof (XRenderColor)))
356
    {
357
	stops = (XFixed *) buf;
358
    }
359
    else
360
    {
361
	stops =
362
	    _cairo_malloc_ab (n_stops,
363
			      sizeof (XFixed) + sizeof (XRenderColor));
364
	if (unlikely (stops == NULL))
365
	    return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
366
    }
367

            
368
    colors = (XRenderColor *) (stops + n_stops);
369
    for (i = 0; i < gradient->n_stops; i++) {
370
	stops[i] =
371
	    _cairo_fixed_16_16_from_double (gradient->stops[i].offset);
372

            
373
	colors[i].red   = gradient->stops[i].color.red_short;
374
	colors[i].green = gradient->stops[i].color.green_short;
375
	colors[i].blue  = gradient->stops[i].color.blue_short;
376
	colors[i].alpha = gradient->stops[i].color.alpha_short;
377
    }
378

            
379
    /* RENDER does not support gradients with less than 2
380
     * stops. If a gradient has only a single stop, duplicate
381
     * it to make RENDER happy. */
382
    if (gradient->n_stops == 1) {
383
	stops[1] =
384
	    _cairo_fixed_16_16_from_double (gradient->stops[0].offset);
385

            
386
	colors[1].red   = gradient->stops[0].color.red_short;
387
	colors[1].green = gradient->stops[0].color.green_short;
388
	colors[1].blue  = gradient->stops[0].color.blue_short;
389
	colors[1].alpha = gradient->stops[0].color.alpha_short;
390
    }
391

            
392
#if 0
393
    /* For some weird reason the X server is sometimes getting
394
     * CreateGradient requests with bad length. So far I've only seen
395
     * XRenderCreateLinearGradient request with 4 stops sometime end up
396
     * with length field matching 0 stops at the server side. I've
397
     * looked at the libXrender code and I can't see anything that
398
     * could cause this behavior. However, for some reason having a
399
     * XSync call here seems to avoid the issue so I'll keep it here
400
     * until it's solved.
401
     */
402
    XSync (display->display, False);
403
#endif
404

            
405
    _cairo_gradient_pattern_fit_to_range (gradient, PIXMAN_MAX_INT >> 1, &matrix, extremes);
406

            
407
    if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
408
	XLinearGradient grad;
409

            
410
	grad.p1.x = _cairo_fixed_16_16_from_double (extremes[0].center.x);
411
	grad.p1.y = _cairo_fixed_16_16_from_double (extremes[0].center.y);
412
	grad.p2.x = _cairo_fixed_16_16_from_double (extremes[1].center.x);
413
	grad.p2.y = _cairo_fixed_16_16_from_double (extremes[1].center.y);
414

            
415
	picture = XRenderCreateLinearGradient (display->display, &grad,
416
					       stops, colors,
417
					       n_stops);
418
    } else {
419
	XRadialGradient grad;
420

            
421
	grad.inner.x      = _cairo_fixed_16_16_from_double (extremes[0].center.x);
422
	grad.inner.y      = _cairo_fixed_16_16_from_double (extremes[0].center.y);
423
	grad.inner.radius = _cairo_fixed_16_16_from_double (extremes[0].radius);
424
	grad.outer.x      = _cairo_fixed_16_16_from_double (extremes[1].center.x);
425
	grad.outer.y      = _cairo_fixed_16_16_from_double (extremes[1].center.y);
426
	grad.outer.radius = _cairo_fixed_16_16_from_double (extremes[1].radius);
427

            
428
	picture = XRenderCreateRadialGradient (display->display, &grad,
429
					       stops, colors,
430
					       n_stops);
431
    }
432

            
433
    if (stops != (XFixed *) buf)
434
	free (stops);
435

            
436
    *src_x = *src_y = 0;
437
    if (! picture_set_properties (display, picture,
438
				  &gradient->base, &gradient->base.matrix,
439
				  extents,
440
				  src_x, src_y)) {
441
	XRenderFreePicture (display->display, picture);
442
	return render_pattern (dst, &gradient->base, is_mask, extents, src_x, src_y);
443
    }
444

            
445
    return source (dst, picture, None);
446
}
447

            
448
static cairo_surface_t *
449
color_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
450
{
451
    Display *dpy = dst->display->display;
452
    XRenderColor xcolor;
453
    Picture picture;
454
    Pixmap pixmap = None;
455

            
456
    xcolor.red   = color->red_short;
457
    xcolor.green = color->green_short;
458
    xcolor.blue  = color->blue_short;
459
    xcolor.alpha = color->alpha_short;
460

            
461
    if (CAIRO_RENDER_HAS_GRADIENTS(dst->display)) {
462
	picture = XRenderCreateSolidFill (dpy, &xcolor);
463
    } else {
464
	XRenderPictureAttributes pa;
465
	int mask = 0;
466

            
467
	pa.repeat = RepeatNormal;
468
	mask |= CPRepeat;
469

            
470
	pixmap = XCreatePixmap (dpy, dst->drawable, 1, 1, 32);
471
	picture = XRenderCreatePicture (dpy, pixmap,
472
					_cairo_xlib_display_get_xrender_format (dst->display, CAIRO_FORMAT_ARGB32),
473
					mask, &pa);
474

            
475
	if (CAIRO_RENDER_HAS_FILL_RECTANGLES(dst->display)) {
476
	    XRectangle r = { 0, 0, 1, 1};
477
	    XRenderFillRectangles (dpy, PictOpSrc, picture, &xcolor, &r, 1);
478
	} else {
479
	    XGCValues gcv;
480
	    GC gc;
481

            
482
	    gc = _cairo_xlib_screen_get_gc (dst->display, dst->screen,
483
					    32, pixmap);
484
	    if (unlikely (gc == NULL)) {
485
		XFreePixmap (dpy, pixmap);
486
		return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
487
	    }
488

            
489
	    gcv.foreground = 0;
490
	    gcv.foreground |= (uint32_t)color->alpha_short >> 8 << 24;
491
	    gcv.foreground |= color->red_short   >> 8 << 16;
492
	    gcv.foreground |= color->green_short >> 8 << 8;
493
	    gcv.foreground |= color->blue_short  >> 8 << 0;
494
	    gcv.fill_style = FillSolid;
495

            
496
	    XChangeGC (dpy, gc, GCFillStyle | GCForeground, &gcv);
497
	    XFillRectangle (dpy, pixmap, gc, 0, 0, 1, 1);
498

            
499
	    _cairo_xlib_screen_put_gc (dst->display, dst->screen, 32, gc);
500
	}
501
    }
502

            
503
    return source (dst, picture, pixmap);
504
}
505

            
506
static cairo_surface_t *
507
alpha_source (cairo_xlib_surface_t *dst, uint8_t alpha)
508
{
509
    cairo_xlib_display_t *display = dst->display;
510

            
511
    if (display->alpha[alpha] == NULL) {
512
	cairo_color_t color;
513

            
514
	color.red_short = color.green_short = color.blue_short = 0;
515
	color.alpha_short = alpha << 8 | alpha;
516

            
517
	display->alpha[alpha] = color_source (dst, &color);
518
    }
519

            
520
    return cairo_surface_reference (display->alpha[alpha]);
521
}
522

            
523
static cairo_surface_t *
524
white_source (cairo_xlib_surface_t *dst)
525
{
526
    cairo_xlib_display_t *display = dst->display;
527

            
528
    if (display->white == NULL)
529
	display->white = color_source (dst, CAIRO_COLOR_WHITE);
530

            
531
    return cairo_surface_reference (display->white);
532
}
533

            
534
static cairo_surface_t *
535
opaque_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
536
{
537
    cairo_xlib_display_t *display = dst->display;
538
    uint32_t pixel =
539
	0xff000000 |
540
	color->red_short   >> 8 << 16 |
541
	color->green_short >> 8 << 8 |
542
	color->blue_short  >> 8 << 0;
543
    int i;
544

            
545
    if (display->last_solid_cache[0].color == pixel)
546
	return cairo_surface_reference (display->solid[display->last_solid_cache[0].index]);
547

            
548
    for (i = 0; i < 16; i++) {
549
	if (display->solid_cache[i] == pixel)
550
	    goto done;
551
    }
552

            
553
    i = hars_petruska_f54_1_random () % 16;
554
    cairo_surface_destroy (display->solid[i]);
555

            
556
    display->solid[i] = color_source (dst, color);
557
    display->solid_cache[i] = pixel;
558

            
559
done:
560
    display->last_solid_cache[0].color = pixel;
561
    display->last_solid_cache[0].index = i;
562
    return cairo_surface_reference (display->solid[i]);
563
}
564

            
565
static cairo_surface_t *
566
transparent_source (cairo_xlib_surface_t *dst, const cairo_color_t *color)
567
{
568
    cairo_xlib_display_t *display = dst->display;
569
    uint32_t pixel =
570
	(uint32_t)color->alpha_short >> 8 << 24 |
571
	color->red_short   >> 8 << 16 |
572
	color->green_short >> 8 << 8 |
573
	color->blue_short  >> 8 << 0;
574
    int i;
575

            
576
    if (display->last_solid_cache[1].color == pixel) {
577
    assert (display->solid[display->last_solid_cache[1].index]);
578
	return cairo_surface_reference (display->solid[display->last_solid_cache[1].index]);
579
    }
580

            
581
    for (i = 16; i < 32; i++) {
582
	if (display->solid_cache[i] == pixel)
583
	    goto done;
584
    }
585

            
586
    i = 16 + (hars_petruska_f54_1_random () % 16);
587
    cairo_surface_destroy (display->solid[i]);
588

            
589
    display->solid[i] = color_source (dst, color);
590
    display->solid_cache[i] = pixel;
591

            
592
done:
593
    display->last_solid_cache[1].color = pixel;
594
    display->last_solid_cache[1].index = i;
595
    assert (display->solid[i]);
596
    return cairo_surface_reference (display->solid[i]);
597
}
598

            
599
static cairo_surface_t *
600
solid_source (cairo_xlib_surface_t *dst,
601
	      const cairo_color_t *color)
602
{
603
    if ((color->red_short | color->green_short | color->blue_short) <= 0xff)
604
	return alpha_source (dst, color->alpha_short >> 8);
605

            
606
    if (CAIRO_ALPHA_SHORT_IS_OPAQUE (color->alpha_short)) {
607
	if (color->red_short >= 0xff00 && color->green_short >= 0xff00 && color->blue_short >= 0xff00)
608
	    return white_source (dst);
609

            
610
	return opaque_source (dst, color);
611
    } else
612
	return transparent_source (dst, color);
613
}
614

            
615
static cairo_xlib_source_t *init_source (cairo_xlib_surface_t *dst,
616
					 cairo_xlib_surface_t *src)
617
{
618
    Display *dpy = dst->display->display;
619
    cairo_xlib_source_t *source = &src->embedded_source;
620

            
621
    /* As these are frequent and meant to be fast, we track pictures for
622
     * native surface and minimise update requests.
623
     */
624
    if (source->picture == None) {
625
	XRenderPictureAttributes pa;
626

            
627
	_cairo_surface_init (&source->base,
628
			     &cairo_xlib_source_backend,
629
			     NULL, /* device */
630
			     CAIRO_CONTENT_COLOR_ALPHA,
631
			     FALSE); /* is_vector */
632

            
633
	pa.subwindow_mode = IncludeInferiors;
634
	source->picture = XRenderCreatePicture (dpy,
635
						src->drawable,
636
						src->xrender_format,
637
						CPSubwindowMode, &pa);
638

            
639
	source->has_component_alpha = 0;
640
	source->has_matrix = 0;
641
	source->filter = CAIRO_FILTER_NEAREST;
642
	source->extend = CAIRO_EXTEND_NONE;
643
    }
644

            
645
    return (cairo_xlib_source_t *) cairo_surface_reference (&source->base);
646
}
647

            
648
static cairo_surface_t *
649
embedded_source (cairo_xlib_surface_t *dst,
650
		 const cairo_surface_pattern_t *pattern,
651
		 const cairo_rectangle_int_t *extents,
652
		 int *src_x, int *src_y,
653
		 cairo_xlib_source_t *source)
654
{
655
    Display *dpy = dst->display->display;
656
    cairo_int_status_t status;
657
    XTransform xtransform;
658
    XRenderPictureAttributes pa;
659
    unsigned mask = 0;
660

            
661
    status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
662
						    pattern->base.filter,
663
						    extents->x + extents->width / 2,
664
						    extents->y + extents->height / 2,
665
						    (pixman_transform_t *)&xtransform,
666
						    src_x, src_y);
667

            
668
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
669
	if (source->has_matrix) {
670
	    source->has_matrix = 0;
671
	    memcpy (&xtransform, &identity, sizeof (identity));
672
	    status = CAIRO_INT_STATUS_SUCCESS;
673
	}
674
    } else
675
	source->has_matrix = 1;
676
    if (status == CAIRO_INT_STATUS_SUCCESS)
677
	XRenderSetPictureTransform (dpy, source->picture, &xtransform);
678

            
679
    if (source->filter != pattern->base.filter) {
680
	picture_set_filter (dpy, source->picture, pattern->base.filter);
681
	source->filter = pattern->base.filter;
682
    }
683

            
684
    if (source->has_component_alpha != pattern->base.has_component_alpha) {
685
	pa.component_alpha = pattern->base.has_component_alpha;
686
	mask |= CPComponentAlpha;
687
	source->has_component_alpha = pattern->base.has_component_alpha;
688
    }
689

            
690
    if (source->extend != pattern->base.extend) {
691
	pa.repeat = extend_to_repeat (pattern->base.extend);
692
	mask |= CPRepeat;
693
	source->extend = pattern->base.extend;
694
    }
695

            
696
    if (mask)
697
	XRenderChangePicture (dpy, source->picture, mask, &pa);
698

            
699
    return &source->base;
700
}
701

            
702
static cairo_surface_t *
703
subsurface_source (cairo_xlib_surface_t *dst,
704
		   const cairo_surface_pattern_t *pattern,
705
		   cairo_bool_t is_mask,
706
		   const cairo_rectangle_int_t *extents,
707
		   const cairo_rectangle_int_t *sample,
708
		   int *src_x, int *src_y)
709
{
710
    cairo_surface_subsurface_t *sub;
711
    cairo_xlib_surface_t *src;
712
    cairo_xlib_source_t *source;
713
    Display *dpy = dst->display->display;
714
    cairo_int_status_t status;
715
    cairo_surface_pattern_t local_pattern;
716
    XTransform xtransform;
717
    XRenderPictureAttributes pa;
718
    unsigned mask = 0;
719

            
720
    sub = (cairo_surface_subsurface_t *) pattern->surface;
721

            
722
    if (sample->x >= 0 && sample->y >= 0 &&
723
	sample->x + sample->width  <= sub->extents.width &&
724
	sample->y + sample->height <= sub->extents.height)
725
    {
726
	src = (cairo_xlib_surface_t *) sub->target;
727
	status = _cairo_surface_flush (&src->base, 0);
728
	if (unlikely (status))
729
	    return _cairo_surface_create_in_error (status);
730

            
731
	if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
732
	    _cairo_matrix_is_translation (&pattern->base.matrix))
733
	{
734
	    *src_x += pattern->base.matrix.x0 + sub->extents.x;
735
	    *src_y += pattern->base.matrix.y0 + sub->extents.y;
736

            
737
	    _cairo_xlib_surface_ensure_picture (src);
738
	    return cairo_surface_reference (&src->base);
739
	}
740
	else
741
	{
742
	    cairo_surface_pattern_t local_pattern = *pattern;
743
	    local_pattern.base.matrix.x0 += sub->extents.x;
744
	    local_pattern.base.matrix.y0 += sub->extents.y;
745
	    local_pattern.base.extend = CAIRO_EXTEND_NONE;
746
	    return embedded_source (dst, &local_pattern, extents,
747
				    src_x, src_y, init_source (dst, src));
748
	}
749
    }
750

            
751
    if (sub->snapshot && sub->snapshot->type == CAIRO_SURFACE_TYPE_XLIB) {
752
	src = (cairo_xlib_surface_t *) cairo_surface_reference (sub->snapshot);
753
	source = &src->embedded_source;
754
    } else {
755
	src = (cairo_xlib_surface_t *)
756
	    _cairo_surface_create_scratch (&dst->base,
757
					   sub->base.content,
758
					   sub->extents.width,
759
					   sub->extents.height,
760
					   NULL);
761
	if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
762
	    cairo_surface_destroy (&src->base);
763
	    return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
764
	}
765

            
766
	_cairo_pattern_init_for_surface (&local_pattern, sub->target);
767
	cairo_matrix_init_translate (&local_pattern.base.matrix,
768
				     sub->extents.x, sub->extents.y);
769
	local_pattern.base.filter = CAIRO_FILTER_NEAREST;
770
	status = _cairo_surface_paint (&src->base,
771
				       CAIRO_OPERATOR_SOURCE,
772
				       &local_pattern.base,
773
				       NULL);
774
	_cairo_pattern_fini (&local_pattern.base);
775

            
776
	if (unlikely (status)) {
777
	    cairo_surface_destroy (&src->base);
778
	    return _cairo_surface_create_in_error (status);
779
	}
780

            
781
	_cairo_xlib_surface_ensure_picture (src);
782
	_cairo_surface_subsurface_set_snapshot (&sub->base, &src->base);
783

            
784
	source = &src->embedded_source;
785
	source->has_component_alpha = 0;
786
	source->has_matrix = 0;
787
	source->filter = CAIRO_FILTER_NEAREST;
788
	source->extend = CAIRO_EXTEND_NONE;
789
    }
790

            
791
    status = _cairo_matrix_to_pixman_matrix_offset (&pattern->base.matrix,
792
						    pattern->base.filter,
793
						    extents->x + extents->width / 2,
794
						    extents->y + extents->height / 2,
795
						    (pixman_transform_t *)&xtransform,
796
						    src_x, src_y);
797
    if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) {
798
	if (source->has_matrix) {
799
	    source->has_matrix = 0;
800
	    memcpy (&xtransform, &identity, sizeof (identity));
801
	    status = CAIRO_INT_STATUS_SUCCESS;
802
	}
803
    } else
804
	source->has_matrix = 1;
805
    if (status == CAIRO_INT_STATUS_SUCCESS)
806
	XRenderSetPictureTransform (dpy, src->picture, &xtransform);
807

            
808
    if (source->filter != pattern->base.filter) {
809
	picture_set_filter (dpy, src->picture, pattern->base.filter);
810
	source->filter = pattern->base.filter;
811
    }
812

            
813
    if (source->has_component_alpha != pattern->base.has_component_alpha) {
814
	pa.component_alpha = pattern->base.has_component_alpha;
815
	mask |= CPComponentAlpha;
816
	source->has_component_alpha = pattern->base.has_component_alpha;
817
    }
818

            
819
    if (source->extend != pattern->base.extend) {
820
	pa.repeat = extend_to_repeat (pattern->base.extend);
821
	mask |= CPRepeat;
822
	source->extend = pattern->base.extend;
823
    }
824

            
825
    if (mask)
826
	XRenderChangePicture (dpy, src->picture, mask, &pa);
827

            
828
    return &src->base;
829
}
830

            
831
static cairo_surface_t *
832
native_source (cairo_xlib_surface_t *dst,
833
	       const cairo_surface_pattern_t *pattern,
834
	       cairo_bool_t is_mask,
835
	       const cairo_rectangle_int_t *extents,
836
	       const cairo_rectangle_int_t *sample,
837
	       int *src_x, int *src_y)
838
{
839
    cairo_xlib_surface_t *src;
840
    cairo_int_status_t status;
841

            
842
    if (_cairo_surface_is_subsurface (pattern->surface))
843
	return subsurface_source (dst, pattern, is_mask,
844
				  extents, sample,
845
				  src_x, src_y);
846

            
847
    src = unwrap_source (pattern);
848
    status = _cairo_surface_flush (&src->base, 0);
849
    if (unlikely (status))
850
	return _cairo_surface_create_in_error (status);
851

            
852
    if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
853
	sample->x >= 0 && sample->y >= 0 &&
854
	sample->x + sample->width  <= src->width &&
855
	sample->y + sample->height <= src->height &&
856
	_cairo_matrix_is_translation (&pattern->base.matrix))
857
    {
858
	*src_x += pattern->base.matrix.x0;
859
	*src_y += pattern->base.matrix.y0;
860
	_cairo_xlib_surface_ensure_picture (src);
861
	return cairo_surface_reference (&src->base);
862
    }
863

            
864
    return embedded_source (dst, pattern, extents, src_x, src_y,
865
			    init_source (dst, src));
866
}
867

            
868
static cairo_surface_t *
869
recording_pattern_get_surface (const cairo_pattern_t *pattern)
870
{
871
    cairo_surface_t *surface;
872

            
873
    surface = ((const cairo_surface_pattern_t *) pattern)->surface;
874

            
875
    if (_cairo_surface_is_paginated (surface))
876
	return cairo_surface_reference (_cairo_paginated_surface_get_recording (surface));
877

            
878
    if (_cairo_surface_is_snapshot (surface))
879
	return _cairo_surface_snapshot_get_target (surface);
880

            
881
    return cairo_surface_reference (surface);
882
}
883

            
884
static cairo_surface_t *
885
record_source (cairo_xlib_surface_t *dst,
886
	       const cairo_surface_pattern_t *pattern,
887
	       cairo_bool_t is_mask,
888
	       const cairo_rectangle_int_t *extents,
889
	       const cairo_rectangle_int_t *sample,
890
	       int *src_x, int *src_y)
891
{
892
    cairo_xlib_surface_t *src;
893
    cairo_surface_t *recording;
894
    cairo_matrix_t matrix, m;
895
    cairo_status_t status;
896
    cairo_rectangle_int_t upload, limit;
897

            
898
    upload = *sample;
899
    if (_cairo_surface_get_extents (pattern->surface, &limit) &&
900
	! _cairo_rectangle_intersect (&upload, &limit))
901
    {
902
	if (pattern->base.extend == CAIRO_EXTEND_NONE)
903
	    return alpha_source (dst, 0);
904

            
905
	upload = limit;
906
    }
907

            
908
    src = (cairo_xlib_surface_t *)
909
	_cairo_surface_create_scratch (&dst->base,
910
				       pattern->surface->content,
911
				       upload.width,
912
				       upload.height,
913
				       NULL);
914
    if (src->base.type != CAIRO_SURFACE_TYPE_XLIB) {
915
	cairo_surface_destroy (&src->base);
916
	return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
917
    }
918

            
919
    cairo_matrix_init_translate (&matrix, upload.x, upload.y);
920
    recording = recording_pattern_get_surface (&pattern->base),
921
    status = _cairo_recording_surface_replay_with_clip (recording,
922
							&matrix, &src->base,
923
							NULL);
924
    cairo_surface_destroy (recording);
925
    if (unlikely (status)) {
926
	cairo_surface_destroy (&src->base);
927
	return _cairo_surface_create_in_error (status);
928
    }
929

            
930
    matrix = pattern->base.matrix;
931
    if (upload.x | upload.y) {
932
	cairo_matrix_init_translate (&m, -upload.x, -upload.y);
933
	cairo_matrix_multiply (&matrix, &matrix, &m);
934
    }
935

            
936
    _cairo_xlib_surface_ensure_picture (src);
937
    if (! picture_set_properties (src->display, src->picture,
938
				  &pattern->base, &matrix, extents,
939
				  src_x, src_y))
940
    {
941
	cairo_surface_destroy (&src->base);
942
	return render_pattern (dst, &pattern->base, is_mask,
943
			       extents, src_x, src_y);
944
    }
945

            
946
    return &src->base;
947
}
948

            
949
static cairo_surface_t *
950
surface_source (cairo_xlib_surface_t *dst,
951
		const cairo_surface_pattern_t *pattern,
952
		cairo_bool_t is_mask,
953
		const cairo_rectangle_int_t *extents,
954
		const cairo_rectangle_int_t *sample,
955
		int *src_x, int *src_y)
956
{
957
    cairo_surface_t *src;
958
    cairo_xlib_surface_t *xsrc;
959
    cairo_surface_pattern_t local_pattern;
960
    cairo_status_t status;
961
    cairo_rectangle_int_t upload, limit;
962

            
963
    src = pattern->surface;
964
    if (src->type == CAIRO_SURFACE_TYPE_IMAGE &&
965
	src->device == dst->base.device &&
966
	_cairo_xlib_shm_surface_get_pixmap (src)) {
967
	cairo_xlib_proxy_t *proxy;
968

            
969
	proxy = _cairo_calloc (sizeof(*proxy));
970
	if (unlikely (proxy == NULL))
971
	    return _cairo_surface_create_in_error (CAIRO_STATUS_NO_MEMORY);
972

            
973
	_cairo_surface_init (&proxy->source.base,
974
			     &cairo_xlib_proxy_backend,
975
			     dst->base.device,
976
			     src->content,
977
			     src->is_vector);
978

            
979
	proxy->source.dpy = dst->display->display;
980
	proxy->source.picture = XRenderCreatePicture (proxy->source.dpy,
981
						      _cairo_xlib_shm_surface_get_pixmap (src),
982
						      _cairo_xlib_shm_surface_get_xrender_format (src),
983
						      0, NULL);
984
	proxy->source.pixmap = None;
985

            
986
	proxy->source.has_component_alpha = 0;
987
	proxy->source.has_matrix = 0;
988
	proxy->source.filter = CAIRO_FILTER_NEAREST;
989
	proxy->source.extend = CAIRO_EXTEND_NONE;
990
	proxy->owner = cairo_surface_reference (src);
991

            
992
	return embedded_source (dst, pattern, extents, src_x, src_y,
993
				&proxy->source);
994
    }
995

            
996
    upload = *sample;
997
    if (_cairo_surface_get_extents (pattern->surface, &limit)) {
998
	if (pattern->base.extend == CAIRO_EXTEND_NONE) {
999
	    if (! _cairo_rectangle_intersect (&upload, &limit))
		return alpha_source (dst, 0);
	} else if (pattern->base.extend == CAIRO_EXTEND_PAD) {
	    if (! _cairo_rectangle_intersect (&upload, &limit))
		upload = limit;
	} else {
	    if (upload.x < limit.x ||
		upload.x + upload.width > limit.x + limit.width ||
		upload.y < limit.y ||
		upload.y + upload.height > limit.y + limit.height)
	    {
		upload = limit;
	    }
	}
    }
    xsrc = (cairo_xlib_surface_t *)
	    _cairo_surface_create_scratch (&dst->base,
					   src->content,
					   upload.width,
					   upload.height,
					   NULL);
    if (xsrc->base.type != CAIRO_SURFACE_TYPE_XLIB) {
	cairo_surface_destroy (src);
	cairo_surface_destroy (&xsrc->base);
	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
    }
    if (_cairo_surface_is_image (src)) {
	status = _cairo_xlib_surface_draw_image (xsrc, (cairo_image_surface_t *)src,
						 upload.x, upload.y,
						 upload.width, upload.height,
						 0, 0);
    } else {
	cairo_image_surface_t *image;
	cairo_rectangle_int_t map_extents = { 0,0, upload.width,upload.height };
	image = _cairo_surface_map_to_image (&xsrc->base, &map_extents);
	_cairo_pattern_init_for_surface (&local_pattern, pattern->surface);
	cairo_matrix_init_translate (&local_pattern.base.matrix,
				     upload.x, upload.y);
	status = _cairo_surface_paint (&image->base,
				       CAIRO_OPERATOR_SOURCE,
				       &local_pattern.base,
				       NULL);
	_cairo_pattern_fini (&local_pattern.base);
	status = _cairo_surface_unmap_image (&xsrc->base, image);
	if (unlikely (status)) {
	    cairo_surface_destroy (&xsrc->base);
	    return _cairo_surface_create_in_error (status);
	}
	status = _cairo_xlib_surface_put_shm (xsrc);
	if (unlikely (status)) {
	    cairo_surface_destroy (&xsrc->base);
	    return _cairo_surface_create_in_error (status);
	}
    }
    _cairo_pattern_init_static_copy (&local_pattern.base, &pattern->base);
    if (upload.x | upload.y) {
	cairo_matrix_t m;
	cairo_matrix_init_translate (&m, -upload.x, -upload.y);
	cairo_matrix_multiply (&local_pattern.base.matrix,
			       &local_pattern.base.matrix,
			       &m);
    }
    *src_x = *src_y = 0;
    _cairo_xlib_surface_ensure_picture (xsrc);
    if (! picture_set_properties (xsrc->display,
				  xsrc->picture,
				  &local_pattern.base,
				  &local_pattern.base.matrix,
				  extents,
				  src_x, src_y))
    {
	cairo_surface_destroy (&xsrc->base);
	return render_pattern (dst, &pattern->base,
			       is_mask, extents,
			       src_x, src_y);
    }
    return &xsrc->base;
}
static cairo_bool_t
pattern_is_supported (cairo_xlib_display_t *display,
		      const cairo_pattern_t *pattern)
{
    if (pattern->type == CAIRO_PATTERN_TYPE_MESH)
	return FALSE;
    if (display->buggy_pad_reflect) {
	if (pattern->extend == CAIRO_EXTEND_REPEAT || pattern->extend == CAIRO_EXTEND_PAD)
	    return FALSE;
    }
    if (display->buggy_gradients) {
	if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR || pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
	    return FALSE;
    }
    switch (pattern->filter) {
    case CAIRO_FILTER_FAST:
    case CAIRO_FILTER_NEAREST:
	return CAIRO_RENDER_HAS_PICTURE_TRANSFORM (display) ||
	    _cairo_matrix_is_integer_translation (&pattern->matrix, NULL, NULL);
    case CAIRO_FILTER_GOOD:
	return CAIRO_RENDER_HAS_FILTER_GOOD (display);
    case CAIRO_FILTER_BEST:
	return CAIRO_RENDER_HAS_FILTER_BEST (display);
    case CAIRO_FILTER_BILINEAR:
    case CAIRO_FILTER_GAUSSIAN:
    default:
	return CAIRO_RENDER_HAS_FILTERS (display);
    }
}
cairo_surface_t *
_cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst,
				       const cairo_pattern_t *pattern,
				       cairo_bool_t is_mask,
				       const cairo_rectangle_int_t *extents,
				       const cairo_rectangle_int_t *sample,
				       int *src_x, int *src_y)
{
    cairo_xlib_surface_t *dst = (cairo_xlib_surface_t *)_dst;
    *src_x = *src_y = 0;
    if (pattern == NULL || pattern->type == CAIRO_PATTERN_TYPE_SOLID) {
	if (pattern == NULL)
	    pattern = &_cairo_pattern_white.base;
	return solid_source (dst, &((cairo_solid_pattern_t *)pattern)->color);
    }
    if (pattern_is_supported (dst->display, pattern)) {
	if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
	    cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *)pattern;
	    if (spattern->surface->type == CAIRO_SURFACE_TYPE_XLIB &&
		_cairo_xlib_surface_same_screen (dst,
						 unwrap_source (spattern)))
		return native_source (dst, spattern, is_mask,
				      extents, sample,
				      src_x, src_y);
	    if (spattern->surface->type == CAIRO_SURFACE_TYPE_RECORDING)
		return record_source (dst, spattern, is_mask,
				      extents, sample,
				      src_x, src_y);
	    return surface_source (dst, spattern, is_mask,
				   extents, sample,
				   src_x, src_y);
	}
	if (pattern->type == CAIRO_PATTERN_TYPE_LINEAR ||
	    pattern->type == CAIRO_PATTERN_TYPE_RADIAL)
	{
	    cairo_gradient_pattern_t *gpattern = (cairo_gradient_pattern_t *)pattern;
	    return gradient_source (dst, gpattern, is_mask, extents, src_x, src_y);
	}
    }
    return render_pattern (dst, pattern, is_mask, extents, src_x, src_y);
}
#endif /* !CAIRO_HAS_XLIB_XCB_FUNCTIONS */