Subversion Repositories Kolibri OS

Rev

Rev 1891 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1891 serge 1
/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
2
/*
3
 * Copyright © 2000 SuSE, Inc.
4
 * Copyright © 2007 Red Hat, Inc.
5
 *
6
 * Permission to use, copy, modify, distribute, and sell this software and its
7
 * documentation for any purpose is hereby granted without fee, provided that
8
 * the above copyright notice appear in all copies and that both that
9
 * copyright notice and this permission notice appear in supporting
10
 * documentation, and that the name of SuSE not be used in advertising or
11
 * publicity pertaining to distribution of the software without specific,
12
 * written prior permission.  SuSE makes no representations about the
13
 * suitability of this software for any purpose.  It is provided "as is"
14
 * without express or implied warranty.
15
 *
16
 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
18
 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20
 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21
 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
 *
23
 * Author:  Keith Packard, SuSE, Inc.
24
 */
25
 
26
#ifdef HAVE_CONFIG_H
27
#include 
28
#endif
29
#include "pixman-private.h"
30
 
31
#include 
32
 
3931 Serge 33
pixman_implementation_t *global_implementation;
34
 
35
#ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
36
static void __attribute__((constructor))
37
pixman_constructor (void)
1891 serge 38
{
3931 Serge 39
    global_implementation = _pixman_choose_implementation ();
1891 serge 40
}
3931 Serge 41
#endif
1891 serge 42
 
43
typedef struct operator_info_t operator_info_t;
44
 
45
struct operator_info_t
46
{
47
    uint8_t	opaque_info[4];
48
};
49
 
