1 /*
2  * This file is part of the Scale2x project.
3  *
4  * Copyright (C) 2001, 2002, 2003, 2004 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 
21 /*
22  * This file contains a C and MMX implementation of the Scale2x effect.
23  *
24  * You can find an high level description of the effect at :
25  *
26  * http://scale2x.sourceforge.net/
27  *
28  * Alternatively at the previous license terms, you are allowed to use this
29  * code in your program with these conditions:
30  * - the program is not used in commercial activities.
31  * - the whole source code of the program is released with the binary.
32  * - derivative works of the program are allowed.
33  */
34 
35 #include "common/scummsys.h"
36 
37 #include "graphics/scaler/scale3x.h"
38 
39 /***************************************************************************/
40 /* Scale3x C implementation */
41 
scale3x_8_def_border(scale3x_uint8 * __restrict__ dst,const scale3x_uint8 * __restrict__ src0,const scale3x_uint8 * __restrict__ src1,const scale3x_uint8 * __restrict__ src2,unsigned count)42 static inline void scale3x_8_def_border(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count) {
43 	/* central pixels */
44 	while (count) {
45 		if (src0[0] != src2[0] && src1[-1] != src1[1]) {
46 			dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
47 			dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
48 			dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
49 		} else {
50 			dst[0] = src1[0];
51 			dst[1] = src1[0];
52 			dst[2] = src1[0];
53 		}
54 
55 		++src0;
56 		++src1;
57 		++src2;
58 		dst += 3;
59 		--count;
60 	}
61 }
62 
scale3x_8_def_center(scale3x_uint8 * __restrict__ dst,const scale3x_uint8 * __restrict__ src0,const scale3x_uint8 * __restrict__ src1,const scale3x_uint8 * __restrict__ src2,unsigned count)63 static inline void scale3x_8_def_center(scale3x_uint8* __restrict__ dst, const scale3x_uint8* __restrict__ src0, const scale3x_uint8* __restrict__ src1, const scale3x_uint8* __restrict__ src2, unsigned count) {
64 	/* central pixels */
65 	while (count) {
66 		if (src0[0] != src2[0] && src1[-1] != src1[1]) {
67 			dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
68 			dst[1] = src1[0];
69 			dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
70 		} else {
71 			dst[0] = src1[0];
72 			dst[1] = src1[0];
73 			dst[2] = src1[0];
74 		}
75 
76 		++src0;
77 		++src1;
78 		++src2;
79 		dst += 3;
80 		--count;
81 	}
82 }
83 
scale3x_16_def_border(scale3x_uint16 * __restrict__ dst,const scale3x_uint16 * __restrict__ src0,const scale3x_uint16 * __restrict__ src1,const scale3x_uint16 * __restrict__ src2,unsigned count)84 static inline void scale3x_16_def_border(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count) {
85 	/* central pixels */
86 	while (count) {
87 		if (src0[0] != src2[0] && src1[-1] != src1[1]) {
88 			dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
89 			dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
90 			dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
91 		} else {
92 			dst[0] = src1[0];
93 			dst[1] = src1[0];
94 			dst[2] = src1[0];
95 		}
96 
97 		++src0;
98 		++src1;
99 		++src2;
100 		dst += 3;
101 		--count;
102 	}
103 }
104 
scale3x_16_def_center(scale3x_uint16 * __restrict__ dst,const scale3x_uint16 * __restrict__ src0,const scale3x_uint16 * __restrict__ src1,const scale3x_uint16 * __restrict__ src2,unsigned count)105 static inline void scale3x_16_def_center(scale3x_uint16* __restrict__ dst, const scale3x_uint16* __restrict__ src0, const scale3x_uint16* __restrict__ src1, const scale3x_uint16* __restrict__ src2, unsigned count) {
106 	/* central pixels */
107 	while (count) {
108 		if (src0[0] != src2[0] && src1[-1] != src1[1]) {
109 			dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
110 			dst[1] = src1[0];
111 			dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
112 		} else {
113 			dst[0] = src1[0];
114 			dst[1] = src1[0];
115 			dst[2] = src1[0];
116 		}
117 
118 		++src0;
119 		++src1;
120 		++src2;
121 		dst += 3;
122 		--count;
123 	}
124 }
125 
scale3x_32_def_border(scale3x_uint32 * __restrict__ dst,const scale3x_uint32 * __restrict__ src0,const scale3x_uint32 * __restrict__ src1,const scale3x_uint32 * __restrict__ src2,unsigned count)126 static inline void scale3x_32_def_border(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count) {
127 	/* central pixels */
128 	while (count) {
129 		if (src0[0] != src2[0] && src1[-1] != src1[1]) {
130 			dst[0] = src1[-1] == src0[0] ? src1[-1] : src1[0];
131 			dst[1] = (src1[-1] == src0[0] && src1[0] != src0[1]) || (src1[1] == src0[0] && src1[0] != src0[-1]) ? src0[0] : src1[0];
132 			dst[2] = src1[1] == src0[0] ? src1[1] : src1[0];
133 		} else {
134 			dst[0] = src1[0];
135 			dst[1] = src1[0];
136 			dst[2] = src1[0];
137 		}
138 
139 		++src0;
140 		++src1;
141 		++src2;
142 		dst += 3;
143 		--count;
144 	}
145 }
146 
scale3x_32_def_center(scale3x_uint32 * __restrict__ dst,const scale3x_uint32 * __restrict__ src0,const scale3x_uint32 * __restrict__ src1,const scale3x_uint32 * __restrict__ src2,unsigned count)147 static inline void scale3x_32_def_center(scale3x_uint32* __restrict__ dst, const scale3x_uint32* __restrict__ src0, const scale3x_uint32* __restrict__ src1, const scale3x_uint32* __restrict__ src2, unsigned count) {
148 	/* central pixels */
149 	while (count) {
150 		if (src0[0] != src2[0] && src1[-1] != src1[1]) {
151 			dst[0] = (src1[-1] == src0[0] && src1[0] != src2[-1]) || (src1[-1] == src2[0] && src1[0] != src0[-1]) ? src1[-1] : src1[0];
152 			dst[1] = src1[0];
153 			dst[2] = (src1[1] == src0[0] && src1[0] != src2[1]) || (src1[1] == src2[0] && src1[0] != src0[1]) ? src1[1] : src1[0];
154 		} else {
155 			dst[0] = src1[0];
156 			dst[1] = src1[0];
157 			dst[2] = src1[0];
158 		}
159 
160 		++src0;
161 		++src1;
162 		++src2;
163 		dst += 3;
164 		--count;
165 	}
166 }
167 
168 /**
169  * Scale by a factor of 3 a row of pixels of 8 bits.
170  * The function is implemented in C.
171  * The pixels over the left and right borders are assumed of the same color of
172  * the pixels on the border.
173  * @param src0 Pointer at the first pixel of the previous row.
174  * @param src1 Pointer at the first pixel of the current row.
175  * @param src2 Pointer at the first pixel of the next row.
176  * @param count Length in pixels of the src0, src1 and src2 rows.
177  * It must be at least 2.
178  * @param dst0 First destination row, triple length in pixels.
179  * @param dst1 Second destination row, triple length in pixels.
180  * @param dst2 Third destination row, triple length in pixels.
181  */
scale3x_8_def(scale3x_uint8 * dst0,scale3x_uint8 * dst1,scale3x_uint8 * dst2,const scale3x_uint8 * src0,const scale3x_uint8 * src1,const scale3x_uint8 * src2,unsigned count)182 void scale3x_8_def(scale3x_uint8* dst0, scale3x_uint8* dst1, scale3x_uint8* dst2, const scale3x_uint8* src0, const scale3x_uint8* src1, const scale3x_uint8* src2, unsigned count) {
183 	scale3x_8_def_border(dst0, src0, src1, src2, count);
184 	scale3x_8_def_center(dst1, src0, src1, src2, count);
185 	scale3x_8_def_border(dst2, src2, src1, src0, count);
186 }
187 
188 /**
189  * Scale by a factor of 3 a row of pixels of 16 bits.
190  * This function operates like scale3x_8_def() but for 16 bits pixels.
191  * @param src0 Pointer at the first pixel of the previous row.
192  * @param src1 Pointer at the first pixel of the current row.
193  * @param src2 Pointer at the first pixel of the next row.
194  * @param count Length in pixels of the src0, src1 and src2 rows.
195  * It must be at least 2.
196  * @param dst0 First destination row, triple length in pixels.
197  * @param dst1 Second destination row, triple length in pixels.
198  * @param dst2 Third destination row, triple length in pixels.
199  */
scale3x_16_def(scale3x_uint16 * dst0,scale3x_uint16 * dst1,scale3x_uint16 * dst2,const scale3x_uint16 * src0,const scale3x_uint16 * src1,const scale3x_uint16 * src2,unsigned count)200 void scale3x_16_def(scale3x_uint16* dst0, scale3x_uint16* dst1, scale3x_uint16* dst2, const scale3x_uint16* src0, const scale3x_uint16* src1, const scale3x_uint16* src2, unsigned count) {
201 	scale3x_16_def_border(dst0, src0, src1, src2, count);
202 	scale3x_16_def_center(dst1, src0, src1, src2, count);
203 	scale3x_16_def_border(dst2, src2, src1, src0, count);
204 }
205 
206 /**
207  * Scale by a factor of 3 a row of pixels of 32 bits.
208  * This function operates like scale3x_8_def() but for 32 bits pixels.
209  * @param src0 Pointer at the first pixel of the previous row.
210  * @param src1 Pointer at the first pixel of the current row.
211  * @param src2 Pointer at the first pixel of the next row.
212  * @param count Length in pixels of the src0, src1 and src2 rows.
213  * It must be at least 2.
214  * @param dst0 First destination row, triple length in pixels.
215  * @param dst1 Second destination row, triple length in pixels.
216  * @param dst2 Third destination row, triple length in pixels.
217  */
scale3x_32_def(scale3x_uint32 * dst0,scale3x_uint32 * dst1,scale3x_uint32 * dst2,const scale3x_uint32 * src0,const scale3x_uint32 * src1,const scale3x_uint32 * src2,unsigned count)218 void scale3x_32_def(scale3x_uint32* dst0, scale3x_uint32* dst1, scale3x_uint32* dst2, const scale3x_uint32* src0, const scale3x_uint32* src1, const scale3x_uint32* src2, unsigned count) {
219 	scale3x_32_def_border(dst0, src0, src1, src2, count);
220 	scale3x_32_def_center(dst1, src0, src1, src2, count);
221 	scale3x_32_def_border(dst2, src2, src1, src0, count);
222 }
223