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 #define PACK(a, b, c, d) \
36 (((uint8_t)PIXMAN_OP_ ## a << 0) | \
37 ((uint8_t)PIXMAN_OP_ ## b << 8) | \
38 ((uint8_t)PIXMAN_OP_ ## c << 16) | \
39 ((uint8_t)PIXMAN_OP_ ## d << 24))
41 static const uint32_t operator_table[] =
43 /* Neither Opaque Src Opaque Dst Opaque Both Opaque */
44 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
45 PACK (SRC, SRC, SRC, SRC),
46 PACK (DST, DST, DST, DST),
47 PACK (OVER, SRC, OVER, SRC),
48 PACK (OVER_REVERSE, OVER_REVERSE, DST, DST),
49 PACK (IN, IN, SRC, SRC),
50 PACK (IN_REVERSE, DST, IN_REVERSE, DST),
51 PACK (OUT, OUT, CLEAR, CLEAR),
52 PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR),
53 PACK (ATOP, IN, OVER, SRC),
54 PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST),
55 PACK (XOR, OUT, OUT_REVERSE, CLEAR),
56 PACK (ADD, ADD, ADD, ADD),
57 PACK (SATURATE, OVER_REVERSE, DST, DST),
62 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
63 PACK (SRC, SRC, SRC, SRC),
64 PACK (DST, DST, DST, DST),
65 PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER),
66 PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
67 PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN),
68 PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE),
69 PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT),
70 PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE),
71 PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP),
72 PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
73 PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR),
80 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
81 PACK (SRC, SRC, SRC, SRC),
82 PACK (DST, DST, DST, DST),
83 PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER),
84 PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
85 PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN),
86 PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE),
87 PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT),
88 PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE),
89 PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP),
90 PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
91 PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR),
98 PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY),
99 PACK (SCREEN, SCREEN, SCREEN, SCREEN),
100 PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY),
101 PACK (DARKEN, DARKEN, DARKEN, DARKEN),
102 PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN),
103 PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE),
104 PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN),
105 PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT),
106 PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT),
107 PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE),
108 PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION),
109 PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE),
110 PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION),
111 PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR),
112 PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY),
118 * Optimize the current operator based on opacity of source or destination
119 * The output operator should be mathematically equivalent to the source.
122 optimize_operator (pixman_op_t op,
127 pixman_bool_t is_source_opaque, is_dest_opaque;
130 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE) != 0;
131 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE) != 0;
133 shift = 8 * ((is_dest_opaque << 1) | is_source_opaque);
135 return (operator_table[op] >> shift) & 0xff;
139 apply_workaround (pixman_image_t *image,
142 uint32_t ** save_bits,
146 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
148 /* Some X servers generate images that point to the
149 * wrong place in memory, but then set the clip region
150 * to point to the right place. Because of an old bug
151 * in pixman, this would actually work.
153 * Here we try and undo the damage
155 int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
156 pixman_box32_t *extents;
160 extents = pixman_region32_extents (&(image->common.clip_region));
164 *save_bits = image->bits.bits;
168 pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
170 t = (uint8_t *)image->bits.bits;
171 t += dy * image->bits.rowstride * 4 + dx * bpp;
172 image->bits.bits = (uint32_t *)t;
180 unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
182 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
184 image->bits.bits = bits;
185 pixman_region32_translate (&image->common.clip_region, dx, dy);
190 * Computing composite region
192 static inline pixman_bool_t
193 clip_general_image (pixman_region32_t * region,
194 pixman_region32_t * clip,
198 if (pixman_region32_n_rects (region) == 1 &&
199 pixman_region32_n_rects (clip) == 1)
201 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL);
202 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL);
205 if (rbox->x1 < (v = cbox->x1 + dx))
207 if (rbox->x2 > (v = cbox->x2 + dx))
209 if (rbox->y1 < (v = cbox->y1 + dy))
211 if (rbox->y2 > (v = cbox->y2 + dy))
213 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
215 pixman_region32_init (region);
219 else if (!pixman_region32_not_empty (clip))
226 pixman_region32_translate (region, -dx, -dy);
228 if (!pixman_region32_intersect (region, region, clip))
232 pixman_region32_translate (region, dx, dy);
235 return pixman_region32_not_empty (region);
238 static inline pixman_bool_t
239 clip_source_image (pixman_region32_t * region,
240 pixman_image_t * image,
244 /* Source clips are ignored, unless they are explicitly turned on
245 * and the clip in question was set by an X client. (Because if
246 * the clip was not set by a client, then it is a hierarchy
247 * clip and those should always be ignored for sources).
249 if (!image->common.clip_sources || !image->common.client_clip)
252 return clip_general_image (region,
253 &image->common.clip_region,
258 * returns FALSE if the final region is empty. Indistinguishable from
259 * an allocation failure, but rendering ignores those anyways.
262 pixman_compute_composite_region32 (pixman_region32_t * region,
263 pixman_image_t * src_image,
264 pixman_image_t * mask_image,
265 pixman_image_t * dst_image,
275 region->extents.x1 = dest_x;
276 region->extents.x2 = dest_x + width;
277 region->extents.y1 = dest_y;
278 region->extents.y2 = dest_y + height;
280 region->extents.x1 = MAX (region->extents.x1, 0);
281 region->extents.y1 = MAX (region->extents.y1, 0);
282 region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
283 region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
287 /* Check for empty operation */
288 if (region->extents.x1 >= region->extents.x2 ||
289 region->extents.y1 >= region->extents.y2)
291 pixman_region32_init (region);
295 if (dst_image->common.have_clip_region)
297 if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
299 pixman_region32_fini (region);
304 if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region)
306 if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
307 -dst_image->common.alpha_origin_x,
308 -dst_image->common.alpha_origin_y))
310 pixman_region32_fini (region);
315 /* clip against src */
316 if (src_image->common.have_clip_region)
318 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
320 pixman_region32_fini (region);
324 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
326 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
327 dest_x - (src_x - src_image->common.alpha_origin_x),
328 dest_y - (src_y - src_image->common.alpha_origin_y)))
330 pixman_region32_fini (region);
334 /* clip against mask */
335 if (mask_image && mask_image->common.have_clip_region)
337 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
339 pixman_region32_fini (region);
342 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
344 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
345 dest_x - (mask_x - mask_image->common.alpha_origin_x),
346 dest_y - (mask_y - mask_image->common.alpha_origin_y)))
348 pixman_region32_fini (region);
358 walk_region_internal (pixman_implementation_t *imp,
360 pixman_image_t * src_image,
361 pixman_image_t * mask_image,
362 pixman_image_t * dst_image,
371 pixman_bool_t src_repeat,
372 pixman_bool_t mask_repeat,
373 pixman_region32_t * region,
374 pixman_composite_func_t composite_rect)
376 int w, h, w_this, h_this;
377 int x_msk, y_msk, x_src, y_src, x_dst, y_dst;
378 int src_dy = src_y - dest_y;
379 int src_dx = src_x - dest_x;
380 int mask_dy = mask_y - dest_y;
381 int mask_dx = mask_x - dest_x;
382 const pixman_box32_t *pbox;
385 pbox = pixman_region32_rectangles (region, &n);
387 /* Fast path for non-repeating sources */
388 if (!src_repeat && !mask_repeat)
392 (*composite_rect) (imp, op,
393 src_image, mask_image, dst_image,
401 pbox->y2 - pbox->y1);
411 h = pbox->y2 - pbox->y1;
412 y_src = pbox->y1 + src_dy;
413 y_msk = pbox->y1 + mask_dy;
419 w = pbox->x2 - pbox->x1;
420 x_src = pbox->x1 + src_dx;
421 x_msk = pbox->x1 + mask_dx;
426 y_msk = MOD (y_msk, mask_image->bits.height);
427 if (h_this > mask_image->bits.height - y_msk)
428 h_this = mask_image->bits.height - y_msk;
433 y_src = MOD (y_src, src_image->bits.height);
434 if (h_this > src_image->bits.height - y_src)
435 h_this = src_image->bits.height - y_src;
444 x_msk = MOD (x_msk, mask_image->bits.width);
445 if (w_this > mask_image->bits.width - x_msk)
446 w_this = mask_image->bits.width - x_msk;
451 x_src = MOD (x_src, src_image->bits.width);
452 if (w_this > src_image->bits.width - x_src)
453 w_this = src_image->bits.width - x_src;
456 (*composite_rect) (imp, op,
457 src_image, mask_image, dst_image,
458 x_src, y_src, x_msk, y_msk, x_dst, y_dst,
477 static force_inline pixman_bool_t
478 image_covers (pixman_image_t *image,
479 pixman_box32_t *extents,
483 if (image->common.type == BITS &&
484 image->common.repeat == PIXMAN_REPEAT_NONE)
486 if (x > extents->x1 || y > extents->y1 ||
487 x + image->bits.width < extents->x2 ||
488 y + image->bits.height < extents->y2)
498 do_composite (pixman_implementation_t *imp,
501 pixman_image_t *mask,
502 pixman_image_t *dest,
512 #define N_CACHED_FAST_PATHS 8
513 static THREAD_LOCAL pixman_fast_path_t tls_cache[N_CACHED_FAST_PATHS];
514 pixman_format_code_t src_format, mask_format, dest_format;
515 uint32_t src_flags, mask_flags, dest_flags;
516 pixman_region32_t region;
517 pixman_box32_t *extents;
521 int mask_dx, mask_dy;
523 int dest_dx, dest_dy;
524 pixman_bool_t need_workaround;
525 pixman_fast_path_t *cache;
526 const pixman_fast_path_t *info;
529 src_format = src->common.extended_format_code;
530 src_flags = src->common.flags;
534 mask_format = mask->common.extended_format_code;
535 mask_flags = mask->common.flags;
539 mask_format = PIXMAN_null;
540 mask_flags = FAST_PATH_IS_OPAQUE;
543 dest_format = dest->common.extended_format_code;
544 dest_flags = dest->common.flags;
546 /* Check for pixbufs */
547 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
548 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
549 (src->common.repeat == mask->common.repeat) &&
550 (src_x == mask_x && src_y == mask_y))
552 if (src_format == PIXMAN_x8b8g8r8)
553 src_format = mask_format = PIXMAN_pixbuf;
554 else if (src_format == PIXMAN_x8r8g8b8)
555 src_format = mask_format = PIXMAN_rpixbuf;
558 /* Check for workaround */
559 need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
563 apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
564 apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
565 apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
568 pixman_region32_init (®ion);
570 if (!pixman_compute_composite_region32 (
571 ®ion, src, mask, dest,
572 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
577 extents = pixman_region32_extents (®ion);
579 if (image_covers (src, extents, dest_x - src_x, dest_y - src_y))
580 src_flags |= FAST_PATH_COVERS_CLIP;
582 if (mask && image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y))
583 mask_flags |= FAST_PATH_COVERS_CLIP;
586 * Check if we can replace our operator by a simpler one
587 * if the src or dest are opaque. The output operator should be
588 * mathematically equivalent to the source.
590 op = optimize_operator (op, src_flags, mask_flags, dest_flags);
591 if (op == PIXMAN_OP_DST)
594 /* Check cache for fast paths */
597 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
601 /* Note that we check for equality here, not whether
602 * the cached fast path matches. This is to prevent
603 * us from selecting an overly general fast path
604 * when a more specific one would work.
606 if (info->op == op &&
607 info->src_format == src_format &&
608 info->mask_format == mask_format &&
609 info->dest_format == dest_format &&
610 info->src_flags == src_flags &&
611 info->mask_flags == mask_flags &&
612 info->dest_flags == dest_flags &&
621 info = imp->fast_paths;
623 while (info->op != PIXMAN_OP_NONE)
625 if ((info->op == op || info->op == PIXMAN_OP_any) &&
627 ((info->src_format == src_format) ||
628 (info->src_format == PIXMAN_any)) &&
629 ((info->mask_format == mask_format) ||
630 (info->mask_format == PIXMAN_any)) &&
631 ((info->dest_format == dest_format) ||
632 (info->dest_format == PIXMAN_any)) &&
634 (info->src_flags & src_flags) == info->src_flags &&
635 (info->mask_flags & mask_flags) == info->mask_flags &&
636 (info->dest_flags & dest_flags) == info->dest_flags)
638 /* Set i to the last spot in the cache so that the
639 * move-to-front code below will work
641 i = N_CACHED_FAST_PATHS - 1;
652 /* We didn't find a compositing routine. This should not happen, but if
653 * it somehow does, just exit rather than crash.
658 walk_region_internal (imp, op,
660 src_x, src_y, mask_x, mask_y,
663 (src_flags & FAST_PATH_SIMPLE_REPEAT),
664 (mask_flags & FAST_PATH_SIMPLE_REPEAT),
665 ®ion, info->func);
669 /* Make a copy of info->func, because info->func may change when
670 * we update the cache.
672 pixman_composite_func_t func = info->func;
675 cache[i + 1] = cache[i];
678 cache[0].src_format = src_format;
679 cache[0].src_flags = src_flags;
680 cache[0].mask_format = mask_format;
681 cache[0].mask_flags = mask_flags;
682 cache[0].dest_format = dest_format;
683 cache[0].dest_flags = dest_flags;
684 cache[0].func = func;
690 unapply_workaround (src, src_bits, src_dx, src_dy);
691 unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
692 unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
695 pixman_region32_fini (®ion);
699 pixman_image_composite (pixman_op_t op,
700 pixman_image_t * src,
701 pixman_image_t * mask,
702 pixman_image_t * dest,
712 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
713 mask_x, mask_y, dest_x, dest_y, width, height);
717 * Work around GCC bug causing crashes in Mozilla with SSE2
719 * When using -msse, gcc generates movdqa instructions assuming that
720 * the stack is 16 byte aligned. Unfortunately some applications, such
721 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
722 * causes the movdqa instructions to fail.
724 * The __force_align_arg_pointer__ makes gcc generate a prologue that
725 * realigns the stack pointer to 16 bytes.
727 * On x86-64 this is not necessary because the standard ABI already
728 * calls for a 16 byte aligned stack.
730 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
732 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
733 __attribute__((__force_align_arg_pointer__))
736 pixman_image_composite32 (pixman_op_t op,
737 pixman_image_t * src,
738 pixman_image_t * mask,
739 pixman_image_t * dest,
749 _pixman_image_validate (src);
751 _pixman_image_validate (mask);
752 _pixman_image_validate (dest);
755 imp = _pixman_choose_implementation ();
757 do_composite (imp, op,
765 PIXMAN_EXPORT pixman_bool_t
766 pixman_blt (uint32_t *src_bits,
780 imp = _pixman_choose_implementation ();
782 return _pixman_implementation_blt (imp, src_bits, dst_bits, src_stride, dst_stride,
789 PIXMAN_EXPORT pixman_bool_t
790 pixman_fill (uint32_t *bits,
800 imp = _pixman_choose_implementation ();
802 return _pixman_implementation_fill (imp, bits, stride, bpp, x, y, width, height, xor);
806 color_to_uint32 (const pixman_color_t *color)
809 (color->alpha >> 8 << 24) |
810 (color->red >> 8 << 16) |
811 (color->green & 0xff00) |
816 color_to_pixel (pixman_color_t * color,
818 pixman_format_code_t format)
820 uint32_t c = color_to_uint32 (color);
822 if (!(format == PIXMAN_a8r8g8b8 ||
823 format == PIXMAN_x8r8g8b8 ||
824 format == PIXMAN_a8b8g8r8 ||
825 format == PIXMAN_x8b8g8r8 ||
826 format == PIXMAN_b8g8r8a8 ||
827 format == PIXMAN_b8g8r8x8 ||
828 format == PIXMAN_r5g6b5 ||
829 format == PIXMAN_b5g6r5 ||
830 format == PIXMAN_a8))
835 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
837 c = ((c & 0xff000000) >> 0) |
838 ((c & 0x00ff0000) >> 16) |
839 ((c & 0x0000ff00) >> 0) |
840 ((c & 0x000000ff) << 16);
842 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
844 c = ((c & 0xff000000) >> 24) |
845 ((c & 0x00ff0000) >> 8) |
846 ((c & 0x0000ff00) << 8) |
847 ((c & 0x000000ff) << 24);
850 if (format == PIXMAN_a8)
852 else if (format == PIXMAN_r5g6b5 ||
853 format == PIXMAN_b5g6r5)
854 c = CONVERT_8888_TO_0565 (c);
857 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
858 printf ("pixel: %x\n", c);
865 PIXMAN_EXPORT pixman_bool_t
866 pixman_image_fill_rectangles (pixman_op_t op,
867 pixman_image_t * dest,
868 pixman_color_t * color,
870 const pixman_rectangle16_t *rects)
872 pixman_box32_t stack_boxes[6];
873 pixman_box32_t *boxes;
874 pixman_bool_t result;
879 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
888 for (i = 0; i < n_rects; ++i)
890 boxes[i].x1 = rects[i].x;
891 boxes[i].y1 = rects[i].y;
892 boxes[i].x2 = boxes[i].x1 + rects[i].width;
893 boxes[i].y2 = boxes[i].y1 + rects[i].height;
896 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
898 if (boxes != stack_boxes)
904 PIXMAN_EXPORT pixman_bool_t
905 pixman_image_fill_boxes (pixman_op_t op,
906 pixman_image_t * dest,
907 pixman_color_t * color,
909 const pixman_box32_t *boxes)
911 pixman_image_t *solid;
915 _pixman_image_validate (dest);
917 if (color->alpha == 0xffff)
919 if (op == PIXMAN_OP_OVER)
923 if (op == PIXMAN_OP_CLEAR)
935 if (op == PIXMAN_OP_SRC)
939 if (color_to_pixel (color, &pixel, dest->bits.format))
941 pixman_region32_t fill_region;
943 pixman_box32_t *rects;
945 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
948 if (dest->common.have_clip_region)
950 if (!pixman_region32_intersect (&fill_region,
952 &dest->common.clip_region))
956 rects = pixman_region32_rectangles (&fill_region, &n_rects);
957 for (j = 0; j < n_rects; ++j)
959 const pixman_box32_t *rect = &(rects[j]);
960 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
961 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
965 pixman_region32_fini (&fill_region);
970 solid = pixman_image_create_solid_fill (color);
974 for (i = 0; i < n_boxes; ++i)
976 const pixman_box32_t *box = &(boxes[i]);
978 pixman_image_composite32 (op, solid, NULL, dest,
981 box->x2 - box->x1, box->y2 - box->y1);
984 pixman_image_unref (solid);
992 * Returns the version of the pixman library encoded in a single
993 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
994 * later versions compare greater than earlier versions.
996 * A run-time comparison to check that pixman's version is greater than
997 * or equal to version X.Y.Z could be performed as follows:
999 * <informalexample><programlisting>
1000 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1001 * </programlisting></informalexample>
1003 * See also pixman_version_string() as well as the compile-time
1004 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1006 * Return value: the encoded version.
1009 pixman_version (void)
1011 return PIXMAN_VERSION;
1015 * pixman_version_string:
1017 * Returns the version of the pixman library as a human-readable string
1018 * of the form "X.Y.Z".
1020 * See also pixman_version() as well as the compile-time equivalents
1021 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1023 * Return value: a string containing the version.
1025 PIXMAN_EXPORT const char*
1026 pixman_version_string (void)
1028 return PIXMAN_VERSION_STRING;
1032 * pixman_format_supported_source:
1033 * @format: A pixman_format_code_t format
1035 * Return value: whether the provided format code is a supported
1036 * format for a pixman surface used as a source in
1039 * Currently, all pixman_format_code_t values are supported.
1041 PIXMAN_EXPORT pixman_bool_t
1042 pixman_format_supported_source (pixman_format_code_t format)
1046 /* 32 bpp formats */
1047 case PIXMAN_a2b10g10r10:
1048 case PIXMAN_x2b10g10r10:
1049 case PIXMAN_a2r10g10b10:
1050 case PIXMAN_x2r10g10b10:
1051 case PIXMAN_a8r8g8b8:
1052 case PIXMAN_x8r8g8b8:
1053 case PIXMAN_a8b8g8r8:
1054 case PIXMAN_x8b8g8r8:
1055 case PIXMAN_b8g8r8a8:
1056 case PIXMAN_b8g8r8x8:
1061 /* 16 bpp formats */
1062 case PIXMAN_a1r5g5b5:
1063 case PIXMAN_x1r5g5b5:
1064 case PIXMAN_a1b5g5r5:
1065 case PIXMAN_x1b5g5r5:
1066 case PIXMAN_a4r4g4b4:
1067 case PIXMAN_x4r4g4b4:
1068 case PIXMAN_a4b4g4r4:
1069 case PIXMAN_x4b4g4r4:
1074 case PIXMAN_a2r2g2b2:
1075 case PIXMAN_a2b2g2r2:
1079 /* Collides with PIXMAN_c8
1082 /* Collides with PIXMAN_g8
1089 case PIXMAN_a1r1g1b1:
1090 case PIXMAN_a1b1g1r1:
1107 * pixman_format_supported_destination:
1108 * @format: A pixman_format_code_t format
1110 * Return value: whether the provided format code is a supported
1111 * format for a pixman surface used as a destination in
1114 * Currently, all pixman_format_code_t values are supported
1115 * except for the YUV formats.
1117 PIXMAN_EXPORT pixman_bool_t
1118 pixman_format_supported_destination (pixman_format_code_t format)
1120 /* YUV formats cannot be written to at the moment */
1121 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1124 return pixman_format_supported_source (format);
1127 PIXMAN_EXPORT pixman_bool_t
1128 pixman_compute_composite_region (pixman_region16_t * region,
1129 pixman_image_t * src_image,
1130 pixman_image_t * mask_image,
1131 pixman_image_t * dst_image,
1141 pixman_region32_t r32;
1142 pixman_bool_t retval;
1144 pixman_region32_init (&r32);
1146 retval = pixman_compute_composite_region32 (
1147 &r32, src_image, mask_image, dst_image,
1148 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1153 if (!pixman_region16_copy_from_region32 (region, &r32))
1157 pixman_region32_fini (&r32);