LCOV - code coverage report
Current view: directory - gfx/cairo/libpixman/src - pixman-fast-path.h (source / functions) Found Hit Coverage
Test: app.info Lines: 39 21 53.8 %
Date: 2012-06-02 Functions: 0 0 -

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

Generated by: LCOV version 1.7