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