Glide Plugin GLES2 port from mupen64plus-ae, but with special FrameSkip code
[mupen64plus-pandora.git] / source / gles2glide64 / src / GlideHQ / TextureFilters.cpp
CommitLineData
98e75f2d 1/*
2Copyright (C) 2003 Rice1964
3
4This program is free software; you can redistribute it and/or
5modify it under the terms of the GNU General Public License
6as published by the Free Software Foundation; either version 2
7of the License, or (at your option) any later version.
8
9This program is distributed in the hope that it will be useful,
10but WITHOUT ANY WARRANTY; without even the implied warranty of
11MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12GNU General Public License for more details.
13
14You should have received a copy of the GNU General Public License
15along with this program; if not, write to the Free Software
16Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18*/
19
20/* Copyright (C) 2007 Hiroshi Morii <koolsmoky(at)users.sourceforge.net>
21 * Modified for the Texture Filtering library
22 */
23
24#include <string.h>
25#include "TextureFilters.h"
26
27/************************************************************************/
28/* 2X filters */
29/************************************************************************/
30
31#define DWORD_MAKE(r, g, b, a) ((uint32) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)))
32#define WORD_MAKE(r, g, b, a) ((uint16) (((a) << 12) | ((r) << 8) | ((g) << 4) | (b)))
33
34// Basic 2x R8G8B8A8 filter with interpolation
35
36void Texture2x_32(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
37{
38 uint32 *pDst1, *pDst2;
39 uint32 *pSrc, *pSrc2;
40 uint32 nWidth = width;
41 uint32 nHeight = height;
42
43 uint32 b1;
44 uint32 g1;
45 uint32 r1;
46 uint32 a1;
47 uint32 b2;
48 uint32 g2;
49 uint32 r2;
50 uint32 a2;
51 uint32 b3;
52 uint32 g3;
53 uint32 r3;
54 uint32 a3;
55 uint32 b4;
56 uint32 g4;
57 uint32 r4;
58 uint32 a4;
59
60 uint32 xSrc;
61 uint32 ySrc;
62
63 for (ySrc = 0; ySrc < nHeight; ySrc++)
64 {
65 pSrc = (uint32*)(((uint8*)srcPtr)+ySrc*srcPitch);
66 pSrc2 = (uint32*)(((uint8*)srcPtr)+(ySrc+1)*srcPitch);
67 pDst1 = (uint32*)(((uint8*)dstPtr)+(ySrc*2)*dstPitch);
68 pDst2 = (uint32*)(((uint8*)dstPtr)+(ySrc*2+1)*dstPitch);
69
70 for (xSrc = 0; xSrc < nWidth; xSrc++)
71 {
72 b1 = (pSrc[xSrc]>>0)&0xFF;
73 g1 = (pSrc[xSrc]>>8)&0xFF;
74 r1 = (pSrc[xSrc]>>16)&0xFF;
75 a1 = (pSrc[xSrc]>>24)&0xFF;
76
77 // Pixel 1
78 pDst1[xSrc*2] = pSrc[xSrc];
79
80 // Pixel 2
81 if( xSrc<nWidth-1 )
82 {
83 b2 = (pSrc[xSrc+1]>>0)&0xFF;
84 g2 = (pSrc[xSrc+1]>>8)&0xFF;
85 r2 = (pSrc[xSrc+1]>>16)&0xFF;
86 a2 = (pSrc[xSrc+1]>>24)&0xFF;
87 pDst1[xSrc*2+1] = DWORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
88 }
89 else
90 pDst1[xSrc*2+1] = pSrc[xSrc];
91
92 // Pixel 3
93 if( ySrc<nHeight-1 )
94 {
95 b3 = (pSrc2[xSrc]>>0)&0xFF;
96 g3 = (pSrc2[xSrc]>>8)&0xFF;
97 r3 = (pSrc2[xSrc]>>16)&0xFF;
98 a3 = (pSrc2[xSrc]>>24)&0xFF;
99 pDst2[xSrc*2] = DWORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
100 if( xSrc<nWidth-1 )
101 {
102 b4 = (pSrc2[xSrc+1]>>0)&0xFF;
103 g4 = (pSrc2[xSrc+1]>>8)&0xFF;
104 r4 = (pSrc2[xSrc+1]>>16)&0xFF;
105 a4 = (pSrc2[xSrc+1]>>24)&0xFF;
106 // Pixel 4
107 pDst2[xSrc*2+1] = DWORD_MAKE((r1+r2+r3+r4)/4, (g1+g2+g3+g4)/4, (b1+b2+b3+b4)/4, (a1+a2+a3+a4)/4);
108 }
109 else
110 {
111 // Pixel 4
112 pDst2[xSrc*2+1] = DWORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
113 }
114 }
115 else
116 {
117 // Pixel 3
118 pDst2[xSrc*2] = pSrc[xSrc];
119 // Pixel 4
120 if( xSrc<nWidth-1 )
121 {
122 pDst2[xSrc*2+1] = DWORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
123 }
124 else
125 {
126 pDst2[xSrc*2+1] = pSrc[xSrc];
127 }
128 }
129 }
130 }
131}
132
133#if !_16BPP_HACK
134// Basic 2x R4G4B4A4 filter with interpolation
135void Texture2x_16(uint8 *srcPtr, uint32 srcPitch, uint8 *dstPtr, uint32 dstPitch, int width, int height)
136{
137 uint16 *pDst1, *pDst2;
138 uint16 *pSrc, *pSrc2;
139 uint32 nWidth = width;
140 uint32 nHeight = height;
141
142 uint16 b1;
143 uint16 g1;
144 uint16 r1;
145 uint16 a1;
146 uint16 b2;
147 uint16 g2;
148 uint16 r2;
149 uint16 a2;
150 uint16 b3;
151 uint16 g3;
152 uint16 r3;
153 uint16 a3;
154 uint16 b4;
155 uint16 g4;
156 uint16 r4;
157 uint16 a4;
158
159 uint16 xSrc;
160 uint16 ySrc;
161
162 for (ySrc = 0; ySrc < nHeight; ySrc++)
163 {
164 pSrc = (uint16*)(((uint8*)srcPtr)+ySrc*srcPitch);
165 pSrc2 = (uint16*)(((uint8*)srcPtr)+(ySrc+1)*srcPitch);
166 pDst1 = (uint16*)(((uint8*)dstPtr)+(ySrc*2)*dstPitch);
167 pDst2 = (uint16*)(((uint8*)dstPtr)+(ySrc*2+1)*dstPitch);
168
169 for (xSrc = 0; xSrc < nWidth; xSrc++)
170 {
171 b1 = (pSrc[xSrc]>> 0)&0xF;
172 g1 = (pSrc[xSrc]>> 4)&0xF;
173 r1 = (pSrc[xSrc]>> 8)&0xF;
174 a1 = (pSrc[xSrc]>>12)&0xF;
175
176 if( xSrc<nWidth-1 )
177 {
178 b2 = (pSrc[xSrc+1]>> 0)&0xF;
179 g2 = (pSrc[xSrc+1]>> 4)&0xF;
180 r2 = (pSrc[xSrc+1]>> 8)&0xF;
181 a2 = (pSrc[xSrc+1]>>12)&0xF;
182 }
183
184 if( ySrc<nHeight-1 )
185 {
186 b3 = (pSrc2[xSrc]>> 0)&0xF;
187 g3 = (pSrc2[xSrc]>> 4)&0xF;
188 r3 = (pSrc2[xSrc]>> 8)&0xF;
189 a3 = (pSrc2[xSrc]>>12)&0xF;
190 if( xSrc<nWidth-1 )
191 {
192 b4 = (pSrc2[xSrc+1]>> 0)&0xF;
193 g4 = (pSrc2[xSrc+1]>> 4)&0xF;
194 r4 = (pSrc2[xSrc+1]>> 8)&0xF;
195 a4 = (pSrc2[xSrc+1]>>12)&0xF;
196 }
197 }
198
199 // Pixel 1
200 pDst1[xSrc*2] = pSrc[xSrc];
201
202 // Pixel 2
203 if( xSrc<nWidth-1 )
204 {
205 pDst1[xSrc*2+1] = WORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
206 }
207 else
208 pDst1[xSrc*2+1] = pSrc[xSrc];
209
210
211 // Pixel 3
212 if( ySrc<nHeight-1 )
213 {
214 pDst2[xSrc*2] = WORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
215 }
216 else
217 pDst2[xSrc*2] = pSrc[xSrc];
218
219 // Pixel 4
220 if( xSrc<nWidth-1 )
221 {
222 if( ySrc<nHeight-1 )
223 {
224 pDst2[xSrc*2+1] = WORD_MAKE((r1+r2+r3+r4)/4, (g1+g2+g3+g4)/4, (b1+b2+b3+b4)/4, (a1+a2+a3+a4)/4);
225 }
226 else
227 {
228 pDst2[xSrc*2+1] = WORD_MAKE((r1+r2)/2, (g1+g2)/2, (b1+b2)/2, (a1+a2)/2);
229 }
230 }
231 else
232 {
233 if( ySrc<nHeight-1 )
234 {
235 pDst2[xSrc*2+1] = WORD_MAKE((r1+r3)/2, (g1+g3)/2, (b1+b3)/2, (a1+a3)/2);
236 }
237 else
238 pDst2[xSrc*2+1] = pSrc[xSrc];
239 }
240 }
241 }
242}
243#endif /* !_16BPP_HACK */
244
245/*
246 * Sharp filters
247 * Hiroshi Morii <koolsmoky@users.sourceforge.net>
248 */
249void SharpFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter)
250{
251 // NOTE: for now we get away with copying the boundaries
252 // filter the boundaries if we face problems
253
254 uint32 mul1, mul2, mul3, shift4;
255
256 uint32 x,y,z;
257 uint32 *_src1, *_src2, *_src3, *_dest;
258 uint32 val[4];
259 uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9;
260
261 switch( filter )
262 {
263 case SHARP_FILTER_2:
264 mul1=1;
265 mul2=8;
266 mul3=12;
267 shift4=2;
268 break;
269 case SHARP_FILTER_1:
270 default:
271 mul1=1;
272 mul2=8;
273 mul3=16;
274 shift4=3;
275 break;
276 }
277
278 // setup rows
279 _src1 = src;
280 _src2 = _src1 + srcwidth;
281 _src3 = _src2 + srcwidth;
282 _dest = dest;
283
284 // copy the first row
285 memcpy(_dest, _src1, (srcwidth << 2));
286 _dest += srcwidth;
287 // filter 2nd row to 1 row before the last
288 for (y = 1; y < srcheight-1; y++) {
289 // copy the first pixel
290 _dest[0] = *_src2;
291 // filter 2nd pixel to 1 pixel before last
292 for (x = 1; x < srcwidth-1; x++) {
293 for (z=0; z<4; z++) {
294 t1 = *((uint8*)(_src1+x-1)+z);
295 t2 = *((uint8*)(_src1+x )+z);
296 t3 = *((uint8*)(_src1+x+1)+z);
297 t4 = *((uint8*)(_src2+x-1)+z);
298 t5 = *((uint8*)(_src2+x )+z);
299 t6 = *((uint8*)(_src2+x+1)+z);
300 t7 = *((uint8*)(_src3+x-1)+z);
301 t8 = *((uint8*)(_src3+x )+z);
302 t9 = *((uint8*)(_src3+x+1)+z);
303
304 if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) {
305 val[z]= ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4;
306 if (val[z] > 0xFF) val[z] = 0xFF;
307 } else {
308 val[z] = t5;
309 }
310 }
311 _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
312 }
313 // copy the ending pixel
314 _dest[srcwidth-1] = *(_src3 - 1);
315 // next row
316 _src1 += srcwidth;
317 _src2 += srcwidth;
318 _src3 += srcwidth;
319 _dest += srcwidth;
320 }
321 // copy the last row
322 memcpy(_dest, _src2, (srcwidth << 2));
323}
324
325#if !_16BPP_HACK
326void SharpFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter)
327{
328 // NOTE: for now we get away with copying the boundaries
329 // filter the boundaries if we face problems
330
331 uint16 mul1, mul2, mul3, shift4;
332
333 uint32 x,y,z;
334 uint16 *_src1, *_src2, *_src3, *_dest;
335 uint16 val[4];
336 uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9;
337
338 switch( filter ) {
339 case SHARP_FILTER_2:
340 mul1=1;
341 mul2=8;
342 mul3=12;
343 shift4=2;
344 break;
345 case SHARP_FILTER_1:
346 default:
347 mul1=1;
348 mul2=8;
349 mul3=16;
350 shift4=3;
351 break;
352 }
353
354 // setup rows
355 _src1 = src;
356 _src2 = _src1 + srcwidth;
357 _src3 = _src2 + srcwidth;
358 _dest = dest;
359
360 // copy the first row
361 memcpy(_dest, _src1, (srcwidth << 1));
362 _dest += srcwidth;
363 // filter 2nd row to 1 row before the last
364 for( y = 1; y < srcheight - 1; y++) {
365 // copy the first pixel
366 _dest[0] = *_src2;
367 // filter 2nd pixel to 1 pixel before last
368 for( x = 1; x < srcwidth - 1; x++) {
369 for( z = 0; z < 4; z++ ) {
370 /* Hiroshi Morii <koolsmoky@users.sourceforge.net>
371 * Read the entire 16bit pixel and then extract the A,R,G,B components.
372 */
373 uint32 shift = z << 2;
374 t1 = ((*((uint16*)(_src1+x-1))) >> shift) & 0xF;
375 t2 = ((*((uint16*)(_src1+x ))) >> shift) & 0xF;
376 t3 = ((*((uint16*)(_src1+x+1))) >> shift) & 0xF;
377 t4 = ((*((uint16*)(_src2+x-1))) >> shift) & 0xF;
378 t5 = ((*((uint16*)(_src2+x ))) >> shift) & 0xF;
379 t6 = ((*((uint16*)(_src2+x+1))) >> shift) & 0xF;
380 t7 = ((*((uint16*)(_src3+x-1))) >> shift) & 0xF;
381 t8 = ((*((uint16*)(_src3+x ))) >> shift) & 0xF;
382 t9 = ((*((uint16*)(_src3+x+1))) >> shift) & 0xF;
383
384 if( (t5*mul2) > (t1+t3+t7+t9+t2+t4+t6+t8)*mul1 ) {
385 val[z] = ((t5*mul3) - (t1+t3+t7+t9+t2+t4+t6+t8)*mul1)>>shift4;
386 if (val[z] > 0xF) val[z] = 0xF;
387 } else {
388 val[z] = t5;
389 }
390 }
391 _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
392 }
393 // copy the ending pixel
394 _dest[srcwidth-1] = *(_src3 - 1);
395 // next row
396 _src1 += srcwidth;
397 _src2 += srcwidth;
398 _src3 += srcwidth;
399 _dest += srcwidth;
400 }
401 // copy the last row
402 memcpy(_dest, _src2, (srcwidth << 1));
403}
404#endif /* !_16BPP_HACK */
405
406/*
407 * Smooth filters
408 * Hiroshi Morii <koolsmoky@users.sourceforge.net>
409 */
410void SmoothFilter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter)
411{
412 // NOTE: for now we get away with copying the boundaries
413 // filter the boundaries if we face problems
414
415 uint32 mul1, mul2, mul3, shift4;
416
417 uint32 x,y,z;
418 uint32 *_src1, *_src2, *_src3, *_dest;
419 uint32 val[4];
420 uint32 t1,t2,t3,t4,t5,t6,t7,t8,t9;
421
422 switch( filter ) {
423 case SMOOTH_FILTER_4:
424 mul1=1;
425 mul2=2;
426 mul3=4;
427 shift4=4;
428 break;
429 case SMOOTH_FILTER_3:
430 mul1=1;
431 mul2=1;
432 mul3=8;
433 shift4=4;
434 break;
435 case SMOOTH_FILTER_2:
436 mul1=1;
437 mul2=1;
438 mul3=2;
439 shift4=2;
440 break;
441 case SMOOTH_FILTER_1:
442 default:
443 mul1=1;
444 mul2=1;
445 mul3=6;
446 shift4=3;
447 break;
448 }
449
450 switch (filter) {
451 case SMOOTH_FILTER_3:
452 case SMOOTH_FILTER_4:
453 // setup rows
454 _src1 = src;
455 _src2 = _src1 + srcwidth;
456 _src3 = _src2 + srcwidth;
457 _dest = dest;
458 // copy the first row
459 memcpy(_dest, _src1, (srcwidth << 2));
460 _dest += srcwidth;
461 // filter 2nd row to 1 row before the last
462 for (y = 1; y < srcheight - 1; y++){
463 // copy the first pixel
464 _dest[0] = _src2[0];
465 // filter 2nd pixel to 1 pixel before last
466 for (x = 1; x < srcwidth - 1; x++) {
467 for (z = 0; z < 4; z++ ) {
468 t1 = *((uint8*)(_src1+x-1)+z);
469 t2 = *((uint8*)(_src1+x )+z);
470 t3 = *((uint8*)(_src1+x+1)+z);
471 t4 = *((uint8*)(_src2+x-1)+z);
472 t5 = *((uint8*)(_src2+x )+z);
473 t6 = *((uint8*)(_src2+x+1)+z);
474 t7 = *((uint8*)(_src3+x-1)+z);
475 t8 = *((uint8*)(_src3+x )+z);
476 t9 = *((uint8*)(_src3+x+1)+z);
477 /* the component value must not overflow 0xFF */
478 val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4;
479 if (val[z] > 0xFF) val[z] = 0xFF;
480 }
481 _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
482 }
483 // copy the ending pixel
484 _dest[srcwidth-1] = *(_src3 - 1);
485 // next row
486 _src1 += srcwidth;
487 _src2 += srcwidth;
488 _src3 += srcwidth;
489 _dest += srcwidth;
490 }
491 // copy the last row
492 memcpy(_dest, _src2, (srcwidth << 2));
493 break;
494 case SMOOTH_FILTER_1:
495 case SMOOTH_FILTER_2:
496 default:
497 // setup rows
498 _src1 = src;
499 _src2 = _src1 + srcwidth;
500 _src3 = _src2 + srcwidth;
501 _dest = dest;
502 // copy the first row
503 memcpy(_dest, _src1, (srcwidth << 2));
504 _dest += srcwidth;
505 // filter 2nd row to 1 row before the last
506 for (y = 1; y < srcheight - 1; y++) {
507 // filter 1st pixel to the last
508 if (y & 1) {
509 for( x = 0; x < srcwidth; x++) {
510 for( z = 0; z < 4; z++ ) {
511 t2 = *((uint8*)(_src1+x )+z);
512 t5 = *((uint8*)(_src2+x )+z);
513 t8 = *((uint8*)(_src3+x )+z);
514 /* the component value must not overflow 0xFF */
515 val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4;
516 if (val[z] > 0xFF) val[z] = 0xFF;
517 }
518 _dest[x] = val[0]|(val[1]<<8)|(val[2]<<16)|(val[3]<<24);
519 }
520 } else {
521 memcpy(_dest, _src2, (srcwidth << 2));
522 }
523 // next row
524 _src1 += srcwidth;
525 _src2 += srcwidth;
526 _src3 += srcwidth;
527 _dest += srcwidth;
528 }
529 // copy the last row
530 memcpy(_dest, _src2, (srcwidth << 2));
531 break;
532 }
533}
534
535#if !_16BPP_HACK
536void SmoothFilter_4444(uint16 *src, uint32 srcwidth, uint32 srcheight, uint16 *dest, uint32 filter)
537{
538 // NOTE: for now we get away with copying the boundaries
539 // filter the boundaries if we face problems
540
541 uint16 mul1, mul2, mul3, shift4;
542
543 uint32 x,y,z;
544 uint16 *_src1, *_src2, *_src3, *_dest;
545 uint16 val[4];
546 uint16 t1,t2,t3,t4,t5,t6,t7,t8,t9;
547
548 switch( filter ) {
549 case SMOOTH_FILTER_4:
550 mul1=1;
551 mul2=2;
552 mul3=4;
553 shift4=4;
554 break;
555 case SMOOTH_FILTER_3:
556 mul1=1;
557 mul2=1;
558 mul3=8;
559 shift4=4;
560 break;
561 case SMOOTH_FILTER_2:
562 mul1=1;
563 mul2=1;
564 mul3=2;
565 shift4=2;
566 break;
567 case SMOOTH_FILTER_1:
568 default:
569 mul1=1;
570 mul2=1;
571 mul3=6;
572 shift4=3;
573 break;
574 }
575
576 switch (filter) {
577 case SMOOTH_FILTER_3:
578 case SMOOTH_FILTER_4:
579 // setup rows
580 _src1 = src;
581 _src2 = _src1 + srcwidth;
582 _src3 = _src2 + srcwidth;
583 _dest = dest;
584 // copy the first row
585 memcpy(_dest, _src1, (srcwidth << 1));
586 _dest += srcwidth;
587 // filter 2nd row to 1 row before the last
588 for (y = 1; y < srcheight - 1; y++) {
589 // copy the first pixel
590 _dest[0] = *_src2;
591 // filter 2nd pixel to 1 pixel before last
592 for (x = 1; x < srcwidth - 1; x++) {
593 for (z = 0; z < 4; z++ ) {
594 /* Read the entire 16bit pixel and then extract the A,R,G,B components. */
595 uint32 shift = z << 2;
596 t1 = ((*(uint16*)(_src1+x-1)) >> shift) & 0xF;
597 t2 = ((*(uint16*)(_src1+x )) >> shift) & 0xF;
598 t3 = ((*(uint16*)(_src1+x+1)) >> shift) & 0xF;
599 t4 = ((*(uint16*)(_src2+x-1)) >> shift) & 0xF;
600 t5 = ((*(uint16*)(_src2+x )) >> shift) & 0xF;
601 t6 = ((*(uint16*)(_src2+x+1)) >> shift) & 0xF;
602 t7 = ((*(uint16*)(_src3+x-1)) >> shift) & 0xF;
603 t8 = ((*(uint16*)(_src3+x )) >> shift) & 0xF;
604 t9 = ((*(uint16*)(_src3+x+1)) >> shift) & 0xF;
605 /* the component value must not overflow 0xF */
606 val[z] = ((t1+t3+t7+t9)*mul1+((t2+t4+t6+t8)*mul2)+(t5*mul3))>>shift4;
607 if (val[z] > 0xF) val[z] = 0xF;
608 }
609 _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
610 }
611 // copy the ending pixel
612 _dest[srcwidth-1] = *(_src3 - 1);
613 // next row
614 _src1 += srcwidth;
615 _src2 += srcwidth;
616 _src3 += srcwidth;
617 _dest += srcwidth;
618 }
619 // copy the last row
620 memcpy(_dest, _src2, (srcwidth << 1));
621 break;
622 case SMOOTH_FILTER_1:
623 case SMOOTH_FILTER_2:
624 default:
625 // setup rows
626 _src1 = src;
627 _src2 = _src1 + srcwidth;
628 _src3 = _src2 + srcwidth;
629 _dest = dest;
630 // copy the first row
631 memcpy(_dest, _src1, (srcwidth << 1));
632 _dest += srcwidth;
633 // filter 2nd row to 1 row before the last
634 for( y = 1; y < srcheight - 1; y++) {
635 if (y & 1) {
636 for( x = 0; x < srcwidth; x++) {
637 for( z = 0; z < 4; z++ ) {
638 /* Read the entire 16bit pixel and then extract the A,R,G,B components. */
639 uint32 shift = z << 2;
640 t2 = ((*(uint16*)(_src1+x)) >> shift) & 0xF;
641 t5 = ((*(uint16*)(_src2+x)) >> shift) & 0xF;
642 t8 = ((*(uint16*)(_src3+x)) >> shift) & 0xF;
643 /* the component value must not overflow 0xF */
644 val[z] = ((t2+t8)*mul2+(t5*mul3))>>shift4;
645 if (val[z] > 0xF) val[z] = 0xF;
646 }
647 _dest[x] = val[0]|(val[1]<<4)|(val[2]<<8)|(val[3]<<12);
648 }
649 } else {
650 memcpy(_dest, _src2, (srcwidth << 1));
651 }
652 // next row
653 _src1 += srcwidth;
654 _src2 += srcwidth;
655 _src3 += srcwidth;
656 _dest += srcwidth;
657 }
658 // copy the last row
659 memcpy(_dest, _src2, (srcwidth << 1));
660 break;
661 }
662}
663#endif /* !_16BPP_HACK */
664
665void filter_8888(uint32 *src, uint32 srcwidth, uint32 srcheight, uint32 *dest, uint32 filter) {
666 switch (filter & ENHANCEMENT_MASK) {
667 case HQ4X_ENHANCEMENT:
668 hq4x_8888((uint8*)src, (uint8*)dest, srcwidth, srcheight, srcwidth, (srcwidth << 4));
669 return;
670 case HQ2X_ENHANCEMENT:
671 hq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
672 return;
673 case HQ2XS_ENHANCEMENT:
674 hq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
675 return;
676 case LQ2X_ENHANCEMENT:
677 lq2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
678 return;
679 case LQ2XS_ENHANCEMENT:
680 lq2xS_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
681 return;
682 case X2SAI_ENHANCEMENT:
683 Super2xSaI_8888((uint32*)src, (uint32*)dest, srcwidth, srcheight, srcwidth);
684 return;
685 case X2_ENHANCEMENT:
686 Texture2x_32((uint8*)src, (srcwidth << 2), (uint8*)dest, (srcwidth << 3), srcwidth, srcheight);
687 return;
688 }
689
690 switch (filter & (SMOOTH_FILTER_MASK|SHARP_FILTER_MASK)) {
691 case SMOOTH_FILTER_1:
692 case SMOOTH_FILTER_2:
693 case SMOOTH_FILTER_3:
694 case SMOOTH_FILTER_4:
695 SmoothFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SMOOTH_FILTER_MASK));
696 return;
697 case SHARP_FILTER_1:
698 case SHARP_FILTER_2:
699 SharpFilter_8888((uint32*)src, srcwidth, srcheight, (uint32*)dest, (filter & SHARP_FILTER_MASK));
700 return;
701 }
702}