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