When pixman_compute_composite_region32() returns FALSE, don't fini the region.
[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         for (i = 0; i < 4; ++i)
617         {
618             pixman_fixed_48_16_t tx, ty;
619             pixman_vector_t v;
620
621             v.vector[0] = (i & 0x01)? x1 : x2;
622             v.vector[1] = (i & 0x02)? y1 : y2;
623             v.vector[2] = pixman_fixed_1;
624
625             if (!pixman_transform_point (transform, &v))
626                 return FALSE;
627
628             tx = (pixman_fixed_48_16_t)v.vector[0];
629             ty = (pixman_fixed_48_16_t)v.vector[1];
630
631             if (i == 0)
632             {
633                 tx1 = tx;
634                 ty1 = ty;
635                 tx2 = tx;
636                 ty2 = ty;
637             }
638             else
639             {
640                 if (tx < tx1)
641                     tx1 = tx;
642                 if (ty < ty1)
643                     ty1 = ty;
644                 if (tx > tx2)
645                     tx2 = tx;
646                 if (ty > ty2)
647                     ty2 = ty;
648             }
649         }
650     }
651
652     /* Expand the source area by a tiny bit so account of different rounding that
653      * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
654      * 0.5 so this won't cause the area computed to be overly pessimistic.
655      */
656     tx1 += x_off - 8 * pixman_fixed_e;
657     ty1 += y_off - 8 * pixman_fixed_e;
658     tx2 += x_off + width + 8 * pixman_fixed_e;
659     ty2 += y_off + height + 8 * pixman_fixed_e;
660
661     if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
662         ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
663         tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
664         ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
665     {
666         return FALSE;
667     }
668     else
669     {
670         extents->x1 = pixman_fixed_to_int (tx1);
671         extents->y1 = pixman_fixed_to_int (ty1);
672         extents->x2 = pixman_fixed_to_int (tx2) + 1;
673         extents->y2 = pixman_fixed_to_int (ty2) + 1;
674
675         return TRUE;
676     }
677 }
678
679 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
680
681 static pixman_bool_t
682 analyze_extent (pixman_image_t *image, int x, int y,
683                 const pixman_box32_t *extents, uint32_t *flags)
684 {
685     pixman_transform_t *transform;
686     pixman_fixed_t *params;
687     pixman_fixed_t x_off, y_off;
688     pixman_fixed_t width, height;
689     pixman_box32_t ex;
690
691     *flags |= FAST_PATH_COVERS_CLIP;
692     if (!image)
693         return TRUE;
694
695     transform = image->common.transform;
696     if (image->common.type == BITS)
697     {
698         /* During repeat mode calculations we might convert the
699          * width/height of an image to fixed 16.16, so we need
700          * them to be smaller than 16 bits.
701          */
702         if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
703             return FALSE;
704
705         if (image->common.repeat == PIXMAN_REPEAT_NONE &&
706             (x > extents->x1 || y > extents->y1 ||
707              x + image->bits.width < extents->x2 ||
708              y + image->bits.height < extents->y2))
709         {
710             (*flags) &= ~FAST_PATH_COVERS_CLIP;
711         }
712     }
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     if (image->common.type == BITS)
728     {
729         switch (image->common.filter)
730         {
731         case PIXMAN_FILTER_CONVOLUTION:
732             params = image->common.filter_params;
733             x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
734             y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
735             width = params[0];
736             height = params[1];
737             break;
738
739         case PIXMAN_FILTER_GOOD:
740         case PIXMAN_FILTER_BEST:
741         case PIXMAN_FILTER_BILINEAR:
742             x_off = - pixman_fixed_1 / 2;
743             y_off = - pixman_fixed_1 / 2;
744             width = pixman_fixed_1;
745             height = pixman_fixed_1;
746             break;
747
748         case PIXMAN_FILTER_FAST:
749         case PIXMAN_FILTER_NEAREST:
750             x_off = - pixman_fixed_e;
751             y_off = - pixman_fixed_e;
752             width = 0;
753             height = 0;
754             break;
755
756         default:
757             return FALSE;
758         }
759     }
760     else
761     {
762         x_off = 0;
763         y_off = 0;
764         width = 0;
765         height = 0;
766     }
767
768     /* Check that the extents expanded by one don't overflow. This ensures that
769      * compositing functions can simply walk the source space using 16.16 variables
770      * without worrying about overflow.
771      */
772     ex.x1 = extents->x1 - 1;
773     ex.y1 = extents->y1 - 1;
774     ex.x2 = extents->x2 + 1;
775     ex.y2 = extents->y2 + 1;
776
777     if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
778         return FALSE;
779
780     if (image->type == BITS)
781     {
782         /* Check whether the non-expanded, transformed extent is entirely within
783          * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
784          */
785         ex = *extents;
786         if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
787         {
788             if (ex.x1 >= 0 && ex.y1 >= 0 && ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
789                 *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
790         }
791     }
792
793     return TRUE;
794 }
795
796 /*
797  * Work around GCC bug causing crashes in Mozilla with SSE2
798  *
799  * When using -msse, gcc generates movdqa instructions assuming that
800  * the stack is 16 byte aligned. Unfortunately some applications, such
801  * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
802  * causes the movdqa instructions to fail.
803  *
804  * The __force_align_arg_pointer__ makes gcc generate a prologue that
805  * realigns the stack pointer to 16 bytes.
806  *
807  * On x86-64 this is not necessary because the standard ABI already
808  * calls for a 16 byte aligned stack.
809  *
810  * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
811  */
812 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
813 __attribute__((__force_align_arg_pointer__))
814 #endif
815 PIXMAN_EXPORT void
816 pixman_image_composite32 (pixman_op_t      op,
817                           pixman_image_t * src,
818                           pixman_image_t * mask,
819                           pixman_image_t * dest,
820                           int32_t          src_x,
821                           int32_t          src_y,
822                           int32_t          mask_x,
823                           int32_t          mask_y,
824                           int32_t          dest_x,
825                           int32_t          dest_y,
826                           int32_t          width,
827                           int32_t          height)
828 {
829     pixman_format_code_t src_format, mask_format, dest_format;
830     uint32_t src_flags, mask_flags, dest_flags;
831     pixman_region32_t region;
832     pixman_box32_t *extents;
833     uint32_t *src_bits;
834     int src_dx, src_dy;
835     uint32_t *mask_bits;
836     int mask_dx, mask_dy;
837     uint32_t *dest_bits;
838     int dest_dx, dest_dy;
839     pixman_bool_t need_workaround;
840     pixman_implementation_t *imp;
841     pixman_composite_func_t func;
842
843     _pixman_image_validate (src);
844     if (mask)
845         _pixman_image_validate (mask);
846     _pixman_image_validate (dest);
847
848     src_format = src->common.extended_format_code;
849     src_flags = src->common.flags;
850
851     if (mask)
852     {
853         mask_format = mask->common.extended_format_code;
854         mask_flags = mask->common.flags;
855     }
856     else
857     {
858         mask_format = PIXMAN_null;
859         mask_flags = FAST_PATH_IS_OPAQUE;
860     }
861
862     dest_format = dest->common.extended_format_code;
863     dest_flags = dest->common.flags;
864
865     /* Check for pixbufs */
866     if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
867         (src->type == BITS && src->bits.bits == mask->bits.bits)           &&
868         (src->common.repeat == mask->common.repeat)                        &&
869         (src_x == mask_x && src_y == mask_y))
870     {
871         if (src_format == PIXMAN_x8b8g8r8)
872             src_format = mask_format = PIXMAN_pixbuf;
873         else if (src_format == PIXMAN_x8r8g8b8)
874             src_format = mask_format = PIXMAN_rpixbuf;
875     }
876
877     /* Check for workaround */
878     need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
879
880     if (need_workaround)
881     {
882         apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
883         apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
884         apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
885     }
886
887     pixman_region32_init (&region);
888
889     if (!pixman_compute_composite_region32 (
890             &region, src, mask, dest,
891             src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
892     {
893         goto out;
894     }
895
896     extents = pixman_region32_extents (&region);
897
898     if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
899         goto out;
900
901     if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
902         goto out;
903
904     /* If the clip is within the source samples, and the samples are opaque,
905      * then the source is effectively opaque.
906      */
907 #define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP)
908
909     if ((src_flags & BOTH) == BOTH)
910         src_flags |= FAST_PATH_IS_OPAQUE;
911     
912     if ((mask_flags & BOTH) == BOTH)
913         mask_flags |= FAST_PATH_IS_OPAQUE;
914     
915     /*
916      * Check if we can replace our operator by a simpler one
917      * if the src or dest are opaque. The output operator should be
918      * mathematically equivalent to the source.
919      */
920     op = optimize_operator (op, src_flags, mask_flags, dest_flags);
921     if (op == PIXMAN_OP_DST)
922         goto out;
923
924     if (lookup_composite_function (op,
925                                    src_format, src_flags,
926                                    mask_format, mask_flags,
927                                    dest_format, dest_flags,
928                                    &imp, &func))
929     {
930         walk_region_internal (imp, op,
931                               src, mask, dest,
932                               src_x, src_y, mask_x, mask_y,
933                               dest_x, dest_y,
934                               width, height,
935                               (src_flags & FAST_PATH_SIMPLE_REPEAT),
936                               (mask_flags & FAST_PATH_SIMPLE_REPEAT),
937                               &region, func);
938     }
939
940 out:
941     if (need_workaround)
942     {
943         unapply_workaround (src, src_bits, src_dx, src_dy);
944         unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
945         unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
946     }
947
948     pixman_region32_fini (&region);
949 }
950
951 PIXMAN_EXPORT void
952 pixman_image_composite (pixman_op_t      op,
953                         pixman_image_t * src,
954                         pixman_image_t * mask,
955                         pixman_image_t * dest,
956                         int16_t          src_x,
957                         int16_t          src_y,
958                         int16_t          mask_x,
959                         int16_t          mask_y,
960                         int16_t          dest_x,
961                         int16_t          dest_y,
962                         uint16_t         width,
963                         uint16_t         height)
964 {
965     pixman_image_composite32 (op, src, mask, dest, src_x, src_y, 
966                               mask_x, mask_y, dest_x, dest_y, width, height);
967 }
968
969 PIXMAN_EXPORT pixman_bool_t
970 pixman_blt (uint32_t *src_bits,
971             uint32_t *dst_bits,
972             int       src_stride,
973             int       dst_stride,
974             int       src_bpp,
975             int       dst_bpp,
976             int       src_x,
977             int       src_y,
978             int       dst_x,
979             int       dst_y,
980             int       width,
981             int       height)
982 {
983     return _pixman_implementation_blt (get_implementation(),
984                                        src_bits, dst_bits, src_stride, dst_stride,
985                                        src_bpp, dst_bpp,
986                                        src_x, src_y,
987                                        dst_x, dst_y,
988                                        width, height);
989 }
990
991 PIXMAN_EXPORT pixman_bool_t
992 pixman_fill (uint32_t *bits,
993              int       stride,
994              int       bpp,
995              int       x,
996              int       y,
997              int       width,
998              int       height,
999              uint32_t xor)
1000 {
1001     return _pixman_implementation_fill (
1002         get_implementation(), bits, stride, bpp, x, y, width, height, xor);
1003 }
1004
1005 static uint32_t
1006 color_to_uint32 (const pixman_color_t *color)
1007 {
1008     return
1009         (color->alpha >> 8 << 24) |
1010         (color->red >> 8 << 16) |
1011         (color->green & 0xff00) |
1012         (color->blue >> 8);
1013 }
1014
1015 static pixman_bool_t
1016 color_to_pixel (pixman_color_t *     color,
1017                 uint32_t *           pixel,
1018                 pixman_format_code_t format)
1019 {
1020     uint32_t c = color_to_uint32 (color);
1021
1022     if (!(format == PIXMAN_a8r8g8b8     ||
1023           format == PIXMAN_x8r8g8b8     ||
1024           format == PIXMAN_a8b8g8r8     ||
1025           format == PIXMAN_x8b8g8r8     ||
1026           format == PIXMAN_b8g8r8a8     ||
1027           format == PIXMAN_b8g8r8x8     ||
1028           format == PIXMAN_r5g6b5       ||
1029           format == PIXMAN_b5g6r5       ||
1030           format == PIXMAN_a8))
1031     {
1032         return FALSE;
1033     }
1034
1035     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
1036     {
1037         c = ((c & 0xff000000) >>  0) |
1038             ((c & 0x00ff0000) >> 16) |
1039             ((c & 0x0000ff00) >>  0) |
1040             ((c & 0x000000ff) << 16);
1041     }
1042     if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
1043     {
1044         c = ((c & 0xff000000) >> 24) |
1045             ((c & 0x00ff0000) >>  8) |
1046             ((c & 0x0000ff00) <<  8) |
1047             ((c & 0x000000ff) << 24);
1048     }
1049
1050     if (format == PIXMAN_a8)
1051         c = c >> 24;
1052     else if (format == PIXMAN_r5g6b5 ||
1053              format == PIXMAN_b5g6r5)
1054         c = CONVERT_8888_TO_0565 (c);
1055
1056 #if 0
1057     printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
1058     printf ("pixel: %x\n", c);
1059 #endif
1060
1061     *pixel = c;
1062     return TRUE;
1063 }
1064
1065 PIXMAN_EXPORT pixman_bool_t
1066 pixman_image_fill_rectangles (pixman_op_t                 op,
1067                               pixman_image_t *            dest,
1068                               pixman_color_t *            color,
1069                               int                         n_rects,
1070                               const pixman_rectangle16_t *rects)
1071 {
1072     pixman_box32_t stack_boxes[6];
1073     pixman_box32_t *boxes;
1074     pixman_bool_t result;
1075     int i;
1076
1077     if (n_rects > 6)
1078     {
1079         boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
1080         if (boxes == NULL)
1081             return FALSE;
1082     }
1083     else
1084     {
1085         boxes = stack_boxes;
1086     }
1087
1088     for (i = 0; i < n_rects; ++i)
1089     {
1090         boxes[i].x1 = rects[i].x;
1091         boxes[i].y1 = rects[i].y;
1092         boxes[i].x2 = boxes[i].x1 + rects[i].width;
1093         boxes[i].y2 = boxes[i].y1 + rects[i].height;
1094     }
1095
1096     result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
1097
1098     if (boxes != stack_boxes)
1099         free (boxes);
1100     
1101     return result;
1102 }
1103
1104 PIXMAN_EXPORT pixman_bool_t
1105 pixman_image_fill_boxes (pixman_op_t           op,
1106                          pixman_image_t *      dest,
1107                          pixman_color_t *      color,
1108                          int                   n_boxes,
1109                          const pixman_box32_t *boxes)
1110 {
1111     pixman_image_t *solid;
1112     pixman_color_t c;
1113     int i;
1114
1115     _pixman_image_validate (dest);
1116     
1117     if (color->alpha == 0xffff)
1118     {
1119         if (op == PIXMAN_OP_OVER)
1120             op = PIXMAN_OP_SRC;
1121     }
1122
1123     if (op == PIXMAN_OP_CLEAR)
1124     {
1125         c.red = 0;
1126         c.green = 0;
1127         c.blue = 0;
1128         c.alpha = 0;
1129
1130         color = &c;
1131
1132         op = PIXMAN_OP_SRC;
1133     }
1134
1135     if (op == PIXMAN_OP_SRC)
1136     {
1137         uint32_t pixel;
1138
1139         if (color_to_pixel (color, &pixel, dest->bits.format))
1140         {
1141             pixman_region32_t fill_region;
1142             int n_rects, j;
1143             pixman_box32_t *rects;
1144
1145             if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
1146                 return FALSE;
1147
1148             if (dest->common.have_clip_region)
1149             {
1150                 if (!pixman_region32_intersect (&fill_region,
1151                                                 &fill_region,
1152                                                 &dest->common.clip_region))
1153                     return FALSE;
1154             }
1155
1156             rects = pixman_region32_rectangles (&fill_region, &n_rects);
1157             for (j = 0; j < n_rects; ++j)
1158             {
1159                 const pixman_box32_t *rect = &(rects[j]);
1160                 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
1161                              rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
1162                              pixel);
1163             }
1164
1165             pixman_region32_fini (&fill_region);
1166             return TRUE;
1167         }
1168     }
1169
1170     solid = pixman_image_create_solid_fill (color);
1171     if (!solid)
1172         return FALSE;
1173
1174     for (i = 0; i < n_boxes; ++i)
1175     {
1176         const pixman_box32_t *box = &(boxes[i]);
1177
1178         pixman_image_composite32 (op, solid, NULL, dest,
1179                                   0, 0, 0, 0,
1180                                   box->x1, box->y1,
1181                                   box->x2 - box->x1, box->y2 - box->y1);
1182     }
1183
1184     pixman_image_unref (solid);
1185
1186     return TRUE;
1187 }
1188
1189 /**
1190  * pixman_version:
1191  *
1192  * Returns the version of the pixman library encoded in a single
1193  * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1194  * later versions compare greater than earlier versions.
1195  *
1196  * A run-time comparison to check that pixman's version is greater than
1197  * or equal to version X.Y.Z could be performed as follows:
1198  *
1199  * <informalexample><programlisting>
1200  * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1201  * </programlisting></informalexample>
1202  *
1203  * See also pixman_version_string() as well as the compile-time
1204  * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1205  *
1206  * Return value: the encoded version.
1207  **/
1208 PIXMAN_EXPORT int
1209 pixman_version (void)
1210 {
1211     return PIXMAN_VERSION;
1212 }
1213
1214 /**
1215  * pixman_version_string:
1216  *
1217  * Returns the version of the pixman library as a human-readable string
1218  * of the form "X.Y.Z".
1219  *
1220  * See also pixman_version() as well as the compile-time equivalents
1221  * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1222  *
1223  * Return value: a string containing the version.
1224  **/
1225 PIXMAN_EXPORT const char*
1226 pixman_version_string (void)
1227 {
1228     return PIXMAN_VERSION_STRING;
1229 }
1230
1231 /**
1232  * pixman_format_supported_source:
1233  * @format: A pixman_format_code_t format
1234  *
1235  * Return value: whether the provided format code is a supported
1236  * format for a pixman surface used as a source in
1237  * rendering.
1238  *
1239  * Currently, all pixman_format_code_t values are supported.
1240  **/
1241 PIXMAN_EXPORT pixman_bool_t
1242 pixman_format_supported_source (pixman_format_code_t format)
1243 {
1244     switch (format)
1245     {
1246     /* 32 bpp formats */
1247     case PIXMAN_a2b10g10r10:
1248     case PIXMAN_x2b10g10r10:
1249     case PIXMAN_a2r10g10b10:
1250     case PIXMAN_x2r10g10b10:
1251     case PIXMAN_a8r8g8b8:
1252     case PIXMAN_x8r8g8b8:
1253     case PIXMAN_a8b8g8r8:
1254     case PIXMAN_x8b8g8r8:
1255     case PIXMAN_b8g8r8a8:
1256     case PIXMAN_b8g8r8x8:
1257     case PIXMAN_r8g8b8:
1258     case PIXMAN_b8g8r8:
1259     case PIXMAN_r5g6b5:
1260     case PIXMAN_b5g6r5:
1261     case PIXMAN_x14r6g6b6:
1262     /* 16 bpp formats */
1263     case PIXMAN_a1r5g5b5:
1264     case PIXMAN_x1r5g5b5:
1265     case PIXMAN_a1b5g5r5:
1266     case PIXMAN_x1b5g5r5:
1267     case PIXMAN_a4r4g4b4:
1268     case PIXMAN_x4r4g4b4:
1269     case PIXMAN_a4b4g4r4:
1270     case PIXMAN_x4b4g4r4:
1271     /* 8bpp formats */
1272     case PIXMAN_a8:
1273     case PIXMAN_r3g3b2:
1274     case PIXMAN_b2g3r3:
1275     case PIXMAN_a2r2g2b2:
1276     case PIXMAN_a2b2g2r2:
1277     case PIXMAN_c8:
1278     case PIXMAN_g8:
1279     case PIXMAN_x4a4:
1280     /* Collides with PIXMAN_c8
1281        case PIXMAN_x4c4:
1282      */
1283     /* Collides with PIXMAN_g8
1284        case PIXMAN_x4g4:
1285      */
1286     /* 4bpp formats */
1287     case PIXMAN_a4:
1288     case PIXMAN_r1g2b1:
1289     case PIXMAN_b1g2r1:
1290     case PIXMAN_a1r1g1b1:
1291     case PIXMAN_a1b1g1r1:
1292     case PIXMAN_c4:
1293     case PIXMAN_g4:
1294     /* 1bpp formats */
1295     case PIXMAN_a1:
1296     case PIXMAN_g1:
1297     /* YUV formats */
1298     case PIXMAN_yuy2:
1299     case PIXMAN_yv12:
1300         return TRUE;
1301
1302     default:
1303         return FALSE;
1304     }
1305 }
1306
1307 /**
1308  * pixman_format_supported_destination:
1309  * @format: A pixman_format_code_t format
1310  *
1311  * Return value: whether the provided format code is a supported
1312  * format for a pixman surface used as a destination in
1313  * rendering.
1314  *
1315  * Currently, all pixman_format_code_t values are supported
1316  * except for the YUV formats.
1317  **/
1318 PIXMAN_EXPORT pixman_bool_t
1319 pixman_format_supported_destination (pixman_format_code_t format)
1320 {
1321     /* YUV formats cannot be written to at the moment */
1322     if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1323         return FALSE;
1324
1325     return pixman_format_supported_source (format);
1326 }
1327
1328 PIXMAN_EXPORT pixman_bool_t
1329 pixman_compute_composite_region (pixman_region16_t * region,
1330                                  pixman_image_t *    src_image,
1331                                  pixman_image_t *    mask_image,
1332                                  pixman_image_t *    dst_image,
1333                                  int16_t             src_x,
1334                                  int16_t             src_y,
1335                                  int16_t             mask_x,
1336                                  int16_t             mask_y,
1337                                  int16_t             dest_x,
1338                                  int16_t             dest_y,
1339                                  uint16_t            width,
1340                                  uint16_t            height)
1341 {
1342     pixman_region32_t r32;
1343     pixman_bool_t retval;
1344
1345     pixman_region32_init (&r32);
1346
1347     retval = pixman_compute_composite_region32 (
1348         &r32, src_image, mask_image, dst_image,
1349         src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1350         width, height);
1351
1352     if (retval)
1353     {
1354         if (!pixman_region16_copy_from_region32 (region, &r32))
1355             retval = FALSE;
1356     }
1357
1358     pixman_region32_fini (&r32);
1359     return retval;
1360 }