1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/cairo/libpixman/src/pixman-fast-path.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1022 @@ 1.4 +/* -*- Mode: c; c-basic-offset: 4; tab-width: 8; indent-tabs-mode: t; -*- */ 1.5 +/* 1.6 + * Copyright © 2000 SuSE, Inc. 1.7 + * Copyright © 2007 Red Hat, Inc. 1.8 + * 1.9 + * Permission to use, copy, modify, distribute, and sell this software and its 1.10 + * documentation for any purpose is hereby granted without fee, provided that 1.11 + * the above copyright notice appear in all copies and that both that 1.12 + * copyright notice and this permission notice appear in supporting 1.13 + * documentation, and that the name of SuSE not be used in advertising or 1.14 + * publicity pertaining to distribution of the software without specific, 1.15 + * written prior permission. SuSE makes no representations about the 1.16 + * suitability of this software for any purpose. It is provided "as is" 1.17 + * without express or implied warranty. 1.18 + * 1.19 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 1.20 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 1.21 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1.22 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 1.23 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 1.24 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1.25 + * 1.26 + * Author: Keith Packard, SuSE, Inc. 1.27 + */ 1.28 + 1.29 +#ifndef PIXMAN_FAST_PATH_H__ 1.30 +#define PIXMAN_FAST_PATH_H__ 1.31 + 1.32 +#include "pixman-private.h" 1.33 + 1.34 +#define PIXMAN_REPEAT_COVER -1 1.35 + 1.36 +static force_inline pixman_bool_t 1.37 +repeat (pixman_repeat_t repeat, int *c, int size) 1.38 +{ 1.39 + if (repeat == PIXMAN_REPEAT_NONE) 1.40 + { 1.41 + if (*c < 0 || *c >= size) 1.42 + return FALSE; 1.43 + } 1.44 + else if (repeat == PIXMAN_REPEAT_NORMAL) 1.45 + { 1.46 + while (*c >= size) 1.47 + *c -= size; 1.48 + while (*c < 0) 1.49 + *c += size; 1.50 + } 1.51 + else if (repeat == PIXMAN_REPEAT_PAD) 1.52 + { 1.53 + *c = CLIP (*c, 0, size - 1); 1.54 + } 1.55 + else /* REFLECT */ 1.56 + { 1.57 + *c = MOD (*c, size * 2); 1.58 + if (*c >= size) 1.59 + *c = size * 2 - *c - 1; 1.60 + } 1.61 + return TRUE; 1.62 +} 1.63 + 1.64 +/* 1.65 + * For each scanline fetched from source image with PAD repeat: 1.66 + * - calculate how many pixels need to be padded on the left side 1.67 + * - calculate how many pixels need to be padded on the right side 1.68 + * - update width to only count pixels which are fetched from the image 1.69 + * All this information is returned via 'width', 'left_pad', 'right_pad' 1.70 + * arguments. The code is assuming that 'unit_x' is positive. 1.71 + * 1.72 + * Note: 64-bit math is used in order to avoid potential overflows, which 1.73 + * is probably excessive in many cases. This particular function 1.74 + * may need its own correctness test and performance tuning. 1.75 + */ 1.76 +static force_inline void 1.77 +pad_repeat_get_scanline_bounds (int32_t source_image_width, 1.78 + pixman_fixed_t vx, 1.79 + pixman_fixed_t unit_x, 1.80 + int32_t * width, 1.81 + int32_t * left_pad, 1.82 + int32_t * right_pad) 1.83 +{ 1.84 + int64_t max_vx = (int64_t) source_image_width << 16; 1.85 + int64_t tmp; 1.86 + if (vx < 0) 1.87 + { 1.88 + tmp = ((int64_t) unit_x - 1 - vx) / unit_x; 1.89 + if (tmp > *width) 1.90 + { 1.91 + *left_pad = *width; 1.92 + *width = 0; 1.93 + } 1.94 + else 1.95 + { 1.96 + *left_pad = (int32_t) tmp; 1.97 + *width -= (int32_t) tmp; 1.98 + } 1.99 + } 1.100 + else 1.101 + { 1.102 + *left_pad = 0; 1.103 + } 1.104 + tmp = ((int64_t) unit_x - 1 - vx + max_vx) / unit_x - *left_pad; 1.105 + if (tmp < 0) 1.106 + { 1.107 + *right_pad = *width; 1.108 + *width = 0; 1.109 + } 1.110 + else if (tmp >= *width) 1.111 + { 1.112 + *right_pad = 0; 1.113 + } 1.114 + else 1.115 + { 1.116 + *right_pad = *width - (int32_t) tmp; 1.117 + *width = (int32_t) tmp; 1.118 + } 1.119 +} 1.120 + 1.121 +/* A macroified version of specialized nearest scalers for some 1.122 + * common 8888 and 565 formats. It supports SRC and OVER ops. 1.123 + * 1.124 + * There are two repeat versions, one that handles repeat normal, 1.125 + * and one without repeat handling that only works if the src region 1.126 + * used is completely covered by the pre-repeated source samples. 1.127 + * 1.128 + * The loops are unrolled to process two pixels per iteration for better 1.129 + * performance on most CPU architectures (superscalar processors 1.130 + * can issue several operations simultaneously, other processors can hide 1.131 + * instructions latencies by pipelining operations). Unrolling more 1.132 + * does not make much sense because the compiler will start running out 1.133 + * of spare registers soon. 1.134 + */ 1.135 + 1.136 +#define GET_8888_ALPHA(s) ((s) >> 24) 1.137 + /* This is not actually used since we don't have an OVER with 1.138 + 565 source, but it is needed to build. */ 1.139 +#define GET_0565_ALPHA(s) 0xff 1.140 + 1.141 +#define FAST_NEAREST_SCANLINE(scanline_func_name, SRC_FORMAT, DST_FORMAT, \ 1.142 + src_type_t, dst_type_t, OP, repeat_mode) \ 1.143 +static force_inline void \ 1.144 +scanline_func_name (dst_type_t *dst, \ 1.145 + const src_type_t *src, \ 1.146 + int32_t w, \ 1.147 + pixman_fixed_t vx, \ 1.148 + pixman_fixed_t unit_x, \ 1.149 + pixman_fixed_t max_vx, \ 1.150 + pixman_bool_t fully_transparent_src) \ 1.151 +{ \ 1.152 + uint32_t d; \ 1.153 + src_type_t s1, s2; \ 1.154 + uint8_t a1, a2; \ 1.155 + int x1, x2; \ 1.156 + \ 1.157 + if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER && fully_transparent_src) \ 1.158 + return; \ 1.159 + \ 1.160 + if (PIXMAN_OP_ ## OP != PIXMAN_OP_SRC && PIXMAN_OP_ ## OP != PIXMAN_OP_OVER) \ 1.161 + abort(); \ 1.162 + \ 1.163 + while ((w -= 2) >= 0) \ 1.164 + { \ 1.165 + x1 = vx >> 16; \ 1.166 + vx += unit_x; \ 1.167 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ 1.168 + { \ 1.169 + /* This works because we know that unit_x is positive */ \ 1.170 + while (vx >= max_vx) \ 1.171 + vx -= max_vx; \ 1.172 + } \ 1.173 + s1 = src[x1]; \ 1.174 + \ 1.175 + x2 = vx >> 16; \ 1.176 + vx += unit_x; \ 1.177 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ 1.178 + { \ 1.179 + /* This works because we know that unit_x is positive */ \ 1.180 + while (vx >= max_vx) \ 1.181 + vx -= max_vx; \ 1.182 + } \ 1.183 + s2 = src[x2]; \ 1.184 + \ 1.185 + if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \ 1.186 + { \ 1.187 + a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \ 1.188 + a2 = GET_ ## SRC_FORMAT ## _ALPHA(s2); \ 1.189 + \ 1.190 + if (a1 == 0xff) \ 1.191 + { \ 1.192 + *dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ 1.193 + } \ 1.194 + else if (s1) \ 1.195 + { \ 1.196 + d = CONVERT_ ## DST_FORMAT ## _TO_8888 (*dst); \ 1.197 + s1 = CONVERT_ ## SRC_FORMAT ## _TO_8888 (s1); \ 1.198 + a1 ^= 0xff; \ 1.199 + UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \ 1.200 + *dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \ 1.201 + } \ 1.202 + dst++; \ 1.203 + \ 1.204 + if (a2 == 0xff) \ 1.205 + { \ 1.206 + *dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \ 1.207 + } \ 1.208 + else if (s2) \ 1.209 + { \ 1.210 + d = CONVERT_## DST_FORMAT ## _TO_8888 (*dst); \ 1.211 + s2 = CONVERT_## SRC_FORMAT ## _TO_8888 (s2); \ 1.212 + a2 ^= 0xff; \ 1.213 + UN8x4_MUL_UN8_ADD_UN8x4 (d, a2, s2); \ 1.214 + *dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \ 1.215 + } \ 1.216 + dst++; \ 1.217 + } \ 1.218 + else /* PIXMAN_OP_SRC */ \ 1.219 + { \ 1.220 + *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ 1.221 + *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s2); \ 1.222 + } \ 1.223 + } \ 1.224 + \ 1.225 + if (w & 1) \ 1.226 + { \ 1.227 + x1 = vx >> 16; \ 1.228 + s1 = src[x1]; \ 1.229 + \ 1.230 + if (PIXMAN_OP_ ## OP == PIXMAN_OP_OVER) \ 1.231 + { \ 1.232 + a1 = GET_ ## SRC_FORMAT ## _ALPHA(s1); \ 1.233 + \ 1.234 + if (a1 == 0xff) \ 1.235 + { \ 1.236 + *dst = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ 1.237 + } \ 1.238 + else if (s1) \ 1.239 + { \ 1.240 + d = CONVERT_## DST_FORMAT ## _TO_8888 (*dst); \ 1.241 + s1 = CONVERT_ ## SRC_FORMAT ## _TO_8888 (s1); \ 1.242 + a1 ^= 0xff; \ 1.243 + UN8x4_MUL_UN8_ADD_UN8x4 (d, a1, s1); \ 1.244 + *dst = CONVERT_8888_TO_ ## DST_FORMAT (d); \ 1.245 + } \ 1.246 + dst++; \ 1.247 + } \ 1.248 + else /* PIXMAN_OP_SRC */ \ 1.249 + { \ 1.250 + *dst++ = CONVERT_ ## SRC_FORMAT ## _TO_ ## DST_FORMAT (s1); \ 1.251 + } \ 1.252 + } \ 1.253 +} 1.254 + 1.255 +#define FAST_NEAREST_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t, \ 1.256 + dst_type_t, repeat_mode, have_mask, mask_is_solid) \ 1.257 +static void \ 1.258 +fast_composite_scaled_nearest ## scale_func_name (pixman_implementation_t *imp, \ 1.259 + pixman_op_t op, \ 1.260 + pixman_image_t * src_image, \ 1.261 + pixman_image_t * mask_image, \ 1.262 + pixman_image_t * dst_image, \ 1.263 + int32_t src_x, \ 1.264 + int32_t src_y, \ 1.265 + int32_t mask_x, \ 1.266 + int32_t mask_y, \ 1.267 + int32_t dst_x, \ 1.268 + int32_t dst_y, \ 1.269 + int32_t width, \ 1.270 + int32_t height) \ 1.271 +{ \ 1.272 + dst_type_t *dst_line; \ 1.273 + mask_type_t *mask_line; \ 1.274 + src_type_t *src_first_line; \ 1.275 + int y; \ 1.276 + pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */ \ 1.277 + pixman_fixed_t max_vy; \ 1.278 + pixman_vector_t v; \ 1.279 + pixman_fixed_t vx, vy; \ 1.280 + pixman_fixed_t unit_x, unit_y; \ 1.281 + int32_t left_pad, right_pad; \ 1.282 + \ 1.283 + src_type_t *src; \ 1.284 + dst_type_t *dst; \ 1.285 + mask_type_t solid_mask; \ 1.286 + const mask_type_t *mask = &solid_mask; \ 1.287 + int src_stride, mask_stride, dst_stride; \ 1.288 + \ 1.289 + PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1); \ 1.290 + if (have_mask) \ 1.291 + { \ 1.292 + if (mask_is_solid) \ 1.293 + solid_mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format); \ 1.294 + else \ 1.295 + PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t, \ 1.296 + mask_stride, mask_line, 1); \ 1.297 + } \ 1.298 + /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \ 1.299 + * transformed from destination space to source space */ \ 1.300 + PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \ 1.301 + \ 1.302 + /* reference point is the center of the pixel */ \ 1.303 + v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \ 1.304 + v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \ 1.305 + v.vector[2] = pixman_fixed_1; \ 1.306 + \ 1.307 + if (!pixman_transform_point_3d (src_image->common.transform, &v)) \ 1.308 + return; \ 1.309 + \ 1.310 + unit_x = src_image->common.transform->matrix[0][0]; \ 1.311 + unit_y = src_image->common.transform->matrix[1][1]; \ 1.312 + \ 1.313 + /* Round down to closest integer, ensuring that 0.5 rounds to 0, not 1 */ \ 1.314 + v.vector[0] -= pixman_fixed_e; \ 1.315 + v.vector[1] -= pixman_fixed_e; \ 1.316 + \ 1.317 + vx = v.vector[0]; \ 1.318 + vy = v.vector[1]; \ 1.319 + \ 1.320 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ 1.321 + { \ 1.322 + /* Clamp repeating positions inside the actual samples */ \ 1.323 + max_vx = src_image->bits.width << 16; \ 1.324 + max_vy = src_image->bits.height << 16; \ 1.325 + \ 1.326 + repeat (PIXMAN_REPEAT_NORMAL, &vx, max_vx); \ 1.327 + repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \ 1.328 + } \ 1.329 + \ 1.330 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \ 1.331 + PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ 1.332 + { \ 1.333 + pad_repeat_get_scanline_bounds (src_image->bits.width, vx, unit_x, \ 1.334 + &width, &left_pad, &right_pad); \ 1.335 + vx += left_pad * unit_x; \ 1.336 + } \ 1.337 + \ 1.338 + while (--height >= 0) \ 1.339 + { \ 1.340 + dst = dst_line; \ 1.341 + dst_line += dst_stride; \ 1.342 + if (have_mask && !mask_is_solid) \ 1.343 + { \ 1.344 + mask = mask_line; \ 1.345 + mask_line += mask_stride; \ 1.346 + } \ 1.347 + \ 1.348 + y = vy >> 16; \ 1.349 + vy += unit_y; \ 1.350 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NORMAL) \ 1.351 + repeat (PIXMAN_REPEAT_NORMAL, &vy, max_vy); \ 1.352 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ 1.353 + { \ 1.354 + repeat (PIXMAN_REPEAT_PAD, &y, src_image->bits.height); \ 1.355 + src = src_first_line + src_stride * y; \ 1.356 + if (left_pad > 0) \ 1.357 + { \ 1.358 + scanline_func (mask, dst, src, left_pad, 0, 0, 0, FALSE); \ 1.359 + } \ 1.360 + if (width > 0) \ 1.361 + { \ 1.362 + scanline_func (mask + (mask_is_solid ? 0 : left_pad), \ 1.363 + dst + left_pad, src, width, vx, unit_x, 0, FALSE); \ 1.364 + } \ 1.365 + if (right_pad > 0) \ 1.366 + { \ 1.367 + scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \ 1.368 + dst + left_pad + width, src + src_image->bits.width - 1, \ 1.369 + right_pad, 0, 0, 0, FALSE); \ 1.370 + } \ 1.371 + } \ 1.372 + else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ 1.373 + { \ 1.374 + static const src_type_t zero[1] = { 0 }; \ 1.375 + if (y < 0 || y >= src_image->bits.height) \ 1.376 + { \ 1.377 + scanline_func (mask, dst, zero, left_pad + width + right_pad, 0, 0, 0, TRUE); \ 1.378 + continue; \ 1.379 + } \ 1.380 + src = src_first_line + src_stride * y; \ 1.381 + if (left_pad > 0) \ 1.382 + { \ 1.383 + scanline_func (mask, dst, zero, left_pad, 0, 0, 0, TRUE); \ 1.384 + } \ 1.385 + if (width > 0) \ 1.386 + { \ 1.387 + scanline_func (mask + (mask_is_solid ? 0 : left_pad), \ 1.388 + dst + left_pad, src, width, vx, unit_x, 0, FALSE); \ 1.389 + } \ 1.390 + if (right_pad > 0) \ 1.391 + { \ 1.392 + scanline_func (mask + (mask_is_solid ? 0 : left_pad + width), \ 1.393 + dst + left_pad + width, zero, right_pad, 0, 0, 0, TRUE); \ 1.394 + } \ 1.395 + } \ 1.396 + else \ 1.397 + { \ 1.398 + src = src_first_line + src_stride * y; \ 1.399 + scanline_func (mask, dst, src, width, vx, unit_x, max_vx, FALSE); \ 1.400 + } \ 1.401 + } \ 1.402 +} 1.403 + 1.404 +/* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */ 1.405 +#define FAST_NEAREST_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t, \ 1.406 + dst_type_t, repeat_mode, have_mask, mask_is_solid) \ 1.407 + FAST_NEAREST_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t, \ 1.408 + dst_type_t, repeat_mode, have_mask, mask_is_solid) 1.409 + 1.410 +#define FAST_NEAREST_MAINLOOP_NOMASK(scale_func_name, scanline_func, src_type_t, dst_type_t, \ 1.411 + repeat_mode) \ 1.412 + static force_inline void \ 1.413 + scanline_func##scale_func_name##_wrapper ( \ 1.414 + const uint8_t *mask, \ 1.415 + dst_type_t *dst, \ 1.416 + const src_type_t *src, \ 1.417 + int32_t w, \ 1.418 + pixman_fixed_t vx, \ 1.419 + pixman_fixed_t unit_x, \ 1.420 + pixman_fixed_t max_vx, \ 1.421 + pixman_bool_t fully_transparent_src) \ 1.422 + { \ 1.423 + scanline_func (dst, src, w, vx, unit_x, max_vx, fully_transparent_src); \ 1.424 + } \ 1.425 + FAST_NEAREST_MAINLOOP_INT (scale_func_name, scanline_func##scale_func_name##_wrapper, \ 1.426 + src_type_t, uint8_t, dst_type_t, repeat_mode, FALSE, FALSE) 1.427 + 1.428 +#define FAST_NEAREST_MAINLOOP(scale_func_name, scanline_func, src_type_t, dst_type_t, \ 1.429 + repeat_mode) \ 1.430 + FAST_NEAREST_MAINLOOP_NOMASK(_ ## scale_func_name, scanline_func, src_type_t, \ 1.431 + dst_type_t, repeat_mode) 1.432 + 1.433 +#define FAST_NEAREST(scale_func_name, SRC_FORMAT, DST_FORMAT, \ 1.434 + src_type_t, dst_type_t, OP, repeat_mode) \ 1.435 + FAST_NEAREST_SCANLINE(scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \ 1.436 + SRC_FORMAT, DST_FORMAT, src_type_t, dst_type_t, \ 1.437 + OP, repeat_mode) \ 1.438 + FAST_NEAREST_MAINLOOP_NOMASK(_ ## scale_func_name ## _ ## OP, \ 1.439 + scaled_nearest_scanline_ ## scale_func_name ## _ ## OP, \ 1.440 + src_type_t, dst_type_t, repeat_mode) 1.441 + 1.442 + 1.443 +#define SCALED_NEAREST_FLAGS \ 1.444 + (FAST_PATH_SCALE_TRANSFORM | \ 1.445 + FAST_PATH_NO_ALPHA_MAP | \ 1.446 + FAST_PATH_NEAREST_FILTER | \ 1.447 + FAST_PATH_NO_ACCESSORS | \ 1.448 + FAST_PATH_NARROW_FORMAT) 1.449 + 1.450 +#define SIMPLE_NEAREST_FAST_PATH_NORMAL(op,s,d,func) \ 1.451 + { PIXMAN_OP_ ## op, \ 1.452 + PIXMAN_ ## s, \ 1.453 + (SCALED_NEAREST_FLAGS | \ 1.454 + FAST_PATH_NORMAL_REPEAT | \ 1.455 + FAST_PATH_X_UNIT_POSITIVE), \ 1.456 + PIXMAN_null, 0, \ 1.457 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.458 + fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ 1.459 + } 1.460 + 1.461 +#define SIMPLE_NEAREST_FAST_PATH_PAD(op,s,d,func) \ 1.462 + { PIXMAN_OP_ ## op, \ 1.463 + PIXMAN_ ## s, \ 1.464 + (SCALED_NEAREST_FLAGS | \ 1.465 + FAST_PATH_PAD_REPEAT | \ 1.466 + FAST_PATH_X_UNIT_POSITIVE), \ 1.467 + PIXMAN_null, 0, \ 1.468 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.469 + fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ 1.470 + } 1.471 + 1.472 +#define SIMPLE_NEAREST_FAST_PATH_NONE(op,s,d,func) \ 1.473 + { PIXMAN_OP_ ## op, \ 1.474 + PIXMAN_ ## s, \ 1.475 + (SCALED_NEAREST_FLAGS | \ 1.476 + FAST_PATH_NONE_REPEAT | \ 1.477 + FAST_PATH_X_UNIT_POSITIVE), \ 1.478 + PIXMAN_null, 0, \ 1.479 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.480 + fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ 1.481 + } 1.482 + 1.483 +#define SIMPLE_NEAREST_FAST_PATH_COVER(op,s,d,func) \ 1.484 + { PIXMAN_OP_ ## op, \ 1.485 + PIXMAN_ ## s, \ 1.486 + SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ 1.487 + PIXMAN_null, 0, \ 1.488 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.489 + fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ 1.490 + } 1.491 + 1.492 +#define SIMPLE_NEAREST_A8_MASK_FAST_PATH_NORMAL(op,s,d,func) \ 1.493 + { PIXMAN_OP_ ## op, \ 1.494 + PIXMAN_ ## s, \ 1.495 + (SCALED_NEAREST_FLAGS | \ 1.496 + FAST_PATH_NORMAL_REPEAT | \ 1.497 + FAST_PATH_X_UNIT_POSITIVE), \ 1.498 + PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ 1.499 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.500 + fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ 1.501 + } 1.502 + 1.503 +#define SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD(op,s,d,func) \ 1.504 + { PIXMAN_OP_ ## op, \ 1.505 + PIXMAN_ ## s, \ 1.506 + (SCALED_NEAREST_FLAGS | \ 1.507 + FAST_PATH_PAD_REPEAT | \ 1.508 + FAST_PATH_X_UNIT_POSITIVE), \ 1.509 + PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ 1.510 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.511 + fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ 1.512 + } 1.513 + 1.514 +#define SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE(op,s,d,func) \ 1.515 + { PIXMAN_OP_ ## op, \ 1.516 + PIXMAN_ ## s, \ 1.517 + (SCALED_NEAREST_FLAGS | \ 1.518 + FAST_PATH_NONE_REPEAT | \ 1.519 + FAST_PATH_X_UNIT_POSITIVE), \ 1.520 + PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ 1.521 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.522 + fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ 1.523 + } 1.524 + 1.525 +#define SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER(op,s,d,func) \ 1.526 + { PIXMAN_OP_ ## op, \ 1.527 + PIXMAN_ ## s, \ 1.528 + SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ 1.529 + PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ 1.530 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.531 + fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ 1.532 + } 1.533 + 1.534 +#define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NORMAL(op,s,d,func) \ 1.535 + { PIXMAN_OP_ ## op, \ 1.536 + PIXMAN_ ## s, \ 1.537 + (SCALED_NEAREST_FLAGS | \ 1.538 + FAST_PATH_NORMAL_REPEAT | \ 1.539 + FAST_PATH_X_UNIT_POSITIVE), \ 1.540 + PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ 1.541 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.542 + fast_composite_scaled_nearest_ ## func ## _normal ## _ ## op, \ 1.543 + } 1.544 + 1.545 +#define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD(op,s,d,func) \ 1.546 + { PIXMAN_OP_ ## op, \ 1.547 + PIXMAN_ ## s, \ 1.548 + (SCALED_NEAREST_FLAGS | \ 1.549 + FAST_PATH_PAD_REPEAT | \ 1.550 + FAST_PATH_X_UNIT_POSITIVE), \ 1.551 + PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ 1.552 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.553 + fast_composite_scaled_nearest_ ## func ## _pad ## _ ## op, \ 1.554 + } 1.555 + 1.556 +#define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE(op,s,d,func) \ 1.557 + { PIXMAN_OP_ ## op, \ 1.558 + PIXMAN_ ## s, \ 1.559 + (SCALED_NEAREST_FLAGS | \ 1.560 + FAST_PATH_NONE_REPEAT | \ 1.561 + FAST_PATH_X_UNIT_POSITIVE), \ 1.562 + PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ 1.563 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.564 + fast_composite_scaled_nearest_ ## func ## _none ## _ ## op, \ 1.565 + } 1.566 + 1.567 +#define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER(op,s,d,func) \ 1.568 + { PIXMAN_OP_ ## op, \ 1.569 + PIXMAN_ ## s, \ 1.570 + SCALED_NEAREST_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ 1.571 + PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ 1.572 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.573 + fast_composite_scaled_nearest_ ## func ## _cover ## _ ## op, \ 1.574 + } 1.575 + 1.576 +/* Prefer the use of 'cover' variant, because it is faster */ 1.577 +#define SIMPLE_NEAREST_FAST_PATH(op,s,d,func) \ 1.578 + SIMPLE_NEAREST_FAST_PATH_COVER (op,s,d,func), \ 1.579 + SIMPLE_NEAREST_FAST_PATH_NONE (op,s,d,func), \ 1.580 + SIMPLE_NEAREST_FAST_PATH_PAD (op,s,d,func), \ 1.581 + SIMPLE_NEAREST_FAST_PATH_NORMAL (op,s,d,func) 1.582 + 1.583 +#define SIMPLE_NEAREST_A8_MASK_FAST_PATH(op,s,d,func) \ 1.584 + SIMPLE_NEAREST_A8_MASK_FAST_PATH_COVER (op,s,d,func), \ 1.585 + SIMPLE_NEAREST_A8_MASK_FAST_PATH_NONE (op,s,d,func), \ 1.586 + SIMPLE_NEAREST_A8_MASK_FAST_PATH_PAD (op,s,d,func) 1.587 + 1.588 +#define SIMPLE_NEAREST_SOLID_MASK_FAST_PATH(op,s,d,func) \ 1.589 + SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \ 1.590 + SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \ 1.591 + SIMPLE_NEAREST_SOLID_MASK_FAST_PATH_PAD (op,s,d,func) 1.592 + 1.593 +/*****************************************************************************/ 1.594 + 1.595 +/* 1.596 + * Identify 5 zones in each scanline for bilinear scaling. Depending on 1.597 + * whether 2 pixels to be interpolated are fetched from the image itself, 1.598 + * from the padding area around it or from both image and padding area. 1.599 + */ 1.600 +static force_inline void 1.601 +bilinear_pad_repeat_get_scanline_bounds (int32_t source_image_width, 1.602 + pixman_fixed_t vx, 1.603 + pixman_fixed_t unit_x, 1.604 + int32_t * left_pad, 1.605 + int32_t * left_tz, 1.606 + int32_t * width, 1.607 + int32_t * right_tz, 1.608 + int32_t * right_pad) 1.609 +{ 1.610 + int width1 = *width, left_pad1, right_pad1; 1.611 + int width2 = *width, left_pad2, right_pad2; 1.612 + 1.613 + pad_repeat_get_scanline_bounds (source_image_width, vx, unit_x, 1.614 + &width1, &left_pad1, &right_pad1); 1.615 + pad_repeat_get_scanline_bounds (source_image_width, vx + pixman_fixed_1, 1.616 + unit_x, &width2, &left_pad2, &right_pad2); 1.617 + 1.618 + *left_pad = left_pad2; 1.619 + *left_tz = left_pad1 - left_pad2; 1.620 + *right_tz = right_pad2 - right_pad1; 1.621 + *right_pad = right_pad1; 1.622 + *width -= *left_pad + *left_tz + *right_tz + *right_pad; 1.623 +} 1.624 + 1.625 +/* 1.626 + * Main loop template for single pass bilinear scaling. It needs to be 1.627 + * provided with 'scanline_func' which should do the compositing operation. 1.628 + * The needed function has the following prototype: 1.629 + * 1.630 + * scanline_func (dst_type_t * dst, 1.631 + * const mask_type_ * mask, 1.632 + * const src_type_t * src_top, 1.633 + * const src_type_t * src_bottom, 1.634 + * int32_t width, 1.635 + * int weight_top, 1.636 + * int weight_bottom, 1.637 + * pixman_fixed_t vx, 1.638 + * pixman_fixed_t unit_x, 1.639 + * pixman_fixed_t max_vx, 1.640 + * pixman_bool_t zero_src) 1.641 + * 1.642 + * Where: 1.643 + * dst - destination scanline buffer for storing results 1.644 + * mask - mask buffer (or single value for solid mask) 1.645 + * src_top, src_bottom - two source scanlines 1.646 + * width - number of pixels to process 1.647 + * weight_top - weight of the top row for interpolation 1.648 + * weight_bottom - weight of the bottom row for interpolation 1.649 + * vx - initial position for fetching the first pair of 1.650 + * pixels from the source buffer 1.651 + * unit_x - position increment needed to move to the next pair 1.652 + * of pixels 1.653 + * max_vx - image size as a fixed point value, can be used for 1.654 + * implementing NORMAL repeat (when it is supported) 1.655 + * zero_src - boolean hint variable, which is set to TRUE when 1.656 + * all source pixels are fetched from zero padding 1.657 + * zone for NONE repeat 1.658 + * 1.659 + * Note: normally the sum of 'weight_top' and 'weight_bottom' is equal to 256, 1.660 + * but sometimes it may be less than that for NONE repeat when handling 1.661 + * fuzzy antialiased top or bottom image edges. Also both top and 1.662 + * bottom weight variables are guaranteed to have value in 0-255 1.663 + * range and can fit into unsigned byte or be used with 8-bit SIMD 1.664 + * multiplication instructions. 1.665 + */ 1.666 +#define FAST_BILINEAR_MAINLOOP_INT(scale_func_name, scanline_func, src_type_t, mask_type_t, \ 1.667 + dst_type_t, repeat_mode, have_mask, mask_is_solid) \ 1.668 +static void \ 1.669 +fast_composite_scaled_bilinear ## scale_func_name (pixman_implementation_t *imp, \ 1.670 + pixman_op_t op, \ 1.671 + pixman_image_t * src_image, \ 1.672 + pixman_image_t * mask_image, \ 1.673 + pixman_image_t * dst_image, \ 1.674 + int32_t src_x, \ 1.675 + int32_t src_y, \ 1.676 + int32_t mask_x, \ 1.677 + int32_t mask_y, \ 1.678 + int32_t dst_x, \ 1.679 + int32_t dst_y, \ 1.680 + int32_t width, \ 1.681 + int32_t height) \ 1.682 +{ \ 1.683 + dst_type_t *dst_line; \ 1.684 + mask_type_t *mask_line; \ 1.685 + src_type_t *src_first_line; \ 1.686 + int y1, y2; \ 1.687 + pixman_fixed_t max_vx = INT32_MAX; /* suppress uninitialized variable warning */ \ 1.688 + pixman_vector_t v; \ 1.689 + pixman_fixed_t vx, vy; \ 1.690 + pixman_fixed_t unit_x, unit_y; \ 1.691 + int32_t left_pad, left_tz, right_tz, right_pad; \ 1.692 + \ 1.693 + dst_type_t *dst; \ 1.694 + mask_type_t solid_mask; \ 1.695 + const mask_type_t *mask = &solid_mask; \ 1.696 + int src_stride, mask_stride, dst_stride; \ 1.697 + \ 1.698 + PIXMAN_IMAGE_GET_LINE (dst_image, dst_x, dst_y, dst_type_t, dst_stride, dst_line, 1); \ 1.699 + if (have_mask) \ 1.700 + { \ 1.701 + if (mask_is_solid) \ 1.702 + { \ 1.703 + solid_mask = _pixman_image_get_solid (imp, mask_image, dst_image->bits.format); \ 1.704 + mask_stride = 0; \ 1.705 + } \ 1.706 + else \ 1.707 + { \ 1.708 + PIXMAN_IMAGE_GET_LINE (mask_image, mask_x, mask_y, mask_type_t, \ 1.709 + mask_stride, mask_line, 1); \ 1.710 + } \ 1.711 + } \ 1.712 + /* pass in 0 instead of src_x and src_y because src_x and src_y need to be \ 1.713 + * transformed from destination space to source space */ \ 1.714 + PIXMAN_IMAGE_GET_LINE (src_image, 0, 0, src_type_t, src_stride, src_first_line, 1); \ 1.715 + \ 1.716 + /* reference point is the center of the pixel */ \ 1.717 + v.vector[0] = pixman_int_to_fixed (src_x) + pixman_fixed_1 / 2; \ 1.718 + v.vector[1] = pixman_int_to_fixed (src_y) + pixman_fixed_1 / 2; \ 1.719 + v.vector[2] = pixman_fixed_1; \ 1.720 + \ 1.721 + if (!pixman_transform_point_3d (src_image->common.transform, &v)) \ 1.722 + return; \ 1.723 + \ 1.724 + unit_x = src_image->common.transform->matrix[0][0]; \ 1.725 + unit_y = src_image->common.transform->matrix[1][1]; \ 1.726 + \ 1.727 + v.vector[0] -= pixman_fixed_1 / 2; \ 1.728 + v.vector[1] -= pixman_fixed_1 / 2; \ 1.729 + \ 1.730 + vy = v.vector[1]; \ 1.731 + \ 1.732 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD || \ 1.733 + PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ 1.734 + { \ 1.735 + bilinear_pad_repeat_get_scanline_bounds (src_image->bits.width, v.vector[0], unit_x, \ 1.736 + &left_pad, &left_tz, &width, &right_tz, &right_pad); \ 1.737 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ 1.738 + { \ 1.739 + /* PAD repeat does not need special handling for 'transition zones' and */ \ 1.740 + /* they can be combined with 'padding zones' safely */ \ 1.741 + left_pad += left_tz; \ 1.742 + right_pad += right_tz; \ 1.743 + left_tz = right_tz = 0; \ 1.744 + } \ 1.745 + v.vector[0] += left_pad * unit_x; \ 1.746 + } \ 1.747 + \ 1.748 + while (--height >= 0) \ 1.749 + { \ 1.750 + int weight1, weight2; \ 1.751 + dst = dst_line; \ 1.752 + dst_line += dst_stride; \ 1.753 + vx = v.vector[0]; \ 1.754 + if (have_mask && !mask_is_solid) \ 1.755 + { \ 1.756 + mask = mask_line; \ 1.757 + mask_line += mask_stride; \ 1.758 + } \ 1.759 + \ 1.760 + y1 = pixman_fixed_to_int (vy); \ 1.761 + weight2 = (vy >> 8) & 0xff; \ 1.762 + if (weight2) \ 1.763 + { \ 1.764 + /* normal case, both row weights are in 0-255 range and fit unsigned byte */ \ 1.765 + y2 = y1 + 1; \ 1.766 + weight1 = 256 - weight2; \ 1.767 + } \ 1.768 + else \ 1.769 + { \ 1.770 + /* set both top and bottom row to the same scanline, and weights to 128+128 */ \ 1.771 + y2 = y1; \ 1.772 + weight1 = weight2 = 128; \ 1.773 + } \ 1.774 + vy += unit_y; \ 1.775 + if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_PAD) \ 1.776 + { \ 1.777 + src_type_t *src1, *src2; \ 1.778 + src_type_t buf1[2]; \ 1.779 + src_type_t buf2[2]; \ 1.780 + repeat (PIXMAN_REPEAT_PAD, &y1, src_image->bits.height); \ 1.781 + repeat (PIXMAN_REPEAT_PAD, &y2, src_image->bits.height); \ 1.782 + src1 = src_first_line + src_stride * y1; \ 1.783 + src2 = src_first_line + src_stride * y2; \ 1.784 + \ 1.785 + if (left_pad > 0) \ 1.786 + { \ 1.787 + buf1[0] = buf1[1] = src1[0]; \ 1.788 + buf2[0] = buf2[1] = src2[0]; \ 1.789 + scanline_func (dst, mask, \ 1.790 + buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, FALSE); \ 1.791 + dst += left_pad; \ 1.792 + if (have_mask && !mask_is_solid) \ 1.793 + mask += left_pad; \ 1.794 + } \ 1.795 + if (width > 0) \ 1.796 + { \ 1.797 + scanline_func (dst, mask, \ 1.798 + src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \ 1.799 + dst += width; \ 1.800 + if (have_mask && !mask_is_solid) \ 1.801 + mask += width; \ 1.802 + } \ 1.803 + if (right_pad > 0) \ 1.804 + { \ 1.805 + buf1[0] = buf1[1] = src1[src_image->bits.width - 1]; \ 1.806 + buf2[0] = buf2[1] = src2[src_image->bits.width - 1]; \ 1.807 + scanline_func (dst, mask, \ 1.808 + buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, FALSE); \ 1.809 + } \ 1.810 + } \ 1.811 + else if (PIXMAN_REPEAT_ ## repeat_mode == PIXMAN_REPEAT_NONE) \ 1.812 + { \ 1.813 + src_type_t *src1, *src2; \ 1.814 + src_type_t buf1[2]; \ 1.815 + src_type_t buf2[2]; \ 1.816 + /* handle top/bottom zero padding by just setting weights to 0 if needed */ \ 1.817 + if (y1 < 0) \ 1.818 + { \ 1.819 + weight1 = 0; \ 1.820 + y1 = 0; \ 1.821 + } \ 1.822 + if (y1 >= src_image->bits.height) \ 1.823 + { \ 1.824 + weight1 = 0; \ 1.825 + y1 = src_image->bits.height - 1; \ 1.826 + } \ 1.827 + if (y2 < 0) \ 1.828 + { \ 1.829 + weight2 = 0; \ 1.830 + y2 = 0; \ 1.831 + } \ 1.832 + if (y2 >= src_image->bits.height) \ 1.833 + { \ 1.834 + weight2 = 0; \ 1.835 + y2 = src_image->bits.height - 1; \ 1.836 + } \ 1.837 + src1 = src_first_line + src_stride * y1; \ 1.838 + src2 = src_first_line + src_stride * y2; \ 1.839 + \ 1.840 + if (left_pad > 0) \ 1.841 + { \ 1.842 + buf1[0] = buf1[1] = 0; \ 1.843 + buf2[0] = buf2[1] = 0; \ 1.844 + scanline_func (dst, mask, \ 1.845 + buf1, buf2, left_pad, weight1, weight2, 0, 0, 0, TRUE); \ 1.846 + dst += left_pad; \ 1.847 + if (have_mask && !mask_is_solid) \ 1.848 + mask += left_pad; \ 1.849 + } \ 1.850 + if (left_tz > 0) \ 1.851 + { \ 1.852 + buf1[0] = 0; \ 1.853 + buf1[1] = src1[0]; \ 1.854 + buf2[0] = 0; \ 1.855 + buf2[1] = src2[0]; \ 1.856 + scanline_func (dst, mask, \ 1.857 + buf1, buf2, left_tz, weight1, weight2, \ 1.858 + pixman_fixed_frac (vx), unit_x, 0, FALSE); \ 1.859 + dst += left_tz; \ 1.860 + if (have_mask && !mask_is_solid) \ 1.861 + mask += left_tz; \ 1.862 + vx += left_tz * unit_x; \ 1.863 + } \ 1.864 + if (width > 0) \ 1.865 + { \ 1.866 + scanline_func (dst, mask, \ 1.867 + src1, src2, width, weight1, weight2, vx, unit_x, 0, FALSE); \ 1.868 + dst += width; \ 1.869 + if (have_mask && !mask_is_solid) \ 1.870 + mask += width; \ 1.871 + vx += width * unit_x; \ 1.872 + } \ 1.873 + if (right_tz > 0) \ 1.874 + { \ 1.875 + buf1[0] = src1[src_image->bits.width - 1]; \ 1.876 + buf1[1] = 0; \ 1.877 + buf2[0] = src2[src_image->bits.width - 1]; \ 1.878 + buf2[1] = 0; \ 1.879 + scanline_func (dst, mask, \ 1.880 + buf1, buf2, right_tz, weight1, weight2, \ 1.881 + pixman_fixed_frac (vx), unit_x, 0, FALSE); \ 1.882 + dst += right_tz; \ 1.883 + if (have_mask && !mask_is_solid) \ 1.884 + mask += right_tz; \ 1.885 + } \ 1.886 + if (right_pad > 0) \ 1.887 + { \ 1.888 + buf1[0] = buf1[1] = 0; \ 1.889 + buf2[0] = buf2[1] = 0; \ 1.890 + scanline_func (dst, mask, \ 1.891 + buf1, buf2, right_pad, weight1, weight2, 0, 0, 0, TRUE); \ 1.892 + } \ 1.893 + } \ 1.894 + else \ 1.895 + { \ 1.896 + scanline_func (dst, mask, src_first_line + src_stride * y1, \ 1.897 + src_first_line + src_stride * y2, width, \ 1.898 + weight1, weight2, vx, unit_x, max_vx, FALSE); \ 1.899 + } \ 1.900 + } \ 1.901 +} 1.902 + 1.903 +/* A workaround for old sun studio, see: https://bugs.freedesktop.org/show_bug.cgi?id=32764 */ 1.904 +#define FAST_BILINEAR_MAINLOOP_COMMON(scale_func_name, scanline_func, src_type_t, mask_type_t, \ 1.905 + dst_type_t, repeat_mode, have_mask, mask_is_solid) \ 1.906 + FAST_BILINEAR_MAINLOOP_INT(_ ## scale_func_name, scanline_func, src_type_t, mask_type_t,\ 1.907 + dst_type_t, repeat_mode, have_mask, mask_is_solid) 1.908 + 1.909 +#define SCALED_BILINEAR_FLAGS \ 1.910 + (FAST_PATH_SCALE_TRANSFORM | \ 1.911 + FAST_PATH_NO_ALPHA_MAP | \ 1.912 + FAST_PATH_BILINEAR_FILTER | \ 1.913 + FAST_PATH_NO_ACCESSORS | \ 1.914 + FAST_PATH_NARROW_FORMAT) 1.915 + 1.916 +#define SIMPLE_BILINEAR_FAST_PATH_PAD(op,s,d,func) \ 1.917 + { PIXMAN_OP_ ## op, \ 1.918 + PIXMAN_ ## s, \ 1.919 + (SCALED_BILINEAR_FLAGS | \ 1.920 + FAST_PATH_PAD_REPEAT | \ 1.921 + FAST_PATH_X_UNIT_POSITIVE), \ 1.922 + PIXMAN_null, 0, \ 1.923 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.924 + fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ 1.925 + } 1.926 + 1.927 +#define SIMPLE_BILINEAR_FAST_PATH_NONE(op,s,d,func) \ 1.928 + { PIXMAN_OP_ ## op, \ 1.929 + PIXMAN_ ## s, \ 1.930 + (SCALED_BILINEAR_FLAGS | \ 1.931 + FAST_PATH_NONE_REPEAT | \ 1.932 + FAST_PATH_X_UNIT_POSITIVE), \ 1.933 + PIXMAN_null, 0, \ 1.934 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.935 + fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ 1.936 + } 1.937 + 1.938 +#define SIMPLE_BILINEAR_FAST_PATH_COVER(op,s,d,func) \ 1.939 + { PIXMAN_OP_ ## op, \ 1.940 + PIXMAN_ ## s, \ 1.941 + SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ 1.942 + PIXMAN_null, 0, \ 1.943 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.944 + fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ 1.945 + } 1.946 + 1.947 +#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD(op,s,d,func) \ 1.948 + { PIXMAN_OP_ ## op, \ 1.949 + PIXMAN_ ## s, \ 1.950 + (SCALED_BILINEAR_FLAGS | \ 1.951 + FAST_PATH_PAD_REPEAT | \ 1.952 + FAST_PATH_X_UNIT_POSITIVE), \ 1.953 + PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ 1.954 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.955 + fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ 1.956 + } 1.957 + 1.958 +#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE(op,s,d,func) \ 1.959 + { PIXMAN_OP_ ## op, \ 1.960 + PIXMAN_ ## s, \ 1.961 + (SCALED_BILINEAR_FLAGS | \ 1.962 + FAST_PATH_NONE_REPEAT | \ 1.963 + FAST_PATH_X_UNIT_POSITIVE), \ 1.964 + PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ 1.965 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.966 + fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ 1.967 + } 1.968 + 1.969 +#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER(op,s,d,func) \ 1.970 + { PIXMAN_OP_ ## op, \ 1.971 + PIXMAN_ ## s, \ 1.972 + SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ 1.973 + PIXMAN_a8, MASK_FLAGS (a8, FAST_PATH_UNIFIED_ALPHA), \ 1.974 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.975 + fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ 1.976 + } 1.977 + 1.978 +#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD(op,s,d,func) \ 1.979 + { PIXMAN_OP_ ## op, \ 1.980 + PIXMAN_ ## s, \ 1.981 + (SCALED_BILINEAR_FLAGS | \ 1.982 + FAST_PATH_PAD_REPEAT | \ 1.983 + FAST_PATH_X_UNIT_POSITIVE), \ 1.984 + PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ 1.985 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.986 + fast_composite_scaled_bilinear_ ## func ## _pad ## _ ## op, \ 1.987 + } 1.988 + 1.989 +#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE(op,s,d,func) \ 1.990 + { PIXMAN_OP_ ## op, \ 1.991 + PIXMAN_ ## s, \ 1.992 + (SCALED_BILINEAR_FLAGS | \ 1.993 + FAST_PATH_NONE_REPEAT | \ 1.994 + FAST_PATH_X_UNIT_POSITIVE), \ 1.995 + PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ 1.996 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.997 + fast_composite_scaled_bilinear_ ## func ## _none ## _ ## op, \ 1.998 + } 1.999 + 1.1000 +#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER(op,s,d,func) \ 1.1001 + { PIXMAN_OP_ ## op, \ 1.1002 + PIXMAN_ ## s, \ 1.1003 + SCALED_BILINEAR_FLAGS | FAST_PATH_SAMPLES_COVER_CLIP, \ 1.1004 + PIXMAN_solid, MASK_FLAGS (solid, FAST_PATH_UNIFIED_ALPHA), \ 1.1005 + PIXMAN_ ## d, FAST_PATH_STD_DEST_FLAGS, \ 1.1006 + fast_composite_scaled_bilinear_ ## func ## _cover ## _ ## op, \ 1.1007 + } 1.1008 + 1.1009 +/* Prefer the use of 'cover' variant, because it is faster */ 1.1010 +#define SIMPLE_BILINEAR_FAST_PATH(op,s,d,func) \ 1.1011 + SIMPLE_BILINEAR_FAST_PATH_COVER (op,s,d,func), \ 1.1012 + SIMPLE_BILINEAR_FAST_PATH_NONE (op,s,d,func), \ 1.1013 + SIMPLE_BILINEAR_FAST_PATH_PAD (op,s,d,func) 1.1014 + 1.1015 +#define SIMPLE_BILINEAR_A8_MASK_FAST_PATH(op,s,d,func) \ 1.1016 + SIMPLE_BILINEAR_A8_MASK_FAST_PATH_COVER (op,s,d,func), \ 1.1017 + SIMPLE_BILINEAR_A8_MASK_FAST_PATH_NONE (op,s,d,func), \ 1.1018 + SIMPLE_BILINEAR_A8_MASK_FAST_PATH_PAD (op,s,d,func) 1.1019 + 1.1020 +#define SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH(op,s,d,func) \ 1.1021 + SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_COVER (op,s,d,func), \ 1.1022 + SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_NONE (op,s,d,func), \ 1.1023 + SIMPLE_BILINEAR_SOLID_MASK_FAST_PATH_PAD (op,s,d,func) 1.1024 + 1.1025 +#endif