Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1891 | serge | 1 | /* |
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 |
||
8 | * |
||
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. |
||
18 | * |
||
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 |
||
26 | * SOFTWARE. |
||
27 | */ |
||
28 | #ifdef HAVE_CONFIG_H |
||
29 | #include |
||
30 | #endif |
||
31 | #include |
||
32 | #include |
||
33 | #include |
||
34 | #include |
||
35 | #include |
||
36 | #include |
||
37 | #include |
||
38 | #include "pixman-private.h" |
||
39 | #include "pixman-combine32.h" |
||
40 | #include "pixman-private.h" |
||
41 | |||
42 | #define SCANLINE_BUFFER_LENGTH 8192 |
||
43 | |||
44 | static void |
||
45 | general_composite_rect (pixman_implementation_t *imp, |
||
46 | pixman_op_t op, |
||
47 | pixman_image_t * src, |
||
48 | pixman_image_t * mask, |
||
49 | pixman_image_t * dest, |
||
50 | int32_t src_x, |
||
51 | int32_t src_y, |
||
52 | int32_t mask_x, |
||
53 | int32_t mask_y, |
||
54 | int32_t dest_x, |
||
55 | int32_t dest_y, |
||
56 | int32_t width, |
||
57 | int32_t height) |
||
58 | { |
||
59 | uint64_t stack_scanline_buffer[(SCANLINE_BUFFER_LENGTH * 3 + 7) / 8]; |
||
60 | uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; |
||
61 | uint8_t *src_buffer, *mask_buffer, *dest_buffer; |
||
62 | fetch_scanline_t fetch_src = NULL, fetch_mask = NULL, fetch_dest = NULL; |
||
63 | pixman_combine_32_func_t compose; |
||
64 | store_scanline_t store; |
||
65 | source_image_class_t src_class, mask_class; |
||
66 | pixman_bool_t component_alpha; |
||
67 | uint32_t *bits; |
||
68 | int32_t stride; |
||
69 | int narrow, Bpp; |
||
70 | int i; |
||
71 | |||
72 | narrow = |
||
73 | (src->common.flags & FAST_PATH_NARROW_FORMAT) && |
||
74 | (!mask || mask->common.flags & FAST_PATH_NARROW_FORMAT) && |
||
75 | (dest->common.flags & FAST_PATH_NARROW_FORMAT); |
||
76 | Bpp = narrow ? 4 : 8; |
||
77 | |||
78 | if (width * Bpp > SCANLINE_BUFFER_LENGTH) |
||
79 | { |
||
80 | scanline_buffer = pixman_malloc_abc (width, 3, Bpp); |
||
81 | |||
82 | if (!scanline_buffer) |
||
83 | return; |
||
84 | } |
||
85 | |||
86 | src_buffer = scanline_buffer; |
||
87 | mask_buffer = src_buffer + width * Bpp; |
||
88 | dest_buffer = mask_buffer + width * Bpp; |
||
89 | |||
90 | src_class = _pixman_image_classify (src, |
||
91 | src_x, src_y, |
||
92 | width, height); |
||
93 | |||
94 | mask_class = SOURCE_IMAGE_CLASS_UNKNOWN; |
||
95 | |||
96 | if (mask) |
||
97 | { |
||
98 | mask_class = _pixman_image_classify (mask, |
||
99 | src_x, src_y, |
||
100 | width, height); |
||
101 | } |
||
102 | |||
103 | if (op == PIXMAN_OP_CLEAR) |
||
104 | fetch_src = NULL; |
||
105 | else if (narrow) |
||
106 | fetch_src = _pixman_image_get_scanline_32; |
||
107 | else |
||
108 | fetch_src = _pixman_image_get_scanline_64; |
||
109 | |||
110 | if (!mask || op == PIXMAN_OP_CLEAR) |
||
111 | fetch_mask = NULL; |
||
112 | else if (narrow) |
||
113 | fetch_mask = _pixman_image_get_scanline_32; |
||
114 | else |
||
115 | fetch_mask = _pixman_image_get_scanline_64; |
||
116 | |||
117 | if (op == PIXMAN_OP_CLEAR || op == PIXMAN_OP_SRC) |
||
118 | fetch_dest = NULL; |
||
119 | else if (narrow) |
||
120 | fetch_dest = _pixman_image_get_scanline_32; |
||
121 | else |
||
122 | fetch_dest = _pixman_image_get_scanline_64; |
||
123 | |||
124 | if (narrow) |
||
125 | store = _pixman_image_store_scanline_32; |
||
126 | else |
||
127 | store = _pixman_image_store_scanline_64; |
||
128 | |||
129 | /* Skip the store step and composite directly into the |
||
130 | * destination if the output format of the compose func matches |
||
131 | * the destination format. |
||
132 | * |
||
133 | * If the destination format is a8r8g8b8 then we can always do |
||
134 | * this. If it is x8r8g8b8, then we can only do it if the |
||
135 | * operator doesn't make use of destination alpha. |
||
136 | */ |
||
137 | if ((dest->bits.format == PIXMAN_a8r8g8b8) || |
||
138 | (dest->bits.format == PIXMAN_x8r8g8b8 && |
||
139 | (op == PIXMAN_OP_OVER || |
||
140 | op == PIXMAN_OP_ADD || |
||
141 | op == PIXMAN_OP_SRC || |
||
142 | op == PIXMAN_OP_CLEAR || |
||
143 | op == PIXMAN_OP_IN_REVERSE || |
||
144 | op == PIXMAN_OP_OUT_REVERSE || |
||
145 | op == PIXMAN_OP_DST))) |
||
146 | { |
||
147 | if (narrow && |
||
148 | !dest->common.alpha_map && |
||
149 | !dest->bits.write_func) |
||
150 | { |
||
151 | store = NULL; |
||
152 | } |
||
153 | } |
||
154 | |||
155 | if (!store) |
||
156 | { |
||
157 | bits = dest->bits.bits; |
||
158 | stride = dest->bits.rowstride; |
||
159 | } |
||
160 | else |
||
161 | { |
||
162 | bits = NULL; |
||
163 | stride = 0; |
||
164 | } |
||
165 | |||
166 | component_alpha = |
||
167 | fetch_src && |
||
168 | fetch_mask && |
||
169 | mask && |
||
170 | mask->common.type == BITS && |
||
171 | mask->common.component_alpha && |
||
172 | PIXMAN_FORMAT_RGB (mask->bits.format); |
||
173 | |||
174 | if (narrow) |
||
175 | { |
||
176 | if (component_alpha) |
||
177 | compose = _pixman_implementation_combine_32_ca; |
||
178 | else |
||
179 | compose = _pixman_implementation_combine_32; |
||
180 | } |
||
181 | else |
||
182 | { |
||
183 | if (component_alpha) |
||
184 | compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64_ca; |
||
185 | else |
||
186 | compose = (pixman_combine_32_func_t)_pixman_implementation_combine_64; |
||
187 | } |
||
188 | |||
189 | if (!compose) |
||
190 | return; |
||
191 | |||
192 | if (!fetch_mask) |
||
193 | mask_buffer = NULL; |
||
194 | |||
195 | for (i = 0; i < height; ++i) |
||
196 | { |
||
197 | /* fill first half of scanline with source */ |
||
198 | if (fetch_src) |
||
199 | { |
||
200 | if (fetch_mask) |
||
201 | { |
||
202 | /* fetch mask before source so that fetching of |
||
203 | source can be optimized */ |
||
204 | fetch_mask (mask, mask_x, mask_y + i, |
||
205 | width, (void *)mask_buffer, 0); |
||
206 | |||
207 | if (mask_class == SOURCE_IMAGE_CLASS_HORIZONTAL) |
||
208 | fetch_mask = NULL; |
||
209 | } |
||
210 | |||
211 | if (src_class == SOURCE_IMAGE_CLASS_HORIZONTAL) |
||
212 | { |
||
213 | fetch_src (src, src_x, src_y + i, |
||
214 | width, (void *)src_buffer, 0); |
||
215 | fetch_src = NULL; |
||
216 | } |
||
217 | else |
||
218 | { |
||
219 | fetch_src (src, src_x, src_y + i, |
||
220 | width, (void *)src_buffer, (void *)mask_buffer); |
||
221 | } |
||
222 | } |
||
223 | else if (fetch_mask) |
||
224 | { |
||
225 | fetch_mask (mask, mask_x, mask_y + i, |
||
226 | width, (void *)mask_buffer, 0); |
||
227 | } |
||
228 | |||
229 | if (store) |
||
230 | { |
||
231 | /* fill dest into second half of scanline */ |
||
232 | if (fetch_dest) |
||
233 | { |
||
234 | fetch_dest (dest, dest_x, dest_y + i, |
||
235 | width, (void *)dest_buffer, 0); |
||
236 | } |
||
237 | |||
238 | /* blend */ |
||
239 | compose (imp->toplevel, op, |
||
240 | (void *)dest_buffer, |
||
241 | (void *)src_buffer, |
||
242 | (void *)mask_buffer, |
||
243 | width); |
||
244 | |||
245 | /* write back */ |
||
246 | store (&(dest->bits), dest_x, dest_y + i, width, |
||
247 | (void *)dest_buffer); |
||
248 | } |
||
249 | else |
||
250 | { |
||
251 | /* blend */ |
||
252 | compose (imp->toplevel, op, |
||
253 | bits + (dest_y + i) * stride + dest_x, |
||
254 | (void *)src_buffer, (void *)mask_buffer, width); |
||
255 | } |
||
256 | } |
||
257 | |||
258 | if (scanline_buffer != (uint8_t *) stack_scanline_buffer) |
||
259 | free (scanline_buffer); |
||
260 | } |
||
261 | |||
262 | static const pixman_fast_path_t general_fast_path[] = |
||
263 | { |
||
264 | { PIXMAN_OP_any, PIXMAN_any, 0, PIXMAN_any, 0, PIXMAN_any, 0, general_composite_rect }, |
||
265 | { PIXMAN_OP_NONE } |
||
266 | }; |
||
267 | |||
268 | static pixman_bool_t |
||
269 | general_blt (pixman_implementation_t *imp, |
||
270 | uint32_t * src_bits, |
||
271 | uint32_t * dst_bits, |
||
272 | int src_stride, |
||
273 | int dst_stride, |
||
274 | int src_bpp, |
||
275 | int dst_bpp, |
||
276 | int src_x, |
||
277 | int src_y, |
||
278 | int dst_x, |
||
279 | int dst_y, |
||
280 | int width, |
||
281 | int height) |
||
282 | { |
||
283 | /* We can't blit unless we have sse2 or mmx */ |
||
284 | |||
285 | return FALSE; |
||
286 | } |
||
287 | |||
288 | static pixman_bool_t |
||
289 | general_fill (pixman_implementation_t *imp, |
||
290 | uint32_t * bits, |
||
291 | int stride, |
||
292 | int bpp, |
||
293 | int x, |
||
294 | int y, |
||
295 | int width, |
||
296 | int height, |
||
297 | uint32_t xor) |
||
298 | { |
||
299 | return FALSE; |
||
300 | } |
||
301 | |||
302 | pixman_implementation_t * |
||
303 | _pixman_implementation_create_general (void) |
||
304 | { |
||
305 | pixman_implementation_t *imp = _pixman_implementation_create (NULL, general_fast_path); |
||
306 | |||
307 | _pixman_setup_combiner_functions_32 (imp); |
||
308 | _pixman_setup_combiner_functions_64 (imp); |
||
309 | |||
310 | imp->blt = general_blt; |
||
311 | imp->fill = general_fill; |
||
312 | |||
313 | return imp; |
||
314 | }> |
||
315 |