2 * Copyright © 2009 Red Hat, Inc.
3 * Copyright © 2000 SuSE, Inc.
4 * Copyright © 2007 Red Hat, Inc.
5 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc.
6 * 2005 Lars Knoll & Zack Rusin, Trolltech
7 * 2008 Aaron Plattner, NVIDIA Corporation
9 * Permission to use, copy, modify, distribute, and sell this software and its
10 * documentation for any purpose is hereby granted without fee, provided that
11 * the above copyright notice appear in all copies and that both that
12 * copyright notice and this permission notice appear in supporting
13 * documentation, and that the name of Red Hat not be used in advertising or
14 * publicity pertaining to distribution of the software without specific,
15 * written prior permission. Red Hat makes no representations about the
16 * suitability of this software for any purpose. It is provided "as is"
17 * without express or implied warranty.
19 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
20 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
21 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
23 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
24 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
25 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
38 #include "pixman-private.h"
41 general_iter_init (pixman_iter_t
*iter
, const pixman_iter_info_t
*info
)
43 pixman_image_t
*image
= iter
->image
;
48 if ((iter
->iter_flags
& ITER_SRC
) == ITER_SRC
)
49 _pixman_bits_image_src_iter_init (image
, iter
);
51 _pixman_bits_image_dest_iter_init (image
, iter
);
55 _pixman_linear_gradient_iter_init (image
, iter
);
59 _pixman_radial_gradient_iter_init (image
, iter
);
63 _pixman_conical_gradient_iter_init (image
, iter
);
67 _pixman_log_error (FUNC
, "Solid image not handled by noop");
71 _pixman_log_error (FUNC
, "Pixman bug: unknown image type\n");
76 static const pixman_iter_info_t general_iters
[] =
78 { PIXMAN_any
, 0, 0, general_iter_init
, NULL
, NULL
},
82 typedef struct op_info_t op_info_t
;
88 #define ITER_IGNORE_BOTH \
89 (ITER_IGNORE_ALPHA | ITER_IGNORE_RGB | ITER_LOCALIZED_ALPHA)
91 static const op_info_t op_flags
[PIXMAN_N_OPERATORS
] =
94 { ITER_IGNORE_BOTH
, ITER_IGNORE_BOTH
}, /* CLEAR */
95 { ITER_LOCALIZED_ALPHA
, ITER_IGNORE_BOTH
}, /* SRC */
96 { ITER_IGNORE_BOTH
, ITER_LOCALIZED_ALPHA
}, /* DST */
97 { 0, ITER_LOCALIZED_ALPHA
}, /* OVER */
98 { ITER_LOCALIZED_ALPHA
, 0 }, /* OVER_REVERSE */
99 { ITER_LOCALIZED_ALPHA
, ITER_IGNORE_RGB
}, /* IN */
100 { ITER_IGNORE_RGB
, ITER_LOCALIZED_ALPHA
}, /* IN_REVERSE */
101 { ITER_LOCALIZED_ALPHA
, ITER_IGNORE_RGB
}, /* OUT */
102 { ITER_IGNORE_RGB
, ITER_LOCALIZED_ALPHA
}, /* OUT_REVERSE */
104 { 0, 0 }, /* ATOP_REVERSE */
106 { ITER_LOCALIZED_ALPHA
, ITER_LOCALIZED_ALPHA
}, /* ADD */
107 { 0, 0 }, /* SATURATE */
110 #define SCANLINE_BUFFER_LENGTH 8192
113 operator_needs_division (pixman_op_t op
)
115 static const uint8_t needs_division
[] =
117 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, /* SATURATE */
118 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* DISJOINT */
119 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, /* CONJOINT */
120 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0, /* blend ops */
123 return needs_division
[op
];
127 general_composite_rect (pixman_implementation_t
*imp
,
128 pixman_composite_info_t
*info
)
130 PIXMAN_COMPOSITE_ARGS (info
);
131 uint8_t stack_scanline_buffer
[3 * SCANLINE_BUFFER_LENGTH
];
132 uint8_t *scanline_buffer
= (uint8_t *) stack_scanline_buffer
;
133 uint8_t *src_buffer
, *mask_buffer
, *dest_buffer
;
134 pixman_iter_t src_iter
, mask_iter
, dest_iter
;
135 pixman_combine_32_func_t compose
;
136 pixman_bool_t component_alpha
;
137 iter_flags_t width_flag
, src_iter_flags
;
141 if ((src_image
->common
.flags
& FAST_PATH_NARROW_FORMAT
) &&
142 (!mask_image
|| mask_image
->common
.flags
& FAST_PATH_NARROW_FORMAT
) &&
143 (dest_image
->common
.flags
& FAST_PATH_NARROW_FORMAT
) &&
144 !(operator_needs_division (op
)))
146 width_flag
= ITER_NARROW
;
151 width_flag
= ITER_WIDE
;
155 #define ALIGN(addr) \
156 ((uint8_t *)((((uintptr_t)(addr)) + 15) & (~15)))
158 if (width
<= 0 || _pixman_multiply_overflows_int (width
, Bpp
* 3))
161 if (width
* Bpp
* 3 > sizeof (stack_scanline_buffer
) - 15 * 3)
163 scanline_buffer
= pixman_malloc_ab_plus_c (width
, Bpp
* 3, 15 * 3);
165 if (!scanline_buffer
)
169 src_buffer
= ALIGN (scanline_buffer
);
170 mask_buffer
= ALIGN (src_buffer
+ width
* Bpp
);
171 dest_buffer
= ALIGN (mask_buffer
+ width
* Bpp
);
173 if (width_flag
== ITER_WIDE
)
175 /* To make sure there aren't any NANs in the buffers */
176 memset (src_buffer
, 0, width
* Bpp
);
177 memset (mask_buffer
, 0, width
* Bpp
);
178 memset (dest_buffer
, 0, width
* Bpp
);
182 src_iter_flags
= width_flag
| op_flags
[op
].src
| ITER_SRC
;
184 _pixman_implementation_iter_init (imp
->toplevel
, &src_iter
, src_image
,
185 src_x
, src_y
, width
, height
,
186 src_buffer
, src_iter_flags
,
190 if ((src_iter_flags
& (ITER_IGNORE_ALPHA
| ITER_IGNORE_RGB
)) ==
191 (ITER_IGNORE_ALPHA
| ITER_IGNORE_RGB
))
193 /* If it doesn't matter what the source is, then it doesn't matter
199 component_alpha
= mask_image
&& mask_image
->common
.component_alpha
;
201 _pixman_implementation_iter_init (
202 imp
->toplevel
, &mask_iter
,
203 mask_image
, mask_x
, mask_y
, width
, height
, mask_buffer
,
204 ITER_SRC
| width_flag
| (component_alpha
? 0 : ITER_IGNORE_RGB
),
208 _pixman_implementation_iter_init (
209 imp
->toplevel
, &dest_iter
, dest_image
, dest_x
, dest_y
, width
, height
,
210 dest_buffer
, ITER_DEST
| width_flag
| op_flags
[op
].dst
, info
->dest_flags
);
212 compose
= _pixman_implementation_lookup_combiner (
213 imp
->toplevel
, op
, component_alpha
, width_flag
!= ITER_WIDE
);
215 for (i
= 0; i
< height
; ++i
)
219 m
= mask_iter
.get_scanline (&mask_iter
, NULL
);
220 s
= src_iter
.get_scanline (&src_iter
, m
);
221 d
= dest_iter
.get_scanline (&dest_iter
, NULL
);
223 compose (imp
->toplevel
, op
, d
, s
, m
, width
);
225 dest_iter
.write_back (&dest_iter
);
229 src_iter
.fini (&src_iter
);
231 mask_iter
.fini (&mask_iter
);
233 dest_iter
.fini (&dest_iter
);
235 if (scanline_buffer
!= (uint8_t *) stack_scanline_buffer
)
236 free (scanline_buffer
);
239 static const pixman_fast_path_t general_fast_path
[] =
241 { PIXMAN_OP_any
, PIXMAN_any
, 0, PIXMAN_any
, 0, PIXMAN_any
, 0, general_composite_rect
},
245 pixman_implementation_t
*
246 _pixman_implementation_create_general (void)
248 pixman_implementation_t
*imp
= _pixman_implementation_create (NULL
, general_fast_path
);
250 _pixman_setup_combiner_functions_32 (imp
);
251 _pixman_setup_combiner_functions_float (imp
);
253 imp
->iter_info
= general_iters
;