Home | History | Annotate | Download | only in test
      1 #define _GNU_SOURCE
      2 
      3 #include "utils.h"
      4 #include <math.h>
      5 #include <signal.h>
      6 #include <stdlib.h>
      7 
      8 #ifdef HAVE_GETTIMEOFDAY
      9 #include <sys/time.h>
     10 #else
     11 #include <time.h>
     12 #endif
     13 
     14 #ifdef HAVE_UNISTD_H
     15 #include <unistd.h>
     16 #endif
     17 
     18 #ifdef HAVE_SYS_MMAN_H
     19 #include <sys/mman.h>
     20 #endif
     21 
     22 #ifdef HAVE_FENV_H
     23 #include <fenv.h>
     24 #endif
     25 
     26 #ifdef HAVE_LIBPNG
     27 #include <png.h>
     28 #endif
     29 
     30 /* Random number generator state
     31  */
     32 
     33 prng_t prng_state_data;
     34 prng_t *prng_state;
     35 
     36 /*----------------------------------------------------------------------------*\
     37  *  CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
     38  *
     39  *  This program generates the CRC-32 values for the files named in the
     40  *  command-line arguments.  These are the same CRC-32 values used by GZIP,
     41  *  PKZIP, and ZMODEM.  The Crc32_ComputeBuf () can also be detached and
     42  *  used independently.
     43  *
     44  *  THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
     45  *
     46  *  Based on the byte-oriented implementation "File Verification Using CRC"
     47  *  by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
     48  *
     49  *  v1.0.0: original release.
     50  *  v1.0.1: fixed printf formats.
     51  *  v1.0.2: fixed something else.
     52  *  v1.0.3: replaced CRC constant table by generator function.
     53  *  v1.0.4: reformatted code, made ANSI C.  1994-12-05.
     54  *  v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
     55 \*----------------------------------------------------------------------------*/
     56 
     57 /*----------------------------------------------------------------------------*\
     58  *  NAME:
     59  *     Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
     60  *  DESCRIPTION:
     61  *     Computes or accumulates the CRC-32 value for a memory buffer.
     62  *     The 'inCrc32' gives a previously accumulated CRC-32 value to allow
     63  *     a CRC to be generated for multiple sequential buffer-fuls of data.
     64  *     The 'inCrc32' for the first buffer must be zero.
     65  *  ARGUMENTS:
     66  *     inCrc32 - accumulated CRC-32 value, must be 0 on first call
     67  *     buf     - buffer to compute CRC-32 value for
     68  *     bufLen  - number of bytes in buffer
     69  *  RETURNS:
     70  *     crc32 - computed CRC-32 value
     71  *  ERRORS:
     72  *     (no errors are possible)
     73 \*----------------------------------------------------------------------------*/
     74 
     75 uint32_t
     76 compute_crc32 (uint32_t    in_crc32,
     77 	       const void *buf,
     78 	       size_t      buf_len)
     79 {
     80     static const uint32_t crc_table[256] = {
     81 	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
     82 	0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
     83 	0x09B64C2B, 0x7EB17CBD,	0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
     84 	0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
     85 	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,	0x14015C4F, 0x63066CD9,
     86 	0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
     87 	0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
     88 	0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
     89 	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
     90 	0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
     91 	0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
     92 	0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
     93 	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
     94 	0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
     95 	0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
     96 	0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
     97 	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
     98 	0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
     99 	0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
    100 	0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
    101 	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
    102 	0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
    103 	0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
    104 	0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
    105 	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
    106 	0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
    107 	0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
    108 	0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
    109 	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
    110 	0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
    111 	0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
    112 	0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
    113 	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
    114 	0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
    115 	0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
    116 	0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
    117 	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
    118 	0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
    119 	0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
    120 	0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
    121 	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
    122 	0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
    123 	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
    124     };
    125 
    126     uint32_t              crc32;
    127     unsigned char *       byte_buf;
    128     size_t                i;
    129 
    130     /* accumulate crc32 for buffer */
    131     crc32 = in_crc32 ^ 0xFFFFFFFF;
    132     byte_buf = (unsigned char*) buf;
    133 
    134     for (i = 0; i < buf_len; i++)
    135 	crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
    136 
    137     return (crc32 ^ 0xFFFFFFFF);
    138 }
    139 
    140 static uint32_t
    141 compute_crc32_for_image_internal (uint32_t        crc32,
    142 				  pixman_image_t *img,
    143 				  pixman_bool_t	  remove_alpha,
    144 				  pixman_bool_t	  remove_rgb)
    145 {
    146     pixman_format_code_t fmt = pixman_image_get_format (img);
    147     uint32_t *data = pixman_image_get_data (img);
    148     int stride = pixman_image_get_stride (img);
    149     int height = pixman_image_get_height (img);
    150     uint32_t mask = 0xffffffff;
    151     int i;
    152 
    153     /* mask unused 'x' part */
    154     if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
    155 	PIXMAN_FORMAT_DEPTH (fmt) != 0)
    156     {
    157 	uint32_t m = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
    158 
    159 	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
    160 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
    161 	{
    162 	    m <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
    163 	}
    164 
    165 	mask &= m;
    166     }
    167 
    168     /* mask alpha channel */
    169     if (remove_alpha && PIXMAN_FORMAT_A (fmt))
    170     {
    171 	uint32_t m;
    172 
    173 	if (PIXMAN_FORMAT_BPP (fmt) == 32)
    174 	    m = 0xffffffff;
    175 	else
    176 	    m = (1 << PIXMAN_FORMAT_BPP (fmt)) - 1;
    177 
    178 	m >>= PIXMAN_FORMAT_A (fmt);
    179 
    180 	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
    181 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA ||
    182 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_A)
    183 	{
    184 	    /* Alpha is at the bottom of the pixel */
    185 	    m <<= PIXMAN_FORMAT_A (fmt);
    186 	}
    187 
    188 	mask &= m;
    189     }
    190 
    191     /* mask rgb channels */
    192     if (remove_rgb && PIXMAN_FORMAT_RGB (fmt))
    193     {
    194 	uint32_t m = ((uint32_t)~0) >> (32 - PIXMAN_FORMAT_BPP (fmt));
    195 	uint32_t size = PIXMAN_FORMAT_R (fmt) + PIXMAN_FORMAT_G (fmt) + PIXMAN_FORMAT_B (fmt);
    196 
    197 	m &= ~((1 << size) - 1);
    198 
    199 	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
    200 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
    201 	{
    202 	    /* RGB channels are at the top of the pixel */
    203 	    m >>= size;
    204 	}
    205 
    206 	mask &= m;
    207     }
    208 
    209     for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++)
    210 	mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
    211 
    212     for (i = 0; i < stride * height / 4; i++)
    213 	data[i] &= mask;
    214 
    215     /* swap endiannes in order to provide identical results on both big
    216      * and litte endian systems
    217      */
    218     image_endian_swap (img);
    219 
    220     return compute_crc32 (crc32, data, stride * height);
    221 }
    222 
    223 uint32_t
    224 compute_crc32_for_image (uint32_t        crc32,
    225 			 pixman_image_t *img)
    226 {
    227     if (img->common.alpha_map)
    228     {
    229 	crc32 = compute_crc32_for_image_internal (crc32, img, TRUE, FALSE);
    230 	crc32 = compute_crc32_for_image_internal (
    231 	    crc32, (pixman_image_t *)img->common.alpha_map, FALSE, TRUE);
    232     }
    233     else
    234     {
    235 	crc32 = compute_crc32_for_image_internal (crc32, img, FALSE, FALSE);
    236     }
    237 
    238     return crc32;
    239 }
    240 
    241 /* perform endian conversion of pixel data
    242  */
    243 void
    244 image_endian_swap (pixman_image_t *img)
    245 {
    246     int stride = pixman_image_get_stride (img);
    247     uint32_t *data = pixman_image_get_data (img);
    248     int height = pixman_image_get_height (img);
    249     int bpp = PIXMAN_FORMAT_BPP (pixman_image_get_format (img));
    250     int i, j;
    251 
    252     /* swap bytes only on big endian systems */
    253     if (is_little_endian())
    254 	return;
    255 
    256     if (bpp == 8)
    257 	return;
    258 
    259     for (i = 0; i < height; i++)
    260     {
    261 	uint8_t *line_data = (uint8_t *)data + stride * i;
    262 
    263 	switch (bpp)
    264 	{
    265 	case 1:
    266 	    for (j = 0; j < stride; j++)
    267 	    {
    268 		line_data[j] =
    269 		    ((line_data[j] & 0x80) >> 7) |
    270 		    ((line_data[j] & 0x40) >> 5) |
    271 		    ((line_data[j] & 0x20) >> 3) |
    272 		    ((line_data[j] & 0x10) >> 1) |
    273 		    ((line_data[j] & 0x08) << 1) |
    274 		    ((line_data[j] & 0x04) << 3) |
    275 		    ((line_data[j] & 0x02) << 5) |
    276 		    ((line_data[j] & 0x01) << 7);
    277 	    }
    278 	    break;
    279 	case 4:
    280 	    for (j = 0; j < stride; j++)
    281 	    {
    282 		line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
    283 	    }
    284 	    break;
    285 	case 16:
    286 	    for (j = 0; j + 2 <= stride; j += 2)
    287 	    {
    288 		char t1 = line_data[j + 0];
    289 		char t2 = line_data[j + 1];
    290 
    291 		line_data[j + 1] = t1;
    292 		line_data[j + 0] = t2;
    293 	    }
    294 	    break;
    295 	case 24:
    296 	    for (j = 0; j + 3 <= stride; j += 3)
    297 	    {
    298 		char t1 = line_data[j + 0];
    299 		char t2 = line_data[j + 1];
    300 		char t3 = line_data[j + 2];
    301 
    302 		line_data[j + 2] = t1;
    303 		line_data[j + 1] = t2;
    304 		line_data[j + 0] = t3;
    305 	    }
    306 	    break;
    307 	case 32:
    308 	    for (j = 0; j + 4 <= stride; j += 4)
    309 	    {
    310 		char t1 = line_data[j + 0];
    311 		char t2 = line_data[j + 1];
    312 		char t3 = line_data[j + 2];
    313 		char t4 = line_data[j + 3];
    314 
    315 		line_data[j + 3] = t1;
    316 		line_data[j + 2] = t2;
    317 		line_data[j + 1] = t3;
    318 		line_data[j + 0] = t4;
    319 	    }
    320 	    break;
    321 	default:
    322 	    assert (FALSE);
    323 	    break;
    324 	}
    325     }
    326 }
    327 
    328 #define N_LEADING_PROTECTED	10
    329 #define N_TRAILING_PROTECTED	10
    330 
    331 typedef struct
    332 {
    333     void *addr;
    334     uint32_t len;
    335     uint8_t *trailing;
    336     int n_bytes;
    337 } info_t;
    338 
    339 #if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE) && defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
    340 
    341 /* This is apparently necessary on at least OS X */
    342 #ifndef MAP_ANONYMOUS
    343 #define MAP_ANONYMOUS MAP_ANON
    344 #endif
    345 
    346 void *
    347 fence_malloc (int64_t len)
    348 {
    349     unsigned long page_size = getpagesize();
    350     unsigned long page_mask = page_size - 1;
    351     uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
    352     uint32_t n_bytes =
    353 	(page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
    354 	 n_payload_bytes) & ~page_mask;
    355     uint8_t *initial_page;
    356     uint8_t *leading_protected;
    357     uint8_t *trailing_protected;
    358     uint8_t *payload;
    359     uint8_t *addr;
    360 
    361     if (len < 0)
    362 	abort();
    363 
    364     addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
    365 		 -1, 0);
    366 
    367     if (addr == MAP_FAILED)
    368     {
    369 	printf ("mmap failed on %lld %u\n", (long long int)len, n_bytes);
    370 	return NULL;
    371     }
    372 
    373     initial_page = (uint8_t *)(((uintptr_t)addr + page_mask) & ~page_mask);
    374     leading_protected = initial_page + page_size;
    375     payload = leading_protected + N_LEADING_PROTECTED * page_size;
    376     trailing_protected = payload + n_payload_bytes;
    377 
    378     ((info_t *)initial_page)->addr = addr;
    379     ((info_t *)initial_page)->len = len;
    380     ((info_t *)initial_page)->trailing = trailing_protected;
    381     ((info_t *)initial_page)->n_bytes = n_bytes;
    382 
    383     if ((mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
    384 		  PROT_NONE) == -1) ||
    385 	(mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
    386 		  PROT_NONE) == -1))
    387     {
    388 	munmap (addr, n_bytes);
    389 	return NULL;
    390     }
    391 
    392     return payload;
    393 }
    394 
    395 void
    396 fence_free (void *data)
    397 {
    398     uint32_t page_size = getpagesize();
    399     uint8_t *payload = data;
    400     uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
    401     uint8_t *initial_page = leading_protected - page_size;
    402     info_t *info = (info_t *)initial_page;
    403 
    404     munmap (info->addr, info->n_bytes);
    405 }
    406 
    407 #else
    408 
    409 void *
    410 fence_malloc (int64_t len)
    411 {
    412     return malloc (len);
    413 }
    414 
    415 void
    416 fence_free (void *data)
    417 {
    418     free (data);
    419 }
    420 
    421 #endif
    422 
    423 uint8_t *
    424 make_random_bytes (int n_bytes)
    425 {
    426     uint8_t *bytes = fence_malloc (n_bytes);
    427 
    428     if (!bytes)
    429 	return NULL;
    430 
    431     prng_randmemset (bytes, n_bytes, 0);
    432 
    433     return bytes;
    434 }
    435 
    436 void
    437 a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels)
    438 {
    439     uint8_t *dst8 = (uint8_t *)dst;
    440     int i;
    441 
    442     for (i = 0; i < n_pixels; ++i)
    443     {
    444 	uint32_t p = src[i];
    445 	uint8_t a, r, g, b;
    446 
    447 	a = (p & 0xff000000) >> 24;
    448 	r = (p & 0x00ff0000) >> 16;
    449 	g = (p & 0x0000ff00) >> 8;
    450 	b = (p & 0x000000ff) >> 0;
    451 
    452 	if (a != 0)
    453 	{
    454 #define DIVIDE(c, a)							\
    455 	    do								\
    456 	    {								\
    457 		int t = ((c) * 255) / a;				\
    458 		(c) = t < 0? 0 : t > 255? 255 : t;			\
    459 	    } while (0)
    460 
    461 	    DIVIDE (r, a);
    462 	    DIVIDE (g, a);
    463 	    DIVIDE (b, a);
    464 	}
    465 
    466 	*dst8++ = r;
    467 	*dst8++ = g;
    468 	*dst8++ = b;
    469 	*dst8++ = a;
    470     }
    471 }
    472 
    473 #ifdef HAVE_LIBPNG
    474 
    475 pixman_bool_t
    476 write_png (pixman_image_t *image, const char *filename)
    477 {
    478     int width = pixman_image_get_width (image);
    479     int height = pixman_image_get_height (image);
    480     int stride = width * 4;
    481     uint32_t *data = malloc (height * stride);
    482     pixman_image_t *copy;
    483     png_struct *write_struct;
    484     png_info *info_struct;
    485     pixman_bool_t result = FALSE;
    486     FILE *f = fopen (filename, "wb");
    487     png_bytep *row_pointers;
    488     int i;
    489 
    490     if (!f)
    491 	return FALSE;
    492 
    493     row_pointers = malloc (height * sizeof (png_bytep));
    494 
    495     copy = pixman_image_create_bits (
    496 	PIXMAN_a8r8g8b8, width, height, data, stride);
    497 
    498     pixman_image_composite32 (
    499 	PIXMAN_OP_SRC, image, NULL, copy, 0, 0, 0, 0, 0, 0, width, height);
    500 
    501     a8r8g8b8_to_rgba_np (data, data, height * width);
    502 
    503     for (i = 0; i < height; ++i)
    504 	row_pointers[i] = (png_bytep)(data + i * width);
    505 
    506     if (!(write_struct = png_create_write_struct (
    507 	      PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
    508 	goto out1;
    509 
    510     if (!(info_struct = png_create_info_struct (write_struct)))
    511 	goto out2;
    512 
    513     png_init_io (write_struct, f);
    514 
    515     png_set_IHDR (write_struct, info_struct, width, height,
    516 		  8, PNG_COLOR_TYPE_RGB_ALPHA,
    517 		  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
    518 		  PNG_FILTER_TYPE_BASE);
    519 
    520     png_write_info (write_struct, info_struct);
    521 
    522     png_write_image (write_struct, row_pointers);
    523 
    524     png_write_end (write_struct, NULL);
    525 
    526     result = TRUE;
    527 
    528 out2:
    529     png_destroy_write_struct (&write_struct, &info_struct);
    530 
    531 out1:
    532     if (fclose (f) != 0)
    533 	result = FALSE;
    534 
    535     pixman_image_unref (copy);
    536     free (row_pointers);
    537     free (data);
    538     return result;
    539 }
    540 
    541 #else /* no libpng */
    542 
    543 pixman_bool_t
    544 write_png (pixman_image_t *image, const char *filename)
    545 {
    546     return FALSE;
    547 }
    548 
    549 #endif
    550 
    551 static void
    552 color8_to_color16 (uint32_t color8, pixman_color_t *color16)
    553 {
    554     color16->alpha = ((color8 & 0xff000000) >> 24);
    555     color16->red =   ((color8 & 0x00ff0000) >> 16);
    556     color16->green = ((color8 & 0x0000ff00) >> 8);
    557     color16->blue =  ((color8 & 0x000000ff) >> 0);
    558 
    559     color16->alpha |= color16->alpha << 8;
    560     color16->red   |= color16->red << 8;
    561     color16->blue  |= color16->blue << 8;
    562     color16->green |= color16->green << 8;
    563 }
    564 
    565 void
    566 draw_checkerboard (pixman_image_t *image,
    567 		   int check_size,
    568 		   uint32_t color1, uint32_t color2)
    569 {
    570     pixman_color_t check1, check2;
    571     pixman_image_t *c1, *c2;
    572     int n_checks_x, n_checks_y;
    573     int i, j;
    574 
    575     color8_to_color16 (color1, &check1);
    576     color8_to_color16 (color2, &check2);
    577 
    578     c1 = pixman_image_create_solid_fill (&check1);
    579     c2 = pixman_image_create_solid_fill (&check2);
    580 
    581     n_checks_x = (
    582 	pixman_image_get_width (image) + check_size - 1) / check_size;
    583     n_checks_y = (
    584 	pixman_image_get_height (image) + check_size - 1) / check_size;
    585 
    586     for (j = 0; j < n_checks_y; j++)
    587     {
    588 	for (i = 0; i < n_checks_x; i++)
    589 	{
    590 	    pixman_image_t *src;
    591 
    592 	    if (((i ^ j) & 1))
    593 		src = c1;
    594 	    else
    595 		src = c2;
    596 
    597 	    pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image,
    598 				      0, 0, 0, 0,
    599 				      i * check_size, j * check_size,
    600 				      check_size, check_size);
    601 	}
    602     }
    603 }
    604 
    605 /*
    606  * A function, which can be used as a core part of the test programs,
    607  * intended to detect various problems with the help of fuzzing input
    608  * to pixman API (according to some templates, aka "smart" fuzzing).
    609  * Some general information about such testing can be found here:
    610  * http://en.wikipedia.org/wiki/Fuzz_testing
    611  *
    612  * It may help detecting:
    613  *  - crashes on bad handling of valid or reasonably invalid input to
    614  *    pixman API.
    615  *  - deviations from the behavior of older pixman releases.
    616  *  - deviations from the behavior of the same pixman release, but
    617  *    configured in a different way (for example with SIMD optimizations
    618  *    disabled), or running on a different OS or hardware.
    619  *
    620  * The test is performed by calling a callback function a huge number
    621  * of times. The callback function is expected to run some snippet of
    622  * pixman code with pseudorandom variations to the data feeded to
    623  * pixman API. A result of running each callback function should be
    624  * some deterministic value which depends on test number (test number
    625  * can be used as a seed for PRNG). When 'verbose' argument is nonzero,
    626  * callback function is expected to print to stdout some information
    627  * about what it does.
    628  *
    629  * Return values from many small tests are accumulated together and
    630  * used as final checksum, which can be compared to some expected
    631  * value. Running the tests not individually, but in a batch helps
    632  * to reduce process start overhead and also allows to parallelize
    633  * testing and utilize multiple CPU cores.
    634  *
    635  * The resulting executable can be run without any arguments. In
    636  * this case it runs a batch of tests starting from 1 and up to
    637  * 'default_number_of_iterations'. The resulting checksum is
    638  * compared with 'expected_checksum' and FAIL or PASS verdict
    639  * depends on the result of this comparison.
    640  *
    641  * If the executable is run with 2 numbers provided as command line
    642  * arguments, they specify the starting and ending numbers for a test
    643  * batch.
    644  *
    645  * If the executable is run with only one number provided as a command
    646  * line argument, then this number is used to call the callback function
    647  * once, and also with verbose flag set.
    648  */
    649 int
    650 fuzzer_test_main (const char *test_name,
    651 		  int         default_number_of_iterations,
    652 		  uint32_t    expected_checksum,
    653 		  uint32_t    (*test_function)(int testnum, int verbose),
    654 		  int         argc,
    655 		  const char *argv[])
    656 {
    657     int i, n1 = 1, n2 = 0;
    658     uint32_t checksum = 0;
    659     int verbose = getenv ("VERBOSE") != NULL;
    660 
    661     if (argc >= 3)
    662     {
    663 	n1 = atoi (argv[1]);
    664 	n2 = atoi (argv[2]);
    665 	if (n2 < n1)
    666 	{
    667 	    printf ("invalid test range\n");
    668 	    return 1;
    669 	}
    670     }
    671     else if (argc >= 2)
    672     {
    673 	n2 = atoi (argv[1]);
    674 	checksum = test_function (n2, 1);
    675 	printf ("%d: checksum=%08X\n", n2, checksum);
    676 	return 0;
    677     }
    678     else
    679     {
    680 	n1 = 1;
    681 	n2 = default_number_of_iterations;
    682     }
    683 
    684 #ifdef USE_OPENMP
    685     #pragma omp parallel for reduction(+:checksum) default(none) \
    686 					shared(n1, n2, test_function, verbose)
    687 #endif
    688     for (i = n1; i <= n2; i++)
    689     {
    690 	uint32_t crc = test_function (i, 0);
    691 	if (verbose)
    692 	    printf ("%d: %08X\n", i, crc);
    693 	checksum += crc;
    694     }
    695 
    696     if (n1 == 1 && n2 == default_number_of_iterations)
    697     {
    698 	if (checksum == expected_checksum)
    699 	{
    700 	    printf ("%s test passed (checksum=%08X)\n",
    701 		    test_name, checksum);
    702 	}
    703 	else
    704 	{
    705 	    printf ("%s test failed! (checksum=%08X, expected %08X)\n",
    706 		    test_name, checksum, expected_checksum);
    707 	    return 1;
    708 	}
    709     }
    710     else
    711     {
    712 	printf ("%d-%d: checksum=%08X\n", n1, n2, checksum);
    713     }
    714 
    715     return 0;
    716 }
    717 
    718 /* Try to obtain current time in seconds */
    719 double
    720 gettime (void)
    721 {
    722 #ifdef HAVE_GETTIMEOFDAY
    723     struct timeval tv;
    724 
    725     gettimeofday (&tv, NULL);
    726     return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
    727 #else
    728     return (double)clock() / (double)CLOCKS_PER_SEC;
    729 #endif
    730 }
    731 
    732 uint32_t
    733 get_random_seed (void)
    734 {
    735     union { double d; uint32_t u32; } t;
    736     t.d = gettime();
    737     prng_srand (t.u32);
    738 
    739     return prng_rand ();
    740 }
    741 
    742 #ifdef HAVE_SIGACTION
    743 #ifdef HAVE_ALARM
    744 static const char *global_msg;
    745 
    746 static void
    747 on_alarm (int signo)
    748 {
    749     printf ("%s\n", global_msg);
    750     exit (1);
    751 }
    752 #endif
    753 #endif
    754 
    755 void
    756 fail_after (int seconds, const char *msg)
    757 {
    758 #ifdef HAVE_SIGACTION
    759 #ifdef HAVE_ALARM
    760     struct sigaction action;
    761 
    762     global_msg = msg;
    763 
    764     memset (&action, 0, sizeof (action));
    765     action.sa_handler = on_alarm;
    766 
    767     alarm (seconds);
    768 
    769     sigaction (SIGALRM, &action, NULL);
    770 #endif
    771 #endif
    772 }
    773 
    774 void
    775 enable_divbyzero_exceptions (void)
    776 {
    777 #ifdef HAVE_FENV_H
    778 #ifdef HAVE_FEENABLEEXCEPT
    779     feenableexcept (FE_DIVBYZERO);
    780 #endif
    781 #endif
    782 }
    783 
    784 void *
    785 aligned_malloc (size_t align, size_t size)
    786 {
    787     void *result;
    788 
    789 #ifdef HAVE_POSIX_MEMALIGN
    790     if (posix_memalign (&result, align, size) != 0)
    791       result = NULL;
    792 #else
    793     result = malloc (size);
    794 #endif
    795 
    796     return result;
    797 }
    798 
    799 #define CONVERT_15(c, is_rgb)						\
    800     (is_rgb?								\
    801      ((((c) >> 3) & 0x001f) |						\
    802       (((c) >> 6) & 0x03e0) |						\
    803       (((c) >> 9) & 0x7c00)) :						\
    804      (((((c) >> 16) & 0xff) * 153 +					\
    805        (((c) >>  8) & 0xff) * 301 +					\
    806        (((c)      ) & 0xff) * 58) >> 2))
    807 
    808 double
    809 convert_srgb_to_linear (double c)
    810 {
    811     if (c <= 0.04045)
    812         return c / 12.92;
    813     else
    814         return pow ((c + 0.055) / 1.055, 2.4);
    815 }
    816 
    817 double
    818 convert_linear_to_srgb (double c)
    819 {
    820     if (c <= 0.0031308)
    821         return c * 12.92;
    822     else
    823         return 1.055 * pow (c, 1.0/2.4) - 0.055;
    824 }
    825 
    826 void
    827 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
    828 {
    829     int i;
    830     uint32_t mask = (1 << depth) - 1;
    831 
    832     for (i = 0; i < 32768; ++i)
    833 	palette->ent[i] = prng_rand() & mask;
    834 
    835     memset (palette->rgba, 0, sizeof (palette->rgba));
    836 
    837     for (i = 0; i < mask + 1; ++i)
    838     {
    839 	uint32_t rgba24;
    840  	pixman_bool_t retry;
    841 	uint32_t i15;
    842 
    843 	/* We filled the rgb->index map with random numbers, but we
    844 	 * do need the ability to round trip, that is if some indexed
    845 	 * color expands to an argb24, then the 15 bit version of that
    846 	 * color must map back to the index. Anything else, we don't
    847 	 * care about too much.
    848 	 */
    849 	do
    850 	{
    851 	    uint32_t old_idx;
    852 
    853 	    rgba24 = prng_rand();
    854 	    i15 = CONVERT_15 (rgba24, is_rgb);
    855 
    856 	    old_idx = palette->ent[i15];
    857 	    if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15)
    858 		retry = 1;
    859 	    else
    860 		retry = 0;
    861 	} while (retry);
    862 
    863 	palette->rgba[i] = rgba24;
    864 	palette->ent[i15] = i;
    865     }
    866 
    867     for (i = 0; i < mask + 1; ++i)
    868     {
    869 	assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
    870     }
    871 }
    872 
    873 const char *
    874 operator_name (pixman_op_t op)
    875 {
    876     switch (op)
    877     {
    878     case PIXMAN_OP_CLEAR: return "PIXMAN_OP_CLEAR";
    879     case PIXMAN_OP_SRC: return "PIXMAN_OP_SRC";
    880     case PIXMAN_OP_DST: return "PIXMAN_OP_DST";
    881     case PIXMAN_OP_OVER: return "PIXMAN_OP_OVER";
    882     case PIXMAN_OP_OVER_REVERSE: return "PIXMAN_OP_OVER_REVERSE";
    883     case PIXMAN_OP_IN: return "PIXMAN_OP_IN";
    884     case PIXMAN_OP_IN_REVERSE: return "PIXMAN_OP_IN_REVERSE";
    885     case PIXMAN_OP_OUT: return "PIXMAN_OP_OUT";
    886     case PIXMAN_OP_OUT_REVERSE: return "PIXMAN_OP_OUT_REVERSE";
    887     case PIXMAN_OP_ATOP: return "PIXMAN_OP_ATOP";
    888     case PIXMAN_OP_ATOP_REVERSE: return "PIXMAN_OP_ATOP_REVERSE";
    889     case PIXMAN_OP_XOR: return "PIXMAN_OP_XOR";
    890     case PIXMAN_OP_ADD: return "PIXMAN_OP_ADD";
    891     case PIXMAN_OP_SATURATE: return "PIXMAN_OP_SATURATE";
    892 
    893     case PIXMAN_OP_DISJOINT_CLEAR: return "PIXMAN_OP_DISJOINT_CLEAR";
    894     case PIXMAN_OP_DISJOINT_SRC: return "PIXMAN_OP_DISJOINT_SRC";
    895     case PIXMAN_OP_DISJOINT_DST: return "PIXMAN_OP_DISJOINT_DST";
    896     case PIXMAN_OP_DISJOINT_OVER: return "PIXMAN_OP_DISJOINT_OVER";
    897     case PIXMAN_OP_DISJOINT_OVER_REVERSE: return "PIXMAN_OP_DISJOINT_OVER_REVERSE";
    898     case PIXMAN_OP_DISJOINT_IN: return "PIXMAN_OP_DISJOINT_IN";
    899     case PIXMAN_OP_DISJOINT_IN_REVERSE: return "PIXMAN_OP_DISJOINT_IN_REVERSE";
    900     case PIXMAN_OP_DISJOINT_OUT: return "PIXMAN_OP_DISJOINT_OUT";
    901     case PIXMAN_OP_DISJOINT_OUT_REVERSE: return "PIXMAN_OP_DISJOINT_OUT_REVERSE";
    902     case PIXMAN_OP_DISJOINT_ATOP: return "PIXMAN_OP_DISJOINT_ATOP";
    903     case PIXMAN_OP_DISJOINT_ATOP_REVERSE: return "PIXMAN_OP_DISJOINT_ATOP_REVERSE";
    904     case PIXMAN_OP_DISJOINT_XOR: return "PIXMAN_OP_DISJOINT_XOR";
    905 
    906     case PIXMAN_OP_CONJOINT_CLEAR: return "PIXMAN_OP_CONJOINT_CLEAR";
    907     case PIXMAN_OP_CONJOINT_SRC: return "PIXMAN_OP_CONJOINT_SRC";
    908     case PIXMAN_OP_CONJOINT_DST: return "PIXMAN_OP_CONJOINT_DST";
    909     case PIXMAN_OP_CONJOINT_OVER: return "PIXMAN_OP_CONJOINT_OVER";
    910     case PIXMAN_OP_CONJOINT_OVER_REVERSE: return "PIXMAN_OP_CONJOINT_OVER_REVERSE";
    911     case PIXMAN_OP_CONJOINT_IN: return "PIXMAN_OP_CONJOINT_IN";
    912     case PIXMAN_OP_CONJOINT_IN_REVERSE: return "PIXMAN_OP_CONJOINT_IN_REVERSE";
    913     case PIXMAN_OP_CONJOINT_OUT: return "PIXMAN_OP_CONJOINT_OUT";
    914     case PIXMAN_OP_CONJOINT_OUT_REVERSE: return "PIXMAN_OP_CONJOINT_OUT_REVERSE";
    915     case PIXMAN_OP_CONJOINT_ATOP: return "PIXMAN_OP_CONJOINT_ATOP";
    916     case PIXMAN_OP_CONJOINT_ATOP_REVERSE: return "PIXMAN_OP_CONJOINT_ATOP_REVERSE";
    917     case PIXMAN_OP_CONJOINT_XOR: return "PIXMAN_OP_CONJOINT_XOR";
    918 
    919     case PIXMAN_OP_MULTIPLY: return "PIXMAN_OP_MULTIPLY";
    920     case PIXMAN_OP_SCREEN: return "PIXMAN_OP_SCREEN";
    921     case PIXMAN_OP_OVERLAY: return "PIXMAN_OP_OVERLAY";
    922     case PIXMAN_OP_DARKEN: return "PIXMAN_OP_DARKEN";
    923     case PIXMAN_OP_LIGHTEN: return "PIXMAN_OP_LIGHTEN";
    924     case PIXMAN_OP_COLOR_DODGE: return "PIXMAN_OP_COLOR_DODGE";
    925     case PIXMAN_OP_COLOR_BURN: return "PIXMAN_OP_COLOR_BURN";
    926     case PIXMAN_OP_HARD_LIGHT: return "PIXMAN_OP_HARD_LIGHT";
    927     case PIXMAN_OP_SOFT_LIGHT: return "PIXMAN_OP_SOFT_LIGHT";
    928     case PIXMAN_OP_DIFFERENCE: return "PIXMAN_OP_DIFFERENCE";
    929     case PIXMAN_OP_EXCLUSION: return "PIXMAN_OP_EXCLUSION";
    930     case PIXMAN_OP_HSL_HUE: return "PIXMAN_OP_HSL_HUE";
    931     case PIXMAN_OP_HSL_SATURATION: return "PIXMAN_OP_HSL_SATURATION";
    932     case PIXMAN_OP_HSL_COLOR: return "PIXMAN_OP_HSL_COLOR";
    933     case PIXMAN_OP_HSL_LUMINOSITY: return "PIXMAN_OP_HSL_LUMINOSITY";
    934 
    935     case PIXMAN_OP_NONE:
    936 	return "<invalid operator 'none'>";
    937     };
    938 
    939     return "<unknown operator>";
    940 }
    941 
    942 const char *
    943 format_name (pixman_format_code_t format)
    944 {
    945     switch (format)
    946     {
    947 /* 32bpp formats */
    948     case PIXMAN_a8r8g8b8: return "a8r8g8b8";
    949     case PIXMAN_x8r8g8b8: return "x8r8g8b8";
    950     case PIXMAN_a8b8g8r8: return "a8b8g8r8";
    951     case PIXMAN_x8b8g8r8: return "x8b8g8r8";
    952     case PIXMAN_b8g8r8a8: return "b8g8r8a8";
    953     case PIXMAN_b8g8r8x8: return "b8g8r8x8";
    954     case PIXMAN_r8g8b8a8: return "r8g8b8a8";
    955     case PIXMAN_r8g8b8x8: return "r8g8b8x8";
    956     case PIXMAN_x14r6g6b6: return "x14r6g6b6";
    957     case PIXMAN_x2r10g10b10: return "x2r10g10b10";
    958     case PIXMAN_a2r10g10b10: return "a2r10g10b10";
    959     case PIXMAN_x2b10g10r10: return "x2b10g10r10";
    960     case PIXMAN_a2b10g10r10: return "a2b10g10r10";
    961 
    962 /* sRGB formats */
    963     case PIXMAN_a8r8g8b8_sRGB: return "a8r8g8b8_sRGB";
    964 
    965 /* 24bpp formats */
    966     case PIXMAN_r8g8b8: return "r8g8b8";
    967     case PIXMAN_b8g8r8: return "b8g8r8";
    968 
    969 /* 16bpp formats */
    970     case PIXMAN_r5g6b5: return "r5g6b5";
    971     case PIXMAN_b5g6r5: return "b5g6r5";
    972 
    973     case PIXMAN_a1r5g5b5: return "a1r5g5b5";
    974     case PIXMAN_x1r5g5b5: return "x1r5g5b5";
    975     case PIXMAN_a1b5g5r5: return "a1b5g5r5";
    976     case PIXMAN_x1b5g5r5: return "x1b5g5r5";
    977     case PIXMAN_a4r4g4b4: return "a4r4g4b4";
    978     case PIXMAN_x4r4g4b4: return "x4r4g4b4";
    979     case PIXMAN_a4b4g4r4: return "a4b4g4r4";
    980     case PIXMAN_x4b4g4r4: return "x4b4g4r4";
    981 
    982 /* 8bpp formats */
    983     case PIXMAN_a8: return "a8";
    984     case PIXMAN_r3g3b2: return "r3g3b2";
    985     case PIXMAN_b2g3r3: return "b2g3r3";
    986     case PIXMAN_a2r2g2b2: return "a2r2g2b2";
    987     case PIXMAN_a2b2g2r2: return "a2b2g2r2";
    988 
    989 #if 0
    990     case PIXMAN_x4c4: return "x4c4";
    991     case PIXMAN_g8: return "g8";
    992 #endif
    993     case PIXMAN_c8: return "x4c4 / c8";
    994     case PIXMAN_x4g4: return "x4g4 / g8";
    995 
    996     case PIXMAN_x4a4: return "x4a4";
    997 
    998 /* 4bpp formats */
    999     case PIXMAN_a4: return "a4";
   1000     case PIXMAN_r1g2b1: return "r1g2b1";
   1001     case PIXMAN_b1g2r1: return "b1g2r1";
   1002     case PIXMAN_a1r1g1b1: return "a1r1g1b1";
   1003     case PIXMAN_a1b1g1r1: return "a1b1g1r1";
   1004 
   1005     case PIXMAN_c4: return "c4";
   1006     case PIXMAN_g4: return "g4";
   1007 
   1008 /* 1bpp formats */
   1009     case PIXMAN_a1: return "a1";
   1010 
   1011     case PIXMAN_g1: return "g1";
   1012 
   1013 /* YUV formats */
   1014     case PIXMAN_yuy2: return "yuy2";
   1015     case PIXMAN_yv12: return "yv12";
   1016     };
   1017 
   1018     /* Fake formats.
   1019      *
   1020      * This is separate switch to prevent GCC from complaining
   1021      * that the values are not in the pixman_format_code_t enum.
   1022      */
   1023     switch ((uint32_t)format)
   1024     {
   1025     case PIXMAN_null: return "null";
   1026     case PIXMAN_solid: return "solid";
   1027     case PIXMAN_pixbuf: return "pixbuf";
   1028     case PIXMAN_rpixbuf: return "rpixbuf";
   1029     case PIXMAN_unknown: return "unknown";
   1030     };
   1031 
   1032     return "<unknown format>";
   1033 };
   1034 
   1035 static double
   1036 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
   1037 {
   1038 #define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
   1039 
   1040     double Fa, Fb;
   1041 
   1042     switch (op)
   1043     {
   1044     case PIXMAN_OP_CLEAR:
   1045     case PIXMAN_OP_DISJOINT_CLEAR:
   1046     case PIXMAN_OP_CONJOINT_CLEAR:
   1047 	return mult_chan (src, dst, 0.0, 0.0);
   1048 
   1049     case PIXMAN_OP_SRC:
   1050     case PIXMAN_OP_DISJOINT_SRC:
   1051     case PIXMAN_OP_CONJOINT_SRC:
   1052 	return mult_chan (src, dst, 1.0, 0.0);
   1053 
   1054     case PIXMAN_OP_DST:
   1055     case PIXMAN_OP_DISJOINT_DST:
   1056     case PIXMAN_OP_CONJOINT_DST:
   1057 	return mult_chan (src, dst, 0.0, 1.0);
   1058 
   1059     case PIXMAN_OP_OVER:
   1060 	return mult_chan (src, dst, 1.0, 1.0 - srca);
   1061 
   1062     case PIXMAN_OP_OVER_REVERSE:
   1063 	return mult_chan (src, dst, 1.0 - dsta, 1.0);
   1064 
   1065     case PIXMAN_OP_IN:
   1066 	return mult_chan (src, dst, dsta, 0.0);
   1067 
   1068     case PIXMAN_OP_IN_REVERSE:
   1069 	return mult_chan (src, dst, 0.0, srca);
   1070 
   1071     case PIXMAN_OP_OUT:
   1072 	return mult_chan (src, dst, 1.0 - dsta, 0.0);
   1073 
   1074     case PIXMAN_OP_OUT_REVERSE:
   1075 	return mult_chan (src, dst, 0.0, 1.0 - srca);
   1076 
   1077     case PIXMAN_OP_ATOP:
   1078 	return mult_chan (src, dst, dsta, 1.0 - srca);
   1079 
   1080     case PIXMAN_OP_ATOP_REVERSE:
   1081 	return mult_chan (src, dst, 1.0 - dsta,  srca);
   1082 
   1083     case PIXMAN_OP_XOR:
   1084 	return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
   1085 
   1086     case PIXMAN_OP_ADD:
   1087 	return mult_chan (src, dst, 1.0, 1.0);
   1088 
   1089     case PIXMAN_OP_SATURATE:
   1090     case PIXMAN_OP_DISJOINT_OVER_REVERSE:
   1091 	if (srca == 0.0)
   1092 	    Fa = 1.0;
   1093 	else
   1094 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
   1095 	return mult_chan (src, dst, Fa, 1.0);
   1096 
   1097     case PIXMAN_OP_DISJOINT_OVER:
   1098 	if (dsta == 0.0)
   1099 	    Fb = 1.0;
   1100 	else
   1101 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
   1102 	return mult_chan (src, dst, 1.0, Fb);
   1103 
   1104     case PIXMAN_OP_DISJOINT_IN:
   1105 	if (srca == 0.0)
   1106 	    Fa = 0.0;
   1107 	else
   1108 	    Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
   1109 	return mult_chan (src, dst, Fa, 0.0);
   1110 
   1111     case PIXMAN_OP_DISJOINT_IN_REVERSE:
   1112 	if (dsta == 0.0)
   1113 	    Fb = 0.0;
   1114 	else
   1115 	    Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
   1116 	return mult_chan (src, dst, 0.0, Fb);
   1117 
   1118     case PIXMAN_OP_DISJOINT_OUT:
   1119 	if (srca == 0.0)
   1120 	    Fa = 1.0;
   1121 	else
   1122 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
   1123 	return mult_chan (src, dst, Fa, 0.0);
   1124 
   1125     case PIXMAN_OP_DISJOINT_OUT_REVERSE:
   1126 	if (dsta == 0.0)
   1127 	    Fb = 1.0;
   1128 	else
   1129 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
   1130 	return mult_chan (src, dst, 0.0, Fb);
   1131 
   1132     case PIXMAN_OP_DISJOINT_ATOP:
   1133 	if (srca == 0.0)
   1134 	    Fa = 0.0;
   1135 	else
   1136 	    Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
   1137 	if (dsta == 0.0)
   1138 	    Fb = 1.0;
   1139 	else
   1140 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
   1141 	return mult_chan (src, dst, Fa, Fb);
   1142 
   1143     case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
   1144 	if (srca == 0.0)
   1145 	    Fa = 1.0;
   1146 	else
   1147 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
   1148 	if (dsta == 0.0)
   1149 	    Fb = 0.0;
   1150 	else
   1151 	    Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
   1152 	return mult_chan (src, dst, Fa, Fb);
   1153 
   1154     case PIXMAN_OP_DISJOINT_XOR:
   1155 	if (srca == 0.0)
   1156 	    Fa = 1.0;
   1157 	else
   1158 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
   1159 	if (dsta == 0.0)
   1160 	    Fb = 1.0;
   1161 	else
   1162 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
   1163 	return mult_chan (src, dst, Fa, Fb);
   1164 
   1165     case PIXMAN_OP_CONJOINT_OVER:
   1166 	if (dsta == 0.0)
   1167 	    Fb = 0.0;
   1168 	else
   1169 	    Fb = MAX (0.0, 1.0 - srca / dsta);
   1170 	return mult_chan (src, dst, 1.0, Fb);
   1171 
   1172     case PIXMAN_OP_CONJOINT_OVER_REVERSE:
   1173 	if (srca == 0.0)
   1174 	    Fa = 0.0;
   1175 	else
   1176 	    Fa = MAX (0.0, 1.0 - dsta / srca);
   1177 	return mult_chan (src, dst, Fa, 1.0);
   1178 
   1179     case PIXMAN_OP_CONJOINT_IN:
   1180 	if (srca == 0.0)
   1181 	    Fa = 1.0;
   1182 	else
   1183 	    Fa = MIN (1.0, dsta / srca);
   1184 	return mult_chan (src, dst, Fa, 0.0);
   1185 
   1186     case PIXMAN_OP_CONJOINT_IN_REVERSE:
   1187 	if (dsta == 0.0)
   1188 	    Fb = 1.0;
   1189 	else
   1190 	    Fb = MIN (1.0, srca / dsta);
   1191 	return mult_chan (src, dst, 0.0, Fb);
   1192 
   1193     case PIXMAN_OP_CONJOINT_OUT:
   1194 	if (srca == 0.0)
   1195 	    Fa = 0.0;
   1196 	else
   1197 	    Fa = MAX (0.0, 1.0 - dsta / srca);
   1198 	return mult_chan (src, dst, Fa, 0.0);
   1199 
   1200     case PIXMAN_OP_CONJOINT_OUT_REVERSE:
   1201 	if (dsta == 0.0)
   1202 	    Fb = 0.0;
   1203 	else
   1204 	    Fb = MAX (0.0, 1.0 - srca / dsta);
   1205 	return mult_chan (src, dst, 0.0, Fb);
   1206 
   1207     case PIXMAN_OP_CONJOINT_ATOP:
   1208 	if (srca == 0.0)
   1209 	    Fa = 1.0;
   1210 	else
   1211 	    Fa = MIN (1.0, dsta / srca);
   1212 	if (dsta == 0.0)
   1213 	    Fb = 0.0;
   1214 	else
   1215 	    Fb = MAX (0.0, 1.0 - srca / dsta);
   1216 	return mult_chan (src, dst, Fa, Fb);
   1217 
   1218     case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
   1219 	if (srca == 0.0)
   1220 	    Fa = 0.0;
   1221 	else
   1222 	    Fa = MAX (0.0, 1.0 - dsta / srca);
   1223 	if (dsta == 0.0)
   1224 	    Fb = 1.0;
   1225 	else
   1226 	    Fb = MIN (1.0, srca / dsta);
   1227 	return mult_chan (src, dst, Fa, Fb);
   1228 
   1229     case PIXMAN_OP_CONJOINT_XOR:
   1230 	if (srca == 0.0)
   1231 	    Fa = 0.0;
   1232 	else
   1233 	    Fa = MAX (0.0, 1.0 - dsta / srca);
   1234 	if (dsta == 0.0)
   1235 	    Fb = 0.0;
   1236 	else
   1237 	    Fb = MAX (0.0, 1.0 - srca / dsta);
   1238 	return mult_chan (src, dst, Fa, Fb);
   1239 
   1240     case PIXMAN_OP_MULTIPLY:
   1241     case PIXMAN_OP_SCREEN:
   1242     case PIXMAN_OP_OVERLAY:
   1243     case PIXMAN_OP_DARKEN:
   1244     case PIXMAN_OP_LIGHTEN:
   1245     case PIXMAN_OP_COLOR_DODGE:
   1246     case PIXMAN_OP_COLOR_BURN:
   1247     case PIXMAN_OP_HARD_LIGHT:
   1248     case PIXMAN_OP_SOFT_LIGHT:
   1249     case PIXMAN_OP_DIFFERENCE:
   1250     case PIXMAN_OP_EXCLUSION:
   1251     case PIXMAN_OP_HSL_HUE:
   1252     case PIXMAN_OP_HSL_SATURATION:
   1253     case PIXMAN_OP_HSL_COLOR:
   1254     case PIXMAN_OP_HSL_LUMINOSITY:
   1255     default:
   1256 	abort();
   1257 	return 0; /* silence MSVC */
   1258     }
   1259 #undef mult_chan
   1260 }
   1261 
   1262 void
   1263 do_composite (pixman_op_t op,
   1264 	      const color_t *src,
   1265 	      const color_t *mask,
   1266 	      const color_t *dst,
   1267 	      color_t *result,
   1268 	      pixman_bool_t component_alpha)
   1269 {
   1270     color_t srcval, srcalpha;
   1271 
   1272     if (mask == NULL)
   1273     {
   1274 	srcval = *src;
   1275 
   1276 	srcalpha.r = src->a;
   1277 	srcalpha.g = src->a;
   1278 	srcalpha.b = src->a;
   1279 	srcalpha.a = src->a;
   1280     }
   1281     else if (component_alpha)
   1282     {
   1283 	srcval.r = src->r * mask->r;
   1284 	srcval.g = src->g * mask->g;
   1285 	srcval.b = src->b * mask->b;
   1286 	srcval.a = src->a * mask->a;
   1287 
   1288 	srcalpha.r = src->a * mask->r;
   1289 	srcalpha.g = src->a * mask->g;
   1290 	srcalpha.b = src->a * mask->b;
   1291 	srcalpha.a = src->a * mask->a;
   1292     }
   1293     else
   1294     {
   1295 	srcval.r = src->r * mask->a;
   1296 	srcval.g = src->g * mask->a;
   1297 	srcval.b = src->b * mask->a;
   1298 	srcval.a = src->a * mask->a;
   1299 
   1300 	srcalpha.r = src->a * mask->a;
   1301 	srcalpha.g = src->a * mask->a;
   1302 	srcalpha.b = src->a * mask->a;
   1303 	srcalpha.a = src->a * mask->a;
   1304     }
   1305 
   1306     result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
   1307     result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
   1308     result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
   1309     result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
   1310 }
   1311 
   1312 static double
   1313 round_channel (double p, int m)
   1314 {
   1315     int t;
   1316     double r;
   1317 
   1318     t = p * ((1 << m));
   1319     t -= t >> m;
   1320 
   1321     r = t / (double)((1 << m) - 1);
   1322 
   1323     return r;
   1324 }
   1325 
   1326 void
   1327 round_color (pixman_format_code_t format, color_t *color)
   1328 {
   1329     if (PIXMAN_FORMAT_R (format) == 0)
   1330     {
   1331 	color->r = 0.0;
   1332 	color->g = 0.0;
   1333 	color->b = 0.0;
   1334     }
   1335     else
   1336     {
   1337 	color->r = round_channel (color->r, PIXMAN_FORMAT_R (format));
   1338 	color->g = round_channel (color->g, PIXMAN_FORMAT_G (format));
   1339 	color->b = round_channel (color->b, PIXMAN_FORMAT_B (format));
   1340     }
   1341 
   1342     if (PIXMAN_FORMAT_A (format) == 0)
   1343 	color->a = 1;
   1344     else
   1345 	color->a = round_channel (color->a, PIXMAN_FORMAT_A (format));
   1346 }
   1347 
   1348 /* Check whether @pixel is a valid quantization of the a, r, g, b
   1349  * parameters. Some slack is permitted.
   1350  */
   1351 void
   1352 pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
   1353 {
   1354     assert (PIXMAN_FORMAT_VIS (format));
   1355 
   1356     checker->format = format;
   1357 
   1358     switch (PIXMAN_FORMAT_TYPE (format))
   1359     {
   1360     case PIXMAN_TYPE_A:
   1361 	checker->bs = 0;
   1362 	checker->gs = 0;
   1363 	checker->rs = 0;
   1364 	checker->as = 0;
   1365 	break;
   1366 
   1367     case PIXMAN_TYPE_ARGB:
   1368     case PIXMAN_TYPE_ARGB_SRGB:
   1369 	checker->bs = 0;
   1370 	checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
   1371 	checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
   1372 	checker->as = checker->rs + PIXMAN_FORMAT_R (format);
   1373 	break;
   1374 
   1375     case PIXMAN_TYPE_ABGR:
   1376 	checker->rs = 0;
   1377 	checker->gs = checker->rs + PIXMAN_FORMAT_R (format);
   1378 	checker->bs = checker->gs + PIXMAN_FORMAT_G (format);
   1379 	checker->as = checker->bs + PIXMAN_FORMAT_B (format);
   1380 	break;
   1381 
   1382     case PIXMAN_TYPE_BGRA:
   1383 	/* With BGRA formats we start counting at the high end of the pixel */
   1384 	checker->bs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
   1385 	checker->gs = checker->bs - PIXMAN_FORMAT_B (format);
   1386 	checker->rs = checker->gs - PIXMAN_FORMAT_G (format);
   1387 	checker->as = checker->rs - PIXMAN_FORMAT_R (format);
   1388 	break;
   1389 
   1390     case PIXMAN_TYPE_RGBA:
   1391 	/* With BGRA formats we start counting at the high end of the pixel */
   1392 	checker->rs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
   1393 	checker->gs = checker->rs - PIXMAN_FORMAT_R (format);
   1394 	checker->bs = checker->gs - PIXMAN_FORMAT_G (format);
   1395 	checker->as = checker->bs - PIXMAN_FORMAT_B (format);
   1396 	break;
   1397 
   1398     default:
   1399 	assert (0);
   1400 	break;
   1401     }
   1402 
   1403     checker->am = ((1 << PIXMAN_FORMAT_A (format)) - 1) << checker->as;
   1404     checker->rm = ((1 << PIXMAN_FORMAT_R (format)) - 1) << checker->rs;
   1405     checker->gm = ((1 << PIXMAN_FORMAT_G (format)) - 1) << checker->gs;
   1406     checker->bm = ((1 << PIXMAN_FORMAT_B (format)) - 1) << checker->bs;
   1407 
   1408     checker->aw = PIXMAN_FORMAT_A (format);
   1409     checker->rw = PIXMAN_FORMAT_R (format);
   1410     checker->gw = PIXMAN_FORMAT_G (format);
   1411     checker->bw = PIXMAN_FORMAT_B (format);
   1412 }
   1413 
   1414 void
   1415 pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
   1416 			   int *a, int *r, int *g, int *b)
   1417 {
   1418     *a = (pixel & checker->am) >> checker->as;
   1419     *r = (pixel & checker->rm) >> checker->rs;
   1420     *g = (pixel & checker->gm) >> checker->gs;
   1421     *b = (pixel & checker->bm) >> checker->bs;
   1422 }
   1423 
   1424 void
   1425 pixel_checker_get_masks (const pixel_checker_t *checker,
   1426                          uint32_t              *am,
   1427                          uint32_t              *rm,
   1428                          uint32_t              *gm,
   1429                          uint32_t              *bm)
   1430 {
   1431     if (am)
   1432         *am = checker->am;
   1433     if (rm)
   1434         *rm = checker->rm;
   1435     if (gm)
   1436         *gm = checker->gm;
   1437     if (bm)
   1438         *bm = checker->bm;
   1439 }
   1440 
   1441 void
   1442 pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
   1443                                       uint32_t pixel, color_t *color)
   1444 {
   1445     int a, r, g, b;
   1446 
   1447     pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b);
   1448 
   1449     if (checker->am == 0)
   1450         color->a = 1.0;
   1451     else
   1452         color->a = a / (double)(checker->am >> checker->as);
   1453 
   1454     if (checker->rm == 0)
   1455         color->r = 0.0;
   1456     else
   1457         color->r = r / (double)(checker->rm >> checker->rs);
   1458 
   1459     if (checker->gm == 0)
   1460         color->g = 0.0;
   1461     else
   1462         color->g = g / (double)(checker->gm >> checker->gs);
   1463 
   1464     if (checker->bm == 0)
   1465         color->b = 0.0;
   1466     else
   1467         color->b = b / (double)(checker->bm >> checker->bs);
   1468 
   1469     if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
   1470     {
   1471 	color->r = convert_srgb_to_linear (color->r);
   1472 	color->g = convert_srgb_to_linear (color->g);
   1473 	color->b = convert_srgb_to_linear (color->b);
   1474     }
   1475 }
   1476 
   1477 static int32_t
   1478 convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def)
   1479 {
   1480     int32_t r;
   1481 
   1482     if (!mask)
   1483 	v = def;
   1484 
   1485     r = (v * ((mask >> shift) + 1));
   1486     r -= r >> width;
   1487 
   1488     return r;
   1489 }
   1490 
   1491 static void
   1492 get_limits (const pixel_checker_t *checker, double limit,
   1493 	    color_t *color,
   1494 	    int *ao, int *ro, int *go, int *bo)
   1495 {
   1496     color_t tmp;
   1497 
   1498     if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
   1499     {
   1500 	tmp.a = color->a;
   1501 	tmp.r = convert_linear_to_srgb (color->r);
   1502 	tmp.g = convert_linear_to_srgb (color->g);
   1503 	tmp.b = convert_linear_to_srgb (color->b);
   1504 
   1505 	color = &tmp;
   1506     }
   1507 
   1508     *ao = convert (color->a + limit, checker->aw, checker->am, checker->as, 1.0);
   1509     *ro = convert (color->r + limit, checker->rw, checker->rm, checker->rs, 0.0);
   1510     *go = convert (color->g + limit, checker->gw, checker->gm, checker->gs, 0.0);
   1511     *bo = convert (color->b + limit, checker->bw, checker->bm, checker->bs, 0.0);
   1512 }
   1513 
   1514 /* The acceptable deviation in units of [0.0, 1.0]
   1515  */
   1516 #define DEVIATION (0.0064)
   1517 
   1518 void
   1519 pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
   1520 		       int *am, int *rm, int *gm, int *bm)
   1521 {
   1522     get_limits (checker, DEVIATION, color, am, rm, gm, bm);
   1523 }
   1524 
   1525 void
   1526 pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
   1527 		       int *am, int *rm, int *gm, int *bm)
   1528 {
   1529     get_limits (checker, - DEVIATION, color, am, rm, gm, bm);
   1530 }
   1531 
   1532 pixman_bool_t
   1533 pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
   1534 		     color_t *color)
   1535 {
   1536     int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
   1537     int32_t ai, ri, gi, bi;
   1538     pixman_bool_t result;
   1539 
   1540     pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
   1541     pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
   1542     pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
   1543 
   1544     result =
   1545 	a_lo <= ai && ai <= a_hi	&&
   1546 	r_lo <= ri && ri <= r_hi	&&
   1547 	g_lo <= gi && gi <= g_hi	&&
   1548 	b_lo <= bi && bi <= b_hi;
   1549 
   1550     return result;
   1551 }
   1552