50
#define PACK(neither, src, dest, both)			\
51
    {{	    (uint8_t)PIXMAN_OP_ ## neither,		\
52
	    (uint8_t)PIXMAN_OP_ ## src,			\
53
	    (uint8_t)PIXMAN_OP_ ## dest,		\
54
	    (uint8_t)PIXMAN_OP_ ## both		}}
55
 
56
static const operator_info_t operator_table[] =
57
{
58
    /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
59
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
60
    PACK (SRC,                   SRC,                   SRC,                   SRC),
61
    PACK (DST,                   DST,                   DST,                   DST),
62
    PACK (OVER,                  SRC,                   OVER,                  SRC),
63
    PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
64
    PACK (IN,                    IN,                    SRC,                   SRC),
65
    PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
66
    PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
67
    PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
68
    PACK (ATOP,                  IN,                    OVER,                  SRC),
69
    PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
70
    PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
71
    PACK (ADD,                   ADD,                   ADD,                   ADD),
72
    PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
73
 
74
    {{ 0 /* 0x0e */ }},
75
    {{ 0 /* 0x0f */ }},
76
 
77
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
78
    PACK (SRC,                   SRC,                   SRC,                   SRC),
79
    PACK (DST,                   DST,                   DST,                   DST),
80
    PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
81
    PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
82
    PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
83
    PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
84
    PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
85
    PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
86
    PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
87
    PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
88
    PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
89
 
90
    {{ 0 /* 0x1c */ }},
91
    {{ 0 /* 0x1d */ }},
92
    {{ 0 /* 0x1e */ }},
93
    {{ 0 /* 0x1f */ }},
94
 
95
    PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
96
    PACK (SRC,                   SRC,                   SRC,                   SRC),
97
    PACK (DST,                   DST,                   DST,                   DST),
98
    PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
99
    PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
100
    PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
101
    PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
102
    PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
103
    PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
104
    PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
105
    PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
106
    PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
107
 
108
    {{ 0 /* 0x2c */ }},
109
    {{ 0 /* 0x2d */ }},
110
    {{ 0 /* 0x2e */ }},
111
    {{ 0 /* 0x2f */ }},
112
 
113
    PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
114
    PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
115
    PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
116
    PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
117
    PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
118
    PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
119
    PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
120
    PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
121
    PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
122
    PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
123
    PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
124
    PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
125
    PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
126
    PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
127
    PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
128
};
129
 
130
/*
131
 * Optimize the current operator based on opacity of source or destination
132
 * The output operator should be mathematically equivalent to the source.
133
 */
134
static pixman_op_t
135
optimize_operator (pixman_op_t     op,
136
		   uint32_t        src_flags,
137
		   uint32_t        mask_flags,
138
		   uint32_t        dst_flags)
139
{
140
    pixman_bool_t is_source_opaque, is_dest_opaque;
141
 
142
#define OPAQUE_SHIFT 13
143
 
144
    COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
145
 
146
    is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
147
    is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
148
 
149
    is_dest_opaque >>= OPAQUE_SHIFT - 1;
150
    is_source_opaque >>= OPAQUE_SHIFT;
151
 
152
    return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
153
}
154
 
155
/*
156
 * Computing composite region
157
 */
158
static inline pixman_bool_t
159
clip_general_image (pixman_region32_t * region,
160
                    pixman_region32_t * clip,
161
                    int                 dx,
162
                    int                 dy)
163
{
164
    if (pixman_region32_n_rects (region) == 1 &&
165
        pixman_region32_n_rects (clip) == 1)
166
    {
167
	pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
168
	pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
169
	int v;
170
 
171
	if (rbox->x1 < (v = cbox->x1 + dx))
172
	    rbox->x1 = v;
173
	if (rbox->x2 > (v = cbox->x2 + dx))
174
	    rbox->x2 = v;
175
	if (rbox->y1 < (v = cbox->y1 + dy))
176
	    rbox->y1 = v;
177
	if (rbox->y2 > (v = cbox->y2 + dy))
178
	    rbox->y2 = v;
179
	if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
180
	{
181
	    pixman_region32_init (region);
182
	    return FALSE;
183
	}
184
    }
185
    else if (!pixman_region32_not_empty (clip))
186
    {
187
	return FALSE;
188
    }
189
    else
190
    {
191
	if (dx || dy)
192
	    pixman_region32_translate (region, -dx, -dy);
193
 
194
	if (!pixman_region32_intersect (region, region, clip))
195
	    return FALSE;
196
 
197
	if (dx || dy)
198
	    pixman_region32_translate (region, dx, dy);
199
    }
200
 
201
    return pixman_region32_not_empty (region);
202
}
203
 
204
static inline pixman_bool_t
205
clip_source_image (pixman_region32_t * region,
206
                   pixman_image_t *    image,
207
                   int                 dx,
208
                   int                 dy)
209
{
210
    /* Source clips are ignored, unless they are explicitly turned on
211
     * and the clip in question was set by an X client. (Because if
212
     * the clip was not set by a client, then it is a hierarchy
213
     * clip and those should always be ignored for sources).
214
     */
215
    if (!image->common.clip_sources || !image->common.client_clip)
216
	return TRUE;
217
 
218
    return clip_general_image (region,
219
                               &image->common.clip_region,
220
                               dx, dy);
221
}
222
 
223
/*
224
 * returns FALSE if the final region is empty.  Indistinguishable from
225
 * an allocation failure, but rendering ignores those anyways.
226
 */
3931 Serge 227
pixman_bool_t
228
_pixman_compute_composite_region32 (pixman_region32_t * region,
229
				    pixman_image_t *    src_image,
230
				    pixman_image_t *    mask_image,
231
				    pixman_image_t *    dest_image,
232
				    int32_t             src_x,
233
				    int32_t             src_y,
234
				    int32_t             mask_x,
235
				    int32_t             mask_y,
236
				    int32_t             dest_x,
237
				    int32_t             dest_y,
238
				    int32_t             width,
239
				    int32_t             height)
1891 serge 240
{
241
    region->extents.x1 = dest_x;
242
    region->extents.x2 = dest_x + width;
243
    region->extents.y1 = dest_y;
244
    region->extents.y2 = dest_y + height;
245
 
246
    region->extents.x1 = MAX (region->extents.x1, 0);
247
    region->extents.y1 = MAX (region->extents.y1, 0);
3931 Serge 248
    region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
249
    region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
1891 serge 250
 
251
    region->data = 0;
252
 
253
    /* Check for empty operation */
254
    if (region->extents.x1 >= region->extents.x2 ||
255
        region->extents.y1 >= region->extents.y2)
256
    {
257
	region->extents.x1 = 0;
258
	region->extents.x2 = 0;
259
	region->extents.y1 = 0;
260
	region->extents.y2 = 0;
261
	return FALSE;
262
    }
263
 
3931 Serge 264
    if (dest_image->common.have_clip_region)
1891 serge 265
    {
3931 Serge 266
	if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
1891 serge 267
	    return FALSE;
268
    }
269
 
3931 Serge 270
    if (dest_image->common.alpha_map)
1891 serge 271
    {
272
	if (!pixman_region32_intersect_rect (region, region,
3931 Serge 273
					     dest_image->common.alpha_origin_x,
274
					     dest_image->common.alpha_origin_y,
275
					     dest_image->common.alpha_map->width,
276
					     dest_image->common.alpha_map->height))
1891 serge 277
	{
278
	    return FALSE;
279
	}
280
	if (!pixman_region32_not_empty (region))
281
	    return FALSE;
3931 Serge 282
	if (dest_image->common.alpha_map->common.have_clip_region)
1891 serge 283
	{
3931 Serge 284
	    if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
285
				     -dest_image->common.alpha_origin_x,
286
				     -dest_image->common.alpha_origin_y))
1891 serge 287
	    {
288
		return FALSE;
289
	    }
290
	}
291
    }
292
 
293
    /* clip against src */
294
    if (src_image->common.have_clip_region)
295
    {
296
	if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
297
	    return FALSE;
298
    }
299
    if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
300
    {
301
	if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
302
	                        dest_x - (src_x - src_image->common.alpha_origin_x),
303
	                        dest_y - (src_y - src_image->common.alpha_origin_y)))
304
	{
305
	    return FALSE;
306
	}
307
    }
308
    /* clip against mask */
