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