14f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger/* NEON optimized code (C) COPYRIGHT 2009 Motorola
24f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger *
34f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * Use of this source code is governed by a BSD-style license that can be
44f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger * found in the LICENSE file.
54f1dae40e24d57d647db01443b8bf2410514b8b5Derek Sollenberger */
63600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
70910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmapProcState.h"
80910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkPerspIter.h"
90910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkShader.h"
109a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#include "SkUtils.h"
119a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
129a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed/*  returns 0...(n-1) given any x (positive or negative).
139a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
149a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    As an example, if n (which is always positive) is 5...
159a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
169a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed          x: -8 -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  8
179a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    returns:  2  3  4  0  1  2  3  4  0  1  2  3  4  0  1  2  3
189a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed */
199a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic inline int sk_int_mod(int x, int n) {
209a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    SkASSERT(n > 0);
219a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if ((unsigned)x >= (unsigned)n) {
229a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (x < 0) {
239a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            x = n + ~(~x % n);
249a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        } else {
259a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            x = x % n;
269a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
279a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
289a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    return x;
299a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
300910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
310910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
320910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
330910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
340910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define MAKENAME(suffix)        ClampX_ClampY ## suffix
350910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEX_PROCF(fx, max)    SkClampMax((fx) >> 16, max)
360910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEY_PROCF(fy, max)    SkClampMax((fy) >> 16, max)
370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
380910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
390910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define CHECK_FOR_DECAL
403600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#if	defined(__ARM_HAVE_NEON)
413600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    #include "SkBitmapProcState_matrix_clamp.h"
423600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#else
433600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    #include "SkBitmapProcState_matrix.h"
443600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#endif
450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
460910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define MAKENAME(suffix)        RepeatX_RepeatY ## suffix
470910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEX_PROCF(fx, max)    (((fx) & 0xFFFF) * ((max) + 1) >> 16)
480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEY_PROCF(fy, max)    (((fy) & 0xFFFF) * ((max) + 1) >> 16)
490910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
500910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
513600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#if	defined(__ARM_HAVE_NEON)
523600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    #include "SkBitmapProcState_matrix_repeat.h"
533600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#else
543600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    #include "SkBitmapProcState_matrix.h"
553600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#endif
560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define MAKENAME(suffix)        GeneralXY ## suffix
580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define PREAMBLE(state)         SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; \
590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project                                SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY
600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define PREAMBLE_PARAM_X        , SkBitmapProcState::FixedTileProc tileProcX
610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define PREAMBLE_PARAM_Y        , SkBitmapProcState::FixedTileProc tileProcY
620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define PREAMBLE_ARG_X          , tileProcX
630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define PREAMBLE_ARG_Y          , tileProcY
640910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEX_PROCF(fx, max)    (tileProcX(fx) * ((max) + 1) >> 16)
650910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEY_PROCF(fy, max)    (tileProcY(fy) * ((max) + 1) >> 16)
660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx) * ((max) + 1) >> 12) & 0xF)
670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy) * ((max) + 1) >> 12) & 0xF)
680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#include "SkBitmapProcState_matrix.h"
690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU fixed_clamp(SkFixed x)
710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (x >> 16)
740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        x = 0xFFFF;
750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (x < 0)
760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        x = 0;
770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#else
780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (x >> 16)
790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        if (x < 0)
810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            x = 0;
820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        else
830910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project            x = 0xFFFF;
840910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
850910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project#endif
860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return x;
870910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
880910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
890910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU fixed_repeat(SkFixed x)
900910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
910910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return x & 0xFFFF;
920910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
930910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
940910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic inline U16CPU fixed_mirror(SkFixed x)
950910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
960910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkFixed s = x << 15 >> 31;
970910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
980910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return (x ^ s) & 0xFFFF;
990910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1000910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1010910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectstatic SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
1020910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1030910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (SkShader::kClamp_TileMode == m)
1040910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return fixed_clamp;
1050910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (SkShader::kRepeat_TileMode == m)
1060910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        return fixed_repeat;
1070910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    SkASSERT(SkShader::kMirror_TileMode == m);
1080910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    return fixed_mirror;
1090910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1119a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic inline U16CPU int_clamp(int x, int n) {
1129a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
1139a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (x >= n)
1149a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        x = n - 1;
1159a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (x < 0)
1169a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        x = 0;
1179a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#else
1189a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if ((unsigned)x >= (unsigned)n) {
1199a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (x < 0) {
1209a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            x = 0;
1219a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        } else {
1229a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            x = n - 1;
1239a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
1249a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
1259a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#endif
1269a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    return x;
1279a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
1280910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1299a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic inline U16CPU int_repeat(int x, int n) {
1309a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    return sk_int_mod(x, n);
1319a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
1329a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
1339a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic inline U16CPU int_mirror(int x, int n) {
1349a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    x = sk_int_mod(x, 2 * n);
1359a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (x >= n) {
1369a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        x = n + ~(x - n);
1370910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1389a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    return x;
1399a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
1400910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1419a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#if 0
1429a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic void test_int_tileprocs() {
1439a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    for (int i = -8; i <= 8; i++) {
1449a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        SkDebugf(" int_mirror(%2d, 3) = %d\n", i, int_mirror(i, 3));
1450910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
1469a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
1479a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#endif
1480910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1499a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned tm) {
1509a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (SkShader::kClamp_TileMode == tm)
1519a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        return int_clamp;
1529a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (SkShader::kRepeat_TileMode == tm)
1539a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        return int_repeat;
1549a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    SkASSERT(SkShader::kMirror_TileMode == tm);
1559a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    return int_mirror;
1560910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
1570910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1580910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project//////////////////////////////////////////////////////////////////////////////
1590910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1600910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
1610910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
1620910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    int i;
1630910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
1643600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#if	defined(__ARM_HAVE_NEON)
1653600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    if (count >= 8) {
1663600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        /* SkFixed is 16.16 fixed point */
1673600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        SkFixed dx2 = dx+dx;
1683600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        SkFixed dx4 = dx2+dx2;
1693600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        SkFixed dx8 = dx4+dx4;
1703600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
1713600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        /* now build fx/fx+dx/fx+2dx/fx+3dx */
1723600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        SkFixed fx1, fx2, fx3;
1733600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        int32x2_t lower, upper;
1743600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        int32x4_t lbase, hbase;
1753600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        uint16_t *dst16 = (uint16_t *)dst;
1763600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
1773600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        fx1 = fx+dx;
1783600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        fx2 = fx1+dx;
1793600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        fx3 = fx2+dx;
1803600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
1813600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        /* avoid an 'lbase unitialized' warning */
1823600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        lbase = vdupq_n_s32(fx);
1833600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        lbase = vsetq_lane_s32(fx1, lbase, 1);
1843600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        lbase = vsetq_lane_s32(fx2, lbase, 2);
1853600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        lbase = vsetq_lane_s32(fx3, lbase, 3);
1863600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        hbase = vaddq_s32(lbase, vdupq_n_s32(dx4));
1873600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
1883600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        /* take upper 16 of each, store, and bump everything */
1893600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        do {
1903600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            int32x4_t lout, hout;
1913600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            uint16x8_t hi16;
1923600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
1933600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            lout = lbase;
1943600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            hout = hbase;
1953600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            /* gets hi's of all louts then hi's of all houts */
1963600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            asm ("vuzpq.16 %q0, %q1" : "+w" (lout), "+w" (hout));
1973600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            hi16 = vreinterpretq_u16_s32(hout);
1983600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            vst1q_u16(dst16, hi16);
1993600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2003600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            /* on to the next */
2013600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            lbase = vaddq_s32 (lbase, vdupq_n_s32(dx8));
2023600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            hbase = vaddq_s32 (hbase, vdupq_n_s32(dx8));
2033600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            dst16 += 8;
2043600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            count -= 8;
2053600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            fx += dx8;
2063600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        } while (count >= 8);
2073600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        dst = (uint32_t *) dst16;
2083600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    }
2093600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#else
2100910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    for (i = (count >> 2); i > 0; --i)
2110910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2120910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
2130910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fx += dx+dx;
2140910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
2150910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fx += dx+dx;
2160910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2173600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    count &= 3;
2183600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#endif
2190910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2203600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    uint16_t* xx = (uint16_t*)dst;
2213600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    for (i = count; i > 0; --i) {
2220910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *xx++ = SkToU16(fx >> 16); fx += dx;
2230910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2240910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2250910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Projectvoid decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
2270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project{
2283600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2293600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#if	defined(__ARM_HAVE_NEON)
2303600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    if (count >= 8) {
2313600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        int32x4_t wide_fx;
2323600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        int32x4_t wide_fx2;
2333600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        int32x4_t wide_dx8 = vdupq_n_s32(dx*8);
2343600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2353600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        wide_fx = vdupq_n_s32(fx);
2363600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        wide_fx = vsetq_lane_s32(fx+dx, wide_fx, 1);
2373600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        wide_fx = vsetq_lane_s32(fx+dx+dx, wide_fx, 2);
2383600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        wide_fx = vsetq_lane_s32(fx+dx+dx+dx, wide_fx, 3);
2393600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2403600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        wide_fx2 = vaddq_s32(wide_fx, vdupq_n_s32(dx+dx+dx+dx));
2413600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2423600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        while (count >= 8) {
2433600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            int32x4_t wide_out;
2443600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            int32x4_t wide_out2;
2453600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2463600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            wide_out = vshlq_n_s32(vshrq_n_s32(wide_fx, 12), 14);
2473600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            wide_out = vorrq_s32(wide_out,
2483600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            vaddq_s32(vshrq_n_s32(wide_fx,16), vdupq_n_s32(1)));
2493600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2503600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            wide_out2 = vshlq_n_s32(vshrq_n_s32(wide_fx2, 12), 14);
2513600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            wide_out2 = vorrq_s32(wide_out2,
2523600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            vaddq_s32(vshrq_n_s32(wide_fx2,16), vdupq_n_s32(1)));
2533600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2543600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            vst1q_u32(dst, vreinterpretq_u32_s32(wide_out));
2553600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            vst1q_u32(dst+4, vreinterpretq_u32_s32(wide_out2));
2563600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2573600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            dst += 8;
2583600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            fx += dx*8;
2593600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            wide_fx = vaddq_s32(wide_fx, wide_dx8);
2603600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            wide_fx2 = vaddq_s32(wide_fx2, wide_dx8);
2613600ab34671774af980bb97ecff2842c4cfc5955Mike Reed            count -= 8;
2623600ab34671774af980bb97ecff2842c4cfc5955Mike Reed        }
2633600ab34671774af980bb97ecff2842c4cfc5955Mike Reed    }
2643600ab34671774af980bb97ecff2842c4cfc5955Mike Reed#endif
2653600ab34671774af980bb97ecff2842c4cfc5955Mike Reed
2660910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    if (count & 1)
2670910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2680910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((fx >> (16 + 14)) == 0);
2690910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
2700910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fx += dx;
2710910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2720910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    while ((count -= 2) >= 0)
2730910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    {
2740910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        SkASSERT((fx >> (16 + 14)) == 0);
2750910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
2760910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fx += dx;
2770910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2780910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
2790910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project        fx += dx;
2800910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    }
2810910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
2820910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2839a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed///////////////////////////////////////////////////////////////////////////////
2849a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed// stores the same as SCALE, but is cheaper to compute. Also since there is no
2859a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed// scale, we don't need/have a FILTER version
2860910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
2879a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic void fill_sequential(uint16_t xptr[], int start, int count) {
2889a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#if 1
2899a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (reinterpret_cast<intptr_t>(xptr) & 0x2) {
2909a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        *xptr++ = start++;
2919a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        count -= 1;
2929a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
2939a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (count > 3) {
2949a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        uint32_t* xxptr = reinterpret_cast<uint32_t*>(xptr);
2959a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        uint32_t pattern0 = PACK_TWO_SHORTS(start + 0, start + 1);
2969a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        uint32_t pattern1 = PACK_TWO_SHORTS(start + 2, start + 3);
2979a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        start += count & ~3;
2989a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        int qcount = count >> 2;
2999a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        do {
3009a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            *xxptr++ = pattern0;
3019a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            pattern0 += 0x40004;
3029a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            *xxptr++ = pattern1;
3039a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            pattern1 += 0x40004;
304c1c43a17e7f2a87951739691056728a80e9aef6bMike Reed        } while (--qcount != 0);
3059a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        xptr = reinterpret_cast<uint16_t*>(xxptr);
3069a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        count &= 3;
3079a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3089a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    while (--count >= 0) {
3099a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        *xptr++ = start++;
3109a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3119a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#else
3129a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    for (int i = 0; i < count; i++) {
3139a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        *xptr++ = start++;
3149a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3159a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed#endif
3169a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
3170910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3189a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic int nofilter_trans_preamble(const SkBitmapProcState& s, uint32_t** xy,
3199a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                                   int x, int y) {
3209a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    SkPoint pt;
3219a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
3229a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed               SkIntToScalar(y) + SK_ScalarHalf, &pt);
3239a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    **xy = s.fIntTileProcY(SkScalarToFixed(pt.fY) >> 16,
3249a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                           s.fBitmap->height());
3259a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    *xy += 1;   // bump the ptr
3269a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    // return our starting X position
3279a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    return SkScalarToFixed(pt.fX) >> 16;
3289a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
3290910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3309a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic void clampx_nofilter_trans(const SkBitmapProcState& s,
3319a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                                  uint32_t xy[], int count, int x, int y) {
3329a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
3339a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
3349a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int xpos = nofilter_trans_preamble(s, &xy, x, y);
3359a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    const int width = s.fBitmap->width();
3369a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (1 == width) {
3379a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        // all of the following X values must be 0
3389a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        memset(xy, 0, count * sizeof(uint16_t));
3399a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        return;
3409a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3410910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
3429a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
3439a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int n;
3449a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
3459a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    // fill before 0 as needed
3469a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (xpos < 0) {
3479a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        n = -xpos;
3489a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (n > count) {
3499a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            n = count;
3509a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
3519a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        memset(xptr, 0, n * sizeof(uint16_t));
3529a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        count -= n;
3539a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (0 == count) {
3549a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            return;
3559a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
3569a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        xptr += n;
3579a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        xpos = 0;
3589a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3599a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
3609a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    // fill in 0..width-1 if needed
3619a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (xpos < width) {
3629a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        n = width - xpos;
3639a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (n > count) {
3649a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            n = count;
3659a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
3669a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fill_sequential(xptr, xpos, n);
3679a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        count -= n;
3689a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (0 == count) {
3699a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            return;
3709a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
3719a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        xptr += n;
3729a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3739a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
3749a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    // fill the remaining with the max value
3754c1037238c8ebcef8c75b5d43730ed308a11102cMike Reed    sk_memset16(xptr, width - 1, count);
3769a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
3779a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
3789a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic void repeatx_nofilter_trans(const SkBitmapProcState& s,
3799a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                                   uint32_t xy[], int count, int x, int y) {
3809a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
3819a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
3829a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int xpos = nofilter_trans_preamble(s, &xy, x, y);
3839a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    const int width = s.fBitmap->width();
3849a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (1 == width) {
3859a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        // all of the following X values must be 0
3869a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        memset(xy, 0, count * sizeof(uint16_t));
3879a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        return;
3889a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3899a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
3909a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
3919a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int start = sk_int_mod(xpos, width);
3929a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int n = width - start;
3939a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (n > count) {
3949a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        n = count;
3959a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
3969a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    fill_sequential(xptr, start, n);
3979a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    xptr += n;
3989a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    count -= n;
3999a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4009a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    while (count >= width) {
4019a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fill_sequential(xptr, 0, width);
4029a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        xptr += width;
4039a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        count -= width;
4049a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4059a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4069a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (count > 0) {
4079a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fill_sequential(xptr, 0, count);
4089a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4099a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
4109a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4119a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic void fill_backwards(uint16_t xptr[], int pos, int count) {
4129a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    for (int i = 0; i < count; i++) {
4139a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        SkASSERT(pos >= 0);
4149a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        xptr[i] = pos--;
4159a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4169a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
4179a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4189a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reedstatic void mirrorx_nofilter_trans(const SkBitmapProcState& s,
4199a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                                   uint32_t xy[], int count, int x, int y) {
4209a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
4219a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4229a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int xpos = nofilter_trans_preamble(s, &xy, x, y);
4239a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    const int width = s.fBitmap->width();
4249a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (1 == width) {
4259a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        // all of the following X values must be 0
4269a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        memset(xy, 0, count * sizeof(uint16_t));
4279a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        return;
4289a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4299a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4309a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
4319a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    // need to know our start, and our initial phase (forward or backward)
4329a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    bool forward;
4339a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int n;
4349a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int start = sk_int_mod(xpos, 2 * width);
4359a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (start >= width) {
4369a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        start = width + ~(start - width);
4379a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        forward = false;
4389a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        n = start + 1;  // [start .. 0]
4399a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    } else {
4409a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        forward = true;
4419a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        n = width - start;  // [start .. width)
4429a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4439a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (n > count) {
4449a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        n = count;
4459a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4469a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (forward) {
4479a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fill_sequential(xptr, start, n);
4489a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    } else {
4499a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fill_backwards(xptr, start, n);
4509a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4519a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    forward = !forward;
4529a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    xptr += n;
4530910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project    count -= n;
4549a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4559a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    while (count >= width) {
4569a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (forward) {
4579a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            fill_sequential(xptr, 0, width);
4589a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        } else {
4599a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            fill_backwards(xptr, width - 1, width);
4609a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
4619a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        forward = !forward;
4629a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        xptr += width;
4639a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        count -= width;
4649a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4659a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4669a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (count > 0) {
4679a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        if (forward) {
4689a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            fill_sequential(xptr, 0, count);
4699a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        } else {
4709a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            fill_backwards(xptr, width - 1, count);
4719a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
4729a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4739a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed}
4749a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4759a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed///////////////////////////////////////////////////////////////////////////////
4769a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4779a5843c9b6ef01f25513bef72a91936f75cc4458Mike ReedSkBitmapProcState::MatrixProc
4789a5843c9b6ef01f25513bef72a91936f75cc4458Mike ReedSkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
4799a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed//    test_int_tileprocs();
4809a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    // check for our special case when there is no scale/affine/perspective
4819a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (trivial_matrix) {
4829a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        SkASSERT(!fDoFilter);
4839a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fIntTileProcY = choose_int_tile_proc(fTileModeY);
4849a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        switch (fTileModeX) {
4859a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            case SkShader::kClamp_TileMode:
4869a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                return clampx_nofilter_trans;
4879a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            case SkShader::kRepeat_TileMode:
4889a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                return repeatx_nofilter_trans;
4899a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed            case SkShader::kMirror_TileMode:
4909a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed                return mirrorx_nofilter_trans;
4919a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        }
4929a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4939a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
4949a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    int index = 0;
4959a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (fDoFilter) {
4969a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        index = 1;
4979a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
4989a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (fInvType & SkMatrix::kPerspective_Mask) {
4999a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        index += 4;
5009a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    } else if (fInvType & SkMatrix::kAffine_Mask) {
50117d1e95f527382203087356175890dab480ed3baMike Reed        index += 2;
5029a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
5039a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
5049a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (SkShader::kClamp_TileMode == fTileModeX &&
5059a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        SkShader::kClamp_TileMode == fTileModeY)
5069a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    {
5079a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        // clamp gets special version of filterOne
5089a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fFilterOneX = SK_Fixed1;
5099a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        fFilterOneY = SK_Fixed1;
5109a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        return ClampX_ClampY_Procs[index];
5119a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
5129a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
5139a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    // all remaining procs use this form for filterOne
5149a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    fFilterOneX = SK_Fixed1 / fBitmap->width();
5159a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    fFilterOneY = SK_Fixed1 / fBitmap->height();
5169a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
5179a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    if (SkShader::kRepeat_TileMode == fTileModeX &&
5189a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        SkShader::kRepeat_TileMode == fTileModeY)
5199a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    {
5209a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed        return RepeatX_RepeatY_Procs[index];
5219a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    }
5229a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed
5239a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    fTileProcX = choose_tile_proc(fTileModeX);
5249a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    fTileProcY = choose_tile_proc(fTileModeY);
5259a5843c9b6ef01f25513bef72a91936f75cc4458Mike Reed    return GeneralXY_Procs[index];
5260910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project}
5270910916c0f7b951ee55c4b7c6358295b9bca0565The Android Open Source Project
528