309
    if (mask_image && mask_image->common.have_clip_region)
310
    {
311
	if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
312
	    return FALSE;
313
 
314
	if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
315
	{
316
	    if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
317
	                            dest_x - (mask_x - mask_image->common.alpha_origin_x),
318
	                            dest_y - (mask_y - mask_image->common.alpha_origin_y)))
319
	    {
320
		return FALSE;
321
	    }
322
	}
323
    }
324
 
325
    return TRUE;
326
}
327
 
328
typedef struct
329
{
3931 Serge 330
    pixman_fixed_48_16_t	x1;
331
    pixman_fixed_48_16_t	y1;
332
    pixman_fixed_48_16_t	x2;
333
    pixman_fixed_48_16_t	y2;
334
} box_48_16_t;
1891 serge 335
 
3931 Serge 336
static pixman_bool_t
337
compute_transformed_extents (pixman_transform_t *transform,
338
			     const pixman_box32_t *extents,
339
			     box_48_16_t *transformed)
1891 serge 340
{
3931 Serge 341
    pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
342
    pixman_fixed_t x1, y1, x2, y2;
1891 serge 343
    int i;
344
 
3931 Serge 345
    x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
346
    y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
347
    x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
348
    y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
1891 serge 349
 
3931 Serge 350
    if (!transform)
1891 serge 351
    {
3931 Serge 352
	transformed->x1 = x1;
353
	transformed->y1 = y1;
354
	transformed->x2 = x2;
355
	transformed->y2 = y2;
1891 serge 356
 
3931 Serge 357
	return TRUE;
1891 serge 358
    }
359
 
3931 Serge 360
    tx1 = ty1 = INT64_MAX;
361
    tx2 = ty2 = INT64_MIN;
362
 
363
    for (i = 0; i < 4; ++i)
1891 serge 364
    {
3931 Serge 365
	pixman_fixed_48_16_t tx, ty;
366
	pixman_vector_t v;
1891 serge 367
 
3931 Serge 368
	v.vector[0] = (i & 0x01)? x1 : x2;
369
	v.vector[1] = (i & 0x02)? y1 : y2;
370
	v.vector[2] = pixman_fixed_1;
1891 serge 371
 
3931 Serge 372
	if (!pixman_transform_point (transform, &v))
373
	    return FALSE;
1891 serge 374
 
3931 Serge 375
	tx = (pixman_fixed_48_16_t)v.vector[0];
376
	ty = (pixman_fixed_48_16_t)v.vector[1];
1891 serge 377
 
3931 Serge 378
	if (tx < tx1)
379
	    tx1 = tx;
380
	if (ty < ty1)
381
	    ty1 = ty;
382
	if (tx > tx2)
383
	    tx2 = tx;
384
	if (ty > ty2)
385
	    ty2 = ty;
1891 serge 386
    }
387
 
3931 Serge 388
    transformed->x1 = tx1;
389
    transformed->y1 = ty1;
390
    transformed->x2 = tx2;
391
    transformed->y2 = ty2;
1891 serge 392
 
393
    return TRUE;
394
}
395
 
396
#define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
3931 Serge 397
#define ABS(f)      (((f) < 0)?  (-(f)) : (f))
398
#define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
1891 serge 399
 
400
static pixman_bool_t
3931 Serge 401
analyze_extent (pixman_image_t       *image,
402
		const pixman_box32_t *extents,
403
		uint32_t             *flags)
1891 serge 404
{
405
    pixman_transform_t *transform;
406
    pixman_fixed_t x_off, y_off;
407
    pixman_fixed_t width, height;
3931 Serge 408
    pixman_fixed_t *params;
409
    box_48_16_t transformed;
410
    pixman_box32_t exp_extents;
1891 serge 411
 
412
    if (!image)
413
	return TRUE;
414
 
415
    /* Some compositing functions walk one step
416
     * outside the destination rectangle, so we
417
     * check here that the expanded-by-one source
418
     * extents in destination space fits in 16 bits
419
     */
3931 Serge 420
    if (!IS_16BIT (extents->x1 - 1)		||
421
	!IS_16BIT (extents->y1 - 1)		||
422
	!IS_16BIT (extents->x2 + 1)		||
423
	!IS_16BIT (extents->y2 + 1))
1891 serge 424
    {
425
	return FALSE;
426
    }
427
 
428
    transform = image->common.transform;
429
    if (image->common.type == BITS)
430
    {
431
	/* During repeat mode calculations we might convert the
432
	 * width/height of an image to fixed 16.16, so we need
433
	 * them to be smaller than 16 bits.
434
	 */
435
	if (image->bits.width >= 0x7fff	|| image->bits.height >= 0x7fff)
436
	    return FALSE;
437
 
3931 Serge 438
	if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
439
	    extents->x1 >= 0 &&
440
	    extents->y1 >= 0 &&
441
	    extents->x2 <= image->bits.width &&
442
	    extents->y2 <= image->bits.height)
1891 serge 443
	{
3931 Serge 444
	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
1891 serge 445
	    return TRUE;
446
	}
3931 Serge 447
 
1891 serge 448
	switch (image->common.filter)
449
	{
450
	case PIXMAN_FILTER_CONVOLUTION:
451
	    params = image->common.filter_params;
452
	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
453
	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
454
	    width = params[0];
455
	    height = params[1];
456
	    break;
457
 
3931 Serge 458
	case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
459
	    params = image->common.filter_params;
460
	    x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
461
	    y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
462
	    width = params[0];
463
	    height = params[1];
464
	    break;
465
 
1891 serge 466
	case PIXMAN_FILTER_GOOD:
467
	case PIXMAN_FILTER_BEST:
468
	case PIXMAN_FILTER_BILINEAR:
469
	    x_off = - pixman_fixed_1 / 2;
470
	    y_off = - pixman_fixed_1 / 2;
471
	    width = pixman_fixed_1;
472
	    height = pixman_fixed_1;
473
	    break;
474
 
475
	case PIXMAN_FILTER_FAST:
476
	case PIXMAN_FILTER_NEAREST:
477
	    x_off = - pixman_fixed_e;
478
	    y_off = - pixman_fixed_e;
479
	    width = 0;
480
	    height = 0;
481
	    break;
482
 
483
	default:
484
	    return FALSE;
485
	}
486
    }
