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
33prng_t prng_state_data;
34prng_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
75uint32_t
76compute_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
140static uint32_t
141compute_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
223uint32_t
224compute_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 */
243void
244image_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
331typedef 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
346void *
347fence_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
395void
396fence_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
409void *
410fence_malloc (int64_t len)
411{
412    return malloc (len);
413}
414
415void
416fence_free (void *data)
417{
418    free (data);
419}
420
421#endif
422
423uint8_t *
424make_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
436void
437a8r8g8b8_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
475pixman_bool_t
476write_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
528out2:
529    png_destroy_write_struct (&write_struct, &info_struct);
530
531out1:
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
543pixman_bool_t
544write_png (pixman_image_t *image, const char *filename)
545{
546    return FALSE;
547}
548
549#endif
550
551static void
552color8_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
565void
566draw_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 */
649int
650fuzzer_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 */
719double
720gettime (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
732uint32_t
733get_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
744static const char *global_msg;
745
746static void
747on_alarm (int signo)
748{
749    printf ("%s\n", global_msg);
750    exit (1);
751}
752#endif
753#endif
754
755void
756fail_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
774void
775enable_divbyzero_exceptions (void)
776{
777#ifdef HAVE_FENV_H
778#ifdef HAVE_FEENABLEEXCEPT
779    feenableexcept (FE_DIVBYZERO);
780#endif
781#endif
782}
783
784void *
785aligned_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
808double
809convert_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
817double
818convert_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
826void
827initialize_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
873const char *
874operator_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
942const char *
943format_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
1035static double
1036calc_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
1262void
1263do_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
1312static double
1313round_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
1326void
1327round_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 */
1351void
1352pixel_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
1414void
1415pixel_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
1424void
1425pixel_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
1441void
1442pixel_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
1477static int32_t
1478convert (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
1491static void
1492get_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
1518void
1519pixel_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
1525void
1526pixel_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
1532pixman_bool_t
1533pixel_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