Home | History | Annotate | Download | only in test
      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 (&region);
    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 		&region, &region, 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 		    &region, &region, x, y, width, height);
    507 	    }
    508 	}
    509 
    510 	pixman_image_set_clip_region32 (image, &region);
    511 
    512 	pixman_region32_fini (&region);
    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