487
    else
488
    {
489
	x_off = 0;
490
	y_off = 0;
491
	width = 0;
492
	height = 0;
493
    }
494
 
3931 Serge 495
    if (!compute_transformed_extents (transform, extents, &transformed))
496
	return FALSE;
497
 
498
    /* Expand the source area by a tiny bit so account of different rounding that
499
     * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
500
     * 0.5 so this won't cause the area computed to be overly pessimistic.
1891 serge 501
     */
3931 Serge 502
    transformed.x1 -= 8 * pixman_fixed_e;
503
    transformed.y1 -= 8 * pixman_fixed_e;
504
    transformed.x2 += 8 * pixman_fixed_e;
505
    transformed.y2 += 8 * pixman_fixed_e;
1891 serge 506
 
3931 Serge 507
    if (image->common.type == BITS)
508
    {
509
	if (pixman_fixed_to_int (transformed.x1) >= 0			&&
510
	    pixman_fixed_to_int (transformed.y1) >= 0			&&
511
	    pixman_fixed_to_int (transformed.x2) < image->bits.width	&&
512
	    pixman_fixed_to_int (transformed.y2) < image->bits.height)
513
	{
514
	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
515
	}
516
 
517
	if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0		  &&
518
	    pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0		  &&
519
	    pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
520
	    pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
521
	{
522
	    *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
523
	}
524
    }
525
 
526
    /* Check we don't overflow when the destination extents are expanded by one.
527
     * This ensures that compositing functions can simply walk the source space
528
     * using 16.16 variables without worrying about overflow.
529
     */
530
    exp_extents = *extents;
531
    exp_extents.x1 -= 1;
532
    exp_extents.y1 -= 1;
533
    exp_extents.x2 += 1;
534
    exp_extents.y2 += 1;
535
 
536
    if (!compute_transformed_extents (transform, &exp_extents, &transformed))
1891 serge 537
	return FALSE;
3931 Serge 538
 
539
    if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e)	||
540
	!IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e)	||
541
	!IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width)	||
542
	!IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
543
    {
544
	return FALSE;
545
    }
1891 serge 546
 
547
    return TRUE;
548
}
549
 
550
/*
551
 * Work around GCC bug causing crashes in Mozilla with SSE2
552
 *
553
 * When using -msse, gcc generates movdqa instructions assuming that
554
 * the stack is 16 byte aligned. Unfortunately some applications, such
555
 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
556
 * causes the movdqa instructions to fail.
557
 *
558
 * The __force_align_arg_pointer__ makes gcc generate a prologue that
559
 * realigns the stack pointer to 16 bytes.
560
 *
561
 * On x86-64 this is not necessary because the standard ABI already
562
 * calls for a 16 byte aligned stack.
563
 *
564
 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
565
 */
566
#if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
567
__attribute__((__force_align_arg_pointer__))
568
#endif
569
PIXMAN_EXPORT void
570
pixman_image_composite32 (pixman_op_t      op,
571
                          pixman_image_t * src,
572
                          pixman_image_t * mask,
573
                          pixman_image_t * dest,
574
                          int32_t          src_x,
575
                          int32_t          src_y,
576
                          int32_t          mask_x,
577
                          int32_t          mask_y,
578
                          int32_t          dest_x,
579
                          int32_t          dest_y,
580
                          int32_t          width,
581
                          int32_t          height)
