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