Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ |
michael@0 | 2 | /* |
michael@0 | 3 | * Copyright © 2000 SuSE, Inc. |
michael@0 | 4 | * Copyright © 2007 Red Hat, Inc. |
michael@0 | 5 | * |
michael@0 | 6 | * Permission to use, copy, modify, distribute, and sell this software and its |
michael@0 | 7 | * documentation for any purpose is hereby granted without fee, provided that |
michael@0 | 8 | * the above copyright notice appear in all copies and that both that |
michael@0 | 9 | * copyright notice and this permission notice appear in supporting |
michael@0 | 10 | * documentation, and that the name of SuSE not be used in advertising or |
michael@0 | 11 | * publicity pertaining to distribution of the software without specific, |
michael@0 | 12 | * written prior permission. SuSE makes no representations about the |
michael@0 | 13 | * suitability of this software for any purpose. It is provided "as is" |
michael@0 | 14 | * without express or implied warranty. |
michael@0 | 15 | * |
michael@0 | 16 | * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL |
michael@0 | 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE |
michael@0 | 18 | * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
michael@0 | 19 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
michael@0 | 20 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
michael@0 | 21 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
michael@0 | 22 | * |
michael@0 | 23 | * Author: Keith Packard, SuSE, Inc. |
michael@0 | 24 | */ |
michael@0 | 25 | |
michael@0 | 26 | #ifndef PIXMAN_FAST_PATH_H__ |
michael@0 | 27 | #define PIXMAN_FAST_PATH_H__ |
michael@0 | 28 | |
michael@0 | 29 | #include "pixman-private.h" |
michael@0 | 30 | |
michael@0 | 31 | #define PIXMAN_REPEAT_COVER -1 |
michael@0 | 32 | |
michael@0 | 33 | /* Flags describing input parameters to fast path macro template. |
michael@0 | 34 | * Turning on some flag values may indicate that |
michael@0 | 35 | * "some property X is available so template can use this" or |
michael@0 | 36 | * "some property X should be handled by template". |
michael@0 | 37 | * |
michael@0 | 38 | * FLAG_HAVE_SOLID_MASK |
michael@0 | 39 | * Input mask is solid so template should handle this. |
michael@0 | 40 | * |
michael@0 | 41 | * FLAG_HAVE_NON_SOLID_MASK |
michael@0 | 42 | * Input mask is bits mask so template should handle this. |
michael@0 | 43 | * |
michael@0 | 44 | * FLAG_HAVE_SOLID_MASK and FLAG_HAVE_NON_SOLID_MASK are mutually |
michael@0 | 45 | * exclusive. (It's not allowed to turn both flags on) |
michael@0 | 46 | */ |
michael@0 | 47 | #define FLAG_NONE (0) |
michael@0 | 48 | #define FLAG_HAVE_SOLID_MASK (1 << 1) |
michael@0 | 49 | #define FLAG_HAVE_NON_SOLID_MASK (1 << 2) |
michael@0 | 50 | |
michael@0 | 51 | /* To avoid too short repeated scanline function calls, extend source |
michael@0 | 52 | * scanlines having width less than below constant value. |
michael@0 | 53 | */ |
michael@0 | 54 | #define REPEAT_NORMAL_MIN_WIDTH 64 |
michael@0 | 55 | |
michael@0 | 56 | static force_inline pixman_bool_t |
michael@0 | 57 | repeat (pixman_repeat_t repeat, int *c, int size) |
michael@0 | 58 | { |
michael@0 | 59 | if (repeat == PIXMAN_REPEAT_NONE) |
michael@0 | 60 | { |
michael@0 | 61 | if (*c < 0 || *c >= size) |
michael@0 | 62 | return FALSE; |
michael@0 | 63 | } |
michael@0 | 64 | else if (repeat == PIXMAN_REPEAT_NORMAL) |
michael@0 | 65 | { |
michael@0 | 66 | while (*c >= size) |
michael@0 | 67 | *c -= size; |
michael@0 | 68 | while (*c < 0) |
michael@0 | 69 | *c += size; |
michael@0 | 70 | } |
michael@0 | 71 | else if (repeat == PIXMAN_REPEAT_PAD) |
michael@0 | 72 | { |
michael@0 | 73 | *c = CLIP (*c, 0, size - 1); |
michael@0 | 74 | } |
michael@0 | 75 | else /* REFLECT */ |
michael@0 | 76 | { |
michael@0 | 77 | *c = MOD (*c, size * 2); |
michael@0 | 78 | if (*c >= size) |
michael@0 | 79 | *c = size * 2 - *c - 1; |
michael@0 | 80 | } |
michael@0 | 81 | return TRUE; |
michael@0 | 82 | } |
michael@0 | 83 | |
michael@0 | 84 | static force_inline int |
michael@0 | 85 | pixman_fixed_to_bilinear_weight (pixman_fixed_t x) |
michael@0 | 86 | { |
michael@0 | 87 | return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) & |
michael@0 | 88 | ((1 << BILINEAR_INTERPOLATION_BITS) - 1); |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | #if BILINEAR_INTERPOLATION_BITS <= 4 |
michael@0 | 92 | /* Inspired by Filter_32_opaque from Skia */ |
michael@0 | 93 | static force_inline uint32_t |
michael@0 | 94 | bilinear_interpolation (uint32_t tl, uint32_t tr, |
michael@0 | 95 | uint32_t bl, uint32_t br, |
michael@0 | 96 | int distx, int disty) |
michael@0 | 97 | { |
michael@0 | 98 | int distxy, distxiy, distixy, distixiy; |
michael@0 | 99 | uint32_t lo, hi; |
michael@0 | 100 | |
michael@0 | 101 | distx <<= (4 - BILINEAR_INTERPOLATION_BITS); |
michael@0 | 102 | disty <<= (4 - BILINEAR_INTERPOLATION_BITS); |
michael@0 | 103 | |
michael@0 | 104 | distxy = distx * disty; |
michael@0 | 105 | distxiy = (distx << 4) - distxy; /* distx * (16 - disty) */ |
michael@0 | 106 | distixy = (disty << 4) - distxy; /* disty * (16 - distx) */ |
michael@0 | 107 | distixiy = |
michael@0 | 108 | 16 * 16 - (disty << 4) - |
michael@0 | 109 | (distx << 4) + distxy; /* (16 - distx) * (16 - disty) */ |
michael@0 | 110 | |
michael@0 | 111 | lo = (tl & 0xff00ff) * distixiy; |
michael@0 | 112 | hi = ((tl >> 8) & 0xff00ff) * distixiy; |
michael@0 | 113 | |
michael@0 | 114 | lo += (tr & 0xff00ff) * distxiy; |
michael@0 | 115 | hi += ((tr >> 8) & 0xff00ff) * distxiy; |
michael@0 | 116 | |
michael@0 | 117 | lo += (bl & 0xff00ff) * distixy; |
michael@0 | 118 | hi += ((bl >> 8) & 0xff00ff) * distixy; |
michael@0 | 119 | |
michael@0 | 120 | lo += (br & 0xff00ff) * distxy; |
michael@0 | 121 | hi += ((br >> 8) & 0xff00ff) * distxy; |
michael@0 | 122 | |
michael@0 | 123 | return ((lo >> 8) & 0xff00ff) | (hi & ~0xff00ff); |
michael@0 | 124 | } |
michael@0 | 125 | |
michael@0 | 126 | #else |
michael@0 | 127 | #if SIZEOF_LONG > 4 |
michael@0 | 128 | |
michael@0 | 129 | static force_inline uint32_t |
michael@0 | 130 | bilinear_interpolation (uint32_t tl, uint32_t tr, |
michael@0 | 131 | uint32_t bl, uint32_t br, |
michael@0 | 132 | int distx, int disty) |
michael@0 | 133 | { |
michael@0 | 134 | uint64_t distxy, distxiy, distixy, distixiy; |
michael@0 | 135 | uint64_t tl64, tr64, bl64, br64; |
michael@0 | 136 | uint64_t f, r; |
michael@0 | 137 | |
michael@0 | 138 | distx <<= (8 - BILINEAR_INTERPOLATION_BITS); |
michael@0 | 139 | disty <<= (8 - BILINEAR_INTERPOLATION_BITS); |
michael@0 | 140 | |
michael@0 | 141 | distxy = distx * disty; |
michael@0 | 142 | distxiy = distx * (256 - disty); |
michael@0 | 143 | distixy = (256 - distx) * disty; |
michael@0 | 144 | distixiy = (256 - distx) * (256 - disty); |
michael@0 | 145 | |
michael@0 | 146 | /* Alpha and Blue */ |
michael@0 | 147 | tl64 = tl & 0xff0000ff; |
michael@0 | 148 | tr64 = tr & 0xff0000ff; |
michael@0 | 149 | bl64 = bl & 0xff0000ff; |
michael@0 | 150 | br64 = br & 0xff0000ff; |
michael@0 | 151 | |
michael@0 | 152 | f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy; |
michael@0 | 153 | r = f & 0x0000ff0000ff0000ull; |
michael@0 | 154 | |
michael@0 | 155 | /* Red and Green */ |
michael@0 | 156 | tl64 = tl; |
michael@0 | 157 | tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull); |
michael@0 | 158 | |
michael@0 | 159 | tr64 = tr; |
michael@0 | 160 | tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull); |
michael@0 | 161 | |
michael@0 | 162 | bl64 = bl; |
michael@0 | 163 | bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull); |
michael@0 | 164 | |
michael@0 | 165 | br64 = br; |
michael@0 | 166 | br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull); |
michael@0 | 167 | |
michael@0 | 168 | f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy; |
michael@0 | 169 | r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull); |
michael@0 | 170 | |
michael@0 | 171 | return (uint32_t)(r >> 16); |
michael@0 | 172 | } |
michael@0 | 173 | |
michael@0 | 174 | #else |
michael@0 | 175 | |
michael@0 | 176 | #ifdef LOW_QUALITY_INTERPOLATION |
michael@0 | 177 | /* Based on Filter_32_opaque_portable from Skia */ |
michael@0 | 178 | static force_inline uint32_t |
michael@0 | 179 | bilinear_interpolation(uint32_t a00, uint32_t a01, |
michael@0 | 180 | uint32_t a10, uint32_t a11, |
michael@0 | 181 | int x, int y) |
michael@0 | 182 | { |
michael@0 | 183 | int xy = x * y; |
michael@0 | 184 | static const uint32_t mask = 0xff00ff; |
michael@0 | 185 | |
michael@0 | 186 | int scale = 256 - 16*y - 16*x + xy; |
michael@0 | 187 | uint32_t lo = (a00 & mask) * scale; |
michael@0 | 188 | uint32_t hi = ((a00 >> 8) & mask) * scale; |
michael@0 | 189 | |
michael@0 | 190 | scale = 16*x - xy; |
michael@0 | 191 | lo += (a01 & mask) * scale; |
michael@0 | 192 | hi += ((a01 >> 8) & mask) * scale; |
michael@0 | 193 | |
michael@0 | 194 | scale = 16*y - xy; |
michael@0 | 195 | lo += (a10 & mask) * scale; |
michael@0 | 196 | hi += ((a10 >> 8) & mask) * scale; |
michael@0 | 197 | |
michael@0 | 198 | lo += (a11 & mask) * xy; |
michael@0 | 199 | hi += ((a11 >> 8) & mask) * xy; |
michael@0 | 200 | |
michael@0 | 201 | return ((lo >> 8) & mask) | (hi & ~mask); |
michael@0 | 202 | } |
michael@0 | 203 | #else |
michael@0 | 204 | static force_inline uint32_t |
michael@0 | 205 | bilinear_interpolation (uint32_t tl, uint32_t tr, |
michael@0 | 206 | uint32_t bl, uint32_t br, |
michael@0 | 207 | int distx, int disty) |
michael@0 | 208 | { |
michael@0 | 209 | int distxy, distxiy, distixy, distixiy; |
michael@0 | 210 | uint32_t f, r; |
michael@0 | 211 | |
michael@0 | 212 | distx <<= (8 - BILINEAR_INTERPOLATION_BITS); |
michael@0 | 213 | disty <<= (8 - BILINEAR_INTERPOLATION_BITS); |
michael@0 | 214 | |
michael@0 | 215 | distxy = distx * disty; |
michael@0 | 216 | distxiy = (distx << 8) - distxy; /* distx * (256 - disty) */ |
michael@0 | 217 | distixy = (disty << 8) - distxy; /* disty * (256 - distx) */ |
michael@0 | 218 | distixiy = |
michael@0 | 219 | 256 * 256 - (disty << 8) - |
michael@0 | 220 | (distx << 8) + distxy; /* (256 - distx) * (256 - disty) */ |
michael@0 | 221 | |
michael@0 | 222 | /* Blue */ |
michael@0 | 223 | r = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy |
michael@0 | 224 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy; |
michael@0 | 225 | |
michael@0 | 226 | /* Green */ |
michael@0 | 227 | f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy |
michael@0 | 228 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy; |
michael@0 | 229 | r |= f & 0xff000000; |
michael@0 | 230 | |
michael@0 | 231 | tl >>= 16; |
michael@0 | 232 | tr >>= 16; |
michael@0 | 233 | bl >>= 16; |
michael@0 | 234 | br >>= 16; |
michael@0 | 235 | r >>= 16; |
michael@0 | 236 | |
michael@0 | 237 | /* Red */ |
michael@0 | 238 | f = (tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy |
michael@0 | 239 | + (bl & 0x000000ff) * distixy + (br & 0x000000ff) * distxy; |
michael@0 | 240 | r |= f & 0x00ff0000; |
michael@0 | 241 | |
michael@0 | 242 | /* Alpha */ |
michael@0 | 243 | f = (tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy |
michael@0 | 244 | + (bl & 0x0000ff00) * distixy + (br & 0x0000ff00) * distxy; |
michael@0 | 245 | r |= f & 0xff000000; |
michael@0 | 246 | |
michael@0 | 247 | return r; |
michael@0 | 248 | } |
michael@0 | 249 | #endif |
michael@0 | 250 | #endif |
michael@0 | 251 | #endif // BILINEAR_INTERPOLATION_BITS <= 4 |
michael@0 | 252 | |
michael@0 | 253 | /* |
michael@0 | 254 | * For each scanline fetched from source image with PAD repeat: |
michael@0 | 255 | * - calculate how many pixels need to be padded on the left side |
michael@0 | 256 | * - calculate how many pixels need to be padded on the right side |
michael@0 | 257 | * - update width to only count pixels which are fetched from the image |
michael@0 | 258 | * All this information is returned via 'width', 'left_pad', 'right_pad' |
michael@0 | 259 | * arguments. The code is assuming that 'unit_x' is positive. |
michael@0 | 260 | * |
michael@0 | 261 | * Note: 64-bit math is used in order to avoid potential overflows, which |
michael@0 | 262 | * is probably excessive in many cases. This particular function |
michael@0 | 263 | * may need its own correctness test and performance tuning. |
michael@0 | 264 | */ |
michael@0 | 265 | static force_inline void |
michael@0 | 266 | pad_repeat_get_scanline_bounds (int32_t source_image_width, |
michael@0 | 267 | pixman_fixed_t vx, |
michael@0 | 268 | pixman_fixed_t unit_x, |
michael@0 | 269 | int32_t * width, |
michael@0 | 270 | int32_t * left_pad, |
michael@0 | 271 | int32_t * right_pad) |
michael@0 | 272 | { |
michael@0 | 273 | int64_t max_vx = (int64_t) source_image_width << 16; |
michael@0 | 274 | int64_t tmp; |
michael@0 | 275 | if (vx < 0) |
michael@0 | 276 | { |
michael@0 | 277 | tmp = ((int64_t) unit_x - 1 - vx) / unit_x; |
michael@0 | 278 | if (tmp > *width) |
michael@0 | 279 | { |
michael@0 | 280 | *left_pad = *width; |
michael@0 | 281 | *width = 0; |
michael@0 | 282 | } |
michael@0 | 283 | else |
michael@0 | 284 | { |
michael@0 | 285 | *left_pad = (int32_t) tmp; |
michael@0 | 286 | *width -= (int32_t) tmp; |
michael@0 | 287 | } |
michael@0 | 288 | } |
michael@0 | 289 | else |
michael@0 | 290 | { |
michael@0 | 291 | *left_pad = 0; |
michael@0 | 292 | } |
michael@0 | 293 | tmp = ((int64_t) unit_x - 1 - vx + max_vx) / unit_x - *left_pad; |
michael@0 | 294 | if (tmp < 0) |
michael@0 | 295 | { |
michael@0 | 296 | *right_pad = *width; |
michael@0 | 297 | *width = 0; |
michael@0 | 298 | } |
michael@0 | 299 | else if (tmp >= *width) |
michael@0 | 300 | { |
michael@0 | 301 | *right_pad = 0; |
michael@0 | 302 | } |
michael@0 | 303 | else |
michael@0 | 304 | { |
michael@0 | 305 | *right_pad = *width - (int32_t) tmp; |
michael@0 | 306 | *width = (int32_t) tmp; |
michael@0 | 307 | } |
michael@0 | 308 | } |
michael@0 | 309 | |
michael@0 | 310 | /* A macroified version of specialized nearest scalers for some |
michael@0 | 311 | * common 8888 and 565 formats. It supports SRC and OVER ops. |
michael@0 | 312 | * |
michael@0 | 313 | * There are two repeat versions, one that handles repeat normal, |
michael@0 | 314 | * and one without repeat handling that only works if the src region |
michael@0 | 315 | * used is completely covered by the pre-repeated source samples. |
michael@0 | 316 | * |
michael@0 | 317 | * The loops are unrolled to process two pixels per iteration for better |
michael@0 | 318 | * performance on most CPU architectures (superscalar processors |
michael@0 | 319 | * can issue several operations simultaneously, other processors can hide |
michael@0 | 320 | * instructions latencies by pipelining operations). Unrolling more |
michael@0 | 321 | * does not make much sense because the compiler will start running out |
michael@0 | 322 | * of spare registers soon. |
michael@0 | 323 | */ |
michael@0 | 324 | |
michael@0 | 325 | #define GET_8888_ALPHA(s) ((s) >> 24) |
michael@0 | 326 | /* This is not actually used since we don't have an OVER with |
michael@0 | 327 | 565 source, but it is needed to build. */ |
michael@0 | 328 | #define GET_0565_ALPHA(s) 0xff |
michael@0 | 329 | #define GET_x888_ALPHA(s) 0xff |
michael@0 | 330 | |
michael@0 | 331 | #define FAST_NEAREST_SCANLINE(scanline_func_name, SRC_FORMAT, DST_FORMAT, \ |
michael@0 | 332 | src_type_t, dst_type_t, OP, repeat_mode) \ |
michael@0 | 333 | static force_inline void \ |
michael@0 | 334 | scanline_func_name (dst_type_t *dst, \ |
michael@0 | 335 | const src_type_t *src, \ |
michael@0 | 336 | int32_t w, \ |
michael@0 | 337 | pixman_fixed_t vx, \ |
michael@0 | 338 | pixman_fixed_t unit_x, \ |
michael@0 | 339 | pixman_fixed_t src_width_fixed, \ |
michael@0 | 340 | pixman_bool_t fully_transparent_src) \ |
michael@0 | 341 | { \ |
michael@0 | 342 | uint32_t d; \ |
michael@0 | 343 | src_type_t s1, s2; \ |
michael@0 | 344 | uint8_t a1, a2; \ |
michael@0 | 345 | int x1, x2; \ |
michael@0 | 346 | \ |
michael@0 | 347 | if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER && fully_transparent_src) \ |
michael@0 | 348 | return; \ |
michael@0 | 349 | \ |
michael@0 | 350 | if (PIXMAN_OP_ ## OP != PIXMAN_OP_SRC && PIXMAN_OP_ ## OP != PIXMAN_OP_OVER) \ |
michael@0 | 351 | abort(); \ |
michael@0 | 352 | \ |
michael@0 | 353 | while ((w -= 2) >= 0) \ |
michael@0 | 354 | { \ |
michael@0 | 355 | x1 = pixman_fixed_to_int (vx); \ |
michael@0 | 356 | vx += unit_x; \ |
michael@0 | 357 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
michael@0 | 358 | { \ |
michael@0 | 359 | /* This works because we know that unit_x is positive */ \ |
michael@0 | 360 | while (vx >= 0) \ |
michael@0 | 361 | vx -= src_width_fixed; \ |
michael@0 | 362 | } \ |
michael@0 | 363 | s1 = *(src + x1); \ |
michael@0 | 364 | \ |
michael@0 | 365 | x2 = pixman_fixed_to_int (vx); \ |
michael@0 | 366 | vx += unit_x; \ |
michael@0 | 367 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
michael@0 | 368 | { \ |
michael@0 | 369 | /* This works because we know that unit_x is positive */ \ |
michael@0 | 370 | while (vx >= 0) \ |
michael@0 | 371 | vx -= src_width_fixed; \ |
michael@0 | 372 | } \ |
michael@0 | 373 | s2 = *(src + x2); \ |
michael@0 | 374 | \ |
michael@0 | 375 | if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \ |
michael@0 | 376 | { \ |
michael@0 | 377 | a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \ |
michael@0 | 378 | a2 = GET_ ## SRC_FORMAT ## _ALPHA(s2); \ |
michael@0 | 379 | \ |
michael@0 | 380 | if (a1 == 0xff) \ |
michael@0 | 381 | { \ |
michael@0 | 382 | *dst = convert_ ## SRC_FORMAT ## _to_ ## DST_FORMAT (s1); \ |
michael@0 | 383 | } \ |
michael@0 | 384 | else if (s1) \ |
michael@0 | 385 | { \ |
michael@0 | 386 | d = convert_ ## DST_FORMAT ## _to_8888 (*dst); \ |
michael@0 | 387 | s1 = convert_ ## SRC_FORMAT ## _to_8888 (s1); \ |
michael@0 | 388 | a1 ^= 0xff; \ |
michael@0 | 389 | UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \ |
michael@0 | 390 | *dst = convert_8888_to_ ## DST_FORMAT (d); \ |
michael@0 | 391 | } \ |
michael@0 | 392 | dst++; \ |
michael@0 | 393 | \ |
michael@0 | 394 | if (a2 == 0xff) \ |
michael@0 | 395 | { \ |
michael@0 | 396 | *dst = convert_ ## SRC_FORMAT ## _to_ ## DST_FORMAT (s2); \ |
michael@0 | 397 | } \ |
michael@0 | 398 | else if (s2) \ |
michael@0 | 399 | { \ |
michael@0 | 400 | d = convert_## DST_FORMAT ## _to_8888 (*dst); \ |
michael@0 | 401 | s2 = convert_## SRC_FORMAT ## _to_8888 (s2); \ |
michael@0 | 402 | a2 ^= 0xff; \ |
michael@0 | 403 | UN8x4_MUL_UN8_ADD_UN8x4 (d, a2, s2); \ |
michael@0 | 404 | *dst = convert_8888_to_ ## DST_FORMAT (d); \ |
michael@0 | 405 | } \ |
michael@0 | 406 | dst++; \ |
michael@0 | 407 | } \ |
michael@0 | 408 | else /* PIXMAN_OP_SRC */ \ |
michael@0 | 409 | { \ |
michael@0 | 410 | *dst++ = convert_ ## SRC_FORMAT ## _to_ ## DST_FORMAT (s1); \ |
michael@0 | 411 | *dst++ = convert_ ## SRC_FORMAT ## _to_ ## DST_FORMAT (s2); \ |
michael@0 | 412 | } \ |
michael@0 | 413 | } \ |
michael@0 | 414 | \ |
michael@0 | 415 | if (w & 1) \ |
michael@0 | 416 | { \ |
michael@0 | 417 | x1 = pixman_fixed_to_int (vx); \ |
michael@0 | 418 | s1 = *(src + x1); \ |
michael@0 | 419 | \ |
michael@0 | 420 | if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \ |
michael@0 | 421 | { \ |
michael@0 | 422 | a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \ |
michael@0 | 423 | \ |
michael@0 | 424 | if (a1 == 0xff) \ |
michael@0 | 425 | { \ |
michael@0 | 426 | *dst = convert_ ## SRC_FORMAT ## _to_ ## DST_FORMAT (s1); \ |
michael@0 | 427 | } \ |
michael@0 | 428 | else if (s1) \ |
michael@0 | 429 | { \ |
michael@0 | 430 | d = convert_## DST_FORMAT ## _to_8888 (*dst); \ |
michael@0 | 431 | s1 = convert_ ## SRC_FORMAT ## _to_8888 (s1); \ |
michael@0 | 432 | a1 ^= 0xff; \ |
michael@0 | 433 | UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \ |
michael@0 | 434 | *dst = convert_8888_to_ ## DST_FORMAT (d); \ |
michael@0 | 435 | } \ |
michael@0 | 436 | dst++; \ |
michael@0 | 437 | } \ |
michael@0 | 438 | else /* PIXMAN_OP_SRC */ \ |
michael@0 | 439 | { \ |
michael@0 | 440 | *dst++ = convert_ ## SRC_FORMAT ## _to_ ## DST_FORMAT (s1); \ |
michael@0 | 441 | } \ |
michael@0 | 442 | } \ |
michael@0 | 443 | } |
michael@0 | 444 | |
michael@0 | 445 | #define FAST_NEAREST_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
michael@0 | 446 | dst_type_t, repeat_mode, have_mask, mask_is_solid) \ |
michael@0 | 447 | static void \ |
michael@0 | 448 | fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp, \ |
michael@0 | 449 | pixman_composite_info_t *info) \ |
michael@0 | 450 | { \ |
michael@0 | 451 | PIXMAN_COMPOSITE_ARGS (info); \ |
michael@0 | 452 | dst_type_t *dst_line; \ |
michael@0 | 453 | mask_type_t *mask_line; \ |
michael@0 | 454 | src_type_t *src_first_line; \ |
michael@0 | 455 | int y; \ |
michael@0 | 456 | pixman_fixed_t src_width_fixed = pixman_int_to_fixed (src_image->bits.width); \ |
michael@0 | 457 | pixman_fixed_t max_vy; \ |
michael@0 | 458 | pixman_vector_t v; \ |
michael@0 | 459 | pixman_fixed_t vx, vy; \ |
michael@0 | 460 | pixman_fixed_t unit_x, unit_y; \ |
michael@0 | 461 | int32_t left_pad, right_pad; \ |
michael@0 | 462 | \ |
michael@0 | 463 | src_type_t *src; \ |
michael@0 | 464 | dst_type_t *dst; \ |
michael@0 | 465 | mask_type_t solid_mask; \ |
michael@0 | 466 | const mask_type_t *mask = &solid_mask; \ |
michael@0 | 467 | int src_stride, mask_stride, dst_stride; \ |
michael@0 | 468 | \ |
michael@0 | 469 | PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type_t, dst_stride, dst_line, 1); \ |
michael@0 | 470 | if (have_mask) \ |
michael@0 | 471 | { \ |
michael@0 | 472 | if (mask_is_solid) \ |
michael@0 | 473 | solid_mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format); \ |
michael@0 | 474 | else \ |
michael@0 | 475 | PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t, \ |
michael@0 | 476 | mask_stride, mask_line, 1); \ |
michael@0 | 477 | } \ |
michael@0 | 478 | /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \ |
michael@0 | 479 | * transformed from destination space to source space */ \ |
michael@0 | 480 | PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \ |
michael@0 | 481 | \ |
michael@0 | 482 | /* reference point is the center of the pixel */ \ |
michael@0 | 483 | v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \ |
michael@0 | 484 | v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \ |
michael@0 | 485 | v.vector[2] = pixman_fixed_1; \ |
michael@0 | 486 | \ |
michael@0 | 487 | if (!pixman_transform_point_3d (src_image->common.transform, &v)) \ |
michael@0 | 488 | return; \ |
michael@0 | 489 | \ |
michael@0 | 490 | unit_x = src_image->common.transform->matrix[0][0]; \ |
michael@0 | 491 | unit_y = src_image->common.transform->matrix[1][1]; \ |
michael@0 | 492 | \ |
michael@0 | 493 | /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ \ |
michael@0 | 494 | v.vector[0] -= pixman_fixed_e; \ |
michael@0 | 495 | v.vector[1] -= pixman_fixed_e; \ |
michael@0 | 496 | \ |
michael@0 | 497 | vx = v.vector[0]; \ |
michael@0 | 498 | vy = v.vector[1]; \ |
michael@0 | 499 | \ |
michael@0 | 500 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
michael@0 | 501 | { \ |
michael@0 | 502 | max_vy = pixman_int_to_fixed (src_image->bits.height); \ |
michael@0 | 503 | \ |
michael@0 | 504 | /* Clamp repeating positions inside the actual samples */ \ |
michael@0 | 505 | repeat (PIXMAN_REPEAT_NORMAL, &vx, src_width_fixed); \ |
michael@0 | 506 | repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \ |
michael@0 | 507 | } \ |
michael@0 | 508 | \ |
michael@0 | 509 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \ |
michael@0 | 510 | PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
michael@0 | 511 | { \ |
michael@0 | 512 | pad_repeat_get_scanline_bounds (src_image->bits.width, vx, unit_x, \ |
michael@0 | 513 | &width, &left_pad, &right_pad); \ |
michael@0 | 514 | vx += left_pad * unit_x; \ |
michael@0 | 515 | } \ |
michael@0 | 516 | \ |
michael@0 | 517 | while (--height >= 0) \ |
michael@0 | 518 | { \ |
michael@0 | 519 | dst = dst_line; \ |
michael@0 | 520 | dst_line += dst_stride; \ |
michael@0 | 521 | if (have_mask && !mask_is_solid) \ |
michael@0 | 522 | { \ |
michael@0 | 523 | mask = mask_line; \ |
michael@0 | 524 | mask_line += mask_stride; \ |
michael@0 | 525 | } \ |
michael@0 | 526 | \ |
michael@0 | 527 | y = pixman_fixed_to_int (vy); \ |
michael@0 | 528 | vy += unit_y; \ |
michael@0 | 529 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
michael@0 | 530 | repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \ |
michael@0 | 531 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ |
michael@0 | 532 | { \ |
michael@0 | 533 | repeat (PIXMAN_REPEAT_PAD, &y, src_image->bits.height); \ |
michael@0 | 534 | src = src_first_line + src_stride * y; \ |
michael@0 | 535 | if (left_pad > 0) \ |
michael@0 | 536 | { \ |
michael@0 | 537 | scanline_func (mask, dst, \ |
michael@0 | 538 | src + src_image->bits.width - src_image->bits.width + 1, \ |
michael@0 | 539 | left_pad, -pixman_fixed_e, 0, src_width_fixed, FALSE); \ |
michael@0 | 540 | } \ |
michael@0 | 541 | if (width > 0) \ |
michael@0 | 542 | { \ |
michael@0 | 543 | scanline_func (mask + (mask_is_solid ? 0 : left_pad), \ |
michael@0 | 544 | dst + left_pad, src + src_image->bits.width, width, \ |
michael@0 | 545 | vx - src_width_fixed, unit_x, src_width_fixed, FALSE); \ |
michael@0 | 546 | } \ |
michael@0 | 547 | if (right_pad > 0) \ |
michael@0 | 548 | { \ |
michael@0 | 549 | scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \ |
michael@0 | 550 | dst + left_pad + width, src + src_image->bits.width, \ |
michael@0 | 551 | right_pad, -pixman_fixed_e, 0, src_width_fixed, FALSE); \ |
michael@0 | 552 | } \ |
michael@0 | 553 | } \ |
michael@0 | 554 | else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
michael@0 | 555 | { \ |
michael@0 | 556 | static const src_type_t zero[1] = { 0 }; \ |
michael@0 | 557 | if (y < 0 || y >= src_image->bits.height) \ |
michael@0 | 558 | { \ |
michael@0 | 559 | scanline_func (mask, dst, zero + 1, left_pad + width + right_pad, \ |
michael@0 | 560 | -pixman_fixed_e, 0, src_width_fixed, TRUE); \ |
michael@0 | 561 | continue; \ |
michael@0 | 562 | } \ |
michael@0 | 563 | src = src_first_line + src_stride * y; \ |
michael@0 | 564 | if (left_pad > 0) \ |
michael@0 | 565 | { \ |
michael@0 | 566 | scanline_func (mask, dst, zero + 1, left_pad, \ |
michael@0 | 567 | -pixman_fixed_e, 0, src_width_fixed, TRUE); \ |
michael@0 | 568 | } \ |
michael@0 | 569 | if (width > 0) \ |
michael@0 | 570 | { \ |
michael@0 | 571 | scanline_func (mask + (mask_is_solid ? 0 : left_pad), \ |
michael@0 | 572 | dst + left_pad, src + src_image->bits.width, width, \ |
michael@0 | 573 | vx - src_width_fixed, unit_x, src_width_fixed, FALSE); \ |
michael@0 | 574 | } \ |
michael@0 | 575 | if (right_pad > 0) \ |
michael@0 | 576 | { \ |
michael@0 | 577 | scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \ |
michael@0 | 578 | dst + left_pad + width, zero + 1, right_pad, \ |
michael@0 | 579 | -pixman_fixed_e, 0, src_width_fixed, TRUE); \ |
michael@0 | 580 | } \ |
michael@0 | 581 | } \ |
michael@0 | 582 | else \ |
michael@0 | 583 | { \ |
michael@0 | 584 | src = src_first_line + src_stride * y; \ |
michael@0 | 585 | scanline_func (mask, dst, src + src_image->bits.width, width, vx - src_width_fixed, \ |
michael@0 | 586 | unit_x, src_width_fixed, FALSE); \ |
michael@0 | 587 | } \ |
michael@0 | 588 | } \ |
michael@0 | 589 | } |
michael@0 | 590 | |
michael@0 | 591 | /* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */ |
michael@0 | 592 | #define FAST_NEAREST_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
michael@0 | 593 | dst_type_t, repeat_mode, have_mask, mask_is_solid) \ |
michael@0 | 594 | FAST_NEAREST_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t, \ |
michael@0 | 595 | dst_type_t, repeat_mode, have_mask, mask_is_solid) |
michael@0 | 596 | |
michael@0 | 597 | #define FAST_NEAREST_MAINLOOP_NOMASK(scale_func_name, scanline_func, src_type_t, dst_type_t, \ |
michael@0 | 598 | repeat_mode) \ |
michael@0 | 599 | static force_inline void \ |
michael@0 | 600 | scanline_func##scale_func_name##_wrapper ( \ |
michael@0 | 601 | const uint8_t *mask, \ |
michael@0 | 602 | dst_type_t *dst, \ |
michael@0 | 603 | const src_type_t *src, \ |
michael@0 | 604 | int32_t w, \ |
michael@0 | 605 | pixman_fixed_t vx, \ |
michael@0 | 606 | pixman_fixed_t unit_x, \ |
michael@0 | 607 | pixman_fixed_t max_vx, \ |
michael@0 | 608 | pixman_bool_t fully_transparent_src) \ |
michael@0 | 609 | { \ |
michael@0 | 610 | scanline_func (dst, src, w, vx, unit_x, max_vx, fully_transparent_src); \ |
michael@0 | 611 | } \ |
michael@0 | 612 | FAST_NEAREST_MAINLOOP_INT (scale_func_name, scanline_func##scale_func_name##_wrapper, \ |
michael@0 | 613 | src_type_t, uint8_t, dst_type_t, repeat_mode, FALSE, FALSE) |
michael@0 | 614 | |
michael@0 | 615 | #define FAST_NEAREST_MAINLOOP(scale_func_name, scanline_func, src_type_t, dst_type_t, \ |
michael@0 | 616 | repeat_mode) \ |
michael@0 | 617 | FAST_NEAREST_MAINLOOP_NOMASK(_ ## scale_func_name, scanline_func, src_type_t, \ |
michael@0 | 618 | dst_type_t, repeat_mode) |
michael@0 | 619 | |
michael@0 | 620 | #define FAST_NEAREST(scale_func_name, SRC_FORMAT, DST_FORMAT, \ |
michael@0 | 621 | src_type_t, dst_type_t, OP, repeat_mode) \ |
michael@0 | 622 | FAST_NEAREST_SCANLINE(scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \ |
michael@0 | 623 | SRC_FORMAT, DST_FORMAT, src_type_t, dst_type_t, \ |
michael@0 | 624 | OP, repeat_mode) \ |
michael@0 | 625 | FAST_NEAREST_MAINLOOP_NOMASK(_ ## scale_func_name ## _ ## OP, \ |
michael@0 | 626 | scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \ |
michael@0 | 627 | src_type_t, dst_type_t, repeat_mode) |
michael@0 | 628 | |
michael@0 | 629 | |
michael@0 | 630 | #define SCALED_NEAREST_FLAGS \ |
michael@0 | 631 | (FAST_PATH_SCALE_TRANSFORM | \ |
michael@0 | 632 | FAST_PATH_NO_ALPHA_MAP | \ |
michael@0 | 633 | FAST_PATH_NEAREST_FILTER | \ |
michael@0 | 634 | FAST_PATH_NO_ACCESSORS | \ |
michael@0 | 635 | FAST_PATH_NARROW_FORMAT) |
michael@0 | 636 | |
michael@0 | 637 | #define SIMPLE_NEAREST_FAST_PATH_NORMAL(op,s,d,func) \ |
michael@0 | 638 | { PIXMAN_OP_ ## op, \ |
michael@0 | 639 | PIXMAN_ ## s, \ |
michael@0 | 640 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 641 | FAST_PATH_NORMAL_REPEAT | \ |
michael@0 | 642 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 643 | PIXMAN_null, 0, \ |
michael@0 | 644 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 645 | fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ |
michael@0 | 646 | } |
michael@0 | 647 | |
michael@0 | 648 | #define SIMPLE_NEAREST_FAST_PATH_PAD(op,s,d,func) \ |
michael@0 | 649 | { PIXMAN_OP_ ## op, \ |
michael@0 | 650 | PIXMAN_ ## s, \ |
michael@0 | 651 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 652 | FAST_PATH_PAD_REPEAT | \ |
michael@0 | 653 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 654 | PIXMAN_null, 0, \ |
michael@0 | 655 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 656 | fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ |
michael@0 | 657 | } |
michael@0 | 658 | |
michael@0 | 659 | #define SIMPLE_NEAREST_FAST_PATH_NONE(op,s,d,func) \ |
michael@0 | 660 | { PIXMAN_OP_ ## op, \ |
michael@0 | 661 | PIXMAN_ ## s, \ |
michael@0 | 662 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 663 | FAST_PATH_NONE_REPEAT | \ |
michael@0 | 664 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 665 | PIXMAN_null, 0, \ |
michael@0 | 666 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 667 | fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ |
michael@0 | 668 | } |
michael@0 | 669 | |
michael@0 | 670 | #define SIMPLE_NEAREST_FAST_PATH_COVER(op,s,d,func) \ |
michael@0 | 671 | { PIXMAN_OP_ ## op, \ |
michael@0 | 672 | PIXMAN_ ## s, \ |
michael@0 | 673 | SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST, \ |
michael@0 | 674 | PIXMAN_null, 0, \ |
michael@0 | 675 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 676 | fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ |
michael@0 | 677 | } |
michael@0 | 678 | |
michael@0 | 679 | #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL(op,s,d,func) \ |
michael@0 | 680 | { PIXMAN_OP_ ## op, \ |
michael@0 | 681 | PIXMAN_ ## s, \ |
michael@0 | 682 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 683 | FAST_PATH_NORMAL_REPEAT | \ |
michael@0 | 684 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 685 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 686 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 687 | fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ |
michael@0 | 688 | } |
michael@0 | 689 | |
michael@0 | 690 | #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD(op,s,d,func) \ |
michael@0 | 691 | { PIXMAN_OP_ ## op, \ |
michael@0 | 692 | PIXMAN_ ## s, \ |
michael@0 | 693 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 694 | FAST_PATH_PAD_REPEAT | \ |
michael@0 | 695 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 696 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 697 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 698 | fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ |
michael@0 | 699 | } |
michael@0 | 700 | |
michael@0 | 701 | #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE(op,s,d,func) \ |
michael@0 | 702 | { PIXMAN_OP_ ## op, \ |
michael@0 | 703 | PIXMAN_ ## s, \ |
michael@0 | 704 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 705 | FAST_PATH_NONE_REPEAT | \ |
michael@0 | 706 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 707 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 708 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 709 | fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ |
michael@0 | 710 | } |
michael@0 | 711 | |
michael@0 | 712 | #define SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER(op,s,d,func) \ |
michael@0 | 713 | { PIXMAN_OP_ ## op, \ |
michael@0 | 714 | PIXMAN_ ## s, \ |
michael@0 | 715 | SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST, \ |
michael@0 | 716 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 717 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 718 | fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ |
michael@0 | 719 | } |
michael@0 | 720 | |
michael@0 | 721 | #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL(op,s,d,func) \ |
michael@0 | 722 | { PIXMAN_OP_ ## op, \ |
michael@0 | 723 | PIXMAN_ ## s, \ |
michael@0 | 724 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 725 | FAST_PATH_NORMAL_REPEAT | \ |
michael@0 | 726 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 727 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 728 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 729 | fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ |
michael@0 | 730 | } |
michael@0 | 731 | |
michael@0 | 732 | #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD(op,s,d,func) \ |
michael@0 | 733 | { PIXMAN_OP_ ## op, \ |
michael@0 | 734 | PIXMAN_ ## s, \ |
michael@0 | 735 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 736 | FAST_PATH_PAD_REPEAT | \ |
michael@0 | 737 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 738 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 739 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 740 | fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ |
michael@0 | 741 | } |
michael@0 | 742 | |
michael@0 | 743 | #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE(op,s,d,func) \ |
michael@0 | 744 | { PIXMAN_OP_ ## op, \ |
michael@0 | 745 | PIXMAN_ ## s, \ |
michael@0 | 746 | (SCALED_NEAREST_FLAGS | \ |
michael@0 | 747 | FAST_PATH_NONE_REPEAT | \ |
michael@0 | 748 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 749 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 750 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 751 | fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ |
michael@0 | 752 | } |
michael@0 | 753 | |
michael@0 | 754 | #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER(op,s,d,func) \ |
michael@0 | 755 | { PIXMAN_OP_ ## op, \ |
michael@0 | 756 | PIXMAN_ ## s, \ |
michael@0 | 757 | SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP_NEAREST, \ |
michael@0 | 758 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 759 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 760 | fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ |
michael@0 | 761 | } |
michael@0 | 762 | |
michael@0 | 763 | /* Prefer the use of 'cover' variant, because it is faster */ |
michael@0 | 764 | #define SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \ |
michael@0 | 765 | SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \ |
michael@0 | 766 | SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \ |
michael@0 | 767 | SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func), \ |
michael@0 | 768 | SIMPLE_NEAREST_FAST_PATH_NORMAL (op,s,d,func) |
michael@0 | 769 | |
michael@0 | 770 | #define SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \ |
michael@0 | 771 | SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \ |
michael@0 | 772 | SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \ |
michael@0 | 773 | SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func) |
michael@0 | 774 | |
michael@0 | 775 | #define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH(op,s,d,func) \ |
michael@0 | 776 | SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \ |
michael@0 | 777 | SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \ |
michael@0 | 778 | SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func) |
michael@0 | 779 | |
michael@0 | 780 | /*****************************************************************************/ |
michael@0 | 781 | |
michael@0 | 782 | /* |
michael@0 | 783 | * Identify 5 zones in each scanline for bilinear scaling. Depending on |
michael@0 | 784 | * whether 2 pixels to be interpolated are fetched from the image itself, |
michael@0 | 785 | * from the padding area around it or from both image and padding area. |
michael@0 | 786 | */ |
michael@0 | 787 | static force_inline void |
michael@0 | 788 | bilinear_pad_repeat_get_scanline_bounds (int32_t source_image_width, |
michael@0 | 789 | pixman_fixed_t vx, |
michael@0 | 790 | pixman_fixed_t unit_x, |
michael@0 | 791 | int32_t * left_pad, |
michael@0 | 792 | int32_t * left_tz, |
michael@0 | 793 | int32_t * width, |
michael@0 | 794 | int32_t * right_tz, |
michael@0 | 795 | int32_t * right_pad) |
michael@0 | 796 | { |
michael@0 | 797 | int width1 = *width, left_pad1, right_pad1; |
michael@0 | 798 | int width2 = *width, left_pad2, right_pad2; |
michael@0 | 799 | |
michael@0 | 800 | pad_repeat_get_scanline_bounds (source_image_width, vx, unit_x, |
michael@0 | 801 | &width1, &left_pad1, &right_pad1); |
michael@0 | 802 | pad_repeat_get_scanline_bounds (source_image_width, vx + pixman_fixed_1, |
michael@0 | 803 | unit_x, &width2, &left_pad2, &right_pad2); |
michael@0 | 804 | |
michael@0 | 805 | *left_pad = left_pad2; |
michael@0 | 806 | *left_tz = left_pad1 - left_pad2; |
michael@0 | 807 | *right_tz = right_pad2 - right_pad1; |
michael@0 | 808 | *right_pad = right_pad1; |
michael@0 | 809 | *width -= *left_pad + *left_tz + *right_tz + *right_pad; |
michael@0 | 810 | } |
michael@0 | 811 | |
michael@0 | 812 | /* |
michael@0 | 813 | * Main loop template for single pass bilinear scaling. It needs to be |
michael@0 | 814 | * provided with 'scanline_func' which should do the compositing operation. |
michael@0 | 815 | * The needed function has the following prototype: |
michael@0 | 816 | * |
michael@0 | 817 | * scanline_func (dst_type_t * dst, |
michael@0 | 818 | * const mask_type_ * mask, |
michael@0 | 819 | * const src_type_t * src_top, |
michael@0 | 820 | * const src_type_t * src_bottom, |
michael@0 | 821 | * int32_t width, |
michael@0 | 822 | * int weight_top, |
michael@0 | 823 | * int weight_bottom, |
michael@0 | 824 | * pixman_fixed_t vx, |
michael@0 | 825 | * pixman_fixed_t unit_x, |
michael@0 | 826 | * pixman_fixed_t max_vx, |
michael@0 | 827 | * pixman_bool_t zero_src) |
michael@0 | 828 | * |
michael@0 | 829 | * Where: |
michael@0 | 830 | * dst - destination scanline buffer for storing results |
michael@0 | 831 | * mask - mask buffer (or single value for solid mask) |
michael@0 | 832 | * src_top, src_bottom - two source scanlines |
michael@0 | 833 | * width - number of pixels to process |
michael@0 | 834 | * weight_top - weight of the top row for interpolation |
michael@0 | 835 | * weight_bottom - weight of the bottom row for interpolation |
michael@0 | 836 | * vx - initial position for fetching the first pair of |
michael@0 | 837 | * pixels from the source buffer |
michael@0 | 838 | * unit_x - position increment needed to move to the next pair |
michael@0 | 839 | * of pixels |
michael@0 | 840 | * max_vx - image size as a fixed point value, can be used for |
michael@0 | 841 | * implementing NORMAL repeat (when it is supported) |
michael@0 | 842 | * zero_src - boolean hint variable, which is set to TRUE when |
michael@0 | 843 | * all source pixels are fetched from zero padding |
michael@0 | 844 | * zone for NONE repeat |
michael@0 | 845 | * |
michael@0 | 846 | * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to |
michael@0 | 847 | * BILINEAR_INTERPOLATION_RANGE, but sometimes it may be less than that |
michael@0 | 848 | * for NONE repeat when handling fuzzy antialiased top or bottom image |
michael@0 | 849 | * edges. Also both top and bottom weight variables are guaranteed to |
michael@0 | 850 | * have value, which is less than BILINEAR_INTERPOLATION_RANGE. |
michael@0 | 851 | * For example, the weights can fit into unsigned byte or be used |
michael@0 | 852 | * with 8-bit SIMD multiplication instructions for 8-bit interpolation |
michael@0 | 853 | * precision. |
michael@0 | 854 | */ |
michael@0 | 855 | |
michael@0 | 856 | /* Replace a single "scanline_func" with "fetch_func" & "op_func" to allow optional |
michael@0 | 857 | * two stage processing (bilinear fetch to a temp buffer, followed by unscaled |
michael@0 | 858 | * combine), "op_func" may be NULL, in this case we keep old behavior. |
michael@0 | 859 | * This is ugly and gcc issues some warnings, but works. |
michael@0 | 860 | * |
michael@0 | 861 | * An advice: clang has much better error reporting than gcc for deeply nested macros. |
michael@0 | 862 | */ |
michael@0 | 863 | |
michael@0 | 864 | #define scanline_func(dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 865 | scanline_buf, mask, src_top, src_bottom, width, \ |
michael@0 | 866 | weight_top, weight_bottom, vx, unit_x, max_vx, zero_src) \ |
michael@0 | 867 | do { \ |
michael@0 | 868 | if (op_func != NULL) \ |
michael@0 | 869 | { \ |
michael@0 | 870 | fetch_func ((void *)scanline_buf, (mask), (src_top), (src_bottom), (width), \ |
michael@0 | 871 | (weight_top), (weight_bottom), (vx), (unit_x), (max_vx), (zero_src)); \ |
michael@0 | 872 | ((void (*)(dst_type_t *, const mask_type_t *, const src_type_t *, int)) op_func)\ |
michael@0 | 873 | ((dst), (mask), (src_type_t *)scanline_buf, (width)); \ |
michael@0 | 874 | } \ |
michael@0 | 875 | else \ |
michael@0 | 876 | { \ |
michael@0 | 877 | fetch_func ((void*)(dst), (mask), (src_top), (src_bottom), (width), (weight_top), \ |
michael@0 | 878 | (weight_bottom), (vx), (unit_x), (max_vx), (zero_src)); \ |
michael@0 | 879 | } \ |
michael@0 | 880 | } while (0) |
michael@0 | 881 | |
michael@0 | 882 | |
michael@0 | 883 | #define SCANLINE_BUFFER_LENGTH 3072 |
michael@0 | 884 | |
michael@0 | 885 | #define FAST_BILINEAR_MAINLOOP_INT(scale_func_name, fetch_func, op_func, src_type_t, \ |
michael@0 | 886 | mask_type_t, dst_type_t, repeat_mode, flags) \ |
michael@0 | 887 | static void \ |
michael@0 | 888 | fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, \ |
michael@0 | 889 | pixman_composite_info_t *info) \ |
michael@0 | 890 | { \ |
michael@0 | 891 | PIXMAN_COMPOSITE_ARGS (info); \ |
michael@0 | 892 | dst_type_t *dst_line; \ |
michael@0 | 893 | mask_type_t *mask_line; \ |
michael@0 | 894 | src_type_t *src_first_line; \ |
michael@0 | 895 | int y1, y2; \ |
michael@0 | 896 | pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */ \ |
michael@0 | 897 | pixman_vector_t v; \ |
michael@0 | 898 | pixman_fixed_t vx, vy; \ |
michael@0 | 899 | pixman_fixed_t unit_x, unit_y; \ |
michael@0 | 900 | int32_t left_pad, left_tz, right_tz, right_pad; \ |
michael@0 | 901 | \ |
michael@0 | 902 | dst_type_t *dst; \ |
michael@0 | 903 | mask_type_t solid_mask; \ |
michael@0 | 904 | const mask_type_t *mask = &solid_mask; \ |
michael@0 | 905 | int src_stride, mask_stride, dst_stride; \ |
michael@0 | 906 | \ |
michael@0 | 907 | int src_width; \ |
michael@0 | 908 | pixman_fixed_t src_width_fixed; \ |
michael@0 | 909 | int max_x; \ |
michael@0 | 910 | pixman_bool_t need_src_extension; \ |
michael@0 | 911 | \ |
michael@0 | 912 | uint64_t stack_scanline_buffer[SCANLINE_BUFFER_LENGTH]; \ |
michael@0 | 913 | uint8_t *scanline_buffer = (uint8_t *) stack_scanline_buffer; \ |
michael@0 | 914 | \ |
michael@0 | 915 | PIXMAN_IMAGE_GET_LINE (dest_image, dest_x, dest_y, dst_type_t, dst_stride, dst_line, 1); \ |
michael@0 | 916 | if (flags & FLAG_HAVE_SOLID_MASK) \ |
michael@0 | 917 | { \ |
michael@0 | 918 | solid_mask = _pixman_image_get_solid (imp, mask_image, dest_image->bits.format); \ |
michael@0 | 919 | mask_stride = 0; \ |
michael@0 | 920 | } \ |
michael@0 | 921 | else if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 922 | { \ |
michael@0 | 923 | PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t, \ |
michael@0 | 924 | mask_stride, mask_line, 1); \ |
michael@0 | 925 | } \ |
michael@0 | 926 | \ |
michael@0 | 927 | /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \ |
michael@0 | 928 | * transformed from destination space to source space */ \ |
michael@0 | 929 | PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \ |
michael@0 | 930 | \ |
michael@0 | 931 | /* reference point is the center of the pixel */ \ |
michael@0 | 932 | v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \ |
michael@0 | 933 | v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \ |
michael@0 | 934 | v.vector[2] = pixman_fixed_1; \ |
michael@0 | 935 | \ |
michael@0 | 936 | if (!pixman_transform_point_3d (src_image->common.transform, &v)) \ |
michael@0 | 937 | return; \ |
michael@0 | 938 | \ |
michael@0 | 939 | unit_x = src_image->common.transform->matrix[0][0]; \ |
michael@0 | 940 | unit_y = src_image->common.transform->matrix[1][1]; \ |
michael@0 | 941 | \ |
michael@0 | 942 | v.vector[0] -= pixman_fixed_1 / 2; \ |
michael@0 | 943 | v.vector[1] -= pixman_fixed_1 / 2; \ |
michael@0 | 944 | \ |
michael@0 | 945 | vy = v.vector[1]; \ |
michael@0 | 946 | \ |
michael@0 | 947 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \ |
michael@0 | 948 | PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
michael@0 | 949 | { \ |
michael@0 | 950 | bilinear_pad_repeat_get_scanline_bounds (src_image->bits.width, v.vector[0], unit_x, \ |
michael@0 | 951 | &left_pad, &left_tz, &width, &right_tz, &right_pad); \ |
michael@0 | 952 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ |
michael@0 | 953 | { \ |
michael@0 | 954 | /* PAD repeat does not need special handling for 'transition zones' and */ \ |
michael@0 | 955 | /* they can be combined with 'padding zones' safely */ \ |
michael@0 | 956 | left_pad += left_tz; \ |
michael@0 | 957 | right_pad += right_tz; \ |
michael@0 | 958 | left_tz = right_tz = 0; \ |
michael@0 | 959 | } \ |
michael@0 | 960 | v.vector[0] += left_pad * unit_x; \ |
michael@0 | 961 | } \ |
michael@0 | 962 | \ |
michael@0 | 963 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
michael@0 | 964 | { \ |
michael@0 | 965 | vx = v.vector[0]; \ |
michael@0 | 966 | repeat (PIXMAN_REPEAT_NORMAL, &vx, pixman_int_to_fixed(src_image->bits.width)); \ |
michael@0 | 967 | max_x = pixman_fixed_to_int (vx + (width - 1) * (int64_t)unit_x) + 1; \ |
michael@0 | 968 | \ |
michael@0 | 969 | if (src_image->bits.width < REPEAT_NORMAL_MIN_WIDTH) \ |
michael@0 | 970 | { \ |
michael@0 | 971 | src_width = 0; \ |
michael@0 | 972 | \ |
michael@0 | 973 | while (src_width < REPEAT_NORMAL_MIN_WIDTH && src_width <= max_x) \ |
michael@0 | 974 | src_width += src_image->bits.width; \ |
michael@0 | 975 | \ |
michael@0 | 976 | need_src_extension = TRUE; \ |
michael@0 | 977 | } \ |
michael@0 | 978 | else \ |
michael@0 | 979 | { \ |
michael@0 | 980 | src_width = src_image->bits.width; \ |
michael@0 | 981 | need_src_extension = FALSE; \ |
michael@0 | 982 | } \ |
michael@0 | 983 | \ |
michael@0 | 984 | src_width_fixed = pixman_int_to_fixed (src_width); \ |
michael@0 | 985 | } \ |
michael@0 | 986 | \ |
michael@0 | 987 | if (op_func != NULL && width * sizeof(src_type_t) > sizeof(stack_scanline_buffer)) \ |
michael@0 | 988 | { \ |
michael@0 | 989 | scanline_buffer = pixman_malloc_ab (width, sizeof(src_type_t)); \ |
michael@0 | 990 | \ |
michael@0 | 991 | if (!scanline_buffer) \ |
michael@0 | 992 | return; \ |
michael@0 | 993 | } \ |
michael@0 | 994 | \ |
michael@0 | 995 | while (--height >= 0) \ |
michael@0 | 996 | { \ |
michael@0 | 997 | int weight1, weight2; \ |
michael@0 | 998 | dst = dst_line; \ |
michael@0 | 999 | dst_line += dst_stride; \ |
michael@0 | 1000 | vx = v.vector[0]; \ |
michael@0 | 1001 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1002 | { \ |
michael@0 | 1003 | mask = mask_line; \ |
michael@0 | 1004 | mask_line += mask_stride; \ |
michael@0 | 1005 | } \ |
michael@0 | 1006 | \ |
michael@0 | 1007 | y1 = pixman_fixed_to_int (vy); \ |
michael@0 | 1008 | weight2 = pixman_fixed_to_bilinear_weight (vy); \ |
michael@0 | 1009 | if (weight2) \ |
michael@0 | 1010 | { \ |
michael@0 | 1011 | /* both weight1 and weight2 are smaller than BILINEAR_INTERPOLATION_RANGE */ \ |
michael@0 | 1012 | y2 = y1 + 1; \ |
michael@0 | 1013 | weight1 = BILINEAR_INTERPOLATION_RANGE - weight2; \ |
michael@0 | 1014 | } \ |
michael@0 | 1015 | else \ |
michael@0 | 1016 | { \ |
michael@0 | 1017 | /* set both top and bottom row to the same scanline and tweak weights */ \ |
michael@0 | 1018 | y2 = y1; \ |
michael@0 | 1019 | weight1 = weight2 = BILINEAR_INTERPOLATION_RANGE / 2; \ |
michael@0 | 1020 | } \ |
michael@0 | 1021 | vy += unit_y; \ |
michael@0 | 1022 | if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ |
michael@0 | 1023 | { \ |
michael@0 | 1024 | src_type_t *src1, *src2; \ |
michael@0 | 1025 | src_type_t buf1[2]; \ |
michael@0 | 1026 | src_type_t buf2[2]; \ |
michael@0 | 1027 | repeat (PIXMAN_REPEAT_PAD, &y1, src_image->bits.height); \ |
michael@0 | 1028 | repeat (PIXMAN_REPEAT_PAD, &y2, src_image->bits.height); \ |
michael@0 | 1029 | src1 = src_first_line + src_stride * y1; \ |
michael@0 | 1030 | src2 = src_first_line + src_stride * y2; \ |
michael@0 | 1031 | \ |
michael@0 | 1032 | if (left_pad > 0) \ |
michael@0 | 1033 | { \ |
michael@0 | 1034 | buf1[0] = buf1[1] = src1[0]; \ |
michael@0 | 1035 | buf2[0] = buf2[1] = src2[0]; \ |
michael@0 | 1036 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1037 | scanline_buffer, mask, buf1, buf2, left_pad, weight1, weight2, \ |
michael@0 | 1038 | 0, 0, 0, FALSE); \ |
michael@0 | 1039 | dst += left_pad; \ |
michael@0 | 1040 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1041 | mask += left_pad; \ |
michael@0 | 1042 | } \ |
michael@0 | 1043 | if (width > 0) \ |
michael@0 | 1044 | { \ |
michael@0 | 1045 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1046 | scanline_buffer, mask, src1, src2, width, weight1, weight2, \ |
michael@0 | 1047 | vx, unit_x, 0, FALSE); \ |
michael@0 | 1048 | dst += width; \ |
michael@0 | 1049 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1050 | mask += width; \ |
michael@0 | 1051 | } \ |
michael@0 | 1052 | if (right_pad > 0) \ |
michael@0 | 1053 | { \ |
michael@0 | 1054 | buf1[0] = buf1[1] = src1[src_image->bits.width - 1]; \ |
michael@0 | 1055 | buf2[0] = buf2[1] = src2[src_image->bits.width - 1]; \ |
michael@0 | 1056 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1057 | scanline_buffer, mask, buf1, buf2, right_pad, weight1, weight2, \ |
michael@0 | 1058 | 0, 0, 0, FALSE); \ |
michael@0 | 1059 | } \ |
michael@0 | 1060 | } \ |
michael@0 | 1061 | else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ |
michael@0 | 1062 | { \ |
michael@0 | 1063 | src_type_t *src1, *src2; \ |
michael@0 | 1064 | src_type_t buf1[2]; \ |
michael@0 | 1065 | src_type_t buf2[2]; \ |
michael@0 | 1066 | /* handle top/bottom zero padding by just setting weights to 0 if needed */ \ |
michael@0 | 1067 | if (y1 < 0) \ |
michael@0 | 1068 | { \ |
michael@0 | 1069 | weight1 = 0; \ |
michael@0 | 1070 | y1 = 0; \ |
michael@0 | 1071 | } \ |
michael@0 | 1072 | if (y1 >= src_image->bits.height) \ |
michael@0 | 1073 | { \ |
michael@0 | 1074 | weight1 = 0; \ |
michael@0 | 1075 | y1 = src_image->bits.height - 1; \ |
michael@0 | 1076 | } \ |
michael@0 | 1077 | if (y2 < 0) \ |
michael@0 | 1078 | { \ |
michael@0 | 1079 | weight2 = 0; \ |
michael@0 | 1080 | y2 = 0; \ |
michael@0 | 1081 | } \ |
michael@0 | 1082 | if (y2 >= src_image->bits.height) \ |
michael@0 | 1083 | { \ |
michael@0 | 1084 | weight2 = 0; \ |
michael@0 | 1085 | y2 = src_image->bits.height - 1; \ |
michael@0 | 1086 | } \ |
michael@0 | 1087 | src1 = src_first_line + src_stride * y1; \ |
michael@0 | 1088 | src2 = src_first_line + src_stride * y2; \ |
michael@0 | 1089 | \ |
michael@0 | 1090 | if (left_pad > 0) \ |
michael@0 | 1091 | { \ |
michael@0 | 1092 | buf1[0] = buf1[1] = 0; \ |
michael@0 | 1093 | buf2[0] = buf2[1] = 0; \ |
michael@0 | 1094 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1095 | scanline_buffer, mask, buf1, buf2, left_pad, weight1, weight2, \ |
michael@0 | 1096 | 0, 0, 0, TRUE); \ |
michael@0 | 1097 | dst += left_pad; \ |
michael@0 | 1098 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1099 | mask += left_pad; \ |
michael@0 | 1100 | } \ |
michael@0 | 1101 | if (left_tz > 0) \ |
michael@0 | 1102 | { \ |
michael@0 | 1103 | buf1[0] = 0; \ |
michael@0 | 1104 | buf1[1] = src1[0]; \ |
michael@0 | 1105 | buf2[0] = 0; \ |
michael@0 | 1106 | buf2[1] = src2[0]; \ |
michael@0 | 1107 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1108 | scanline_buffer, mask, buf1, buf2, left_tz, weight1, weight2, \ |
michael@0 | 1109 | pixman_fixed_frac (vx), unit_x, 0, FALSE); \ |
michael@0 | 1110 | dst += left_tz; \ |
michael@0 | 1111 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1112 | mask += left_tz; \ |
michael@0 | 1113 | vx += left_tz * unit_x; \ |
michael@0 | 1114 | } \ |
michael@0 | 1115 | if (width > 0) \ |
michael@0 | 1116 | { \ |
michael@0 | 1117 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1118 | scanline_buffer, mask, src1, src2, width, weight1, weight2, \ |
michael@0 | 1119 | vx, unit_x, 0, FALSE); \ |
michael@0 | 1120 | dst += width; \ |
michael@0 | 1121 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1122 | mask += width; \ |
michael@0 | 1123 | vx += width * unit_x; \ |
michael@0 | 1124 | } \ |
michael@0 | 1125 | if (right_tz > 0) \ |
michael@0 | 1126 | { \ |
michael@0 | 1127 | buf1[0] = src1[src_image->bits.width - 1]; \ |
michael@0 | 1128 | buf1[1] = 0; \ |
michael@0 | 1129 | buf2[0] = src2[src_image->bits.width - 1]; \ |
michael@0 | 1130 | buf2[1] = 0; \ |
michael@0 | 1131 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1132 | scanline_buffer, mask, buf1, buf2, right_tz, weight1, weight2, \ |
michael@0 | 1133 | pixman_fixed_frac (vx), unit_x, 0, FALSE); \ |
michael@0 | 1134 | dst += right_tz; \ |
michael@0 | 1135 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1136 | mask += right_tz; \ |
michael@0 | 1137 | } \ |
michael@0 | 1138 | if (right_pad > 0) \ |
michael@0 | 1139 | { \ |
michael@0 | 1140 | buf1[0] = buf1[1] = 0; \ |
michael@0 | 1141 | buf2[0] = buf2[1] = 0; \ |
michael@0 | 1142 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1143 | scanline_buffer, mask, buf1, buf2, right_pad, weight1, weight2, \ |
michael@0 | 1144 | 0, 0, 0, TRUE); \ |
michael@0 | 1145 | } \ |
michael@0 | 1146 | } \ |
michael@0 | 1147 | else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ |
michael@0 | 1148 | { \ |
michael@0 | 1149 | int32_t num_pixels; \ |
michael@0 | 1150 | int32_t width_remain; \ |
michael@0 | 1151 | src_type_t * src_line_top; \ |
michael@0 | 1152 | src_type_t * src_line_bottom; \ |
michael@0 | 1153 | src_type_t buf1[2]; \ |
michael@0 | 1154 | src_type_t buf2[2]; \ |
michael@0 | 1155 | src_type_t extended_src_line0[REPEAT_NORMAL_MIN_WIDTH*2]; \ |
michael@0 | 1156 | src_type_t extended_src_line1[REPEAT_NORMAL_MIN_WIDTH*2]; \ |
michael@0 | 1157 | int i, j; \ |
michael@0 | 1158 | \ |
michael@0 | 1159 | repeat (PIXMAN_REPEAT_NORMAL, &y1, src_image->bits.height); \ |
michael@0 | 1160 | repeat (PIXMAN_REPEAT_NORMAL, &y2, src_image->bits.height); \ |
michael@0 | 1161 | src_line_top = src_first_line + src_stride * y1; \ |
michael@0 | 1162 | src_line_bottom = src_first_line + src_stride * y2; \ |
michael@0 | 1163 | \ |
michael@0 | 1164 | if (need_src_extension) \ |
michael@0 | 1165 | { \ |
michael@0 | 1166 | for (i=0; i<src_width;) \ |
michael@0 | 1167 | { \ |
michael@0 | 1168 | for (j=0; j<src_image->bits.width; j++, i++) \ |
michael@0 | 1169 | { \ |
michael@0 | 1170 | extended_src_line0[i] = src_line_top[j]; \ |
michael@0 | 1171 | extended_src_line1[i] = src_line_bottom[j]; \ |
michael@0 | 1172 | } \ |
michael@0 | 1173 | } \ |
michael@0 | 1174 | \ |
michael@0 | 1175 | src_line_top = &extended_src_line0[0]; \ |
michael@0 | 1176 | src_line_bottom = &extended_src_line1[0]; \ |
michael@0 | 1177 | } \ |
michael@0 | 1178 | \ |
michael@0 | 1179 | /* Top & Bottom wrap around buffer */ \ |
michael@0 | 1180 | buf1[0] = src_line_top[src_width - 1]; \ |
michael@0 | 1181 | buf1[1] = src_line_top[0]; \ |
michael@0 | 1182 | buf2[0] = src_line_bottom[src_width - 1]; \ |
michael@0 | 1183 | buf2[1] = src_line_bottom[0]; \ |
michael@0 | 1184 | \ |
michael@0 | 1185 | width_remain = width; \ |
michael@0 | 1186 | \ |
michael@0 | 1187 | while (width_remain > 0) \ |
michael@0 | 1188 | { \ |
michael@0 | 1189 | /* We use src_width_fixed because it can make vx in original source range */ \ |
michael@0 | 1190 | repeat (PIXMAN_REPEAT_NORMAL, &vx, src_width_fixed); \ |
michael@0 | 1191 | \ |
michael@0 | 1192 | /* Wrap around part */ \ |
michael@0 | 1193 | if (pixman_fixed_to_int (vx) == src_width - 1) \ |
michael@0 | 1194 | { \ |
michael@0 | 1195 | /* for positive unit_x \ |
michael@0 | 1196 | * num_pixels = max(n) + 1, where vx + n*unit_x < src_width_fixed \ |
michael@0 | 1197 | * \ |
michael@0 | 1198 | * vx is in range [0, src_width_fixed - pixman_fixed_e] \ |
michael@0 | 1199 | * So we are safe from overflow. \ |
michael@0 | 1200 | */ \ |
michael@0 | 1201 | num_pixels = ((src_width_fixed - vx - pixman_fixed_e) / unit_x) + 1; \ |
michael@0 | 1202 | \ |
michael@0 | 1203 | if (num_pixels > width_remain) \ |
michael@0 | 1204 | num_pixels = width_remain; \ |
michael@0 | 1205 | \ |
michael@0 | 1206 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, \ |
michael@0 | 1207 | dst, scanline_buffer, mask, buf1, buf2, num_pixels, \ |
michael@0 | 1208 | weight1, weight2, pixman_fixed_frac(vx), \ |
michael@0 | 1209 | unit_x, src_width_fixed, FALSE); \ |
michael@0 | 1210 | \ |
michael@0 | 1211 | width_remain -= num_pixels; \ |
michael@0 | 1212 | vx += num_pixels * unit_x; \ |
michael@0 | 1213 | dst += num_pixels; \ |
michael@0 | 1214 | \ |
michael@0 | 1215 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1216 | mask += num_pixels; \ |
michael@0 | 1217 | \ |
michael@0 | 1218 | repeat (PIXMAN_REPEAT_NORMAL, &vx, src_width_fixed); \ |
michael@0 | 1219 | } \ |
michael@0 | 1220 | \ |
michael@0 | 1221 | /* Normal scanline composite */ \ |
michael@0 | 1222 | if (pixman_fixed_to_int (vx) != src_width - 1 && width_remain > 0) \ |
michael@0 | 1223 | { \ |
michael@0 | 1224 | /* for positive unit_x \ |
michael@0 | 1225 | * num_pixels = max(n) + 1, where vx + n*unit_x < (src_width_fixed - 1) \ |
michael@0 | 1226 | * \ |
michael@0 | 1227 | * vx is in range [0, src_width_fixed - pixman_fixed_e] \ |
michael@0 | 1228 | * So we are safe from overflow here. \ |
michael@0 | 1229 | */ \ |
michael@0 | 1230 | num_pixels = ((src_width_fixed - pixman_fixed_1 - vx - pixman_fixed_e) \ |
michael@0 | 1231 | / unit_x) + 1; \ |
michael@0 | 1232 | \ |
michael@0 | 1233 | if (num_pixels > width_remain) \ |
michael@0 | 1234 | num_pixels = width_remain; \ |
michael@0 | 1235 | \ |
michael@0 | 1236 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, \ |
michael@0 | 1237 | dst, scanline_buffer, mask, src_line_top, src_line_bottom, \ |
michael@0 | 1238 | num_pixels, weight1, weight2, vx, unit_x, src_width_fixed, \ |
michael@0 | 1239 | FALSE); \ |
michael@0 | 1240 | \ |
michael@0 | 1241 | width_remain -= num_pixels; \ |
michael@0 | 1242 | vx += num_pixels * unit_x; \ |
michael@0 | 1243 | dst += num_pixels; \ |
michael@0 | 1244 | \ |
michael@0 | 1245 | if (flags & FLAG_HAVE_NON_SOLID_MASK) \ |
michael@0 | 1246 | mask += num_pixels; \ |
michael@0 | 1247 | } \ |
michael@0 | 1248 | } \ |
michael@0 | 1249 | } \ |
michael@0 | 1250 | else \ |
michael@0 | 1251 | { \ |
michael@0 | 1252 | scanline_func (dst_type_t, mask_type_t, src_type_t, fetch_func, op_func, dst, \ |
michael@0 | 1253 | scanline_buffer, mask, \ |
michael@0 | 1254 | src_first_line + src_stride * y1, \ |
michael@0 | 1255 | src_first_line + src_stride * y2, width, \ |
michael@0 | 1256 | weight1, weight2, vx, unit_x, max_vx, FALSE); \ |
michael@0 | 1257 | } \ |
michael@0 | 1258 | } \ |
michael@0 | 1259 | if (scanline_buffer != (uint8_t *) stack_scanline_buffer) \ |
michael@0 | 1260 | free (scanline_buffer); \ |
michael@0 | 1261 | } |
michael@0 | 1262 | |
michael@0 | 1263 | /* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */ |
michael@0 | 1264 | #define FAST_BILINEAR_MAINLOOP_COMMON(scale_func_name, fetch_func, op_func, src_type_t, mask_type_t,\ |
michael@0 | 1265 | dst_type_t, repeat_mode, flags) \ |
michael@0 | 1266 | FAST_BILINEAR_MAINLOOP_INT(_ ## scale_func_name, fetch_func, op_func, src_type_t, mask_type_t,\ |
michael@0 | 1267 | dst_type_t, repeat_mode, flags) |
michael@0 | 1268 | |
michael@0 | 1269 | #define SCALED_BILINEAR_FLAGS \ |
michael@0 | 1270 | (FAST_PATH_SCALE_TRANSFORM | \ |
michael@0 | 1271 | FAST_PATH_NO_ALPHA_MAP | \ |
michael@0 | 1272 | FAST_PATH_BILINEAR_FILTER | \ |
michael@0 | 1273 | FAST_PATH_NO_ACCESSORS | \ |
michael@0 | 1274 | FAST_PATH_NARROW_FORMAT) |
michael@0 | 1275 | |
michael@0 | 1276 | #define SIMPLE_BILINEAR_FAST_PATH_PAD(op,s,d,func) \ |
michael@0 | 1277 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1278 | PIXMAN_ ## s, \ |
michael@0 | 1279 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1280 | FAST_PATH_PAD_REPEAT | \ |
michael@0 | 1281 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1282 | PIXMAN_null, 0, \ |
michael@0 | 1283 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1284 | fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ |
michael@0 | 1285 | } |
michael@0 | 1286 | |
michael@0 | 1287 | #define SIMPLE_BILINEAR_FAST_PATH_NONE(op,s,d,func) \ |
michael@0 | 1288 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1289 | PIXMAN_ ## s, \ |
michael@0 | 1290 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1291 | FAST_PATH_NONE_REPEAT | \ |
michael@0 | 1292 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1293 | PIXMAN_null, 0, \ |
michael@0 | 1294 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1295 | fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ |
michael@0 | 1296 | } |
michael@0 | 1297 | |
michael@0 | 1298 | #define SIMPLE_BILINEAR_FAST_PATH_COVER(op,s,d,func) \ |
michael@0 | 1299 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1300 | PIXMAN_ ## s, \ |
michael@0 | 1301 | SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR, \ |
michael@0 | 1302 | PIXMAN_null, 0, \ |
michael@0 | 1303 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1304 | fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ |
michael@0 | 1305 | } |
michael@0 | 1306 | |
michael@0 | 1307 | #define SIMPLE_BILINEAR_FAST_PATH_NORMAL(op,s,d,func) \ |
michael@0 | 1308 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1309 | PIXMAN_ ## s, \ |
michael@0 | 1310 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1311 | FAST_PATH_NORMAL_REPEAT | \ |
michael@0 | 1312 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1313 | PIXMAN_null, 0, \ |
michael@0 | 1314 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1315 | fast_composite_scaled_bilinear_ ## func ## _normal ## _ ## op, \ |
michael@0 | 1316 | } |
michael@0 | 1317 | |
michael@0 | 1318 | #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD(op,s,d,func) \ |
michael@0 | 1319 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1320 | PIXMAN_ ## s, \ |
michael@0 | 1321 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1322 | FAST_PATH_PAD_REPEAT | \ |
michael@0 | 1323 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1324 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1325 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1326 | fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ |
michael@0 | 1327 | } |
michael@0 | 1328 | |
michael@0 | 1329 | #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE(op,s,d,func) \ |
michael@0 | 1330 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1331 | PIXMAN_ ## s, \ |
michael@0 | 1332 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1333 | FAST_PATH_NONE_REPEAT | \ |
michael@0 | 1334 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1335 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1336 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1337 | fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ |
michael@0 | 1338 | } |
michael@0 | 1339 | |
michael@0 | 1340 | #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER(op,s,d,func) \ |
michael@0 | 1341 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1342 | PIXMAN_ ## s, \ |
michael@0 | 1343 | SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR, \ |
michael@0 | 1344 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1345 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1346 | fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ |
michael@0 | 1347 | } |
michael@0 | 1348 | |
michael@0 | 1349 | #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NORMAL(op,s,d,func) \ |
michael@0 | 1350 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1351 | PIXMAN_ ## s, \ |
michael@0 | 1352 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1353 | FAST_PATH_NORMAL_REPEAT | \ |
michael@0 | 1354 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1355 | PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1356 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1357 | fast_composite_scaled_bilinear_ ## func ## _normal ## _ ## op, \ |
michael@0 | 1358 | } |
michael@0 | 1359 | |
michael@0 | 1360 | #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD(op,s,d,func) \ |
michael@0 | 1361 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1362 | PIXMAN_ ## s, \ |
michael@0 | 1363 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1364 | FAST_PATH_PAD_REPEAT | \ |
michael@0 | 1365 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1366 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1367 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1368 | fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ |
michael@0 | 1369 | } |
michael@0 | 1370 | |
michael@0 | 1371 | #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE(op,s,d,func) \ |
michael@0 | 1372 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1373 | PIXMAN_ ## s, \ |
michael@0 | 1374 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1375 | FAST_PATH_NONE_REPEAT | \ |
michael@0 | 1376 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1377 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1378 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1379 | fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ |
michael@0 | 1380 | } |
michael@0 | 1381 | |
michael@0 | 1382 | #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER(op,s,d,func) \ |
michael@0 | 1383 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1384 | PIXMAN_ ## s, \ |
michael@0 | 1385 | SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP_BILINEAR, \ |
michael@0 | 1386 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1387 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1388 | fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ |
michael@0 | 1389 | } |
michael@0 | 1390 | |
michael@0 | 1391 | #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NORMAL(op,s,d,func) \ |
michael@0 | 1392 | { PIXMAN_OP_ ## op, \ |
michael@0 | 1393 | PIXMAN_ ## s, \ |
michael@0 | 1394 | (SCALED_BILINEAR_FLAGS | \ |
michael@0 | 1395 | FAST_PATH_NORMAL_REPEAT | \ |
michael@0 | 1396 | FAST_PATH_X_UNIT_POSITIVE), \ |
michael@0 | 1397 | PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ |
michael@0 | 1398 | PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ |
michael@0 | 1399 | fast_composite_scaled_bilinear_ ## func ## _normal ## _ ## op, \ |
michael@0 | 1400 | } |
michael@0 | 1401 | |
michael@0 | 1402 | /* Prefer the use of 'cover' variant, because it is faster */ |
michael@0 | 1403 | #define SIMPLE_BILINEAR_FAST_PATH(op,s,d,func) \ |
michael@0 | 1404 | SIMPLE_BILINEAR_FAST_PATH_COVER (op,s,d,func), \ |
michael@0 | 1405 | SIMPLE_BILINEAR_FAST_PATH_NONE (op,s,d,func), \ |
michael@0 | 1406 | SIMPLE_BILINEAR_FAST_PATH_PAD (op,s,d,func), \ |
michael@0 | 1407 | SIMPLE_BILINEAR_FAST_PATH_NORMAL (op,s,d,func) |
michael@0 | 1408 | |
michael@0 | 1409 | #define SIMPLE_BILINEAR_A8_MASK_FAST_PATH(op,s,d,func) \ |
michael@0 | 1410 | SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER (op,s,d,func), \ |
michael@0 | 1411 | SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE (op,s,d,func), \ |
michael@0 | 1412 | SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD (op,s,d,func), \ |
michael@0 | 1413 | SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NORMAL (op,s,d,func) |
michael@0 | 1414 | |
michael@0 | 1415 | #define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH(op,s,d,func) \ |
michael@0 | 1416 | SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \ |
michael@0 | 1417 | SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \ |
michael@0 | 1418 | SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD (op,s,d,func), \ |
michael@0 | 1419 | SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NORMAL (op,s,d,func) |
michael@0 | 1420 | |
michael@0 | 1421 | #endif |