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