1 /*
2 
3 TestImageFilter.c: test program for MMX filter routines
4 
5 (C) A. Schiffler, 2006, zlib license
6 (C) Sylvain Beucler, 2013, zlib license
7 
8 */
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
13 #include <time.h>
14 
15 #include "SDL.h"
16 
17 #ifdef WIN32
18 #include <windows.h>
19 #include "SDL_imageFilter.h"
20 #ifndef bcmp
21 #define bcmp(s1, s2, n) memcmp ((s1), (s2), (n))
22 #endif
23 #else
24 #include "SDL/SDL_imageFilter.h"
25 #endif
26 
27 #define SRC_SIZE 23
28 
29 int total_count = 0;
30 int ok_count = 0;
31 
setup_src(unsigned char * src1,unsigned char * src2)32 void setup_src(unsigned char *src1, unsigned char *src2)
33 {
34 	int i;
35 
36 	src1[0]=1;
37 	src1[2]=1;
38 	src1[1]=4;
39 	src1[3]=3;
40 	src1[4]=33;
41 	for (i=5; i<14; i++) src1[i]=i;
42 	src1[14]=8;
43 	for (i=15; i<SRC_SIZE; i++) src1[i]=rand();
44 
45 	src2[0]=1;
46 	src2[1]=3;
47 	src2[2]=3;
48 	src2[3]=2;
49 	src2[4]=44;
50 	for (i=5; i<14; i++) src2[i]=14-i;
51 	src2[14]=10;
52 	for (i=15; i<SRC_SIZE; i++) src2[i]=src1[i];
53 }
54 
print_result(int mmx,char * label,unsigned char * src1,unsigned char * src2,unsigned char * dst)55 void print_result(int mmx, char *label, unsigned char *src1, unsigned char *src2, unsigned char *dst)
56 {
57 	char blabel[80];
58 	int i;
59 	memset((void *)blabel, ' ', 80);
60 	blabel[strlen(label)+4]=0;
61 
62 	printf("\n");
63 	printf ("%s   pos   ", blabel);
64 	for (i = 0; i < SRC_SIZE; i++)
65 		printf("%2d ", i);
66 	printf("\n");
67 
68 	printf ("%s   src1  ", blabel);
69 	for (i = 0; i < SRC_SIZE; i++)
70 		printf("%02x ", src1[i]);
71 	printf("\n");
72 
73 	if (src2) {
74 		printf ("%s   src2  ", blabel);
75 		for (i = 0; i < SRC_SIZE; i++)
76 			printf("%02x ", src2[i]);
77 	}
78 	printf("\n");
79 
80 	printf ("%s %s   dest  ",mmx?"MMX":" C ",label);
81 	for (i = 0; i < SRC_SIZE; i++)
82 		printf("%02x ", dst[i]);
83 	printf("\n");
84 }
85 
print_compare(unsigned char * dst1,unsigned char * dst2)86 void print_compare(unsigned char *dst1, unsigned char *dst2)
87 {
88 	total_count++;
89 	if (bcmp(dst1,dst2,SRC_SIZE)==0) {
90 		printf ("OK\n");
91 		ok_count++;
92 	} else {
93 		printf ("ERROR\n");
94 	}
95 }
96 
print_line()97 void print_line()
98 {
99 	printf ("------------------------------------------------------------------------\n\n\n");
100 }
101 
pause()102 void pause()
103 {
104 	char ch;
105 	do {
106 		ch = getchar();
107 		putchar('.');
108 	} while (ch != '\n');
109 }
110 
111 /* ----------- main ---------- */
112 
main(int argc,char * argv[])113 int main(int argc, char *argv[])
114 {
115 	unsigned char src1[SRC_SIZE], src2[SRC_SIZE], dstm[SRC_SIZE], dstc[SRC_SIZE];
116 	int size = 2*1024*1024;
117 	unsigned char *t1 = (unsigned char *)malloc(size), *t2 = (unsigned char *)malloc(size), *d = (unsigned char *)malloc(size);
118 	int i;
119 
120 	// Interestingly, C tests are about 4x faster
121 	// on malloc(size) than on char[size]
122 
123 	printf("src1:\t%s (%p)\tsrc2:\t%s (%p)\tdstm:\t%s (%p)\tdstc:\t%s (%p)\n",
124 		((long long)src1%8) ? "not aligned" : "aligned", src1,
125 		((long long)src2%8) ? "not aligned" : "aligned", src2,
126 		((long long)dstm%8) ? "not aligned" : "aligned", dstm,
127 		((long long)dstc%8) ? "not aligned" : "aligned", dstc);
128 
129 	printf("t1:\t%s (%p)\tt2:\t%s (%p)\td:\t%s (%p)\n",
130 		((long long)t1%8) ? "not aligned" : "aligned", t1,
131 		((long long)t2%8) ? "not aligned" : "aligned", t2,
132 		((long long) d%8) ? "not aligned" : "aligned",  d);
133 
134 	{
135 		/* Initialize to make valgrind happy */
136 		srand((unsigned int)time(NULL));
137 		for (i = 0; i < size; i++) {
138 			/* use more random lower-order bits (int->char) */
139 			t1[i] = rand(); t2[i] = rand(); d[i] = rand();
140 		}
141 	}
142 
143 	SDL_Init(SDL_INIT_TIMER);
144 
145 	/* SDL_imageFilter Test */
146 
147 	printf ("TestImageFilter\n\n");
148 	printf ("Testing an array of 23 bytes - first 16 bytes should be processed\n");
149 	printf ("by MMX or C code, the last 7 bytes only by C code.\n\n");
150 
151 	print_line();
152 
153 
154 #define	TEST_C   0
155 #define	TEST_MMX 1
156 	{
157 #define FUNC(f) { #f, SDL_imageFilter ## f }
158 		struct func {
159 			char* name;
160 			int (*f)(unsigned char*, unsigned char*, unsigned char*, unsigned int);
161 		};
162 		struct func funcs[] = {
163 			FUNC(BitAnd),
164 			FUNC(BitOr),
165 			FUNC(Add),
166 			FUNC(AbsDiff),
167 			FUNC(Mean),
168 			FUNC(Sub),
169 			FUNC(Mult),
170 			FUNC(MultNor),
171 			FUNC(MultDivby2),
172 			FUNC(MultDivby4),
173 			FUNC(Div),
174 		};
175 
176 		int k;
177 		for (k = 0; k < sizeof(funcs)/sizeof(struct func); k++) {
178 			Uint32 start;
179 			int i;
180 
181 			setup_src(src1, src2);
182 
183 			SDL_imageFilterMMXon();
184 			funcs[k].f(src1, src2, dstm, SRC_SIZE);
185 			print_result(TEST_MMX, funcs[k].name, src1, src2, dstm);
186 			start = SDL_GetTicks();
187 			for (i = 0; i < 50; i++) {
188 				funcs[k].f(t1, t2, d, size);
189 			}
190 			printf("MMX %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
191 
192 			SDL_imageFilterMMXoff();
193 			funcs[k].f(src1, src2, dstc, SRC_SIZE);
194 			print_result(TEST_C, funcs[k].name, src1, src2, dstc);
195 			start = SDL_GetTicks();
196 			for (i = 0; i < 50; i++) {
197 				funcs[k].f(t1, t2, d, size);
198 			}
199 			printf(" C  %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
200 
201 			print_compare(dstm,dstc);
202 			print_line();
203 		}
204 	}
205 
206 	{
207 		Uint32 start;
208 		int i;
209 		char call[1024];
210 		sprintf(call, "BitNegation");
211 
212 		setup_src(src1, src2);
213 
214 		SDL_imageFilterMMXon();
215 		SDL_imageFilterBitNegation(src1, dstm, SRC_SIZE);
216 		print_result(TEST_MMX, call, src1, NULL, dstm);
217 		start = SDL_GetTicks();
218 		for (i = 0; i < 50; i++) {
219 			SDL_imageFilterBitNegation(t1, d, size);
220 		}
221 		printf("MMX %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
222 
223 		SDL_imageFilterMMXoff();
224 		SDL_imageFilterBitNegation(src1, dstc, SRC_SIZE);
225 		print_result(TEST_C, call, src1, NULL, dstc);
226 		start = SDL_GetTicks();
227 		for (i = 0; i < 50; i++) {
228 			SDL_imageFilterBitNegation(t1, d, size);
229 		}
230 		printf(" C  %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
231 
232 		print_compare(dstm,dstc);
233 		print_line();
234 	}
235 
236 
237 	{
238 #undef FUNC
239 #define FUNC(f, c) { #f, SDL_imageFilter ## f, c }
240 		struct func {
241 			char* name;
242 			int (*f)(unsigned char*, unsigned char*, unsigned int, unsigned char);
243 			unsigned char arg;
244 		};
245 		struct func funcs[] = {
246 			FUNC(AddByte,                3),
247 			FUNC(AddByteToHalf,          3),
248 			FUNC(SubByte,                3),
249 			FUNC(ShiftRight,             1),
250 			FUNC(ShiftRightUint,         4),
251 			FUNC(MultByByte,             3),
252 			FUNC(ShiftLeftByte,          3),
253 			FUNC(ShiftLeft,              3),
254 			FUNC(ShiftLeftUint,          4),
255 			FUNC(BinarizeUsingThreshold, 9),
256 		};
257 
258 		int k;
259 		for (k = 0; k < sizeof(funcs)/sizeof(struct func); k++) {
260 			Uint32 start;
261 			int i;
262 			char call[1024];
263 			sprintf(call, "%s(%u)", funcs[k].name, funcs[k].arg);
264 
265 			setup_src(src1, src2);
266 
267 			SDL_imageFilterMMXon();
268 			funcs[k].f(src1, dstm, SRC_SIZE, funcs[k].arg);
269 			print_result(TEST_MMX, call, src1, NULL, dstm);
270 			start = SDL_GetTicks();
271 			for (i = 0; i < 50; i++) {
272 				funcs[k].f(t1, d, size, funcs[k].arg);
273 			}
274 			printf("MMX %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
275 
276 			SDL_imageFilterMMXoff();
277 			funcs[k].f(src1, dstc, SRC_SIZE, funcs[k].arg);
278 			print_result(TEST_C, call, src1, NULL, dstc);
279 			start = SDL_GetTicks();
280 			for (i = 0; i < 50; i++) {
281 				funcs[k].f(t1, d, size, funcs[k].arg);
282 			}
283 			printf(" C  %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
284 
285 			print_compare(dstm,dstc);
286 			print_line();
287 		}
288 	}
289 
290 
291 	{
292 #undef FUNC
293 #define FUNC(f, c1, c2) { #f, SDL_imageFilter ## f, c1, c2 }
294 		struct func {
295 			char* name;
296 			int (*f)(unsigned char*, unsigned char*, unsigned int, unsigned char, unsigned char);
297 			unsigned char arg1, arg2;
298 		};
299 		struct func funcs[] = {
300 			FUNC(ShiftRightAndMultByByte, 1, 3),
301 			FUNC(ClipToRange, 3, 8),
302 		};
303 
304 		int k;
305 		for (k = 0; k < sizeof(funcs)/sizeof(struct func); k++) {
306 			Uint32 start;
307 			int i;
308 			char call[1024];
309 			sprintf(call, "%s(%u,%u)", funcs[k].name, funcs[k].arg1, funcs[k].arg2);
310 
311 			setup_src(src1, src2);
312 
313 			SDL_imageFilterMMXon();
314 			funcs[k].f(src1, dstm, SRC_SIZE, funcs[k].arg1, funcs[k].arg2);
315 			print_result(TEST_MMX, call, src1, NULL, dstm);
316 			start = SDL_GetTicks();
317 			for (i = 0; i < 50; i++) {
318 				funcs[k].f(t1, d, size, funcs[k].arg1, funcs[k].arg2);
319 			}
320 			printf("MMX %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
321 
322 			SDL_imageFilterMMXoff();
323 			funcs[k].f(src1, dstc, SRC_SIZE, funcs[k].arg1, funcs[k].arg2);
324 			print_result(TEST_C, call, src1, NULL, dstc);
325 			start = SDL_GetTicks();
326 			for (i = 0; i < 50; i++) {
327 				funcs[k].f(t1, d, size, funcs[k].arg1, funcs[k].arg2);
328 			}
329 			printf(" C  %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
330 
331 			print_compare(dstm,dstc);
332 			print_line();
333 		}
334 	}
335 
336 
337 	{
338 		Uint32 start;
339 		int i;
340 		char call[1024];
341 		sprintf(call, "NormalizeLinear(0,33,0,255)");
342 
343 		setup_src(src1, src2);
344 
345 		SDL_imageFilterMMXon();
346 		SDL_imageFilterNormalizeLinear(src1, dstm, SRC_SIZE, 0,33, 0,255);
347 		print_result(TEST_MMX, call, src1, NULL, dstm);
348 		start = SDL_GetTicks();
349 		for (i = 0; i < 50; i++) {
350 			SDL_imageFilterNormalizeLinear(t1, d, size, 0,33, 0,255);
351 		}
352 		printf("MMX %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
353 
354 		SDL_imageFilterMMXoff();
355 		SDL_imageFilterNormalizeLinear(src1, dstc, SRC_SIZE, 0,33, 0,255);
356 		print_result(TEST_C, call, src1, NULL, dstc);
357 		start = SDL_GetTicks();
358 		for (i = 0; i < 50; i++) {
359 			SDL_imageFilterNormalizeLinear(t1, d, size, 0,33, 0,255);
360 		}
361 		printf(" C  %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
362 
363 		print_compare(dstm,dstc);
364 		print_line();
365 	}
366 
367 
368 	/* Uint functions */
369 	/* Disabled, since broken *//* ??? */
370 	{
371 #undef FUNC
372 #define FUNC(f, c) { #f, SDL_imageFilter ## f, c }
373 		struct func {
374 			char* name;
375 			int (*f)(unsigned char*, unsigned char*, unsigned int, unsigned int);
376 			unsigned int arg;
377 		};
378 		struct func funcs[] = {
379 			FUNC(AddUint,       0x01020304),
380 			FUNC(SubUint,       0x01020304),
381 		};
382 
383 		int k;
384 		for (k = 0; k < sizeof(funcs)/sizeof(struct func); k++) {
385 			Uint32 start;
386 			int i;
387 			char call[1024];
388 			sprintf(call, "%s(%u)", funcs[k].name, funcs[k].arg);
389 
390 			setup_src(src1, src2);
391 
392 			SDL_imageFilterMMXon();
393 			funcs[k].f(src1, dstm, SRC_SIZE, funcs[k].arg);
394 			print_result(TEST_MMX, call, src1, NULL, dstm);
395 			start = SDL_GetTicks();
396 			for (i = 0; i < 50; i++) {
397 				funcs[k].f(t1, d, size, funcs[k].arg);
398 			}
399 			printf("MMX %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
400 
401 			SDL_imageFilterMMXoff();
402 			funcs[k].f(src1, dstc, SRC_SIZE, funcs[k].arg);
403 			print_result(TEST_C, call, src1, NULL, dstc);
404 			start = SDL_GetTicks();
405 			for (i = 0; i < 50; i++) {
406 				funcs[k].f(t1, d, size, funcs[k].arg);
407 			}
408 			printf(" C  %dx%dk: %dms\n", i, size/1024, SDL_GetTicks() - start);
409 
410 			print_compare(dstm,dstc);
411 			print_line();
412 		}
413 	}
414 
415 
416 	SDL_imageFilterMMXon();
417 	if (SDL_imageFilterMMXdetect())
418 	{
419 		printf("MMX was detected\n\n");
420 	}
421 	else
422 	{
423 		printf("MMX was NOT detected\n\n");
424 	}
425 
426 	printf ("Result: %i of %i passed OK.\n", ok_count, total_count);
427 
428 #ifdef WIN32
429 	printf("Press Enter to continue ...");
430 	pause();
431 #endif
432 
433 	SDL_Quit();
434 	free(d);
435 	free(t2);
436 	free(t1);
437 	exit(0);
438 }
439