test: Port composite test over to use new pixel_checker_t object.
[profile/ivi/pixman.git] / test / composite.c
1 /*
2  * Copyright © 2005 Eric Anholt
3  * Copyright © 2009 Chris Wilson
4  * Copyright © 2010 Soeren Sandmann
5  * Copyright © 2010 Red Hat, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of Eric Anholt not be used in
12  * advertising or publicity pertaining to distribution of the software without
13  * specific, written prior permission.  Eric Anholt makes no
14  * representations about the suitability of this software for any purpose.  It
15  * is provided "as is" without express or implied warranty.
16  *
17  * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19  * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23  * PERFORMANCE OF THIS SOFTWARE.
24  */
25 #include <stdio.h>
26 #include <stdlib.h> /* abort() */
27 #include <math.h>
28 #include <time.h>
29 #include "utils.h"
30
31 typedef struct format_t format_t;
32 typedef struct image_t image_t;
33 typedef struct operator_t operator_t;
34
35 struct format_t
36 {
37     pixman_format_code_t format;
38     const char *name;
39 };
40
41 static const color_t colors[] =
42 {
43     { 1.0, 1.0, 1.0, 1.0 },
44     { 1.0, 1.0, 1.0, 0.0 },
45     { 0.0, 0.0, 0.0, 1.0 },
46     { 0.0, 0.0, 0.0, 0.0 },
47     { 1.0, 0.0, 0.0, 1.0 },
48     { 0.0, 1.0, 0.0, 1.0 },
49     { 0.0, 0.0, 1.0, 1.0 },
50     { 0.5, 0.0, 0.0, 0.5 },
51 };
52
53 static uint16_t
54 _color_double_to_short (double d)
55 {
56     uint32_t i;
57
58     i = (uint32_t) (d * 65536);
59     i -= (i >> 16);
60
61     return i;
62 }
63
64 static void
65 compute_pixman_color (const color_t *color,
66                       pixman_color_t *out)
67 {
68     out->red   = _color_double_to_short (color->r);
69     out->green = _color_double_to_short (color->g);
70     out->blue  = _color_double_to_short (color->b);
71     out->alpha = _color_double_to_short (color->a);
72 }
73
74 #define REPEAT 0x01000000
75 #define FLAGS  0xff000000
76
77 static const int sizes[] =
78 {
79     0,
80     1,
81     1 | REPEAT,
82     10
83 };
84
85 static const format_t formats[] =
86 {
87 #define P(x) { PIXMAN_##x, #x }
88
89     /* 32 bpp formats */
90     P(a8r8g8b8),
91     P(x8r8g8b8),
92     P(a8b8g8r8),
93     P(x8b8g8r8),
94     P(b8g8r8a8),
95     P(b8g8r8x8),
96     P(r8g8b8a8),
97     P(r8g8b8x8),
98     P(x2r10g10b10),
99     P(x2b10g10r10),
100     P(a2r10g10b10),
101     P(a2b10g10r10),
102
103     /* 24 bpp formats */
104     P(r8g8b8),
105     P(b8g8r8),
106     P(r5g6b5),
107     P(b5g6r5),
108
109     /* 16 bpp formats */
110     P(x1r5g5b5),
111     P(x1b5g5r5),
112     P(a1r5g5b5),
113     P(a1b5g5r5),
114     P(a4b4g4r4),
115     P(x4b4g4r4),
116     P(a4r4g4b4),
117     P(x4r4g4b4),
118
119     /* 8 bpp formats */
120     P(a8),
121     P(r3g3b2),
122     P(b2g3r3),
123     P(a2r2g2b2),
124     P(a2b2g2r2),
125     P(x4a4),
126
127     /* 4 bpp formats */
128     P(a4),
129     P(r1g2b1),
130     P(b1g2r1),
131     P(a1r1g1b1),
132     P(a1b1g1r1),
133
134     /* 1 bpp formats */
135     P(a1)
136 #undef P
137 };
138
139 struct image_t
140 {
141     pixman_image_t *image;
142     const format_t *format;
143     const color_t *color;
144     pixman_repeat_t repeat;
145     int size;
146 };
147
148 struct operator_t
149 {
150     pixman_op_t op;
151     const char *name;
152 };
153
154 static const operator_t operators[] =
155 {
156 #define P(x) { PIXMAN_OP_##x, #x }
157     P(CLEAR),
158     P(SRC),
159     P(DST),
160     P(OVER),
161     P(OVER_REVERSE),
162     P(IN),
163     P(IN_REVERSE),
164     P(OUT),
165     P(OUT_REVERSE),
166     P(ATOP),
167     P(ATOP_REVERSE),
168     P(XOR),
169     P(ADD),
170     P(SATURATE),
171
172     P(DISJOINT_CLEAR),
173     P(DISJOINT_SRC),
174     P(DISJOINT_DST),
175     P(DISJOINT_OVER),
176     P(DISJOINT_OVER_REVERSE),
177     P(DISJOINT_IN),
178     P(DISJOINT_IN_REVERSE),
179     P(DISJOINT_OUT),
180     P(DISJOINT_OUT_REVERSE),
181     P(DISJOINT_ATOP),
182     P(DISJOINT_ATOP_REVERSE),
183     P(DISJOINT_XOR),
184
185     P(CONJOINT_CLEAR),
186     P(CONJOINT_SRC),
187     P(CONJOINT_DST),
188     P(CONJOINT_OVER),
189     P(CONJOINT_OVER_REVERSE),
190     P(CONJOINT_IN),
191     P(CONJOINT_IN_REVERSE),
192     P(CONJOINT_OUT),
193     P(CONJOINT_OUT_REVERSE),
194     P(CONJOINT_ATOP),
195     P(CONJOINT_ATOP_REVERSE),
196     P(CONJOINT_XOR),
197 #undef P
198 };
199
200 static double
201 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
202 {
203 #define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
204
205     double Fa, Fb;
206
207     switch (op)
208     {
209     case PIXMAN_OP_CLEAR:
210     case PIXMAN_OP_DISJOINT_CLEAR:
211     case PIXMAN_OP_CONJOINT_CLEAR:
212         return mult_chan (src, dst, 0.0, 0.0);
213
214     case PIXMAN_OP_SRC:
215     case PIXMAN_OP_DISJOINT_SRC:
216     case PIXMAN_OP_CONJOINT_SRC:
217         return mult_chan (src, dst, 1.0, 0.0);
218
219     case PIXMAN_OP_DST:
220     case PIXMAN_OP_DISJOINT_DST:
221     case PIXMAN_OP_CONJOINT_DST:
222         return mult_chan (src, dst, 0.0, 1.0);
223
224     case PIXMAN_OP_OVER:
225         return mult_chan (src, dst, 1.0, 1.0 - srca);
226
227     case PIXMAN_OP_OVER_REVERSE:
228         return mult_chan (src, dst, 1.0 - dsta, 1.0);
229
230     case PIXMAN_OP_IN:
231         return mult_chan (src, dst, dsta, 0.0);
232
233     case PIXMAN_OP_IN_REVERSE:
234         return mult_chan (src, dst, 0.0, srca);
235
236     case PIXMAN_OP_OUT:
237         return mult_chan (src, dst, 1.0 - dsta, 0.0);
238
239     case PIXMAN_OP_OUT_REVERSE:
240         return mult_chan (src, dst, 0.0, 1.0 - srca);
241
242     case PIXMAN_OP_ATOP:
243         return mult_chan (src, dst, dsta, 1.0 - srca);
244
245     case PIXMAN_OP_ATOP_REVERSE:
246         return mult_chan (src, dst, 1.0 - dsta,  srca);
247
248     case PIXMAN_OP_XOR:
249         return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
250
251     case PIXMAN_OP_ADD:
252         return mult_chan (src, dst, 1.0, 1.0);
253
254     case PIXMAN_OP_SATURATE:
255     case PIXMAN_OP_DISJOINT_OVER_REVERSE:
256         if (srca == 0.0)
257             Fa = 1.0;
258         else
259             Fa = MIN (1.0, (1.0 - dsta) / srca);
260         return mult_chan (src, dst, Fa, 1.0);
261
262     case PIXMAN_OP_DISJOINT_OVER:
263         if (dsta == 0.0)
264             Fb = 1.0;
265         else
266             Fb = MIN (1.0, (1.0 - srca) / dsta);
267         return mult_chan (src, dst, 1.0, Fb);
268
269     case PIXMAN_OP_DISJOINT_IN:
270         if (srca == 0.0)
271             Fa = 0.0;
272         else
273             Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
274         return mult_chan (src, dst, Fa, 0.0);
275
276     case PIXMAN_OP_DISJOINT_IN_REVERSE:
277         if (dsta == 0.0)
278             Fb = 0.0;
279         else
280             Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
281         return mult_chan (src, dst, 0.0, Fb);
282
283     case PIXMAN_OP_DISJOINT_OUT:
284         if (srca == 0.0)
285             Fa = 1.0;
286         else
287             Fa = MIN (1.0, (1.0 - dsta) / srca);
288         return mult_chan (src, dst, Fa, 0.0);
289
290     case PIXMAN_OP_DISJOINT_OUT_REVERSE:
291         if (dsta == 0.0)
292             Fb = 1.0;
293         else
294             Fb = MIN (1.0, (1.0 - srca) / dsta);
295         return mult_chan (src, dst, 0.0, Fb);
296
297     case PIXMAN_OP_DISJOINT_ATOP:
298         if (srca == 0.0)
299             Fa = 0.0;
300         else
301             Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
302         if (dsta == 0.0)
303             Fb = 1.0;
304         else
305             Fb = MIN (1.0, (1.0 - srca) / dsta);
306         return mult_chan (src, dst, Fa, Fb);
307
308     case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
309         if (srca == 0.0)
310             Fa = 1.0;
311         else
312             Fa = MIN (1.0, (1.0 - dsta) / srca);
313         if (dsta == 0.0)
314             Fb = 0.0;
315         else
316             Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
317         return mult_chan (src, dst, Fa, Fb);
318
319     case PIXMAN_OP_DISJOINT_XOR:
320         if (srca == 0.0)
321             Fa = 1.0;
322         else
323             Fa = MIN (1.0, (1.0 - dsta) / srca);
324         if (dsta == 0.0)
325             Fb = 1.0;
326         else
327             Fb = MIN (1.0, (1.0 - srca) / dsta);
328         return mult_chan (src, dst, Fa, Fb);
329
330     case PIXMAN_OP_CONJOINT_OVER:
331         if (dsta == 0.0)
332             Fb = 0.0;
333         else
334             Fb = MAX (0.0, 1.0 - srca / dsta);
335         return mult_chan (src, dst, 1.0, Fb);
336
337     case PIXMAN_OP_CONJOINT_OVER_REVERSE:
338         if (srca == 0.0)
339             Fa = 0.0;
340         else
341             Fa = MAX (0.0, 1.0 - dsta / srca);
342         return mult_chan (src, dst, Fa, 1.0);
343
344     case PIXMAN_OP_CONJOINT_IN:
345         if (srca == 0.0)
346             Fa = 1.0;
347         else
348             Fa = MIN (1.0, dsta / srca);
349         return mult_chan (src, dst, Fa, 0.0);
350
351     case PIXMAN_OP_CONJOINT_IN_REVERSE:
352         if (dsta == 0.0)
353             Fb = 1.0;
354         else
355             Fb = MIN (1.0, srca / dsta);
356         return mult_chan (src, dst, 0.0, Fb);
357
358     case PIXMAN_OP_CONJOINT_OUT:
359         if (srca == 0.0)
360             Fa = 0.0;
361         else
362             Fa = MAX (0.0, 1.0 - dsta / srca);
363         return mult_chan (src, dst, Fa, 0.0);
364
365     case PIXMAN_OP_CONJOINT_OUT_REVERSE:
366         if (dsta == 0.0)
367             Fb = 0.0;
368         else
369             Fb = MAX (0.0, 1.0 - srca / dsta);
370         return mult_chan (src, dst, 0.0, Fb);
371
372     case PIXMAN_OP_CONJOINT_ATOP:
373         if (srca == 0.0)
374             Fa = 1.0;
375         else
376             Fa = MIN (1.0, dsta / srca);
377         if (dsta == 0.0)
378             Fb = 0.0;
379         else
380             Fb = MAX (0.0, 1.0 - srca / dsta);
381         return mult_chan (src, dst, Fa, Fb);
382
383     case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
384         if (srca == 0.0)
385             Fa = 0.0;
386         else
387             Fa = MAX (0.0, 1.0 - dsta / srca);
388         if (dsta == 0.0)
389             Fb = 1.0;
390         else
391             Fb = MIN (1.0, srca / dsta);
392         return mult_chan (src, dst, Fa, Fb);
393
394     case PIXMAN_OP_CONJOINT_XOR:
395         if (srca == 0.0)
396             Fa = 0.0;
397         else
398             Fa = MAX (0.0, 1.0 - dsta / srca);
399         if (dsta == 0.0)
400             Fb = 0.0;
401         else
402             Fb = MAX (0.0, 1.0 - srca / dsta);
403         return mult_chan (src, dst, Fa, Fb);
404
405     case PIXMAN_OP_MULTIPLY:
406     case PIXMAN_OP_SCREEN:
407     case PIXMAN_OP_OVERLAY:
408     case PIXMAN_OP_DARKEN:
409     case PIXMAN_OP_LIGHTEN:
410     case PIXMAN_OP_COLOR_DODGE:
411     case PIXMAN_OP_COLOR_BURN:
412     case PIXMAN_OP_HARD_LIGHT:
413     case PIXMAN_OP_SOFT_LIGHT:
414     case PIXMAN_OP_DIFFERENCE:
415     case PIXMAN_OP_EXCLUSION:
416     case PIXMAN_OP_HSL_HUE:
417     case PIXMAN_OP_HSL_SATURATION:
418     case PIXMAN_OP_HSL_COLOR:
419     case PIXMAN_OP_HSL_LUMINOSITY:
420     default:
421         abort();
422         return 0; /* silence MSVC */
423     }
424 #undef mult_chan
425 }
426
427 static void
428 do_composite (pixman_op_t op,
429               const color_t *src,
430               const color_t *mask,
431               const color_t *dst,
432               color_t *result,
433               pixman_bool_t component_alpha)
434 {
435     color_t srcval, srcalpha;
436
437     if (mask == NULL)
438     {
439         srcval = *src;
440
441         srcalpha.r = src->a;
442         srcalpha.g = src->a;
443         srcalpha.b = src->a;
444         srcalpha.a = src->a;
445     }
446     else if (component_alpha)
447     {
448         srcval.r = src->r * mask->r;
449         srcval.g = src->g * mask->g;
450         srcval.b = src->b * mask->b;
451         srcval.a = src->a * mask->a;
452
453         srcalpha.r = src->a * mask->r;
454         srcalpha.g = src->a * mask->g;
455         srcalpha.b = src->a * mask->b;
456         srcalpha.a = src->a * mask->a;
457     }
458     else
459     {
460         srcval.r = src->r * mask->a;
461         srcval.g = src->g * mask->a;
462         srcval.b = src->b * mask->a;
463         srcval.a = src->a * mask->a;
464
465         srcalpha.r = src->a * mask->a;
466         srcalpha.g = src->a * mask->a;
467         srcalpha.b = src->a * mask->a;
468         srcalpha.a = src->a * mask->a;
469     }
470
471     result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
472     result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
473     result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
474     result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
475 }
476
477 static uint32_t
478 get_value (pixman_image_t *image)
479 {
480     uint32_t value = *(uint32_t *)pixman_image_get_data (image);
481
482 #ifdef WORDS_BIGENDIAN
483     {
484         pixman_format_code_t format = pixman_image_get_format (image);
485         value >>= 8 * sizeof(value) - PIXMAN_FORMAT_BPP (format);
486     }
487 #endif
488
489     return value;
490 }
491
492 static char *
493 describe_image (image_t *info, char *buf)
494 {
495     if (info->size)
496     {
497         sprintf (buf, "%s, %dx%d%s",
498                  info->format->name,
499                  info->size, info->size,
500                  info->repeat ? " R" :"");
501     }
502     else
503     {
504         sprintf (buf, "solid");
505     }
506
507     return buf;
508 }
509
510 static char *
511 describe_color (const color_t *color, char *buf)
512 {
513     sprintf (buf, "%.3f %.3f %.3f %.3f",
514              color->r, color->g, color->b, color->a);
515
516     return buf;
517 }
518
519 static pixman_bool_t
520 composite_test (image_t *dst,
521                 const operator_t *op,
522                 image_t *src,
523                 image_t *mask,
524                 pixman_bool_t component_alpha,
525                 int testno)
526 {
527     pixman_color_t fill;
528     pixman_rectangle16_t rect;
529     color_t expected, tdst, tsrc, tmsk;
530     pixel_checker_t checker;
531
532     /* Initialize dst */
533     compute_pixman_color (dst->color, &fill);
534     rect.x = rect.y = 0;
535     rect.width = rect.height = dst->size;
536     pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image, &fill, 1, &rect);
537
538     if (mask)
539     {
540         pixman_image_set_component_alpha (mask->image, component_alpha);
541
542         pixman_image_composite (op->op, src->image, mask->image, dst->image,
543                                 0, 0, 0, 0, 0, 0, dst->size, dst->size);
544     }
545     else
546     {
547         pixman_image_composite (op->op, src->image, NULL, dst->image,
548                                 0, 0,
549                                 0, 0,
550                                 0, 0,
551                                 dst->size, dst->size);
552     }
553
554     tdst = *dst->color;
555     round_color (dst->format->format, &tdst);
556
557     tsrc = *src->color;
558     if (src->size)
559         round_color (src->format->format, &tsrc);
560
561     if (mask)
562     {
563         tmsk = *mask->color;
564         if (mask->size)
565             round_color (mask->format->format, &tmsk);
566         if (component_alpha && PIXMAN_FORMAT_R (mask->format->format) == 0)
567         {
568             /* Ax component-alpha masks expand alpha into
569              * all color channels.
570              */
571             tmsk.r = tmsk.g = tmsk.b = tmsk.a;
572         }
573     }
574
575     do_composite (op->op,
576                   &tsrc,
577                   mask? &tmsk : NULL,
578                   &tdst,
579                   &expected,
580                   component_alpha);
581
582     pixel_checker_init (&checker, dst->format->format);
583
584     if (!pixel_checker_check (&checker, get_value (dst->image), &expected))
585     {
586         char buf[40], buf2[40];
587         int a, r, g, b;
588         uint32_t pixel;
589
590         printf ("---- Test %d failed ----\n", testno);
591         printf ("Operator:      %s %s\n",
592                  op->name, component_alpha ? "CA" : "");
593
594         printf ("Source:        %s\n", describe_image (src, buf));
595         if (mask != NULL)
596             printf ("Mask:          %s\n", describe_image (mask, buf));
597
598         printf ("Destination:   %s\n\n", describe_image (dst, buf));
599         printf ("               R     G     B     A         Rounded\n");
600         printf ("Source color:  %s     %s\n",
601                 describe_color (src->color, buf),
602                 describe_color (&tsrc, buf2));
603         if (mask)
604         {
605             printf ("Mask color:    %s     %s\n",
606                     describe_color (mask->color, buf),
607                     describe_color (&tmsk, buf2));
608         }
609         printf ("Dest. color:   %s     %s\n",
610                 describe_color (dst->color, buf),
611                 describe_color (&tdst, buf2));
612
613         pixel = get_value (dst->image);
614
615         printf ("Expected:      %s\n", describe_color (&expected, buf));
616
617         pixel_checker_split_pixel (&checker, pixel, &a, &r, &g, &b);
618
619         printf ("Got:           %5d %5d %5d %5d  [pixel: 0x%08x]\n", r, g, b, a, pixel);
620         pixel_checker_get_min (&checker, &expected, &a, &r, &g, &b);
621         printf ("Min accepted:  %5d %5d %5d %5d\n", r, g, b, a);
622         pixel_checker_get_max (&checker, &expected, &a, &r, &g, &b);
623         printf ("Max accepted:  %5d %5d %5d %5d\n", r, g, b, a);
624
625         return FALSE;
626     }
627     return TRUE;
628 }
629
630 static void
631 image_init (image_t *info,
632             int color,
633             int format,
634             int size)
635 {
636     pixman_color_t fill;
637
638     info->color = &colors[color];
639     compute_pixman_color (info->color, &fill);
640
641     info->format = &formats[format];
642     info->size = sizes[size] & ~FLAGS;
643     info->repeat = PIXMAN_REPEAT_NONE;
644
645     if (info->size)
646     {
647         pixman_rectangle16_t rect;
648
649         info->image = pixman_image_create_bits (info->format->format,
650                                                 info->size, info->size,
651                                                 NULL, 0);
652
653         rect.x = rect.y = 0;
654         rect.width = rect.height = info->size;
655         pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill,
656                                       1, &rect);
657
658         if (sizes[size] & REPEAT)
659         {
660             pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL);
661             info->repeat = PIXMAN_REPEAT_NORMAL;
662         }
663     }
664     else
665     {
666         info->image = pixman_image_create_solid_fill (&fill);
667     }
668 }
669
670 static void
671 image_fini (image_t *info)
672 {
673     pixman_image_unref (info->image);
674 }
675
676 static int
677 random_size (void)
678 {
679     return lcg_rand_n (ARRAY_LENGTH (sizes));
680 }
681
682 static int
683 random_color (void)
684 {
685     return lcg_rand_n (ARRAY_LENGTH (colors));
686 }
687
688 static int
689 random_format (void)
690 {
691     return lcg_rand_n (ARRAY_LENGTH (formats));
692 }
693
694 static pixman_bool_t
695 run_test (uint32_t seed)
696 {
697     image_t src, mask, dst;
698     const operator_t *op;
699     int ca;
700     int ok;
701
702     lcg_srand (seed);
703
704     image_init (&dst, random_color(), random_format(), 1);
705     image_init (&src, random_color(), random_format(), random_size());
706     image_init (&mask, random_color(), random_format(), random_size());
707
708     op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]);
709
710     ca = lcg_rand_n (3);
711
712     switch (ca)
713     {
714     case 0:
715         ok = composite_test (&dst, op, &src, NULL, FALSE, seed);
716         break;
717     case 1:
718         ok = composite_test (&dst, op, &src, &mask, FALSE, seed);
719         break;
720     case 2:
721         ok = composite_test (&dst, op, &src, &mask,
722                              mask.size? TRUE : FALSE, seed);
723         break;
724     default:
725         ok = FALSE;
726         break;
727     }
728
729     image_fini (&src);
730     image_fini (&mask);
731     image_fini (&dst);
732
733     return ok;
734 }
735
736 int
737 main (int argc, char **argv)
738 {
739 #define N_TESTS (8 * 1024 * 1024)
740     int result = 0;
741     uint32_t i, seed;
742
743     if (argc > 1)
744     {
745         char *end;
746
747         i = strtol (argv[1], &end, 0);
748
749         if (end != argv[1])
750         {
751             if (!run_test (i))
752                 return 1;
753             else
754                 return 0;
755         }
756         else
757         {
758             printf ("Usage:\n\n   %s <number>\n\n", argv[0]);
759             return -1;
760         }
761     }
762
763     if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
764         seed = get_random_seed();
765     else
766         seed = 1;
767
768 #ifdef USE_OPENMP
769 #   pragma omp parallel for default(none) shared(result, argv, seed)
770 #endif
771     for (i = 0; i <= N_TESTS; ++i)
772     {
773         if (!result && !run_test (i + seed))
774         {
775             printf ("Test 0x%08X failed.\n", seed + i);
776
777             result = seed + i;
778         }
779     }
780
781     return result;
782 }