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;
143 #define OPAQUE_SHIFT 13
145 COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
147 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
148 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
150 is_dest_opaque >>= OPAQUE_SHIFT - 1;
151 is_source_opaque >>= OPAQUE_SHIFT;
153 return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
157 apply_workaround (pixman_image_t *image,
160 uint32_t ** save_bits,
164 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
166 /* Some X servers generate images that point to the
167 * wrong place in memory, but then set the clip region
168 * to point to the right place. Because of an old bug
169 * in pixman, this would actually work.
171 * Here we try and undo the damage
173 int bpp = PIXMAN_FORMAT_BPP (image->bits.format) / 8;
174 pixman_box32_t *extents;
178 extents = pixman_region32_extents (&(image->common.clip_region));
182 *save_bits = image->bits.bits;
186 pixman_region32_translate (&(image->common.clip_region), -dx, -dy);
188 t = (uint8_t *)image->bits.bits;
189 t += dy * image->bits.rowstride * 4 + dx * bpp;
190 image->bits.bits = (uint32_t *)t;
198 unapply_workaround (pixman_image_t *image, uint32_t *bits, int dx, int dy)
200 if (image && (image->common.flags & FAST_PATH_NEEDS_WORKAROUND))
202 image->bits.bits = bits;
203 pixman_region32_translate (&image->common.clip_region, dx, dy);
208 * Computing composite region
210 static inline pixman_bool_t
211 clip_general_image (pixman_region32_t * region,
212 pixman_region32_t * clip,
216 if (pixman_region32_n_rects (region) == 1 &&
217 pixman_region32_n_rects (clip) == 1)
219 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL);
220 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL);
223 if (rbox->x1 < (v = cbox->x1 + dx))
225 if (rbox->x2 > (v = cbox->x2 + dx))
227 if (rbox->y1 < (v = cbox->y1 + dy))
229 if (rbox->y2 > (v = cbox->y2 + dy))
231 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
233 pixman_region32_init (region);
237 else if (!pixman_region32_not_empty (clip))
244 pixman_region32_translate (region, -dx, -dy);
246 if (!pixman_region32_intersect (region, region, clip))
250 pixman_region32_translate (region, dx, dy);
253 return pixman_region32_not_empty (region);
256 static inline pixman_bool_t
257 clip_source_image (pixman_region32_t * region,
258 pixman_image_t * image,
262 /* Source clips are ignored, unless they are explicitly turned on
263 * and the clip in question was set by an X client. (Because if
264 * the clip was not set by a client, then it is a hierarchy
265 * clip and those should always be ignored for sources).
267 if (!image->common.clip_sources || !image->common.client_clip)
270 return clip_general_image (region,
271 &image->common.clip_region,
276 * returns FALSE if the final region is empty. Indistinguishable from
277 * an allocation failure, but rendering ignores those anyways.
280 pixman_compute_composite_region32 (pixman_region32_t * region,
281 pixman_image_t * src_image,
282 pixman_image_t * mask_image,
283 pixman_image_t * dst_image,
293 region->extents.x1 = dest_x;
294 region->extents.x2 = dest_x + width;
295 region->extents.y1 = dest_y;
296 region->extents.y2 = dest_y + height;
298 region->extents.x1 = MAX (region->extents.x1, 0);
299 region->extents.y1 = MAX (region->extents.y1, 0);
300 region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width);
301 region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height);
305 /* Check for empty operation */
306 if (region->extents.x1 >= region->extents.x2 ||
307 region->extents.y1 >= region->extents.y2)
309 region->extents.x1 = 0;
310 region->extents.x2 = 0;
311 region->extents.y1 = 0;
312 region->extents.y2 = 0;
316 if (dst_image->common.have_clip_region)
318 if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0))
322 if (dst_image->common.alpha_map)
324 if (!pixman_region32_intersect_rect (region, region,
325 dst_image->common.alpha_origin_x,
326 dst_image->common.alpha_origin_y,
327 dst_image->common.alpha_map->width,
328 dst_image->common.alpha_map->height))
332 if (!pixman_region32_not_empty (region))
334 if (dst_image->common.alpha_map->common.have_clip_region)
336 if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region,
337 -dst_image->common.alpha_origin_x,
338 -dst_image->common.alpha_origin_y))
345 /* clip against src */
346 if (src_image->common.have_clip_region)
348 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
351 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
353 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
354 dest_x - (src_x - src_image->common.alpha_origin_x),
355 dest_y - (src_y - src_image->common.alpha_origin_y)))
360 /* clip against mask */
361 if (mask_image && mask_image->common.have_clip_region)
363 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
366 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
368 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
369 dest_x - (mask_x - mask_image->common.alpha_origin_x),
370 dest_y - (mask_y - mask_image->common.alpha_origin_y)))
380 #define N_CACHED_FAST_PATHS 8
386 pixman_implementation_t * imp;
387 pixman_fast_path_t fast_path;
388 } cache [N_CACHED_FAST_PATHS];
391 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
393 static force_inline pixman_bool_t
394 lookup_composite_function (pixman_op_t op,
395 pixman_format_code_t src_format,
397 pixman_format_code_t mask_format,
399 pixman_format_code_t dest_format,
401 pixman_implementation_t **out_imp,
402 pixman_composite_func_t *out_func)
404 pixman_implementation_t *imp;
408 /* Check cache for fast paths */
409 cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
411 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
413 const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
415 /* Note that we check for equality here, not whether
416 * the cached fast path matches. This is to prevent
417 * us from selecting an overly general fast path
418 * when a more specific one would work.
420 if (info->op == op &&
421 info->src_format == src_format &&
422 info->mask_format == mask_format &&
423 info->dest_format == dest_format &&
424 info->src_flags == src_flags &&
425 info->mask_flags == mask_flags &&
426 info->dest_flags == dest_flags &&
429 *out_imp = cache->cache[i].imp;
430 *out_func = cache->cache[i].fast_path.func;
436 for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
438 const pixman_fast_path_t *info = imp->fast_paths;
440 while (info->op != PIXMAN_OP_NONE)
442 if ((info->op == op || info->op == PIXMAN_OP_any) &&
444 ((info->src_format == src_format) ||
445 (info->src_format == PIXMAN_any)) &&
446 ((info->mask_format == mask_format) ||
447 (info->mask_format == PIXMAN_any)) &&
448 ((info->dest_format == dest_format) ||
449 (info->dest_format == PIXMAN_any)) &&
451 (info->src_flags & src_flags) == info->src_flags &&
452 (info->mask_flags & mask_flags) == info->mask_flags &&
453 (info->dest_flags & dest_flags) == info->dest_flags)
456 *out_func = info->func;
458 /* Set i to the last spot in the cache so that the
459 * move-to-front code below will work
461 i = N_CACHED_FAST_PATHS - 1;
475 cache->cache[i + 1] = cache->cache[i];
477 cache->cache[0].imp = *out_imp;
478 cache->cache[0].fast_path.op = op;
479 cache->cache[0].fast_path.src_format = src_format;
480 cache->cache[0].fast_path.src_flags = src_flags;
481 cache->cache[0].fast_path.mask_format = mask_format;
482 cache->cache[0].fast_path.mask_flags = mask_flags;
483 cache->cache[0].fast_path.dest_format = dest_format;
484 cache->cache[0].fast_path.dest_flags = dest_flags;
485 cache->cache[0].fast_path.func = *out_func;
492 compute_sample_extents (pixman_transform_t *transform,
493 pixman_box32_t *extents, int x, int y,
494 pixman_fixed_t x_off, pixman_fixed_t y_off,
495 pixman_fixed_t width, pixman_fixed_t height)
497 pixman_fixed_t x1, y1, x2, y2;
498 pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
500 /* We have checked earlier that (extents->x1 - x) etc. fit in a pixman_fixed_t */
501 x1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x1 - x) + pixman_fixed_1 / 2;
502 y1 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y1 - y) + pixman_fixed_1 / 2;
503 x2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->x2 - x) - pixman_fixed_1 / 2;
504 y2 = (pixman_fixed_48_16_t)pixman_int_to_fixed (extents->y2 - y) - pixman_fixed_1 / 2;
508 tx1 = (pixman_fixed_48_16_t)x1;
509 ty1 = (pixman_fixed_48_16_t)y1;
510 tx2 = (pixman_fixed_48_16_t)x2;
511 ty2 = (pixman_fixed_48_16_t)y2;
518 tx1 = ty1 = tx2 = ty2 = 0;
520 for (i = 0; i < 4; ++i)
522 pixman_fixed_48_16_t tx, ty;
525 v.vector[0] = (i & 0x01)? x1 : x2;
526 v.vector[1] = (i & 0x02)? y1 : y2;
527 v.vector[2] = pixman_fixed_1;
529 if (!pixman_transform_point (transform, &v))
532 tx = (pixman_fixed_48_16_t)v.vector[0];
533 ty = (pixman_fixed_48_16_t)v.vector[1];
556 /* Expand the source area by a tiny bit so account of different rounding that
557 * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
558 * 0.5 so this won't cause the area computed to be overly pessimistic.
560 tx1 += x_off - 8 * pixman_fixed_e;
561 ty1 += y_off - 8 * pixman_fixed_e;
562 tx2 += x_off + width + 8 * pixman_fixed_e;
563 ty2 += y_off + height + 8 * pixman_fixed_e;
565 if (tx1 < pixman_min_fixed_48_16 || tx1 > pixman_max_fixed_48_16 ||
566 ty1 < pixman_min_fixed_48_16 || ty1 > pixman_max_fixed_48_16 ||
567 tx2 < pixman_min_fixed_48_16 || tx2 > pixman_max_fixed_48_16 ||
568 ty2 < pixman_min_fixed_48_16 || ty2 > pixman_max_fixed_48_16)
574 extents->x1 = pixman_fixed_to_int (tx1);
575 extents->y1 = pixman_fixed_to_int (ty1);
576 extents->x2 = pixman_fixed_to_int (tx2) + 1;
577 extents->y2 = pixman_fixed_to_int (ty2) + 1;
583 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
586 analyze_extent (pixman_image_t *image, int x, int y,
587 const pixman_box32_t *extents, uint32_t *flags)
589 pixman_transform_t *transform;
590 pixman_fixed_t *params;
591 pixman_fixed_t x_off, y_off;
592 pixman_fixed_t width, height;
598 /* Some compositing functions walk one step
599 * outside the destination rectangle, so we
600 * check here that the expanded-by-one source
601 * extents in destination space fits in 16 bits
603 if (!IS_16BIT (extents->x1 - x - 1) ||
604 !IS_16BIT (extents->y1 - y - 1) ||
605 !IS_16BIT (extents->x2 - x + 1) ||
606 !IS_16BIT (extents->y2 - y + 1))
611 transform = image->common.transform;
612 if (image->common.type == BITS)
614 /* During repeat mode calculations we might convert the
615 * width/height of an image to fixed 16.16, so we need
616 * them to be smaller than 16 bits.
618 if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
621 #define ID_AND_NEAREST (FAST_PATH_ID_TRANSFORM | FAST_PATH_NEAREST_FILTER)
623 if ((image->common.flags & ID_AND_NEAREST) == ID_AND_NEAREST &&
624 extents->x1 - x >= 0 &&
625 extents->y1 - y >= 0 &&
626 extents->x2 - x <= image->bits.width &&
627 extents->y2 - y <= image->bits.height)
629 *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
633 switch (image->common.filter)
635 case PIXMAN_FILTER_CONVOLUTION:
636 params = image->common.filter_params;
637 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
638 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
643 case PIXMAN_FILTER_GOOD:
644 case PIXMAN_FILTER_BEST:
645 case PIXMAN_FILTER_BILINEAR:
646 x_off = - pixman_fixed_1 / 2;
647 y_off = - pixman_fixed_1 / 2;
648 width = pixman_fixed_1;
649 height = pixman_fixed_1;
652 case PIXMAN_FILTER_FAST:
653 case PIXMAN_FILTER_NEAREST:
654 x_off = - pixman_fixed_e;
655 y_off = - pixman_fixed_e;
664 /* Check whether the non-expanded, transformed extent is entirely within
665 * the source image, and set the FAST_PATH_SAMPLES_COVER_CLIP if it is.
668 if (compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height) &&
669 ex.x1 >= 0 && ex.y1 >= 0 &&
670 ex.x2 <= image->bits.width && ex.y2 <= image->bits.height)
672 *flags |= FAST_PATH_SAMPLES_COVER_CLIP;
683 /* Check that the extents expanded by one don't overflow. This ensures that
684 * compositing functions can simply walk the source space using 16.16
685 * variables without worrying about overflow.
687 ex.x1 = extents->x1 - 1;
688 ex.y1 = extents->y1 - 1;
689 ex.x2 = extents->x2 + 1;
690 ex.y2 = extents->y2 + 1;
692 if (!compute_sample_extents (transform, &ex, x, y, x_off, y_off, width, height))
699 * Work around GCC bug causing crashes in Mozilla with SSE2
701 * When using -msse, gcc generates movdqa instructions assuming that
702 * the stack is 16 byte aligned. Unfortunately some applications, such
703 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
704 * causes the movdqa instructions to fail.
706 * The __force_align_arg_pointer__ makes gcc generate a prologue that
707 * realigns the stack pointer to 16 bytes.
709 * On x86-64 this is not necessary because the standard ABI already
710 * calls for a 16 byte aligned stack.
712 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
714 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
715 __attribute__((__force_align_arg_pointer__))
718 pixman_image_composite32 (pixman_op_t op,
719 pixman_image_t * src,
720 pixman_image_t * mask,
721 pixman_image_t * dest,
731 pixman_format_code_t src_format, mask_format, dest_format;
732 uint32_t src_flags, mask_flags, dest_flags;
733 pixman_region32_t region;
734 pixman_box32_t *extents;
738 int mask_dx, mask_dy;
740 int dest_dx, dest_dy;
741 pixman_bool_t need_workaround;
742 pixman_implementation_t *imp;
743 pixman_composite_func_t func;
745 _pixman_image_validate (src);
747 _pixman_image_validate (mask);
748 _pixman_image_validate (dest);
750 src_format = src->common.extended_format_code;
751 src_flags = src->common.flags;
755 mask_format = mask->common.extended_format_code;
756 mask_flags = mask->common.flags;
760 mask_format = PIXMAN_null;
761 mask_flags = FAST_PATH_IS_OPAQUE;
764 dest_format = dest->common.extended_format_code;
765 dest_flags = dest->common.flags;
767 /* Check for pixbufs */
768 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
769 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
770 (src->common.repeat == mask->common.repeat) &&
771 (src_x == mask_x && src_y == mask_y))
773 if (src_format == PIXMAN_x8b8g8r8)
774 src_format = mask_format = PIXMAN_pixbuf;
775 else if (src_format == PIXMAN_x8r8g8b8)
776 src_format = mask_format = PIXMAN_rpixbuf;
779 /* Check for workaround */
780 need_workaround = (src_flags | mask_flags | dest_flags) & FAST_PATH_NEEDS_WORKAROUND;
784 apply_workaround (src, &src_x, &src_y, &src_bits, &src_dx, &src_dy);
785 apply_workaround (mask, &mask_x, &mask_y, &mask_bits, &mask_dx, &mask_dy);
786 apply_workaround (dest, &dest_x, &dest_y, &dest_bits, &dest_dx, &dest_dy);
789 pixman_region32_init (®ion);
791 if (!pixman_compute_composite_region32 (
792 ®ion, src, mask, dest,
793 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
798 extents = pixman_region32_extents (®ion);
800 if (!analyze_extent (src, dest_x - src_x, dest_y - src_y, extents, &src_flags))
803 if (!analyze_extent (mask, dest_x - mask_x, dest_y - mask_y, extents, &mask_flags))
806 /* If the clip is within the source samples, and the samples are opaque,
807 * then the source is effectively opaque.
809 #define BOTH (FAST_PATH_SAMPLES_OPAQUE | FAST_PATH_SAMPLES_COVER_CLIP)
811 if ((src_flags & BOTH) == BOTH)
812 src_flags |= FAST_PATH_IS_OPAQUE;
814 if ((mask_flags & BOTH) == BOTH)
815 mask_flags |= FAST_PATH_IS_OPAQUE;
818 * Check if we can replace our operator by a simpler one
819 * if the src or dest are opaque. The output operator should be
820 * mathematically equivalent to the source.
822 op = optimize_operator (op, src_flags, mask_flags, dest_flags);
823 if (op == PIXMAN_OP_DST)
826 if (lookup_composite_function (op,
827 src_format, src_flags,
828 mask_format, mask_flags,
829 dest_format, dest_flags,
832 const pixman_box32_t *pbox;
835 pbox = pixman_region32_rectangles (®ion, &n);
841 pbox->x1 + src_x - dest_x,
842 pbox->y1 + src_y - dest_y,
843 pbox->x1 + mask_x - dest_x,
844 pbox->y1 + mask_y - dest_y,
848 pbox->y2 - pbox->y1);
857 unapply_workaround (src, src_bits, src_dx, src_dy);
858 unapply_workaround (mask, mask_bits, mask_dx, mask_dy);
859 unapply_workaround (dest, dest_bits, dest_dx, dest_dy);
862 pixman_region32_fini (®ion);
866 pixman_image_composite (pixman_op_t op,
867 pixman_image_t * src,
868 pixman_image_t * mask,
869 pixman_image_t * dest,
879 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
880 mask_x, mask_y, dest_x, dest_y, width, height);
883 PIXMAN_EXPORT pixman_bool_t
884 pixman_blt (uint32_t *src_bits,
897 return _pixman_implementation_blt (get_implementation(),
898 src_bits, dst_bits, src_stride, dst_stride,
905 PIXMAN_EXPORT pixman_bool_t
906 pixman_fill (uint32_t *bits,
915 return _pixman_implementation_fill (
916 get_implementation(), bits, stride, bpp, x, y, width, height, xor);
920 color_to_uint32 (const pixman_color_t *color)
923 (color->alpha >> 8 << 24) |
924 (color->red >> 8 << 16) |
925 (color->green & 0xff00) |
930 color_to_pixel (pixman_color_t * color,
932 pixman_format_code_t format)
934 uint32_t c = color_to_uint32 (color);
936 if (!(format == PIXMAN_a8r8g8b8 ||
937 format == PIXMAN_x8r8g8b8 ||
938 format == PIXMAN_a8b8g8r8 ||
939 format == PIXMAN_x8b8g8r8 ||
940 format == PIXMAN_b8g8r8a8 ||
941 format == PIXMAN_b8g8r8x8 ||
942 format == PIXMAN_r5g6b5 ||
943 format == PIXMAN_b5g6r5 ||
944 format == PIXMAN_a8))
949 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
951 c = ((c & 0xff000000) >> 0) |
952 ((c & 0x00ff0000) >> 16) |
953 ((c & 0x0000ff00) >> 0) |
954 ((c & 0x000000ff) << 16);
956 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
958 c = ((c & 0xff000000) >> 24) |
959 ((c & 0x00ff0000) >> 8) |
960 ((c & 0x0000ff00) << 8) |
961 ((c & 0x000000ff) << 24);
964 if (format == PIXMAN_a8)
966 else if (format == PIXMAN_r5g6b5 ||
967 format == PIXMAN_b5g6r5)
968 c = CONVERT_8888_TO_0565 (c);
971 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
972 printf ("pixel: %x\n", c);
979 PIXMAN_EXPORT pixman_bool_t
980 pixman_image_fill_rectangles (pixman_op_t op,
981 pixman_image_t * dest,
982 pixman_color_t * color,
984 const pixman_rectangle16_t *rects)
986 pixman_box32_t stack_boxes[6];
987 pixman_box32_t *boxes;
988 pixman_bool_t result;
993 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
1002 for (i = 0; i < n_rects; ++i)
1004 boxes[i].x1 = rects[i].x;
1005 boxes[i].y1 = rects[i].y;
1006 boxes[i].x2 = boxes[i].x1 + rects[i].width;
1007 boxes[i].y2 = boxes[i].y1 + rects[i].height;
1010 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
1012 if (boxes != stack_boxes)
1018 PIXMAN_EXPORT pixman_bool_t
1019 pixman_image_fill_boxes (pixman_op_t op,
1020 pixman_image_t * dest,
1021 pixman_color_t * color,
1023 const pixman_box32_t *boxes)
1025 pixman_image_t *solid;
1029 _pixman_image_validate (dest);
1031 if (color->alpha == 0xffff)
1033 if (op == PIXMAN_OP_OVER)
1037 if (op == PIXMAN_OP_CLEAR)
1049 if (op == PIXMAN_OP_SRC)
1053 if (color_to_pixel (color, &pixel, dest->bits.format))
1055 pixman_region32_t fill_region;
1057 pixman_box32_t *rects;
1059 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
1062 if (dest->common.have_clip_region)
1064 if (!pixman_region32_intersect (&fill_region,
1066 &dest->common.clip_region))
1070 rects = pixman_region32_rectangles (&fill_region, &n_rects);
1071 for (j = 0; j < n_rects; ++j)
1073 const pixman_box32_t *rect = &(rects[j]);
1074 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
1075 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
1079 pixman_region32_fini (&fill_region);
1084 solid = pixman_image_create_solid_fill (color);
1088 for (i = 0; i < n_boxes; ++i)
1090 const pixman_box32_t *box = &(boxes[i]);
1092 pixman_image_composite32 (op, solid, NULL, dest,
1095 box->x2 - box->x1, box->y2 - box->y1);
1098 pixman_image_unref (solid);
1106 * Returns the version of the pixman library encoded in a single
1107 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1108 * later versions compare greater than earlier versions.
1110 * A run-time comparison to check that pixman's version is greater than
1111 * or equal to version X.Y.Z could be performed as follows:
1113 * <informalexample><programlisting>
1114 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1115 * </programlisting></informalexample>
1117 * See also pixman_version_string() as well as the compile-time
1118 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1120 * Return value: the encoded version.
1123 pixman_version (void)
1125 return PIXMAN_VERSION;
1129 * pixman_version_string:
1131 * Returns the version of the pixman library as a human-readable string
1132 * of the form "X.Y.Z".
1134 * See also pixman_version() as well as the compile-time equivalents
1135 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1137 * Return value: a string containing the version.
1139 PIXMAN_EXPORT const char*
1140 pixman_version_string (void)
1142 return PIXMAN_VERSION_STRING;
1146 * pixman_format_supported_source:
1147 * @format: A pixman_format_code_t format
1149 * Return value: whether the provided format code is a supported
1150 * format for a pixman surface used as a source in
1153 * Currently, all pixman_format_code_t values are supported.
1155 PIXMAN_EXPORT pixman_bool_t
1156 pixman_format_supported_source (pixman_format_code_t format)
1160 /* 32 bpp formats */
1161 case PIXMAN_a2b10g10r10:
1162 case PIXMAN_x2b10g10r10:
1163 case PIXMAN_a2r10g10b10:
1164 case PIXMAN_x2r10g10b10:
1165 case PIXMAN_a8r8g8b8:
1166 case PIXMAN_x8r8g8b8:
1167 case PIXMAN_a8b8g8r8:
1168 case PIXMAN_x8b8g8r8:
1169 case PIXMAN_b8g8r8a8:
1170 case PIXMAN_b8g8r8x8:
1175 case PIXMAN_x14r6g6b6:
1176 /* 16 bpp formats */
1177 case PIXMAN_a1r5g5b5:
1178 case PIXMAN_x1r5g5b5:
1179 case PIXMAN_a1b5g5r5:
1180 case PIXMAN_x1b5g5r5:
1181 case PIXMAN_a4r4g4b4:
1182 case PIXMAN_x4r4g4b4:
1183 case PIXMAN_a4b4g4r4:
1184 case PIXMAN_x4b4g4r4:
1189 case PIXMAN_a2r2g2b2:
1190 case PIXMAN_a2b2g2r2:
1194 /* Collides with PIXMAN_c8
1197 /* Collides with PIXMAN_g8
1204 case PIXMAN_a1r1g1b1:
1205 case PIXMAN_a1b1g1r1:
1222 * pixman_format_supported_destination:
1223 * @format: A pixman_format_code_t format
1225 * Return value: whether the provided format code is a supported
1226 * format for a pixman surface used as a destination in
1229 * Currently, all pixman_format_code_t values are supported
1230 * except for the YUV formats.
1232 PIXMAN_EXPORT pixman_bool_t
1233 pixman_format_supported_destination (pixman_format_code_t format)
1235 /* YUV formats cannot be written to at the moment */
1236 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1239 return pixman_format_supported_source (format);
1242 PIXMAN_EXPORT pixman_bool_t
1243 pixman_compute_composite_region (pixman_region16_t * region,
1244 pixman_image_t * src_image,
1245 pixman_image_t * mask_image,
1246 pixman_image_t * dst_image,
1256 pixman_region32_t r32;
1257 pixman_bool_t retval;
1259 pixman_region32_init (&r32);
1261 retval = pixman_compute_composite_region32 (
1262 &r32, src_image, mask_image, dst_image,
1263 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1268 if (!pixman_region16_copy_from_region32 (region, &r32))
1272 pixman_region32_fini (&r32);