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