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 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 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 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 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 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 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 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 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 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 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 * 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 399 absolute (int32_t i) 400 { 401 return i < 0? -i : i; 402 } 403 404 static void 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 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 * 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 * 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 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 * 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 * 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 * 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 * 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 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 * 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 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 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 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