582
{
583
    pixman_format_code_t src_format, mask_format, dest_format;
584
    pixman_region32_t region;
3931 Serge 585
    pixman_box32_t extents;
1891 serge 586
    pixman_implementation_t *imp;
587
    pixman_composite_func_t func;
3931 Serge 588
    pixman_composite_info_t info;
589
    const pixman_box32_t *pbox;
590
    int n;
1891 serge 591
 
592
    _pixman_image_validate (src);
593
    if (mask)
594
	_pixman_image_validate (mask);
595
    _pixman_image_validate (dest);
596
 
597
    src_format = src->common.extended_format_code;
3931 Serge 598
    info.src_flags = src->common.flags;
1891 serge 599
 
3931 Serge 600
    if (mask && !(mask->common.flags & FAST_PATH_IS_OPAQUE))
1891 serge 601
    {
602
	mask_format = mask->common.extended_format_code;
3931 Serge 603
	info.mask_flags = mask->common.flags;
1891 serge 604
    }
605
    else
606
    {
607
	mask_format = PIXMAN_null;
3931 Serge 608
	info.mask_flags = FAST_PATH_IS_OPAQUE;
1891 serge 609
    }
610
 
611
    dest_format = dest->common.extended_format_code;
3931 Serge 612
    info.dest_flags = dest->common.flags;
1891 serge 613
 
614
    /* Check for pixbufs */
615
    if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
616
	(src->type == BITS && src->bits.bits == mask->bits.bits)	   &&
617
	(src->common.repeat == mask->common.repeat)			   &&
3931 Serge 618
	(info.src_flags & info.mask_flags & FAST_PATH_ID_TRANSFORM)	   &&
1891 serge 619
	(src_x == mask_x && src_y == mask_y))
620
    {
621
	if (src_format == PIXMAN_x8b8g8r8)
622
	    src_format = mask_format = PIXMAN_pixbuf;
623
	else if (src_format == PIXMAN_x8r8g8b8)
624
	    src_format = mask_format = PIXMAN_rpixbuf;
625
    }
626
 
627
    pixman_region32_init (®ion);
628
 
