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 pixman_implementation_t *imp;
35 typedef struct operator_info_t operator_info_t;
37 struct operator_info_t
39 uint8_t opaque_info[4];
42 #define PACK(neither, src, dest, both) \
43 {{ (uint8_t)PIXMAN_OP_ ## neither, \
44 (uint8_t)PIXMAN_OP_ ## src, \
45 (uint8_t)PIXMAN_OP_ ## dest, \
46 (uint8_t)PIXMAN_OP_ ## both }}
48 static const operator_info_t operator_table[] =
50 /* Neither Opaque Src Opaque Dst Opaque Both Opaque */
51 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
52 PACK (SRC, SRC, SRC, SRC),
53 PACK (DST, DST, DST, DST),
54 PACK (OVER, SRC, OVER, SRC),
55 PACK (OVER_REVERSE, OVER_REVERSE, DST, DST),
56 PACK (IN, IN, SRC, SRC),
57 PACK (IN_REVERSE, DST, IN_REVERSE, DST),
58 PACK (OUT, OUT, CLEAR, CLEAR),
59 PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR),
60 PACK (ATOP, IN, OVER, SRC),
61 PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST),
62 PACK (XOR, OUT, OUT_REVERSE, CLEAR),
63 PACK (ADD, ADD, ADD, ADD),
64 PACK (SATURATE, OVER_REVERSE, DST, DST),
69 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
70 PACK (SRC, SRC, SRC, SRC),
71 PACK (DST, DST, DST, DST),
72 PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER),
73 PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
74 PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN),
75 PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE),
76 PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT),
77 PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE),
78 PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP),
79 PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
80 PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR),
87 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
88 PACK (SRC, SRC, SRC, SRC),
89 PACK (DST, DST, DST, DST),
90 PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER),
91 PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
92 PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN),
93 PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE),
94 PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT),
95 PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE),
96 PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP),
97 PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
98 PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR),
105 PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY),
106 PACK (SCREEN, SCREEN, SCREEN, SCREEN),
107 PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY),
108 PACK (DARKEN, DARKEN, DARKEN, DARKEN),
109 PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN),
110 PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE),
111 PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN),
112 PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT),
113 PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT),
114 PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE),
115 PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION),
116 PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE),
117 PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION),
118 PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR),
119 PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY),
123 * Optimize the current operator based on opacity of source or destination
124 * The output operator should be mathematically equivalent to the source.
127 optimize_operator (pixman_op_t op,
132 pixman_bool_t is_source_opaque, is_dest_opaque;
135 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0;
136 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0;
138 opaqueness = ((is_dest_opaque << 1) | is_source_opaque);
140 return operator_table[op].opaque_info[opaqueness];
144 apply_workaround (pixman_image_t *image,
147 uint32_t ** save_bits,
151 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
153 /* Some X servers generate images that point to the
154 * wrong place in memory, but then set the clip region
155 * to point to the right place. Because of an old bug
156 * in pixman, this would actually work.
158 * Here we try and undo the damage
160 int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
161 pixman_box32_t *extents;
165 extents = pixman_region32_extents (&(image->common.clip_region));
169 *save_bits = image->bits.bits;
173 pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
175 t = (uint8_t *)image->bits.bits;
176 t += dy * image->bits.rowstride * 4 + dx * bpp;
177 image->bits.bits = (uint32_t *)t;
185 unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
187 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
189 image->bits.bits = bits;
190 pixman_region32_translate (&image->common.clip_region, dx, dy);
195 * Computing composite region
197 static inline pixman_bool_t
198 clip_general_image (pixman_region32_t * region,
199 pixman_region32_t * clip,
203 if (pixman_region32_n_rects (region) == 1 &&
204 pixman_region32_n_rects (clip) == 1)
206 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL);
207 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL);
210 if (rbox->x1 < (v = cbox->x1 + dx))
212 if (rbox->x2 > (v = cbox->x2 + dx))
214 if (rbox->y1 < (v = cbox->y1 + dy))
216 if (rbox->y2 > (v = cbox->y2 + dy))
218 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
220 pixman_region32_init (region);
224 else if (!pixman_region32_not_empty (clip))
231 pixman_region32_translate (region, -dx, -dy);
233 if (!pixman_region32_intersect (region, region, clip))
237 pixman_region32_translate (region, dx, dy);
240 return pixman_region32_not_empty (region);
243 static inline pixman_bool_t
244 clip_source_image (pixman_region32_t * region,
245 pixman_image_t * image,
249 /* Source clips are ignored, unless they are explicitly turned on
250 * and the clip in question was set by an X client. (Because if
251 * the clip was not set by a client, then it is a hierarchy
252 * clip and those should always be ignored for sources).
254 if (!image->common.clip_sources || !image->common.client_clip)
257 return clip_general_image (region,
258 &image->common.clip_region,
263 * returns FALSE if the final region is empty. Indistinguishable from
264 * an allocation failure, but rendering ignores those anyways.
267 pixman_compute_composite_region32 (pixman_region32_t * region,
268 pixman_image_t * src_image,
269 pixman_image_t * mask_image,
270 pixman_image_t * dst_image,
280 region->extents.x1 = dest_x;
281 region->extents.x2 = dest_x + width;
282 region->extents.y1 = dest_y;
283 region->extents.y2 = dest_y + height;
285 region->extents.x1 = MAX (region->extents.x1, 0);
286 region->extents.y1 = MAX (region->extents.y1, 0);
287 region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
288 region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
292 /* Check for empty operation */
293 if (region->extents.x1 >= region->extents.x2 ||
294 region->extents.y1 >= region->extents.y2)
296 pixman_region32_init (region);
300 if (dst_image->common.have_clip_region)
302 if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
304 pixman_region32_fini (region);
309 if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
311 if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
312 -dst_image->common.alpha_origin_x,
313 -dst_image->common.alpha_origin_y))
315 pixman_region32_fini (region);
320 /* clip against src */
321 if (src_image->common.have_clip_region)
323 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
325 pixman_region32_fini (region);
329 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
331 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
332 dest_x - (src_x - src_image->common.alpha_origin_x),
333 dest_y - (src_y - src_image->common.alpha_origin_y)))
335 pixman_region32_fini (region);
339 /* clip against mask */
340 if (mask_image && mask_image->common.have_clip_region)
342 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
344 pixman_region32_fini (region);
347 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
349 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
350 dest_x - (mask_x - mask_image->common.alpha_origin_x),
351 dest_y - (mask_y - mask_image->common.alpha_origin_y)))
353 pixman_region32_fini (region);
363 walk_region_internal (pixman_implementation_t *imp,
365 pixman_image_t * src_image,
366 pixman_image_t * mask_image,
367 pixman_image_t * dst_image,
376 pixman_bool_t src_repeat,
377 pixman_bool_t mask_repeat,
378 pixman_region32_t * region,
379 pixman_composite_func_t composite_rect)
381 int w, h, w_this, h_this;
382 int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
383 int src_dy = src_y - dest_y;
384 int src_dx = src_x - dest_x;
385 int mask_dy = mask_y - dest_y;
386 int mask_dx = mask_x - dest_x;
387 const pixman_box32_t *pbox;
390 pbox = pixman_region32_rectangles (region, &n);
392 /* Fast path for non-repeating sources */
393 if (!src_repeat && !mask_repeat)
397 (*composite_rect) (imp, op,
398 src_image, mask_image, dst_image,
406 pbox->y2 - pbox->y1);
416 h = pbox->y2 - pbox->y1;
417 y_src = pbox->y1 + src_dy;
418 y_msk = pbox->y1 + mask_dy;
424 w = pbox->x2 - pbox->x1;
425 x_src = pbox->x1 + src_dx;
426 x_msk = pbox->x1 + mask_dx;
431 y_msk = MOD (y_msk, mask_image->bits.height);
432 if (h_this > mask_image->bits.height - y_msk)
433 h_this = mask_image->bits.height - y_msk;
438 y_src = MOD (y_src, src_image->bits.height);
439 if (h_this > src_image->bits.height - y_src)
440 h_this = src_image->bits.height - y_src;
449 x_msk = MOD (x_msk, mask_image->bits.width);
450 if (w_this > mask_image->bits.width - x_msk)
451 w_this = mask_image->bits.width - x_msk;
456 x_src = MOD (x_src, src_image->bits.width);
457 if (w_this > src_image->bits.width - x_src)
458 w_this = src_image->bits.width - x_src;
461 (*composite_rect) (imp, op,
462 src_image, mask_image, dst_image,
463 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
482 static force_inline pixman_bool_t
483 image_covers (pixman_image_t *image,
484 pixman_box32_t *extents,
488 if (image->common.type == BITS &&
489 image->common.repeat == PIXMAN_REPEAT_NONE)
491 if (x > extents->x1 || y > extents->y1 ||
492 x + image->bits.width < extents->x2 ||
493 y + image->bits.height < extents->y2)
502 #define N_CACHED_FAST_PATHS 8
506 pixman_fast_path_t cache [N_CACHED_FAST_PATHS];
509 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
512 do_composite (pixman_implementation_t *imp,
515 pixman_image_t *mask,
516 pixman_image_t *dest,
526 pixman_format_code_t src_format, mask_format, dest_format;
527 uint32_t src_flags, mask_flags, dest_flags;
528 pixman_region32_t region;
529 pixman_box32_t *extents;
533 int mask_dx, mask_dy;
535 int dest_dx, dest_dy;
536 pixman_bool_t need_workaround;
537 const pixman_fast_path_t *info;
541 src_format = src->common.extended_format_code;
542 src_flags = src->common.flags;
546 mask_format = mask->common.extended_format_code;
547 mask_flags = mask->common.flags;
551 mask_format = PIXMAN_null;
552 mask_flags = FAST_PATH_IS_OPAQUE;
555 dest_format = dest->common.extended_format_code;
556 dest_flags = dest->common.flags;
558 /* Check for pixbufs */
559 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
560 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
561 (src->common.repeat == mask->common.repeat) &&
562 (src_x == mask_x && src_y == mask_y))
564 if (src_format == PIXMAN_x8b8g8r8)
565 src_format = mask_format = PIXMAN_pixbuf;
566 else if (src_format == PIXMAN_x8r8g8b8)
567 src_format = mask_format = PIXMAN_rpixbuf;
570 /* Check for workaround */
571 need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
575 apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
576 apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
577 apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
580 pixman_region32_init (®ion);
582 if (!pixman_compute_composite_region32 (
583 ®ion, src, mask, dest,
584 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
589 extents = pixman_region32_extents (®ion);
591 if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
592 src_flags |= FAST_PATH_COVERS_CLIP;
594 if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
595 mask_flags |= FAST_PATH_COVERS_CLIP;
598 * Check if we can replace our operator by a simpler one
599 * if the src or dest are opaque. The output operator should be
600 * mathematically equivalent to the source.
602 op = optimize_operator (op, src_flags, mask_flags, dest_flags);
603 if (op == PIXMAN_OP_DST)
606 /* Check cache for fast paths */
607 cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
609 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
611 info = &(cache->cache[i]);
613 /* Note that we check for equality here, not whether
614 * the cached fast path matches. This is to prevent
615 * us from selecting an overly general fast path
616 * when a more specific one would work.
618 if (info->op == op &&
619 info->src_format == src_format &&
620 info->mask_format == mask_format &&
621 info->dest_format == dest_format &&
622 info->src_flags == src_flags &&
623 info->mask_flags == mask_flags &&
624 info->dest_flags == dest_flags &&
633 info = imp->fast_paths;
635 while (info->op != PIXMAN_OP_NONE)
637 if ((info->op == op || info->op == PIXMAN_OP_any) &&
639 ((info->src_format == src_format) ||
640 (info->src_format == PIXMAN_any)) &&
641 ((info->mask_format == mask_format) ||
642 (info->mask_format == PIXMAN_any)) &&
643 ((info->dest_format == dest_format) ||
644 (info->dest_format == PIXMAN_any)) &&
646 (info->src_flags & src_flags) == info->src_flags &&
647 (info->mask_flags & mask_flags) == info->mask_flags &&
648 (info->dest_flags & dest_flags) == info->dest_flags)
650 /* Set i to the last spot in the cache so that the
651 * move-to-front code below will work
653 i = N_CACHED_FAST_PATHS - 1;
664 /* We didn't find a compositing routine. This should not happen, but if
665 * it somehow does, just exit rather than crash.
670 walk_region_internal (imp, op,
672 src_x, src_y, mask_x, mask_y,
675 (src_flags & FAST_PATH_SIMPLE_REPEAT),
676 (mask_flags & FAST_PATH_SIMPLE_REPEAT),
677 ®ion, info->func);
681 /* Make a copy of info->func, because info->func may change when
682 * we update the cache.
684 pixman_composite_func_t func = info->func;
687 cache->cache[i + 1] = cache->cache[i];
689 cache->cache[0].op = op;
690 cache->cache[0].src_format = src_format;
691 cache->cache[0].src_flags = src_flags;
692 cache->cache[0].mask_format = mask_format;
693 cache->cache[0].mask_flags = mask_flags;
694 cache->cache[0].dest_format = dest_format;
695 cache->cache[0].dest_flags = dest_flags;
696 cache->cache[0].func = func;
702 unapply_workaround (src, src_bits, src_dx, src_dy);
703 unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
704 unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
707 pixman_region32_fini (®ion);
711 pixman_image_composite (pixman_op_t op,
712 pixman_image_t * src,
713 pixman_image_t * mask,
714 pixman_image_t * dest,
724 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
725 mask_x, mask_y, dest_x, dest_y, width, height);
729 * Work around GCC bug causing crashes in Mozilla with SSE2
731 * When using -msse, gcc generates movdqa instructions assuming that
732 * the stack is 16 byte aligned. Unfortunately some applications, such
733 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
734 * causes the movdqa instructions to fail.
736 * The __force_align_arg_pointer__ makes gcc generate a prologue that
737 * realigns the stack pointer to 16 bytes.
739 * On x86-64 this is not necessary because the standard ABI already
740 * calls for a 16 byte aligned stack.
742 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
744 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
745 __attribute__((__force_align_arg_pointer__))
748 pixman_image_composite32 (pixman_op_t op,
749 pixman_image_t * src,
750 pixman_image_t * mask,
751 pixman_image_t * dest,
761 _pixman_image_validate (src);
763 _pixman_image_validate (mask);
764 _pixman_image_validate (dest);
767 imp = _pixman_choose_implementation ();
769 do_composite (imp, op,
777 PIXMAN_EXPORT pixman_bool_t
778 pixman_blt (uint32_t *src_bits,
792 imp = _pixman_choose_implementation ();
794 return _pixman_implementation_blt (imp, src_bits, dst_bits, src_stride, dst_stride,
801 PIXMAN_EXPORT pixman_bool_t
802 pixman_fill (uint32_t *bits,
812 imp = _pixman_choose_implementation ();
814 return _pixman_implementation_fill (imp, bits, stride, bpp, x, y, width, height, xor);
818 color_to_uint32 (const pixman_color_t *color)
821 (color->alpha >> 8 << 24) |
822 (color->red >> 8 << 16) |
823 (color->green & 0xff00) |
828 color_to_pixel (pixman_color_t * color,
830 pixman_format_code_t format)
832 uint32_t c = color_to_uint32 (color);
834 if (!(format == PIXMAN_a8r8g8b8 ||
835 format == PIXMAN_x8r8g8b8 ||
836 format == PIXMAN_a8b8g8r8 ||
837 format == PIXMAN_x8b8g8r8 ||
838 format == PIXMAN_b8g8r8a8 ||
839 format == PIXMAN_b8g8r8x8 ||
840 format == PIXMAN_r5g6b5 ||
841 format == PIXMAN_b5g6r5 ||
842 format == PIXMAN_a8))
847 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
849 c = ((c & 0xff000000) >> 0) |
850 ((c & 0x00ff0000) >> 16) |
851 ((c & 0x0000ff00) >> 0) |
852 ((c & 0x000000ff) << 16);
854 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
856 c = ((c & 0xff000000) >> 24) |
857 ((c & 0x00ff0000) >> 8) |
858 ((c & 0x0000ff00) << 8) |
859 ((c & 0x000000ff) << 24);
862 if (format == PIXMAN_a8)
864 else if (format == PIXMAN_r5g6b5 ||
865 format == PIXMAN_b5g6r5)
866 c = CONVERT_8888_TO_0565 (c);
869 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
870 printf ("pixel: %x\n", c);
877 PIXMAN_EXPORT pixman_bool_t
878 pixman_image_fill_rectangles (pixman_op_t op,
879 pixman_image_t * dest,
880 pixman_color_t * color,
882 const pixman_rectangle16_t *rects)
884 pixman_box32_t stack_boxes[6];
885 pixman_box32_t *boxes;
886 pixman_bool_t result;
891 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
900 for (i = 0; i < n_rects; ++i)
902 boxes[i].x1 = rects[i].x;
903 boxes[i].y1 = rects[i].y;
904 boxes[i].x2 = boxes[i].x1 + rects[i].width;
905 boxes[i].y2 = boxes[i].y1 + rects[i].height;
908 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
910 if (boxes != stack_boxes)
916 PIXMAN_EXPORT pixman_bool_t
917 pixman_image_fill_boxes (pixman_op_t op,
918 pixman_image_t * dest,
919 pixman_color_t * color,
921 const pixman_box32_t *boxes)
923 pixman_image_t *solid;
927 _pixman_image_validate (dest);
929 if (color->alpha == 0xffff)
931 if (op == PIXMAN_OP_OVER)
935 if (op == PIXMAN_OP_CLEAR)
947 if (op == PIXMAN_OP_SRC)
951 if (color_to_pixel (color, &pixel, dest->bits.format))
953 pixman_region32_t fill_region;
955 pixman_box32_t *rects;
957 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
960 if (dest->common.have_clip_region)
962 if (!pixman_region32_intersect (&fill_region,
964 &dest->common.clip_region))
968 rects = pixman_region32_rectangles (&fill_region, &n_rects);
969 for (j = 0; j < n_rects; ++j)
971 const pixman_box32_t *rect = &(rects[j]);
972 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
973 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
977 pixman_region32_fini (&fill_region);
982 solid = pixman_image_create_solid_fill (color);
986 for (i = 0; i < n_boxes; ++i)
988 const pixman_box32_t *box = &(boxes[i]);
990 pixman_image_composite32 (op, solid, NULL, dest,
993 box->x2 - box->x1, box->y2 - box->y1);
996 pixman_image_unref (solid);
1004 * Returns the version of the pixman library encoded in a single
1005 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1006 * later versions compare greater than earlier versions.
1008 * A run-time comparison to check that pixman's version is greater than
1009 * or equal to version X.Y.Z could be performed as follows:
1011 * <informalexample><programlisting>
1012 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1013 * </programlisting></informalexample>
1015 * See also pixman_version_string() as well as the compile-time
1016 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1018 * Return value: the encoded version.
1021 pixman_version (void)
1023 return PIXMAN_VERSION;
1027 * pixman_version_string:
1029 * Returns the version of the pixman library as a human-readable string
1030 * of the form "X.Y.Z".
1032 * See also pixman_version() as well as the compile-time equivalents
1033 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1035 * Return value: a string containing the version.
1037 PIXMAN_EXPORT const char*
1038 pixman_version_string (void)
1040 return PIXMAN_VERSION_STRING;
1044 * pixman_format_supported_source:
1045 * @format: A pixman_format_code_t format
1047 * Return value: whether the provided format code is a supported
1048 * format for a pixman surface used as a source in
1051 * Currently, all pixman_format_code_t values are supported.
1053 PIXMAN_EXPORT pixman_bool_t
1054 pixman_format_supported_source (pixman_format_code_t format)
1058 /* 32 bpp formats */
1059 case PIXMAN_a2b10g10r10:
1060 case PIXMAN_x2b10g10r10:
1061 case PIXMAN_a2r10g10b10:
1062 case PIXMAN_x2r10g10b10:
1063 case PIXMAN_a8r8g8b8:
1064 case PIXMAN_x8r8g8b8:
1065 case PIXMAN_a8b8g8r8:
1066 case PIXMAN_x8b8g8r8:
1067 case PIXMAN_b8g8r8a8:
1068 case PIXMAN_b8g8r8x8:
1073 /* 16 bpp formats */
1074 case PIXMAN_a1r5g5b5:
1075 case PIXMAN_x1r5g5b5:
1076 case PIXMAN_a1b5g5r5:
1077 case PIXMAN_x1b5g5r5:
1078 case PIXMAN_a4r4g4b4:
1079 case PIXMAN_x4r4g4b4:
1080 case PIXMAN_a4b4g4r4:
1081 case PIXMAN_x4b4g4r4:
1086 case PIXMAN_a2r2g2b2:
1087 case PIXMAN_a2b2g2r2:
1091 /* Collides with PIXMAN_c8
1094 /* Collides with PIXMAN_g8
1101 case PIXMAN_a1r1g1b1:
1102 case PIXMAN_a1b1g1r1:
1119 * pixman_format_supported_destination:
1120 * @format: A pixman_format_code_t format
1122 * Return value: whether the provided format code is a supported
1123 * format for a pixman surface used as a destination in
1126 * Currently, all pixman_format_code_t values are supported
1127 * except for the YUV formats.
1129 PIXMAN_EXPORT pixman_bool_t
1130 pixman_format_supported_destination (pixman_format_code_t format)
1132 /* YUV formats cannot be written to at the moment */
1133 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1136 return pixman_format_supported_source (format);
1139 PIXMAN_EXPORT pixman_bool_t
1140 pixman_compute_composite_region (pixman_region16_t * region,
1141 pixman_image_t * src_image,
1142 pixman_image_t * mask_image,
1143 pixman_image_t * dst_image,
1153 pixman_region32_t r32;
1154 pixman_bool_t retval;
1156 pixman_region32_init (&r32);
1158 retval = pixman_compute_composite_region32 (
1159 &r32, src_image, mask_image, dst_image,
1160 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1165 if (!pixman_region16_copy_from_region32 (region, &r32))
1169 pixman_region32_fini (&r32);