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 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 typedef struct operator_info_t operator_info_t
;
45 struct operator_info_t
47 uint8_t opaque_info
[4];
50 #define PACK(neither, src, dest, both) \
51 {{ (uint8_t)PIXMAN_OP_ ## neither, \
52 (uint8_t)PIXMAN_OP_ ## src, \
53 (uint8_t)PIXMAN_OP_ ## dest, \
54 (uint8_t)PIXMAN_OP_ ## both }}
56 static const operator_info_t operator_table
[] =
58 /* Neither Opaque Src Opaque Dst Opaque Both Opaque */
59 PACK (CLEAR
, CLEAR
, CLEAR
, CLEAR
),
60 PACK (SRC
, SRC
, SRC
, SRC
),
61 PACK (DST
, DST
, DST
, DST
),
62 PACK (OVER
, SRC
, OVER
, SRC
),
63 PACK (OVER_REVERSE
, OVER_REVERSE
, DST
, DST
),
64 PACK (IN
, IN
, SRC
, SRC
),
65 PACK (IN_REVERSE
, DST
, IN_REVERSE
, DST
),
66 PACK (OUT
, OUT
, CLEAR
, CLEAR
),
67 PACK (OUT_REVERSE
, CLEAR
, OUT_REVERSE
, CLEAR
),
68 PACK (ATOP
, IN
, OVER
, SRC
),
69 PACK (ATOP_REVERSE
, OVER_REVERSE
, IN_REVERSE
, DST
),
70 PACK (XOR
, OUT
, OUT_REVERSE
, CLEAR
),
71 PACK (ADD
, ADD
, ADD
, ADD
),
72 PACK (SATURATE
, OVER_REVERSE
, DST
, DST
),
77 PACK (CLEAR
, CLEAR
, CLEAR
, CLEAR
),
78 PACK (SRC
, SRC
, SRC
, SRC
),
79 PACK (DST
, DST
, DST
, DST
),
80 PACK (DISJOINT_OVER
, DISJOINT_OVER
, DISJOINT_OVER
, DISJOINT_OVER
),
81 PACK (DISJOINT_OVER_REVERSE
, DISJOINT_OVER_REVERSE
, DISJOINT_OVER_REVERSE
, DISJOINT_OVER_REVERSE
),
82 PACK (DISJOINT_IN
, DISJOINT_IN
, DISJOINT_IN
, DISJOINT_IN
),
83 PACK (DISJOINT_IN_REVERSE
, DISJOINT_IN_REVERSE
, DISJOINT_IN_REVERSE
, DISJOINT_IN_REVERSE
),
84 PACK (DISJOINT_OUT
, DISJOINT_OUT
, DISJOINT_OUT
, DISJOINT_OUT
),
85 PACK (DISJOINT_OUT_REVERSE
, DISJOINT_OUT_REVERSE
, DISJOINT_OUT_REVERSE
, DISJOINT_OUT_REVERSE
),
86 PACK (DISJOINT_ATOP
, DISJOINT_ATOP
, DISJOINT_ATOP
, DISJOINT_ATOP
),
87 PACK (DISJOINT_ATOP_REVERSE
, DISJOINT_ATOP_REVERSE
, DISJOINT_ATOP_REVERSE
, DISJOINT_ATOP_REVERSE
),
88 PACK (DISJOINT_XOR
, DISJOINT_XOR
, DISJOINT_XOR
, DISJOINT_XOR
),
95 PACK (CLEAR
, CLEAR
, CLEAR
, CLEAR
),
96 PACK (SRC
, SRC
, SRC
, SRC
),
97 PACK (DST
, DST
, DST
, DST
),
98 PACK (CONJOINT_OVER
, CONJOINT_OVER
, CONJOINT_OVER
, CONJOINT_OVER
),
99 PACK (CONJOINT_OVER_REVERSE
, CONJOINT_OVER_REVERSE
, CONJOINT_OVER_REVERSE
, CONJOINT_OVER_REVERSE
),
100 PACK (CONJOINT_IN
, CONJOINT_IN
, CONJOINT_IN
, CONJOINT_IN
),
101 PACK (CONJOINT_IN_REVERSE
, CONJOINT_IN_REVERSE
, CONJOINT_IN_REVERSE
, CONJOINT_IN_REVERSE
),
102 PACK (CONJOINT_OUT
, CONJOINT_OUT
, CONJOINT_OUT
, CONJOINT_OUT
),
103 PACK (CONJOINT_OUT_REVERSE
, CONJOINT_OUT_REVERSE
, CONJOINT_OUT_REVERSE
, CONJOINT_OUT_REVERSE
),
104 PACK (CONJOINT_ATOP
, CONJOINT_ATOP
, CONJOINT_ATOP
, CONJOINT_ATOP
),
105 PACK (CONJOINT_ATOP_REVERSE
, CONJOINT_ATOP_REVERSE
, CONJOINT_ATOP_REVERSE
, CONJOINT_ATOP_REVERSE
),
106 PACK (CONJOINT_XOR
, CONJOINT_XOR
, CONJOINT_XOR
, CONJOINT_XOR
),
113 PACK (MULTIPLY
, MULTIPLY
, MULTIPLY
, MULTIPLY
),
114 PACK (SCREEN
, SCREEN
, SCREEN
, SCREEN
),
115 PACK (OVERLAY
, OVERLAY
, OVERLAY
, OVERLAY
),
116 PACK (DARKEN
, DARKEN
, DARKEN
, DARKEN
),
117 PACK (LIGHTEN
, LIGHTEN
, LIGHTEN
, LIGHTEN
),
118 PACK (COLOR_DODGE
, COLOR_DODGE
, COLOR_DODGE
, COLOR_DODGE
),
119 PACK (COLOR_BURN
, COLOR_BURN
, COLOR_BURN
, COLOR_BURN
),
120 PACK (HARD_LIGHT
, HARD_LIGHT
, HARD_LIGHT
, HARD_LIGHT
),
121 PACK (SOFT_LIGHT
, SOFT_LIGHT
, SOFT_LIGHT
, SOFT_LIGHT
),
122 PACK (DIFFERENCE
, DIFFERENCE
, DIFFERENCE
, DIFFERENCE
),
123 PACK (EXCLUSION
, EXCLUSION
, EXCLUSION
, EXCLUSION
),
124 PACK (HSL_HUE
, HSL_HUE
, HSL_HUE
, HSL_HUE
),
125 PACK (HSL_SATURATION
, HSL_SATURATION
, HSL_SATURATION
, HSL_SATURATION
),
126 PACK (HSL_COLOR
, HSL_COLOR
, HSL_COLOR
, HSL_COLOR
),
127 PACK (HSL_LUMINOSITY
, HSL_LUMINOSITY
, HSL_LUMINOSITY
, HSL_LUMINOSITY
),
131 * Optimize the current operator based on opacity of source or destination
132 * The output operator should be mathematically equivalent to the source.
135 optimize_operator (pixman_op_t op
,
140 pixman_bool_t is_source_opaque
, is_dest_opaque
;
142 #define OPAQUE_SHIFT 13
144 COMPILE_TIME_ASSERT (FAST_PATH_IS_OPAQUE
== (1 << OPAQUE_SHIFT
));
146 is_dest_opaque
= (dst_flags
& FAST_PATH_IS_OPAQUE
);
147 is_source_opaque
= ((src_flags
& mask_flags
) & FAST_PATH_IS_OPAQUE
);
149 is_dest_opaque
>>= OPAQUE_SHIFT
- 1;
150 is_source_opaque
>>= OPAQUE_SHIFT
;
152 return operator_table
[op
].opaque_info
[is_dest_opaque
| is_source_opaque
];
156 * Computing composite region
158 static inline pixman_bool_t
159 clip_general_image (pixman_region32_t
* region
,
160 pixman_region32_t
* clip
,
164 if (pixman_region32_n_rects (region
) == 1 &&
165 pixman_region32_n_rects (clip
) == 1)
167 pixman_box32_t
* rbox
= pixman_region32_rectangles (region
, NULL
);
168 pixman_box32_t
* cbox
= pixman_region32_rectangles (clip
, NULL
);
171 if (rbox
->x1
< (v
= cbox
->x1
+ dx
))
173 if (rbox
->x2
> (v
= cbox
->x2
+ dx
))
175 if (rbox
->y1
< (v
= cbox
->y1
+ dy
))
177 if (rbox
->y2
> (v
= cbox
->y2
+ dy
))
179 if (rbox
->x1
>= rbox
->x2
|| rbox
->y1
>= rbox
->y2
)
181 pixman_region32_init (region
);
185 else if (!pixman_region32_not_empty (clip
))
192 pixman_region32_translate (region
, -dx
, -dy
);
194 if (!pixman_region32_intersect (region
, region
, clip
))
198 pixman_region32_translate (region
, dx
, dy
);
201 return pixman_region32_not_empty (region
);
204 static inline pixman_bool_t
205 clip_source_image (pixman_region32_t
* region
,
206 pixman_image_t
* image
,
210 /* Source clips are ignored, unless they are explicitly turned on
211 * and the clip in question was set by an X client. (Because if
212 * the clip was not set by a client, then it is a hierarchy
213 * clip and those should always be ignored for sources).
215 if (!image
->common
.clip_sources
|| !image
->common
.client_clip
)
218 return clip_general_image (region
,
219 &image
->common
.clip_region
,
224 * returns FALSE if the final region is empty. Indistinguishable from
225 * an allocation failure, but rendering ignores those anyways.
228 _pixman_compute_composite_region32 (pixman_region32_t
* region
,
229 pixman_image_t
* src_image
,
230 pixman_image_t
* mask_image
,
231 pixman_image_t
* dest_image
,
241 region
->extents
.x1
= dest_x
;
242 region
->extents
.x2
= dest_x
+ width
;
243 region
->extents
.y1
= dest_y
;
244 region
->extents
.y2
= dest_y
+ height
;
246 region
->extents
.x1
= MAX (region
->extents
.x1
, 0);
247 region
->extents
.y1
= MAX (region
->extents
.y1
, 0);
248 region
->extents
.x2
= MIN (region
->extents
.x2
, dest_image
->bits
.width
);
249 region
->extents
.y2
= MIN (region
->extents
.y2
, dest_image
->bits
.height
);
253 /* Check for empty operation */
254 if (region
->extents
.x1
>= region
->extents
.x2
||
255 region
->extents
.y1
>= region
->extents
.y2
)
257 region
->extents
.x1
= 0;
258 region
->extents
.x2
= 0;
259 region
->extents
.y1
= 0;
260 region
->extents
.y2
= 0;
264 if (dest_image
->common
.have_clip_region
)
266 if (!clip_general_image (region
, &dest_image
->common
.clip_region
, 0, 0))
270 if (dest_image
->common
.alpha_map
)
272 if (!pixman_region32_intersect_rect (region
, region
,
273 dest_image
->common
.alpha_origin_x
,
274 dest_image
->common
.alpha_origin_y
,
275 dest_image
->common
.alpha_map
->width
,
276 dest_image
->common
.alpha_map
->height
))
280 if (!pixman_region32_not_empty (region
))
282 if (dest_image
->common
.alpha_map
->common
.have_clip_region
)
284 if (!clip_general_image (region
, &dest_image
->common
.alpha_map
->common
.clip_region
,
285 -dest_image
->common
.alpha_origin_x
,
286 -dest_image
->common
.alpha_origin_y
))
293 /* clip against src */
294 if (src_image
->common
.have_clip_region
)
296 if (!clip_source_image (region
, src_image
, dest_x
- src_x
, dest_y
- src_y
))
299 if (src_image
->common
.alpha_map
&& src_image
->common
.alpha_map
->common
.have_clip_region
)
301 if (!clip_source_image (region
, (pixman_image_t
*)src_image
->common
.alpha_map
,
302 dest_x
- (src_x
- src_image
->common
.alpha_origin_x
),
303 dest_y
- (src_y
- src_image
->common
.alpha_origin_y
)))
308 /* clip against mask */
309 if (mask_image
&& mask_image
->common
.have_clip_region
)
311 if (!clip_source_image (region
, mask_image
, dest_x
- mask_x
, dest_y
- mask_y
))
314 if (mask_image
->common
.alpha_map
&& mask_image
->common
.alpha_map
->common
.have_clip_region
)
316 if (!clip_source_image (region
, (pixman_image_t
*)mask_image
->common
.alpha_map
,
317 dest_x
- (mask_x
- mask_image
->common
.alpha_origin_x
),
318 dest_y
- (mask_y
- mask_image
->common
.alpha_origin_y
)))
328 typedef struct box_48_16 box_48_16_t
;
332 pixman_fixed_48_16_t x1
;
333 pixman_fixed_48_16_t y1
;
334 pixman_fixed_48_16_t x2
;
335 pixman_fixed_48_16_t y2
;
339 compute_transformed_extents (pixman_transform_t
*transform
,
340 const pixman_box32_t
*extents
,
341 box_48_16_t
*transformed
)
343 pixman_fixed_48_16_t tx1
, ty1
, tx2
, ty2
;
344 pixman_fixed_t x1
, y1
, x2
, y2
;
347 x1
= pixman_int_to_fixed (extents
->x1
) + pixman_fixed_1
/ 2;
348 y1
= pixman_int_to_fixed (extents
->y1
) + pixman_fixed_1
/ 2;
349 x2
= pixman_int_to_fixed (extents
->x2
) - pixman_fixed_1
/ 2;
350 y2
= pixman_int_to_fixed (extents
->y2
) - pixman_fixed_1
/ 2;
354 transformed
->x1
= x1
;
355 transformed
->y1
= y1
;
356 transformed
->x2
= x2
;
357 transformed
->y2
= y2
;
362 tx1
= ty1
= INT64_MAX
;
363 tx2
= ty2
= INT64_MIN
;
365 for (i
= 0; i
< 4; ++i
)
367 pixman_fixed_48_16_t tx
, ty
;
370 v
.vector
[0] = (i
& 0x01)? x1
: x2
;
371 v
.vector
[1] = (i
& 0x02)? y1
: y2
;
372 v
.vector
[2] = pixman_fixed_1
;
374 if (!pixman_transform_point (transform
, &v
))
377 tx
= (pixman_fixed_48_16_t
)v
.vector
[0];
378 ty
= (pixman_fixed_48_16_t
)v
.vector
[1];
390 transformed
->x1
= tx1
;
391 transformed
->y1
= ty1
;
392 transformed
->x2
= tx2
;
393 transformed
->y2
= ty2
;
398 #define IS_16BIT(x) (((x) >= INT16_MIN) && ((x) <= INT16_MAX))
399 #define ABS(f) (((f) < 0)? (-(f)) : (f))
400 #define IS_16_16(f) (((f) >= pixman_min_fixed_48_16 && ((f) <= pixman_max_fixed_48_16)))
403 analyze_extent (pixman_image_t
*image
,
404 const pixman_box32_t
*extents
,
407 pixman_transform_t
*transform
;
408 pixman_fixed_t x_off
, y_off
;
409 pixman_fixed_t width
, height
;
410 pixman_fixed_t
*params
;
411 box_48_16_t transformed
;
412 pixman_box32_t exp_extents
;
417 /* Some compositing functions walk one step
418 * outside the destination rectangle, so we
419 * check here that the expanded-by-one source
420 * extents in destination space fits in 16 bits
422 if (!IS_16BIT (extents
->x1
- 1) ||
423 !IS_16BIT (extents
->y1
- 1) ||
424 !IS_16BIT (extents
->x2
+ 1) ||
425 !IS_16BIT (extents
->y2
+ 1))
430 transform
= image
->common
.transform
;
431 if (image
->common
.type
== BITS
)
433 /* During repeat mode calculations we might convert the
434 * width/height of an image to fixed 16.16, so we need
435 * them to be smaller than 16 bits.
437 if (image
->bits
.width
>= 0x7fff || image
->bits
.height
>= 0x7fff)
440 if ((image
->common
.flags
& FAST_PATH_ID_TRANSFORM
) == FAST_PATH_ID_TRANSFORM
&&
443 extents
->x2
<= image
->bits
.width
&&
444 extents
->y2
<= image
->bits
.height
)
446 *flags
|= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST
;
450 switch (image
->common
.filter
)
452 case PIXMAN_FILTER_CONVOLUTION
:
453 params
= image
->common
.filter_params
;
454 x_off
= - pixman_fixed_e
- ((params
[0] - pixman_fixed_1
) >> 1);
455 y_off
= - pixman_fixed_e
- ((params
[1] - pixman_fixed_1
) >> 1);
460 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION
:
461 params
= image
->common
.filter_params
;
462 x_off
= - pixman_fixed_e
- ((params
[0] - pixman_fixed_1
) >> 1);
463 y_off
= - pixman_fixed_e
- ((params
[1] - pixman_fixed_1
) >> 1);
468 case PIXMAN_FILTER_GOOD
:
469 case PIXMAN_FILTER_BEST
:
470 case PIXMAN_FILTER_BILINEAR
:
471 x_off
= - pixman_fixed_1
/ 2;
472 y_off
= - pixman_fixed_1
/ 2;
473 width
= pixman_fixed_1
;
474 height
= pixman_fixed_1
;
477 case PIXMAN_FILTER_FAST
:
478 case PIXMAN_FILTER_NEAREST
:
479 x_off
= - pixman_fixed_e
;
480 y_off
= - pixman_fixed_e
;
497 if (!compute_transformed_extents (transform
, extents
, &transformed
))
500 if (image
->common
.type
== BITS
)
502 if (pixman_fixed_to_int (transformed
.x1
- pixman_fixed_e
) >= 0 &&
503 pixman_fixed_to_int (transformed
.y1
- pixman_fixed_e
) >= 0 &&
504 pixman_fixed_to_int (transformed
.x2
- pixman_fixed_e
) < image
->bits
.width
&&
505 pixman_fixed_to_int (transformed
.y2
- pixman_fixed_e
) < image
->bits
.height
)
507 *flags
|= FAST_PATH_SAMPLES_COVER_CLIP_NEAREST
;
510 if (pixman_fixed_to_int (transformed
.x1
- pixman_fixed_1
/ 2) >= 0 &&
511 pixman_fixed_to_int (transformed
.y1
- pixman_fixed_1
/ 2) >= 0 &&
512 pixman_fixed_to_int (transformed
.x2
+ pixman_fixed_1
/ 2) < image
->bits
.width
&&
513 pixman_fixed_to_int (transformed
.y2
+ pixman_fixed_1
/ 2) < image
->bits
.height
)
515 *flags
|= FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR
;
519 /* Check we don't overflow when the destination extents are expanded by one.
520 * This ensures that compositing functions can simply walk the source space
521 * using 16.16 variables without worrying about overflow.
523 exp_extents
= *extents
;
529 if (!compute_transformed_extents (transform
, &exp_extents
, &transformed
))
532 if (!IS_16_16 (transformed
.x1
+ x_off
- 8 * pixman_fixed_e
) ||
533 !IS_16_16 (transformed
.y1
+ y_off
- 8 * pixman_fixed_e
) ||
534 !IS_16_16 (transformed
.x2
+ x_off
+ 8 * pixman_fixed_e
+ width
) ||
535 !IS_16_16 (transformed
.y2
+ y_off
+ 8 * pixman_fixed_e
+ height
))
544 * Work around GCC bug causing crashes in Mozilla with SSE2
546 * When using -msse, gcc generates movdqa instructions assuming that
547 * the stack is 16 byte aligned. Unfortunately some applications, such
548 * as Mozilla and Mono, end up aligning the stack to 4 bytes, which
549 * causes the movdqa instructions to fail.
551 * The __force_align_arg_pointer__ makes gcc generate a prologue that
552 * realigns the stack pointer to 16 bytes.
554 * On x86-64 this is not necessary because the standard ABI already
555 * calls for a 16 byte aligned stack.
557 * See https://bugs.freedesktop.org/show_bug.cgi?id=15693
559 #if defined (USE_SSE2) && defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__)
560 __attribute__((__force_align_arg_pointer__
))
563 pixman_image_composite32 (pixman_op_t op
,
564 pixman_image_t
* src
,
565 pixman_image_t
* mask
,
566 pixman_image_t
* dest
,
576 pixman_format_code_t src_format
, mask_format
, dest_format
;
577 pixman_region32_t region
;
578 pixman_box32_t extents
;
579 pixman_implementation_t
*imp
;
580 pixman_composite_func_t func
;
581 pixman_composite_info_t info
;
582 const pixman_box32_t
*pbox
;
585 _pixman_image_validate (src
);
587 _pixman_image_validate (mask
);
588 _pixman_image_validate (dest
);
590 src_format
= src
->common
.extended_format_code
;
591 info
.src_flags
= src
->common
.flags
;
593 if (mask
&& !(mask
->common
.flags
& FAST_PATH_IS_OPAQUE
))
595 mask_format
= mask
->common
.extended_format_code
;
596 info
.mask_flags
= mask
->common
.flags
;
600 mask_format
= PIXMAN_null
;
601 info
.mask_flags
= FAST_PATH_IS_OPAQUE
| FAST_PATH_NO_ALPHA_MAP
;
604 dest_format
= dest
->common
.extended_format_code
;
605 info
.dest_flags
= dest
->common
.flags
;
607 /* Check for pixbufs */
608 if ((mask_format
== PIXMAN_a8r8g8b8
|| mask_format
== PIXMAN_a8b8g8r8
) &&
609 (src
->type
== BITS
&& src
->bits
.bits
== mask
->bits
.bits
) &&
610 (src
->common
.repeat
== mask
->common
.repeat
) &&
611 (info
.src_flags
& info
.mask_flags
& FAST_PATH_ID_TRANSFORM
) &&
612 (src_x
== mask_x
&& src_y
== mask_y
))
614 if (src_format
== PIXMAN_x8b8g8r8
)
615 src_format
= mask_format
= PIXMAN_pixbuf
;
616 else if (src_format
== PIXMAN_x8r8g8b8
)
617 src_format
= mask_format
= PIXMAN_rpixbuf
;
620 pixman_region32_init (®ion
);
622 if (!_pixman_compute_composite_region32 (
623 ®ion
, src
, mask
, dest
,
624 src_x
, src_y
, mask_x
, mask_y
, dest_x
, dest_y
, width
, height
))
629 extents
= *pixman_region32_extents (®ion
);
631 extents
.x1
-= dest_x
- src_x
;
632 extents
.y1
-= dest_y
- src_y
;
633 extents
.x2
-= dest_x
- src_x
;
634 extents
.y2
-= dest_y
- src_y
;
636 if (!analyze_extent (src
, &extents
, &info
.src_flags
))
639 extents
.x1
-= src_x
- mask_x
;
640 extents
.y1
-= src_y
- mask_y
;
641 extents
.x2
-= src_x
- mask_x
;
642 extents
.y2
-= src_y
- mask_y
;
644 if (!analyze_extent (mask
, &extents
, &info
.mask_flags
))
647 /* If the clip is within the source samples, and the samples are
648 * opaque, then the source is effectively opaque.
650 #define NEAREST_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
651 FAST_PATH_NEAREST_FILTER | \
652 FAST_PATH_SAMPLES_COVER_CLIP_NEAREST)
653 #define BILINEAR_OPAQUE (FAST_PATH_SAMPLES_OPAQUE | \
654 FAST_PATH_BILINEAR_FILTER | \
655 FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR)
657 if ((info
.src_flags
& NEAREST_OPAQUE
) == NEAREST_OPAQUE
||
658 (info
.src_flags
& BILINEAR_OPAQUE
) == BILINEAR_OPAQUE
)
660 info
.src_flags
|= FAST_PATH_IS_OPAQUE
;
663 if ((info
.mask_flags
& NEAREST_OPAQUE
) == NEAREST_OPAQUE
||
664 (info
.mask_flags
& BILINEAR_OPAQUE
) == BILINEAR_OPAQUE
)
666 info
.mask_flags
|= FAST_PATH_IS_OPAQUE
;
670 * Check if we can replace our operator by a simpler one
671 * if the src or dest are opaque. The output operator should be
672 * mathematically equivalent to the source.
674 info
.op
= optimize_operator (op
, info
.src_flags
, info
.mask_flags
, info
.dest_flags
);
676 _pixman_implementation_lookup_composite (
677 get_implementation (), info
.op
,
678 src_format
, info
.src_flags
,
679 mask_format
, info
.mask_flags
,
680 dest_format
, info
.dest_flags
,
683 info
.src_image
= src
;
684 info
.mask_image
= mask
;
685 info
.dest_image
= dest
;
687 pbox
= pixman_region32_rectangles (®ion
, &n
);
691 info
.src_x
= pbox
->x1
+ src_x
- dest_x
;
692 info
.src_y
= pbox
->y1
+ src_y
- dest_y
;
693 info
.mask_x
= pbox
->x1
+ mask_x
- dest_x
;
694 info
.mask_y
= pbox
->y1
+ mask_y
- dest_y
;
695 info
.dest_x
= pbox
->x1
;
696 info
.dest_y
= pbox
->y1
;
697 info
.width
= pbox
->x2
- pbox
->x1
;
698 info
.height
= pbox
->y2
- pbox
->y1
;
706 pixman_region32_fini (®ion
);
710 pixman_image_composite (pixman_op_t op
,
711 pixman_image_t
* src
,
712 pixman_image_t
* mask
,
713 pixman_image_t
* dest
,
723 pixman_image_composite32 (op
, src
, mask
, dest
, src_x
, src_y
,
724 mask_x
, mask_y
, dest_x
, dest_y
, width
, height
);
727 PIXMAN_EXPORT pixman_bool_t
728 pixman_blt (uint32_t *src_bits
,
741 return _pixman_implementation_blt (get_implementation(),
742 src_bits
, dst_bits
, src_stride
, dst_stride
,
749 PIXMAN_EXPORT pixman_bool_t
750 pixman_fill (uint32_t *bits
,
759 return _pixman_implementation_fill (
760 get_implementation(), bits
, stride
, bpp
, x
, y
, width
, height
, filler
);
764 color_to_uint32 (const pixman_color_t
*color
)
767 (color
->alpha
>> 8 << 24) |
768 (color
->red
>> 8 << 16) |
769 (color
->green
& 0xff00) |
774 color_to_pixel (const pixman_color_t
*color
,
776 pixman_format_code_t format
)
778 uint32_t c
= color_to_uint32 (color
);
780 if (!(format
== PIXMAN_a8r8g8b8
||
781 format
== PIXMAN_x8r8g8b8
||
782 format
== PIXMAN_a8b8g8r8
||
783 format
== PIXMAN_x8b8g8r8
||
784 format
== PIXMAN_b8g8r8a8
||
785 format
== PIXMAN_b8g8r8x8
||
786 format
== PIXMAN_r8g8b8a8
||
787 format
== PIXMAN_r8g8b8x8
||
788 format
== PIXMAN_r5g6b5
||
789 format
== PIXMAN_b5g6r5
||
790 format
== PIXMAN_a8
||
791 format
== PIXMAN_a1
))
796 if (PIXMAN_FORMAT_TYPE (format
) == PIXMAN_TYPE_ABGR
)
798 c
= ((c
& 0xff000000) >> 0) |
799 ((c
& 0x00ff0000) >> 16) |
800 ((c
& 0x0000ff00) >> 0) |
801 ((c
& 0x000000ff) << 16);
803 if (PIXMAN_FORMAT_TYPE (format
) == PIXMAN_TYPE_BGRA
)
805 c
= ((c
& 0xff000000) >> 24) |
806 ((c
& 0x00ff0000) >> 8) |
807 ((c
& 0x0000ff00) << 8) |
808 ((c
& 0x000000ff) << 24);
810 if (PIXMAN_FORMAT_TYPE (format
) == PIXMAN_TYPE_RGBA
)
811 c
= ((c
& 0xff000000) >> 24) | (c
<< 8);
813 if (format
== PIXMAN_a1
)
815 else if (format
== PIXMAN_a8
)
817 else if (format
== PIXMAN_r5g6b5
||
818 format
== PIXMAN_b5g6r5
)
819 c
= convert_8888_to_0565 (c
);
822 printf ("color: %x %x %x %x\n", color
->alpha
, color
->red
, color
->green
, color
->blue
);
823 printf ("pixel: %x\n", c
);
830 PIXMAN_EXPORT pixman_bool_t
831 pixman_image_fill_rectangles (pixman_op_t op
,
832 pixman_image_t
* dest
,
833 const pixman_color_t
* color
,
835 const pixman_rectangle16_t
*rects
)
837 pixman_box32_t stack_boxes
[6];
838 pixman_box32_t
*boxes
;
839 pixman_bool_t result
;
844 boxes
= pixman_malloc_ab (sizeof (pixman_box32_t
), n_rects
);
853 for (i
= 0; i
< n_rects
; ++i
)
855 boxes
[i
].x1
= rects
[i
].x
;
856 boxes
[i
].y1
= rects
[i
].y
;
857 boxes
[i
].x2
= boxes
[i
].x1
+ rects
[i
].width
;
858 boxes
[i
].y2
= boxes
[i
].y1
+ rects
[i
].height
;
861 result
= pixman_image_fill_boxes (op
, dest
, color
, n_rects
, boxes
);
863 if (boxes
!= stack_boxes
)
869 PIXMAN_EXPORT pixman_bool_t
870 pixman_image_fill_boxes (pixman_op_t op
,
871 pixman_image_t
* dest
,
872 const pixman_color_t
*color
,
874 const pixman_box32_t
*boxes
)
876 pixman_image_t
*solid
;
880 _pixman_image_validate (dest
);
882 if (color
->alpha
== 0xffff)
884 if (op
== PIXMAN_OP_OVER
)
888 if (op
== PIXMAN_OP_CLEAR
)
900 if (op
== PIXMAN_OP_SRC
)
904 if (color_to_pixel (color
, &pixel
, dest
->bits
.format
))
906 pixman_region32_t fill_region
;
908 pixman_box32_t
*rects
;
910 if (!pixman_region32_init_rects (&fill_region
, boxes
, n_boxes
))
913 if (dest
->common
.have_clip_region
)
915 if (!pixman_region32_intersect (&fill_region
,
917 &dest
->common
.clip_region
))
921 rects
= pixman_region32_rectangles (&fill_region
, &n_rects
);
922 for (j
= 0; j
< n_rects
; ++j
)
924 const pixman_box32_t
*rect
= &(rects
[j
]);
925 pixman_fill (dest
->bits
.bits
, dest
->bits
.rowstride
, PIXMAN_FORMAT_BPP (dest
->bits
.format
),
926 rect
->x1
, rect
->y1
, rect
->x2
- rect
->x1
, rect
->y2
- rect
->y1
,
930 pixman_region32_fini (&fill_region
);
935 solid
= pixman_image_create_solid_fill (color
);
939 for (i
= 0; i
< n_boxes
; ++i
)
941 const pixman_box32_t
*box
= &(boxes
[i
]);
943 pixman_image_composite32 (op
, solid
, NULL
, dest
,
946 box
->x2
- box
->x1
, box
->y2
- box
->y1
);
949 pixman_image_unref (solid
);
957 * Returns the version of the pixman library encoded in a single
958 * integer as per %PIXMAN_VERSION_ENCODE. The encoding ensures that
959 * later versions compare greater than earlier versions.
961 * A run-time comparison to check that pixman's version is greater than
962 * or equal to version X.Y.Z could be performed as follows:
964 * <informalexample><programlisting>
965 * if (pixman_version() >= PIXMAN_VERSION_ENCODE(X,Y,Z)) {...}
966 * </programlisting></informalexample>
968 * See also pixman_version_string() as well as the compile-time
969 * equivalents %PIXMAN_VERSION and %PIXMAN_VERSION_STRING.
971 * Return value: the encoded version.
974 pixman_version (void)
976 return PIXMAN_VERSION
;
980 * pixman_version_string:
982 * Returns the version of the pixman library as a human-readable string
983 * of the form "X.Y.Z".
985 * See also pixman_version() as well as the compile-time equivalents
986 * %PIXMAN_VERSION_STRING and %PIXMAN_VERSION.
988 * Return value: a string containing the version.
990 PIXMAN_EXPORT
const char*
991 pixman_version_string (void)
993 return PIXMAN_VERSION_STRING
;
997 * pixman_format_supported_source:
998 * @format: A pixman_format_code_t format
1000 * Return value: whether the provided format code is a supported
1001 * format for a pixman surface used as a source in
1004 * Currently, all pixman_format_code_t values are supported.
1006 PIXMAN_EXPORT pixman_bool_t
1007 pixman_format_supported_source (pixman_format_code_t format
)
1011 /* 32 bpp formats */
1012 case PIXMAN_a2b10g10r10
:
1013 case PIXMAN_x2b10g10r10
:
1014 case PIXMAN_a2r10g10b10
:
1015 case PIXMAN_x2r10g10b10
:
1016 case PIXMAN_a8r8g8b8
:
1017 case PIXMAN_a8r8g8b8_sRGB
:
1018 case PIXMAN_x8r8g8b8
:
1019 case PIXMAN_a8b8g8r8
:
1020 case PIXMAN_x8b8g8r8
:
1021 case PIXMAN_b8g8r8a8
:
1022 case PIXMAN_b8g8r8x8
:
1023 case PIXMAN_r8g8b8a8
:
1024 case PIXMAN_r8g8b8x8
:
1029 case PIXMAN_x14r6g6b6
:
1030 /* 16 bpp formats */
1031 case PIXMAN_a1r5g5b5
:
1032 case PIXMAN_x1r5g5b5
:
1033 case PIXMAN_a1b5g5r5
:
1034 case PIXMAN_x1b5g5r5
:
1035 case PIXMAN_a4r4g4b4
:
1036 case PIXMAN_x4r4g4b4
:
1037 case PIXMAN_a4b4g4r4
:
1038 case PIXMAN_x4b4g4r4
:
1043 case PIXMAN_a2r2g2b2
:
1044 case PIXMAN_a2b2g2r2
:
1048 /* Collides with PIXMAN_c8
1051 /* Collides with PIXMAN_g8
1058 case PIXMAN_a1r1g1b1
:
1059 case PIXMAN_a1b1g1r1
:
1076 * pixman_format_supported_destination:
1077 * @format: A pixman_format_code_t format
1079 * Return value: whether the provided format code is a supported
1080 * format for a pixman surface used as a destination in
1083 * Currently, all pixman_format_code_t values are supported
1084 * except for the YUV formats.
1086 PIXMAN_EXPORT pixman_bool_t
1087 pixman_format_supported_destination (pixman_format_code_t format
)
1089 /* YUV formats cannot be written to at the moment */
1090 if (format
== PIXMAN_yuy2
|| format
== PIXMAN_yv12
)
1093 return pixman_format_supported_source (format
);
1096 PIXMAN_EXPORT pixman_bool_t
1097 pixman_compute_composite_region (pixman_region16_t
* region
,
1098 pixman_image_t
* src_image
,
1099 pixman_image_t
* mask_image
,
1100 pixman_image_t
* dest_image
,
1110 pixman_region32_t r32
;
1111 pixman_bool_t retval
;
1113 pixman_region32_init (&r32
);
1115 retval
= _pixman_compute_composite_region32 (
1116 &r32
, src_image
, mask_image
, dest_image
,
1117 src_x
, src_y
, mask_x
, mask_y
, dest_x
, dest_y
,
1122 if (!pixman_region16_copy_from_region32 (region
, &r32
))
1126 pixman_region32_fini (&r32
);