292f9317 |
1 | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
2 | * Mupen64plus - TextureFilters_hq2x.cpp * |
3 | * Mupen64Plus homepage: http://code.google.com/p/mupen64plus/ * |
4 | * Copyright (C) 2003 MaxSt ( maxst@hiend3d.com ) * |
5 | * * |
6 | * This program is free software; you can redistribute it and/or modify * |
7 | * it under the terms of the GNU General Public License as published by * |
8 | * the Free Software Foundation; either version 2 of the License, or * |
9 | * (at your option) any later version. * |
10 | * * |
11 | * This program is distributed in the hope that it will be useful, * |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
14 | * GNU General Public License for more details. * |
15 | * * |
16 | * You should have received a copy of the GNU General Public License * |
17 | * along with this program; if not, write to the * |
18 | * Free Software Foundation, Inc., * |
19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * |
20 | * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
21 | |
22 | #include "typedefs.h" |
23 | |
24 | /************************************************************************/ |
25 | /* hq2x filters */ |
26 | /************************************************************************/ |
27 | |
28 | /***************************************************************************/ |
29 | /* Basic types */ |
30 | |
31 | /***************************************************************************/ |
32 | /* interpolation */ |
33 | |
34 | static unsigned interp_bits_per_pixel; |
35 | |
36 | #define INTERP_16_MASK_1_3(v) ((v)&0x0F0F) |
37 | #define INTERP_16_MASK_SHIFT_2_4(v) (((v)&0xF0F0)>>4) |
38 | #define INTERP_16_MASK_SHIFTBACK_2_4(v) ((INTERP_16_MASK_1_3(v))<<4) |
39 | |
40 | static inline uint16 hq2x_interp_16_521(uint16 p1, uint16 p2, uint16 p3) |
41 | { |
42 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*2 + INTERP_16_MASK_1_3(p3)*1) / 8) |
43 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*2 + INTERP_16_MASK_SHIFT_2_4(p3)*1) / 8); |
44 | } |
45 | |
46 | static inline uint16 hq2x_interp_16_332(uint16 p1, uint16 p2, uint16 p3) |
47 | { |
48 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)*2) / 8) |
49 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 8); |
50 | } |
51 | |
52 | static inline uint16 hq2x_interp_16_611(uint16 p1, uint16 p2, uint16 p3) |
53 | { |
54 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*6 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 8) |
55 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*6 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 8); |
56 | } |
57 | |
58 | static inline uint16 hq2x_interp_16_71(uint16 p1, uint16 p2) |
59 | { |
60 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*7 + INTERP_16_MASK_1_3(p2)) / 8) |
61 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*7 + INTERP_16_MASK_SHIFT_2_4(p2)) / 8); |
62 | } |
63 | |
64 | static inline uint16 hq2x_interp_16_211(uint16 p1, uint16 p2, uint16 p3) |
65 | { |
66 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*2 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 4) |
67 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*2 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 4); |
68 | } |
69 | |
70 | static inline uint16 hq2x_interp_16_772(uint16 p1, uint16 p2, uint16 p3) |
71 | { |
72 | return INTERP_16_MASK_1_3(((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2))*7 + INTERP_16_MASK_1_3(p3)*2) / 16) |
73 | | INTERP_16_MASK_SHIFTBACK_2_4(((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2))*7 + INTERP_16_MASK_SHIFT_2_4(p3)*2) / 16); |
74 | } |
75 | |
76 | static inline uint16 hq2x_interp_16_11(uint16 p1, uint16 p2) |
77 | { |
78 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1) + INTERP_16_MASK_1_3(p2)) / 2) |
79 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1) + INTERP_16_MASK_SHIFT_2_4(p2)) / 2); |
80 | } |
81 | |
82 | static inline uint16 hq2x_interp_16_31(uint16 p1, uint16 p2) |
83 | { |
84 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*3 + INTERP_16_MASK_1_3(p2)) / 4) |
85 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*3 + INTERP_16_MASK_SHIFT_2_4(p2)) / 4); |
86 | } |
87 | |
88 | static inline uint16 hq2x_interp_16_1411(uint16 p1, uint16 p2, uint16 p3) |
89 | { |
90 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*14 + INTERP_16_MASK_1_3(p2) + INTERP_16_MASK_1_3(p3)) / 16) |
91 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*14 + INTERP_16_MASK_SHIFT_2_4(p2) + INTERP_16_MASK_SHIFT_2_4(p3)) / 16); |
92 | } |
93 | |
94 | static inline uint16 hq2x_interp_16_431(uint16 p1, uint16 p2, uint16 p3) |
95 | { |
96 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*4 + INTERP_16_MASK_1_3(p2)*3 + INTERP_16_MASK_1_3(p3)) / 8) |
97 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*4 + INTERP_16_MASK_SHIFT_2_4(p2)*3 + INTERP_16_MASK_SHIFT_2_4(p3)) / 8); |
98 | } |
99 | |
100 | static inline uint16 hq2x_interp_16_53(uint16 p1, uint16 p2) |
101 | { |
102 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*5 + INTERP_16_MASK_1_3(p2)*3) / 8) |
103 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*5 + INTERP_16_MASK_SHIFT_2_4(p2)*3) / 8); |
104 | } |
105 | |
106 | static inline uint16 hq2x_interp_16_151(uint16 p1, uint16 p2) |
107 | { |
108 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*15 + INTERP_16_MASK_1_3(p2)) / 16) |
109 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*15 + INTERP_16_MASK_SHIFT_2_4(p2)) / 16); |
110 | } |
111 | |
112 | static inline uint16 hq2x_interp_16_97(uint16 p1, uint16 p2) |
113 | { |
114 | return INTERP_16_MASK_1_3((INTERP_16_MASK_1_3(p1)*9 + INTERP_16_MASK_1_3(p2)*7) / 16) |
115 | | INTERP_16_MASK_SHIFTBACK_2_4((INTERP_16_MASK_SHIFT_2_4(p1)*9 + INTERP_16_MASK_SHIFT_2_4(p2)*7) / 16); |
116 | } |
117 | |
118 | #define INTERP_32_MASK_1_3(v) ((v)&0x00FF00FF) |
119 | #define INTERP_32_MASK_SHIFT_2_4(v) (((v)&0xFF00FF00)>>8) |
120 | #define INTERP_32_MASK_SHIFTBACK_2_4(v) (((INTERP_32_MASK_1_3(v))<<8)) |
121 | |
122 | static inline uint32 hq2x_interp_32_521(uint32 p1, uint32 p2, uint32 p3) |
123 | { |
124 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*5 + INTERP_32_MASK_1_3(p2)*2 + INTERP_32_MASK_1_3(p3)*1) / 8) |
125 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*5 + INTERP_32_MASK_SHIFT_2_4(p2)*2 + INTERP_32_MASK_SHIFT_2_4(p3)*1) / 8); |
126 | } |
127 | |
128 | static inline uint32 hq2x_interp_32_332(uint32 p1, uint32 p2, uint32 p3) |
129 | { |
130 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)*3 + INTERP_32_MASK_1_3(p3)*2) / 8) |
131 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)*3 + INTERP_32_MASK_SHIFT_2_4(p3)*2) / 8); |
132 | } |
133 | |
134 | static inline uint32 hq2x_interp_32_211(uint32 p1, uint32 p2, uint32 p3) |
135 | { |
136 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*2 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 4) |
137 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*2 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 4); |
138 | } |
139 | |
140 | static inline uint32 hq2x_interp_32_611(uint32 p1, uint32 p2, uint32 p3) |
141 | { |
142 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*6 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 8) |
143 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*6 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 8); |
144 | } |
145 | |
146 | static inline uint32 hq2x_interp_32_71(uint32 p1, uint32 p2) |
147 | { |
148 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*7 + INTERP_32_MASK_1_3(p2)) / 8) |
149 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*7 + INTERP_32_MASK_SHIFT_2_4(p2)) / 8); |
150 | } |
151 | |
152 | static inline uint32 hq2x_interp_32_772(uint32 p1, uint32 p2, uint32 p3) |
153 | { |
154 | return INTERP_32_MASK_1_3(((INTERP_32_MASK_1_3(p1) + INTERP_32_MASK_1_3(p2))*7 + INTERP_32_MASK_1_3(p3)*2) / 16) |
155 | | INTERP_32_MASK_SHIFTBACK_2_4(((INTERP_32_MASK_SHIFT_2_4(p1) + INTERP_32_MASK_SHIFT_2_4(p2))*7 + INTERP_32_MASK_SHIFT_2_4(p3)*2) / 16); |
156 | } |
157 | |
158 | static inline uint32 hq2x_interp_32_11(uint32 p1, uint32 p2) |
159 | { |
160 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1) + INTERP_32_MASK_1_3(p2)) / 2) |
161 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1) + INTERP_32_MASK_SHIFT_2_4(p2)) / 2); |
162 | } |
163 | |
164 | static inline uint32 hq2x_interp_32_31(uint32 p1, uint32 p2) |
165 | { |
166 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*3 + INTERP_32_MASK_1_3(p2)) / 4) |
167 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*3 + INTERP_32_MASK_SHIFT_2_4(p2)) / 4); |
168 | } |
169 | |
170 | static inline uint32 hq2x_interp_32_1411(uint32 p1, uint32 p2, uint32 p3) |
171 | { |
172 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*14 + INTERP_32_MASK_1_3(p2) + INTERP_32_MASK_1_3(p3)) / 16) |
173 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*14 + INTERP_32_MASK_SHIFT_2_4(p2) + INTERP_32_MASK_SHIFT_2_4(p3)) / 16); |
174 | } |
175 | |
176 | static inline uint32 hq2x_interp_32_431(uint32 p1, uint32 p2, uint32 p3) |
177 | { |
178 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*4 + INTERP_32_MASK_1_3(p2)*3 + INTERP_32_MASK_1_3(p3)) / 8) |
179 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*4 + INTERP_32_MASK_SHIFT_2_4(p2)*3 + INTERP_32_MASK_SHIFT_2_4(p3)) / 8); |
180 | } |
181 | |
182 | static inline uint32 hq2x_interp_32_53(uint32 p1, uint32 p2) |
183 | { |
184 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*5 + INTERP_32_MASK_1_3(p2)*3) / 8) |
185 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*5 + INTERP_32_MASK_SHIFT_2_4(p2)*3) / 8); |
186 | } |
187 | |
188 | static inline uint32 hq2x_interp_32_151(uint32 p1, uint32 p2) |
189 | { |
190 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*15 + INTERP_32_MASK_1_3(p2)) / 16) |
191 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*15 + INTERP_32_MASK_SHIFT_2_4(p2)) / 16); |
192 | } |
193 | |
194 | static inline uint32 hq2x_interp_32_97(uint32 p1, uint32 p2) |
195 | { |
196 | return INTERP_32_MASK_1_3((INTERP_32_MASK_1_3(p1)*9 + INTERP_32_MASK_1_3(p2)*7) / 16) |
197 | | INTERP_32_MASK_SHIFTBACK_2_4((INTERP_32_MASK_SHIFT_2_4(p1)*9 + INTERP_32_MASK_SHIFT_2_4(p2)*7) / 16); |
198 | } |
199 | |
200 | /***************************************************************************/ |
201 | /* diff */ |
202 | |
203 | #define INTERP_Y_LIMIT (0x30*4) |
204 | #define INTERP_U_LIMIT (0x07*4) |
205 | #define INTERP_V_LIMIT (0x06*8) |
206 | |
207 | static int hq2x_interp_16_diff(uint16 p1, uint16 p2) |
208 | { |
209 | int r, g, b; |
210 | int y, u, v; |
211 | |
212 | if (p1 == p2) |
213 | return 0; |
214 | |
215 | b = (int)((p1 & 0x000F) - (p2 & 0x000F)); |
216 | g = (int)((p1 & 0x00F0) - (p2 & 0x00F0)) >> 4; |
217 | r = (int)((p1 & 0x0F00) - (p2 & 0x0F00)) >> 8; |
218 | |
219 | y = r + g + b; |
220 | u = r - b; |
221 | v = -r + 2*g - b; |
222 | |
223 | if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) |
224 | return 1; |
225 | |
226 | if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) |
227 | return 1; |
228 | |
229 | if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) |
230 | return 1; |
231 | |
232 | return 0; |
233 | } |
234 | |
235 | static int hq2x_interp_32_diff(uint32 p1, uint32 p2) |
236 | { |
237 | int r, g, b; |
238 | int y, u, v; |
239 | |
240 | if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8)) |
241 | return 0; |
242 | |
243 | b = (int)((p1 & 0xFF) - (p2 & 0xFF)); |
244 | g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8; |
245 | r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16; |
246 | |
247 | y = r + g + b; |
248 | u = r - b; |
249 | v = -r + 2*g - b; |
250 | |
251 | if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT) |
252 | return 1; |
253 | |
254 | if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT) |
255 | return 1; |
256 | |
257 | if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT) |
258 | return 1; |
259 | |
260 | return 0; |
261 | } |
262 | |
263 | static void interp_set(unsigned bits_per_pixel) |
264 | { |
265 | interp_bits_per_pixel = bits_per_pixel; |
266 | } |
267 | |
268 | |
269 | static void hq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) |
270 | { |
271 | unsigned i; |
272 | |
273 | for(i=0;i<count;++i) { |
274 | unsigned char mask; |
275 | |
276 | uint16 c[9]; |
277 | |
278 | c[1] = src0[0]; |
279 | c[4] = src1[0]; |
280 | c[7] = src2[0]; |
281 | |
282 | if (i>0) { |
283 | c[0] = src0[-1]; |
284 | c[3] = src1[-1]; |
285 | c[6] = src2[-1]; |
286 | } else { |
287 | c[0] = c[1]; |
288 | c[3] = c[4]; |
289 | c[6] = c[7]; |
290 | } |
291 | |
292 | if (i<count-1) { |
293 | c[2] = src0[1]; |
294 | c[5] = src1[1]; |
295 | c[8] = src2[1]; |
296 | } else { |
297 | c[2] = c[1]; |
298 | c[5] = c[4]; |
299 | c[8] = c[7]; |
300 | } |
301 | |
302 | mask = 0; |
303 | |
304 | if (hq2x_interp_16_diff(c[0], c[4])) |
305 | mask |= 1 << 0; |
306 | if (hq2x_interp_16_diff(c[1], c[4])) |
307 | mask |= 1 << 1; |
308 | if (hq2x_interp_16_diff(c[2], c[4])) |
309 | mask |= 1 << 2; |
310 | if (hq2x_interp_16_diff(c[3], c[4])) |
311 | mask |= 1 << 3; |
312 | if (hq2x_interp_16_diff(c[5], c[4])) |
313 | mask |= 1 << 4; |
314 | if (hq2x_interp_16_diff(c[6], c[4])) |
315 | mask |= 1 << 5; |
316 | if (hq2x_interp_16_diff(c[7], c[4])) |
317 | mask |= 1 << 6; |
318 | if (hq2x_interp_16_diff(c[8], c[4])) |
319 | mask |= 1 << 7; |
320 | |
321 | #define P0 dst0[0] |
322 | #define P1 dst0[1] |
323 | #define P2 dst1[0] |
324 | #define P3 dst1[1] |
325 | #define HQ2X_MUR hq2x_interp_16_diff(c[1], c[5]) |
326 | #define HQ2X_MDR hq2x_interp_16_diff(c[5], c[7]) |
327 | #define HQ2X_MDL hq2x_interp_16_diff(c[7], c[3]) |
328 | #define HQ2X_MUL hq2x_interp_16_diff(c[3], c[1]) |
329 | #define IC(p0) c[p0] |
330 | #define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) |
331 | #define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) |
332 | #define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) |
333 | #define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) |
334 | #define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) |
335 | #define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) |
336 | #define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) |
337 | #define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) |
338 | #define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) |
339 | #define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) |
340 | #define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) |
341 | #define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) |
342 | #define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) |
343 | |
344 | switch (mask) { |
345 | #include "TextureFilters_hq2x.h" |
346 | } |
347 | |
348 | #undef P0 |
349 | #undef P1 |
350 | #undef P2 |
351 | #undef P3 |
352 | #undef HQ2X_MUR |
353 | #undef HQ2X_MDR |
354 | #undef HQ2X_MDL |
355 | #undef HQ2X_MUL |
356 | #undef IC |
357 | #undef I11 |
358 | #undef I211 |
359 | #undef I31 |
360 | #undef I332 |
361 | #undef I431 |
362 | #undef I521 |
363 | #undef I53 |
364 | #undef I611 |
365 | #undef I71 |
366 | #undef I772 |
367 | #undef I97 |
368 | #undef I1411 |
369 | #undef I151 |
370 | |
371 | src0 += 1; |
372 | src1 += 1; |
373 | src2 += 1; |
374 | dst0 += 2; |
375 | dst1 += 2; |
376 | } |
377 | } |
378 | |
379 | static void hq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) |
380 | { |
381 | unsigned i; |
382 | |
383 | for(i=0;i<count;++i) { |
384 | unsigned char mask; |
385 | |
386 | uint32 c[9]; |
387 | |
388 | c[1] = src0[0]; |
389 | c[4] = src1[0]; |
390 | c[7] = src2[0]; |
391 | |
392 | if (i>0) { |
393 | c[0] = src0[-1]; |
394 | c[3] = src1[-1]; |
395 | c[6] = src2[-1]; |
396 | } else { |
397 | c[0] = src0[0]; |
398 | c[3] = src1[0]; |
399 | c[6] = src2[0]; |
400 | } |
401 | |
402 | if (i<count-1) { |
403 | c[2] = src0[1]; |
404 | c[5] = src1[1]; |
405 | c[8] = src2[1]; |
406 | } else { |
407 | c[2] = src0[0]; |
408 | c[5] = src1[0]; |
409 | c[8] = src2[0]; |
410 | } |
411 | |
412 | mask = 0; |
413 | |
414 | if (hq2x_interp_32_diff(c[0], c[4])) |
415 | mask |= 1 << 0; |
416 | if (hq2x_interp_32_diff(c[1], c[4])) |
417 | mask |= 1 << 1; |
418 | if (hq2x_interp_32_diff(c[2], c[4])) |
419 | mask |= 1 << 2; |
420 | if (hq2x_interp_32_diff(c[3], c[4])) |
421 | mask |= 1 << 3; |
422 | if (hq2x_interp_32_diff(c[5], c[4])) |
423 | mask |= 1 << 4; |
424 | if (hq2x_interp_32_diff(c[6], c[4])) |
425 | mask |= 1 << 5; |
426 | if (hq2x_interp_32_diff(c[7], c[4])) |
427 | mask |= 1 << 6; |
428 | if (hq2x_interp_32_diff(c[8], c[4])) |
429 | mask |= 1 << 7; |
430 | |
431 | #define P0 dst0[0] |
432 | #define P1 dst0[1] |
433 | #define P2 dst1[0] |
434 | #define P3 dst1[1] |
435 | #define HQ2X_MUR hq2x_interp_32_diff(c[1], c[5]) |
436 | #define HQ2X_MDR hq2x_interp_32_diff(c[5], c[7]) |
437 | #define HQ2X_MDL hq2x_interp_32_diff(c[7], c[3]) |
438 | #define HQ2X_MUL hq2x_interp_32_diff(c[3], c[1]) |
439 | #define IC(p0) c[p0] |
440 | #define I11(p0,p1) hq2x_interp_32_11(c[p0], c[p1]) |
441 | #define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) |
442 | #define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) |
443 | #define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) |
444 | #define I431(p0,p1,p2) hq2x_interp_32_431(c[p0], c[p1], c[p2]) |
445 | #define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) |
446 | #define I53(p0,p1) hq2x_interp_32_53(c[p0], c[p1]) |
447 | #define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) |
448 | #define I71(p0,p1) hq2x_interp_32_71(c[p0], c[p1]) |
449 | #define I772(p0,p1,p2) hq2x_interp_32_772(c[p0], c[p1], c[p2]) |
450 | #define I97(p0,p1) hq2x_interp_32_97(c[p0], c[p1]) |
451 | #define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) |
452 | #define I151(p0,p1) hq2x_interp_32_151(c[p0], c[p1]) |
453 | |
454 | switch (mask) { |
455 | #include "TextureFilters_hq2x.h" |
456 | } |
457 | |
458 | #undef P0 |
459 | #undef P1 |
460 | #undef P2 |
461 | #undef P3 |
462 | #undef HQ2X_MUR |
463 | #undef HQ2X_MDR |
464 | #undef HQ2X_MDL |
465 | #undef HQ2X_MUL |
466 | #undef IC |
467 | #undef I11 |
468 | #undef I211 |
469 | #undef I31 |
470 | #undef I332 |
471 | #undef I431 |
472 | #undef I521 |
473 | #undef I53 |
474 | #undef I611 |
475 | #undef I71 |
476 | #undef I772 |
477 | #undef I97 |
478 | #undef I1411 |
479 | #undef I151 |
480 | |
481 | src0 += 1; |
482 | src1 += 1; |
483 | src2 += 1; |
484 | dst0 += 2; |
485 | dst1 += 2; |
486 | } |
487 | } |
488 | |
489 | /***************************************************************************/ |
490 | /* LQ2x C implementation */ |
491 | |
492 | /* |
493 | * This effect is derived from the hq2x effect made by Maxim Stepin |
494 | */ |
495 | |
496 | static void lq2x_16_def(uint16* dst0, uint16* dst1, const uint16* src0, const uint16* src1, const uint16* src2, unsigned count) |
497 | { |
498 | unsigned i; |
499 | |
500 | for(i=0;i<count;++i) { |
501 | unsigned char mask; |
502 | |
503 | uint16 c[9]; |
504 | |
505 | c[1] = src0[0]; |
506 | c[4] = src1[0]; |
507 | c[7] = src2[0]; |
508 | |
509 | if (i>0) { |
510 | c[0] = src0[-1]; |
511 | c[3] = src1[-1]; |
512 | c[6] = src2[-1]; |
513 | } else { |
514 | c[0] = c[1]; |
515 | c[3] = c[4]; |
516 | c[6] = c[7]; |
517 | } |
518 | |
519 | if (i<count-1) { |
520 | c[2] = src0[1]; |
521 | c[5] = src1[1]; |
522 | c[8] = src2[1]; |
523 | } else { |
524 | c[2] = c[1]; |
525 | c[5] = c[4]; |
526 | c[8] = c[7]; |
527 | } |
528 | |
529 | mask = 0; |
530 | |
531 | if (c[0] != c[4]) |
532 | mask |= 1 << 0; |
533 | if (c[1] != c[4]) |
534 | mask |= 1 << 1; |
535 | if (c[2] != c[4]) |
536 | mask |= 1 << 2; |
537 | if (c[3] != c[4]) |
538 | mask |= 1 << 3; |
539 | if (c[5] != c[4]) |
540 | mask |= 1 << 4; |
541 | if (c[6] != c[4]) |
542 | mask |= 1 << 5; |
543 | if (c[7] != c[4]) |
544 | mask |= 1 << 6; |
545 | if (c[8] != c[4]) |
546 | mask |= 1 << 7; |
547 | |
548 | #define P0 dst0[0] |
549 | #define P1 dst0[1] |
550 | #define P2 dst1[0] |
551 | #define P3 dst1[1] |
552 | #define HQ2X_MUR (c[1] != c[5]) |
553 | #define HQ2X_MDR (c[5] != c[7]) |
554 | #define HQ2X_MDL (c[7] != c[3]) |
555 | #define HQ2X_MUL (c[3] != c[1]) |
556 | #define IC(p0) c[p0] |
557 | #define I11(p0,p1) hq2x_interp_16_11(c[p0], c[p1]) |
558 | #define I211(p0,p1,p2) hq2x_interp_16_211(c[p0], c[p1], c[p2]) |
559 | #define I31(p0,p1) hq2x_interp_16_31(c[p0], c[p1]) |
560 | #define I332(p0,p1,p2) hq2x_interp_16_332(c[p0], c[p1], c[p2]) |
561 | #define I431(p0,p1,p2) hq2x_interp_16_431(c[p0], c[p1], c[p2]) |
562 | #define I521(p0,p1,p2) hq2x_interp_16_521(c[p0], c[p1], c[p2]) |
563 | #define I53(p0,p1) hq2x_interp_16_53(c[p0], c[p1]) |
564 | #define I611(p0,p1,p2) hq2x_interp_16_611(c[p0], c[p1], c[p2]) |
565 | #define I71(p0,p1) hq2x_interp_16_71(c[p0], c[p1]) |
566 | #define I772(p0,p1,p2) hq2x_interp_16_772(c[p0], c[p1], c[p2]) |
567 | #define I97(p0,p1) hq2x_interp_16_97(c[p0], c[p1]) |
568 | #define I1411(p0,p1,p2) hq2x_interp_16_1411(c[p0], c[p1], c[p2]) |
569 | #define I151(p0,p1) hq2x_interp_16_151(c[p0], c[p1]) |
570 | |
571 | switch (mask) { |
572 | #include "TextureFilters_lq2x.h" |
573 | } |
574 | |
575 | #undef P0 |
576 | #undef P1 |
577 | #undef P2 |
578 | #undef P3 |
579 | #undef HQ2X_MUR |
580 | #undef HQ2X_MDR |
581 | #undef HQ2X_MDL |
582 | #undef HQ2X_MUL |
583 | #undef IC |
584 | #undef I11 |
585 | #undef I211 |
586 | #undef I31 |
587 | #undef I332 |
588 | #undef I431 |
589 | #undef I521 |
590 | #undef I53 |
591 | #undef I611 |
592 | #undef I71 |
593 | #undef I772 |
594 | #undef I97 |
595 | #undef I1411 |
596 | #undef I151 |
597 | |
598 | src0 += 1; |
599 | src1 += 1; |
600 | src2 += 1; |
601 | dst0 += 2; |
602 | dst1 += 2; |
603 | } |
604 | } |
605 | |
606 | static void lq2x_32_def(uint32* dst0, uint32* dst1, const uint32* src0, const uint32* src1, const uint32* src2, unsigned count) |
607 | { |
608 | unsigned i; |
609 | |
610 | for(i=0;i<count;++i) { |
611 | unsigned char mask; |
612 | |
613 | uint32 c[9]; |
614 | |
615 | c[1] = src0[0]; |
616 | c[4] = src1[0]; |
617 | c[7] = src2[0]; |
618 | |
619 | if (i>0) { |
620 | c[0] = src0[-1]; |
621 | c[3] = src1[-1]; |
622 | c[6] = src2[-1]; |
623 | } else { |
624 | c[0] = c[1]; |
625 | c[3] = c[4]; |
626 | c[6] = c[7]; |
627 | } |
628 | |
629 | if (i<count-1) { |
630 | c[2] = src0[1]; |
631 | c[5] = src1[1]; |
632 | c[8] = src2[1]; |
633 | } else { |
634 | c[2] = c[1]; |
635 | c[5] = c[4]; |
636 | c[8] = c[7]; |
637 | } |
638 | |
639 | mask = 0; |
640 | |
641 | if (c[0] != c[4]) |
642 | mask |= 1 << 0; |
643 | if (c[1] != c[4]) |
644 | mask |= 1 << 1; |
645 | if (c[2] != c[4]) |
646 | mask |= 1 << 2; |
647 | if (c[3] != c[4]) |
648 | mask |= 1 << 3; |
649 | if (c[5] != c[4]) |
650 | mask |= 1 << 4; |
651 | if (c[6] != c[4]) |
652 | mask |= 1 << 5; |
653 | if (c[7] != c[4]) |
654 | mask |= 1 << 6; |
655 | if (c[8] != c[4]) |
656 | mask |= 1 << 7; |
657 | |
658 | #define P0 dst0[0] |
659 | #define P1 dst0[1] |
660 | #define P2 dst1[0] |
661 | #define P3 dst1[1] |
662 | #define HQ2X_MUR (c[1] != c[5]) |
663 | #define HQ2X_MDR (c[5] != c[7]) |
664 | #define HQ2X_MDL (c[7] != c[3]) |
665 | #define HQ2X_MUL (c[3] != c[1]) |
666 | #define IC(p0) c[p0] |
667 | #define I11(p0,p1) hq2x_interp_32_11(c[p0], c[p1]) |
668 | #define I211(p0,p1,p2) hq2x_interp_32_211(c[p0], c[p1], c[p2]) |
669 | #define I31(p0,p1) hq2x_interp_32_31(c[p0], c[p1]) |
670 | #define I332(p0,p1,p2) hq2x_interp_32_332(c[p0], c[p1], c[p2]) |
671 | #define I431(p0,p1,p2) hq2x_interp_32_431(c[p0], c[p1], c[p2]) |
672 | #define I521(p0,p1,p2) hq2x_interp_32_521(c[p0], c[p1], c[p2]) |
673 | #define I53(p0,p1) hq2x_interp_32_53(c[p0], c[p1]) |
674 | #define I611(p0,p1,p2) hq2x_interp_32_611(c[p0], c[p1], c[p2]) |
675 | #define I71(p0,p1) hq2x_interp_32_71(c[p0], c[p1]) |
676 | #define I772(p0,p1,p2) hq2x_interp_32_772(c[p0], c[p1], c[p2]) |
677 | #define I97(p0,p1) hq2x_interp_32_97(c[p0], c[p1]) |
678 | #define I1411(p0,p1,p2) hq2x_interp_32_1411(c[p0], c[p1], c[p2]) |
679 | #define I151(p0,p1) hq2x_interp_32_151(c[p0], c[p1]) |
680 | |
681 | switch (mask) { |
682 | #include "TextureFilters_lq2x.h" |
683 | } |
684 | |
685 | #undef P0 |
686 | #undef P1 |
687 | #undef P2 |
688 | #undef P3 |
689 | #undef HQ2X_MUR |
690 | #undef HQ2X_MDR |
691 | #undef HQ2X_MDL |
692 | #undef HQ2X_MUL |
693 | #undef IC |
694 | #undef I11 |
695 | #undef I211 |
696 | #undef I31 |
697 | #undef I332 |
698 | #undef I431 |
699 | #undef I521 |
700 | #undef I53 |
701 | #undef I611 |
702 | #undef I71 |
703 | #undef I772 |
704 | #undef I97 |
705 | #undef I1411 |
706 | #undef I151 |
707 | |
708 | src0 += 1; |
709 | src1 += 1; |
710 | src2 += 1; |
711 | dst0 += 2; |
712 | dst1 += 2; |
713 | } |
714 | } |
715 | |
716 | void hq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
717 | { |
718 | uint16 *dst0 = (uint16 *)dstPtr; |
719 | uint16 *dst1 = dst0 + (dstPitch >> 1); |
720 | |
721 | uint16 *src0 = (uint16 *)srcPtr; |
722 | uint16 *src1 = src0 + (srcPitch >> 1); |
723 | uint16 *src2 = src1 + (srcPitch >> 1); |
724 | |
725 | hq2x_16_def(dst0, dst1, src0, src0, src1, width); |
726 | if( height == 1 ) return; |
727 | |
728 | int count = height; |
729 | |
730 | count -= 2; |
731 | while(count>0) { |
732 | dst0 += dstPitch; |
733 | dst1 += dstPitch; |
734 | hq2x_16_def(dst0, dst1, src0, src1, src2, width); |
735 | src0 = src1; |
736 | src1 = src2; |
737 | src2 += srcPitch >> 1; |
738 | --count; |
739 | } |
740 | dst0 += dstPitch; |
741 | dst1 += dstPitch; |
742 | hq2x_16_def(dst0, dst1, src0, src1, src1, width); |
743 | } |
744 | |
745 | void hq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
746 | { |
747 | uint32 *dst0 = (uint32 *)dstPtr; |
748 | uint32 *dst1 = dst0 + (dstPitch >> 2); |
749 | |
750 | uint32 *src0 = (uint32 *)srcPtr; |
751 | uint32 *src1 = src0 + (srcPitch >> 2); |
752 | uint32 *src2 = src1 + (srcPitch >> 2); |
753 | hq2x_32_def(dst0, dst1, src0, src0, src1, width); |
754 | if( height == 1 ) return; |
755 | |
756 | int count = height; |
757 | |
758 | count -= 2; |
759 | while(count>0) { |
760 | dst0 += dstPitch >> 1; |
761 | dst1 += dstPitch >> 1; |
762 | hq2x_32_def(dst0, dst1, src0, src1, src2, width); |
763 | src0 = src1; |
764 | src1 = src2; |
765 | src2 += srcPitch >> 2; |
766 | --count; |
767 | } |
768 | dst0 += dstPitch >> 1; |
769 | dst1 += dstPitch >> 1; |
770 | hq2x_32_def(dst0, dst1, src0, src1, src1, width); |
771 | } |
772 | |
773 | void lq2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
774 | { |
775 | uint16 *dst0 = (uint16 *)dstPtr; |
776 | uint16 *dst1 = dst0 + (dstPitch >> 1); |
777 | |
778 | uint16 *src0 = (uint16 *)srcPtr; |
779 | uint16 *src1 = src0 + (srcPitch >> 1); |
780 | uint16 *src2 = src1 + (srcPitch >> 1); |
781 | |
782 | lq2x_16_def(dst0, dst1, src0, src0, src1, width); |
783 | if( height == 1 ) return; |
784 | |
785 | int count = height; |
786 | |
787 | count -= 2; |
788 | while(count>0) { |
789 | dst0 += dstPitch; |
790 | dst1 += dstPitch; |
791 | hq2x_16_def(dst0, dst1, src0, src1, src2, width); |
792 | src0 = src1; |
793 | src1 = src2; |
794 | src2 += srcPitch >> 1; |
795 | --count; |
796 | } |
797 | dst0 += dstPitch; |
798 | dst1 += dstPitch; |
799 | lq2x_16_def(dst0, dst1, src0, src1, src1, width); |
800 | } |
801 | |
802 | void lq2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height) |
803 | { |
804 | uint32 *dst0 = (uint32 *)dstPtr; |
805 | uint32 *dst1 = dst0 + (dstPitch >> 2); |
806 | |
807 | uint32 *src0 = (uint32 *)srcPtr; |
808 | uint32 *src1 = src0 + (srcPitch >> 2); |
809 | uint32 *src2 = src1 + (srcPitch >> 2); |
810 | lq2x_32_def(dst0, dst1, src0, src0, src1, width); |
811 | if( height == 1 ) return; |
812 | |
813 | int count = height; |
814 | |
815 | count -= 2; |
816 | while(count>0) { |
817 | dst0 += dstPitch >> 1; |
818 | dst1 += dstPitch >> 1; |
819 | hq2x_32_def(dst0, dst1, src0, src1, src2, width); |
820 | src0 = src1; |
821 | src1 = src2; |
822 | src2 += srcPitch >> 2; |
823 | --count; |
824 | } |
825 | dst0 += dstPitch >> 1; |
826 | dst1 += dstPitch >> 1; |
827 | lq2x_32_def(dst0, dst1, src0, src1, src1, width); |
828 | } |
829 | |
830 | void hq2x_init(unsigned bits_per_pixel) |
831 | { |
832 | interp_set(bits_per_pixel); |
833 | } |
834 | |
835 | /************************************************************************/ |
836 | /* hq3x filters */ |
837 | /************************************************************************/ |
838 | |
839 | /************************************************************************/ |
840 | /* scale2x filters */ |
841 | /************************************************************************/ |
842 | |
843 | /************************************************************************/ |
844 | /* scale3x filters */ |
845 | /************************************************************************/ |
846 | |