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