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 <config.h>
28 #endif
29 #include "pixman-private.h"
30 
31 #include <stdlib.h>
32 
33 static pixman_implementation_t *imp;
34 
35 typedef struct operator_info_t operator_info_t;
36 
37 struct operator_info_t
38 {
39     uint8_t	opaque_info[4];
40 };
41 
42 #define PACK(neither, src, dest, both)			\
43     {{	    (uint8_t)PIXMAN_OP_ ## neither,		\
44 	    (uint8_t)PIXMAN_OP_ ## src,			\
45 	    (uint8_t)PIXMAN_OP_ ## dest,		\
46 	    (uint8_t)PIXMAN_OP_ ## both		}}
47 
48 static const operator_info_t operator_table[] =
49 {
50     /*    Neither Opaque         Src Opaque             Dst Opaque             Both Opaque */
51     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
52     PACK (SRC,                   SRC,                   SRC,                   SRC),
53     PACK (DST,                   DST,                   DST,                   DST),
54     PACK (OVER,                  SRC,                   OVER,                  SRC),
55     PACK (OVER_REVERSE,          OVER_REVERSE,          DST,                   DST),
56     PACK (IN,                    IN,                    SRC,                   SRC),
57     PACK (IN_REVERSE,            DST,                   IN_REVERSE,            DST),
58     PACK (OUT,                   OUT,                   CLEAR,                 CLEAR),
59     PACK (OUT_REVERSE,           CLEAR,                 OUT_REVERSE,           CLEAR),
60     PACK (ATOP,                  IN,                    OVER,                  SRC),
61     PACK (ATOP_REVERSE,          OVER_REVERSE,          IN_REVERSE,            DST),
62     PACK (XOR,                   OUT,                   OUT_REVERSE,           CLEAR),
63     PACK (ADD,                   ADD,                   ADD,                   ADD),
64     PACK (SATURATE,              OVER_REVERSE,          DST,                   DST),
65 
66     {{ 0 /* 0x0e */ }},
67     {{ 0 /* 0x0f */ }},
68 
69     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
70     PACK (SRC,                   SRC,                   SRC,                   SRC),
71     PACK (DST,                   DST,                   DST,                   DST),
72     PACK (DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER,         DISJOINT_OVER),
73     PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
74     PACK (DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN,           DISJOINT_IN),
75     PACK (DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE,   DISJOINT_IN_REVERSE),
76     PACK (DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT,          DISJOINT_OUT),
77     PACK (DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE,  DISJOINT_OUT_REVERSE),
78     PACK (DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP,         DISJOINT_ATOP),
79     PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
80     PACK (DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR,          DISJOINT_XOR),
81 
82     {{ 0 /* 0x1c */ }},
83     {{ 0 /* 0x1d */ }},
84     {{ 0 /* 0x1e */ }},
85     {{ 0 /* 0x1f */ }},
86 
87     PACK (CLEAR,                 CLEAR,                 CLEAR,                 CLEAR),
88     PACK (SRC,                   SRC,                   SRC,                   SRC),
89     PACK (DST,                   DST,                   DST,                   DST),
90     PACK (CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER,         CONJOINT_OVER),
91     PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
92     PACK (CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN,           CONJOINT_IN),
93     PACK (CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE,   CONJOINT_IN_REVERSE),
94     PACK (CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT,          CONJOINT_OUT),
95     PACK (CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE,  CONJOINT_OUT_REVERSE),
96     PACK (CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP,         CONJOINT_ATOP),
97     PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
98     PACK (CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR,          CONJOINT_XOR),
99 
100     {{ 0 /* 0x2c */ }},
101     {{ 0 /* 0x2d */ }},
102     {{ 0 /* 0x2e */ }},
103     {{ 0 /* 0x2f */ }},
104 
105     PACK (MULTIPLY,              MULTIPLY,              MULTIPLY,              MULTIPLY),
106     PACK (SCREEN,                SCREEN,                SCREEN,                SCREEN),
107     PACK (OVERLAY,               OVERLAY,               OVERLAY,               OVERLAY),
108     PACK (DARKEN,                DARKEN,                DARKEN,                DARKEN),
109     PACK (LIGHTEN,               LIGHTEN,               LIGHTEN,               LIGHTEN),
110     PACK (COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE,           COLOR_DODGE),
111     PACK (COLOR_BURN,            COLOR_BURN,            COLOR_BURN,            COLOR_BURN),
112     PACK (HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT,            HARD_LIGHT),
113     PACK (SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT,            SOFT_LIGHT),
114     PACK (DIFFERENCE,            DIFFERENCE,            DIFFERENCE,            DIFFERENCE),
115     PACK (EXCLUSION,             EXCLUSION,             EXCLUSION,             EXCLUSION),
116     PACK (HSL_HUE,               HSL_HUE,               HSL_HUE,               HSL_HUE),
117     PACK (HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION,        HSL_SATURATION),
118     PACK (HSL_COLOR,             HSL_COLOR,             HSL_COLOR,             HSL_COLOR),
119     PACK (HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY,        HSL_LUMINOSITY),
120 };
121 
122 /*
123  * Optimize the current operator based on opacity of source or destination
124  * The output operator should be mathematically equivalent to the source.
125  */
126 static pixman_op_t
optimize_operator(pixman_op_t op,uint32_t src_flags,uint32_t mask_flags,uint32_t dst_flags)127 optimize_operator (pixman_op_t     op,
128 		   uint32_t        src_flags,
129 		   uint32_t        mask_flags,
130 		   uint32_t        dst_flags)
131 {
132     pixman_bool_t is_source_opaque, is_dest_opaque;
133     int opaqueness;
134 
135     is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0;
136     is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0;
137 
138     opaqueness = ((is_dest_opaque << 1) | is_source_opaque);
139 
140     return operator_table[op].opaque_info[opaqueness];
141 }
142 
143 static void
apply_workaround(pixman_image_t * image,int32_t * x,int32_t * y,uint32_t ** save_bits,int * save_dx,int * save_dy)144 apply_workaround (pixman_image_t *image,
145 		  int32_t *       x,
146 		  int32_t *       y,
147 		  uint32_t **     save_bits,
148 		  int *           save_dx,
149 		  int *           save_dy)
150 {
151     if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
152     {
153 	/* Some X servers generate images that point to the
154 	 * wrong place in memory, but then set the clip region
155 	 * to point to the right place. Because of an old bug
156 	 * in pixman, this would actually work.
157 	 *
158 	 * Here we try and undo the damage
159 	 */
160 	int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
161 	pixman_box32_t *extents;
162 	uint8_t *t;
163 	int dx, dy;
164 
165 	extents = pixman_region32_extents (&(image->common.clip_region));
166 	dx = extents->x1;
167 	dy = extents->y1;
168 
169 	*save_bits = image->bits.bits;
170 
171 	*x -= dx;
172 	*y -= dy;
173 	pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
174 
175 	t = (uint8_t *)image->bits.bits;
176 	t += dy * image->bits.rowstride * 4 + dx * bpp;
177 	image->bits.bits = (uint32_t *)t;
178 
179 	*save_dx = dx;
180 	*save_dy = dy;
181     }
182 }
183 
184 static void
unapply_workaround(pixman_image_t * image,uint32_t * bits,int dx,int dy)185 unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
186 {
187     if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
188     {
189 	image->bits.bits = bits;
190 	pixman_region32_translate (&image->common.clip_region, dx, dy);
191     }
192 }
193 
194 /*
195  * Computing composite region
196  */
197 static inline pixman_bool_t
clip_general_image(pixman_region32_t * region,pixman_region32_t * clip,int dx,int dy)198 clip_general_image (pixman_region32_t * region,
199                     pixman_region32_t * clip,
200                     int                 dx,
201                     int                 dy)
202 {
203     if (pixman_region32_n_rects (region) == 1 &&
204         pixman_region32_n_rects (clip) == 1)
205     {
206 	pixman_box32_t *  rbox = pixman_region32_rectangles (region, NULL);
207 	pixman_box32_t *  cbox = pixman_region32_rectangles (clip, NULL);
208 	int v;
209 
210 	if (rbox->x1 < (v = cbox->x1 + dx))
211 	    rbox->x1 = v;
212 	if (rbox->x2 > (v = cbox->x2 + dx))
213 	    rbox->x2 = v;
214 	if (rbox->y1 < (v = cbox->y1 + dy))
215 	    rbox->y1 = v;
216 	if (rbox->y2 > (v = cbox->y2 + dy))
217 	    rbox->y2 = v;
218 	if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
219 	{
220 	    pixman_region32_init (region);
221 	    return FALSE;
222 	}
223     }
224     else if (!pixman_region32_not_empty (clip))
225     {
226 	return FALSE;
227     }
228     else
229     {
230 	if (dx || dy)
231 	    pixman_region32_translate (region, -dx, -dy);
232 
233 	if (!pixman_region32_intersect (region, region, clip))
234 	    return FALSE;
235 
236 	if (dx || dy)
237 	    pixman_region32_translate (region, dx, dy);
238     }
239 
240     return pixman_region32_not_empty (region);
241 }
242 
243 static inline pixman_bool_t
clip_source_image(pixman_region32_t * region,pixman_image_t * image,int dx,int dy)244 clip_source_image (pixman_region32_t * region,
245                    pixman_image_t *    image,
246                    int                 dx,
247                    int                 dy)
248 {
249     /* Source clips are ignored, unless they are explicitly turned on
250      * and the clip in question was set by an X client. (Because if
251      * the clip was not set by a client, then it is a hierarchy
252      * clip and those should always be ignored for sources).
253      */
254     if (!image->common.clip_sources || !image->common.client_clip)
255 	return TRUE;
256 
257     return clip_general_image (region,
258                                &image->common.clip_region,
259                                dx, dy);
260 }
261 
262 /*
263  * returns FALSE if the final region is empty.  Indistinguishable from
264  * an allocation failure, but rendering ignores those anyways.
265  */
266 static pixman_bool_t
pixman_compute_composite_region32(pixman_region32_t * region,pixman_image_t * src_image,pixman_image_t * mask_image,pixman_image_t * dst_image,int32_t src_x,int32_t src_y,int32_t mask_x,int32_t mask_y,int32_t dest_x,int32_t dest_y,int32_t width,int32_t height)267 pixman_compute_composite_region32 (pixman_region32_t * region,
268                                    pixman_image_t *    src_image,
269                                    pixman_image_t *    mask_image,
270                                    pixman_image_t *    dst_image,
271                                    int32_t             src_x,
272                                    int32_t             src_y,
273                                    int32_t             mask_x,
274                                    int32_t             mask_y,
275                                    int32_t             dest_x,
276                                    int32_t             dest_y,
277                                    int32_t             width,
278                                    int32_t             height)
279 {
280     region->extents.x1 = dest_x;
281     region->extents.x2 = dest_x + width;
282     region->extents.y1 = dest_y;
283     region->extents.y2 = dest_y + height;
284 
285     region->extents.x1 = MAX (region->extents.x1, 0);
286     region->extents.y1 = MAX (region->extents.y1, 0);
287     region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
288     region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
289 
290     region->data = 0;
291 
292     /* Check for empty operation */
293     if (region->extents.x1 >= region->extents.x2 ||
294         region->extents.y1 >= region->extents.y2)
295     {
296 	pixman_region32_init (region);
297 	return FALSE;
298     }
299 
300     if (dst_image->common.have_clip_region)
301     {
302 	if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
303 	{
304 	    pixman_region32_fini (region);
305 	    return FALSE;
306 	}
307     }
308 
309     if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
310     {
311 	if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
312 	                         -dst_image->common.alpha_origin_x,
313 	                         -dst_image->common.alpha_origin_y))
314 	{
315 	    pixman_region32_fini (region);
316 	    return FALSE;
317 	}
318     }
319 
320     /* clip against src */
321     if (src_image->common.have_clip_region)
322     {
323 	if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
324 	{
325 	    pixman_region32_fini (region);
326 	    return FALSE;
327 	}
328     }
329     if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
330     {
331 	if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
332 	                        dest_x - (src_x - src_image->common.alpha_origin_x),
333 	                        dest_y - (src_y - src_image->common.alpha_origin_y)))
334 	{
335 	    pixman_region32_fini (region);
336 	    return FALSE;
337 	}
338     }
339     /* clip against mask */
340     if (mask_image && mask_image->common.have_clip_region)
341     {
342 	if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
343 	{
344 	    pixman_region32_fini (region);
345 	    return FALSE;
346 	}
347 	if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
348 	{
349 	    if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
350 	                            dest_x - (mask_x - mask_image->common.alpha_origin_x),
351 	                            dest_y - (mask_y - mask_image->common.alpha_origin_y)))
352 	    {
353 		pixman_region32_fini (region);
354 		return FALSE;
355 	    }
356 	}
357     }
358 
359     return TRUE;
360 }
361 
362 static void
walk_region_internal(pixman_implementation_t * imp,pixman_op_t op,pixman_image_t * src_image,pixman_image_t * mask_image,pixman_image_t * dst_image,int32_t src_x,int32_t src_y,int32_t mask_x,int32_t mask_y,int32_t dest_x,int32_t dest_y,int32_t width,int32_t height,pixman_bool_t src_repeat,pixman_bool_t mask_repeat,pixman_region32_t * region,pixman_composite_func_t composite_rect)363 walk_region_internal (pixman_implementation_t *imp,
364                       pixman_op_t              op,
365                       pixman_image_t *         src_image,
366                       pixman_image_t *         mask_image,
367                       pixman_image_t *         dst_image,
368                       int32_t                  src_x,
369                       int32_t                  src_y,
370                       int32_t                  mask_x,
371                       int32_t                  mask_y,
372                       int32_t                  dest_x,
373                       int32_t                  dest_y,
374                       int32_t                  width,
375                       int32_t                  height,
376                       pixman_bool_t            src_repeat,
377                       pixman_bool_t            mask_repeat,
378                       pixman_region32_t *      region,
379                       pixman_composite_func_t  composite_rect)
380 {
381     int w, h, w_this, h_this;
382     int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
383     int src_dy = src_y - dest_y;
384     int src_dx = src_x - dest_x;
385     int mask_dy = mask_y - dest_y;
386     int mask_dx = mask_x - dest_x;
387     const pixman_box32_t *pbox;
388     int n;
389 
390     pbox = pixman_region32_rectangles (region, &n);
391 
392     /* Fast path for non-repeating sources */
393     if (!src_repeat && !mask_repeat)
394     {
395        while (n--)
396        {
397            (*composite_rect) (imp, op,
398                               src_image, mask_image, dst_image,
399                               pbox->x1 + src_dx,
400                               pbox->y1 + src_dy,
401                               pbox->x1 + mask_dx,
402                               pbox->y1 + mask_dy,
403                               pbox->x1,
404                               pbox->y1,
405                               pbox->x2 - pbox->x1,
406                               pbox->y2 - pbox->y1);
407 
408            pbox++;
409        }
410 
411        return;
412     }
413 
414     while (n--)
415     {
416 	h = pbox->y2 - pbox->y1;
417 	y_src = pbox->y1 + src_dy;
418 	y_msk = pbox->y1 + mask_dy;
419 	y_dst = pbox->y1;
420 
421 	while (h)
422 	{
423 	    h_this = h;
424 	    w = pbox->x2 - pbox->x1;
425 	    x_src = pbox->x1 + src_dx;
426 	    x_msk = pbox->x1 + mask_dx;
427 	    x_dst = pbox->x1;
428 
429 	    if (mask_repeat)
430 	    {
431 		y_msk = MOD (y_msk, mask_image->bits.height);
432 		if (h_this > mask_image->bits.height - y_msk)
433 		    h_this = mask_image->bits.height - y_msk;
434 	    }
435 
436 	    if (src_repeat)
437 	    {
438 		y_src = MOD (y_src, src_image->bits.height);
439 		if (h_this > src_image->bits.height - y_src)
440 		    h_this = src_image->bits.height - y_src;
441 	    }
442 
443 	    while (w)
444 	    {
445 		w_this = w;
446 
447 		if (mask_repeat)
448 		{
449 		    x_msk = MOD (x_msk, mask_image->bits.width);
450 		    if (w_this > mask_image->bits.width - x_msk)
451 			w_this = mask_image->bits.width - x_msk;
452 		}
453 
454 		if (src_repeat)
455 		{
456 		    x_src = MOD (x_src, src_image->bits.width);
457 		    if (w_this > src_image->bits.width - x_src)
458 			w_this = src_image->bits.width - x_src;
459 		}
460 
461 		(*composite_rect) (imp, op,
462 				   src_image, mask_image, dst_image,
463 				   x_src, y_src, x_msk, y_msk, x_dst, y_dst,
464 				   w_this, h_this);
465 		w -= w_this;
466 
467 		x_src += w_this;
468 		x_msk += w_this;
469 		x_dst += w_this;
470 	    }
471 
472 	    h -= h_this;
473 	    y_src += h_this;
474 	    y_msk += h_this;
475 	    y_dst += h_this;
476 	}
477 
478 	pbox++;
479     }
480 }
481 
482 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
483 
484 static force_inline uint32_t
compute_src_extents_flags(pixman_image_t * image,pixman_box32_t * extents,int x,int y)485 compute_src_extents_flags (pixman_image_t *image,
486 			   pixman_box32_t *extents,
487 			   int             x,
488 			   int             y)
489 {
490     pixman_box16_t extents16;
491     uint32_t flags;
492 
493     flags = FAST_PATH_COVERS_CLIP;
494 
495     if (image->common.type != BITS)
496 	return flags;
497 
498     if (image->common.repeat == PIXMAN_REPEAT_NONE &&
499 	(x > extents->x1 || y > extents->y1 ||
500 	 x + image->bits.width < extents->x2 ||
501 	 y + image->bits.height < extents->y2))
502     {
503 	flags &= ~FAST_PATH_COVERS_CLIP;
504     }
505 
506     if (IS_16BIT (extents->x1 - x) &&
507 	IS_16BIT (extents->y1 - y) &&
508 	IS_16BIT (extents->x2 - x) &&
509 	IS_16BIT (extents->y2 - y))
510     {
511 	extents16.x1 = extents->x1 - x;
512 	extents16.y1 = extents->y1 - y;
513 	extents16.x2 = extents->x2 - x;
514 	extents16.y2 = extents->y2 - y;
515 
516 	if (!image->common.transform ||
517 	    pixman_transform_bounds (image->common.transform, &extents16))
518 	{
519 	    if (extents16.x1 >= 0  && extents16.y1 >= 0 &&
520 		extents16.x2 <= image->bits.width &&
521 		extents16.y2 <= image->bits.height)
522 	    {
523 		flags |= FAST_PATH_SAMPLES_COVER_CLIP;
524 	    }
525 	}
526     }
527 
528     if (IS_16BIT (extents->x1 - x - 1) &&
529 	IS_16BIT (extents->y1 - y - 1) &&
530 	IS_16BIT (extents->x2 - x + 1) &&
531 	IS_16BIT (extents->y2 - y + 1))
532     {
533 	extents16.x1 = extents->x1 - x - 1;
534 	extents16.y1 = extents->y1 - y - 1;
535 	extents16.x2 = extents->x2 - x + 1;
536 	extents16.y2 = extents->y2 - y + 1;
537 
538 	if (/* src space expanded by one in dest space fits in 16 bit */
539 	    (!image->common.transform ||
540 	     pixman_transform_bounds (image->common.transform, &extents16)) &&
541 	    /* And src image size can be used as 16.16 fixed point */
542 	    image->bits.width < 0x7fff &&
543 	    image->bits.height < 0x7fff)
544 	{
545 	    /* Then we're "16bit safe" */
546 	    flags |= FAST_PATH_16BIT_SAFE;
547 	}
548     }
549 
550     return flags;
551 }
552 
553 #define N_CACHED_FAST_PATHS 8
554 
555 typedef struct
556 {
557     pixman_fast_path_t cache [N_CACHED_FAST_PATHS];
558 } cache_t;
559 
560 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
561 
562 static void
do_composite(pixman_implementation_t * imp,pixman_op_t op,pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,int src_x,int src_y,int mask_x,int mask_y,int dest_x,int dest_y,int width,int height)563 do_composite (pixman_implementation_t *imp,
564 	      pixman_op_t	       op,
565 	      pixman_image_t	      *src,
566 	      pixman_image_t	      *mask,
567 	      pixman_image_t	      *dest,
568 	      int		       src_x,
569 	      int		       src_y,
570 	      int		       mask_x,
571 	      int		       mask_y,
572 	      int		       dest_x,
573 	      int		       dest_y,
574 	      int		       width,
575 	      int		       height)
576 {
577     pixman_format_code_t src_format, mask_format, dest_format;
578     uint32_t src_flags, mask_flags, dest_flags;
579     pixman_region32_t region;
580     pixman_box32_t *extents;
581     uint32_t *src_bits;
582     int src_dx, src_dy;
583     uint32_t *mask_bits;
584     int mask_dx, mask_dy;
585     uint32_t *dest_bits;
586     int dest_dx, dest_dy;
587     pixman_bool_t need_workaround;
588     const pixman_fast_path_t *info;
589     cache_t *cache;
590     int i;
591 
592     src_format = src->common.extended_format_code;
593     src_flags = src->common.flags;
594 
595     if (mask)
596     {
597 	mask_format = mask->common.extended_format_code;
598 	mask_flags = mask->common.flags;
599     }
600     else
601     {
602 	mask_format = PIXMAN_null;
603 	mask_flags = FAST_PATH_IS_OPAQUE;
604     }
605 
606     dest_format = dest->common.extended_format_code;
607     dest_flags = dest->common.flags;
608 
609     /* Check for pixbufs */
610     if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
611 	(src->type == BITS && src->bits.bits == mask->bits.bits)	   &&
612 	(src->common.repeat == mask->common.repeat)			   &&
613 	(src_x == mask_x && src_y == mask_y))
614     {
615 	if (src_format == PIXMAN_x8b8g8r8)
616 	    src_format = mask_format = PIXMAN_pixbuf;
617 	else if (src_format == PIXMAN_x8r8g8b8)
618 	    src_format = mask_format = PIXMAN_rpixbuf;
619     }
620 
621     /* Check for workaround */
622     need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
623 
624     if (need_workaround)
625     {
626 	apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
627 	apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
628 	apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
629     }
630 
631     pixman_region32_init (&region);
632 
633     if (!pixman_compute_composite_region32 (
634 	    &region, src, mask, dest,
635 	    src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
636     {
637 	goto out;
638     }
639 
640     extents = pixman_region32_extents (&region);
641 
642     src_flags |= compute_src_extents_flags (src, extents, dest_x - src_x, dest_y - src_y);
643 
644     if (mask)
645 	mask_flags |= compute_src_extents_flags (mask, extents, dest_x - mask_x, dest_y - mask_y);
646 
647     /*
648      * Check if we can replace our operator by a simpler one
649      * if the src or dest are opaque. The output operator should be
650      * mathematically equivalent to the source.
651      */
652     op = optimize_operator (op, src_flags, mask_flags, dest_flags);
653     if (op == PIXMAN_OP_DST)
654 	goto out;
655 
656     /* Check cache for fast paths */
657     cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
658 
659     for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
660     {
661 	info = &(cache->cache[i]);
662 
663 	/* Note that we check for equality here, not whether
664 	 * the cached fast path matches. This is to prevent
665 	 * us from selecting an overly general fast path
666 	 * when a more specific one would work.
667 	 */
668 	if (info->op == op			&&
669 	    info->src_format == src_format	&&
670 	    info->mask_format == mask_format	&&
671 	    info->dest_format == dest_format	&&
672 	    info->src_flags == src_flags	&&
673 	    info->mask_flags == mask_flags	&&
674 	    info->dest_flags == dest_flags	&&
675 	    info->func)
676 	{
677 	    goto found;
678 	}
679     }
680 
681     while (imp)
682     {
683 	info = imp->fast_paths;
684 
685 	while (info->op != PIXMAN_OP_NONE)
686 	{
687 	    if ((info->op == op || info->op == PIXMAN_OP_any)		&&
688 		/* Formats */
689 		((info->src_format == src_format) ||
690 		 (info->src_format == PIXMAN_any))			&&
691 		((info->mask_format == mask_format) ||
692 		 (info->mask_format == PIXMAN_any))			&&
693 		((info->dest_format == dest_format) ||
694 		 (info->dest_format == PIXMAN_any))			&&
695 		/* Flags */
696 		(info->src_flags & src_flags) == info->src_flags	&&
697 		(info->mask_flags & mask_flags) == info->mask_flags	&&
698 		(info->dest_flags & dest_flags) == info->dest_flags)
699 	    {
700 		/* Set i to the last spot in the cache so that the
701 		 * move-to-front code below will work
702 		 */
703 		i = N_CACHED_FAST_PATHS - 1;
704 
705 		goto found;
706 	    }
707 
708 	    ++info;
709 	}
710 
711 	imp = imp->delegate;
712     }
713 
714     /* We didn't find a compositing routine. This should not happen, but if
715      * it somehow does, just exit rather than crash.
716      */
717     goto out;
718 
719 found:
720     walk_region_internal (imp, op,
721 			  src, mask, dest,
722 			  src_x, src_y, mask_x, mask_y,
723 			  dest_x, dest_y,
724 			  width, height,
725 			  (src_flags & FAST_PATH_SIMPLE_REPEAT),
726 			  (mask_flags & FAST_PATH_SIMPLE_REPEAT),
727 			  &region, info->func);
728 
729     if (i)
730     {
731 	/* Make a copy of info->func, because info->func may change when
732 	 * we update the cache.
733 	 */
734 	pixman_composite_func_t func = info->func;
735 
736 	while (i--)
737 	    cache->cache[i + 1] = cache->cache[i];
738 
739 	cache->cache[0].op = op;
740 	cache->cache[0].src_format = src_format;
741 	cache->cache[0].src_flags = src_flags;
742 	cache->cache[0].mask_format = mask_format;
743 	cache->cache[0].mask_flags = mask_flags;
744 	cache->cache[0].dest_format = dest_format;
745 	cache->cache[0].dest_flags = dest_flags;
746 	cache->cache[0].func = func;
747     }
748 
749 out:
750     if (need_workaround)
751     {
752 	unapply_workaround (src, src_bits, src_dx, src_dy);
753 	unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
754 	unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
755     }
756 
757     pixman_region32_fini (&region);
758 }
759 
760 PIXMAN_EXPORT void
pixman_image_composite(pixman_op_t op,pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,int16_t src_x,int16_t src_y,int16_t mask_x,int16_t mask_y,int16_t dest_x,int16_t dest_y,uint16_t width,uint16_t height)761 pixman_image_composite (pixman_op_t      op,
762                         pixman_image_t * src,
763                         pixman_image_t * mask,
764                         pixman_image_t * dest,
765                         int16_t          src_x,
766                         int16_t          src_y,
767                         int16_t          mask_x,
768                         int16_t          mask_y,
769                         int16_t          dest_x,
770                         int16_t          dest_y,
771                         uint16_t         width,
772                         uint16_t         height)
773 {
774     pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
775                               mask_x, mask_y, dest_x, dest_y, width, height);
776 }
777 
778 /*
779  * Work around GCC bug causing crashes in Mozilla with SSE2
780  *
781  * When using -msse, gcc generates movdqa instructions assuming that
782  * the stack is 16 byte aligned. Unfortunately some applications, such
783  * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
784  * causes the movdqa instructions to fail.
785  *
786  * The __force_align_arg_pointer__ makes gcc generate a prologue that
787  * realigns the stack pointer to 16 bytes.
788  *
789  * On x86-64 this is not necessary because the standard ABI already
790  * calls for a 16 byte aligned stack.
791  *
792  * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
793  */
794 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
795 __attribute__((__force_align_arg_pointer__))
796 #endif
797 PIXMAN_EXPORT void
pixman_image_composite32(pixman_op_t op,pixman_image_t * src,pixman_image_t * mask,pixman_image_t * dest,int32_t src_x,int32_t src_y,int32_t mask_x,int32_t mask_y,int32_t dest_x,int32_t dest_y,int32_t width,int32_t height)798 pixman_image_composite32 (pixman_op_t      op,
799                           pixman_image_t * src,
800                           pixman_image_t * mask,
801                           pixman_image_t * dest,
802                           int32_t          src_x,
803                           int32_t          src_y,
804                           int32_t          mask_x,
805                           int32_t          mask_y,
806                           int32_t          dest_x,
807                           int32_t          dest_y,
808                           int32_t          width,
809                           int32_t          height)
810 {
811     _pixman_image_validate (src);
812     if (mask)
813 	_pixman_image_validate (mask);
814     _pixman_image_validate (dest);
815 
816     if (!imp)
817 	imp = _pixman_choose_implementation ();
818 
819     do_composite (imp, op,
820 		  src, mask, dest,
821 		  src_x, src_y,
822 		  mask_x, mask_y,
823 		  dest_x, dest_y,
824 		  width, height);
825 }
826 
827 PIXMAN_EXPORT pixman_bool_t
pixman_blt(uint32_t * src_bits,uint32_t * dst_bits,int src_stride,int dst_stride,int src_bpp,int dst_bpp,int src_x,int src_y,int dst_x,int dst_y,int width,int height)828 pixman_blt (uint32_t *src_bits,
829             uint32_t *dst_bits,
830             int       src_stride,
831             int       dst_stride,
832             int       src_bpp,
833             int       dst_bpp,
834             int       src_x,
835             int       src_y,
836             int       dst_x,
837             int       dst_y,
838             int       width,
839             int       height)
840 {
841     if (!imp)
842 	imp = _pixman_choose_implementation ();
843 
844     return _pixman_implementation_blt (imp, src_bits, dst_bits, src_stride, dst_stride,
845                                        src_bpp, dst_bpp,
846                                        src_x, src_y,
847                                        dst_x, dst_y,
848                                        width, height);
849 }
850 
851 PIXMAN_EXPORT pixman_bool_t
pixman_fill(uint32_t * bits,int stride,int bpp,int x,int y,int width,int height,uint32_t xor)852 pixman_fill (uint32_t *bits,
853              int       stride,
854              int       bpp,
855              int       x,
856              int       y,
857              int       width,
858              int       height,
859              uint32_t xor)
860 {
861     if (!imp)
862 	imp = _pixman_choose_implementation ();
863 
864     return _pixman_implementation_fill (imp, bits, stride, bpp, x, y, width, height, xor);
865 }
866 
867 static uint32_t
color_to_uint32(const pixman_color_t * color)868 color_to_uint32 (const pixman_color_t *color)
869 {
870     return
871         (color->alpha >> 8 << 24) |
872         (color->red >> 8 << 16) |
873         (color->green & 0xff00) |
874         (color->blue >> 8);
875 }
876 
877 static pixman_bool_t
color_to_pixel(pixman_color_t * color,uint32_t * pixel,pixman_format_code_t format)878 color_to_pixel (pixman_color_t *     color,
879                 uint32_t *           pixel,
880                 pixman_format_code_t format)
881 {
882     uint32_t c = color_to_uint32 (color);
883 
884     if (!(format == PIXMAN_a8r8g8b8     ||
885           format == PIXMAN_x8r8g8b8     ||
886           format == PIXMAN_a8b8g8r8     ||
887           format == PIXMAN_x8b8g8r8     ||
888           format == PIXMAN_b8g8r8a8     ||
889           format == PIXMAN_b8g8r8x8     ||
890           format == PIXMAN_r5g6b5       ||
891           format == PIXMAN_b5g6r5       ||
892           format == PIXMAN_a8))
893     {
894 	return FALSE;
895     }
896 
897     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
898     {
899 	c = ((c & 0xff000000) >>  0) |
900 	    ((c & 0x00ff0000) >> 16) |
901 	    ((c & 0x0000ff00) >>  0) |
902 	    ((c & 0x000000ff) << 16);
903     }
904     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
905     {
906 	c = ((c & 0xff000000) >> 24) |
907 	    ((c & 0x00ff0000) >>  8) |
908 	    ((c & 0x0000ff00) <<  8) |
909 	    ((c & 0x000000ff) << 24);
910     }
911 
912     if (format == PIXMAN_a8)
913 	c = c >> 24;
914     else if (format == PIXMAN_r5g6b5 ||
915              format == PIXMAN_b5g6r5)
916 	c = CONVERT_8888_TO_0565 (c);
917 
918 #if 0
919     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
920     printf ("pixel: %x\n", c);
921 #endif
922 
923     *pixel = c;
924     return TRUE;
925 }
926 
927 PIXMAN_EXPORT pixman_bool_t
pixman_image_fill_rectangles(pixman_op_t op,pixman_image_t * dest,pixman_color_t * color,int n_rects,const pixman_rectangle16_t * rects)928 pixman_image_fill_rectangles (pixman_op_t                 op,
929                               pixman_image_t *            dest,
930                               pixman_color_t *            color,
931                               int                         n_rects,
932                               const pixman_rectangle16_t *rects)
933 {
934     pixman_box32_t stack_boxes[6];
935     pixman_box32_t *boxes;
936     pixman_bool_t result;
937     int i;
938 
939     if (n_rects > 6)
940     {
941         boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
942         if (boxes == NULL)
943             return FALSE;
944     }
945     else
946     {
947         boxes = stack_boxes;
948     }
949 
950     for (i = 0; i < n_rects; ++i)
951     {
952         boxes[i].x1 = rects[i].x;
953         boxes[i].y1 = rects[i].y;
954         boxes[i].x2 = boxes[i].x1 + rects[i].width;
955         boxes[i].y2 = boxes[i].y1 + rects[i].height;
956     }
957 
958     result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
959 
960     if (boxes != stack_boxes)
961         free (boxes);
962 
963     return result;
964 }
965 
966 PIXMAN_EXPORT pixman_bool_t
pixman_image_fill_boxes(pixman_op_t op,pixman_image_t * dest,pixman_color_t * color,int n_boxes,const pixman_box32_t * boxes)967 pixman_image_fill_boxes (pixman_op_t           op,
968                          pixman_image_t *      dest,
969                          pixman_color_t *      color,
970                          int                   n_boxes,
971                          const pixman_box32_t *boxes)
972 {
973     pixman_image_t *solid;
974     pixman_color_t c;
975     int i;
976 
977     _pixman_image_validate (dest);
978 
979     if (color->alpha == 0xffff)
980     {
981         if (op == PIXMAN_OP_OVER)
982             op = PIXMAN_OP_SRC;
983     }
984 
985     if (op == PIXMAN_OP_CLEAR)
986     {
987         c.red = 0;
988         c.green = 0;
989         c.blue = 0;
990         c.alpha = 0;
991 
992         color = &c;
993 
994         op = PIXMAN_OP_SRC;
995     }
996 
997     if (op == PIXMAN_OP_SRC)
998     {
999         uint32_t pixel;
1000 
1001         if (color_to_pixel (color, &pixel, dest->bits.format))
1002         {
1003             pixman_region32_t fill_region;
1004             int n_rects, j;
1005             pixman_box32_t *rects;
1006 
1007             if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
1008                 return FALSE;
1009 
1010             if (dest->common.have_clip_region)
1011             {
1012                 if (!pixman_region32_intersect (&fill_region,
1013                                                 &fill_region,
1014                                                 &dest->common.clip_region))
1015                     return FALSE;
1016             }
1017 
1018             rects = pixman_region32_rectangles (&fill_region, &n_rects);
1019             for (j = 0; j < n_rects; ++j)
1020             {
1021                 const pixman_box32_t *rect = &(rects[j]);
1022                 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
1023                              rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
1024                              pixel);
1025             }
1026 
1027             pixman_region32_fini (&fill_region);
1028             return TRUE;
1029         }
1030     }
1031 
1032     solid = pixman_image_create_solid_fill (color);
1033     if (!solid)
1034         return FALSE;
1035 
1036     for (i = 0; i < n_boxes; ++i)
1037     {
1038         const pixman_box32_t *box = &(boxes[i]);
1039 
1040         pixman_image_composite32 (op, solid, NULL, dest,
1041                                   0, 0, 0, 0,
1042                                   box->x1, box->y1,
1043                                   box->x2 - box->x1, box->y2 - box->y1);
1044     }
1045 
1046     pixman_image_unref (solid);
1047 
1048     return TRUE;
1049 }
1050 
1051 /**
1052  * pixman_version:
1053  *
1054  * Returns the version of the pixman library encoded in a single
1055  * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1056  * later versions compare greater than earlier versions.
1057  *
1058  * A run-time comparison to check that pixman's version is greater than
1059  * or equal to version X.Y.Z could be performed as follows:
1060  *
1061  * <informalexample><programlisting>
1062  * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1063  * </programlisting></informalexample>
1064  *
1065  * See also pixman_version_string() as well as the compile-time
1066  * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1067  *
1068  * Return value: the encoded version.
1069  **/
1070 PIXMAN_EXPORT int
pixman_version(void)1071 pixman_version (void)
1072 {
1073     return PIXMAN_VERSION;
1074 }
1075 
1076 /**
1077  * pixman_version_string:
1078  *
1079  * Returns the version of the pixman library as a human-readable string
1080  * of the form "X.Y.Z".
1081  *
1082  * See also pixman_version() as well as the compile-time equivalents
1083  * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1084  *
1085  * Return value: a string containing the version.
1086  **/
1087 PIXMAN_EXPORT const char*
pixman_version_string(void)1088 pixman_version_string (void)
1089 {
1090     return PIXMAN_VERSION_STRING;
1091 }
1092 
1093 /**
1094  * pixman_format_supported_source:
1095  * @format: A pixman_format_code_t format
1096  *
1097  * Return value: whether the provided format code is a supported
1098  * format for a pixman surface used as a source in
1099  * rendering.
1100  *
1101  * Currently, all pixman_format_code_t values are supported.
1102  **/
1103 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_source(pixman_format_code_t format)1104 pixman_format_supported_source (pixman_format_code_t format)
1105 {
1106     switch (format)
1107     {
1108     /* 32 bpp formats */
1109     case PIXMAN_a2b10g10r10:
1110     case PIXMAN_x2b10g10r10:
1111     case PIXMAN_a2r10g10b10:
1112     case PIXMAN_x2r10g10b10:
1113     case PIXMAN_a8r8g8b8:
1114     case PIXMAN_x8r8g8b8:
1115     case PIXMAN_a8b8g8r8:
1116     case PIXMAN_x8b8g8r8:
1117     case PIXMAN_b8g8r8a8:
1118     case PIXMAN_b8g8r8x8:
1119     case PIXMAN_r8g8b8:
1120     case PIXMAN_b8g8r8:
1121     case PIXMAN_r5g6b5:
1122     case PIXMAN_b5g6r5:
1123     /* 16 bpp formats */
1124     case PIXMAN_a1r5g5b5:
1125     case PIXMAN_x1r5g5b5:
1126     case PIXMAN_a1b5g5r5:
1127     case PIXMAN_x1b5g5r5:
1128     case PIXMAN_a4r4g4b4:
1129     case PIXMAN_x4r4g4b4:
1130     case PIXMAN_a4b4g4r4:
1131     case PIXMAN_x4b4g4r4:
1132     /* 8bpp formats */
1133     case PIXMAN_a8:
1134     case PIXMAN_r3g3b2:
1135     case PIXMAN_b2g3r3:
1136     case PIXMAN_a2r2g2b2:
1137     case PIXMAN_a2b2g2r2:
1138     case PIXMAN_c8:
1139     case PIXMAN_g8:
1140     case PIXMAN_x4a4:
1141     /* Collides with PIXMAN_c8
1142        case PIXMAN_x4c4:
1143      */
1144     /* Collides with PIXMAN_g8
1145        case PIXMAN_x4g4:
1146      */
1147     /* 4bpp formats */
1148     case PIXMAN_a4:
1149     case PIXMAN_r1g2b1:
1150     case PIXMAN_b1g2r1:
1151     case PIXMAN_a1r1g1b1:
1152     case PIXMAN_a1b1g1r1:
1153     case PIXMAN_c4:
1154     case PIXMAN_g4:
1155     /* 1bpp formats */
1156     case PIXMAN_a1:
1157     case PIXMAN_g1:
1158     /* YUV formats */
1159     case PIXMAN_yuy2:
1160     case PIXMAN_yv12:
1161 	return TRUE;
1162 
1163     default:
1164 	return FALSE;
1165     }
1166 }
1167 
1168 /**
1169  * pixman_format_supported_destination:
1170  * @format: A pixman_format_code_t format
1171  *
1172  * Return value: whether the provided format code is a supported
1173  * format for a pixman surface used as a destination in
1174  * rendering.
1175  *
1176  * Currently, all pixman_format_code_t values are supported
1177  * except for the YUV formats.
1178  **/
1179 PIXMAN_EXPORT pixman_bool_t
pixman_format_supported_destination(pixman_format_code_t format)1180 pixman_format_supported_destination (pixman_format_code_t format)
1181 {
1182     /* YUV formats cannot be written to at the moment */
1183     if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1184 	return FALSE;
1185 
1186     return pixman_format_supported_source (format);
1187 }
1188 
1189 PIXMAN_EXPORT pixman_bool_t
pixman_compute_composite_region(pixman_region16_t * region,pixman_image_t * src_image,pixman_image_t * mask_image,pixman_image_t * dst_image,int16_t src_x,int16_t src_y,int16_t mask_x,int16_t mask_y,int16_t dest_x,int16_t dest_y,uint16_t width,uint16_t height)1190 pixman_compute_composite_region (pixman_region16_t * region,
1191                                  pixman_image_t *    src_image,
1192                                  pixman_image_t *    mask_image,
1193                                  pixman_image_t *    dst_image,
1194                                  int16_t             src_x,
1195                                  int16_t             src_y,
1196                                  int16_t             mask_x,
1197                                  int16_t             mask_y,
1198                                  int16_t             dest_x,
1199                                  int16_t             dest_y,
1200                                  uint16_t            width,
1201                                  uint16_t            height)
1202 {
1203     pixman_region32_t r32;
1204     pixman_bool_t retval;
1205 
1206     pixman_region32_init (&r32);
1207 
1208     retval = pixman_compute_composite_region32 (
1209 	&r32, src_image, mask_image, dst_image,
1210 	src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1211 	width, height);
1212 
1213     if (retval)
1214     {
1215 	if (!pixman_region16_copy_from_region32 (region, &r32))
1216 	    retval = FALSE;
1217     }
1218 
1219     pixman_region32_fini (&r32);
1220     return retval;
1221 }
1222