stress-test.c revision a156c6bd
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 12static 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 66static 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 76static int 77get_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 105static uint32_t 106real_reader (const void *src, int size); 107 108static void *xor_ptr(const void *ptr) 109{ 110 return (void *)(((intptr_t)ptr) ^ (intptr_t)0x8000000080000000); 111} 112 113static void 114destroy (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 137static uint32_t 138real_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 155static void 156real_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 179static uint32_t 180fake_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 189static void 190fake_writer (void *src, uint32_t value, int size) 191{ 192 assert (size == 1 || size == 2 || size == 4); 193} 194 195static int32_t 196log_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 205static int32_t 206rand_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 214static int32_t 215rand_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 223typedef enum 224{ 225 DONT_CARE, 226 PREFER_ALPHA, 227 REQUIRE_ALPHA 228} alpha_preference_t; 229 230static pixman_format_code_t 231random_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 252static pixman_image_t * 253create_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 427static pixman_repeat_t repeats[] = 428{ 429 PIXMAN_REPEAT_NONE, 430 PIXMAN_REPEAT_NORMAL, 431 PIXMAN_REPEAT_REFLECT, 432 PIXMAN_REPEAT_PAD 433}; 434 435static uint32_t 436absolute (int32_t i) 437{ 438 return i < 0? -i : i; 439} 440 441static void 442set_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 618static pixman_color_t 619random_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 633static pixman_image_t * 634create_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 642static pixman_gradient_stop_t * 643create_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 671static pixman_point_fixed_t 672create_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 682static pixman_image_t * 683create_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 704static pixman_image_t * 705create_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 731static pixman_image_t * 732create_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 755static pixman_image_t * 756create_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 790static void 791random_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 799static pixman_trapezoid_t * 800create_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 823static 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 883static void 884run_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 975out: 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 984static pixman_bool_t 985get_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 1001int 1002main (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