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