3931 Serge 629
    if (!_pixman_compute_composite_region32 (
1891 serge 630
	    ®ion, src, mask, dest,
631
	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
632
    {
633
	goto out;
634
    }
635
 
3931 Serge 636
    extents = *pixman_region32_extents (®ion);
1891 serge 637
 
3931 Serge 638
    extents.x1 -= dest_x - src_x;
639
    extents.y1 -= dest_y - src_y;
640
    extents.x2 -= dest_x - src_x;
641
    extents.y2 -= dest_y - src_y;
642
 
643
    if (!analyze_extent (src, &extents, &info.src_flags))
1891 serge 644
	goto out;
645
 
3931 Serge 646
    extents.x1 -= src_x - mask_x;
647
    extents.y1 -= src_y - mask_y;
648
    extents.x2 -= src_x - mask_x;
649
    extents.y2 -= src_y - mask_y;
650
 
651
    if (!analyze_extent (mask, &extents, &info.mask_flags))
1891 serge 652
	goto out;
653
 
3931 Serge 654
    /* If the clip is within the source samples, and the samples are
655
     * opaque, then the source is effectively opaque.
1891 serge 656
     */
3931 Serge 657
#define NEAREST_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
658
			 FAST_PATH_NEAREST_FILTER |			\
659
			 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
660
#define BILINEAR_OPAQUE	(FAST_PATH_SAMPLES_OPAQUE |			\
661
			 FAST_PATH_BILINEAR_FILTER |			\
662
			 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
1891 serge 663
 
3931 Serge 664
    if ((info.src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
665
	(info.src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
666
    {
667
	info.src_flags |= FAST_PATH_IS_OPAQUE;
668
    }
669
 
670
    if ((info.mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
671
	(info.mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
672
    {
673
	info.mask_flags |= FAST_PATH_IS_OPAQUE;
674
    }
675
 
1891 serge 676
    /*
677
     * Check if we can replace our operator by a simpler one
678
     * if the src or dest are opaque. The output operator should be
679
     * mathematically equivalent to the source.
680
     */
3931 Serge 681
    info.op = optimize_operator (op, info.src_flags, info.mask_flags, info.dest_flags);
1891 serge 682
 
3931 Serge 683
    _pixman_implementation_lookup_composite (
684
	get_implementation (), info.op,
685
	src_format, info.src_flags,
686
	mask_format, info.mask_flags,
687
	dest_format, info.dest_flags,
688
	&imp, &func);
689
 
690
    info.src_image = src;
691
    info.mask_image = mask;
692
    info.dest_image = dest;
693
 
694
    pbox = pixman_region32_rectangles (®ion, &n);
695
 
696
    while (n--)
1891 serge 697
    {
3931 Serge 698
	info.src_x = pbox->x1 + src_x - dest_x;
699
	info.src_y = pbox->y1 + src_y - dest_y;
700
	info.mask_x = pbox->x1 + mask_x - dest_x;
701
	info.mask_y = pbox->y1 + mask_y - dest_y;
702
	info.dest_x = pbox->x1;
703
	info.dest_y = pbox->y1;
704
	info.width = pbox->x2 - pbox->x1;
705
	info.height = pbox->y2 - pbox->y1;
1891 serge 706
 
3931 Serge 707
	func (imp, &info);
708
 
709
	pbox++;
1891 serge 710
    }
711
 
712
out:
713
    pixman_region32_fini (®ion);
714
}
715
 
716
PIXMAN_EXPORT void
717
pixman_image_composite (pixman_op_t      op,
718
                        pixman_image_t * src,
719
                        pixman_image_t * mask,
720
                        pixman_image_t * dest,
721
                        int16_t          src_x,
722
                        int16_t          src_y,
723
                        int16_t          mask_x,
724
                        int16_t          mask_y,
725
                        int16_t          dest_x,
726
                        int16_t          dest_y,
727
                        uint16_t         width,
728
                        uint16_t         height)
729
{
730
    pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
731
                              mask_x, mask_y, dest_x, dest_y, width, height);
732
}
733
 
734
PIXMAN_EXPORT pixman_bool_t
735
pixman_blt (uint32_t *src_bits,
736
            uint32_t *dst_bits,
737
            int       src_stride,
738
            int       dst_stride,
739
            int       src_bpp,
740
            int       dst_bpp,
741
            int       src_x,
742
            int       src_y,
3931 Serge 743
            int       dest_x,
744
            int       dest_y,
1891 serge 745
            int       width,
746
            int       height)
747
{
748
    return _pixman_implementation_blt (get_implementation(),
749
				       src_bits, dst_bits, src_stride, dst_stride,
750
                                       src_bpp, dst_bpp,
751
                                       src_x, src_y,
3931 Serge 752
                                       dest_x, dest_y,
1891 serge 753
                                       width, height);
754
}
755
 
756
PIXMAN_EXPORT pixman_bool_t
757
pixman_fill (uint32_t *bits,
758
             int       stride,
759
             int       bpp,
760
             int       x,
761
             int       y,
762
             int       width,
763
             int       height,
3931 Serge 764
             uint32_t  filler)
1891 serge 765
{
766
    return _pixman_implementation_fill (
3931 Serge 767
	get_implementation(), bits, stride, bpp, x, y, width, height, filler);
1891 serge 768
}
769
 
770
static uint32_t
771
color_to_uint32 (const pixman_color_t *color)
772
{
773
    return
774
        (color->alpha >> 8 << 24) |
775
        (color->red >> 8 << 16) |
776
        (color->green & 0xff00) |
777
        (color->blue >> 8);
778
}
779
 
780
static pixman_bool_t
3931 Serge 781
color_to_pixel (const pixman_color_t *color,
782
                uint32_t *            pixel,
783
                pixman_format_code_t  format)
1891 serge 784
{
785
    uint32_t c = color_to_uint32 (color);
786
 
787
    if (!(format == PIXMAN_a8r8g8b8     ||
788
          format == PIXMAN_x8r8g8b8     ||
789
          format == PIXMAN_a8b8g8r8     ||
790
          format == PIXMAN_x8b8g8r8     ||
791
          format == PIXMAN_b8g8r8a8     ||
792
          format == PIXMAN_b8g8r8x8     ||
3931 Serge 793
          format == PIXMAN_r8g8b8a8     ||
794
          format == PIXMAN_r8g8b8x8     ||
1891 serge 795
          format == PIXMAN_r5g6b5       ||
796
          format == PIXMAN_b5g6r5       ||
3931 Serge 797
          format == PIXMAN_a8           ||
798
          format == PIXMAN_a1))
1891 serge 799
    {
800
	return FALSE;
801
    }
802
 
803
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
804
    {
805
	c = ((c & 0xff000000) >>  0) |
806
	    ((c & 0x00ff0000) >> 16) |
807
	    ((c & 0x0000ff00) >>  0) |
808
	    ((c & 0x000000ff) << 16);
809
    }
810
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
811
    {
812
	c = ((c & 0xff000000) >> 24) |
813
	    ((c & 0x00ff0000) >>  8) |
814
	    ((c & 0x0000ff00) <<  8) |
815
	    ((c & 0x000000ff) << 24);
816
    }
3931 Serge 817
    if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
818
	c = ((c & 0xff000000) >> 24) | (c << 8);
1891 serge 819
 
3931 Serge 820
    if (format == PIXMAN_a1)
821
	c = c >> 31;
822
    else if (format == PIXMAN_a8)
1891 serge 823
	c = c >> 24;
824
    else if (format == PIXMAN_r5g6b5 ||
825
             format == PIXMAN_b5g6r5)
3931 Serge 826
	c = convert_8888_to_0565 (c);
1891 serge 827
 
828
#if 0
829
    printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
830
    printf ("pixel: %x\n", c);
831
#endif
832
 
833
    *pixel = c;
834
    return TRUE;
835
}
836
 
837
PIXMAN_EXPORT pixman_bool_t
838
pixman_image_fill_rectangles (pixman_op_t                 op,
839
                              pixman_image_t *            dest,
3931 Serge 840
			      const pixman_color_t *      color,
1891 serge 841
                              int                         n_rects,
842
                              const pixman_rectangle16_t *rects)
843
{
844
    pixman_box32_t stack_boxes[6];
845
    pixman_box32_t *boxes;
846
    pixman_bool_t result;
847
    int i;
848
 
849
    if (n_rects > 6)
850
    {
851
        boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
852
        if (boxes == NULL)
853
            return FALSE;
854
    }
855
    else
856
    {
857
        boxes = stack_boxes;
858
    }
859
 
860
    for (i = 0; i < n_rects; ++i)
861
    {
862
        boxes[i].x1 = rects[i].x;
863
        boxes[i].y1 = rects[i].y;
864
        boxes[i].x2 = boxes[i].x1 + rects[i].width;
865
        boxes[i].y2 = boxes[i].y1 + rects[i].height;
866
    }
867
 
868
    result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
869
 
870
    if (boxes != stack_boxes)
871
        free (boxes);
872
 
873
    return result;
874
}
875
 
876
PIXMAN_EXPORT pixman_bool_t
877
pixman_image_fill_boxes (pixman_op_t           op,
878
                         pixman_image_t *      dest,
3931 Serge 879
                         const pixman_color_t *color,
1891 serge 880
                         int                   n_boxes,
881
                         const pixman_box32_t *boxes)
882
{
883
    pixman_image_t *solid;
884
    pixman_color_t c;
885
    int i;
886
 
887
    _pixman_image_validate (dest);
888
 
889
    if (color->alpha == 0xffff)
890
    {
891
        if (op == PIXMAN_OP_OVER)
892
            op = PIXMAN_OP_SRC;
893
    }
894
 
895
    if (op == PIXMAN_OP_CLEAR)
896
    {
897
        c.red = 0;
898
        c.green = 0;
899
        c.blue = 0;
900
        c.alpha = 0;
901
 
902
        color = &c;
903
 
904
        op = PIXMAN_OP_SRC;
905
    }
906
 
907
    if (op == PIXMAN_OP_SRC)
908
    {
909
        uint32_t pixel;
910
 
911
        if (color_to_pixel (color, &pixel, dest->bits.format))
912
        {
913
            pixman_region32_t fill_region;
914
            int n_rects, j;
915
            pixman_box32_t *rects;
916
 
917
            if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
918
                return FALSE;
919
 
920
            if (dest->common.have_clip_region)
921
            {
922
                if (!pixman_region32_intersect (&fill_region,
923
                                                &fill_region,
924
                                                &dest->common.clip_region))
925
                    return FALSE;
926
            }
927
 
928
            rects = pixman_region32_rectangles (&fill_region, &n_rects);
929
            for (j = 0; j < n_rects; ++j)
930
            {
931
                const pixman_box32_t *rect = &(rects[j]);
932
                pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
933
                             rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
934
                             pixel);
935
            }
936
 
937
            pixman_region32_fini (&fill_region);
938
            return TRUE;
939
        }
940
    }
941
 
942
    solid = pixman_image_create_solid_fill (color);
943
    if (!solid)
944
        return FALSE;
945
 
946
    for (i = 0; i < n_boxes; ++i)
947
    {
948
        const pixman_box32_t *box = &(boxes[i]);
949
 
950
        pixman_image_composite32 (op, solid, NULL, dest,
951
                                  0, 0, 0, 0,
952
                                  box->x1, box->y1,
953
                                  box->x2 - box->x1, box->y2 - box->y1);
954
    }
955
 
956
    pixman_image_unref (solid);
957
 
958
    return TRUE;
959
}
960
 
961
/**
962
 * pixman_version:
963
 *
964
 * Returns the version of the pixman library encoded in a single
965
 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
966
 * later versions compare greater than earlier versions.
967
 *
968
 * A run-time comparison to check that pixman's version is greater than
969
 * or equal to version X.Y.Z could be performed as follows:
970
 *
971
 * 
972
 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
973
 * 
974
 *
975
 * See also pixman_version_string() as well as the compile-time
976
 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
977
 *
978
 * Return value: the encoded version.
979
 **/
980
PIXMAN_EXPORT int
981
pixman_version (void)
982
{
983
    return PIXMAN_VERSION;
984
}
985
 
986
/**
987
 * pixman_version_string:
988
 *
989
 * Returns the version of the pixman library as a human-readable string
990
 * of the form "X.Y.Z".
991
 *
992
 * See also pixman_version() as well as the compile-time equivalents
993
 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
994
 *
995
 * Return value: a string containing the version.
996
 **/
997
PIXMAN_EXPORT const char*
998
pixman_version_string (void)
999
{
1000
    return PIXMAN_VERSION_STRING;
1001
}
1002
 
1003
/**
1004
 * pixman_format_supported_source:
1005
 * @format: A pixman_format_code_t format
1006
 *
1007
 * Return value: whether the provided format code is a supported
1008
 * format for a pixman surface used as a source in
1009
 * rendering.
1010
 *
1011
 * Currently, all pixman_format_code_t values are supported.
1012
 **/
1013
PIXMAN_EXPORT pixman_bool_t
1014
pixman_format_supported_source (pixman_format_code_t format)
1015
{
1016
    switch (format)
1017
    {
1018
    /* 32 bpp formats */
1019
    case PIXMAN_a2b10g10r10:
1020
    case PIXMAN_x2b10g10r10:
1021
    case PIXMAN_a2r10g10b10:
1022
    case PIXMAN_x2r10g10b10:
1023
    case PIXMAN_a8r8g8b8:
3931 Serge 1024
    case PIXMAN_a8r8g8b8_sRGB:
1891 serge 1025
    case PIXMAN_x8r8g8b8:
1026
    case PIXMAN_a8b8g8r8:
1027
    case PIXMAN_x8b8g8r8:
1028
    case PIXMAN_b8g8r8a8:
1029
    case PIXMAN_b8g8r8x8:
3931 Serge 1030
    case PIXMAN_r8g8b8a8:
1031
    case PIXMAN_r8g8b8x8:
1891 serge 1032
    case PIXMAN_r8g8b8:
1033
    case PIXMAN_b8g8r8:
1034
    case PIXMAN_r5g6b5:
1035
    case PIXMAN_b5g6r5:
1036
    case PIXMAN_x14r6g6b6:
1037
    /* 16 bpp formats */
1038
    case PIXMAN_a1r5g5b5:
1039
    case PIXMAN_x1r5g5b5:
1040
    case PIXMAN_a1b5g5r5:
1041
    case PIXMAN_x1b5g5r5:
1042
    case PIXMAN_a4r4g4b4:
1043
    case PIXMAN_x4r4g4b4:
1044
    case PIXMAN_a4b4g4r4:
1045
    case PIXMAN_x4b4g4r4:
1046
    /* 8bpp formats */
1047
    case PIXMAN_a8:
1048
    case PIXMAN_r3g3b2:
1049
    case PIXMAN_b2g3r3:
1050
    case PIXMAN_a2r2g2b2:
1051
    case PIXMAN_a2b2g2r2:
1052
    case PIXMAN_c8:
1053
    case PIXMAN_g8:
1054
    case PIXMAN_x4a4:
1055
    /* Collides with PIXMAN_c8
1056
       case PIXMAN_x4c4:
1057
     */
1058
    /* Collides with PIXMAN_g8
1059
       case PIXMAN_x4g4:
1060
     */
1061
    /* 4bpp formats */
1062
    case PIXMAN_a4:
1063
    case PIXMAN_r1g2b1:
1064
    case PIXMAN_b1g2r1:
1065
    case PIXMAN_a1r1g1b1:
1066
    case PIXMAN_a1b1g1r1:
1067
    case PIXMAN_c4:
1068
    case PIXMAN_g4:
1069
    /* 1bpp formats */
1070
    case PIXMAN_a1:
1071
    case PIXMAN_g1:
1072
    /* YUV formats */
1073
    case PIXMAN_yuy2:
1074
    case PIXMAN_yv12:
1075
	return TRUE;
1076
 
1077
    default:
1078
	return FALSE;
1079
    }
1080
}
1081
 
1082
/**
1083
 * pixman_format_supported_destination:
1084
 * @format: A pixman_format_code_t format
1085
 *
1086
 * Return value: whether the provided format code is a supported
1087
 * format for a pixman surface used as a destination in
1088
 * rendering.
1089
 *
1090
 * Currently, all pixman_format_code_t values are supported
1091
 * except for the YUV formats.
1092
 **/
1093
PIXMAN_EXPORT pixman_bool_t
1094
pixman_format_supported_destination (pixman_format_code_t format)
1095
{
1096
    /* YUV formats cannot be written to at the moment */
1097
    if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1098
	return FALSE;
1099
 
1100
    return pixman_format_supported_source (format);
1101
}
1102
 
1103
PIXMAN_EXPORT pixman_bool_t
1104
pixman_compute_composite_region (pixman_region16_t * region,
1105
                                 pixman_image_t *    src_image,
1106
                                 pixman_image_t *    mask_image,
3931 Serge 1107
                                 pixman_image_t *    dest_image,
1891 serge 1108
                                 int16_t             src_x,
1109
                                 int16_t             src_y,
1110
                                 int16_t             mask_x,
1111
                                 int16_t             mask_y,
1112
                                 int16_t             dest_x,
1113
                                 int16_t             dest_y,
1114
                                 uint16_t            width,
1115
                                 uint16_t            height)
1116
{
1117
    pixman_region32_t r32;
1118
    pixman_bool_t retval;
1119
 
1120
    pixman_region32_init (&r32);
1121
 
3931 Serge 1122
    retval = _pixman_compute_composite_region32 (
1123
	&r32, src_image, mask_image, dest_image,
1891 serge 1124
	src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1125
	width, height);
1126
 
1127
    if (retval)
1128
    {
1129
	if (!pixman_region16_copy_from_region32 (region, &r32))
1130
	    retval = FALSE;
1131
    }
1132
 
1133
    pixman_region32_fini (&r32);
1134
    return retval;
1135
}