SkBitmapProcState_matrixProcs.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
1#include "SkBitmapProcState.h"
2#include "SkPerspIter.h"
3#include "SkShader.h"
4
5void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
6void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count);
7
8#ifdef SK_CPU_BENDIAN
9    #define PACK_TWO_SHORTS(pri, sec) ((pri) << 16 | (sec))
10#else
11    #define PACK_TWO_SHORTS(pri, sec) ((pri) | ((sec) << 16))
12#endif
13
14#ifdef SK_DEBUG
15    static uint32_t pack_two_shorts(U16CPU pri, U16CPU sec)
16    {
17        SkASSERT((uint16_t)pri == pri);
18        SkASSERT((uint16_t)sec == sec);
19        return PACK_TWO_SHORTS(pri, sec);
20    }
21#else
22    #define pack_two_shorts(pri, sec)   PACK_TWO_SHORTS(pri, sec)
23#endif
24
25#define MAKENAME(suffix)        ClampX_ClampY ## suffix
26#define TILEX_PROCF(fx, max)    SkClampMax((fx) >> 16, max)
27#define TILEY_PROCF(fy, max)    SkClampMax((fy) >> 16, max)
28#define TILEX_LOW_BITS(fx, max) (((fx) >> 12) & 0xF)
29#define TILEY_LOW_BITS(fy, max) (((fy) >> 12) & 0xF)
30#define CHECK_FOR_DECAL
31#include "SkBitmapProcState_matrix.h"
32
33#define MAKENAME(suffix)        RepeatX_RepeatY ## suffix
34#define TILEX_PROCF(fx, max)    (((fx) & 0xFFFF) * ((max) + 1) >> 16)
35#define TILEY_PROCF(fy, max)    (((fy) & 0xFFFF) * ((max) + 1) >> 16)
36#define TILEX_LOW_BITS(fx, max) ((((fx) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
37#define TILEY_LOW_BITS(fy, max) ((((fy) & 0xFFFF) * ((max) + 1) >> 12) & 0xF)
38#include "SkBitmapProcState_matrix.h"
39
40#define MAKENAME(suffix)        GeneralXY ## suffix
41#define PREAMBLE(state)         SkBitmapProcState::FixedTileProc tileProcX = (state).fTileProcX; \
42                                SkBitmapProcState::FixedTileProc tileProcY = (state).fTileProcY
43#define PREAMBLE_PARAM_X        , SkBitmapProcState::FixedTileProc tileProcX
44#define PREAMBLE_PARAM_Y        , SkBitmapProcState::FixedTileProc tileProcY
45#define PREAMBLE_ARG_X          , tileProcX
46#define PREAMBLE_ARG_Y          , tileProcY
47#define TILEX_PROCF(fx, max)    (tileProcX(fx) * ((max) + 1) >> 16)
48#define TILEY_PROCF(fy, max)    (tileProcY(fy) * ((max) + 1) >> 16)
49#define TILEX_LOW_BITS(fx, max) ((tileProcX(fx) * ((max) + 1) >> 12) & 0xF)
50#define TILEY_LOW_BITS(fy, max) ((tileProcY(fy) * ((max) + 1) >> 12) & 0xF)
51#include "SkBitmapProcState_matrix.h"
52
53static inline U16CPU fixed_clamp(SkFixed x)
54{
55#ifdef SK_CPU_HAS_CONDITIONAL_INSTR
56    if (x >> 16)
57        x = 0xFFFF;
58    if (x < 0)
59        x = 0;
60#else
61    if (x >> 16)
62    {
63        if (x < 0)
64            x = 0;
65        else
66            x = 0xFFFF;
67    }
68#endif
69    return x;
70}
71
72static inline U16CPU fixed_repeat(SkFixed x)
73{
74    return x & 0xFFFF;
75}
76
77static inline U16CPU fixed_mirror(SkFixed x)
78{
79    SkFixed s = x << 15 >> 31;
80    // s is FFFFFFFF if we're on an odd interval, or 0 if an even interval
81    return (x ^ s) & 0xFFFF;
82}
83
84static SkBitmapProcState::FixedTileProc choose_tile_proc(unsigned m)
85{
86    if (SkShader::kClamp_TileMode == m)
87        return fixed_clamp;
88    if (SkShader::kRepeat_TileMode == m)
89        return fixed_repeat;
90    SkASSERT(SkShader::kMirror_TileMode == m);
91    return fixed_mirror;
92}
93
94SkBitmapProcState::MatrixProc SkBitmapProcState::chooseMatrixProc()
95{
96    int index = 0;
97    if (fDoFilter)
98        index = 1;
99    if (fInvType & SkMatrix::kPerspective_Mask)
100        index |= 4;
101    else if (fInvType & SkMatrix::kAffine_Mask)
102        index |= 2;
103
104    if (SkShader::kClamp_TileMode == fTileModeX &&
105        SkShader::kClamp_TileMode == fTileModeY)
106    {
107        // clamp gets special version of filterOne
108        fFilterOneX = SK_Fixed1;
109        fFilterOneY = SK_Fixed1;
110        return ClampX_ClampY_Procs[index];
111    }
112
113    // all remaining procs use this form for filterOne
114    fFilterOneX = SK_Fixed1 / fBitmap->width();
115    fFilterOneY = SK_Fixed1 / fBitmap->height();
116
117    if (SkShader::kRepeat_TileMode == fTileModeX &&
118        SkShader::kRepeat_TileMode == fTileModeY)
119    {
120        return RepeatX_RepeatY_Procs[index];
121    }
122
123    // only general needs these procs
124    fTileProcX = choose_tile_proc(fTileModeX);
125    fTileProcY = choose_tile_proc(fTileModeY);
126    return GeneralXY_Procs[index];
127}
128
129//////////////////////////////////////////////////////////////////////////////
130
131void decal_nofilter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
132{
133    int i;
134
135    for (i = (count >> 2); i > 0; --i)
136    {
137        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
138        fx += dx+dx;
139        *dst++ = pack_two_shorts(fx >> 16, (fx + dx) >> 16);
140        fx += dx+dx;
141    }
142    uint16_t* xx = (uint16_t*)dst;
143
144    for (i = (count & 3); i > 0; --i)
145    {
146        *xx++ = SkToU16(fx >> 16); fx += dx;
147    }
148}
149
150void decal_filter_scale(uint32_t dst[], SkFixed fx, SkFixed dx, int count)
151{
152    if (count & 1)
153    {
154        SkASSERT((fx >> (16 + 14)) == 0);
155        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
156        fx += dx;
157    }
158    while ((count -= 2) >= 0)
159    {
160        SkASSERT((fx >> (16 + 14)) == 0);
161        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
162        fx += dx;
163
164        *dst++ = (fx >> 12 << 14) | ((fx >> 16) + 1);
165        fx += dx;
166    }
167}
168
169///////////////////////////////////
170
171void repeat_nofilter_identity(uint32_t dst[], int x, int width, int count)
172{
173    if (x >= width)
174        x %= width;
175
176    int i;
177    uint16_t* xx = (uint16_t*)dst;
178
179    // do the first partial run
180    int n = width - x;
181    if (n > count)
182        n = count;
183
184    count -= n;
185    n += x;
186    for (i = x; i < n; i++)
187        *xx++ = SkToU16(i);
188
189    // do all the full-width runs
190    while ((count -= width) >= 0)
191        for (i = 0; i < width; i++)
192            *xx++ = SkToU16(i);
193
194    // final cleanup run
195    count += width;
196    for (i = 0; i < count; i++)
197        *xx++ = SkToU16(i);
198}
199
200