1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkFilterProc.h"
11
12/*  [1-x 1-y] [x 1-y]
13    [1-x   y] [x   y]
14*/
15
16static unsigned bilerp00(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return a00; }
17static unsigned bilerp01(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (3 * a00 + a01) >> 2; }
18static unsigned bilerp02(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (a00 + a01) >> 1; }
19static unsigned bilerp03(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (a00 + 3 * a01) >> 2; }
20
21static unsigned bilerp10(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (3 * a00 + a10) >> 2; }
22static unsigned bilerp11(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (9 * a00 + 3 * (a01 + a10) + a11) >> 4; }
23static unsigned bilerp12(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (3 * (a00 + a01) + a10 + a11) >> 3; }
24static unsigned bilerp13(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (9 * a01 + 3 * (a00 + a11) + a10) >> 4; }
25
26static unsigned bilerp20(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (a00 + a10) >> 1; }
27static unsigned bilerp21(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (3 * (a00 + a10) + a01 + a11) >> 3; }
28static unsigned bilerp22(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (a00 + a01 + a10 + a11) >> 2; }
29static unsigned bilerp23(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (3 * (a01 + a11) + a00 + a10) >> 3; }
30
31static unsigned bilerp30(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (a00 + 3 * a10) >> 2; }
32static unsigned bilerp31(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (9 * a10 + 3 * (a00 + a11) + a01) >> 4; }
33static unsigned bilerp32(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (3 * (a10 + a11) + a00 + a01) >> 3; }
34static unsigned bilerp33(unsigned a00, unsigned a01, unsigned a10, unsigned a11) { return (9 * a11 + 3 * (a01 + a10) + a00) >> 4; }
35
36static const SkFilterProc gBilerpProcs[4 * 4] = {
37    bilerp00, bilerp01, bilerp02, bilerp03,
38    bilerp10, bilerp11, bilerp12, bilerp13,
39    bilerp20, bilerp21, bilerp22, bilerp23,
40    bilerp30, bilerp31, bilerp32, bilerp33
41};
42
43const SkFilterProc* SkGetBilinearFilterProcTable()
44{
45    return gBilerpProcs;
46}
47
48///////////////////////////////////////////////////////////////////////////////
49///////////////////////////////////////////////////////////////////////////////
50
51#define MASK            0xFF00FF
52#define LO_PAIR(x)      ((x) & MASK)
53#define HI_PAIR(x)      (((x) >> 8) & MASK)
54#define COMBINE(lo, hi) (((lo) & ~0xFF00) | (((hi) & ~0xFF00) << 8))
55
56///////////////////////////////////////////////////////////////////////////////
57
58static unsigned bilerp4_00(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
59    return c00;
60}
61static unsigned bilerp4_01(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
62    uint32_t lo = (3 * LO_PAIR(c00) + LO_PAIR(c01)) >> 2;
63    uint32_t hi = (3 * HI_PAIR(c00) + HI_PAIR(c01)) >> 2;
64    return COMBINE(lo, hi);
65}
66static unsigned bilerp4_02(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
67    uint32_t lo = (LO_PAIR(c00) + LO_PAIR(c01)) >> 1;
68    uint32_t hi = (HI_PAIR(c00) + HI_PAIR(c01)) >> 1;
69    return COMBINE(lo, hi);
70}
71static unsigned bilerp4_03(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
72    uint32_t lo = (LO_PAIR(c00) + 3 * LO_PAIR(c01)) >> 2;
73    uint32_t hi = (HI_PAIR(c00) + 3 * HI_PAIR(c01)) >> 2;
74    return COMBINE(lo, hi);
75}
76
77static unsigned bilerp4_10(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
78    uint32_t lo = (3 * LO_PAIR(c00) + LO_PAIR(c10)) >> 2;
79    uint32_t hi = (3 * HI_PAIR(c00) + HI_PAIR(c10)) >> 2;
80    return COMBINE(lo, hi);
81}
82static unsigned bilerp4_11(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
83    uint32_t lo = (9 * LO_PAIR(c00) + 3 * (LO_PAIR(c01) + LO_PAIR(c10)) + LO_PAIR(c11)) >> 4;
84    uint32_t hi = (9 * HI_PAIR(c00) + 3 * (HI_PAIR(c01) + HI_PAIR(c10)) + HI_PAIR(c11)) >> 4;
85    return COMBINE(lo, hi);
86}
87static unsigned bilerp4_12(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
88    uint32_t lo = (3 * (LO_PAIR(c00) + LO_PAIR(c01)) + LO_PAIR(c10) + LO_PAIR(c11)) >> 3;
89    uint32_t hi = (3 * (HI_PAIR(c00) + HI_PAIR(c01)) + HI_PAIR(c10) + HI_PAIR(c11)) >> 3;
90    return COMBINE(lo, hi);
91}
92static unsigned bilerp4_13(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
93    uint32_t lo = (9 * LO_PAIR(c01) + 3 * (LO_PAIR(c00) + LO_PAIR(c11)) + LO_PAIR(c10)) >> 4;
94    uint32_t hi = (9 * HI_PAIR(c01) + 3 * (HI_PAIR(c00) + HI_PAIR(c11)) + HI_PAIR(c10)) >> 4;
95    return COMBINE(lo, hi);
96}
97
98static unsigned bilerp4_20(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
99    uint32_t lo = (LO_PAIR(c00) + LO_PAIR(c10)) >> 1;
100    uint32_t hi = (HI_PAIR(c00) + HI_PAIR(c10)) >> 1;
101    return COMBINE(lo, hi);
102}
103static unsigned bilerp4_21(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
104    uint32_t lo = (3 * (LO_PAIR(c00) + LO_PAIR(c10)) + LO_PAIR(c01) + LO_PAIR(c11)) >> 3;
105    uint32_t hi = (3 * (HI_PAIR(c00) + HI_PAIR(c10)) + HI_PAIR(c01) + HI_PAIR(c11)) >> 3;
106    return COMBINE(lo, hi);
107}
108static unsigned bilerp4_22(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
109    uint32_t lo = (LO_PAIR(c00) + LO_PAIR(c01) + LO_PAIR(c10) + LO_PAIR(c11)) >> 2;
110    uint32_t hi = (HI_PAIR(c00) + HI_PAIR(c01) + HI_PAIR(c10) + HI_PAIR(c11)) >> 2;
111    return COMBINE(lo, hi);
112}
113static unsigned bilerp4_23(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
114    uint32_t lo = (3 * (LO_PAIR(c01) + LO_PAIR(c11)) + LO_PAIR(c00) + LO_PAIR(c10)) >> 3;
115    uint32_t hi = (3 * (HI_PAIR(c01) + HI_PAIR(c11)) + HI_PAIR(c00) + HI_PAIR(c10)) >> 3;
116    return COMBINE(lo, hi);
117}
118
119static unsigned bilerp4_30(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
120    uint32_t lo = (LO_PAIR(c00) + 3 * LO_PAIR(c10)) >> 2;
121    uint32_t hi = (HI_PAIR(c00) + 3 * HI_PAIR(c10)) >> 2;
122    return COMBINE(lo, hi);
123}
124static unsigned bilerp4_31(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
125    uint32_t lo = (9 * LO_PAIR(c10) + 3 * (LO_PAIR(c00) + LO_PAIR(c11)) + LO_PAIR(c01)) >> 4;
126    uint32_t hi = (9 * HI_PAIR(c10) + 3 * (HI_PAIR(c00) + HI_PAIR(c11)) + HI_PAIR(c01)) >> 4;
127    return COMBINE(lo, hi);
128}
129static unsigned bilerp4_32(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
130    uint32_t lo = (3 * (LO_PAIR(c10) + LO_PAIR(c11)) + LO_PAIR(c00) + LO_PAIR(c01)) >> 3;
131    uint32_t hi = (3 * (HI_PAIR(c10) + HI_PAIR(c11)) + HI_PAIR(c00) + HI_PAIR(c01)) >> 3;
132    return COMBINE(lo, hi);
133}
134static unsigned bilerp4_33(uint32_t c00, uint32_t c01, uint32_t c10, uint32_t c11) {
135    uint32_t lo = (9 * LO_PAIR(c11) + 3 * (LO_PAIR(c01) + LO_PAIR(c10)) + LO_PAIR(c00)) >> 4;
136    uint32_t hi = (9 * HI_PAIR(c11) + 3 * (HI_PAIR(c01) + HI_PAIR(c10)) + HI_PAIR(c00)) >> 4;
137    return COMBINE(lo, hi);
138}
139
140static const SkFilter32Proc gBilerp32Procs[4 * 4] = {
141    bilerp4_00, bilerp4_01, bilerp4_02, bilerp4_03,
142    bilerp4_10, bilerp4_11, bilerp4_12, bilerp4_13,
143    bilerp4_20, bilerp4_21, bilerp4_22, bilerp4_23,
144    bilerp4_30, bilerp4_31, bilerp4_32, bilerp4_33
145};
146
147const SkFilter32Proc* SkGetFilter32ProcTable()
148{
149    return gBilerp32Procs;
150}
151
152///////////////////////////////////////////////////////////////////////////////
153
154static uint32_t bilerptr00(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
155    return *a00;
156}
157static uint32_t bilerptr01(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
158    uint32_t c00 = *a00;
159    uint32_t c01 = *a01;
160    uint32_t lo = (3 * LO_PAIR(c00) + LO_PAIR(c01)) >> 2;
161    uint32_t hi = (3 * HI_PAIR(c00) + HI_PAIR(c01)) >> 2;
162    return COMBINE(lo, hi);
163}
164static uint32_t bilerptr02(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
165    uint32_t c00 = *a00;
166    uint32_t c01 = *a01;
167    uint32_t lo = (LO_PAIR(c00) + LO_PAIR(c01)) >> 1;
168    uint32_t hi = (HI_PAIR(c00) + HI_PAIR(c01)) >> 1;
169    return COMBINE(lo, hi);
170}
171static uint32_t bilerptr03(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
172    uint32_t c00 = *a00;
173    uint32_t c01 = *a01;
174    uint32_t lo = (LO_PAIR(c00) + 3 * LO_PAIR(c01)) >> 2;
175    uint32_t hi = (HI_PAIR(c00) + 3 * HI_PAIR(c01)) >> 2;
176    return COMBINE(lo, hi);
177}
178
179static uint32_t bilerptr10(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
180    uint32_t c00 = *a00;
181    uint32_t c10 = *a10;
182    uint32_t lo = (3 * LO_PAIR(c00) + LO_PAIR(c10)) >> 2;
183    uint32_t hi = (3 * HI_PAIR(c00) + HI_PAIR(c10)) >> 2;
184    return COMBINE(lo, hi);
185}
186static uint32_t bilerptr11(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
187    uint32_t c00 = *a00;
188    uint32_t c01 = *a01;
189    uint32_t c10 = *a10;
190    uint32_t c11 = *a11;
191    uint32_t lo = (9 * LO_PAIR(c00) + 3 * (LO_PAIR(c01) + LO_PAIR(c10)) + LO_PAIR(c11)) >> 4;
192    uint32_t hi = (9 * HI_PAIR(c00) + 3 * (HI_PAIR(c01) + HI_PAIR(c10)) + HI_PAIR(c11)) >> 4;
193    return COMBINE(lo, hi);
194}
195static uint32_t bilerptr12(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
196    uint32_t c00 = *a00;
197    uint32_t c01 = *a01;
198    uint32_t c10 = *a10;
199    uint32_t c11 = *a11;
200    uint32_t lo = (3 * (LO_PAIR(c00) + LO_PAIR(c01)) + LO_PAIR(c10) + LO_PAIR(c11)) >> 3;
201    uint32_t hi = (3 * (HI_PAIR(c00) + HI_PAIR(c01)) + HI_PAIR(c10) + HI_PAIR(c11)) >> 3;
202    return COMBINE(lo, hi);
203}
204static uint32_t bilerptr13(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
205    uint32_t c00 = *a00;
206    uint32_t c01 = *a01;
207    uint32_t c10 = *a10;
208    uint32_t c11 = *a11;
209    uint32_t lo = (9 * LO_PAIR(c01) + 3 * (LO_PAIR(c00) + LO_PAIR(c11)) + LO_PAIR(c10)) >> 4;
210    uint32_t hi = (9 * HI_PAIR(c01) + 3 * (HI_PAIR(c00) + HI_PAIR(c11)) + HI_PAIR(c10)) >> 4;
211    return COMBINE(lo, hi);
212}
213
214static uint32_t bilerptr20(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
215    uint32_t c00 = *a00;
216    uint32_t c10 = *a10;
217    uint32_t lo = (LO_PAIR(c00) + LO_PAIR(c10)) >> 1;
218    uint32_t hi = (HI_PAIR(c00) + HI_PAIR(c10)) >> 1;
219    return COMBINE(lo, hi);
220}
221static uint32_t bilerptr21(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
222    uint32_t c00 = *a00;
223    uint32_t c01 = *a01;
224    uint32_t c10 = *a10;
225    uint32_t c11 = *a11;
226    uint32_t lo = (3 * (LO_PAIR(c00) + LO_PAIR(c10)) + LO_PAIR(c01) + LO_PAIR(c11)) >> 3;
227    uint32_t hi = (3 * (HI_PAIR(c00) + HI_PAIR(c10)) + HI_PAIR(c01) + HI_PAIR(c11)) >> 3;
228    return COMBINE(lo, hi);
229}
230static uint32_t bilerptr22(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
231    uint32_t c00 = *a00;
232    uint32_t c01 = *a01;
233    uint32_t c10 = *a10;
234    uint32_t c11 = *a11;
235    uint32_t lo = (LO_PAIR(c00) + LO_PAIR(c01) + LO_PAIR(c10) + LO_PAIR(c11)) >> 2;
236    uint32_t hi = (HI_PAIR(c00) + HI_PAIR(c01) + HI_PAIR(c10) + HI_PAIR(c11)) >> 2;
237    return COMBINE(lo, hi);
238}
239static uint32_t bilerptr23(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
240    uint32_t c00 = *a00;
241    uint32_t c01 = *a01;
242    uint32_t c10 = *a10;
243    uint32_t c11 = *a11;
244    uint32_t lo = (3 * (LO_PAIR(c01) + LO_PAIR(c11)) + LO_PAIR(c00) + LO_PAIR(c10)) >> 3;
245    uint32_t hi = (3 * (HI_PAIR(c01) + HI_PAIR(c11)) + HI_PAIR(c00) + HI_PAIR(c10)) >> 3;
246    return COMBINE(lo, hi);
247}
248
249static uint32_t bilerptr30(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
250    uint32_t c00 = *a00;
251    uint32_t c10 = *a10;
252    uint32_t lo = (LO_PAIR(c00) + 3 * LO_PAIR(c10)) >> 2;
253    uint32_t hi = (HI_PAIR(c00) + 3 * HI_PAIR(c10)) >> 2;
254    return COMBINE(lo, hi);
255}
256static uint32_t bilerptr31(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
257    uint32_t c00 = *a00;
258    uint32_t c01 = *a01;
259    uint32_t c10 = *a10;
260    uint32_t c11 = *a11;
261    uint32_t lo = (9 * LO_PAIR(c10) + 3 * (LO_PAIR(c00) + LO_PAIR(c11)) + LO_PAIR(c01)) >> 4;
262    uint32_t hi = (9 * HI_PAIR(c10) + 3 * (HI_PAIR(c00) + HI_PAIR(c11)) + HI_PAIR(c01)) >> 4;
263    return COMBINE(lo, hi);
264}
265static uint32_t bilerptr32(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
266    uint32_t c00 = *a00;
267    uint32_t c01 = *a01;
268    uint32_t c10 = *a10;
269    uint32_t c11 = *a11;
270    uint32_t lo = (3 * (LO_PAIR(c10) + LO_PAIR(c11)) + LO_PAIR(c00) + LO_PAIR(c01)) >> 3;
271    uint32_t hi = (3 * (HI_PAIR(c10) + HI_PAIR(c11)) + HI_PAIR(c00) + HI_PAIR(c01)) >> 3;
272    return COMBINE(lo, hi);
273}
274static uint32_t bilerptr33(const uint32_t* a00, const uint32_t* a01, const uint32_t* a10, const uint32_t* a11) {
275    uint32_t c00 = *a00;
276    uint32_t c01 = *a01;
277    uint32_t c10 = *a10;
278    uint32_t c11 = *a11;
279    uint32_t lo = (9 * LO_PAIR(c11) + 3 * (LO_PAIR(c01) + LO_PAIR(c10)) + LO_PAIR(c00)) >> 4;
280    uint32_t hi = (9 * HI_PAIR(c11) + 3 * (HI_PAIR(c01) + HI_PAIR(c10)) + HI_PAIR(c00)) >> 4;
281    return COMBINE(lo, hi);
282}
283
284static const SkFilterPtrProc gBilerpPtrProcs[4 * 4] = {
285    bilerptr00, bilerptr01, bilerptr02, bilerptr03,
286    bilerptr10, bilerptr11, bilerptr12, bilerptr13,
287    bilerptr20, bilerptr21, bilerptr22, bilerptr23,
288    bilerptr30, bilerptr31, bilerptr32, bilerptr33
289};
290
291const SkFilterPtrProc* SkGetBilinearFilterPtrProcTable()
292{
293    return gBilerpPtrProcs;
294}
295