1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */
3 * Copyright © 2000 SuSE, Inc.
4 * Copyright © 2007 Red Hat, Inc.
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.
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.
23 * Author: Keith Packard, SuSE, Inc.
29 #include "pixman-private.h"
33 static force_inline pixman_implementation_t *
34 get_implementation (void)
36 static pixman_implementation_t *global_implementation;
38 if (!global_implementation)
39 global_implementation = _pixman_choose_implementation ();
41 return global_implementation;
44 typedef struct operator_info_t operator_info_t;
46 struct operator_info_t
48 uint8_t opaque_info[4];
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 }}
57 static const operator_info_t operator_table[] =
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),
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),
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),
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),
132 * Optimize the current operator based on opacity of source or destination
133 * The output operator should be mathematically equivalent to the source.
136 optimize_operator (pixman_op_t op,
141 pixman_bool_t is_source_opaque, is_dest_opaque;
144 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0;
145 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0;
147 opaqueness = ((is_dest_opaque << 1) | is_source_opaque);
149 return operator_table[op].opaque_info[opaqueness];
153 apply_workaround (pixman_image_t *image,
156 uint32_t ** save_bits,
160 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
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.
167 * Here we try and undo the damage
169 int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
170 pixman_box32_t *extents;
174 extents = pixman_region32_extents (&(image->common.clip_region));
178 *save_bits = image->bits.bits;
182 pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
184 t = (uint8_t *)image->bits.bits;
185 t += dy * image->bits.rowstride * 4 + dx * bpp;
186 image->bits.bits = (uint32_t *)t;
194 unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
196 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
198 image->bits.bits = bits;
199 pixman_region32_translate (&image->common.clip_region, dx, dy);
204 * Computing composite region
206 static inline pixman_bool_t
207 clip_general_image (pixman_region32_t * region,
208 pixman_region32_t * clip,
212 if (pixman_region32_n_rects (region) == 1 &&
213 pixman_region32_n_rects (clip) == 1)
215 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL);
216 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL);
219 if (rbox->x1 < (v = cbox->x1 + dx))
221 if (rbox->x2 > (v = cbox->x2 + dx))
223 if (rbox->y1 < (v = cbox->y1 + dy))
225 if (rbox->y2 > (v = cbox->y2 + dy))
227 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
229 pixman_region32_init (region);
233 else if (!pixman_region32_not_empty (clip))
240 pixman_region32_translate (region, -dx, -dy);
242 if (!pixman_region32_intersect (region, region, clip))
246 pixman_region32_translate (region, dx, dy);
249 return pixman_region32_not_empty (region);
252 static inline pixman_bool_t
253 clip_source_image (pixman_region32_t * region,
254 pixman_image_t * image,
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).
263 if (!image->common.clip_sources || !image->common.client_clip)
266 return clip_general_image (region,
267 &image->common.clip_region,
272 * returns FALSE if the final region is empty. Indistinguishable from
273 * an allocation failure, but rendering ignores those anyways.
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,
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;
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);
301 /* Check for empty operation */
302 if (region->extents.x1 >= region->extents.x2 ||
303 region->extents.y1 >= region->extents.y2)
305 pixman_region32_init (region);
309 if (dst_image->common.have_clip_region)
311 if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
313 pixman_region32_fini (region);
318 if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
320 if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
321 -dst_image->common.alpha_origin_x,
322 -dst_image->common.alpha_origin_y))
324 pixman_region32_fini (region);
329 /* clip against src */
330 if (src_image->common.have_clip_region)
332 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
334 pixman_region32_fini (region);
338 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
340 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
341 dest_x - (src_x - src_image->common.alpha_origin_x),
342 dest_y - (src_y - src_image->common.alpha_origin_y)))
344 pixman_region32_fini (region);
348 /* clip against mask */
349 if (mask_image && mask_image->common.have_clip_region)
351 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
353 pixman_region32_fini (region);
356 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
358 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
359 dest_x - (mask_x - mask_image->common.alpha_origin_x),
360 dest_y - (mask_y - mask_image->common.alpha_origin_y)))
362 pixman_region32_fini (region);
372 walk_region_internal (pixman_implementation_t *imp,
374 pixman_image_t * src_image,
375 pixman_image_t * mask_image,
376 pixman_image_t * dst_image,
385 pixman_bool_t src_repeat,
386 pixman_bool_t mask_repeat,
387 pixman_region32_t * region,
388 pixman_composite_func_t composite_rect)
390 int w, h, w_this, h_this;
391 int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
392 int src_dy = src_y - dest_y;
393 int src_dx = src_x - dest_x;
394 int mask_dy = mask_y - dest_y;
395 int mask_dx = mask_x - dest_x;
396 const pixman_box32_t *pbox;
399 pbox = pixman_region32_rectangles (region, &n);
401 /* Fast path for non-repeating sources */
402 if (!src_repeat && !mask_repeat)
406 (*composite_rect) (imp, op,
407 src_image, mask_image, dst_image,
415 pbox->y2 - pbox->y1);
425 h = pbox->y2 - pbox->y1;
426 y_src = pbox->y1 + src_dy;
427 y_msk = pbox->y1 + mask_dy;
433 w = pbox->x2 - pbox->x1;
434 x_src = pbox->x1 + src_dx;
435 x_msk = pbox->x1 + mask_dx;
440 y_msk = MOD (y_msk, mask_image->bits.height);
441 if (h_this > mask_image->bits.height - y_msk)
442 h_this = mask_image->bits.height - y_msk;
447 y_src = MOD (y_src, src_image->bits.height);
448 if (h_this > src_image->bits.height - y_src)
449 h_this = src_image->bits.height - y_src;
458 x_msk = MOD (x_msk, mask_image->bits.width);
459 if (w_this > mask_image->bits.width - x_msk)
460 w_this = mask_image->bits.width - x_msk;
465 x_src = MOD (x_src, src_image->bits.width);
466 if (w_this > src_image->bits.width - x_src)
467 w_this = src_image->bits.width - x_src;
470 (*composite_rect) (imp, op,
471 src_image, mask_image, dst_image,
472 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
491 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
493 static force_inline uint32_t
494 compute_src_extents_flags (pixman_image_t *image,
495 pixman_box32_t *extents,
499 pixman_box16_t extents16;
502 flags = FAST_PATH_COVERS_CLIP;
504 if (image->common.type != BITS)
507 if (image->common.repeat == PIXMAN_REPEAT_NONE &&
508 (x > extents->x1 || y > extents->y1 ||
509 x + image->bits.width < extents->x2 ||
510 y + image->bits.height < extents->y2))
512 flags &= ~FAST_PATH_COVERS_CLIP;
515 if (IS_16BIT (extents->x1 - x) &&
516 IS_16BIT (extents->y1 - y) &&
517 IS_16BIT (extents->x2 - x) &&
518 IS_16BIT (extents->y2 - y))
520 extents16.x1 = extents->x1 - x;
521 extents16.y1 = extents->y1 - y;
522 extents16.x2 = extents->x2 - x;
523 extents16.y2 = extents->y2 - y;
525 if (!image->common.transform ||
526 pixman_transform_bounds (image->common.transform, &extents16))
528 if (extents16.x1 >= 0 && extents16.y1 >= 0 &&
529 extents16.x2 <= image->bits.width &&
530 extents16.y2 <= image->bits.height)
532 flags |= FAST_PATH_SAMPLES_COVER_CLIP;
537 if (IS_16BIT (extents->x1 - x - 1) &&
538 IS_16BIT (extents->y1 - y - 1) &&
539 IS_16BIT (extents->x2 - x + 1) &&
540 IS_16BIT (extents->y2 - y + 1))
542 extents16.x1 = extents->x1 - x - 1;
543 extents16.y1 = extents->y1 - y - 1;
544 extents16.x2 = extents->x2 - x + 1;
545 extents16.y2 = extents->y2 - y + 1;
547 if (/* src space expanded by one in dest space fits in 16 bit */
548 (!image->common.transform ||
549 pixman_transform_bounds (image->common.transform, &extents16)) &&
550 /* And src image size can be used as 16.16 fixed point */
551 image->bits.width < 0x7fff &&
552 image->bits.height < 0x7fff)
554 /* Then we're "16bit safe" */
555 flags |= FAST_PATH_16BIT_SAFE;
562 #define N_CACHED_FAST_PATHS 8
568 pixman_implementation_t * imp;
569 pixman_fast_path_t fast_path;
570 } cache [N_CACHED_FAST_PATHS];
573 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
575 static force_inline void
576 lookup_composite_function (pixman_op_t op,
577 pixman_format_code_t src_format,
579 pixman_format_code_t mask_format,
581 pixman_format_code_t dest_format,
583 pixman_implementation_t **out_imp,
584 pixman_composite_func_t *out_func)
586 pixman_implementation_t *imp;
590 /* Check cache for fast paths */
591 cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
593 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
595 const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
597 /* Note that we check for equality here, not whether
598 * the cached fast path matches. This is to prevent
599 * us from selecting an overly general fast path
600 * when a more specific one would work.
602 if (info->op == op &&
603 info->src_format == src_format &&
604 info->mask_format == mask_format &&
605 info->dest_format == dest_format &&
606 info->src_flags == src_flags &&
607 info->mask_flags == mask_flags &&
608 info->dest_flags == dest_flags &&
611 *out_imp = cache->cache[i].imp;
612 *out_func = cache->cache[i].fast_path.func;
618 for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
620 const pixman_fast_path_t *info = imp->fast_paths;
622 while (info->op != PIXMAN_OP_NONE)
624 if ((info->op == op || info->op == PIXMAN_OP_any) &&
626 ((info->src_format == src_format) ||
627 (info->src_format == PIXMAN_any)) &&
628 ((info->mask_format == mask_format) ||
629 (info->mask_format == PIXMAN_any)) &&
630 ((info->dest_format == dest_format) ||
631 (info->dest_format == PIXMAN_any)) &&
633 (info->src_flags & src_flags) == info->src_flags &&
634 (info->mask_flags & mask_flags) == info->mask_flags &&
635 (info->dest_flags & dest_flags) == info->dest_flags)
638 *out_func = info->func;
640 /* Set i to the last spot in the cache so that the
641 * move-to-front code below will work
643 i = N_CACHED_FAST_PATHS - 1;
657 cache->cache[i + 1] = cache->cache[i];
659 cache->cache[0].imp = *out_imp;
660 cache->cache[0].fast_path.op = op;
661 cache->cache[0].fast_path.src_format = src_format;
662 cache->cache[0].fast_path.src_flags = src_flags;
663 cache->cache[0].fast_path.mask_format = mask_format;
664 cache->cache[0].fast_path.mask_flags = mask_flags;
665 cache->cache[0].fast_path.dest_format = dest_format;
666 cache->cache[0].fast_path.dest_flags = dest_flags;
667 cache->cache[0].fast_path.func = *out_func;
673 do_composite (pixman_op_t op,
675 pixman_image_t *mask,
676 pixman_image_t *dest,
686 pixman_format_code_t src_format, mask_format, dest_format;
687 uint32_t src_flags, mask_flags, dest_flags;
688 pixman_region32_t region;
689 pixman_box32_t *extents;
693 int mask_dx, mask_dy;
695 int dest_dx, dest_dy;
696 pixman_bool_t need_workaround;
697 pixman_implementation_t *imp;
698 pixman_composite_func_t func;
700 src_format = src->common.extended_format_code;
701 src_flags = src->common.flags;
705 mask_format = mask->common.extended_format_code;
706 mask_flags = mask->common.flags;
710 mask_format = PIXMAN_null;
711 mask_flags = FAST_PATH_IS_OPAQUE;
714 dest_format = dest->common.extended_format_code;
715 dest_flags = dest->common.flags;
717 /* Check for pixbufs */
718 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
719 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
720 (src->common.repeat == mask->common.repeat) &&
721 (src_x == mask_x && src_y == mask_y))
723 if (src_format == PIXMAN_x8b8g8r8)
724 src_format = mask_format = PIXMAN_pixbuf;
725 else if (src_format == PIXMAN_x8r8g8b8)
726 src_format = mask_format = PIXMAN_rpixbuf;
729 /* Check for workaround */
730 need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
734 apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
735 apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
736 apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
739 pixman_region32_init (®ion);
741 if (!pixman_compute_composite_region32 (
742 ®ion, src, mask, dest,
743 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
748 extents = pixman_region32_extents (®ion);
750 src_flags |= compute_src_extents_flags (src, extents, dest_x - src_x, dest_y - src_y);
753 mask_flags |= compute_src_extents_flags (mask, extents, dest_x - mask_x, dest_y - mask_y);
756 * Check if we can replace our operator by a simpler one
757 * if the src or dest are opaque. The output operator should be
758 * mathematically equivalent to the source.
760 op = optimize_operator (op, src_flags, mask_flags, dest_flags);
761 if (op == PIXMAN_OP_DST)
764 lookup_composite_function (op,
765 src_format, src_flags,
766 mask_format, mask_flags,
767 dest_format, dest_flags,
770 walk_region_internal (imp, op,
772 src_x, src_y, mask_x, mask_y,
775 (src_flags & FAST_PATH_SIMPLE_REPEAT),
776 (mask_flags & FAST_PATH_SIMPLE_REPEAT),
782 unapply_workaround (src, src_bits, src_dx, src_dy);
783 unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
784 unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
787 pixman_region32_fini (®ion);
791 pixman_image_composite (pixman_op_t op,
792 pixman_image_t * src,
793 pixman_image_t * mask,
794 pixman_image_t * dest,
804 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
805 mask_x, mask_y, dest_x, dest_y, width, height);
809 * Work around GCC bug causing crashes in Mozilla with SSE2
811 * When using -msse, gcc generates movdqa instructions assuming that
812 * the stack is 16 byte aligned. Unfortunately some applications, such
813 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
814 * causes the movdqa instructions to fail.
816 * The __force_align_arg_pointer__ makes gcc generate a prologue that
817 * realigns the stack pointer to 16 bytes.
819 * On x86-64 this is not necessary because the standard ABI already
820 * calls for a 16 byte aligned stack.
822 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
824 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
825 __attribute__((__force_align_arg_pointer__))
828 pixman_image_composite32 (pixman_op_t op,
829 pixman_image_t * src,
830 pixman_image_t * mask,
831 pixman_image_t * dest,
841 _pixman_image_validate (src);
843 _pixman_image_validate (mask);
844 _pixman_image_validate (dest);
854 PIXMAN_EXPORT pixman_bool_t
855 pixman_blt (uint32_t *src_bits,
868 return _pixman_implementation_blt (get_implementation(),
869 src_bits, dst_bits, src_stride, dst_stride,
876 PIXMAN_EXPORT pixman_bool_t
877 pixman_fill (uint32_t *bits,
886 return _pixman_implementation_fill (
887 get_implementation(), bits, stride, bpp, x, y, width, height, xor);
891 color_to_uint32 (const pixman_color_t *color)
894 (color->alpha >> 8 << 24) |
895 (color->red >> 8 << 16) |
896 (color->green & 0xff00) |
901 color_to_pixel (pixman_color_t * color,
903 pixman_format_code_t format)
905 uint32_t c = color_to_uint32 (color);
907 if (!(format == PIXMAN_a8r8g8b8 ||
908 format == PIXMAN_x8r8g8b8 ||
909 format == PIXMAN_a8b8g8r8 ||
910 format == PIXMAN_x8b8g8r8 ||
911 format == PIXMAN_b8g8r8a8 ||
912 format == PIXMAN_b8g8r8x8 ||
913 format == PIXMAN_r5g6b5 ||
914 format == PIXMAN_b5g6r5 ||
915 format == PIXMAN_a8))
920 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
922 c = ((c & 0xff000000) >> 0) |
923 ((c & 0x00ff0000) >> 16) |
924 ((c & 0x0000ff00) >> 0) |
925 ((c & 0x000000ff) << 16);
927 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
929 c = ((c & 0xff000000) >> 24) |
930 ((c & 0x00ff0000) >> 8) |
931 ((c & 0x0000ff00) << 8) |
932 ((c & 0x000000ff) << 24);
935 if (format == PIXMAN_a8)
937 else if (format == PIXMAN_r5g6b5 ||
938 format == PIXMAN_b5g6r5)
939 c = CONVERT_8888_TO_0565 (c);
942 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
943 printf ("pixel: %x\n", c);
950 PIXMAN_EXPORT pixman_bool_t
951 pixman_image_fill_rectangles (pixman_op_t op,
952 pixman_image_t * dest,
953 pixman_color_t * color,
955 const pixman_rectangle16_t *rects)
957 pixman_box32_t stack_boxes[6];
958 pixman_box32_t *boxes;
959 pixman_bool_t result;
964 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
973 for (i = 0; i < n_rects; ++i)
975 boxes[i].x1 = rects[i].x;
976 boxes[i].y1 = rects[i].y;
977 boxes[i].x2 = boxes[i].x1 + rects[i].width;
978 boxes[i].y2 = boxes[i].y1 + rects[i].height;
981 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
983 if (boxes != stack_boxes)
989 PIXMAN_EXPORT pixman_bool_t
990 pixman_image_fill_boxes (pixman_op_t op,
991 pixman_image_t * dest,
992 pixman_color_t * color,
994 const pixman_box32_t *boxes)
996 pixman_image_t *solid;
1000 _pixman_image_validate (dest);
1002 if (color->alpha == 0xffff)
1004 if (op == PIXMAN_OP_OVER)
1008 if (op == PIXMAN_OP_CLEAR)
1020 if (op == PIXMAN_OP_SRC)
1024 if (color_to_pixel (color, &pixel, dest->bits.format))
1026 pixman_region32_t fill_region;
1028 pixman_box32_t *rects;
1030 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
1033 if (dest->common.have_clip_region)
1035 if (!pixman_region32_intersect (&fill_region,
1037 &dest->common.clip_region))
1041 rects = pixman_region32_rectangles (&fill_region, &n_rects);
1042 for (j = 0; j < n_rects; ++j)
1044 const pixman_box32_t *rect = &(rects[j]);
1045 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
1046 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
1050 pixman_region32_fini (&fill_region);
1055 solid = pixman_image_create_solid_fill (color);
1059 for (i = 0; i < n_boxes; ++i)
1061 const pixman_box32_t *box = &(boxes[i]);
1063 pixman_image_composite32 (op, solid, NULL, dest,
1066 box->x2 - box->x1, box->y2 - box->y1);
1069 pixman_image_unref (solid);
1077 * Returns the version of the pixman library encoded in a single
1078 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1079 * later versions compare greater than earlier versions.
1081 * A run-time comparison to check that pixman's version is greater than
1082 * or equal to version X.Y.Z could be performed as follows:
1084 * <informalexample><programlisting>
1085 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1086 * </programlisting></informalexample>
1088 * See also pixman_version_string() as well as the compile-time
1089 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1091 * Return value: the encoded version.
1094 pixman_version (void)
1096 return PIXMAN_VERSION;
1100 * pixman_version_string:
1102 * Returns the version of the pixman library as a human-readable string
1103 * of the form "X.Y.Z".
1105 * See also pixman_version() as well as the compile-time equivalents
1106 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1108 * Return value: a string containing the version.
1110 PIXMAN_EXPORT const char*
1111 pixman_version_string (void)
1113 return PIXMAN_VERSION_STRING;
1117 * pixman_format_supported_source:
1118 * @format: A pixman_format_code_t format
1120 * Return value: whether the provided format code is a supported
1121 * format for a pixman surface used as a source in
1124 * Currently, all pixman_format_code_t values are supported.
1126 PIXMAN_EXPORT pixman_bool_t
1127 pixman_format_supported_source (pixman_format_code_t format)
1131 /* 32 bpp formats */
1132 case PIXMAN_a2b10g10r10:
1133 case PIXMAN_x2b10g10r10:
1134 case PIXMAN_a2r10g10b10:
1135 case PIXMAN_x2r10g10b10:
1136 case PIXMAN_a8r8g8b8:
1137 case PIXMAN_x8r8g8b8:
1138 case PIXMAN_a8b8g8r8:
1139 case PIXMAN_x8b8g8r8:
1140 case PIXMAN_b8g8r8a8:
1141 case PIXMAN_b8g8r8x8:
1146 case PIXMAN_x14r6g6b6:
1147 /* 16 bpp formats */
1148 case PIXMAN_a1r5g5b5:
1149 case PIXMAN_x1r5g5b5:
1150 case PIXMAN_a1b5g5r5:
1151 case PIXMAN_x1b5g5r5:
1152 case PIXMAN_a4r4g4b4:
1153 case PIXMAN_x4r4g4b4:
1154 case PIXMAN_a4b4g4r4:
1155 case PIXMAN_x4b4g4r4:
1160 case PIXMAN_a2r2g2b2:
1161 case PIXMAN_a2b2g2r2:
1165 /* Collides with PIXMAN_c8
1168 /* Collides with PIXMAN_g8
1175 case PIXMAN_a1r1g1b1:
1176 case PIXMAN_a1b1g1r1:
1193 * pixman_format_supported_destination:
1194 * @format: A pixman_format_code_t format
1196 * Return value: whether the provided format code is a supported
1197 * format for a pixman surface used as a destination in
1200 * Currently, all pixman_format_code_t values are supported
1201 * except for the YUV formats.
1203 PIXMAN_EXPORT pixman_bool_t
1204 pixman_format_supported_destination (pixman_format_code_t format)
1206 /* YUV formats cannot be written to at the moment */
1207 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1210 return pixman_format_supported_source (format);
1213 PIXMAN_EXPORT pixman_bool_t
1214 pixman_compute_composite_region (pixman_region16_t * region,
1215 pixman_image_t * src_image,
1216 pixman_image_t * mask_image,
1217 pixman_image_t * dst_image,
1227 pixman_region32_t r32;
1228 pixman_bool_t retval;
1230 pixman_region32_init (&r32);
1232 retval = pixman_compute_composite_region32 (
1233 &r32, src_image, mask_image, dst_image,
1234 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1239 if (!pixman_region16_copy_from_region32 (region, &r32))
1243 pixman_region32_fini (&r32);