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 #ifndef __INTERP_H
32 #define __INTERP_H
33
34 #include "gfxtypes.h"
35
36 /***************************************************************************/
37 /* Basic types */
38
39 /***************************************************************************/
40 /* interpolation */
41
42 static unsigned interp_mask[2];
43 static unsigned interp_bits_per_pixel;
44
45 #define INTERP_16_MASK_1(v) (v & interp_mask[0])
46 #define INTERP_16_MASK_2(v) (v & interp_mask[1])
47
interp_16_521(u16 p1,u16 p2,u16 p3)48 static inline u16 interp_16_521(u16 p1, u16 p2, u16 p3)
49 {
50 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*2 + INTERP_16_MASK_1(p3)*1) / 8)
51 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*2 + INTERP_16_MASK_2(p3)*1) / 8);
52 }
53
interp_16_332(u16 p1,u16 p2,u16 p3)54 static inline u16 interp_16_332(u16 p1, u16 p2, u16 p3)
55 {
56 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)*2) / 8)
57 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)*2) / 8);
58 }
59
interp_16_611(u16 p1,u16 p2,u16 p3)60 static inline u16 interp_16_611(u16 p1, u16 p2, u16 p3)
61 {
62 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*6 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 8)
63 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*6 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 8);
64 }
65
interp_16_71(u16 p1,u16 p2)66 static inline u16 interp_16_71(u16 p1, u16 p2)
67 {
68 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*7 + INTERP_16_MASK_1(p2)) / 8)
69 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*7 + INTERP_16_MASK_2(p2)) / 8);
70 }
71
interp_16_211(u16 p1,u16 p2,u16 p3)72 static inline u16 interp_16_211(u16 p1, u16 p2, u16 p3)
73 {
74 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*2 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 4)
75 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*2 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 4);
76 }
77
interp_16_772(u16 p1,u16 p2,u16 p3)78 static inline u16 interp_16_772(u16 p1, u16 p2, u16 p3)
79 {
80 return INTERP_16_MASK_1(((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2))*7 + INTERP_16_MASK_1(p3)*2) / 16)
81 | INTERP_16_MASK_2(((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2))*7 + INTERP_16_MASK_2(p3)*2) / 16);
82 }
83
interp_16_11(u16 p1,u16 p2)84 static inline u16 interp_16_11(u16 p1, u16 p2)
85 {
86 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1) + INTERP_16_MASK_1(p2)) / 2)
87 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1) + INTERP_16_MASK_2(p2)) / 2);
88 }
89
interp_16_31(u16 p1,u16 p2)90 static inline u16 interp_16_31(u16 p1, u16 p2)
91 {
92 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*3 + INTERP_16_MASK_1(p2)) / 4)
93 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*3 + INTERP_16_MASK_2(p2)) / 4);
94 }
95
interp_16_1411(u16 p1,u16 p2,u16 p3)96 static inline u16 interp_16_1411(u16 p1, u16 p2, u16 p3)
97 {
98 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*14 + INTERP_16_MASK_1(p2) + INTERP_16_MASK_1(p3)) / 16)
99 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*14 + INTERP_16_MASK_2(p2) + INTERP_16_MASK_2(p3)) / 16);
100 }
101
interp_16_431(u16 p1,u16 p2,u16 p3)102 static inline u16 interp_16_431(u16 p1, u16 p2, u16 p3)
103 {
104 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*4 + INTERP_16_MASK_1(p2)*3 + INTERP_16_MASK_1(p3)) / 8)
105 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*4 + INTERP_16_MASK_2(p2)*3 + INTERP_16_MASK_2(p3)) / 8);
106 }
107
interp_16_53(u16 p1,u16 p2)108 static inline u16 interp_16_53(u16 p1, u16 p2)
109 {
110 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*5 + INTERP_16_MASK_1(p2)*3) / 8)
111 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*5 + INTERP_16_MASK_2(p2)*3) / 8);
112 }
113
interp_16_151(u16 p1,u16 p2)114 static inline u16 interp_16_151(u16 p1, u16 p2)
115 {
116 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*15 + INTERP_16_MASK_1(p2)) / 16)
117 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*15 + INTERP_16_MASK_2(p2)) / 16);
118 }
119
interp_16_97(u16 p1,u16 p2)120 static inline u16 interp_16_97(u16 p1, u16 p2)
121 {
122 return INTERP_16_MASK_1((INTERP_16_MASK_1(p1)*9 + INTERP_16_MASK_1(p2)*7) / 16)
123 | INTERP_16_MASK_2((INTERP_16_MASK_2(p1)*9 + INTERP_16_MASK_2(p2)*7) / 16);
124 }
125
126 #define INTERP_32_MASK_1(v) (v & 0xFF00FF)
127 #define INTERP_32_MASK_2(v) (v & 0x00FF00)
128
interp_32_521(u32 p1,u32 p2,u32 p3)129 static inline u32 interp_32_521(u32 p1, u32 p2, u32 p3)
130 {
131 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*2 + INTERP_32_MASK_1(p3)*1) / 8)
132 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*2 + INTERP_32_MASK_2(p3)*1) / 8);
133 }
134
interp_32_332(u32 p1,u32 p2,u32 p3)135 static inline u32 interp_32_332(u32 p1, u32 p2, u32 p3)
136 {
137 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)*2) / 8)
138 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)*2) / 8);
139 }
140
interp_32_211(u32 p1,u32 p2,u32 p3)141 static inline u32 interp_32_211(u32 p1, u32 p2, u32 p3)
142 {
143 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*2 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 4)
144 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*2 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 4);
145 }
146
interp_32_611(u32 p1,u32 p2,u32 p3)147 static inline u32 interp_32_611(u32 p1, u32 p2, u32 p3)
148 {
149 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*6 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 8)
150 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*6 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 8);
151 }
152
interp_32_71(u32 p1,u32 p2)153 static inline u32 interp_32_71(u32 p1, u32 p2)
154 {
155 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*7 + INTERP_32_MASK_1(p2)) / 8)
156 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*7 + INTERP_32_MASK_2(p2)) / 8);
157 }
158
interp_32_772(u32 p1,u32 p2,u32 p3)159 static inline u32 interp_32_772(u32 p1, u32 p2, u32 p3)
160 {
161 return INTERP_32_MASK_1(((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2))*7 + INTERP_32_MASK_1(p3)*2) / 16)
162 | INTERP_32_MASK_2(((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2))*7 + INTERP_32_MASK_2(p3)*2) / 16);
163 }
164
interp_32_11(u32 p1,u32 p2)165 static inline u32 interp_32_11(u32 p1, u32 p2)
166 {
167 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1) + INTERP_32_MASK_1(p2)) / 2)
168 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1) + INTERP_32_MASK_2(p2)) / 2);
169 }
170
interp_32_31(u32 p1,u32 p2)171 static inline u32 interp_32_31(u32 p1, u32 p2)
172 {
173 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*3 + INTERP_32_MASK_1(p2)) / 4)
174 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*3 + INTERP_32_MASK_2(p2)) / 4);
175 }
176
interp_32_1411(u32 p1,u32 p2,u32 p3)177 static inline u32 interp_32_1411(u32 p1, u32 p2, u32 p3)
178 {
179 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*14 + INTERP_32_MASK_1(p2) + INTERP_32_MASK_1(p3)) / 16)
180 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*14 + INTERP_32_MASK_2(p2) + INTERP_32_MASK_2(p3)) / 16);
181 }
182
interp_32_431(u32 p1,u32 p2,u32 p3)183 static inline u32 interp_32_431(u32 p1, u32 p2, u32 p3)
184 {
185 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*4 + INTERP_32_MASK_1(p2)*3 + INTERP_32_MASK_1(p3)) / 8)
186 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*4 + INTERP_32_MASK_2(p2)*3 + INTERP_32_MASK_2(p3)) / 8);
187 }
188
interp_32_53(u32 p1,u32 p2)189 static inline u32 interp_32_53(u32 p1, u32 p2)
190 {
191 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*5 + INTERP_32_MASK_1(p2)*3) / 8)
192 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*5 + INTERP_32_MASK_2(p2)*3) / 8);
193 }
194
interp_32_151(u32 p1,u32 p2)195 static inline u32 interp_32_151(u32 p1, u32 p2)
196 {
197 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*15 + INTERP_32_MASK_1(p2)) / 16)
198 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*15 + INTERP_32_MASK_2(p2)) / 16);
199 }
200
interp_32_97(u32 p1,u32 p2)201 static inline u32 interp_32_97(u32 p1, u32 p2)
202 {
203 return INTERP_32_MASK_1((INTERP_32_MASK_1(p1)*9 + INTERP_32_MASK_1(p2)*7) / 16)
204 | INTERP_32_MASK_2((INTERP_32_MASK_2(p1)*9 + INTERP_32_MASK_2(p2)*7) / 16);
205 }
206
207 /***************************************************************************/
208 /* diff */
209
210 #define INTERP_Y_LIMIT (0x30*4)
211 #define INTERP_U_LIMIT (0x07*4)
212 #define INTERP_V_LIMIT (0x06*8)
213
interp_16_diff(u16 p1,u16 p2)214 static int interp_16_diff(u16 p1, u16 p2)
215 {
216 int r, g, b;
217 int y, u, v;
218
219 if (p1 == p2)
220 return 0;
221
222 if (interp_bits_per_pixel == 16) {
223 b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
224 g = (int)((p1 & 0x7E0) - (p2 & 0x7E0)) >> 3;
225 r = (int)((p1 & 0xF800) - (p2 & 0xF800)) >> 8;
226 } else {
227 b = (int)((p1 & 0x1F) - (p2 & 0x1F)) << 3;
228 g = (int)((p1 & 0x3E0) - (p2 & 0x3E0)) >> 2;
229 r = (int)((p1 & 0x7C00) - (p2 & 0x7C00)) >> 7;
230 }
231
232 y = r + g + b;
233 u = r - b;
234 v = -r + 2*g - b;
235
236 if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
237 return 1;
238
239 if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
240 return 1;
241
242 if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
243 return 1;
244
245 return 0;
246 }
247
interp_32_diff(u32 p1,u32 p2)248 static int interp_32_diff(u32 p1, u32 p2)
249 {
250 int r, g, b;
251 int y, u, v;
252
253 if ((p1 & 0xF8F8F8) == (p2 & 0xF8F8F8))
254 return 0;
255
256 b = (int)((p1 & 0xFF) - (p2 & 0xFF));
257 g = (int)((p1 & 0xFF00) - (p2 & 0xFF00)) >> 8;
258 r = (int)((p1 & 0xFF0000) - (p2 & 0xFF0000)) >> 16;
259
260 y = r + g + b;
261 u = r - b;
262 v = -r + 2*g - b;
263
264 if (y < -INTERP_Y_LIMIT || y > INTERP_Y_LIMIT)
265 return 1;
266
267 if (u < -INTERP_U_LIMIT || u > INTERP_U_LIMIT)
268 return 1;
269
270 if (v < -INTERP_V_LIMIT || v > INTERP_V_LIMIT)
271 return 1;
272
273 return 0;
274 }
275
interp_set(unsigned bits_per_pixel)276 static void interp_set(unsigned bits_per_pixel)
277 {
278 interp_bits_per_pixel = bits_per_pixel;
279
280 switch (bits_per_pixel) {
281 case 15 :
282 interp_mask[0] = 0x7C1F;
283 interp_mask[1] = 0x03E0;
284 break;
285 case 16 :
286 interp_mask[0] = 0xF81F;
287 interp_mask[1] = 0x07E0;
288 break;
289 case 32 :
290 interp_mask[0] = 0xFF00FF;
291 interp_mask[1] = 0x00FF00;
292 break;
293 }
294 }
295
296 #endif
297