1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "utils.h"
4 #include <sys/types.h>
5
6 #if 0
7 #define fence_malloc malloc
8 #define fence_free free
9 #define make_random_bytes malloc
10 #endif
11
12 static const pixman_format_code_t image_formats[] =
13 {
14 PIXMAN_rgba_float,
15 PIXMAN_rgb_float,
16 PIXMAN_a8r8g8b8,
17 PIXMAN_x8r8g8b8,
18 PIXMAN_r5g6b5,
19 PIXMAN_r3g3b2,
20 PIXMAN_a8,
21 PIXMAN_a8b8g8r8,
22 PIXMAN_x8b8g8r8,
23 PIXMAN_b8g8r8a8,
24 PIXMAN_b8g8r8x8,
25 PIXMAN_r8g8b8a8,
26 PIXMAN_r8g8b8x8,
27 PIXMAN_x14r6g6b6,
28 PIXMAN_r8g8b8,
29 PIXMAN_b8g8r8,
30 PIXMAN_a8r8g8b8_sRGB,
31 PIXMAN_r5g6b5,
32 PIXMAN_b5g6r5,
33 PIXMAN_x2r10g10b10,
34 PIXMAN_a2r10g10b10,
35 PIXMAN_x2b10g10r10,
36 PIXMAN_a2b10g10r10,
37 PIXMAN_a1r5g5b5,
38 PIXMAN_x1r5g5b5,
39 PIXMAN_a1b5g5r5,
40 PIXMAN_x1b5g5r5,
41 PIXMAN_a4r4g4b4,
42 PIXMAN_x4r4g4b4,
43 PIXMAN_a4b4g4r4,
44 PIXMAN_x4b4g4r4,
45 PIXMAN_a8,
46 PIXMAN_r3g3b2,
47 PIXMAN_b2g3r3,
48 PIXMAN_a2r2g2b2,
49 PIXMAN_a2b2g2r2,
50 PIXMAN_c8,
51 PIXMAN_g8,
52 PIXMAN_x4c4,
53 PIXMAN_x4g4,
54 PIXMAN_c4,
55 PIXMAN_g4,
56 PIXMAN_g1,
57 PIXMAN_x4a4,
58 PIXMAN_a4,
59 PIXMAN_r1g2b1,
60 PIXMAN_b1g2r1,
61 PIXMAN_a1r1g1b1,
62 PIXMAN_a1b1g1r1,
63 PIXMAN_a1
64 };
65
66 static pixman_filter_t filters[] =
67 {
68 PIXMAN_FILTER_NEAREST,
69 PIXMAN_FILTER_BILINEAR,
70 PIXMAN_FILTER_FAST,
71 PIXMAN_FILTER_GOOD,
72 PIXMAN_FILTER_BEST,
73 PIXMAN_FILTER_CONVOLUTION
74 };
75
76 static int
get_size(void)77 get_size (void)
78 {
79 switch (prng_rand_n (28))
80 {
81 case 0:
82 return 1;
83
84 case 1:
85 return 2;
86
87 default:
88 case 2:
89 return prng_rand_n (100);
90
91 case 4:
92 return prng_rand_n (2000) + 1000;
93
94 case 5:
95 return 65535;
96
97 case 6:
98 return 65536;
99
100 case 7:
101 return prng_rand_n (64000) + 63000;
102 }
103 }
104
105 static uint32_t
106 real_reader (const void *src, int size);
107
xor_ptr(const void * ptr)108 static void *xor_ptr(const void *ptr)
109 {
110 return (void *)(((intptr_t)ptr) ^ (intptr_t)0x8000000080000000);
111 }
112
113 static void
destroy(pixman_image_t * image,void * data)114 destroy (pixman_image_t *image, void *data)
115 {
116 if (image->type == BITS && image->bits.free_me != image->bits.bits)
117 {
118 uint32_t *bits;
119
120 if (image->bits.bits != (void *)0x01)
121 {
122 bits = image->bits.bits;
123
124 if (image->bits.rowstride < 0)
125 bits -= (- image->bits.rowstride * (image->bits.height - 1));
126
127 if (image->bits.read_func == real_reader)
128 bits = xor_ptr(bits);
129
130 fence_free (bits);
131 }
132 }
133
134 free (data);
135 }
136
137 static uint32_t
real_reader(const void * src,int size)138 real_reader (const void *src, int size)
139 {
140 src = xor_ptr(src);
141 switch (size)
142 {
143 case 1:
144 return *(uint8_t *)src;
145 case 2:
146 return *(uint16_t *)src;
147 case 4:
148 return *(uint32_t *)src;
149 default:
150 assert (0);
151 return 0; /* silence MSVC */
152 }
153 }
154
155 static void
real_writer(void * src,uint32_t value,int size)156 real_writer (void *src, uint32_t value, int size)
157 {
158 src = xor_ptr(src);
159 switch (size)
160 {
161 case 1:
162 *(uint8_t *)src = value;
163 break;
164
165 case 2:
166 *(uint16_t *)src = value;
167 break;
168
169 case 4:
170 *(uint32_t *)src = value;
171 break;
172
173 default:
174 assert (0);
175 break;
176 }
177 }
178
179 static uint32_t
fake_reader(const void * src,int size)180 fake_reader (const void *src, int size)
181 {
182 uint32_t r = prng_rand ();
183
184 assert (size == 1 || size == 2 || size == 4);
185
186 return r >> (32 - (size * 8));
187 }
188
189 static void
fake_writer(void * src,uint32_t value,int size)190 fake_writer (void *src, uint32_t value, int size)
191 {
192 assert (size == 1 || size == 2 || size == 4);
193 }
194
195 static int32_t
log_rand(void)196 log_rand (void)
197 {
198 uint32_t mask;
199
200 mask = (1 << prng_rand_n (10)) - 1;
201
202 return (prng_rand () & mask) - (mask >> 1);
203 }
204
205 static int32_t
rand_x(pixman_image_t * image)206 rand_x (pixman_image_t *image)
207 {
208 if (image->type == BITS)
209 return prng_rand_n (image->bits.width);
210 else
211 return log_rand ();
212 }
213
214 static int32_t
rand_y(pixman_image_t * image)215 rand_y (pixman_image_t *image)
216 {
217 if (image->type == BITS)
218 return prng_rand_n (image->bits.height);
219 else
220 return log_rand ();
221 }
222
223 typedef enum
224 {
225 DONT_CARE,
226 PREFER_ALPHA,
227 REQUIRE_ALPHA
228 } alpha_preference_t;
229
230 static pixman_format_code_t
random_format(alpha_preference_t alpha)231 random_format (alpha_preference_t alpha)
232 {
233 pixman_format_code_t format;
234 int n = prng_rand_n (ARRAY_LENGTH (image_formats));
235
236 if (alpha >= PREFER_ALPHA &&
237 (alpha == REQUIRE_ALPHA || prng_rand_n (4) != 0))
238 {
239 do
240 {
241 format = image_formats[n++ % ARRAY_LENGTH (image_formats)];
242 } while (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_A);
243 }
244 else
245 {
246 format = image_formats[n];
247 }
248
249 return format;
250 }
251
252 static pixman_image_t *
create_random_bits_image(alpha_preference_t alpha_preference)253 create_random_bits_image (alpha_preference_t alpha_preference)
254 {
255 pixman_format_code_t format;
256 pixman_indexed_t *indexed;
257 pixman_image_t *image;
258 int width, height, stride;
259 uint32_t *bits;
260 pixman_read_memory_func_t read_func = NULL;
261 pixman_write_memory_func_t write_func = NULL;
262 pixman_filter_t filter;
263 pixman_fixed_t *coefficients = NULL;
264 int n_coefficients = 0;
265 int align_add, align_mask;
266
267 /* format */
268 format = random_format (alpha_preference);
269 switch (PIXMAN_FORMAT_BPP (format)) {
270 case 128:
271 align_mask = 15;
272 align_add = align_mask + prng_rand_n (65);
273 break;
274 default:
275 align_mask = 3;
276 align_add = align_mask + prng_rand_n (17);
277 break;
278 }
279
280 indexed = NULL;
281 if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_COLOR)
282 {
283 indexed = malloc (sizeof (pixman_indexed_t));
284
285 initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), TRUE);
286 }
287 else if (PIXMAN_FORMAT_TYPE (format) == PIXMAN_TYPE_GRAY)
288 {
289 indexed = malloc (sizeof (pixman_indexed_t));
290
291 initialize_palette (indexed, PIXMAN_FORMAT_BPP (format), FALSE);
292 }
293 else
294 {
295 indexed = NULL;
296 }
297
298 /* size */
299 width = get_size ();
300 height = get_size ();
301
302 while ((uint64_t)width * height > 200000)
303 {
304 if (prng_rand_n(2) == 0)
305 height = 200000 / width;
306 else
307 width = 200000 / height;
308 }
309
310 if (height == 0)
311 height = 1;
312 if (width == 0)
313 width = 1;
314
315 /* bits */
316 switch (prng_rand_n (7))
317 {
318 default:
319 case 0:
320 stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
321 stride = (stride + align_add) & (~align_mask);
322 if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
323 bits = (uint32_t *)make_random_floats (height * stride);
324 else
325 bits = (uint32_t *)make_random_bytes (height * stride);
326 break;
327
328 case 1:
329 stride = 0;
330 bits = NULL;
331 break;
332
333 case 2: /* Zero-filled */
334 stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
335 stride = (stride + align_add) & (~align_mask);
336 bits = fence_malloc (height * stride);
337 if (!bits)
338 return NULL;
339 memset (bits, 0, height * stride);
340 break;
341
342 case 3: /* Filled with 0xFF */
343 stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
344 stride = (stride + align_add) & (~align_mask);
345 bits = fence_malloc (height * stride);
346 if (!bits)
347 return NULL;
348 memset (bits, 0xff, height * stride);
349 break;
350
351 case 4: /* bits is a bad pointer, has read/write functions */
352 if (PIXMAN_FORMAT_BPP (format) <= 32) {
353 stride = 232;
354 bits = (void *)0x01;
355 read_func = fake_reader;
356 write_func = fake_writer;
357 break;
358 }
359
360 case 5: /* bits is a real pointer, has read/write functions */
361 stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
362 stride = (stride + align_add) & (~align_mask);
363 bits = fence_malloc (height * stride);
364 if (!bits)
365 return NULL;
366 memset (bits, 0xff, height * stride);
367 if (PIXMAN_FORMAT_BPP (format) <= 32) {
368 bits = xor_ptr(bits);
369 read_func = real_reader;
370 write_func = real_writer;
371 }
372 break;
373
374 case 6: /* bits is a real pointer, stride is negative */
375 stride = (width * PIXMAN_FORMAT_BPP (format) + 7) / 8;
376 stride = (stride + align_add) & (~align_mask);
377 if (format == PIXMAN_rgb_float || format == PIXMAN_rgba_float)
378 bits = (uint32_t *)make_random_floats (height * stride);
379 else
380 bits = (uint32_t *)make_random_bytes (height * stride);
381 if (!bits)
382 return NULL;
383 bits += ((height - 1) * stride) / 4;
384 stride = - stride;
385 break;
386 }
387
388 /* Filter */
389 filter = filters[prng_rand_n (ARRAY_LENGTH (filters))];
390 if (filter == PIXMAN_FILTER_CONVOLUTION)
391 {
392 int width = prng_rand_n (3);
393 int height = prng_rand_n (4);
394
395 n_coefficients = width * height + 2;
396 coefficients = malloc (n_coefficients * sizeof (pixman_fixed_t));
397
398 if (coefficients)
399 {
400 int i;
401
402 for (i = 0; i < width * height; ++i)
403 coefficients[i + 2] = prng_rand();
404
405 coefficients[0] = width << 16;
406 coefficients[1] = height << 16;
407 }
408 else
409 {
410 filter = PIXMAN_FILTER_BEST;
411 }
412 }
413
414 /* Finally create the image */
415 image = pixman_image_create_bits (format, width, height, bits, stride);
416 if (!image)
417 return NULL;
418
419 pixman_image_set_indexed (image, indexed);
420 pixman_image_set_destroy_function (image, destroy, indexed);
421 pixman_image_set_accessors (image, read_func, write_func);
422 pixman_image_set_filter (image, filter, coefficients, n_coefficients);
423
424 return image;
425 }
426
427 static pixman_repeat_t repeats[] =
428 {
429 PIXMAN_REPEAT_NONE,
430 PIXMAN_REPEAT_NORMAL,
431 PIXMAN_REPEAT_REFLECT,
432 PIXMAN_REPEAT_PAD
433 };
434
435 static uint32_t
absolute(int32_t i)436 absolute (int32_t i)
437 {
438 return i < 0? -i : i;
439 }
440
441 static void
set_general_properties(pixman_image_t * image,pixman_bool_t allow_alpha_map)442 set_general_properties (pixman_image_t *image, pixman_bool_t allow_alpha_map)
443 {
444 pixman_repeat_t repeat;
445
446 /* Set properties that are generic to all images */
447
448 /* Repeat */
449 repeat = repeats[prng_rand_n (ARRAY_LENGTH (repeats))];
450 pixman_image_set_repeat (image, repeat);
451
452 /* Alpha map */
453 if (allow_alpha_map && prng_rand_n (4) == 0)
454 {
455 pixman_image_t *alpha_map;
456 int16_t x, y;
457
458 alpha_map = create_random_bits_image (DONT_CARE);
459
460 if (alpha_map)
461 {
462 set_general_properties (alpha_map, FALSE);
463
464 x = rand_x (image) - image->bits.width / 2;
465 y = rand_y (image) - image->bits.height / 2;
466
467 pixman_image_set_alpha_map (image, alpha_map, x, y);
468
469 pixman_image_unref (alpha_map);
470 }
471 }
472
473 /* Component alpha */
474 pixman_image_set_component_alpha (image, prng_rand_n (3) == 0);
475
476 /* Clip region */
477 if (prng_rand_n (8) < 2)
478 {
479 pixman_region32_t region;
480 int i, n_rects;
481
482 pixman_region32_init (®ion);
483
484 switch (prng_rand_n (12))
485 {
486 case 0:
487 n_rects = 0;
488 break;
489
490 case 1: case 2: case 3:
491 n_rects = 1;
492 break;
493
494 case 4: case 5:
495 n_rects = 2;
496 break;
497
498 case 6: case 7:
499 n_rects = 3;
500 break;
501
502 default:
503 n_rects = prng_rand_n (100);
504 break;
505 }
506
507 for (i = 0; i < n_rects; ++i)
508 {
509 uint32_t width, height;
510 int x, y;
511
512 x = log_rand();
513 y = log_rand();
514 width = absolute (log_rand ()) + 1;
515 height = absolute (log_rand ()) + 1;
516
517 pixman_region32_union_rect (
518 ®ion, ®ion, x, y, width, height);
519 }
520
521 if (image->type == BITS && prng_rand_n (8) != 0)
522 {
523 uint32_t width, height;
524 uint32_t x, y;
525 int i;
526
527 /* Also add a couple of clip rectangles inside the image
528 * so that compositing will actually take place.
529 */
530 for (i = 0; i < 5; ++i)
531 {
532 x = prng_rand_n (2 * image->bits.width) - image->bits.width;
533 y = prng_rand_n (2 * image->bits.height) - image->bits.height;
534 width = prng_rand_n (image->bits.width) - x + 10;
535 height = prng_rand_n (image->bits.height) - y + 10;
536
537 if (width + x < x)
538 width = INT32_MAX - x;
539 if (height + y < y)
540 height = INT32_MAX - y;
541
542 pixman_region32_union_rect (
543 ®ion, ®ion, x, y, width, height);
544 }
545 }
546
547 pixman_image_set_clip_region32 (image, ®ion);
548
549 pixman_region32_fini (®ion);
550 }
551
552 /* Whether source clipping is enabled */
553 pixman_image_set_source_clipping (image, !!prng_rand_n (2));
554
555 /* Client clip */
556 pixman_image_set_has_client_clip (image, !!prng_rand_n (2));
557
558 /* Transform */
559 if (prng_rand_n (5) < 2)
560 {
561 pixman_transform_t xform;
562 int i, j, k;
563 uint32_t tx, ty, sx, sy;
564 uint32_t c, s;
565
566 memset (&xform, 0, sizeof xform);
567 xform.matrix[0][0] = pixman_fixed_1;
568 xform.matrix[1][1] = pixman_fixed_1;
569 xform.matrix[2][2] = pixman_fixed_1;
570
571 for (k = 0; k < 3; ++k)
572 {
573 switch (prng_rand_n (4))
574 {
575 case 0:
576 /* rotation */
577 c = prng_rand_n (2 * 65536) - 65536;
578 s = prng_rand_n (2 * 65536) - 65536;
579 pixman_transform_rotate (&xform, NULL, c, s);
580 break;
581
582 case 1:
583 /* translation */
584 tx = prng_rand();
585 ty = prng_rand();
586 pixman_transform_translate (&xform, NULL, tx, ty);
587 break;
588
589 case 2:
590 /* scale */
591 sx = prng_rand();
592 sy = prng_rand();
593 pixman_transform_scale (&xform, NULL, sx, sy);
594 break;
595
596 case 3:
597 if (prng_rand_n (16) == 0)
598 {
599 /* random */
600 for (i = 0; i < 3; ++i)
601 for (j = 0; j < 3; ++j)
602 xform.matrix[i][j] = prng_rand();
603 break;
604 }
605 else if (prng_rand_n (16) == 0)
606 {
607 /* zero */
608 memset (&xform, 0, sizeof xform);
609 }
610 break;
611 }
612 }
613
614 pixman_image_set_transform (image, &xform);
615 }
616 }
617
618 static pixman_color_t
random_color(void)619 random_color (void)
620 {
621 pixman_color_t color =
622 {
623 prng_rand() & 0xffff,
624 prng_rand() & 0xffff,
625 prng_rand() & 0xffff,
626 prng_rand() & 0xffff,
627 };
628
629 return color;
630 }
631
632
633 static pixman_image_t *
create_random_solid_image(void)634 create_random_solid_image (void)
635 {
636 pixman_color_t color = random_color();
637 pixman_image_t *image = pixman_image_create_solid_fill (&color);
638
639 return image;
640 }
641
642 static pixman_gradient_stop_t *
create_random_stops(int * n_stops)643 create_random_stops (int *n_stops)
644 {
645 pixman_fixed_t step;
646 pixman_fixed_t s;
647 int i;
648 pixman_gradient_stop_t *stops;
649
650 *n_stops = prng_rand_n (50) + 1;
651
652 step = pixman_fixed_1 / *n_stops;
653
654 stops = malloc (*n_stops * sizeof (pixman_gradient_stop_t));
655
656 s = 0;
657 for (i = 0; i < (*n_stops) - 1; ++i)
658 {
659 stops[i].x = s;
660 stops[i].color = random_color();
661
662 s += step;
663 }
664
665 stops[*n_stops - 1].x = pixman_fixed_1;
666 stops[*n_stops - 1].color = random_color();
667
668 return stops;
669 }
670
671 static pixman_point_fixed_t
create_random_point(void)672 create_random_point (void)
673 {
674 pixman_point_fixed_t p;
675
676 p.x = log_rand ();
677 p.y = log_rand ();
678
679 return p;
680 }
681
682 static pixman_image_t *
create_random_linear_image(void)683 create_random_linear_image (void)
684 {
685 int n_stops;
686 pixman_gradient_stop_t *stops;
687 pixman_point_fixed_t p1, p2;
688 pixman_image_t *result;
689
690 stops = create_random_stops (&n_stops);
691 if (!stops)
692 return NULL;
693
694 p1 = create_random_point ();
695 p2 = create_random_point ();
696
697 result = pixman_image_create_linear_gradient (&p1, &p2, stops, n_stops);
698
699 free (stops);
700
701 return result;
702 }
703
704 static pixman_image_t *
create_random_radial_image(void)705 create_random_radial_image (void)
706 {
707 int n_stops;
708 pixman_gradient_stop_t *stops;
709 pixman_point_fixed_t inner_c, outer_c;
710 pixman_fixed_t inner_r, outer_r;
711 pixman_image_t *result;
712
713 inner_c = create_random_point();
714 outer_c = create_random_point();
715 inner_r = prng_rand();
716 outer_r = prng_rand();
717
718 stops = create_random_stops (&n_stops);
719
720 if (!stops)
721 return NULL;
722
723 result = pixman_image_create_radial_gradient (
724 &inner_c, &outer_c, inner_r, outer_r, stops, n_stops);
725
726 free (stops);
727
728 return result;
729 }
730
731 static pixman_image_t *
create_random_conical_image(void)732 create_random_conical_image (void)
733 {
734 pixman_gradient_stop_t *stops;
735 int n_stops;
736 pixman_point_fixed_t c;
737 pixman_fixed_t angle;
738 pixman_image_t *result;
739
740 c = create_random_point();
741 angle = prng_rand();
742
743 stops = create_random_stops (&n_stops);
744
745 if (!stops)
746 return NULL;
747
748 result = pixman_image_create_conical_gradient (&c, angle, stops, n_stops);
749
750 free (stops);
751
752 return result;
753 }
754
755 static pixman_image_t *
create_random_image(void)756 create_random_image (void)
757 {
758 pixman_image_t *result;
759
760 switch (prng_rand_n (5))
761 {
762 default:
763 case 0:
764 result = create_random_bits_image (DONT_CARE);
765 break;
766
767 case 1:
768 result = create_random_solid_image ();
769 break;
770
771 case 2:
772 result = create_random_linear_image ();
773 break;
774
775 case 3:
776 result = create_random_radial_image ();
777 break;
778
779 case 4:
780 result = create_random_conical_image ();
781 break;
782 }
783
784 if (result)
785 set_general_properties (result, TRUE);
786
787 return result;
788 }
789
790 static void
random_line(pixman_line_fixed_t * line,int width,int height)791 random_line (pixman_line_fixed_t *line, int width, int height)
792 {
793 line->p1.x = prng_rand_n (width) << 16;
794 line->p1.y = prng_rand_n (height) << 16;
795 line->p2.x = prng_rand_n (width) << 16;
796 line->p2.y = prng_rand_n (height) << 16;
797 }
798
799 static pixman_trapezoid_t *
create_random_trapezoids(int * n_traps,int height,int width)800 create_random_trapezoids (int *n_traps, int height, int width)
801 {
802 pixman_trapezoid_t *trapezoids;
803 int i;
804
805 *n_traps = prng_rand_n (16) + 1;
806
807 trapezoids = malloc (sizeof (pixman_trapezoid_t) * *n_traps);
808
809 for (i = 0; i < *n_traps; ++i)
810 {
811 pixman_trapezoid_t *t = &(trapezoids[i]);
812
813 t->top = prng_rand_n (height) << 16;
814 t->bottom = prng_rand_n (height) << 16;
815
816 random_line (&t->left, height, width);
817 random_line (&t->right, height, width);
818 }
819
820 return trapezoids;
821 }
822
823 static const pixman_op_t op_list[] =
824 {
825 PIXMAN_OP_SRC,
826 PIXMAN_OP_OVER,
827 PIXMAN_OP_ADD,
828 PIXMAN_OP_CLEAR,
829 PIXMAN_OP_SRC,
830 PIXMAN_OP_DST,
831 PIXMAN_OP_OVER,
832 PIXMAN_OP_OVER_REVERSE,
833 PIXMAN_OP_IN,
834 PIXMAN_OP_IN_REVERSE,
835 PIXMAN_OP_OUT,
836 PIXMAN_OP_OUT_REVERSE,
837 PIXMAN_OP_ATOP,
838 PIXMAN_OP_ATOP_REVERSE,
839 PIXMAN_OP_XOR,
840 PIXMAN_OP_ADD,
841 PIXMAN_OP_SATURATE,
842 PIXMAN_OP_DISJOINT_CLEAR,
843 PIXMAN_OP_DISJOINT_SRC,
844 PIXMAN_OP_DISJOINT_DST,
845 PIXMAN_OP_DISJOINT_OVER,
846 PIXMAN_OP_DISJOINT_OVER_REVERSE,
847 PIXMAN_OP_DISJOINT_IN,
848 PIXMAN_OP_DISJOINT_IN_REVERSE,
849 PIXMAN_OP_DISJOINT_OUT,
850 PIXMAN_OP_DISJOINT_OUT_REVERSE,
851 PIXMAN_OP_DISJOINT_ATOP,
852 PIXMAN_OP_DISJOINT_ATOP_REVERSE,
853 PIXMAN_OP_DISJOINT_XOR,
854 PIXMAN_OP_CONJOINT_CLEAR,
855 PIXMAN_OP_CONJOINT_SRC,
856 PIXMAN_OP_CONJOINT_DST,
857 PIXMAN_OP_CONJOINT_OVER,
858 PIXMAN_OP_CONJOINT_OVER_REVERSE,
859 PIXMAN_OP_CONJOINT_IN,
860 PIXMAN_OP_CONJOINT_IN_REVERSE,
861 PIXMAN_OP_CONJOINT_OUT,
862 PIXMAN_OP_CONJOINT_OUT_REVERSE,
863 PIXMAN_OP_CONJOINT_ATOP,
864 PIXMAN_OP_CONJOINT_ATOP_REVERSE,
865 PIXMAN_OP_CONJOINT_XOR,
866 PIXMAN_OP_MULTIPLY,
867 PIXMAN_OP_SCREEN,
868 PIXMAN_OP_OVERLAY,
869 PIXMAN_OP_DARKEN,
870 PIXMAN_OP_LIGHTEN,
871 PIXMAN_OP_COLOR_DODGE,
872 PIXMAN_OP_COLOR_BURN,
873 PIXMAN_OP_HARD_LIGHT,
874 PIXMAN_OP_DIFFERENCE,
875 PIXMAN_OP_EXCLUSION,
876 PIXMAN_OP_SOFT_LIGHT,
877 PIXMAN_OP_HSL_HUE,
878 PIXMAN_OP_HSL_SATURATION,
879 PIXMAN_OP_HSL_COLOR,
880 PIXMAN_OP_HSL_LUMINOSITY,
881 };
882
883 static void
run_test(uint32_t seed,pixman_bool_t verbose,uint32_t mod)884 run_test (uint32_t seed, pixman_bool_t verbose, uint32_t mod)
885 {
886 pixman_image_t *source, *mask, *dest;
887 pixman_op_t op;
888
889 if (verbose)
890 {
891 if (mod == 0 || (seed % mod) == 0)
892 printf ("Seed 0x%08x\n", seed);
893 }
894
895 source = mask = dest = NULL;
896
897 prng_srand (seed);
898
899 if (prng_rand_n (8) == 0)
900 {
901 int n_traps;
902 pixman_trapezoid_t *trapezoids;
903 int p = prng_rand_n (3);
904
905 if (p == 0)
906 dest = create_random_bits_image (DONT_CARE);
907 else
908 dest = create_random_bits_image (REQUIRE_ALPHA);
909
910 if (!dest)
911 goto out;
912
913 set_general_properties (dest, TRUE);
914
915 if (!(trapezoids = create_random_trapezoids (
916 &n_traps, dest->bits.width, dest->bits.height)))
917 {
918 goto out;
919 }
920
921 switch (p)
922 {
923 case 0:
924 source = create_random_image ();
925
926 if (source)
927 {
928 op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))];
929
930 pixman_composite_trapezoids (
931 op, source, dest,
932 random_format (REQUIRE_ALPHA),
933 rand_x (source), rand_y (source),
934 rand_x (dest), rand_y (dest),
935 n_traps, trapezoids);
936 }
937 break;
938
939 case 1:
940 pixman_rasterize_trapezoid (
941 dest, &trapezoids[prng_rand_n (n_traps)],
942 rand_x (dest), rand_y (dest));
943 break;
944
945 case 2:
946 pixman_add_trapezoids (
947 dest, rand_x (dest), rand_y (dest), n_traps, trapezoids);
948 break;
949 }
950
951 free (trapezoids);
952 }
953 else
954 {
955 dest = create_random_bits_image (DONT_CARE);
956 source = create_random_image ();
957 mask = create_random_image ();
958
959 if (source && mask && dest)
960 {
961 set_general_properties (dest, TRUE);
962
963 op = op_list [prng_rand_n (ARRAY_LENGTH (op_list))];
964
965 pixman_image_composite32 (op,
966 source, mask, dest,
967 rand_x (source), rand_y (source),
968 rand_x (mask), rand_y (mask),
969 0, 0,
970 dest->bits.width,
971 dest->bits.height);
972 }
973 }
974
975 out:
976 if (source)
977 pixman_image_unref (source);
978 if (mask)
979 pixman_image_unref (mask);
980 if (dest)
981 pixman_image_unref (dest);
982 }
983
984 static pixman_bool_t
get_int(char * s,uint32_t * i)985 get_int (char *s, uint32_t *i)
986 {
987 char *end;
988 int p;
989
990 p = strtol (s, &end, 0);
991
992 if (end != s && *end == 0)
993 {
994 *i = p;
995 return TRUE;
996 }
997
998 return FALSE;
999 }
1000
1001 int
main(int argc,char ** argv)1002 main (int argc, char **argv)
1003 {
1004 int verbose = FALSE;
1005 uint32_t seed = 1;
1006 uint32_t n_tests = 8000;
1007 uint32_t mod = 0;
1008 pixman_bool_t use_threads = TRUE;
1009 int32_t i;
1010
1011 pixman_disable_out_of_bounds_workaround ();
1012
1013 enable_divbyzero_exceptions();
1014
1015 if (getenv ("VERBOSE") != NULL)
1016 verbose = TRUE;
1017
1018 for (i = 1; i < argc; ++i)
1019 {
1020 if (strcmp (argv[i], "-v") == 0)
1021 {
1022 verbose = TRUE;
1023
1024 if (i + 1 < argc)
1025 {
1026 get_int (argv[i + 1], &mod);
1027 i++;
1028 }
1029 }
1030 else if (strcmp (argv[i], "-s") == 0 && i + 1 < argc)
1031 {
1032 get_int (argv[i + 1], &seed);
1033 use_threads = FALSE;
1034 i++;
1035 }
1036 else if (strcmp (argv[i], "-n") == 0 && i + 1 < argc)
1037 {
1038 get_int (argv[i + 1], &n_tests);
1039 i++;
1040 }
1041 else
1042 {
1043 if (strcmp (argv[i], "-h") != 0)
1044 printf ("Unknown option '%s'\n\n", argv[i]);
1045
1046 printf ("Options:\n\n"
1047 "-n <number> Number of tests to run\n"
1048 "-s <seed> Seed of first test (ignored if PIXMAN_RANDOMIZE_TESTS is set)\n"
1049 "-v Print out seeds\n"
1050 "-v <n> Print out every n'th seed\n\n");
1051
1052 exit (-1);
1053 }
1054 }
1055
1056 if (getenv ("PIXMAN_RANDOMIZE_TESTS"))
1057 {
1058 seed = get_random_seed();
1059 printf ("First seed: 0x%08x\n", seed);
1060 }
1061
1062 if (use_threads)
1063 {
1064 #ifdef USE_OPENMP
1065 # pragma omp parallel for default(none) shared(verbose, n_tests, mod, seed)
1066 #endif
1067 for (i = 0; i < (int32_t)n_tests; ++i)
1068 run_test (seed + i, verbose, mod);
1069 }
1070 else
1071 {
1072 for (i = 0; i < (int32_t)n_tests; ++i)
1073 run_test (seed + i, verbose, mod);
1074 }
1075
1076 return 0;
1077 }
1078