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 *global_implementation;
35 #ifdef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
36 static void __attribute__((constructor))
37 pixman_constructor (void)
39 global_implementation = _pixman_choose_implementation ();
43 static force_inline pixman_implementation_t *
44 get_implementation (void)
46 #ifndef TOOLCHAIN_SUPPORTS_ATTRIBUTE_CONSTRUCTOR
47 if (!global_implementation)
48 global_implementation = _pixman_choose_implementation ();
50 return global_implementation;
53 typedef struct operator_info_t operator_info_t;
55 struct operator_info_t
57 uint8_t opaque_info[4];
60 #define PACK(neither, src, dest, both) \
61 {{ (uint8_t)PIXMAN_OP_ ## neither, \
62 (uint8_t)PIXMAN_OP_ ## src, \
63 (uint8_t)PIXMAN_OP_ ## dest, \
64 (uint8_t)PIXMAN_OP_ ## both }}
66 static const operator_info_t operator_table[] =
68 /* Neither Opaque Src Opaque Dst Opaque Both Opaque */
69 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
70 PACK (SRC, SRC, SRC, SRC),
71 PACK (DST, DST, DST, DST),
72 PACK (OVER, SRC, OVER, SRC),
73 PACK (OVER_REVERSE, OVER_REVERSE, DST, DST),
74 PACK (IN, IN, SRC, SRC),
75 PACK (IN_REVERSE, DST, IN_REVERSE, DST),
76 PACK (OUT, OUT, CLEAR, CLEAR),
77 PACK (OUT_REVERSE, CLEAR, OUT_REVERSE, CLEAR),
78 PACK (ATOP, IN, OVER, SRC),
79 PACK (ATOP_REVERSE, OVER_REVERSE, IN_REVERSE, DST),
80 PACK (XOR, OUT, OUT_REVERSE, CLEAR),
81 PACK (ADD, ADD, ADD, ADD),
82 PACK (SATURATE, OVER_REVERSE, DST, DST),
87 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
88 PACK (SRC, SRC, SRC, SRC),
89 PACK (DST, DST, DST, DST),
90 PACK (DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER, DISJOINT_OVER),
91 PACK (DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE, DISJOINT_OVER_REVERSE),
92 PACK (DISJOINT_IN, DISJOINT_IN, DISJOINT_IN, DISJOINT_IN),
93 PACK (DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE, DISJOINT_IN_REVERSE),
94 PACK (DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT, DISJOINT_OUT),
95 PACK (DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE, DISJOINT_OUT_REVERSE),
96 PACK (DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP, DISJOINT_ATOP),
97 PACK (DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE, DISJOINT_ATOP_REVERSE),
98 PACK (DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR, DISJOINT_XOR),
105 PACK (CLEAR, CLEAR, CLEAR, CLEAR),
106 PACK (SRC, SRC, SRC, SRC),
107 PACK (DST, DST, DST, DST),
108 PACK (CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER, CONJOINT_OVER),
109 PACK (CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE, CONJOINT_OVER_REVERSE),
110 PACK (CONJOINT_IN, CONJOINT_IN, CONJOINT_IN, CONJOINT_IN),
111 PACK (CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE, CONJOINT_IN_REVERSE),
112 PACK (CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT, CONJOINT_OUT),
113 PACK (CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE, CONJOINT_OUT_REVERSE),
114 PACK (CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP, CONJOINT_ATOP),
115 PACK (CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE, CONJOINT_ATOP_REVERSE),
116 PACK (CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR, CONJOINT_XOR),
123 PACK (MULTIPLY, MULTIPLY, MULTIPLY, MULTIPLY),
124 PACK (SCREEN, SCREEN, SCREEN, SCREEN),
125 PACK (OVERLAY, OVERLAY, OVERLAY, OVERLAY),
126 PACK (DARKEN, DARKEN, DARKEN, DARKEN),
127 PACK (LIGHTEN, LIGHTEN, LIGHTEN, LIGHTEN),
128 PACK (COLOR_DODGE, COLOR_DODGE, COLOR_DODGE, COLOR_DODGE),
129 PACK (COLOR_BURN, COLOR_BURN, COLOR_BURN, COLOR_BURN),
130 PACK (HARD_LIGHT, HARD_LIGHT, HARD_LIGHT, HARD_LIGHT),
131 PACK (SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT, SOFT_LIGHT),
132 PACK (DIFFERENCE, DIFFERENCE, DIFFERENCE, DIFFERENCE),
133 PACK (EXCLUSION, EXCLUSION, EXCLUSION, EXCLUSION),
134 PACK (HSL_HUE, HSL_HUE, HSL_HUE, HSL_HUE),
135 PACK (HSL_SATURATION, HSL_SATURATION, HSL_SATURATION, HSL_SATURATION),
136 PACK (HSL_COLOR, HSL_COLOR, HSL_COLOR, HSL_COLOR),
137 PACK (HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY, HSL_LUMINOSITY),
141 * Optimize the current operator based on opacity of source or destination
142 * The output operator should be mathematically equivalent to the source.
145 optimize_operator (pixman_op_t op,
150 pixman_bool_t is_source_opaque, is_dest_opaque;
152 #define OPAQUE_SHIFT 13
154 COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE == (1 << OPAQUE_SHIFT));
156 is_dest_opaque = (dst_flags & FAST_PATH_IS_OPAQUE);
157 is_source_opaque = ((src_flags & mask_flags) & FAST_PATH_IS_OPAQUE);
159 is_dest_opaque >>= OPAQUE_SHIFT - 1;
160 is_source_opaque >>= OPAQUE_SHIFT;
162 return operator_table[op].opaque_info[is_dest_opaque | is_source_opaque];
166 * Computing composite region
168 static inline pixman_bool_t
169 clip_general_image (pixman_region32_t * region,
170 pixman_region32_t * clip,
174 if (pixman_region32_n_rects (region) == 1 &&
175 pixman_region32_n_rects (clip) == 1)
177 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL);
178 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL);
181 if (rbox->x1 < (v = cbox->x1 + dx))
183 if (rbox->x2 > (v = cbox->x2 + dx))
185 if (rbox->y1 < (v = cbox->y1 + dy))
187 if (rbox->y2 > (v = cbox->y2 + dy))
189 if (rbox->x1 >= rbox->x2 || rbox->y1 >= rbox->y2)
191 pixman_region32_init (region);
195 else if (!pixman_region32_not_empty (clip))
202 pixman_region32_translate (region, -dx, -dy);
204 if (!pixman_region32_intersect (region, region, clip))
208 pixman_region32_translate (region, dx, dy);
211 return pixman_region32_not_empty (region);
214 static inline pixman_bool_t
215 clip_source_image (pixman_region32_t * region,
216 pixman_image_t * image,
220 /* Source clips are ignored, unless they are explicitly turned on
221 * and the clip in question was set by an X client. (Because if
222 * the clip was not set by a client, then it is a hierarchy
223 * clip and those should always be ignored for sources).
225 if (!image->common.clip_sources || !image->common.client_clip)
228 return clip_general_image (region,
229 &image->common.clip_region,
234 * returns FALSE if the final region is empty. Indistinguishable from
235 * an allocation failure, but rendering ignores those anyways.
238 pixman_compute_composite_region32 (pixman_region32_t * region,
239 pixman_image_t * src_image,
240 pixman_image_t * mask_image,
241 pixman_image_t * dest_image,
251 region->extents.x1 = dest_x;
252 region->extents.x2 = dest_x + width;
253 region->extents.y1 = dest_y;
254 region->extents.y2 = dest_y + height;
256 region->extents.x1 = MAX (region->extents.x1, 0);
257 region->extents.y1 = MAX (region->extents.y1, 0);
258 region->extents.x2 = MIN (region->extents.x2, dest_image->bits.width);
259 region->extents.y2 = MIN (region->extents.y2, dest_image->bits.height);
263 /* Check for empty operation */
264 if (region->extents.x1 >= region->extents.x2 ||
265 region->extents.y1 >= region->extents.y2)
267 region->extents.x1 = 0;
268 region->extents.x2 = 0;
269 region->extents.y1 = 0;
270 region->extents.y2 = 0;
274 if (dest_image->common.have_clip_region)
276 if (!clip_general_image (region, &dest_image->common.clip_region, 0, 0))
280 if (dest_image->common.alpha_map)
282 if (!pixman_region32_intersect_rect (region, region,
283 dest_image->common.alpha_origin_x,
284 dest_image->common.alpha_origin_y,
285 dest_image->common.alpha_map->width,
286 dest_image->common.alpha_map->height))
290 if (!pixman_region32_not_empty (region))
292 if (dest_image->common.alpha_map->common.have_clip_region)
294 if (!clip_general_image (region, &dest_image->common.alpha_map->common.clip_region,
295 -dest_image->common.alpha_origin_x,
296 -dest_image->common.alpha_origin_y))
303 /* clip against src */
304 if (src_image->common.have_clip_region)
306 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y))
309 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region)
311 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map,
312 dest_x - (src_x - src_image->common.alpha_origin_x),
313 dest_y - (src_y - src_image->common.alpha_origin_y)))
318 /* clip against mask */
319 if (mask_image && mask_image->common.have_clip_region)
321 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y))
324 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region)
326 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map,
327 dest_x - (mask_x - mask_image->common.alpha_origin_x),
328 dest_y - (mask_y - mask_image->common.alpha_origin_y)))
338 #define N_CACHED_FAST_PATHS 8
344 pixman_implementation_t * imp;
345 pixman_fast_path_t fast_path;
346 } cache [N_CACHED_FAST_PATHS];
349 PIXMAN_DEFINE_THREAD_LOCAL (cache_t, fast_path_cache);
351 static force_inline pixman_bool_t
352 lookup_composite_function (pixman_op_t op,
353 pixman_format_code_t src_format,
355 pixman_format_code_t mask_format,
357 pixman_format_code_t dest_format,
359 pixman_implementation_t **out_imp,
360 pixman_composite_func_t *out_func)
362 pixman_implementation_t *imp;
366 /* Check cache for fast paths */
367 cache = PIXMAN_GET_THREAD_LOCAL (fast_path_cache);
369 for (i = 0; i < N_CACHED_FAST_PATHS; ++i)
371 const pixman_fast_path_t *info = &(cache->cache[i].fast_path);
373 /* Note that we check for equality here, not whether
374 * the cached fast path matches. This is to prevent
375 * us from selecting an overly general fast path
376 * when a more specific one would work.
378 if (info->op == op &&
379 info->src_format == src_format &&
380 info->mask_format == mask_format &&
381 info->dest_format == dest_format &&
382 info->src_flags == src_flags &&
383 info->mask_flags == mask_flags &&
384 info->dest_flags == dest_flags &&
387 *out_imp = cache->cache[i].imp;
388 *out_func = cache->cache[i].fast_path.func;
394 for (imp = get_implementation (); imp != NULL; imp = imp->delegate)
396 const pixman_fast_path_t *info = imp->fast_paths;
398 while (info->op != PIXMAN_OP_NONE)
400 if ((info->op == op || info->op == PIXMAN_OP_any) &&
402 ((info->src_format == src_format) ||
403 (info->src_format == PIXMAN_any)) &&
404 ((info->mask_format == mask_format) ||
405 (info->mask_format == PIXMAN_any)) &&
406 ((info->dest_format == dest_format) ||
407 (info->dest_format == PIXMAN_any)) &&
409 (info->src_flags & src_flags) == info->src_flags &&
410 (info->mask_flags & mask_flags) == info->mask_flags &&
411 (info->dest_flags & dest_flags) == info->dest_flags)
414 *out_func = info->func;
416 /* Set i to the last spot in the cache so that the
417 * move-to-front code below will work
419 i = N_CACHED_FAST_PATHS - 1;
433 cache->cache[i + 1] = cache->cache[i];
435 cache->cache[0].imp = *out_imp;
436 cache->cache[0].fast_path.op = op;
437 cache->cache[0].fast_path.src_format = src_format;
438 cache->cache[0].fast_path.src_flags = src_flags;
439 cache->cache[0].fast_path.mask_format = mask_format;
440 cache->cache[0].fast_path.mask_flags = mask_flags;
441 cache->cache[0].fast_path.dest_format = dest_format;
442 cache->cache[0].fast_path.dest_flags = dest_flags;
443 cache->cache[0].fast_path.func = *out_func;
451 pixman_fixed_48_16_t x1;
452 pixman_fixed_48_16_t y1;
453 pixman_fixed_48_16_t x2;
454 pixman_fixed_48_16_t y2;
458 compute_transformed_extents (pixman_transform_t *transform,
459 const pixman_box32_t *extents,
460 box_48_16_t *transformed)
462 pixman_fixed_48_16_t tx1, ty1, tx2, ty2;
463 pixman_fixed_t x1, y1, x2, y2;
466 x1 = pixman_int_to_fixed (extents->x1) + pixman_fixed_1 / 2;
467 y1 = pixman_int_to_fixed (extents->y1) + pixman_fixed_1 / 2;
468 x2 = pixman_int_to_fixed (extents->x2) - pixman_fixed_1 / 2;
469 y2 = pixman_int_to_fixed (extents->y2) - pixman_fixed_1 / 2;
473 transformed->x1 = x1;
474 transformed->y1 = y1;
475 transformed->x2 = x2;
476 transformed->y2 = y2;
481 tx1 = ty1 = INT64_MAX;
482 tx2 = ty2 = INT64_MIN;
484 for (i = 0; i < 4; ++i)
486 pixman_fixed_48_16_t tx, ty;
489 v.vector[0] = (i & 0x01)? x1 : x2;
490 v.vector[1] = (i & 0x02)? y1 : y2;
491 v.vector[2] = pixman_fixed_1;
493 if (!pixman_transform_point (transform, &v))
496 tx = (pixman_fixed_48_16_t)v.vector[0];
497 ty = (pixman_fixed_48_16_t)v.vector[1];
509 transformed->x1 = tx1;
510 transformed->y1 = ty1;
511 transformed->x2 = tx2;
512 transformed->y2 = ty2;
517 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
518 #define ABS(f) (((f) < 0)? (-(f)) : (f))
519 #define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
522 analyze_extent (pixman_image_t *image,
523 const pixman_box32_t *extents,
526 pixman_transform_t *transform;
527 pixman_fixed_t x_off, y_off;
528 pixman_fixed_t width, height;
529 pixman_fixed_t *params;
530 box_48_16_t transformed;
531 pixman_box32_t exp_extents;
536 /* Some compositing functions walk one step
537 * outside the destination rectangle, so we
538 * check here that the expanded-by-one source
539 * extents in destination space fits in 16 bits
541 if (!IS_16BIT (extents->x1 - 1) ||
542 !IS_16BIT (extents->y1 - 1) ||
543 !IS_16BIT (extents->x2 + 1) ||
544 !IS_16BIT (extents->y2 + 1))
549 transform = image->common.transform;
550 if (image->common.type == BITS)
552 /* During repeat mode calculations we might convert the
553 * width/height of an image to fixed 16.16, so we need
554 * them to be smaller than 16 bits.
556 if (image->bits.width >= 0x7fff || image->bits.height >= 0x7fff)
559 if ((image->common.flags & FAST_PATH_ID_TRANSFORM) == FAST_PATH_ID_TRANSFORM &&
562 extents->x2 <= image->bits.width &&
563 extents->y2 <= image->bits.height)
565 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
569 switch (image->common.filter)
571 case PIXMAN_FILTER_CONVOLUTION:
572 params = image->common.filter_params;
573 x_off = - pixman_fixed_e - ((params[0] - pixman_fixed_1) >> 1);
574 y_off = - pixman_fixed_e - ((params[1] - pixman_fixed_1) >> 1);
579 case PIXMAN_FILTER_GOOD:
580 case PIXMAN_FILTER_BEST:
581 case PIXMAN_FILTER_BILINEAR:
582 x_off = - pixman_fixed_1 / 2;
583 y_off = - pixman_fixed_1 / 2;
584 width = pixman_fixed_1;
585 height = pixman_fixed_1;
588 case PIXMAN_FILTER_FAST:
589 case PIXMAN_FILTER_NEAREST:
590 x_off = - pixman_fixed_e;
591 y_off = - pixman_fixed_e;
608 if (!compute_transformed_extents (transform, extents, &transformed))
611 /* Expand the source area by a tiny bit so account of different rounding that
612 * may happen during sampling. Note that (8 * pixman_fixed_e) is very far from
613 * 0.5 so this won't cause the area computed to be overly pessimistic.
615 transformed.x1 -= 8 * pixman_fixed_e;
616 transformed.y1 -= 8 * pixman_fixed_e;
617 transformed.x2 += 8 * pixman_fixed_e;
618 transformed.y2 += 8 * pixman_fixed_e;
620 if (image->common.type == BITS)
622 if (pixman_fixed_to_int (transformed.x1) >= 0 &&
623 pixman_fixed_to_int (transformed.y1) >= 0 &&
624 pixman_fixed_to_int (transformed.x2) < image->bits.width &&
625 pixman_fixed_to_int (transformed.y2) < image->bits.height)
627 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST;
630 if (pixman_fixed_to_int (transformed.x1 - pixman_fixed_1 / 2) >= 0 &&
631 pixman_fixed_to_int (transformed.y1 - pixman_fixed_1 / 2) >= 0 &&
632 pixman_fixed_to_int (transformed.x2 + pixman_fixed_1 / 2) < image->bits.width &&
633 pixman_fixed_to_int (transformed.y2 + pixman_fixed_1 / 2) < image->bits.height)
635 *flags |= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR;
639 /* Check we don't overflow when the destination extents are expanded by one.
640 * This ensures that compositing functions can simply walk the source space
641 * using 16.16 variables without worrying about overflow.
643 exp_extents = *extents;
649 if (!compute_transformed_extents (transform, &exp_extents, &transformed))
652 if (!IS_16_16 (transformed.x1 + x_off - 8 * pixman_fixed_e) ||
653 !IS_16_16 (transformed.y1 + y_off - 8 * pixman_fixed_e) ||
654 !IS_16_16 (transformed.x2 + x_off + 8 * pixman_fixed_e + width) ||
655 !IS_16_16 (transformed.y2 + y_off + 8 * pixman_fixed_e + height))
664 * Work around GCC bug causing crashes in Mozilla with SSE2
666 * When using -msse, gcc generates movdqa instructions assuming that
667 * the stack is 16 byte aligned. Unfortunately some applications, such
668 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
669 * causes the movdqa instructions to fail.
671 * The __force_align_arg_pointer__ makes gcc generate a prologue that
672 * realigns the stack pointer to 16 bytes.
674 * On x86-64 this is not necessary because the standard ABI already
675 * calls for a 16 byte aligned stack.
677 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
679 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
680 __attribute__((__force_align_arg_pointer__))
683 pixman_image_composite32 (pixman_op_t op,
684 pixman_image_t * src,
685 pixman_image_t * mask,
686 pixman_image_t * dest,
696 pixman_format_code_t src_format, mask_format, dest_format;
697 uint32_t src_flags, mask_flags, dest_flags;
698 pixman_region32_t region;
699 pixman_box32_t extents;
700 pixman_implementation_t *imp;
701 pixman_composite_func_t func;
703 _pixman_image_validate (src);
705 _pixman_image_validate (mask);
706 _pixman_image_validate (dest);
708 src_format = src->common.extended_format_code;
709 src_flags = src->common.flags;
713 mask_format = mask->common.extended_format_code;
714 mask_flags = mask->common.flags;
718 mask_format = PIXMAN_null;
719 mask_flags = FAST_PATH_IS_OPAQUE;
722 dest_format = dest->common.extended_format_code;
723 dest_flags = dest->common.flags;
725 /* Check for pixbufs */
726 if ((mask_format == PIXMAN_a8r8g8b8 || mask_format == PIXMAN_a8b8g8r8) &&
727 (src->type == BITS && src->bits.bits == mask->bits.bits) &&
728 (src->common.repeat == mask->common.repeat) &&
729 (src_x == mask_x && src_y == mask_y))
731 if (src_format == PIXMAN_x8b8g8r8)
732 src_format = mask_format = PIXMAN_pixbuf;
733 else if (src_format == PIXMAN_x8r8g8b8)
734 src_format = mask_format = PIXMAN_rpixbuf;
737 pixman_region32_init (®ion);
739 if (!pixman_compute_composite_region32 (
740 ®ion, src, mask, dest,
741 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height))
746 extents = *pixman_region32_extents (®ion);
748 extents.x1 -= dest_x - src_x;
749 extents.y1 -= dest_y - src_y;
750 extents.x2 -= dest_x - src_x;
751 extents.y2 -= dest_y - src_y;
753 if (!analyze_extent (src, &extents, &src_flags))
756 extents.x1 -= src_x - mask_x;
757 extents.y1 -= src_y - mask_y;
758 extents.x2 -= src_x - mask_x;
759 extents.y2 -= src_y - mask_y;
761 if (!analyze_extent (mask, &extents, &mask_flags))
764 /* If the clip is within the source samples, and the samples are
765 * opaque, then the source is effectively opaque.
767 #define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
768 FAST_PATH_NEAREST_FILTER | \
769 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
770 #define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
771 FAST_PATH_BILINEAR_FILTER | \
772 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
774 if ((src_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
775 (src_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
777 src_flags |= FAST_PATH_IS_OPAQUE;
780 if ((mask_flags & NEAREST_OPAQUE) == NEAREST_OPAQUE ||
781 (mask_flags & BILINEAR_OPAQUE) == BILINEAR_OPAQUE)
783 mask_flags |= FAST_PATH_IS_OPAQUE;
787 * Check if we can replace our operator by a simpler one
788 * if the src or dest are opaque. The output operator should be
789 * mathematically equivalent to the source.
791 op = optimize_operator (op, src_flags, mask_flags, dest_flags);
793 if (lookup_composite_function (op,
794 src_format, src_flags,
795 mask_format, mask_flags,
796 dest_format, dest_flags,
799 pixman_composite_info_t info;
800 const pixman_box32_t *pbox;
804 info.src_image = src;
805 info.mask_image = mask;
806 info.dest_image = dest;
807 info.src_flags = src_flags;
808 info.mask_flags = mask_flags;
809 info.dest_flags = dest_flags;
811 pbox = pixman_region32_rectangles (®ion, &n);
815 info.src_x = pbox->x1 + src_x - dest_x;
816 info.src_y = pbox->y1 + src_y - dest_y;
817 info.mask_x = pbox->x1 + mask_x - dest_x;
818 info.mask_y = pbox->y1 + mask_y - dest_y;
819 info.dest_x = pbox->x1;
820 info.dest_y = pbox->y1;
821 info.width = pbox->x2 - pbox->x1;
822 info.height = pbox->y2 - pbox->y1;
831 pixman_region32_fini (®ion);
835 pixman_image_composite (pixman_op_t op,
836 pixman_image_t * src,
837 pixman_image_t * mask,
838 pixman_image_t * dest,
848 pixman_image_composite32 (op, src, mask, dest, src_x, src_y,
849 mask_x, mask_y, dest_x, dest_y, width, height);
852 PIXMAN_EXPORT pixman_bool_t
853 pixman_blt (uint32_t *src_bits,
866 return _pixman_implementation_blt (get_implementation(),
867 src_bits, dst_bits, src_stride, dst_stride,
874 PIXMAN_EXPORT pixman_bool_t
875 pixman_fill (uint32_t *bits,
884 return _pixman_implementation_fill (
885 get_implementation(), bits, stride, bpp, x, y, width, height, xor);
889 color_to_uint32 (const pixman_color_t *color)
892 (color->alpha >> 8 << 24) |
893 (color->red >> 8 << 16) |
894 (color->green & 0xff00) |
899 color_to_pixel (pixman_color_t * color,
901 pixman_format_code_t format)
903 uint32_t c = color_to_uint32 (color);
905 if (!(format == PIXMAN_a8r8g8b8 ||
906 format == PIXMAN_x8r8g8b8 ||
907 format == PIXMAN_a8b8g8r8 ||
908 format == PIXMAN_x8b8g8r8 ||
909 format == PIXMAN_b8g8r8a8 ||
910 format == PIXMAN_b8g8r8x8 ||
911 format == PIXMAN_r8g8b8a8 ||
912 format == PIXMAN_r8g8b8x8 ||
913 format == PIXMAN_r5g6b5 ||
914 format == PIXMAN_b5g6r5 ||
915 format == PIXMAN_a8 ||
916 format == PIXMAN_a1))
921 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_ABGR)
923 c = ((c & 0xff000000) >> 0) |
924 ((c & 0x00ff0000) >> 16) |
925 ((c & 0x0000ff00) >> 0) |
926 ((c & 0x000000ff) << 16);
928 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_BGRA)
930 c = ((c & 0xff000000) >> 24) |
931 ((c & 0x00ff0000) >> 8) |
932 ((c & 0x0000ff00) << 8) |
933 ((c & 0x000000ff) << 24);
935 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_RGBA)
936 c = ((c & 0xff000000) >> 24) | (c << 8);
938 if (format == PIXMAN_a1)
940 else if (format == PIXMAN_a8)
942 else if (format == PIXMAN_r5g6b5 ||
943 format == PIXMAN_b5g6r5)
944 c = CONVERT_8888_TO_0565 (c);
947 printf ("color: %x %x %x %x\n", color->alpha, color->red, color->green, color->blue);
948 printf ("pixel: %x\n", c);
955 PIXMAN_EXPORT pixman_bool_t
956 pixman_image_fill_rectangles (pixman_op_t op,
957 pixman_image_t * dest,
958 pixman_color_t * color,
960 const pixman_rectangle16_t *rects)
962 pixman_box32_t stack_boxes[6];
963 pixman_box32_t *boxes;
964 pixman_bool_t result;
969 boxes = pixman_malloc_ab (sizeof (pixman_box32_t), n_rects);
978 for (i = 0; i < n_rects; ++i)
980 boxes[i].x1 = rects[i].x;
981 boxes[i].y1 = rects[i].y;
982 boxes[i].x2 = boxes[i].x1 + rects[i].width;
983 boxes[i].y2 = boxes[i].y1 + rects[i].height;
986 result = pixman_image_fill_boxes (op, dest, color, n_rects, boxes);
988 if (boxes != stack_boxes)
994 PIXMAN_EXPORT pixman_bool_t
995 pixman_image_fill_boxes (pixman_op_t op,
996 pixman_image_t * dest,
997 pixman_color_t * color,
999 const pixman_box32_t *boxes)
1001 pixman_image_t *solid;
1005 _pixman_image_validate (dest);
1007 if (color->alpha == 0xffff)
1009 if (op == PIXMAN_OP_OVER)
1013 if (op == PIXMAN_OP_CLEAR)
1025 if (op == PIXMAN_OP_SRC)
1029 if (color_to_pixel (color, &pixel, dest->bits.format))
1031 pixman_region32_t fill_region;
1033 pixman_box32_t *rects;
1035 if (!pixman_region32_init_rects (&fill_region, boxes, n_boxes))
1038 if (dest->common.have_clip_region)
1040 if (!pixman_region32_intersect (&fill_region,
1042 &dest->common.clip_region))
1046 rects = pixman_region32_rectangles (&fill_region, &n_rects);
1047 for (j = 0; j < n_rects; ++j)
1049 const pixman_box32_t *rect = &(rects[j]);
1050 pixman_fill (dest->bits.bits, dest->bits.rowstride, PIXMAN_FORMAT_BPP (dest->bits.format),
1051 rect->x1, rect->y1, rect->x2 - rect->x1, rect->y2 - rect->y1,
1055 pixman_region32_fini (&fill_region);
1060 solid = pixman_image_create_solid_fill (color);
1064 for (i = 0; i < n_boxes; ++i)
1066 const pixman_box32_t *box = &(boxes[i]);
1068 pixman_image_composite32 (op, solid, NULL, dest,
1071 box->x2 - box->x1, box->y2 - box->y1);
1074 pixman_image_unref (solid);
1082 * Returns the version of the pixman library encoded in a single
1083 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
1084 * later versions compare greater than earlier versions.
1086 * A run-time comparison to check that pixman's version is greater than
1087 * or equal to version X.Y.Z could be performed as follows:
1089 * <informalexample><programlisting>
1090 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
1091 * </programlisting></informalexample>
1093 * See also pixman_version_string() as well as the compile-time
1094 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
1096 * Return value: the encoded version.
1099 pixman_version (void)
1101 return PIXMAN_VERSION;
1105 * pixman_version_string:
1107 * Returns the version of the pixman library as a human-readable string
1108 * of the form "X.Y.Z".
1110 * See also pixman_version() as well as the compile-time equivalents
1111 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
1113 * Return value: a string containing the version.
1115 PIXMAN_EXPORT const char*
1116 pixman_version_string (void)
1118 return PIXMAN_VERSION_STRING;
1122 * pixman_format_supported_source:
1123 * @format: A pixman_format_code_t format
1125 * Return value: whether the provided format code is a supported
1126 * format for a pixman surface used as a source in
1129 * Currently, all pixman_format_code_t values are supported.
1131 PIXMAN_EXPORT pixman_bool_t
1132 pixman_format_supported_source (pixman_format_code_t format)
1136 /* 32 bpp formats */
1137 case PIXMAN_a2b10g10r10:
1138 case PIXMAN_x2b10g10r10:
1139 case PIXMAN_a2r10g10b10:
1140 case PIXMAN_x2r10g10b10:
1141 case PIXMAN_a8r8g8b8:
1142 case PIXMAN_x8r8g8b8:
1143 case PIXMAN_a8b8g8r8:
1144 case PIXMAN_x8b8g8r8:
1145 case PIXMAN_b8g8r8a8:
1146 case PIXMAN_b8g8r8x8:
1147 case PIXMAN_r8g8b8a8:
1148 case PIXMAN_r8g8b8x8:
1153 case PIXMAN_x14r6g6b6:
1154 /* 16 bpp formats */
1155 case PIXMAN_a1r5g5b5:
1156 case PIXMAN_x1r5g5b5:
1157 case PIXMAN_a1b5g5r5:
1158 case PIXMAN_x1b5g5r5:
1159 case PIXMAN_a4r4g4b4:
1160 case PIXMAN_x4r4g4b4:
1161 case PIXMAN_a4b4g4r4:
1162 case PIXMAN_x4b4g4r4:
1167 case PIXMAN_a2r2g2b2:
1168 case PIXMAN_a2b2g2r2:
1172 /* Collides with PIXMAN_c8
1175 /* Collides with PIXMAN_g8
1182 case PIXMAN_a1r1g1b1:
1183 case PIXMAN_a1b1g1r1:
1200 * pixman_format_supported_destination:
1201 * @format: A pixman_format_code_t format
1203 * Return value: whether the provided format code is a supported
1204 * format for a pixman surface used as a destination in
1207 * Currently, all pixman_format_code_t values are supported
1208 * except for the YUV formats.
1210 PIXMAN_EXPORT pixman_bool_t
1211 pixman_format_supported_destination (pixman_format_code_t format)
1213 /* YUV formats cannot be written to at the moment */
1214 if (format == PIXMAN_yuy2 || format == PIXMAN_yv12)
1217 return pixman_format_supported_source (format);
1220 PIXMAN_EXPORT pixman_bool_t
1221 pixman_compute_composite_region (pixman_region16_t * region,
1222 pixman_image_t * src_image,
1223 pixman_image_t * mask_image,
1224 pixman_image_t * dest_image,
1234 pixman_region32_t r32;
1235 pixman_bool_t retval;
1237 pixman_region32_init (&r32);
1239 retval = pixman_compute_composite_region32 (
1240 &r32, src_image, mask_image, dest_image,
1241 src_x, src_y, mask_x, mask_y, dest_x, dest_y,
1246 if (!pixman_region16_copy_from_region32 (region, &r32))
1250 pixman_region32_fini (&r32);