|
1 /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ |
|
2 /* |
|
3 * Copyright © 2000 SuSE, Inc. |
|
4 * Copyright © 2007 Red Hat, Inc. |
|
5 * |
|
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. |
|
15 * |
|
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. |
|
22 * |
|
23 * Author: Keith Packard, SuSE, Inc. |
|
24 */ |
|
25 |
|
26 #ifndef PIXMAN_FAST_PATH_H__ |
|
27 #define PIXMAN_FAST_PATH_H__ |
|
28 |
|
29 #include "pixman-private.h" |
|
30 |
|
31 #define PIXMAN_REPEAT_COVER -1 |
|
32 |
|
33 static force_inline pixman_bool_t |
|
34 repeat (pixman_repeat_t repeat, int *c, int size) |
|
35 { |
|
36 if (repeat == PIXMAN_REPEAT_NONE) |
|
37 { |
|
38 if (*c < 0 || *c >= size) |
|
39 return FALSE; |
|
40 } |
|
41 else if (repeat == PIXMAN_REPEAT_NORMAL) |
|
42 { |
|
43 while (*c >= size) |
|
44 *c -= size; |
|
45 while (*c < 0) |
|
46 *c += size; |
|
47 } |
|
48 else if (repeat == PIXMAN_REPEAT_PAD) |
|
49 { |
|
50 *c = CLIP (*c, 0, size - 1); |
|
51 } |
|
52 else /* REFLECT */ |
|
53 { |
|
54 *c = MOD (*c, size * 2); |
|
55 if (*c >= size) |
|
56 *c = size * 2 - *c - 1; |
|
57 } |
|
58 return TRUE; |
|
59 } |
|
60 |
|
61 /* |
|
62 * For each scanline fetched from source image with PAD repeat: |
|
63 * - calculate how many pixels need to be padded on the left side |
|
64 * - calculate how many pixels need to be padded on the right side |
|
65 * - update width to only count pixels which are fetched from the image |
|
66 * All this information is returned via 'width', 'left_pad', 'right_pad' |
|
67 * arguments. The code is assuming that 'unit_x' is positive. |
|
68 * |
|
69 * Note: 64-bit math is used in order to avoid potential overflows, which |
|
70 * is probably excessive in many cases. This particular function |
|
71 * may need its own correctness test and performance tuning. |
|
72 */ |
|
73 static force_inline void |
|
74 pad_repeat_get_scanline_bounds (int32_t source_image_width, |
|
75 pixman_fixed_t vx, |
|
76 pixman_fixed_t unit_x, |
|
77 int32_t * width, |
|
78 int32_t * left_pad, |
|
79 int32_t * right_pad) |
|
80 { |
|
81 int64_t max_vx = (int64_t) source_image_width << 16; |
|
82 int64_t tmp; |
|
83 if (vx < 0) |
|
84 { |
|
85 tmp = ((int64_t) unit_x - 1 - vx) / unit_x; |
|
86 if (tmp > *width) |
|
87 { |
|
88 *left_pad = *width; |
|
89 *width = 0; |
|
90 } |
|
91 else |
|
92 { |
|
93 *left_pad = (int32_t) tmp; |
|
94 *width -= (int32_t) tmp; |
|
95 } |
|
96 } |
|
97 else |
|
98 { |
|
99 *left_pad = 0; |
|
100 } |
|
101 tmp = ((int64_t) unit_x - 1 - vx + max_vx) / unit_x - *left_pad; |
|
102 if (tmp < 0) |
|
103 { |
|
104 *right_pad = *width; |
|
105 *width = 0; |
|
106 } |
|
107 else if (tmp >= *width) |
|
108 { |
|
109 *right_pad = 0; |
|
110 } |
|
111 else |
|
112 { |
|
113 *right_pad = *width - (int32_t) tmp; |
|
114 *width = (int32_t) tmp; |
|
115 } |
|
116 } |
|
117 |
|
118 /* A macroified version of specialized nearest scalers for some |
|
119 * common 8888 and 565 formats. It supports SRC and OVER ops. |
|
120 * |
|
121 * There are two repeat versions, one that handles repeat normal, |
|
122 * and one without repeat handling that only works if the src region |
|
123 * used is completely covered by the pre-repeated source samples. |
|
124 * |
|
125 * The loops are unrolled to process two pixels per iteration for better |
|
126 * performance on most CPU architectures (superscalar processors |
|
127 * can issue several operations simultaneously, other processors can hide |
|
128 * instructions latencies by pipelining operations). Unrolling more |
|
129 * does not make much sense because the compiler will start running out |
|
130 * of spare registers soon. |
|
131 */ |
|
132 |
|
133 #define GET_8888_ALPHA(s) ((s) >> 24) |
|
134 /* This is not actually used since we don't have an OVER with |
|
135 565 source, but it is needed to build. */ |
|
136 #define GET_0565_ALPHA(s) 0xff |
|
137 |
|
138 #define FAST_NEAREST_SCANLINE(scanline_func_name, SRC_FORMAT, DST_FORMAT, \ |
|
139 src_type_t, dst_type_t, OP, repeat_mode) \ |
|
140 static force_inline void \ |
|
141 scanline_func_name (dst_type_t *dst, \ |
|
142 const src_type_t *src, \ |
|
143 int32_t w, \ |
|
144 pixman_fixed_t vx, \ |
|
145 pixman_fixed_t unit_x, \ |
|
146 pixman_fixed_t max_vx, \ |
|
147 pixman_bool_t fully_transparent_src) \ |
|
148 { \ |
|
149 uint32_t d; \ |
|
150 src_type_t s1, s2; \ |
|
151 uint8_t a1, a2; \ |
|
152 int x1, x2; \ |
|
153 \ |
|
154 if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER && fully_transparent_src) \ |
|
155 return; \ |
|
156 \ |
|
157 if (PIXMAN_OP_ ## OP != PIXMAN_OP_SRC && PIXMAN_OP_ ## OP != PIXMAN_OP_OVER) \ |
|
158 abort(); \ |
|
159 \ |
|
160 while ((w -= 2) >= 0) \ |
|
161 { \ |
|
162 x1 = vx >> 16; \ |
|
163 vx += unit_x; \ |
|
164 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
|
165 { \ |
|
166 /* This works because we know that unit_x is positive */ \ |
|
167 while (vx >= max_vx) \ |
|
168 vx -= max_vx; \ |
|
169 } \ |
|
170 s1 = src[x1]; \ |
|
171 \ |
|
172 x2 = vx >> 16; \ |
|
173 vx += unit_x; \ |
|
174 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
|
175 { \ |
|
176 /* This works because we know that unit_x is positive */ \ |
|
177 while (vx >= max_vx) \ |
|
178 vx -= max_vx; \ |
|
179 } \ |
|
180 s2 = src[x2]; \ |
|
181 \ |
|
182 if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \ |
|
183 { \ |
|
184 a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \ |
|
185 a2 = GET_ ## SRC_FORMAT ## _ALPHA(s2); \ |
|
186 \ |
|
187 if (a1 == 0xff) \ |
|
188 { \ |
|
189 *dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ |
|
190 } \ |
|
191 else if (s1) \ |
|
192 { \ |
|
193 d = CONVERT_ ## DST_FORMAT ## _TO_8888 (*dst); \ |
|
194 s1 = CONVERT_ ## SRC_FORMAT ## _TO_8888 (s1); \ |
|
195 a1 ^= 0xff; \ |
|
196 UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \ |
|
197 *dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \ |
|
198 } \ |
|
199 dst++; \ |
|
200 \ |
|
201 if (a2 == 0xff) \ |
|
202 { \ |
|
203 *dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \ |
|
204 } \ |
|
205 else if (s2) \ |
|
206 { \ |
|
207 d = CONVERT_## DST_FORMAT ## _TO_8888 (*dst); \ |
|
208 s2 = CONVERT_## SRC_FORMAT ## _TO_8888 (s2); \ |
|
209 a2 ^= 0xff; \ |
|
210 UN8x4_MUL_UN8_ADD_UN8x4 (d, a2, s2); \ |
|
211 *dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \ |
|
212 } \ |
|
213 dst++; \ |
|
214 } \ |
|
215 else /* PIXMAN_OP_SRC */ \ |
|
216 { \ |
|
217 *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ |
|
218 *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \ |
|
219 } \ |
|
220 } \ |
|
221 \ |
|
222 if (w & 1) \ |
|
223 { \ |
|
224 x1 = vx >> 16; \ |
|
225 s1 = src[x1]; \ |
|
226 \ |
|
227 if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \ |
|
228 { \ |
|
229 a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \ |
|
230 \ |
|
231 if (a1 == 0xff) \ |
|
232 { \ |
|
233 *dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ |
|
234 } \ |
|
235 else if (s1) \ |
|
236 { \ |
|
237 d = CONVERT_## DST_FORMAT ## _TO_8888 (*dst); \ |
|
238 s1 = CONVERT_ ## SRC_FORMAT ## _TO_8888 (s1); \ |
|
239 a1 ^= 0xff; \ |
|
240 UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \ |
|
241 *dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \ |
|
242 } \ |
|
243 dst++; \ |
|
244 } \ |
|
245 else /* PIXMAN_OP_SRC */ \ |
|
246 { \ |
|
247 *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ |
|
248 } \ |
|
249 } \ |
|
250 } |
|
251 |
|
252 #define FAST_NEAREST_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
|
253 dst_type_t, repeat_mode, have_mask, mask_is_solid) \ |
|
254 static void \ |
|
255 fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp, \ |
|
256 pixman_op_t op, \ |
|
257 pixman_image_t * src_image, \ |
|
258 pixman_image_t * mask_image, \ |
|
259 pixman_image_t * dst_image, \ |
|
260 int32_t src_x, \ |
|
261 int32_t src_y, \ |
|
262 int32_t mask_x, \ |
|
263 int32_t mask_y, \ |
|
264 int32_t dst_x, \ |
|
265 int32_t dst_y, \ |
|
266 int32_t width, \ |
|
267 int32_t height) \ |
|
268 { \ |
|
269 dst_type_t *dst_line; \ |
|
270 mask_type_t *mask_line; \ |
|
271 src_type_t *src_first_line; \ |
|
272 int y; \ |
|
273 pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */ \ |
|
274 pixman_fixed_t max_vy; \ |
|
275 pixman_vector_t v; \ |
|
276 pixman_fixed_t vx, vy; \ |
|
277 pixman_fixed_t unit_x, unit_y; \ |
|
278 int32_t left_pad, right_pad; \ |
|
279 \ |
|
280 src_type_t *src; \ |
|
281 dst_type_t *dst; \ |
|
282 mask_type_t solid_mask; \ |
|
283 const mask_type_t *mask = &solid_mask; \ |
|
284 int src_stride, mask_stride, dst_stride; \ |
|
285 \ |
|
286 PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1); \ |
|
287 if (have_mask) \ |
|
288 { \ |
|
289 if (mask_is_solid) \ |
|
290 solid_mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format); \ |
|
291 else \ |
|
292 PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t, \ |
|
293 mask_stride, mask_line, 1); \ |
|
294 } \ |
|
295 /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \ |
|
296 * transformed from destination space to source space */ \ |
|
297 PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \ |
|
298 \ |
|
299 /* reference point is the center of the pixel */ \ |
|
300 v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \ |
|
301 v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \ |
|
302 v.vector[2] = pixman_fixed_1; \ |
|
303 \ |
|
304 if (!pixman_transform_point_3d (src_image->common.transform, &v)) \ |
|
305 return; \ |
|
306 \ |
|
307 unit_x = src_image->common.transform->matrix[0][0]; \ |
|
308 unit_y = src_image->common.transform->matrix[1][1]; \ |
|
309 \ |
|
310 /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ \ |
|
311 v.vector[0] -= pixman_fixed_e; \ |
|
312 v.vector[1] -= pixman_fixed_e; \ |
|
313 \ |
|
314 vx = v.vector[0]; \ |
|
315 vy = v.vector[1]; \ |
|
316 \ |
|
317 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
|
318 { \ |
|
319 /* Clamp repeating positions inside the actual samples */ \ |
|
320 max_vx = src_image->bits.width << 16; \ |
|
321 max_vy = src_image->bits.height << 16; \ |
|
322 \ |
|
323 repeat (PIXMAN_REPEAT_NORMAL, &vx, max_vx); \ |
|
324 repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \ |
|
325 } \ |
|
326 \ |
|
327 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \ |
|
328 PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
|
329 { \ |
|
330 pad_repeat_get_scanline_bounds (src_image->bits.width, vx, unit_x, \ |
|
331 &width, &left_pad, &right_pad); \ |
|
332 vx += left_pad * unit_x; \ |
|
333 } \ |
|
334 \ |
|
335 while (--height >= 0) \ |
|
336 { \ |
|
337 dst = dst_line; \ |
|
338 dst_line += dst_stride; \ |
|
339 if (have_mask && !mask_is_solid) \ |
|
340 { \ |
|
341 mask = mask_line; \ |
|
342 mask_line += mask_stride; \ |
|
343 } \ |
|
344 \ |
|
345 y = vy >> 16; \ |
|
346 vy += unit_y; \ |
|
347 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
|
348 repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \ |
|
349 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ |
|
350 { \ |
|
351 repeat (PIXMAN_REPEAT_PAD, &y, src_image->bits.height); \ |
|
352 src = src_first_line + src_stride * y; \ |
|
353 if (left_pad > 0) \ |
|
354 { \ |
|
355 scanline_func (mask, dst, src, left_pad, 0, 0, 0, FALSE); \ |
|
356 } \ |
|
357 if (width > 0) \ |
|
358 { \ |
|
359 scanline_func (mask + (mask_is_solid ? 0 : left_pad), \ |
|
360 dst + left_pad, src, width, vx, unit_x, 0, FALSE); \ |
|
361 } \ |
|
362 if (right_pad > 0) \ |
|
363 { \ |
|
364 scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \ |
|
365 dst + left_pad + width, src + src_image->bits.width - 1, \ |
|
366 right_pad, 0, 0, 0, FALSE); \ |
|
367 } \ |
|
368 } \ |
|
369 else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
|
370 { \ |
|
371 static const src_type_t zero[1] = { 0 }; \ |
|
372 if (y < 0 || y >= src_image->bits.height) \ |
|
373 { \ |
|
374 scanline_func (mask, dst, zero, left_pad + width + right_pad, 0, 0, 0, TRUE); \ |
|
375 continue; \ |
|
376 } \ |
|
377 src = src_first_line + src_stride * y; \ |
|
378 if (left_pad > 0) \ |
|
379 { \ |
|
380 scanline_func (mask, dst, zero, left_pad, 0, 0, 0, TRUE); \ |
|
381 } \ |
|
382 if (width > 0) \ |
|
383 { \ |
|
384 scanline_func (mask + (mask_is_solid ? 0 : left_pad), \ |
|
385 dst + left_pad, src, width, vx, unit_x, 0, FALSE); \ |
|
386 } \ |
|
387 if (right_pad > 0) \ |
|
388 { \ |
|
389 scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \ |
|
390 dst + left_pad + width, zero, right_pad, 0, 0, 0, TRUE); \ |
|
391 } \ |
|
392 } \ |
|
393 else \ |
|
394 { \ |
|
395 src = src_first_line + src_stride * y; \ |
|
396 scanline_func (mask, dst, src, width, vx, unit_x, max_vx, FALSE); \ |
|
397 } \ |
|
398 } \ |
|
399 } |
|
400 |
|
401 /* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */ |
|
402 #define FAST_NEAREST_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
|
403 dst_type_t, repeat_mode, have_mask, mask_is_solid) \ |
|
404 FAST_NEAREST_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
|
405 dst_type_t, repeat_mode, have_mask, mask_is_solid) |
|
406 |
|
407 #define FAST_NEAREST_MAINLOOP_NOMASK(scale_func_name, scanline_func, src_type_t, dst_type_t, \ |
|
408 repeat_mode) \ |
|
409 static force_inline void \ |
|
410 scanline_func##scale_func_name##_wrapper ( \ |
|
411 const uint8_t *mask, \ |
|
412 dst_type_t *dst, \ |
|
413 const src_type_t *src, \ |
|
414 int32_t w, \ |
|
415 pixman_fixed_t vx, \ |
|
416 pixman_fixed_t unit_x, \ |
|
417 pixman_fixed_t max_vx, \ |
|
418 pixman_bool_t fully_transparent_src) \ |
|
419 { \ |
|
420 scanline_func (dst, src, w, vx, unit_x, max_vx, fully_transparent_src); \ |
|
421 } \ |
|
422 FAST_NEAREST_MAINLOOP_INT (scale_func_name, scanline_func##scale_func_name##_wrapper, \ |
|
423 src_type_t, uint8_t, dst_type_t, repeat_mode, FALSE, FALSE) |
|
424 |
|
425 #define FAST_NEAREST_MAINLOOP(scale_func_name, scanline_func, src_type_t, dst_type_t, \ |
|
426 repeat_mode) \ |
|
427 FAST_NEAREST_MAINLOOP_NOMASK(_ ## scale_func_name, scanline_func, src_type_t, \ |
|
428 dst_type_t, repeat_mode) |
|
429 |
|
430 #define FAST_NEAREST(scale_func_name, SRC_FORMAT, DST_FORMAT, \ |
|
431 src_type_t, dst_type_t, OP, repeat_mode) \ |
|
432 FAST_NEAREST_SCANLINE(scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \ |
|
433 SRC_FORMAT, DST_FORMAT, src_type_t, dst_type_t, \ |
|
434 OP, repeat_mode) \ |
|
435 FAST_NEAREST_MAINLOOP_NOMASK(_ ## scale_func_name ## _ ## OP, \ |
|
436 scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \ |
|
437 src_type_t, dst_type_t, repeat_mode) |
|
438 |
|
439 |
|
440 #define SCALED_NEAREST_FLAGS \ |
|
441 (FAST_PATH_SCALE_TRANSFORM | \ |
|
442 FAST_PATH_NO_ALPHA_MAP | \ |
|
443 FAST_PATH_NEAREST_FILTER | \ |
|
444 FAST_PATH_NO_ACCESSORS | \ |
|
445 FAST_PATH_NARROW_FORMAT) |
|
446 |
|
447 #define SIMPLE_NEAREST_FAST_PATH_NORMAL(op,s,d,func) \ |
|
448 { PIXMAN_OP_ ## op, \ |
|
449 PIXMAN_ ## s, \ |
|
450 (SCALED_NEAREST_FLAGS | \ |
|
451 FAST_PATH_NORMAL_REPEAT | \ |
|
452 FAST_PATH_X_UNIT_POSITIVE), \ |
|
453 PIXMAN_null, 0, \ |
|
454 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
455 fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ |
|
456 } |
|
457 |
|
458 #define SIMPLE_NEAREST_FAST_PATH_PAD(op,s,d,func) \ |
|
459 { PIXMAN_OP_ ## op, \ |
|
460 PIXMAN_ ## s, \ |
|
461 (SCALED_NEAREST_FLAGS | \ |
|
462 FAST_PATH_PAD_REPEAT | \ |
|
463 FAST_PATH_X_UNIT_POSITIVE), \ |
|
464 PIXMAN_null, 0, \ |
|
465 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
466 fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ |
|
467 } |
|
468 |
|
469 #define SIMPLE_NEAREST_FAST_PATH_NONE(op,s,d,func) \ |
|
470 { PIXMAN_OP_ ## op, \ |
|
471 PIXMAN_ ## s, \ |
|
472 (SCALED_NEAREST_FLAGS | \ |
|
473 FAST_PATH_NONE_REPEAT | \ |
|
474 FAST_PATH_X_UNIT_POSITIVE), \ |
|
475 PIXMAN_null, 0, \ |
|
476 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
477 fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ |
|
478 } |
|
479 |
|
480 #define SIMPLE_NEAREST_FAST_PATH_COVER(op,s,d,func) \ |
|
481 { PIXMAN_OP_ ## op, \ |
|
482 PIXMAN_ ## s, \ |
|
483 SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ |
|
484 PIXMAN_null, 0, \ |
|
485 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
486 fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ |
|
487 } |
|
488 |
|
489 #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL(op,s,d,func) \ |
|
490 { PIXMAN_OP_ ## op, \ |
|
491 PIXMAN_ ## s, \ |
|
492 (SCALED_NEAREST_FLAGS | \ |
|
493 FAST_PATH_NORMAL_REPEAT | \ |
|
494 FAST_PATH_X_UNIT_POSITIVE), \ |
|
495 PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
|
496 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
497 fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ |
|
498 } |
|
499 |
|
500 #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD(op,s,d,func) \ |
|
501 { PIXMAN_OP_ ## op, \ |
|
502 PIXMAN_ ## s, \ |
|
503 (SCALED_NEAREST_FLAGS | \ |
|
504 FAST_PATH_PAD_REPEAT | \ |
|
505 FAST_PATH_X_UNIT_POSITIVE), \ |
|
506 PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
|
507 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
508 fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ |
|
509 } |
|
510 |
|
511 #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE(op,s,d,func) \ |
|
512 { PIXMAN_OP_ ## op, \ |
|
513 PIXMAN_ ## s, \ |
|
514 (SCALED_NEAREST_FLAGS | \ |
|
515 FAST_PATH_NONE_REPEAT | \ |
|
516 FAST_PATH_X_UNIT_POSITIVE), \ |
|
517 PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
|
518 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
519 fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ |
|
520 } |
|
521 |
|
522 #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER(op,s,d,func) \ |
|
523 { PIXMAN_OP_ ## op, \ |
|
524 PIXMAN_ ## s, \ |
|
525 SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ |
|
526 PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
|
527 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
528 fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ |
|
529 } |
|
530 |
|
531 #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL(op,s,d,func) \ |
|
532 { PIXMAN_OP_ ## op, \ |
|
533 PIXMAN_ ## s, \ |
|
534 (SCALED_NEAREST_FLAGS | \ |
|
535 FAST_PATH_NORMAL_REPEAT | \ |
|
536 FAST_PATH_X_UNIT_POSITIVE), \ |
|
537 PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
|
538 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
539 fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ |
|
540 } |
|
541 |
|
542 #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD(op,s,d,func) \ |
|
543 { PIXMAN_OP_ ## op, \ |
|
544 PIXMAN_ ## s, \ |
|
545 (SCALED_NEAREST_FLAGS | \ |
|
546 FAST_PATH_PAD_REPEAT | \ |
|
547 FAST_PATH_X_UNIT_POSITIVE), \ |
|
548 PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
|
549 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
550 fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ |
|
551 } |
|
552 |
|
553 #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE(op,s,d,func) \ |
|
554 { PIXMAN_OP_ ## op, \ |
|
555 PIXMAN_ ## s, \ |
|
556 (SCALED_NEAREST_FLAGS | \ |
|
557 FAST_PATH_NONE_REPEAT | \ |
|
558 FAST_PATH_X_UNIT_POSITIVE), \ |
|
559 PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
|
560 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
561 fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ |
|
562 } |
|
563 |
|
564 #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER(op,s,d,func) \ |
|
565 { PIXMAN_OP_ ## op, \ |
|
566 PIXMAN_ ## s, \ |
|
567 SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ |
|
568 PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
|
569 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
570 fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ |
|
571 } |
|
572 |
|
573 /* Prefer the use of 'cover' variant, because it is faster */ |
|
574 #define SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \ |
|
575 SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \ |
|
576 SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \ |
|
577 SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func), \ |
|
578 SIMPLE_NEAREST_FAST_PATH_NORMAL (op,s,d,func) |
|
579 |
|
580 #define SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \ |
|
581 SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \ |
|
582 SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \ |
|
583 SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func) |
|
584 |
|
585 #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH(op,s,d,func) \ |
|
586 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \ |
|
587 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \ |
|
588 SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func) |
|
589 |
|
590 /*****************************************************************************/ |
|
591 |
|
592 /* |
|
593 * Identify 5 zones in each scanline for bilinear scaling. Depending on |
|
594 * whether 2 pixels to be interpolated are fetched from the image itself, |
|
595 * from the padding area around it or from both image and padding area. |
|
596 */ |
|
597 static force_inline void |
|
598 bilinear_pad_repeat_get_scanline_bounds (int32_t source_image_width, |
|
599 pixman_fixed_t vx, |
|
600 pixman_fixed_t unit_x, |
|
601 int32_t * left_pad, |
|
602 int32_t * left_tz, |
|
603 int32_t * width, |
|
604 int32_t * right_tz, |
|
605 int32_t * right_pad) |
|
606 { |
|
607 int width1 = *width, left_pad1, right_pad1; |
|
608 int width2 = *width, left_pad2, right_pad2; |
|
609 |
|
610 pad_repeat_get_scanline_bounds (source_image_width, vx, unit_x, |
|
611 &width1, &left_pad1, &right_pad1); |
|
612 pad_repeat_get_scanline_bounds (source_image_width, vx + pixman_fixed_1, |
|
613 unit_x, &width2, &left_pad2, &right_pad2); |
|
614 |
|
615 *left_pad = left_pad2; |
|
616 *left_tz = left_pad1 - left_pad2; |
|
617 *right_tz = right_pad2 - right_pad1; |
|
618 *right_pad = right_pad1; |
|
619 *width -= *left_pad + *left_tz + *right_tz + *right_pad; |
|
620 } |
|
621 |
|
622 /* |
|
623 * Main loop template for single pass bilinear scaling. It needs to be |
|
624 * provided with 'scanline_func' which should do the compositing operation. |
|
625 * The needed function has the following prototype: |
|
626 * |
|
627 * scanline_func (dst_type_t * dst, |
|
628 * const mask_type_ * mask, |
|
629 * const src_type_t * src_top, |
|
630 * const src_type_t * src_bottom, |
|
631 * int32_t width, |
|
632 * int weight_top, |
|
633 * int weight_bottom, |
|
634 * pixman_fixed_t vx, |
|
635 * pixman_fixed_t unit_x, |
|
636 * pixman_fixed_t max_vx, |
|
637 * pixman_bool_t zero_src) |
|
638 * |
|
639 * Where: |
|
640 * dst - destination scanline buffer for storing results |
|
641 * mask - mask buffer (or single value for solid mask) |
|
642 * src_top, src_bottom - two source scanlines |
|
643 * width - number of pixels to process |
|
644 * weight_top - weight of the top row for interpolation |
|
645 * weight_bottom - weight of the bottom row for interpolation |
|
646 * vx - initial position for fetching the first pair of |
|
647 * pixels from the source buffer |
|
648 * unit_x - position increment needed to move to the next pair |
|
649 * of pixels |
|
650 * max_vx - image size as a fixed point value, can be used for |
|
651 * implementing NORMAL repeat (when it is supported) |
|
652 * zero_src - boolean hint variable, which is set to TRUE when |
|
653 * all source pixels are fetched from zero padding |
|
654 * zone for NONE repeat |
|
655 * |
|
656 * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to 256, |
|
657 * but sometimes it may be less than that for NONE repeat when handling |
|
658 * fuzzy antialiased top or bottom image edges. Also both top and |
|
659 * bottom weight variables are guaranteed to have value in 0-255 |
|
660 * range and can fit into unsigned byte or be used with 8-bit SIMD |
|
661 * multiplication instructions. |
|
662 */ |
|
663 #define FAST_BILINEAR_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
|
664 dst_type_t, repeat_mode, have_mask, mask_is_solid) \ |
|
665 static void \ |
|
666 fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, \ |
|
667 pixman_op_t op, \ |
|
668 pixman_image_t * src_image, \ |
|
669 pixman_image_t * mask_image, \ |
|
670 pixman_image_t * dst_image, \ |
|
671 int32_t src_x, \ |
|
672 int32_t src_y, \ |
|
673 int32_t mask_x, \ |
|
674 int32_t mask_y, \ |
|
675 int32_t dst_x, \ |
|
676 int32_t dst_y, \ |
|
677 int32_t width, \ |
|
678 int32_t height) \ |
|
679 { \ |
|
680 dst_type_t *dst_line; \ |
|
681 mask_type_t *mask_line; \ |
|
682 src_type_t *src_first_line; \ |
|
683 int y1, y2; \ |
|
684 pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */ \ |
|
685 pixman_vector_t v; \ |
|
686 pixman_fixed_t vx, vy; \ |
|
687 pixman_fixed_t unit_x, unit_y; \ |
|
688 int32_t left_pad, left_tz, right_tz, right_pad; \ |
|
689 \ |
|
690 dst_type_t *dst; \ |
|
691 mask_type_t solid_mask; \ |
|
692 const mask_type_t *mask = &solid_mask; \ |
|
693 int src_stride, mask_stride, dst_stride; \ |
|
694 \ |
|
695 PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1); \ |
|
696 if (have_mask) \ |
|
697 { \ |
|
698 if (mask_is_solid) \ |
|
699 { \ |
|
700 solid_mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format); \ |
|
701 mask_stride = 0; \ |
|
702 } \ |
|
703 else \ |
|
704 { \ |
|
705 PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t, \ |
|
706 mask_stride, mask_line, 1); \ |
|
707 } \ |
|
708 } \ |
|
709 /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \ |
|
710 * transformed from destination space to source space */ \ |
|
711 PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \ |
|
712 \ |
|
713 /* reference point is the center of the pixel */ \ |
|
714 v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \ |
|
715 v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \ |
|
716 v.vector[2] = pixman_fixed_1; \ |
|
717 \ |
|
718 if (!pixman_transform_point_3d (src_image->common.transform, &v)) \ |
|
719 return; \ |
|
720 \ |
|
721 unit_x = src_image->common.transform->matrix[0][0]; \ |
|
722 unit_y = src_image->common.transform->matrix[1][1]; \ |
|
723 \ |
|
724 v.vector[0] -= pixman_fixed_1 / 2; \ |
|
725 v.vector[1] -= pixman_fixed_1 / 2; \ |
|
726 \ |
|
727 vy = v.vector[1]; \ |
|
728 \ |
|
729 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \ |
|
730 PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
|
731 { \ |
|
732 bilinear_pad_repeat_get_scanline_bounds (src_image->bits.width, v.vector[0], unit_x, \ |
|
733 &left_pad, &left_tz, &width, &right_tz, &right_pad); \ |
|
734 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ |
|
735 { \ |
|
736 /* PAD repeat does not need special handling for 'transition zones' and */ \ |
|
737 /* they can be combined with 'padding zones' safely */ \ |
|
738 left_pad += left_tz; \ |
|
739 right_pad += right_tz; \ |
|
740 left_tz = right_tz = 0; \ |
|
741 } \ |
|
742 v.vector[0] += left_pad * unit_x; \ |
|
743 } \ |
|
744 \ |
|
745 while (--height >= 0) \ |
|
746 { \ |
|
747 int weight1, weight2; \ |
|
748 dst = dst_line; \ |
|
749 dst_line += dst_stride; \ |
|
750 vx = v.vector[0]; \ |
|
751 if (have_mask && !mask_is_solid) \ |
|
752 { \ |
|
753 mask = mask_line; \ |
|
754 mask_line += mask_stride; \ |
|
755 } \ |
|
756 \ |
|
757 y1 = pixman_fixed_to_int (vy); \ |
|
758 weight2 = (vy >> 8) & 0xff; \ |
|
759 if (weight2) \ |
|
760 { \ |
|
761 /* normal case, both row weights are in 0-255 range and fit unsigned byte */ \ |
|
762 y2 = y1 + 1; \ |
|
763 weight1 = 256 - weight2; \ |
|
764 } \ |
|
765 else \ |
|
766 { \ |
|
767 /* set both top and bottom row to the same scanline, and weights to 128+128 */ \ |
|
768 y2 = y1; \ |
|
769 weight1 = weight2 = 128; \ |
|
770 } \ |
|
771 vy += unit_y; \ |
|
772 if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ |
|
773 { \ |
|
774 src_type_t *src1, *src2; \ |
|
775 src_type_t buf1[2]; \ |
|
776 src_type_t buf2[2]; \ |
|
777 repeat (PIXMAN_REPEAT_PAD, &y1, src_image->bits.height); \ |
|
778 repeat (PIXMAN_REPEAT_PAD, &y2, src_image->bits.height); \ |
|
779 src1 = src_first_line + src_stride * y1; \ |
|
780 src2 = src_first_line + src_stride * y2; \ |
|
781 \ |
|
782 if (left_pad > 0) \ |
|
783 { \ |
|
784 buf1[0] = buf1[1] = src1[0]; \ |
|
785 buf2[0] = buf2[1] = src2[0]; \ |
|
786 scanline_func (dst, mask, \ |
|
787 buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, FALSE); \ |
|
788 dst += left_pad; \ |
|
789 if (have_mask && !mask_is_solid) \ |
|
790 mask += left_pad; \ |
|
791 } \ |
|
792 if (width > 0) \ |
|
793 { \ |
|
794 scanline_func (dst, mask, \ |
|
795 src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \ |
|
796 dst += width; \ |
|
797 if (have_mask && !mask_is_solid) \ |
|
798 mask += width; \ |
|
799 } \ |
|
800 if (right_pad > 0) \ |
|
801 { \ |
|
802 buf1[0] = buf1[1] = src1[src_image->bits.width - 1]; \ |
|
803 buf2[0] = buf2[1] = src2[src_image->bits.width - 1]; \ |
|
804 scanline_func (dst, mask, \ |
|
805 buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, FALSE); \ |
|
806 } \ |
|
807 } \ |
|
808 else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
|
809 { \ |
|
810 src_type_t *src1, *src2; \ |
|
811 src_type_t buf1[2]; \ |
|
812 src_type_t buf2[2]; \ |
|
813 /* handle top/bottom zero padding by just setting weights to 0 if needed */ \ |
|
814 if (y1 < 0) \ |
|
815 { \ |
|
816 weight1 = 0; \ |
|
817 y1 = 0; \ |
|
818 } \ |
|
819 if (y1 >= src_image->bits.height) \ |
|
820 { \ |
|
821 weight1 = 0; \ |
|
822 y1 = src_image->bits.height - 1; \ |
|
823 } \ |
|
824 if (y2 < 0) \ |
|
825 { \ |
|
826 weight2 = 0; \ |
|
827 y2 = 0; \ |
|
828 } \ |
|
829 if (y2 >= src_image->bits.height) \ |
|
830 { \ |
|
831 weight2 = 0; \ |
|
832 y2 = src_image->bits.height - 1; \ |
|
833 } \ |
|
834 src1 = src_first_line + src_stride * y1; \ |
|
835 src2 = src_first_line + src_stride * y2; \ |
|
836 \ |
|
837 if (left_pad > 0) \ |
|
838 { \ |
|
839 buf1[0] = buf1[1] = 0; \ |
|
840 buf2[0] = buf2[1] = 0; \ |
|
841 scanline_func (dst, mask, \ |
|
842 buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, TRUE); \ |
|
843 dst += left_pad; \ |
|
844 if (have_mask && !mask_is_solid) \ |
|
845 mask += left_pad; \ |
|
846 } \ |
|
847 if (left_tz > 0) \ |
|
848 { \ |
|
849 buf1[0] = 0; \ |
|
850 buf1[1] = src1[0]; \ |
|
851 buf2[0] = 0; \ |
|
852 buf2[1] = src2[0]; \ |
|
853 scanline_func (dst, mask, \ |
|
854 buf1, buf2, left_tz, weight1, weight2, \ |
|
855 pixman_fixed_frac (vx), unit_x, 0, FALSE); \ |
|
856 dst += left_tz; \ |
|
857 if (have_mask && !mask_is_solid) \ |
|
858 mask += left_tz; \ |
|
859 vx += left_tz * unit_x; \ |
|
860 } \ |
|
861 if (width > 0) \ |
|
862 { \ |
|
863 scanline_func (dst, mask, \ |
|
864 src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \ |
|
865 dst += width; \ |
|
866 if (have_mask && !mask_is_solid) \ |
|
867 mask += width; \ |
|
868 vx += width * unit_x; \ |
|
869 } \ |
|
870 if (right_tz > 0) \ |
|
871 { \ |
|
872 buf1[0] = src1[src_image->bits.width - 1]; \ |
|
873 buf1[1] = 0; \ |
|
874 buf2[0] = src2[src_image->bits.width - 1]; \ |
|
875 buf2[1] = 0; \ |
|
876 scanline_func (dst, mask, \ |
|
877 buf1, buf2, right_tz, weight1, weight2, \ |
|
878 pixman_fixed_frac (vx), unit_x, 0, FALSE); \ |
|
879 dst += right_tz; \ |
|
880 if (have_mask && !mask_is_solid) \ |
|
881 mask += right_tz; \ |
|
882 } \ |
|
883 if (right_pad > 0) \ |
|
884 { \ |
|
885 buf1[0] = buf1[1] = 0; \ |
|
886 buf2[0] = buf2[1] = 0; \ |
|
887 scanline_func (dst, mask, \ |
|
888 buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, TRUE); \ |
|
889 } \ |
|
890 } \ |
|
891 else \ |
|
892 { \ |
|
893 scanline_func (dst, mask, src_first_line + src_stride * y1, \ |
|
894 src_first_line + src_stride * y2, width, \ |
|
895 weight1, weight2, vx, unit_x, max_vx, FALSE); \ |
|
896 } \ |
|
897 } \ |
|
898 } |
|
899 |
|
900 /* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */ |
|
901 #define FAST_BILINEAR_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
|
902 dst_type_t, repeat_mode, have_mask, mask_is_solid) \ |
|
903 FAST_BILINEAR_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t,\ |
|
904 dst_type_t, repeat_mode, have_mask, mask_is_solid) |
|
905 |
|
906 #define SCALED_BILINEAR_FLAGS \ |
|
907 (FAST_PATH_SCALE_TRANSFORM | \ |
|
908 FAST_PATH_NO_ALPHA_MAP | \ |
|
909 FAST_PATH_BILINEAR_FILTER | \ |
|
910 FAST_PATH_NO_ACCESSORS | \ |
|
911 FAST_PATH_NARROW_FORMAT) |
|
912 |
|
913 #define SIMPLE_BILINEAR_FAST_PATH_PAD(op,s,d,func) \ |
|
914 { PIXMAN_OP_ ## op, \ |
|
915 PIXMAN_ ## s, \ |
|
916 (SCALED_BILINEAR_FLAGS | \ |
|
917 FAST_PATH_PAD_REPEAT | \ |
|
918 FAST_PATH_X_UNIT_POSITIVE), \ |
|
919 PIXMAN_null, 0, \ |
|
920 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
921 fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ |
|
922 } |
|
923 |
|
924 #define SIMPLE_BILINEAR_FAST_PATH_NONE(op,s,d,func) \ |
|
925 { PIXMAN_OP_ ## op, \ |
|
926 PIXMAN_ ## s, \ |
|
927 (SCALED_BILINEAR_FLAGS | \ |
|
928 FAST_PATH_NONE_REPEAT | \ |
|
929 FAST_PATH_X_UNIT_POSITIVE), \ |
|
930 PIXMAN_null, 0, \ |
|
931 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
932 fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ |
|
933 } |
|
934 |
|
935 #define SIMPLE_BILINEAR_FAST_PATH_COVER(op,s,d,func) \ |
|
936 { PIXMAN_OP_ ## op, \ |
|
937 PIXMAN_ ## s, \ |
|
938 SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ |
|
939 PIXMAN_null, 0, \ |
|
940 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
941 fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ |
|
942 } |
|
943 |
|
944 #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD(op,s,d,func) \ |
|
945 { PIXMAN_OP_ ## op, \ |
|
946 PIXMAN_ ## s, \ |
|
947 (SCALED_BILINEAR_FLAGS | \ |
|
948 FAST_PATH_PAD_REPEAT | \ |
|
949 FAST_PATH_X_UNIT_POSITIVE), \ |
|
950 PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
|
951 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
952 fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ |
|
953 } |
|
954 |
|
955 #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE(op,s,d,func) \ |
|
956 { PIXMAN_OP_ ## op, \ |
|
957 PIXMAN_ ## s, \ |
|
958 (SCALED_BILINEAR_FLAGS | \ |
|
959 FAST_PATH_NONE_REPEAT | \ |
|
960 FAST_PATH_X_UNIT_POSITIVE), \ |
|
961 PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
|
962 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
963 fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ |
|
964 } |
|
965 |
|
966 #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER(op,s,d,func) \ |
|
967 { PIXMAN_OP_ ## op, \ |
|
968 PIXMAN_ ## s, \ |
|
969 SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ |
|
970 PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
|
971 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
972 fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ |
|
973 } |
|
974 |
|
975 #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD(op,s,d,func) \ |
|
976 { PIXMAN_OP_ ## op, \ |
|
977 PIXMAN_ ## s, \ |
|
978 (SCALED_BILINEAR_FLAGS | \ |
|
979 FAST_PATH_PAD_REPEAT | \ |
|
980 FAST_PATH_X_UNIT_POSITIVE), \ |
|
981 PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
|
982 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
983 fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ |
|
984 } |
|
985 |
|
986 #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE(op,s,d,func) \ |
|
987 { PIXMAN_OP_ ## op, \ |
|
988 PIXMAN_ ## s, \ |
|
989 (SCALED_BILINEAR_FLAGS | \ |
|
990 FAST_PATH_NONE_REPEAT | \ |
|
991 FAST_PATH_X_UNIT_POSITIVE), \ |
|
992 PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
|
993 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
994 fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ |
|
995 } |
|
996 |
|
997 #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER(op,s,d,func) \ |
|
998 { PIXMAN_OP_ ## op, \ |
|
999 PIXMAN_ ## s, \ |
|
1000 SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ |
|
1001 PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
|
1002 PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
|
1003 fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ |
|
1004 } |
|
1005 |
|
1006 /* Prefer the use of 'cover' variant, because it is faster */ |
|
1007 #define SIMPLE_BILINEAR_FAST_PATH(op,s,d,func) \ |
|
1008 SIMPLE_BILINEAR_FAST_PATH_COVER (op,s,d,func), \ |
|
1009 SIMPLE_BILINEAR_FAST_PATH_NONE (op,s,d,func), \ |
|
1010 SIMPLE_BILINEAR_FAST_PATH_PAD (op,s,d,func) |
|
1011 |
|
1012 #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH(op,s,d,func) \ |
|
1013 SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER (op,s,d,func), \ |
|
1014 SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE (op,s,d,func), \ |
|
1015 SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD (op,s,d,func) |
|
1016 |
|
1017 #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH(op,s,d,func) \ |
|
1018 SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \ |
|
1019 SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \ |
|
1020 SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD (op,s,d,func) |
|
1021 |
|
1022 #endif |