1 /*
2 * This file is part of the Advance project.
3 *
4 * Copyright (C) 2003 Andrea Mazzoleni
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 Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * In addition, as a special exception, Andrea Mazzoleni
21 * gives permission to link the code of this program with
22 * the MAME library (or with modified versions of MAME that use the
23 * same license as MAME), and distribute linked combinations including
24 * the two. You must obey the GNU General Public License in all
25 * respects for all of the code used other than MAME. If you modify
26 * this file, you may extend this exception to your version of the
27 * file, but you are not obligated to do so. If you do not wish to
28 * do so, delete this exception statement from your version.
29 */
30
31 #include "interp.h"
32
33 unsigned interp_mask[2];
34 unsigned interp_bits_per_pixel;
35
36 /***************************************************************************/
37 /* HQ2xS C implementation */
38
39 /*
40 * This effect is derived from the hq2x effect made by Maxim Stepin
41 */
42
hq2xS_16_def(u16 * dst0,u16 * dst1,const u16 * src0,const u16 * src1,const u16 * src2,unsigned count)43 static void hq2xS_16_def(u16* dst0, u16* dst1, const u16* src0, const u16* src1, const u16* src2, unsigned count)
44 {
45 unsigned i;
46
47 for(i=0;i<count;++i) {
48 unsigned char mask;
49
50 u16 c[9];
51
52 c[1] = src0[0];
53 c[4] = src1[0];
54 c[7] = src2[0];
55
56 c[0] = src0[-1];
57 c[3] = src1[-1];
58 c[6] = src2[-1];
59
60 c[2] = src0[1];
61 c[5] = src1[1];
62 c[8] = src2[1];
63
64 mask = 0;
65
66 // hq2xS dynamic edge detection:
67 // simply comparing the center color against its surroundings will give bad results in many cases,
68 // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
69 int brightArray[9];
70 int maxBright = 0, minBright = 999999;
71 for(int j = 0 ; j < 9 ; j++)
72 {
73 int r,g,b;
74 if (interp_bits_per_pixel == 16) {
75 b = (int)((c[j] & 0x1F)) << 3;
76 g = (int)((c[j] & 0x7E0)) >> 3;
77 r = (int)((c[j] & 0xF800)) >> 8;
78 } else {
79 b = (int)((c[j] & 0x1F)) << 3;
80 g = (int)((c[j] & 0x3E0)) >> 2;
81 r = (int)((c[j] & 0x7C00)) >> 7;
82 }
83 const int bright = r+r+r + g+g+g + b+b;
84 if(bright > maxBright) maxBright = bright;
85 if(bright < minBright) minBright = bright;
86
87 brightArray[j] = bright;
88 }
89 int diffBright = ((maxBright - minBright) * 7) >> 4;
90 if(diffBright > 7)
91 {
92 #define ABS(x) ((x) < 0 ? -(x) : (x))
93
94 const int centerBright = brightArray[4];
95 if(ABS(brightArray[0] - centerBright) > diffBright)
96 mask |= 1 << 0;
97 if(ABS(brightArray[1] - centerBright) > diffBright)
98 mask |= 1 << 1;
99 if(ABS(brightArray[2] - centerBright) > diffBright)
100 mask |= 1 << 2;
101 if(ABS(brightArray[3] - centerBright) > diffBright)
102 mask |= 1 << 3;
103 if(ABS(brightArray[5] - centerBright) > diffBright)
104 mask |= 1 << 4;
105 if(ABS(brightArray[6] - centerBright) > diffBright)
106 mask |= 1 << 5;
107 if(ABS(brightArray[7] - centerBright) > diffBright)
108 mask |= 1 << 6;
109 if(ABS(brightArray[8] - centerBright) > diffBright)
110 mask |= 1 << 7;
111 }
112
113 #define P0 dst0[0]
114 #define P1 dst0[1]
115 #define P2 dst1[0]
116 #define P3 dst1[1]
117 #define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right
118 #define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right
119 #define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left
120 #define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left
121 #define IC(p0) c[p0]
122 #define I11(p0,p1) interp_16_11(c[p0], c[p1])
123 #define I211(p0,p1,p2) interp_16_211(c[p0], c[p1], c[p2])
124 #define I31(p0,p1) interp_16_31(c[p0], c[p1])
125 #define I332(p0,p1,p2) interp_16_332(c[p0], c[p1], c[p2])
126 #define I431(p0,p1,p2) interp_16_431(c[p0], c[p1], c[p2])
127 #define I521(p0,p1,p2) interp_16_521(c[p0], c[p1], c[p2])
128 #define I53(p0,p1) interp_16_53(c[p0], c[p1])
129 #define I611(p0,p1,p2) interp_16_611(c[p0], c[p1], c[p2])
130 #define I71(p0,p1) interp_16_71(c[p0], c[p1])
131 #define I772(p0,p1,p2) interp_16_772(c[p0], c[p1], c[p2])
132 #define I97(p0,p1) interp_16_97(c[p0], c[p1])
133 #define I1411(p0,p1,p2) interp_16_1411(c[p0], c[p1], c[p2])
134 #define I151(p0,p1) interp_16_151(c[p0], c[p1])
135
136 switch (mask) {
137 #include "hq2xs.h"
138 }
139
140 #undef P0
141 #undef P1
142 #undef P2
143 #undef P3
144 #undef MUR
145 #undef MDR
146 #undef MDL
147 #undef MUL
148 #undef IC
149 #undef I11
150 #undef I211
151 #undef I31
152 #undef I332
153 #undef I431
154 #undef I521
155 #undef I53
156 #undef I611
157 #undef I71
158 #undef I772
159 #undef I97
160 #undef I1411
161 #undef I151
162
163 src0 += 1;
164 src1 += 1;
165 src2 += 1;
166 dst0 += 2;
167 dst1 += 2;
168 }
169 }
170
hq2xS_32_def(u32 * dst0,u32 * dst1,const u32 * src0,const u32 * src1,const u32 * src2,unsigned count)171 static void hq2xS_32_def(u32* dst0, u32* dst1, const u32* src0, const u32* src1, const u32* src2, unsigned count)
172 {
173 unsigned i;
174
175 for(i=0;i<count;++i) {
176 unsigned char mask;
177
178 u32 c[9];
179
180 c[1] = src0[0];
181 c[4] = src1[0];
182 c[7] = src2[0];
183
184 c[0] = src0[-1];
185 c[3] = src1[-1];
186 c[6] = src2[-1];
187
188 c[2] = src0[1];
189 c[5] = src1[1];
190 c[8] = src2[1];
191
192 mask = 0;
193
194 // hq2xS dynamic edge detection:
195 // simply comparing the center color against its surroundings will give bad results in many cases,
196 // so, instead, compare the center color relative to the max difference in brightness of this 3x3 block
197 int brightArray[9];
198 int maxBright = 0, minBright = 999999;
199 for(int j = 0 ; j < 9 ; j++)
200 {
201 const int b = (int)((c[j] & 0xF8));
202 const int g = (int)((c[j] & 0xF800)) >> 8;
203 const int r = (int)((c[j] & 0xF80000)) >> 16;
204 const int bright = r+r+r + g+g+g + b+b;
205 if(bright > maxBright) maxBright = bright;
206 if(bright < minBright) minBright = bright;
207
208 brightArray[j] = bright;
209 }
210 int diffBright = ((maxBright - minBright) * 7) >> 4;
211 if(diffBright > 7)
212 {
213 #define ABS(x) ((x) < 0 ? -(x) : (x))
214
215 const int centerBright = brightArray[4];
216 if(ABS(brightArray[0] - centerBright) > diffBright)
217 mask |= 1 << 0;
218 if(ABS(brightArray[1] - centerBright) > diffBright)
219 mask |= 1 << 1;
220 if(ABS(brightArray[2] - centerBright) > diffBright)
221 mask |= 1 << 2;
222 if(ABS(brightArray[3] - centerBright) > diffBright)
223 mask |= 1 << 3;
224 if(ABS(brightArray[5] - centerBright) > diffBright)
225 mask |= 1 << 4;
226 if(ABS(brightArray[6] - centerBright) > diffBright)
227 mask |= 1 << 5;
228 if(ABS(brightArray[7] - centerBright) > diffBright)
229 mask |= 1 << 6;
230 if(ABS(brightArray[8] - centerBright) > diffBright)
231 mask |= 1 << 7;
232 }
233
234 #define P0 dst0[0]
235 #define P1 dst0[1]
236 #define P2 dst1[0]
237 #define P3 dst1[1]
238 #define MUR false//(ABS(brightArray[1] - brightArray[5]) > diffBright) // top-right
239 #define MDR false//(ABS(brightArray[5] - brightArray[7]) > diffBright) // bottom-right
240 #define MDL false//(ABS(brightArray[7] - brightArray[3]) > diffBright) // bottom-left
241 #define MUL false//(ABS(brightArray[3] - brightArray[1]) > diffBright) // top-left
242 #define IC(p0) c[p0]
243 #define I11(p0,p1) interp_32_11(c[p0], c[p1])
244 #define I211(p0,p1,p2) interp_32_211(c[p0], c[p1], c[p2])
245 #define I31(p0,p1) interp_32_31(c[p0], c[p1])
246 #define I332(p0,p1,p2) interp_32_332(c[p0], c[p1], c[p2])
247 #define I431(p0,p1,p2) interp_32_431(c[p0], c[p1], c[p2])
248 #define I521(p0,p1,p2) interp_32_521(c[p0], c[p1], c[p2])
249 #define I53(p0,p1) interp_32_53(c[p0], c[p1])
250 #define I611(p0,p1,p2) interp_32_611(c[p0], c[p1], c[p2])
251 #define I71(p0,p1) interp_32_71(c[p0], c[p1])
252 #define I772(p0,p1,p2) interp_32_772(c[p0], c[p1], c[p2])
253 #define I97(p0,p1) interp_32_97(c[p0], c[p1])
254 #define I1411(p0,p1,p2) interp_32_1411(c[p0], c[p1], c[p2])
255 #define I151(p0,p1) interp_32_151(c[p0], c[p1])
256
257 switch (mask) {
258 #include "hq2xs.h"
259 }
260
261 #undef P0
262 #undef P1
263 #undef P2
264 #undef P3
265 #undef MUR
266 #undef MDR
267 #undef MDL
268 #undef MUL
269 #undef IC
270 #undef I11
271 #undef I211
272 #undef I31
273 #undef I332
274 #undef I431
275 #undef I521
276 #undef I53
277 #undef I611
278 #undef I71
279 #undef I772
280 #undef I97
281 #undef I1411
282 #undef I151
283
284 src0 += 1;
285 src1 += 1;
286 src2 += 1;
287 dst0 += 2;
288 dst1 += 2;
289 }
290 }
291
hq2xS(u8 * srcPtr,u32 srcPitch,u8 *,u8 * dstPtr,u32 dstPitch,int width,int height)292 void hq2xS(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
293 u8 *dstPtr, u32 dstPitch, int width, int height)
294 {
295 u16 *dst0 = (u16 *)dstPtr;
296 u16 *dst1 = dst0 + (dstPitch >> 1);
297
298 u16 *src0 = (u16 *)srcPtr;
299 u16 *src1 = src0 + (srcPitch >> 1);
300 u16 *src2 = src1 + (srcPitch >> 1);
301
302 hq2xS_16_def(dst0, dst1, src0, src0, src1, width);
303
304 int count = height;
305
306 count -= 2;
307 while(count) {
308 dst0 += dstPitch;
309 dst1 += dstPitch;
310 hq2xS_16_def(dst0, dst1, src0, src1, src2, width);
311 src0 = src1;
312 src1 = src2;
313 src2 += srcPitch >> 1;
314 --count;
315 }
316 dst0 += dstPitch;
317 dst1 += dstPitch;
318 hq2xS_16_def(dst0, dst1, src0, src1, src1, width);
319 }
320
hq2xS32(u8 * srcPtr,u32 srcPitch,u8 *,u8 * dstPtr,u32 dstPitch,int width,int height)321 void hq2xS32(u8 *srcPtr, u32 srcPitch, u8 * /* deltaPtr */,
322 u8 *dstPtr, u32 dstPitch, int width, int height)
323 {
324 u32 *dst0 = (u32 *)dstPtr;
325 u32 *dst1 = dst0 + (dstPitch >> 2);
326
327 u32 *src0 = (u32 *)srcPtr;
328 u32 *src1 = src0 + (srcPitch >> 2);
329 u32 *src2 = src1 + (srcPitch >> 2);
330 hq2xS_32_def(dst0, dst1, src0, src0, src1, width);
331
332 int count = height;
333
334 count -= 2;
335 while(count) {
336 dst0 += dstPitch >> 1;
337 dst1 += dstPitch >> 1;
338 hq2xS_32_def(dst0, dst1, src0, src1, src2, width);
339 src0 = src1;
340 src1 = src2;
341 src2 += srcPitch >> 2;
342 --count;
343 }
344 dst0 += dstPitch >> 1;
345 dst1 += dstPitch >> 1;
346 hq2xS_32_def(dst0, dst1, src0, src1, src1, width);
347 }
348
hq2xS_init(unsigned bits_per_pixel)349 void hq2xS_init(unsigned bits_per_pixel)
350 {
351 interp_set(bits_per_pixel);
352 }
353