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