1ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed/*
2ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed * Copyright 2008 Google Inc.
3ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed *
4ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed * Use of this source code is governed by a BSD-style license that can be
5ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed * found in the LICENSE file.
6ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed */
7ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed
8ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed// The copyright below was added in 2009, but I see no record of moto contributions...?
9ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed
10fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com/* NEON optimized code (C) COPYRIGHT 2009 Motorola
116c5bf8d9fe6fe263f583a4c22d04e3be879ecfebcaryclark@google.com *
126c5bf8d9fe6fe263f583a4c22d04e3be879ecfebcaryclark@google.com * Use of this source code is governed by a BSD-style license that can be
136c5bf8d9fe6fe263f583a4c22d04e3be879ecfebcaryclark@google.com * found in the LICENSE file.
146c5bf8d9fe6fe263f583a4c22d04e3be879ecfebcaryclark@google.com */
15ed881c2704bc81fe46a68c0cf9e292287313baa6reed@android.com
168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcState.h"
178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkPerspIter.h"
188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h"
1907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com#include "SkUtils.h"
20fce02aca62525c3041226501574f740f7ea3714bdigit@google.com#include "SkUtilsArm.h"
21a8c09668f9e602f77422a344dfa4d13155c91fd3commit-bot@chromium.org#include "SkBitmapProcState_utils.h"
2299c114e0ac732ba01705e24d12f5e4dd7e144abdreed@google.com
2307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com/*  returns 0...(n-1) given any x (positive or negative).
24fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    As an example, if n (which is always positive) is 5...
26fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
2707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com          x: -8 -7 -6 -5 -4 -3 -2 -1  0  1  2  3  4  5  6  7  8
2807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    returns:  2  3  4  0  1  2  3  4  0  1  2  3  4  0  1  2  3
2907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com */
3007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic inline int sk_int_mod(int x, int n) {
3107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    SkASSERT(n > 0);
3207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if ((unsigned)x >= (unsigned)n) {
3307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        if (x < 0) {
3407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            x = n + ~(~x % n);
3507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        } else {
3607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            x = x % n;
3707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
3807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
3907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    return x;
4007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
45d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com#include "SkBitmapProcState_matrix_template.h"
46d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
47d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com///////////////////////////////////////////////////////////////////////////////
48d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
49fce02aca62525c3041226501574f740f7ea3714bdigit@google.com// Compile neon code paths if needed
50809ccf37ec836d0df64afd0b13023fd968d505a4mtklein#if defined(SK_ARM_HAS_NEON)
51fce02aca62525c3041226501574f740f7ea3714bdigit@google.com
52fce02aca62525c3041226501574f740f7ea3714bdigit@google.com// These are defined in src/opts/SkBitmapProcState_matrixProcs_neon.cpp
53fce02aca62525c3041226501574f740f7ea3714bdigit@google.comextern const SkBitmapProcState::MatrixProc ClampX_ClampY_Procs_neon[];
54fce02aca62525c3041226501574f740f7ea3714bdigit@google.comextern const SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs_neon[];
55fce02aca62525c3041226501574f740f7ea3714bdigit@google.com
56809ccf37ec836d0df64afd0b13023fd968d505a4mtklein#endif // defined(SK_ARM_HAS_NEON)
57fce02aca62525c3041226501574f740f7ea3714bdigit@google.com
58fce02aca62525c3041226501574f740f7ea3714bdigit@google.com// Compile non-neon code path if needed
59809ccf37ec836d0df64afd0b13023fd968d505a4mtklein#if !defined(SK_ARM_HAS_NEON)
60d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define MAKENAME(suffix)         ClampX_ClampY ## suffix
61d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define TILEX_PROCF(fx, max)     SkClampMax((fx) >> 16, max)
62d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define TILEY_PROCF(fy, max)     SkClampMax((fy) >> 16, max)
63d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define EXTRACT_LOW_BITS(v, max) (((v) >> 12) & 0xF)
648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define CHECK_FOR_DECAL
65fce02aca62525c3041226501574f740f7ea3714bdigit@google.com#include "SkBitmapProcState_matrix.h"
668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
67d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstruct ClampTileProcs {
68d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
69d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        return SkClampMax(fx >> 16, max);
70d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
71d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
72d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        return SkClampMax(fy >> 16, max);
73d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
74d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com};
75d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
768c4953c6f176469ad287c3270ab146e292b23badcommit-bot@chromium.org// Referenced in opts_check_x86.cpp
77d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid ClampX_ClampY_nofilter_scale(const SkBitmapProcState& s, uint32_t xy[],
78d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                                  int count, int x, int y) {
79d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    return NoFilterProc_Scale<ClampTileProcs, true>(s, xy, count, x, y);
80d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
81d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid ClampX_ClampY_nofilter_affine(const SkBitmapProcState& s, uint32_t xy[],
82d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com                                  int count, int x, int y) {
83d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    return NoFilterProc_Affine<ClampTileProcs>(s, xy, count, x, y);
84d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com}
85d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
86d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstatic SkBitmapProcState::MatrixProc ClampX_ClampY_Procs[] = {
87d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    // only clamp lives in the right coord space to check for decal
88d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    ClampX_ClampY_nofilter_scale,
89d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    ClampX_ClampY_filter_scale,
90d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    ClampX_ClampY_nofilter_affine,
91d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    ClampX_ClampY_filter_affine,
92d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    NoFilterProc_Persp<ClampTileProcs>,
93d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    ClampX_ClampY_filter_persp
94d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com};
95d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
96d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define MAKENAME(suffix)         RepeatX_RepeatY ## suffix
97d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define TILEX_PROCF(fx, max)     SK_USHIFT16((unsigned)((fx) & 0xFFFF) * ((max) + 1))
98d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define TILEY_PROCF(fy, max)     SK_USHIFT16((unsigned)((fy) & 0xFFFF) * ((max) + 1))
99d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define EXTRACT_LOW_BITS(v, max) (((unsigned)((v) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
100fce02aca62525c3041226501574f740f7ea3714bdigit@google.com#include "SkBitmapProcState_matrix.h"
101d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
102d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstruct RepeatTileProcs {
103d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    static unsigned X(const SkBitmapProcState&, SkFixed fx, int max) {
104d5c4265b49d212f7888d0516328f39c4d45d3058tomhudson        SkASSERT(max < 65535);
105d5c4265b49d212f7888d0516328f39c4d45d3058tomhudson        return SK_USHIFT16((unsigned)((fx) & 0xFFFF) * ((max) + 1));
106d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
107d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    static unsigned Y(const SkBitmapProcState&, SkFixed fy, int max) {
108d5c4265b49d212f7888d0516328f39c4d45d3058tomhudson        SkASSERT(max < 65535);
109d5c4265b49d212f7888d0516328f39c4d45d3058tomhudson        return SK_USHIFT16((unsigned)((fy) & 0xFFFF) * ((max) + 1));
110d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
111d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com};
112d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
113d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstatic SkBitmapProcState::MatrixProc RepeatX_RepeatY_Procs[] = {
114d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    NoFilterProc_Scale<RepeatTileProcs, false>,
115d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    RepeatX_RepeatY_filter_scale,
116d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    NoFilterProc_Affine<RepeatTileProcs>,
117d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    RepeatX_RepeatY_filter_affine,
118d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    NoFilterProc_Persp<RepeatTileProcs>,
119d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    RepeatX_RepeatY_filter_persp
120d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com};
121ed881c2704bc81fe46a68c0cf9e292287313baa6reed@android.com#endif
1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define MAKENAME(suffix)        GeneralXY ## suffix
12405af1afd429808913683da75644e48bece12e820humper@google.com#define PREAMBLE(state)         SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; (void) tileProcX; \
12557845a7264ef5183258ec23ffe77c25ec967c755Florin Malita                                SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY; (void) tileProcY;
12657845a7264ef5183258ec23ffe77c25ec967c755Florin Malita#define PREAMBLE_PARAM_X        , SkBitmapProcState::FixedTileProc tileProcX
12757845a7264ef5183258ec23ffe77c25ec967c755Florin Malita#define PREAMBLE_PARAM_Y        , SkBitmapProcState::FixedTileProc tileProcY
12857845a7264ef5183258ec23ffe77c25ec967c755Florin Malita#define PREAMBLE_ARG_X          , tileProcX
12957845a7264ef5183258ec23ffe77c25ec967c755Florin Malita#define PREAMBLE_ARG_Y          , tileProcY
13099c114e0ac732ba01705e24d12f5e4dd7e144abdreed@google.com#define TILEX_PROCF(fx, max)    SK_USHIFT16(tileProcX(fx) * ((max) + 1))
13199c114e0ac732ba01705e24d12f5e4dd7e144abdreed@google.com#define TILEY_PROCF(fy, max)    SK_USHIFT16(tileProcY(fy) * ((max) + 1))
132d1c550e71fa72cfbf03b93c10ec8b9d1d109f8c2Florin Malita#define EXTRACT_LOW_BITS(v, max) (((v * (max + 1)) >> 12) & 0xF)
1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBitmapProcState_matrix.h"
1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
135d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstruct GeneralTileProcs {
136d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    static unsigned X(const SkBitmapProcState& s, SkFixed fx, int max) {
137d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        return SK_USHIFT16(s.fTileProcX(fx) * ((max) + 1));
138d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
139d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    static unsigned Y(const SkBitmapProcState& s, SkFixed fy, int max) {
140d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com        return SK_USHIFT16(s.fTileProcY(fy) * ((max) + 1));
141d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
142d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com};
143d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
144d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstatic SkBitmapProcState::MatrixProc GeneralXY_Procs[] = {
145d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    NoFilterProc_Scale<GeneralTileProcs, false>,
146d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    GeneralXY_filter_scale,
147d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    NoFilterProc_Affine<GeneralTileProcs>,
148d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    GeneralXY_filter_affine,
149d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    NoFilterProc_Persp<GeneralTileProcs>,
150d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    GeneralXY_filter_persp
151d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com};
152d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
153d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com///////////////////////////////////////////////////////////////////////////////
154d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com
155d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstatic inline U16CPU fixed_clamp(SkFixed x) {
15638bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org    if (x < 0) {
1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        x = 0;
15838bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org    }
15938bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org    if (x >> 16) {
160cc0c8e6084e140c962ae9a6885992bafea8ec048reed@google.com        x = 0xFFFF;
1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return x;
1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
165d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstatic inline U16CPU fixed_repeat(SkFixed x) {
1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return x & 0xFFFF;
1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
169d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstatic inline U16CPU fixed_mirror(SkFixed x) {
1703127c99986dc932343aae5ccc575237d99c3aaeccaryclark    SkFixed s = SkLeftShift(x, 15) >> 31;
1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return (x ^ s) & 0xFFFF;
1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
175d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comstatic SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m) {
176d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (SkShader::kClamp_TileMode == m) {
1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fixed_clamp;
178d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
179d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (SkShader::kRepeat_TileMode == m) {
1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        return fixed_repeat;
181d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    }
1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    SkASSERT(SkShader::kMirror_TileMode == m);
1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    return fixed_mirror;
1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
18607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic inline U16CPU int_clamp(int x, int n) {
18738bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org    if (x >= n) {
18807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        x = n - 1;
18938bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org    }
19038bad32cf5297ec6908620fd174cd08c937d331acommit-bot@chromium.org    if (x < 0) {
19107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        x = 0;
19207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
19307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    return x;
19407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
19607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic inline U16CPU int_repeat(int x, int n) {
19707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    return sk_int_mod(x, n);
19807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
19907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
20007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic inline U16CPU int_mirror(int x, int n) {
20107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    x = sk_int_mod(x, 2 * n);
20207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (x >= n) {
20307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        x = n + ~(x - n);
2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
20507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    return x;
20607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
20807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com#if 0
20907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic void test_int_tileprocs() {
21007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    for (int i = -8; i <= 8; i++) {
21107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        SkDebugf(" int_mirror(%2d, 3) = %d\n", i, int_mirror(i, 3));
2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
21307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
21407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com#endif
2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
21607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic SkBitmapProcState::IntTileProc choose_int_tile_proc(unsigned tm) {
21707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (SkShader::kClamp_TileMode == tm)
21807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        return int_clamp;
21907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (SkShader::kRepeat_TileMode == tm)
22007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        return int_repeat;
22107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    SkASSERT(SkShader::kMirror_TileMode == tm);
22207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    return int_mirror;
2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////////////////////////////////////////////////////////////
2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
227d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    int i;
2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
230d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    for (i = (count >> 2); i > 0; --i) {
2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fx += dx+dx;
2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fx += dx+dx;
2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
236ed881c2704bc81fe46a68c0cf9e292287313baa6reed@android.com    count &= 3;
2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
238ed881c2704bc81fe46a68c0cf9e292287313baa6reed@android.com    uint16_t* xx = (uint16_t*)dst;
239ed881c2704bc81fe46a68c0cf9e292287313baa6reed@android.com    for (i = count; i > 0; --i) {
2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *xx++ = SkToU16(fx >> 16); fx += dx;
2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
244d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comvoid decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count) {
245d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (count & 1) {
2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((fx >> (16 + 14)) == 0);
2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fx += dx;
2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
250d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    while ((count -= 2) >= 0) {
2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        SkASSERT((fx >> (16 + 14)) == 0);
2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fx += dx;
2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com        fx += dx;
2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    }
2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com///////////////////////////////////////////////////////////////////////////////
26107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com// stores the same as SCALE, but is cheaper to compute. Also since there is no
26207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com// scale, we don't need/have a FILTER version
2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
26407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic void fill_sequential(uint16_t xptr[], int start, int count) {
26507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com#if 1
26607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (reinterpret_cast<intptr_t>(xptr) & 0x2) {
26707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        *xptr++ = start++;
26807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        count -= 1;
26907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
27007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (count > 3) {
27107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        uint32_t* xxptr = reinterpret_cast<uint32_t*>(xptr);
27207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        uint32_t pattern0 = PACK_TWO_SHORTS(start + 0, start + 1);
27307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        uint32_t pattern1 = PACK_TWO_SHORTS(start + 2, start + 3);
27407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        start += count & ~3;
27507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        int qcount = count >> 2;
27607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        do {
27707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            *xxptr++ = pattern0;
27807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            pattern0 += 0x40004;
27907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            *xxptr++ = pattern1;
28007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            pattern1 += 0x40004;
2814c128c4917acf25c2cc5d1bd22282a4e1bb53d96reed@android.com        } while (--qcount != 0);
28207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        xptr = reinterpret_cast<uint16_t*>(xxptr);
28307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        count &= 3;
28407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
28507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    while (--count >= 0) {
28607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        *xptr++ = start++;
28707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
28807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com#else
28907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    for (int i = 0; i < count; i++) {
29007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        *xptr++ = start++;
29107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
29207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com#endif
29307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
29507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic int nofilter_trans_preamble(const SkBitmapProcState& s, uint32_t** xy,
29607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com                                   int x, int y) {
297eb543071725f465e93ddcc052d54fd5c03f043f9fmalita    const SkBitmapProcStateAutoMapper mapper(s, x, y);
298be5cfa9a9e1cfb77beba27727df7149ab5e7d422fmalita    **xy = s.fIntTileProcY(mapper.intY(), s.fPixmap.height());
29907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    *xy += 1;   // bump the ptr
30007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    // return our starting X position
301be5cfa9a9e1cfb77beba27727df7149ab5e7d422fmalita    return mapper.intX();
30207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com
30407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic void clampx_nofilter_trans(const SkBitmapProcState& s,
30507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com                                  uint32_t xy[], int count, int x, int y) {
30607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
30707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
30807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int xpos = nofilter_trans_preamble(s, &xy, x, y);
309ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    const int width = s.fPixmap.width();
31007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (1 == width) {
31107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        // all of the following X values must be 0
31207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        memset(xy, 0, count * sizeof(uint16_t));
31307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        return;
31407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
315fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
31607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
31707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int n;
31807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
31907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    // fill before 0 as needed
32007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (xpos < 0) {
32107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        n = -xpos;
32207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        if (n > count) {
32307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            n = count;
32407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
32507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        memset(xptr, 0, n * sizeof(uint16_t));
32607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        count -= n;
32707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        if (0 == count) {
32807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            return;
32907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
33007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        xptr += n;
33107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        xpos = 0;
33207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
33307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
33407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    // fill in 0..width-1 if needed
33507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (xpos < width) {
33607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        n = width - xpos;
33707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        if (n > count) {
33807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            n = count;
33907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
34007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fill_sequential(xptr, xpos, n);
34107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        count -= n;
34207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        if (0 == count) {
34307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            return;
34407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
34507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        xptr += n;
34607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
34707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
34807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    // fill the remaining with the max value
349258cb228c636282a3e4f4ce87b1017498e207f33reed@android.com    sk_memset16(xptr, width - 1, count);
35007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
35107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
35207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic void repeatx_nofilter_trans(const SkBitmapProcState& s,
35307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com                                   uint32_t xy[], int count, int x, int y) {
35407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
35507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
35607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int xpos = nofilter_trans_preamble(s, &xy, x, y);
357ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    const int width = s.fPixmap.width();
35807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (1 == width) {
35907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        // all of the following X values must be 0
36007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        memset(xy, 0, count * sizeof(uint16_t));
36107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        return;
36207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
36307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
36407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
36507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int start = sk_int_mod(xpos, width);
36607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int n = width - start;
36707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (n > count) {
36807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        n = count;
36907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
37007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    fill_sequential(xptr, start, n);
37107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    xptr += n;
37207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    count -= n;
37307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
37407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    while (count >= width) {
37507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fill_sequential(xptr, 0, width);
37607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        xptr += width;
37707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        count -= width;
37807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
37907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
38007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (count > 0) {
38107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fill_sequential(xptr, 0, count);
38207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
38307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
38407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
38507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic void fill_backwards(uint16_t xptr[], int pos, int count) {
38607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    for (int i = 0; i < count; i++) {
38707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        SkASSERT(pos >= 0);
38807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        xptr[i] = pos--;
38907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
39007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
39107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
39207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.comstatic void mirrorx_nofilter_trans(const SkBitmapProcState& s,
39307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com                                   uint32_t xy[], int count, int x, int y) {
39407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    SkASSERT((s.fInvType & ~SkMatrix::kTranslate_Mask) == 0);
39507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
39607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int xpos = nofilter_trans_preamble(s, &xy, x, y);
397ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    const int width = s.fPixmap.width();
39807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (1 == width) {
39907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        // all of the following X values must be 0
40007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        memset(xy, 0, count * sizeof(uint16_t));
40107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        return;
40207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
40307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
40407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    uint16_t* xptr = reinterpret_cast<uint16_t*>(xy);
40507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    // need to know our start, and our initial phase (forward or backward)
40607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    bool forward;
40707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int n;
40807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int start = sk_int_mod(xpos, 2 * width);
40907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (start >= width) {
41007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        start = width + ~(start - width);
41107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        forward = false;
41207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        n = start + 1;  // [start .. 0]
41307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    } else {
41407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        forward = true;
41507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        n = width - start;  // [start .. width)
41607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
41707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (n > count) {
41807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        n = count;
41907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
42007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (forward) {
42107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fill_sequential(xptr, start, n);
42207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    } else {
42307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fill_backwards(xptr, start, n);
42407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
42507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    forward = !forward;
42607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    xptr += n;
4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com    count -= n;
428fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
42907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    while (count >= width) {
43007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        if (forward) {
43107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            fill_sequential(xptr, 0, width);
43207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        } else {
43307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            fill_backwards(xptr, width - 1, width);
43407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
43507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        forward = !forward;
43607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        xptr += width;
43707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        count -= width;
43807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
439fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
44007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (count > 0) {
44107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        if (forward) {
44207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            fill_sequential(xptr, 0, count);
44307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        } else {
44407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            fill_backwards(xptr, width - 1, count);
44507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
44607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
44707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com}
44807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
44907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com///////////////////////////////////////////////////////////////////////////////
45007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com
451d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.comSkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) {
45207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com//    test_int_tileprocs();
45307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    // check for our special case when there is no scale/affine/perspective
45405a5647efed7fcbcc5bd1efa445a6a3ab445a6c3reed    if (trivial_matrix && kNone_SkFilterQuality == fFilterQuality) {
45507d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fIntTileProcY = choose_int_tile_proc(fTileModeY);
45607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        switch (fTileModeX) {
45707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            case SkShader::kClamp_TileMode:
45807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com                return clampx_nofilter_trans;
45907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            case SkShader::kRepeat_TileMode:
46007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com                return repeatx_nofilter_trans;
46107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com            case SkShader::kMirror_TileMode:
46207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com                return mirrorx_nofilter_trans;
46307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        }
46407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
465fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
46607d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    int index = 0;
46705a5647efed7fcbcc5bd1efa445a6a3ab445a6c3reed    if (fFilterQuality != kNone_SkFilterQuality) {
46807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        index = 1;
46907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
47007d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    if (fInvType & SkMatrix::kPerspective_Mask) {
47107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        index += 4;
47207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    } else if (fInvType & SkMatrix::kAffine_Mask) {
473a2b2c4ba5351b8cee0f03b5a9eeeb430862bbc7dreed@android.com        index += 2;
47407d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
475fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
476d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (SkShader::kClamp_TileMode == fTileModeX && SkShader::kClamp_TileMode == fTileModeY) {
47707d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        // clamp gets special version of filterOne
47807d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fFilterOneX = SK_Fixed1;
47907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com        fFilterOneY = SK_Fixed1;
480157d94465a47a57e30e5cf49cd57dccd903e27e2digit@google.com        return SK_ARM_NEON_WRAP(ClampX_ClampY_Procs)[index];
48107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
482fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
48307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    // all remaining procs use this form for filterOne
484ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    fFilterOneX = SK_Fixed1 / fPixmap.width();
485ad7ae6c821c530dd6cb54b0e8931ba8b10e8d87dreed    fFilterOneY = SK_Fixed1 / fPixmap.height();
486fbfcd5602128ec010c82cb733c9cdc0a3254f9f3rmistry@google.com
487d9ae2314f58ccac54068a2e50a4a159cf3929c1areed@google.com    if (SkShader::kRepeat_TileMode == fTileModeX && SkShader::kRepeat_TileMode == fTileModeY) {
488157d94465a47a57e30e5cf49cd57dccd903e27e2digit@google.com        return SK_ARM_NEON_WRAP(RepeatX_RepeatY_Procs)[index];
48907d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    }
490fce02aca62525c3041226501574f740f7ea3714bdigit@google.com
49107d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    fTileProcX = choose_tile_proc(fTileModeX);
49207d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    fTileProcY = choose_tile_proc(fTileModeY);
49307d1f008b365e94ef7c7347be19a03d00bd36805reed@android.com    return GeneralXY_Procs[index];
4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com}
495