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)
503 do_composite (pixman_implementation_t *imp,
506 pixman_image_t *mask,
507 pixman_image_t *dest,
517 #define N_CACHED_FAST_PATHS 8
518 static THREAD_LOCAL pixman_fast_path_t tls_cache[N_CACHED_FAST_PATHS];
519 pixman_format_code_t src_format, mask_format, dest_format;
520 uint32_t src_flags, mask_flags, dest_flags;
521 pixman_region32_t region;
522 pixman_box32_t *extents;
526 int mask_dx, mask_dy;
528 int dest_dx, dest_dy;
529 pixman_bool_t need_workaround;
530 pixman_fast_path_t *cache;
531 const pixman_fast_path_t *info;
534 src_format = src->common.extended_format_code;
535 src_flags = src->common.flags;
539 mask_format = mask->common.extended_format_code;
540 mask_flags = mask->common.flags;
544 mask_format = PIXMAN_null;
545 mask_flags = FAST_PATH_IS_OPAQUE;
548 dest_format = dest->common.extended_format_code;
549 dest_flags = dest->common.flags;
551 /* Check for pixbufs */
552 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
553 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
554 (src->common.repeat == mask->common.repeat) &&
555 (src_x == mask_x && src_y == mask_y))
557 if (src_format == PIXMAN_x8b8g8r8)
558 src_format = mask_format = PIXMAN_pixbuf;
559 else if (src_format == PIXMAN_x8r8g8b8)
560 src_format = mask_format = PIXMAN_rpixbuf;
563 /* Check for workaround */
564 need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
568 apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
569 apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
570 apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
573 pixman_region32_init (®ion);
575 if (!pixman_compute_composite_region32 (
576 ®ion, src, mask, dest,
577 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
582 extents = pixman_region32_extents (®ion);
584 if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
585 src_flags |= FAST_PATH_COVERS_CLIP;
587 if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
588 mask_flags |= FAST_PATH_COVERS_CLIP;
591 * Check if we can replace our operator by a simpler one
592 * if the src or dest are opaque. The output operator should be
593 * mathematically equivalent to the source.
595 op = optimize_operator (op, src_flags, mask_flags, dest_flags);
596 if (op == PIXMAN_OP_DST)
599 /* Check cache for fast paths */
602 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
606 /* Note that we check for equality here, not whether
607 * the cached fast path matches. This is to prevent
608 * us from selecting an overly general fast path
609 * when a more specific one would work.
611 if (info->op == op &&
612 info->src_format == src_format &&
613 info->mask_format == mask_format &&
614 info->dest_format == dest_format &&
615 info->src_flags == src_flags &&
616 info->mask_flags == mask_flags &&
617 info->dest_flags == dest_flags &&
626 info = imp->fast_paths;
628 while (info->op != PIXMAN_OP_NONE)
630 if ((info->op == op || info->op == PIXMAN_OP_any) &&
632 ((info->src_format == src_format) ||
633 (info->src_format == PIXMAN_any)) &&
634 ((info->mask_format == mask_format) ||
635 (info->mask_format == PIXMAN_any)) &&
636 ((info->dest_format == dest_format) ||
637 (info->dest_format == PIXMAN_any)) &&
639 (info->src_flags & src_flags) == info->src_flags &&
640 (info->mask_flags & mask_flags) == info->mask_flags &&
641 (info->dest_flags & dest_flags) == info->dest_flags)
643 /* Set i to the last spot in the cache so that the
644 * move-to-front code below will work
646 i = N_CACHED_FAST_PATHS - 1;
657 /* We didn't find a compositing routine. This should not happen, but if
658 * it somehow does, just exit rather than crash.
663 walk_region_internal (imp, op,
665 src_x, src_y, mask_x, mask_y,
668 (src_flags & FAST_PATH_SIMPLE_REPEAT),
669 (mask_flags & FAST_PATH_SIMPLE_REPEAT),
670 ®ion, info->func);
674 /* Make a copy of info->func, because info->func may change when
675 * we update the cache.
677 pixman_composite_func_t func = info->func;
680 cache[i + 1] = cache[i];
683 cache[0].src_format = src_format;
684 cache[0].src_flags = src_flags;
685 cache[0].mask_format = mask_format;
686 cache[0].mask_flags = mask_flags;
687 cache[0].dest_format = dest_format;
688 cache[0].dest_flags = dest_flags;
689 cache[0].func = func;
695 unapply_workaround (src, src_bits, src_dx, src_dy);
696 unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
697 unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
700 pixman_region32_fini (®ion);
704 pixman_image_composite (pixman_op_t op,
705 pixman_image_t * src,
706 pixman_image_t * mask,
707 pixman_image_t * dest,
717 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
718 mask_x, mask_y, dest_x, dest_y, width, height);
722 * Work around GCC bug causing crashes in Mozilla with SSE2
724 * When using -msse, gcc generates movdqa instructions assuming that
725 * the stack is 16 byte aligned. Unfortunately some applications, such
726 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
727 * causes the movdqa instructions to fail.
729 * The __force_align_arg_pointer__ makes gcc generate a prologue that
730 * realigns the stack pointer to 16 bytes.
732 * On x86-64 this is not necessary because the standard ABI already
733 * calls for a 16 byte aligned stack.
735 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
737 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
738 __attribute__((__force_align_arg_pointer__))
741 pixman_image_composite32 (pixman_op_t op,
742 pixman_image_t * src,
743 pixman_image_t * mask,
744 pixman_image_t * dest,
754 _pixman_image_validate (src);
756 _pixman_image_validate (mask);
757 _pixman_image_validate (dest);
760 imp = _pixman_choose_implementation ();
762 do_composite (imp, op,
770 PIXMAN_EXPORT pixman_bool_t
771 pixman_blt (uint32_t *src_bits,
785 imp = _pixman_choose_implementation ();
787 return _pixman_implementation_blt (imp, src_bits, dst_bits, src_stride, dst_stride,
794 PIXMAN_EXPORT pixman_bool_t
795 pixman_fill (uint32_t *bits,
805 imp = _pixman_choose_implementation ();
807 return _pixman_implementation_fill (imp, bits, stride, bpp, x, y, width, height, xor);
811 color_to_uint32 (const pixman_color_t *color)
814 (color->alpha >> 8 << 24) |
815 (color->red >> 8 << 16) |
816 (color->green & 0xff00) |
821 color_to_pixel (pixman_color_t * color,
823 pixman_format_code_t format)
825 uint32_t c = color_to_uint32 (color);
827 if (!(format == PIXMAN_a8r8g8b8 ||
828 format == PIXMAN_x8r8g8b8 ||
829 format == PIXMAN_a8b8g8r8 ||
830 format == PIXMAN_x8b8g8r8 ||
831 format == PIXMAN_b8g8r8a8 ||
832 format == PIXMAN_b8g8r8x8 ||
833 format == PIXMAN_r5g6b5 ||
834 format == PIXMAN_b5g6r5 ||
835 format == PIXMAN_a8))
840 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
842 c = ((c & 0xff000000) >> 0) |
843 ((c & 0x00ff0000) >> 16) |
844 ((c & 0x0000ff00) >> 0) |
845 ((c & 0x000000ff) << 16);
847 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
849 c = ((c & 0xff000000) >> 24) |
850 ((c & 0x00ff0000) >> 8) |
851 ((c & 0x0000ff00) << 8) |
852 ((c & 0x000000ff) << 24);
855 if (format == PIXMAN_a8)
857 else if (format == PIXMAN_r5g6b5 ||
858 format == PIXMAN_b5g6r5)
859 c = CONVERT_8888_TO_0565 (c);
862 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
863 printf ("pixel: %x\n", c);
870 PIXMAN_EXPORT pixman_bool_t
871 pixman_image_fill_rectangles (pixman_op_t op,
872 pixman_image_t * dest,
873 pixman_color_t * color,
875 const pixman_rectangle16_t *rects)
877 pixman_box32_t stack_boxes[6];
878 pixman_box32_t *boxes;
879 pixman_bool_t result;
884 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
893 for (i = 0; i < n_rects; ++i)
895 boxes[i].x1 = rects[i].x;
896 boxes[i].y1 = rects[i].y;
897 boxes[i].x2 = boxes[i].x1 + rects[i].width;
898 boxes[i].y2 = boxes[i].y1 + rects[i].height;
901 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
903 if (boxes != stack_boxes)
909 PIXMAN_EXPORT pixman_bool_t
910 pixman_image_fill_boxes (pixman_op_t op,
911 pixman_image_t * dest,
912 pixman_color_t * color,
914 const pixman_box32_t *boxes)
916 pixman_image_t *solid;
920 _pixman_image_validate (dest);
922 if (color->alpha == 0xffff)
924 if (op == PIXMAN_OP_OVER)
928 if (op == PIXMAN_OP_CLEAR)
940 if (op == PIXMAN_OP_SRC)
944 if (color_to_pixel (color, &pixel, dest->bits.format))
946 pixman_region32_t fill_region;
948 pixman_box32_t *rects;
950 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
953 if (dest->common.have_clip_region)
955 if (!pixman_region32_intersect (&fill_region,
957 &dest->common.clip_region))
961 rects = pixman_region32_rectangles (&fill_region, &n_rects);
962 for (j = 0; j < n_rects; ++j)
964 const pixman_box32_t *rect = &(rects[j]);
965 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
966 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
970 pixman_region32_fini (&fill_region);
975 solid = pixman_image_create_solid_fill (color);
979 for (i = 0; i < n_boxes; ++i)
981 const pixman_box32_t *box = &(boxes[i]);
983 pixman_image_composite32 (op, solid, NULL, dest,
986 box->x2 - box->x1, box->y2 - box->y1);
989 pixman_image_unref (solid);
997 * Returns the version of the pixman library encoded in a single
998 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
999 * later versions compare greater than earlier versions.
1001 * A run-time comparison to check that pixman's version is greater than
1002 * or equal to version X.Y.Z could be performed as follows:
1004 * <informalexample><programlisting>
1005 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1006 * </programlisting></informalexample>
1008 * See also pixman_version_string() as well as the compile-time
1009 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1011 * Return value: the encoded version.
1014 pixman_version (void)
1016 return PIXMAN_VERSION;
1020 * pixman_version_string:
1022 * Returns the version of the pixman library as a human-readable string
1023 * of the form "X.Y.Z".
1025 * See also pixman_version() as well as the compile-time equivalents
1026 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1028 * Return value: a string containing the version.
1030 PIXMAN_EXPORT const char*
1031 pixman_version_string (void)
1033 return PIXMAN_VERSION_STRING;
1037 * pixman_format_supported_source:
1038 * @format: A pixman_format_code_t format
1040 * Return value: whether the provided format code is a supported
1041 * format for a pixman surface used as a source in
1044 * Currently, all pixman_format_code_t values are supported.
1046 PIXMAN_EXPORT pixman_bool_t
1047 pixman_format_supported_source (pixman_format_code_t format)
1051 /* 32 bpp formats */
1052 case PIXMAN_a2b10g10r10:
1053 case PIXMAN_x2b10g10r10:
1054 case PIXMAN_a2r10g10b10:
1055 case PIXMAN_x2r10g10b10:
1056 case PIXMAN_a8r8g8b8:
1057 case PIXMAN_x8r8g8b8:
1058 case PIXMAN_a8b8g8r8:
1059 case PIXMAN_x8b8g8r8:
1060 case PIXMAN_b8g8r8a8:
1061 case PIXMAN_b8g8r8x8:
1066 /* 16 bpp formats */
1067 case PIXMAN_a1r5g5b5:
1068 case PIXMAN_x1r5g5b5:
1069 case PIXMAN_a1b5g5r5:
1070 case PIXMAN_x1b5g5r5:
1071 case PIXMAN_a4r4g4b4:
1072 case PIXMAN_x4r4g4b4:
1073 case PIXMAN_a4b4g4r4:
1074 case PIXMAN_x4b4g4r4:
1079 case PIXMAN_a2r2g2b2:
1080 case PIXMAN_a2b2g2r2:
1084 /* Collides with PIXMAN_c8
1087 /* Collides with PIXMAN_g8
1094 case PIXMAN_a1r1g1b1:
1095 case PIXMAN_a1b1g1r1:
1112 * pixman_format_supported_destination:
1113 * @format: A pixman_format_code_t format
1115 * Return value: whether the provided format code is a supported
1116 * format for a pixman surface used as a destination in
1119 * Currently, all pixman_format_code_t values are supported
1120 * except for the YUV formats.
1122 PIXMAN_EXPORT pixman_bool_t
1123 pixman_format_supported_destination (pixman_format_code_t format)
1125 /* YUV formats cannot be written to at the moment */
1126 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1129 return pixman_format_supported_source (format);
1132 PIXMAN_EXPORT pixman_bool_t
1133 pixman_compute_composite_region (pixman_region16_t * region,
1134 pixman_image_t * src_image,
1135 pixman_image_t * mask_image,
1136 pixman_image_t * dst_image,
1146 pixman_region32_t r32;
1147 pixman_bool_t retval;
1149 pixman_region32_init (&r32);
1151 retval = pixman_compute_composite_region32 (
1152 &r32, src_image, mask_image, dst_image,
1153 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1158 if (!pixman_region16_copy_from_region32 (region, &r32))
1162 pixman_region32_fini (&r32);