1 #define _GNU_SOURCE
2 
3 #include "utils.h"
4 #include <math.h>
5 #include <signal.h>
6 #include <stdlib.h>
7 #include <float.h>
8 #include <ctype.h>
9 #include <limits.h>
10 
11 #ifdef HAVE_GETTIMEOFDAY
12 #include <sys/time.h>
13 #else
14 #include <time.h>
15 #endif
16 
17 #ifdef HAVE_UNISTD_H
18 #include <unistd.h>
19 #endif
20 
21 #ifdef HAVE_SYS_MMAN_H
22 #include <sys/mman.h>
23 #endif
24 
25 #ifdef HAVE_FENV_H
26 #include <fenv.h>
27 #endif
28 
29 #ifdef HAVE_LIBPNG
30 #include <png.h>
31 #endif
32 
33 #define ROUND_UP(x, mult) (((x) + (mult) - 1) / (mult) * (mult))
34 
35 /* Random number generator state
36  */
37 
38 prng_t prng_state_data;
39 prng_t *prng_state;
40 
41 /*----------------------------------------------------------------------------*\
42  *  CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
43  *
44  *  This program generates the CRC-32 values for the files named in the
45  *  command-line arguments.  These are the same CRC-32 values used by GZIP,
46  *  PKZIP, and ZMODEM.  The Crc32_ComputeBuf () can also be detached and
47  *  used independently.
48  *
49  *  THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
50  *
51  *  Based on the byte-oriented implementation "File Verification Using CRC"
52  *  by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
53  *
54  *  v1.0.0: original release.
55  *  v1.0.1: fixed printf formats.
56  *  v1.0.2: fixed something else.
57  *  v1.0.3: replaced CRC constant table by generator function.
58  *  v1.0.4: reformatted code, made ANSI C.  1994-12-05.
59  *  v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
60 \*----------------------------------------------------------------------------*/
61 
62 /*----------------------------------------------------------------------------*\
63  *  NAME:
64  *     Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
65  *  DESCRIPTION:
66  *     Computes or accumulates the CRC-32 value for a memory buffer.
67  *     The 'inCrc32' gives a previously accumulated CRC-32 value to allow
68  *     a CRC to be generated for multiple sequential buffer-fuls of data.
69  *     The 'inCrc32' for the first buffer must be zero.
70  *  ARGUMENTS:
71  *     inCrc32 - accumulated CRC-32 value, must be 0 on first call
72  *     buf     - buffer to compute CRC-32 value for
73  *     bufLen  - number of bytes in buffer
74  *  RETURNS:
75  *     crc32 - computed CRC-32 value
76  *  ERRORS:
77  *     (no errors are possible)
78 \*----------------------------------------------------------------------------*/
79 
80 uint32_t
compute_crc32(uint32_t in_crc32,const void * buf,size_t buf_len)81 compute_crc32 (uint32_t    in_crc32,
82 	       const void *buf,
83 	       size_t      buf_len)
84 {
85     static const uint32_t crc_table[256] = {
86 	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
87 	0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
88 	0x09B64C2B, 0x7EB17CBD,	0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
89 	0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
90 	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,	0x14015C4F, 0x63066CD9,
91 	0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
92 	0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
93 	0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
94 	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
95 	0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
96 	0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
97 	0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
98 	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
99 	0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
100 	0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
101 	0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
102 	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
103 	0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
104 	0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
105 	0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
106 	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
107 	0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
108 	0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
109 	0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
110 	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
111 	0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
112 	0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
113 	0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
114 	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
115 	0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
116 	0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
117 	0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
118 	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
119 	0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
120 	0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
121 	0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
122 	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
123 	0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
124 	0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
125 	0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
126 	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
127 	0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
128 	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
129     };
130 
131     uint32_t              crc32;
132     unsigned char *       byte_buf;
133     size_t                i;
134 
135     /* accumulate crc32 for buffer */
136     crc32 = in_crc32 ^ 0xFFFFFFFF;
137     byte_buf = (unsigned char*) buf;
138 
139     for (i = 0; i < buf_len; i++)
140 	crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
141 
142     return (crc32 ^ 0xFFFFFFFF);
143 }
144 
145 static uint32_t
compute_crc32_for_image_internal(uint32_t crc32,pixman_image_t * img,pixman_bool_t remove_alpha,pixman_bool_t remove_rgb)146 compute_crc32_for_image_internal (uint32_t        crc32,
147 				  pixman_image_t *img,
148 				  pixman_bool_t	  remove_alpha,
149 				  pixman_bool_t	  remove_rgb)
150 {
151     pixman_format_code_t fmt = pixman_image_get_format (img);
152     uint32_t *data = pixman_image_get_data (img);
153     int stride = pixman_image_get_stride (img);
154     int height = pixman_image_get_height (img);
155     uint32_t mask = 0xffffffff;
156     int i;
157 
158     if (stride < 0)
159     {
160 	data += (stride / 4) * (height - 1);
161 	stride = - stride;
162     }
163 
164     /* mask unused 'x' part */
165     if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
166 	PIXMAN_FORMAT_DEPTH (fmt) != 0)
167     {
168 	uint32_t m = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
169 
170 	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
171 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
172 	{
173 	    m <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
174 	}
175 
176 	mask &= m;
177     }
178 
179     /* mask alpha channel */
180     if (remove_alpha && PIXMAN_FORMAT_A (fmt))
181     {
182 	uint32_t m;
183 
184 	if (PIXMAN_FORMAT_BPP (fmt) == 32)
185 	    m = 0xffffffff;
186 	else
187 	    m = (1 << PIXMAN_FORMAT_BPP (fmt)) - 1;
188 
189 	m >>= PIXMAN_FORMAT_A (fmt);
190 
191 	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
192 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA ||
193 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_A)
194 	{
195 	    /* Alpha is at the bottom of the pixel */
196 	    m <<= PIXMAN_FORMAT_A (fmt);
197 	}
198 
199 	mask &= m;
200     }
201 
202     /* mask rgb channels */
203     if (remove_rgb && PIXMAN_FORMAT_RGB (fmt))
204     {
205 	uint32_t m = ((uint32_t)~0) >> (32 - PIXMAN_FORMAT_BPP (fmt));
206 	uint32_t size = PIXMAN_FORMAT_R (fmt) + PIXMAN_FORMAT_G (fmt) + PIXMAN_FORMAT_B (fmt);
207 
208 	m &= ~((1 << size) - 1);
209 
210 	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
211 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
212 	{
213 	    /* RGB channels are at the top of the pixel */
214 	    m >>= size;
215 	}
216 
217 	mask &= m;
218     }
219 
220     for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++)
221 	mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
222 
223     for (i = 0; i < stride * height / 4; i++)
224 	data[i] &= mask;
225 
226     /* swap endiannes in order to provide identical results on both big
227      * and litte endian systems
228      */
229     image_endian_swap (img);
230 
231     return compute_crc32 (crc32, data, stride * height);
232 }
233 
234 uint32_t
compute_crc32_for_image(uint32_t crc32,pixman_image_t * img)235 compute_crc32_for_image (uint32_t        crc32,
236 			 pixman_image_t *img)
237 {
238     if (img->common.alpha_map)
239     {
240 	crc32 = compute_crc32_for_image_internal (crc32, img, TRUE, FALSE);
241 	crc32 = compute_crc32_for_image_internal (
242 	    crc32, (pixman_image_t *)img->common.alpha_map, FALSE, TRUE);
243     }
244     else
245     {
246 	crc32 = compute_crc32_for_image_internal (crc32, img, FALSE, FALSE);
247     }
248 
249     return crc32;
250 }
251 
252 void
print_image(pixman_image_t * image)253 print_image (pixman_image_t *image)
254 {
255     int i, j;
256     int width, height, stride;
257     pixman_format_code_t format;
258     uint8_t *buffer;
259     int s;
260 
261     width = pixman_image_get_width (image);
262     height = pixman_image_get_height (image);
263     stride = pixman_image_get_stride (image);
264     format = pixman_image_get_format (image);
265     buffer = (uint8_t *)pixman_image_get_data (image);
266 
267     s = (stride >= 0)? stride : - stride;
268 
269     printf ("---\n");
270     for (i = 0; i < height; i++)
271     {
272 	for (j = 0; j < s; j++)
273 	{
274 	    if (j == (width * PIXMAN_FORMAT_BPP (format) + 7) / 8)
275 		printf ("| ");
276 
277 	    printf ("%02X ", *((uint8_t *)buffer + i * stride + j));
278 	}
279 	printf ("\n");
280     }
281     printf ("---\n");
282 }
283 
284 /* perform endian conversion of pixel data
285  */
286 void
image_endian_swap(pixman_image_t * img)287 image_endian_swap (pixman_image_t *img)
288 {
289     int stride = pixman_image_get_stride (img);
290     uint32_t *data = pixman_image_get_data (img);
291     int height = pixman_image_get_height (img);
292     int bpp = PIXMAN_FORMAT_BPP (pixman_image_get_format (img));
293     int i, j;
294 
295     /* swap bytes only on big endian systems */
296     if (is_little_endian())
297 	return;
298 
299     if (bpp == 8)
300 	return;
301 
302     for (i = 0; i < height; i++)
303     {
304 	uint8_t *line_data = (uint8_t *)data + stride * i;
305 	int s = (stride >= 0)? stride : - stride;
306 
307 	switch (bpp)
308 	{
309 	case 1:
310 	    for (j = 0; j < s; j++)
311 	    {
312 		line_data[j] =
313 		    ((line_data[j] & 0x80) >> 7) |
314 		    ((line_data[j] & 0x40) >> 5) |
315 		    ((line_data[j] & 0x20) >> 3) |
316 		    ((line_data[j] & 0x10) >> 1) |
317 		    ((line_data[j] & 0x08) << 1) |
318 		    ((line_data[j] & 0x04) << 3) |
319 		    ((line_data[j] & 0x02) << 5) |
320 		    ((line_data[j] & 0x01) << 7);
321 	    }
322 	    break;
323 	case 4:
324 	    for (j = 0; j < s; j++)
325 	    {
326 		line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
327 	    }
328 	    break;
329 	case 16:
330 	    for (j = 0; j + 2 <= s; j += 2)
331 	    {
332 		char t1 = line_data[j + 0];
333 		char t2 = line_data[j + 1];
334 
335 		line_data[j + 1] = t1;
336 		line_data[j + 0] = t2;
337 	    }
338 	    break;
339 	case 24:
340 	    for (j = 0; j + 3 <= s; j += 3)
341 	    {
342 		char t1 = line_data[j + 0];
343 		char t2 = line_data[j + 1];
344 		char t3 = line_data[j + 2];
345 
346 		line_data[j + 2] = t1;
347 		line_data[j + 1] = t2;
348 		line_data[j + 0] = t3;
349 	    }
350 	    break;
351 	case 32:
352 	    for (j = 0; j + 4 <= s; j += 4)
353 	    {
354 		char t1 = line_data[j + 0];
355 		char t2 = line_data[j + 1];
356 		char t3 = line_data[j + 2];
357 		char t4 = line_data[j + 3];
358 
359 		line_data[j + 3] = t1;
360 		line_data[j + 2] = t2;
361 		line_data[j + 1] = t3;
362 		line_data[j + 0] = t4;
363 	    }
364 	    break;
365 	default:
366 	    assert (FALSE);
367 	    break;
368 	}
369     }
370 }
371 
372 #define N_LEADING_PROTECTED	10
373 #define N_TRAILING_PROTECTED	10
374 
375 typedef struct
376 {
377     void *addr;
378     uint32_t len;
379     uint8_t *trailing;
380     int n_bytes;
381 } info_t;
382 
383 #if FENCE_MALLOC_ACTIVE
384 
385 unsigned long
fence_get_page_size()386 fence_get_page_size ()
387 {
388     /* You can fake a page size here, if you want to test e.g. 64 kB
389      * pages on a 4 kB page system. Just put a multiplier below.
390      */
391     return getpagesize ();
392 }
393 
394 /* This is apparently necessary on at least OS X */
395 #ifndef MAP_ANONYMOUS
396 #define MAP_ANONYMOUS MAP_ANON
397 #endif
398 
399 void *
fence_malloc(int64_t len)400 fence_malloc (int64_t len)
401 {
402     unsigned long page_size = fence_get_page_size ();
403     unsigned long page_mask = page_size - 1;
404     uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
405     uint32_t n_bytes =
406 	(page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
407 	 n_payload_bytes) & ~page_mask;
408     uint8_t *initial_page;
409     uint8_t *leading_protected;
410     uint8_t *trailing_protected;
411     uint8_t *payload;
412     uint8_t *addr;
413 
414     if (len < 0)
415 	abort();
416 
417     addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
418 		 -1, 0);
419 
420     if (addr == MAP_FAILED)
421     {
422 	printf ("mmap failed on %lld %u\n", (long long int)len, n_bytes);
423 	return NULL;
424     }
425 
426     initial_page = (uint8_t *)(((uintptr_t)addr + page_mask) & ~page_mask);
427     leading_protected = initial_page + page_size;
428     payload = leading_protected + N_LEADING_PROTECTED * page_size;
429     trailing_protected = payload + n_payload_bytes;
430 
431     ((info_t *)initial_page)->addr = addr;
432     ((info_t *)initial_page)->len = len;
433     ((info_t *)initial_page)->trailing = trailing_protected;
434     ((info_t *)initial_page)->n_bytes = n_bytes;
435 
436     if ((mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
437 		  PROT_NONE) == -1) ||
438 	(mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
439 		  PROT_NONE) == -1))
440     {
441 	munmap (addr, n_bytes);
442 	return NULL;
443     }
444 
445     return payload;
446 }
447 
448 void
fence_free(void * data)449 fence_free (void *data)
450 {
451     uint32_t page_size = fence_get_page_size ();
452     uint8_t *payload = data;
453     uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
454     uint8_t *initial_page = leading_protected - page_size;
455     info_t *info = (info_t *)initial_page;
456 
457     munmap (info->addr, info->n_bytes);
458 }
459 
460 static void
fence_image_destroy(pixman_image_t * image,void * data)461 fence_image_destroy (pixman_image_t *image, void *data)
462 {
463     fence_free (data);
464 }
465 
466 /* Create an image with fence pages.
467  *
468  * Creates an image, where the data area is allocated with fence_malloc ().
469  * Each row has an additional page in the stride.
470  *
471  * min_width is only a minimum width for the image. The width is aligned up
472  * for the row size to be divisible by both page size and pixel size.
473  *
474  * If stride_fence is true, the additional page on each row will be
475  * armed to cause SIGSEGV or SIGBUS on all accesses. This should catch
476  * all accesses outside the valid row pixels.
477  */
478 pixman_image_t *
fence_image_create_bits(pixman_format_code_t format,int min_width,int height,pixman_bool_t stride_fence)479 fence_image_create_bits (pixman_format_code_t format,
480                          int min_width,
481                          int height,
482                          pixman_bool_t stride_fence)
483 {
484     unsigned page_size = fence_get_page_size ();
485     unsigned page_mask = page_size - 1;
486     unsigned bitspp = PIXMAN_FORMAT_BPP (format);
487     unsigned bits_boundary;
488     unsigned row_bits;
489     int width;       /* pixels */
490     unsigned stride; /* bytes */
491     void *pixels;
492     pixman_image_t *image;
493     int i;
494 
495     /* must be power of two */
496     assert (page_size && (page_size & page_mask) == 0);
497 
498     if (bitspp < 1 || min_width < 1 || height < 1)
499         abort ();
500 
501     /* least common multiple between page size * 8 and bitspp */
502     bits_boundary = bitspp;
503     while (! (bits_boundary & 1))
504         bits_boundary >>= 1;
505     bits_boundary *= page_size * 8;
506 
507     /* round up to bits_boundary */
508     row_bits = ROUND_UP ( (unsigned)min_width * bitspp, bits_boundary);
509     width = row_bits / bitspp;
510 
511     stride = row_bits / 8;
512     if (stride_fence)
513         stride += page_size; /* add fence page */
514 
515     if (UINT_MAX / stride < (unsigned)height)
516         abort ();
517 
518     pixels = fence_malloc (stride * (unsigned)height);
519     if (!pixels)
520         return NULL;
521 
522     if (stride_fence)
523     {
524         uint8_t *guard = (uint8_t *)pixels + stride - page_size;
525 
526         /* arm row end fence pages */
527         for (i = 0; i < height; i++)
528         {
529             if (mprotect (guard + i * stride, page_size, PROT_NONE) == -1)
530                 goto out_fail;
531         }
532     }
533 
534     assert (width >= min_width);
535 
536     image = pixman_image_create_bits_no_clear (format, width, height,
537                                                pixels, stride);
538     if (!image)
539         goto out_fail;
540 
541     pixman_image_set_destroy_function (image, fence_image_destroy, pixels);
542 
543     return image;
544 
545 out_fail:
546     fence_free (pixels);
547 
548     return NULL;
549 }
550 
551 #else /* FENCE_MALLOC_ACTIVE */
552 
553 void *
fence_malloc(int64_t len)554 fence_malloc (int64_t len)
555 {
556     return malloc (len);
557 }
558 
559 void
fence_free(void * data)560 fence_free (void *data)
561 {
562     free (data);
563 }
564 
565 pixman_image_t *
fence_image_create_bits(pixman_format_code_t format,int min_width,int height,pixman_bool_t stride_fence)566 fence_image_create_bits (pixman_format_code_t format,
567                          int min_width,
568                          int height,
569                          pixman_bool_t stride_fence)
570 {
571     return pixman_image_create_bits (format, min_width, height, NULL, 0);
572     /* Implicitly allocated storage does not need a destroy function
573      * to get freed on refcount hitting zero.
574      */
575 }
576 
577 unsigned long
fence_get_page_size()578 fence_get_page_size ()
579 {
580     return 0;
581 }
582 
583 #endif /* FENCE_MALLOC_ACTIVE */
584 
585 uint8_t *
make_random_bytes(int n_bytes)586 make_random_bytes (int n_bytes)
587 {
588     uint8_t *bytes = fence_malloc (n_bytes);
589 
590     if (!bytes)
591 	return NULL;
592 
593     prng_randmemset (bytes, n_bytes, 0);
594 
595     return bytes;
596 }
597 
598 float *
make_random_floats(int n_bytes)599 make_random_floats (int n_bytes)
600 {
601     uint8_t *bytes = fence_malloc (n_bytes);
602     float *vals = (float *)bytes;
603 
604     if (!bytes)
605 	return 0;
606 
607     for (n_bytes /= 4; n_bytes; vals++, n_bytes--)
608 	*vals = (float)rand() / (float)RAND_MAX;
609 
610     return (float *)bytes;
611 }
612 
613 void
a8r8g8b8_to_rgba_np(uint32_t * dst,uint32_t * src,int n_pixels)614 a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels)
615 {
616     uint8_t *dst8 = (uint8_t *)dst;
617     int i;
618 
619     for (i = 0; i < n_pixels; ++i)
620     {
621 	uint32_t p = src[i];
622 	uint8_t a, r, g, b;
623 
624 	a = (p & 0xff000000) >> 24;
625 	r = (p & 0x00ff0000) >> 16;
626 	g = (p & 0x0000ff00) >> 8;
627 	b = (p & 0x000000ff) >> 0;
628 
629 	if (a != 0)
630 	{
631 #define DIVIDE(c, a)							\
632 	    do								\
633 	    {								\
634 		int t = ((c) * 255) / a;				\
635 		(c) = t < 0? 0 : t > 255? 255 : t;			\
636 	    } while (0)
637 
638 	    DIVIDE (r, a);
639 	    DIVIDE (g, a);
640 	    DIVIDE (b, a);
641 	}
642 
643 	*dst8++ = r;
644 	*dst8++ = g;
645 	*dst8++ = b;
646 	*dst8++ = a;
647     }
648 }
649 
650 #ifdef HAVE_LIBPNG
651 
652 pixman_bool_t
write_png(pixman_image_t * image,const char * filename)653 write_png (pixman_image_t *image, const char *filename)
654 {
655     int width = pixman_image_get_width (image);
656     int height = pixman_image_get_height (image);
657     int stride = width * 4;
658     uint32_t *data = malloc (height * stride);
659     pixman_image_t *copy;
660     png_struct *write_struct;
661     png_info *info_struct;
662     pixman_bool_t result = FALSE;
663     FILE *f = fopen (filename, "wb");
664     png_bytep *row_pointers;
665     int i;
666 
667     if (!f)
668 	return FALSE;
669 
670     row_pointers = malloc (height * sizeof (png_bytep));
671 
672     copy = pixman_image_create_bits (
673 	PIXMAN_a8r8g8b8, width, height, data, stride);
674 
675     pixman_image_composite32 (
676 	PIXMAN_OP_SRC, image, NULL, copy, 0, 0, 0, 0, 0, 0, width, height);
677 
678     a8r8g8b8_to_rgba_np (data, data, height * width);
679 
680     for (i = 0; i < height; ++i)
681 	row_pointers[i] = (png_bytep)(data + i * width);
682 
683     if (!(write_struct = png_create_write_struct (
684 	      PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
685 	goto out1;
686 
687     if (!(info_struct = png_create_info_struct (write_struct)))
688 	goto out2;
689 
690     png_init_io (write_struct, f);
691 
692     png_set_IHDR (write_struct, info_struct, width, height,
693 		  8, PNG_COLOR_TYPE_RGB_ALPHA,
694 		  PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
695 		  PNG_FILTER_TYPE_BASE);
696 
697     png_write_info (write_struct, info_struct);
698 
699     png_write_image (write_struct, row_pointers);
700 
701     png_write_end (write_struct, NULL);
702 
703     result = TRUE;
704 
705 out2:
706     png_destroy_write_struct (&write_struct, &info_struct);
707 
708 out1:
709     if (fclose (f) != 0)
710 	result = FALSE;
711 
712     pixman_image_unref (copy);
713     free (row_pointers);
714     free (data);
715     return result;
716 }
717 
718 #else /* no libpng */
719 
720 pixman_bool_t
write_png(pixman_image_t * image,const char * filename)721 write_png (pixman_image_t *image, const char *filename)
722 {
723     return FALSE;
724 }
725 
726 #endif
727 
728 static void
color8_to_color16(uint32_t color8,pixman_color_t * color16)729 color8_to_color16 (uint32_t color8, pixman_color_t *color16)
730 {
731     color16->alpha = ((color8 & 0xff000000) >> 24);
732     color16->red =   ((color8 & 0x00ff0000) >> 16);
733     color16->green = ((color8 & 0x0000ff00) >> 8);
734     color16->blue =  ((color8 & 0x000000ff) >> 0);
735 
736     color16->alpha |= color16->alpha << 8;
737     color16->red   |= color16->red << 8;
738     color16->blue  |= color16->blue << 8;
739     color16->green |= color16->green << 8;
740 }
741 
742 void
draw_checkerboard(pixman_image_t * image,int check_size,uint32_t color1,uint32_t color2)743 draw_checkerboard (pixman_image_t *image,
744 		   int check_size,
745 		   uint32_t color1, uint32_t color2)
746 {
747     pixman_color_t check1, check2;
748     pixman_image_t *c1, *c2;
749     int n_checks_x, n_checks_y;
750     int i, j;
751 
752     color8_to_color16 (color1, &check1);
753     color8_to_color16 (color2, &check2);
754 
755     c1 = pixman_image_create_solid_fill (&check1);
756     c2 = pixman_image_create_solid_fill (&check2);
757 
758     n_checks_x = (
759 	pixman_image_get_width (image) + check_size - 1) / check_size;
760     n_checks_y = (
761 	pixman_image_get_height (image) + check_size - 1) / check_size;
762 
763     for (j = 0; j < n_checks_y; j++)
764     {
765 	for (i = 0; i < n_checks_x; i++)
766 	{
767 	    pixman_image_t *src;
768 
769 	    if (((i ^ j) & 1))
770 		src = c1;
771 	    else
772 		src = c2;
773 
774 	    pixman_image_composite32 (PIXMAN_OP_SRC, src, NULL, image,
775 				      0, 0, 0, 0,
776 				      i * check_size, j * check_size,
777 				      check_size, check_size);
778 	}
779     }
780 }
781 
782 static uint32_t
call_test_function(uint32_t (* test_function)(int testnum,int verbose),int testnum,int verbose)783 call_test_function (uint32_t    (*test_function)(int testnum, int verbose),
784 		    int		testnum,
785 		    int		verbose)
786 {
787     uint32_t retval;
788 
789 #if defined (__GNUC__) && defined (_WIN32) && (defined (__i386) || defined (__i386__))
790     __asm__ (
791 	/* Deliberately avoid aligning the stack to 16 bytes */
792 	"pushl	%1\n\t"
793 	"pushl	%2\n\t"
794 	"call	*%3\n\t"
795 	"addl	$8, %%esp\n\t"
796 	: "=a" (retval)
797 	: "r" (verbose),
798 	  "r" (testnum),
799 	  "r" (test_function)
800 	: "edx", "ecx"); /* caller save registers */
801 #else
802     retval = test_function (testnum, verbose);
803 #endif
804 
805     return retval;
806 }
807 
808 /*
809  * A function, which can be used as a core part of the test programs,
810  * intended to detect various problems with the help of fuzzing input
811  * to pixman API (according to some templates, aka "smart" fuzzing).
812  * Some general information about such testing can be found here:
813  * http://en.wikipedia.org/wiki/Fuzz_testing
814  *
815  * It may help detecting:
816  *  - crashes on bad handling of valid or reasonably invalid input to
817  *    pixman API.
818  *  - deviations from the behavior of older pixman releases.
819  *  - deviations from the behavior of the same pixman release, but
820  *    configured in a different way (for example with SIMD optimizations
821  *    disabled), or running on a different OS or hardware.
822  *
823  * The test is performed by calling a callback function a huge number
824  * of times. The callback function is expected to run some snippet of
825  * pixman code with pseudorandom variations to the data feeded to
826  * pixman API. A result of running each callback function should be
827  * some deterministic value which depends on test number (test number
828  * can be used as a seed for PRNG). When 'verbose' argument is nonzero,
829  * callback function is expected to print to stdout some information
830  * about what it does.
831  *
832  * Return values from many small tests are accumulated together and
833  * used as final checksum, which can be compared to some expected
834  * value. Running the tests not individually, but in a batch helps
835  * to reduce process start overhead and also allows to parallelize
836  * testing and utilize multiple CPU cores.
837  *
838  * The resulting executable can be run without any arguments. In
839  * this case it runs a batch of tests starting from 1 and up to
840  * 'default_number_of_iterations'. The resulting checksum is
841  * compared with 'expected_checksum' and FAIL or PASS verdict
842  * depends on the result of this comparison.
843  *
844  * If the executable is run with 2 numbers provided as command line
845  * arguments, they specify the starting and ending numbers for a test
846  * batch.
847  *
848  * If the executable is run with only one number provided as a command
849  * line argument, then this number is used to call the callback function
850  * once, and also with verbose flag set.
851  */
852 int
fuzzer_test_main(const char * test_name,int default_number_of_iterations,uint32_t expected_checksum,uint32_t (* test_function)(int testnum,int verbose),int argc,const char * argv[])853 fuzzer_test_main (const char *test_name,
854 		  int         default_number_of_iterations,
855 		  uint32_t    expected_checksum,
856 		  uint32_t    (*test_function)(int testnum, int verbose),
857 		  int         argc,
858 		  const char *argv[])
859 {
860     int i, n1 = 1, n2 = 0;
861     uint32_t checksum = 0;
862     int verbose = getenv ("VERBOSE") != NULL;
863 
864     if (argc >= 3)
865     {
866 	n1 = atoi (argv[1]);
867 	n2 = atoi (argv[2]);
868 	if (n2 < n1)
869 	{
870 	    printf ("invalid test range\n");
871 	    return 1;
872 	}
873     }
874     else if (argc >= 2)
875     {
876 	n2 = atoi (argv[1]);
877 
878 	checksum = call_test_function (test_function, n2, 1);
879 
880 	printf ("%d: checksum=%08X\n", n2, checksum);
881 	return 0;
882     }
883     else
884     {
885 	n1 = 1;
886 	n2 = default_number_of_iterations;
887     }
888 
889 #ifdef USE_OPENMP
890     #pragma omp parallel for reduction(+:checksum) default(none) \
891 					shared(n1, n2, test_function, verbose)
892 #endif
893     for (i = n1; i <= n2; i++)
894     {
895 	uint32_t crc = call_test_function (test_function, i, 0);
896 	if (verbose)
897 	    printf ("%d: %08X\n", i, crc);
898 	checksum += crc;
899     }
900 
901     if (n1 == 1 && n2 == default_number_of_iterations)
902     {
903 	if (checksum == expected_checksum)
904 	{
905 	    printf ("%s test passed (checksum=%08X)\n",
906 		    test_name, checksum);
907 	}
908 	else
909 	{
910 	    printf ("%s test failed! (checksum=%08X, expected %08X)\n",
911 		    test_name, checksum, expected_checksum);
912 	    return 1;
913 	}
914     }
915     else
916     {
917 	printf ("%d-%d: checksum=%08X\n", n1, n2, checksum);
918     }
919 
920     return 0;
921 }
922 
923 /* Try to obtain current time in seconds */
924 double
gettime(void)925 gettime (void)
926 {
927 #ifdef HAVE_GETTIMEOFDAY
928     struct timeval tv;
929 
930     gettimeofday (&tv, NULL);
931     return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
932 #else
933     return (double)clock() / (double)CLOCKS_PER_SEC;
934 #endif
935 }
936 
937 uint32_t
get_random_seed(void)938 get_random_seed (void)
939 {
940     union { double d; uint32_t u32; } t;
941     t.d = gettime();
942     prng_srand (t.u32);
943 
944     return prng_rand ();
945 }
946 
947 #ifdef HAVE_SIGACTION
948 #ifdef HAVE_ALARM
949 static const char *global_msg;
950 
951 static void
on_alarm(int signo)952 on_alarm (int signo)
953 {
954     printf ("%s\n", global_msg);
955     exit (1);
956 }
957 #endif
958 #endif
959 
960 void
fail_after(int seconds,const char * msg)961 fail_after (int seconds, const char *msg)
962 {
963 #ifdef HAVE_SIGACTION
964 #ifdef HAVE_ALARM
965     struct sigaction action;
966 
967     global_msg = msg;
968 
969     memset (&action, 0, sizeof (action));
970     action.sa_handler = on_alarm;
971 
972     alarm (seconds);
973 
974     sigaction (SIGALRM, &action, NULL);
975 #endif
976 #endif
977 }
978 
979 void
enable_divbyzero_exceptions(void)980 enable_divbyzero_exceptions (void)
981 {
982 #ifdef HAVE_FENV_H
983 #ifdef HAVE_FEENABLEEXCEPT
984 #ifdef HAVE_FEDIVBYZERO
985     feenableexcept (FE_DIVBYZERO);
986 #endif
987 #endif
988 #endif
989 }
990 
991 void
enable_invalid_exceptions(void)992 enable_invalid_exceptions (void)
993 {
994 #ifdef HAVE_FENV_H
995 #ifdef HAVE_FEENABLEEXCEPT
996 #ifdef FE_INVALID
997     feenableexcept (FE_INVALID);
998 #endif
999 #endif
1000 #endif
1001 }
1002 
1003 void *
aligned_malloc(size_t align,size_t size)1004 aligned_malloc (size_t align, size_t size)
1005 {
1006     void *result;
1007 
1008 #ifdef HAVE_POSIX_MEMALIGN
1009     if (posix_memalign (&result, align, size) != 0)
1010       result = NULL;
1011 #else
1012     result = malloc (size);
1013 #endif
1014 
1015     return result;
1016 }
1017 
1018 #define CONVERT_15(c, is_rgb)						\
1019     (is_rgb?								\
1020      ((((c) >> 3) & 0x001f) |						\
1021       (((c) >> 6) & 0x03e0) |						\
1022       (((c) >> 9) & 0x7c00)) :						\
1023      (((((c) >> 16) & 0xff) * 153 +					\
1024        (((c) >>  8) & 0xff) * 301 +					\
1025        (((c)      ) & 0xff) * 58) >> 2))
1026 
1027 double
convert_srgb_to_linear(double c)1028 convert_srgb_to_linear (double c)
1029 {
1030     if (c <= 0.04045)
1031         return c / 12.92;
1032     else
1033         return pow ((c + 0.055) / 1.055, 2.4);
1034 }
1035 
1036 double
convert_linear_to_srgb(double c)1037 convert_linear_to_srgb (double c)
1038 {
1039     if (c <= 0.0031308)
1040         return c * 12.92;
1041     else
1042         return 1.055 * pow (c, 1.0/2.4) - 0.055;
1043 }
1044 
1045 void
initialize_palette(pixman_indexed_t * palette,uint32_t depth,int is_rgb)1046 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
1047 {
1048     int i;
1049     uint32_t mask = (1 << depth) - 1;
1050 
1051     for (i = 0; i < 32768; ++i)
1052 	palette->ent[i] = prng_rand() & mask;
1053 
1054     memset (palette->rgba, 0, sizeof (palette->rgba));
1055 
1056     for (i = 0; i < mask + 1; ++i)
1057     {
1058 	uint32_t rgba24;
1059  	pixman_bool_t retry;
1060 	uint32_t i15;
1061 
1062 	/* We filled the rgb->index map with random numbers, but we
1063 	 * do need the ability to round trip, that is if some indexed
1064 	 * color expands to an argb24, then the 15 bit version of that
1065 	 * color must map back to the index. Anything else, we don't
1066 	 * care about too much.
1067 	 */
1068 	do
1069 	{
1070 	    uint32_t old_idx;
1071 
1072 	    rgba24 = prng_rand();
1073 	    i15 = CONVERT_15 (rgba24, is_rgb);
1074 
1075 	    old_idx = palette->ent[i15];
1076 	    if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15)
1077 		retry = 1;
1078 	    else
1079 		retry = 0;
1080 	} while (retry);
1081 
1082 	palette->rgba[i] = rgba24;
1083 	palette->ent[i15] = i;
1084     }
1085 
1086     for (i = 0; i < mask + 1; ++i)
1087     {
1088 	assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
1089     }
1090 }
1091 
1092 struct operator_entry {
1093     pixman_op_t		 op;
1094     const char		*name;
1095     pixman_bool_t	 is_alias;
1096 };
1097 
1098 typedef struct operator_entry operator_entry_t;
1099 
1100 static const operator_entry_t op_list[] =
1101 {
1102 #define ENTRY(op)							\
1103     { PIXMAN_OP_##op, "PIXMAN_OP_" #op, FALSE }
1104 #define ALIAS(op, nam)							\
1105     { PIXMAN_OP_##op, nam, TRUE }
1106 
1107     /* operator_name () will return the first hit in this table,
1108      * so keep the list properly ordered between entries and aliases.
1109      * Aliases are not listed by list_operators ().
1110      */
1111 
1112     ENTRY (CLEAR),
1113     ENTRY (SRC),
1114     ENTRY (DST),
1115     ENTRY (OVER),
1116     ENTRY (OVER_REVERSE),
1117     ALIAS (OVER_REVERSE,		"overrev"),
1118     ENTRY (IN),
1119     ENTRY (IN_REVERSE),
1120     ALIAS (IN_REVERSE,			"inrev"),
1121     ENTRY (OUT),
1122     ENTRY (OUT_REVERSE),
1123     ALIAS (OUT_REVERSE,			"outrev"),
1124     ENTRY (ATOP),
1125     ENTRY (ATOP_REVERSE),
1126     ALIAS (ATOP_REVERSE,		"atoprev"),
1127     ENTRY (XOR),
1128     ENTRY (ADD),
1129     ENTRY (SATURATE),
1130 
1131     ENTRY (DISJOINT_CLEAR),
1132     ENTRY (DISJOINT_SRC),
1133     ENTRY (DISJOINT_DST),
1134     ENTRY (DISJOINT_OVER),
1135     ENTRY (DISJOINT_OVER_REVERSE),
1136     ENTRY (DISJOINT_IN),
1137     ENTRY (DISJOINT_IN_REVERSE),
1138     ENTRY (DISJOINT_OUT),
1139     ENTRY (DISJOINT_OUT_REVERSE),
1140     ENTRY (DISJOINT_ATOP),
1141     ENTRY (DISJOINT_ATOP_REVERSE),
1142     ENTRY (DISJOINT_XOR),
1143 
1144     ENTRY (CONJOINT_CLEAR),
1145     ENTRY (CONJOINT_SRC),
1146     ENTRY (CONJOINT_DST),
1147     ENTRY (CONJOINT_OVER),
1148     ENTRY (CONJOINT_OVER_REVERSE),
1149     ENTRY (CONJOINT_IN),
1150     ENTRY (CONJOINT_IN_REVERSE),
1151     ENTRY (CONJOINT_OUT),
1152     ENTRY (CONJOINT_OUT_REVERSE),
1153     ENTRY (CONJOINT_ATOP),
1154     ENTRY (CONJOINT_ATOP_REVERSE),
1155     ENTRY (CONJOINT_XOR),
1156 
1157     ENTRY (MULTIPLY),
1158     ENTRY (SCREEN),
1159     ENTRY (OVERLAY),
1160     ENTRY (DARKEN),
1161     ENTRY (LIGHTEN),
1162     ENTRY (COLOR_DODGE),
1163     ENTRY (COLOR_BURN),
1164     ENTRY (HARD_LIGHT),
1165     ENTRY (SOFT_LIGHT),
1166     ENTRY (DIFFERENCE),
1167     ENTRY (EXCLUSION),
1168     ENTRY (HSL_HUE),
1169     ENTRY (HSL_SATURATION),
1170     ENTRY (HSL_COLOR),
1171     ENTRY (HSL_LUMINOSITY),
1172 
1173     ALIAS (NONE, "<invalid operator 'none'>")
1174 
1175 #undef ENTRY
1176 #undef ALIAS
1177 };
1178 
1179 typedef struct {
1180     pixman_dither_t	 dither;
1181     const char		*name;
1182     pixman_bool_t	 is_alias;
1183 } dither_entry_t;
1184 
1185 static const dither_entry_t dither_list[] =
1186 {
1187 #define ENTRY(dither)							\
1188     { PIXMAN_DITHER_##dither, "PIXMAN_DITHER_" #dither, FALSE }
1189 #define ALIAS(dither, nam)							\
1190     { PIXMAN_DITHER_##dither, nam, TRUE }
1191 
1192     /* dither_name () will return the first hit in this table,
1193      * so keep the list properly ordered between entries and aliases.
1194      * Aliases are not listed by list_dithers ().
1195      */
1196 
1197     ENTRY (ORDERED_BAYER_8),
1198     ENTRY (ORDERED_BLUE_NOISE_64),
1199     ENTRY (NONE),
1200 
1201 #undef ENTRY
1202 #undef ALIAS
1203 };
1204 
1205 struct format_entry
1206 {
1207     pixman_format_code_t format;
1208     const char		*name;
1209     pixman_bool_t	 is_alias;
1210 };
1211 
1212 typedef struct format_entry format_entry_t;
1213 
1214 static const format_entry_t format_list[] =
1215 {
1216 #define ENTRY(f)							\
1217     { PIXMAN_##f, #f, FALSE }
1218 #define ALIAS(f, nam)							\
1219     { PIXMAN_##f, nam, TRUE }
1220 
1221     /* format_name () will return the first hit in this table,
1222      * so keep the list properly ordered between entries and aliases.
1223      * Aliases are not listed by list_formats ().
1224      */
1225 
1226 /* 128bpp formats */
1227     ENTRY (rgba_float),
1228 /* 96bpp formats */
1229     ENTRY (rgb_float),
1230 
1231 /* 32bpp formats */
1232     ENTRY (a8r8g8b8),
1233     ALIAS (a8r8g8b8,		"8888"),
1234     ENTRY (x8r8g8b8),
1235     ALIAS (x8r8g8b8,		"x888"),
1236     ENTRY (a8b8g8r8),
1237     ENTRY (x8b8g8r8),
1238     ENTRY (b8g8r8a8),
1239     ENTRY (b8g8r8x8),
1240     ENTRY (r8g8b8a8),
1241     ENTRY (r8g8b8x8),
1242     ENTRY (x14r6g6b6),
1243     ENTRY (x2r10g10b10),
1244     ALIAS (x2r10g10b10,		"2x10"),
1245     ENTRY (a2r10g10b10),
1246     ALIAS (a2r10g10b10,		"2a10"),
1247     ENTRY (x2b10g10r10),
1248     ENTRY (a2b10g10r10),
1249 
1250 /* sRGB formats */
1251     ENTRY (a8r8g8b8_sRGB),
1252 
1253 /* 24bpp formats */
1254     ENTRY (r8g8b8),
1255     ALIAS (r8g8b8,		"0888"),
1256     ENTRY (b8g8r8),
1257 
1258 /* 16 bpp formats */
1259     ENTRY (r5g6b5),
1260     ALIAS (r5g6b5,		"0565"),
1261     ENTRY (b5g6r5),
1262 
1263     ENTRY (a1r5g5b5),
1264     ALIAS (a1r5g5b5,		"1555"),
1265     ENTRY (x1r5g5b5),
1266     ENTRY (a1b5g5r5),
1267     ENTRY (x1b5g5r5),
1268     ENTRY (a4r4g4b4),
1269     ALIAS (a4r4g4b4,		"4444"),
1270     ENTRY (x4r4g4b4),
1271     ENTRY (a4b4g4r4),
1272     ENTRY (x4b4g4r4),
1273 
1274 /* 8bpp formats */
1275     ENTRY (a8),
1276     ALIAS (a8,			"8"),
1277     ENTRY (r3g3b2),
1278     ENTRY (b2g3r3),
1279     ENTRY (a2r2g2b2),
1280     ALIAS (a2r2g2b2,		"2222"),
1281     ENTRY (a2b2g2r2),
1282 
1283     ALIAS (c8,			"x4c4 / c8"),
1284     /* ENTRY (c8), */
1285     ALIAS (g8,			"x4g4 / g8"),
1286     /* ENTRY (g8), */
1287 
1288     ENTRY (x4a4),
1289 
1290     /* These format codes are identical to c8 and g8, respectively. */
1291     /* ENTRY (x4c4), */
1292     /* ENTRY (x4g4), */
1293 
1294 /* 4 bpp formats */
1295     ENTRY (a4),
1296     ENTRY (r1g2b1),
1297     ENTRY (b1g2r1),
1298     ENTRY (a1r1g1b1),
1299     ENTRY (a1b1g1r1),
1300 
1301     ALIAS (c4,			"c4"),
1302     /* ENTRY (c4), */
1303     ALIAS (g4,			"g4"),
1304     /* ENTRY (g4), */
1305 
1306 /* 1bpp formats */
1307     ENTRY (a1),
1308 
1309     ALIAS (g1,			"g1"),
1310     /* ENTRY (g1), */
1311 
1312 /* YUV formats */
1313     ALIAS (yuy2,		"yuy2"),
1314     /* ENTRY (yuy2), */
1315     ALIAS (yv12,		"yv12"),
1316     /* ENTRY (yv12), */
1317 
1318 /* Fake formats, not in pixman_format_code_t enum */
1319     ALIAS (null,		"null"),
1320     ALIAS (solid,		"solid"),
1321     ALIAS (solid,		"n"),
1322     ALIAS (pixbuf,		"pixbuf"),
1323     ALIAS (rpixbuf,		"rpixbuf"),
1324     ALIAS (unknown,		"unknown"),
1325 
1326 #undef ENTRY
1327 #undef ALIAS
1328 };
1329 
1330 pixman_format_code_t
format_from_string(const char * s)1331 format_from_string (const char *s)
1332 {
1333     int i;
1334 
1335     for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
1336     {
1337         const format_entry_t *ent = &format_list[i];
1338 
1339         if (strcasecmp (ent->name, s) == 0)
1340             return ent->format;
1341     }
1342 
1343     return PIXMAN_null;
1344 }
1345 
1346 static void
emit(const char * s,int * n_chars)1347 emit (const char *s, int *n_chars)
1348 {
1349     *n_chars += printf ("%s,", s);
1350     if (*n_chars > 60)
1351     {
1352         printf ("\n    ");
1353         *n_chars = 0;
1354     }
1355     else
1356     {
1357         printf (" ");
1358         (*n_chars)++;
1359     }
1360 }
1361 
1362 void
list_formats(void)1363 list_formats (void)
1364 {
1365     int n_chars;
1366     int i;
1367 
1368     printf ("Formats:\n    ");
1369 
1370     n_chars = 0;
1371     for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
1372     {
1373         const format_entry_t *ent = &format_list[i];
1374 
1375         if (ent->is_alias)
1376             continue;
1377 
1378         emit (ent->name, &n_chars);
1379     }
1380 
1381     printf ("\n\n");
1382 }
1383 
1384 void
list_operators(void)1385 list_operators (void)
1386 {
1387     char short_name [128] = { 0 };
1388     int i, n_chars;
1389 
1390     printf ("Operators:\n    ");
1391 
1392     n_chars = 0;
1393     for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
1394     {
1395         const operator_entry_t *ent = &op_list[i];
1396         int j;
1397 
1398         if (ent->is_alias)
1399             continue;
1400 
1401         snprintf (short_name, sizeof (short_name) - 1, "%s",
1402                   ent->name + strlen ("PIXMAN_OP_"));
1403 
1404         for (j = 0; short_name[j] != '\0'; ++j)
1405             short_name[j] = tolower (short_name[j]);
1406 
1407         emit (short_name, &n_chars);
1408     }
1409 
1410     printf ("\n\n");
1411 }
1412 
1413 void
list_dithers(void)1414 list_dithers (void)
1415 {
1416     int n_chars;
1417     int i;
1418 
1419     printf ("Dithers:\n    ");
1420 
1421     n_chars = 0;
1422     for (i = 0; i < ARRAY_LENGTH (dither_list); ++i)
1423     {
1424         const dither_entry_t *ent = &dither_list[i];
1425 
1426         if (ent->is_alias)
1427             continue;
1428 
1429         emit (ent->name, &n_chars);
1430     }
1431 
1432     printf ("\n\n");
1433 }
1434 
1435 pixman_op_t
operator_from_string(const char * s)1436 operator_from_string (const char *s)
1437 {
1438     int i;
1439 
1440     for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
1441     {
1442         const operator_entry_t *ent = &op_list[i];
1443 
1444         if (ent->is_alias)
1445         {
1446             if (strcasecmp (ent->name, s) == 0)
1447                 return ent->op;
1448         }
1449         else
1450         {
1451             if (strcasecmp (ent->name + strlen ("PIXMAN_OP_"), s) == 0)
1452                 return ent->op;
1453         }
1454     }
1455 
1456     return PIXMAN_OP_NONE;
1457 }
1458 
1459 pixman_dither_t
dither_from_string(const char * s)1460 dither_from_string (const char *s)
1461 {
1462     int i;
1463 
1464     for (i = 0; i < ARRAY_LENGTH (dither_list); ++i)
1465     {
1466         const dither_entry_t *ent = &dither_list[i];
1467 
1468         if (strcasecmp (ent->name, s) == 0)
1469             return ent->dither;
1470     }
1471 
1472     return PIXMAN_DITHER_NONE;
1473 }
1474 
1475 const char *
operator_name(pixman_op_t op)1476 operator_name (pixman_op_t op)
1477 {
1478     int i;
1479 
1480     for (i = 0; i < ARRAY_LENGTH (op_list); ++i)
1481     {
1482         const operator_entry_t *ent = &op_list[i];
1483 
1484         if (ent->op == op)
1485             return ent->name;
1486     }
1487 
1488     return "<unknown operator>";
1489 }
1490 
1491 const char *
format_name(pixman_format_code_t format)1492 format_name (pixman_format_code_t format)
1493 {
1494     int i;
1495 
1496     for (i = 0; i < ARRAY_LENGTH (format_list); ++i)
1497     {
1498         const format_entry_t *ent = &format_list[i];
1499 
1500         if (ent->format == format)
1501             return ent->name;
1502     }
1503 
1504     return "<unknown format>";
1505 };
1506 
1507 const char *
dither_name(pixman_dither_t dither)1508 dither_name (pixman_dither_t dither)
1509 {
1510     int i;
1511 
1512     for (i = 0; i < ARRAY_LENGTH (dither_list); ++i)
1513     {
1514 	const dither_entry_t *ent = &dither_list[i];
1515 
1516 	if (ent->dither == dither)
1517 	    return ent->name;
1518     }
1519 
1520     return "<unknown dither>";
1521 }
1522 
1523 #define IS_ZERO(f)     (-DBL_MIN < (f) && (f) < DBL_MIN)
1524 
1525 typedef double (* blend_func_t) (double as, double s, double ad, double d);
1526 
1527 static force_inline double
blend_multiply(double sa,double s,double da,double d)1528 blend_multiply (double sa, double s, double da, double d)
1529 {
1530     return d * s;
1531 }
1532 
1533 static force_inline double
blend_screen(double sa,double s,double da,double d)1534 blend_screen (double sa, double s, double da, double d)
1535 {
1536     return d * sa + s * da - s * d;
1537 }
1538 
1539 static force_inline double
blend_overlay(double sa,double s,double da,double d)1540 blend_overlay (double sa, double s, double da, double d)
1541 {
1542     if (2 * d < da)
1543         return 2 * s * d;
1544     else
1545         return sa * da - 2 * (da - d) * (sa - s);
1546 }
1547 
1548 static force_inline double
blend_darken(double sa,double s,double da,double d)1549 blend_darken (double sa, double s, double da, double d)
1550 {
1551     s = s * da;
1552     d = d * sa;
1553 
1554     if (s > d)
1555         return d;
1556     else
1557         return s;
1558 }
1559 
1560 static force_inline double
blend_lighten(double sa,double s,double da,double d)1561 blend_lighten (double sa, double s, double da, double d)
1562 {
1563     s = s * da;
1564     d = d * sa;
1565 
1566     if (s > d)
1567         return s;
1568     else
1569         return d;
1570 }
1571 
1572 static force_inline double
blend_color_dodge(double sa,double s,double da,double d)1573 blend_color_dodge (double sa, double s, double da, double d)
1574 {
1575     if (IS_ZERO (d))
1576         return 0.0f;
1577     else if (d * sa >= sa * da - s * da)
1578         return sa * da;
1579     else if (IS_ZERO (sa - s))
1580         return sa * da;
1581     else
1582         return sa * sa * d / (sa - s);
1583 }
1584 
1585 static force_inline double
blend_color_burn(double sa,double s,double da,double d)1586 blend_color_burn (double sa, double s, double da, double d)
1587 {
1588     if (d >= da)
1589         return sa * da;
1590     else if (sa * (da - d) >= s * da)
1591         return 0.0f;
1592     else if (IS_ZERO (s))
1593         return 0.0f;
1594     else
1595         return sa * (da - sa * (da - d) / s);
1596 }
1597 
1598 static force_inline double
blend_hard_light(double sa,double s,double da,double d)1599 blend_hard_light (double sa, double s, double da, double d)
1600 {
1601     if (2 * s < sa)
1602         return 2 * s * d;
1603     else
1604         return sa * da - 2 * (da - d) * (sa - s);
1605 }
1606 
1607 static force_inline double
blend_soft_light(double sa,double s,double da,double d)1608 blend_soft_light (double sa, double s, double da, double d)
1609 {
1610     if (2 * s <= sa)
1611     {
1612         if (IS_ZERO (da))
1613             return d * sa;
1614         else
1615             return d * sa - d * (da - d) * (sa - 2 * s) / da;
1616     }
1617     else
1618     {
1619         if (IS_ZERO (da))
1620         {
1621 	    return d * sa;
1622         }
1623         else
1624         {
1625             if (4 * d <= da)
1626                 return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3);
1627             else
1628                 return d * sa + (sqrt (d * da) - d) * (2 * s - sa);
1629         }
1630     }
1631 }
1632 
1633 static force_inline double
blend_difference(double sa,double s,double da,double d)1634 blend_difference (double sa, double s, double da, double d)
1635 {
1636     double dsa = d * sa;
1637     double sda = s * da;
1638 
1639     if (sda < dsa)
1640         return dsa - sda;
1641     else
1642         return sda - dsa;
1643 }
1644 
1645 static force_inline double
blend_exclusion(double sa,double s,double da,double d)1646 blend_exclusion (double sa, double s, double da, double d)
1647 {
1648     return s * da + d * sa - 2 * d * s;
1649 }
1650 
1651 static double
clamp(double d)1652 clamp (double d)
1653 {
1654     if (d > 1.0)
1655 	return 1.0;
1656     else if (d < 0.0)
1657 	return 0.0;
1658     else
1659 	return d;
1660 }
1661 
1662 static double
blend_channel(double as,double s,double ad,double d,blend_func_t blend)1663 blend_channel (double as, double s, double ad, double d,
1664                    blend_func_t blend)
1665 {
1666     return clamp ((1 - ad) * s + (1 - as) * d + blend (as, s, ad, d));
1667 }
1668 
1669 static double
calc_op(pixman_op_t op,double src,double dst,double srca,double dsta)1670 calc_op (pixman_op_t op, double src, double dst, double srca, double dsta)
1671 {
1672 #define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0)
1673 
1674     double Fa, Fb;
1675 
1676     switch (op)
1677     {
1678     case PIXMAN_OP_CLEAR:
1679     case PIXMAN_OP_DISJOINT_CLEAR:
1680     case PIXMAN_OP_CONJOINT_CLEAR:
1681 	return mult_chan (src, dst, 0.0, 0.0);
1682 
1683     case PIXMAN_OP_SRC:
1684     case PIXMAN_OP_DISJOINT_SRC:
1685     case PIXMAN_OP_CONJOINT_SRC:
1686 	return mult_chan (src, dst, 1.0, 0.0);
1687 
1688     case PIXMAN_OP_DST:
1689     case PIXMAN_OP_DISJOINT_DST:
1690     case PIXMAN_OP_CONJOINT_DST:
1691 	return mult_chan (src, dst, 0.0, 1.0);
1692 
1693     case PIXMAN_OP_OVER:
1694 	return mult_chan (src, dst, 1.0, 1.0 - srca);
1695 
1696     case PIXMAN_OP_OVER_REVERSE:
1697 	return mult_chan (src, dst, 1.0 - dsta, 1.0);
1698 
1699     case PIXMAN_OP_IN:
1700 	return mult_chan (src, dst, dsta, 0.0);
1701 
1702     case PIXMAN_OP_IN_REVERSE:
1703 	return mult_chan (src, dst, 0.0, srca);
1704 
1705     case PIXMAN_OP_OUT:
1706 	return mult_chan (src, dst, 1.0 - dsta, 0.0);
1707 
1708     case PIXMAN_OP_OUT_REVERSE:
1709 	return mult_chan (src, dst, 0.0, 1.0 - srca);
1710 
1711     case PIXMAN_OP_ATOP:
1712 	return mult_chan (src, dst, dsta, 1.0 - srca);
1713 
1714     case PIXMAN_OP_ATOP_REVERSE:
1715 	return mult_chan (src, dst, 1.0 - dsta,  srca);
1716 
1717     case PIXMAN_OP_XOR:
1718 	return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca);
1719 
1720     case PIXMAN_OP_ADD:
1721 	return mult_chan (src, dst, 1.0, 1.0);
1722 
1723     case PIXMAN_OP_SATURATE:
1724     case PIXMAN_OP_DISJOINT_OVER_REVERSE:
1725 	if (srca == 0.0)
1726 	    Fa = 1.0;
1727 	else
1728 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
1729 	return mult_chan (src, dst, Fa, 1.0);
1730 
1731     case PIXMAN_OP_DISJOINT_OVER:
1732 	if (dsta == 0.0)
1733 	    Fb = 1.0;
1734 	else
1735 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
1736 	return mult_chan (src, dst, 1.0, Fb);
1737 
1738     case PIXMAN_OP_DISJOINT_IN:
1739 	if (srca == 0.0)
1740 	    Fa = 0.0;
1741 	else
1742 	    Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
1743 	return mult_chan (src, dst, Fa, 0.0);
1744 
1745     case PIXMAN_OP_DISJOINT_IN_REVERSE:
1746 	if (dsta == 0.0)
1747 	    Fb = 0.0;
1748 	else
1749 	    Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
1750 	return mult_chan (src, dst, 0.0, Fb);
1751 
1752     case PIXMAN_OP_DISJOINT_OUT:
1753 	if (srca == 0.0)
1754 	    Fa = 1.0;
1755 	else
1756 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
1757 	return mult_chan (src, dst, Fa, 0.0);
1758 
1759     case PIXMAN_OP_DISJOINT_OUT_REVERSE:
1760 	if (dsta == 0.0)
1761 	    Fb = 1.0;
1762 	else
1763 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
1764 	return mult_chan (src, dst, 0.0, Fb);
1765 
1766     case PIXMAN_OP_DISJOINT_ATOP:
1767 	if (srca == 0.0)
1768 	    Fa = 0.0;
1769 	else
1770 	    Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca);
1771 	if (dsta == 0.0)
1772 	    Fb = 1.0;
1773 	else
1774 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
1775 	return mult_chan (src, dst, Fa, Fb);
1776 
1777     case PIXMAN_OP_DISJOINT_ATOP_REVERSE:
1778 	if (srca == 0.0)
1779 	    Fa = 1.0;
1780 	else
1781 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
1782 	if (dsta == 0.0)
1783 	    Fb = 0.0;
1784 	else
1785 	    Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta);
1786 	return mult_chan (src, dst, Fa, Fb);
1787 
1788     case PIXMAN_OP_DISJOINT_XOR:
1789 	if (srca == 0.0)
1790 	    Fa = 1.0;
1791 	else
1792 	    Fa = MIN (1.0, (1.0 - dsta) / srca);
1793 	if (dsta == 0.0)
1794 	    Fb = 1.0;
1795 	else
1796 	    Fb = MIN (1.0, (1.0 - srca) / dsta);
1797 	return mult_chan (src, dst, Fa, Fb);
1798 
1799     case PIXMAN_OP_CONJOINT_OVER:
1800 	if (dsta == 0.0)
1801 	    Fb = 0.0;
1802 	else
1803 	    Fb = MAX (0.0, 1.0 - srca / dsta);
1804 	return mult_chan (src, dst, 1.0, Fb);
1805 
1806     case PIXMAN_OP_CONJOINT_OVER_REVERSE:
1807 	if (srca == 0.0)
1808 	    Fa = 0.0;
1809 	else
1810 	    Fa = MAX (0.0, 1.0 - dsta / srca);
1811 	return mult_chan (src, dst, Fa, 1.0);
1812 
1813     case PIXMAN_OP_CONJOINT_IN:
1814 	if (srca == 0.0)
1815 	    Fa = 1.0;
1816 	else
1817 	    Fa = MIN (1.0, dsta / srca);
1818 	return mult_chan (src, dst, Fa, 0.0);
1819 
1820     case PIXMAN_OP_CONJOINT_IN_REVERSE:
1821 	if (dsta == 0.0)
1822 	    Fb = 1.0;
1823 	else
1824 	    Fb = MIN (1.0, srca / dsta);
1825 	return mult_chan (src, dst, 0.0, Fb);
1826 
1827     case PIXMAN_OP_CONJOINT_OUT:
1828 	if (srca == 0.0)
1829 	    Fa = 0.0;
1830 	else
1831 	    Fa = MAX (0.0, 1.0 - dsta / srca);
1832 	return mult_chan (src, dst, Fa, 0.0);
1833 
1834     case PIXMAN_OP_CONJOINT_OUT_REVERSE:
1835 	if (dsta == 0.0)
1836 	    Fb = 0.0;
1837 	else
1838 	    Fb = MAX (0.0, 1.0 - srca / dsta);
1839 	return mult_chan (src, dst, 0.0, Fb);
1840 
1841     case PIXMAN_OP_CONJOINT_ATOP:
1842 	if (srca == 0.0)
1843 	    Fa = 1.0;
1844 	else
1845 	    Fa = MIN (1.0, dsta / srca);
1846 	if (dsta == 0.0)
1847 	    Fb = 0.0;
1848 	else
1849 	    Fb = MAX (0.0, 1.0 - srca / dsta);
1850 	return mult_chan (src, dst, Fa, Fb);
1851 
1852     case PIXMAN_OP_CONJOINT_ATOP_REVERSE:
1853 	if (srca == 0.0)
1854 	    Fa = 0.0;
1855 	else
1856 	    Fa = MAX (0.0, 1.0 - dsta / srca);
1857 	if (dsta == 0.0)
1858 	    Fb = 1.0;
1859 	else
1860 	    Fb = MIN (1.0, srca / dsta);
1861 	return mult_chan (src, dst, Fa, Fb);
1862 
1863     case PIXMAN_OP_CONJOINT_XOR:
1864 	if (srca == 0.0)
1865 	    Fa = 0.0;
1866 	else
1867 	    Fa = MAX (0.0, 1.0 - dsta / srca);
1868 	if (dsta == 0.0)
1869 	    Fb = 0.0;
1870 	else
1871 	    Fb = MAX (0.0, 1.0 - srca / dsta);
1872 	return mult_chan (src, dst, Fa, Fb);
1873 
1874     case PIXMAN_OP_MULTIPLY:
1875     case PIXMAN_OP_SCREEN:
1876     case PIXMAN_OP_OVERLAY:
1877     case PIXMAN_OP_DARKEN:
1878     case PIXMAN_OP_LIGHTEN:
1879     case PIXMAN_OP_COLOR_DODGE:
1880     case PIXMAN_OP_COLOR_BURN:
1881     case PIXMAN_OP_HARD_LIGHT:
1882     case PIXMAN_OP_SOFT_LIGHT:
1883     case PIXMAN_OP_DIFFERENCE:
1884     case PIXMAN_OP_EXCLUSION:
1885     case PIXMAN_OP_HSL_HUE:
1886     case PIXMAN_OP_HSL_SATURATION:
1887     case PIXMAN_OP_HSL_COLOR:
1888     case PIXMAN_OP_HSL_LUMINOSITY:
1889     default:
1890 	abort();
1891 	return 0; /* silence MSVC */
1892     }
1893 #undef mult_chan
1894 }
1895 
1896 void
do_composite(pixman_op_t op,const color_t * src,const color_t * mask,const color_t * dst,color_t * result,pixman_bool_t component_alpha)1897 do_composite (pixman_op_t op,
1898 	      const color_t *src,
1899 	      const color_t *mask,
1900 	      const color_t *dst,
1901 	      color_t *result,
1902 	      pixman_bool_t component_alpha)
1903 {
1904     color_t srcval, srcalpha;
1905 
1906     static const blend_func_t blend_funcs[] =
1907     {
1908         blend_multiply,
1909         blend_screen,
1910         blend_overlay,
1911         blend_darken,
1912         blend_lighten,
1913         blend_color_dodge,
1914         blend_color_burn,
1915         blend_hard_light,
1916         blend_soft_light,
1917         blend_difference,
1918         blend_exclusion,
1919     };
1920 
1921     if (mask == NULL)
1922     {
1923 	srcval = *src;
1924 
1925 	srcalpha.r = src->a;
1926 	srcalpha.g = src->a;
1927 	srcalpha.b = src->a;
1928 	srcalpha.a = src->a;
1929     }
1930     else if (component_alpha)
1931     {
1932 	srcval.r = src->r * mask->r;
1933 	srcval.g = src->g * mask->g;
1934 	srcval.b = src->b * mask->b;
1935 	srcval.a = src->a * mask->a;
1936 
1937 	srcalpha.r = src->a * mask->r;
1938 	srcalpha.g = src->a * mask->g;
1939 	srcalpha.b = src->a * mask->b;
1940 	srcalpha.a = src->a * mask->a;
1941     }
1942     else
1943     {
1944 	srcval.r = src->r * mask->a;
1945 	srcval.g = src->g * mask->a;
1946 	srcval.b = src->b * mask->a;
1947 	srcval.a = src->a * mask->a;
1948 
1949 	srcalpha.r = src->a * mask->a;
1950 	srcalpha.g = src->a * mask->a;
1951 	srcalpha.b = src->a * mask->a;
1952 	srcalpha.a = src->a * mask->a;
1953     }
1954 
1955     if (op >= PIXMAN_OP_MULTIPLY)
1956     {
1957         blend_func_t func = blend_funcs[op - PIXMAN_OP_MULTIPLY];
1958 
1959 	result->a = srcalpha.a + dst->a - srcalpha.a * dst->a;
1960 	result->r = blend_channel (srcalpha.r, srcval.r, dst->a, dst->r, func);
1961 	result->g = blend_channel (srcalpha.g, srcval.g, dst->a, dst->g, func);
1962 	result->b = blend_channel (srcalpha.b, srcval.b, dst->a, dst->b, func);
1963     }
1964     else
1965     {
1966         result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a);
1967         result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a);
1968         result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a);
1969         result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a);
1970     }
1971 }
1972 
1973 static double
round_channel(double p,int m)1974 round_channel (double p, int m)
1975 {
1976     int t;
1977     double r;
1978 
1979     t = p * ((1 << m));
1980     t -= t >> m;
1981 
1982     r = t / (double)((1 << m) - 1);
1983 
1984     return r;
1985 }
1986 
1987 void
round_color(pixman_format_code_t format,color_t * color)1988 round_color (pixman_format_code_t format, color_t *color)
1989 {
1990     if (PIXMAN_FORMAT_R (format) == 0)
1991     {
1992 	color->r = 0.0;
1993 	color->g = 0.0;
1994 	color->b = 0.0;
1995     }
1996     else
1997     {
1998 	color->r = round_channel (color->r, PIXMAN_FORMAT_R (format));
1999 	color->g = round_channel (color->g, PIXMAN_FORMAT_G (format));
2000 	color->b = round_channel (color->b, PIXMAN_FORMAT_B (format));
2001     }
2002 
2003     if (PIXMAN_FORMAT_A (format) == 0)
2004 	color->a = 1;
2005     else
2006 	color->a = round_channel (color->a, PIXMAN_FORMAT_A (format));
2007 }
2008 
2009 /* The acceptable deviation in units of [0.0, 1.0]
2010  */
2011 #define DEVIATION (0.0128)
2012 
2013 /* Check whether @pixel is a valid quantization of the a, r, g, b
2014  * parameters. Some slack is permitted.
2015  */
2016 void
pixel_checker_init(pixel_checker_t * checker,pixman_format_code_t format)2017 pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
2018 {
2019     assert (PIXMAN_FORMAT_VIS (format));
2020 
2021     checker->format = format;
2022 
2023     if (format == PIXMAN_rgba_float ||
2024 	format == PIXMAN_rgb_float)
2025 	return;
2026 
2027     switch (PIXMAN_FORMAT_TYPE (format))
2028     {
2029     case PIXMAN_TYPE_A:
2030 	checker->bs = 0;
2031 	checker->gs = 0;
2032 	checker->rs = 0;
2033 	checker->as = 0;
2034 	break;
2035 
2036     case PIXMAN_TYPE_ARGB:
2037     case PIXMAN_TYPE_ARGB_SRGB:
2038 	checker->bs = 0;
2039 	checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
2040 	checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
2041 	checker->as = checker->rs + PIXMAN_FORMAT_R (format);
2042 	break;
2043 
2044     case PIXMAN_TYPE_ABGR:
2045 	checker->rs = 0;
2046 	checker->gs = checker->rs + PIXMAN_FORMAT_R (format);
2047 	checker->bs = checker->gs + PIXMAN_FORMAT_G (format);
2048 	checker->as = checker->bs + PIXMAN_FORMAT_B (format);
2049 	break;
2050 
2051     case PIXMAN_TYPE_BGRA:
2052 	/* With BGRA formats we start counting at the high end of the pixel */
2053 	checker->bs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
2054 	checker->gs = checker->bs - PIXMAN_FORMAT_B (format);
2055 	checker->rs = checker->gs - PIXMAN_FORMAT_G (format);
2056 	checker->as = checker->rs - PIXMAN_FORMAT_R (format);
2057 	break;
2058 
2059     case PIXMAN_TYPE_RGBA:
2060 	/* With BGRA formats we start counting at the high end of the pixel */
2061 	checker->rs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
2062 	checker->gs = checker->rs - PIXMAN_FORMAT_R (format);
2063 	checker->bs = checker->gs - PIXMAN_FORMAT_G (format);
2064 	checker->as = checker->bs - PIXMAN_FORMAT_B (format);
2065 	break;
2066 
2067     default:
2068 	assert (0);
2069 	break;
2070     }
2071 
2072     checker->am = ((1U << PIXMAN_FORMAT_A (format)) - 1) << checker->as;
2073     checker->rm = ((1U << PIXMAN_FORMAT_R (format)) - 1) << checker->rs;
2074     checker->gm = ((1U << PIXMAN_FORMAT_G (format)) - 1) << checker->gs;
2075     checker->bm = ((1U << PIXMAN_FORMAT_B (format)) - 1) << checker->bs;
2076 
2077     checker->aw = PIXMAN_FORMAT_A (format);
2078     checker->rw = PIXMAN_FORMAT_R (format);
2079     checker->gw = PIXMAN_FORMAT_G (format);
2080     checker->bw = PIXMAN_FORMAT_B (format);
2081 
2082     checker->ad = DEVIATION;
2083     checker->rd = DEVIATION;
2084     checker->gd = DEVIATION;
2085     checker->bd = DEVIATION;
2086 }
2087 
2088 /* When dithering is enabled, we allow one extra pixel of tolerance
2089  */
2090 void
pixel_checker_allow_dither(pixel_checker_t * checker)2091 pixel_checker_allow_dither (pixel_checker_t *checker)
2092 {
2093     checker->ad += 1 / (double)((1 << checker->aw) - 1);
2094     checker->rd += 1 / (double)((1 << checker->rw) - 1);
2095     checker->gd += 1 / (double)((1 << checker->gw) - 1);
2096     checker->bd += 1 / (double)((1 << checker->bw) - 1);
2097 }
2098 
2099 static void
pixel_checker_require_uint32_format(const pixel_checker_t * checker)2100 pixel_checker_require_uint32_format (const pixel_checker_t *checker)
2101 {
2102     assert (checker->format != PIXMAN_rgba_float &&
2103 	    checker->format != PIXMAN_rgb_float);
2104 }
2105 
2106 void
pixel_checker_split_pixel(const pixel_checker_t * checker,uint32_t pixel,int * a,int * r,int * g,int * b)2107 pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
2108 			   int *a, int *r, int *g, int *b)
2109 {
2110     pixel_checker_require_uint32_format(checker);
2111 
2112     *a = (pixel & checker->am) >> checker->as;
2113     *r = (pixel & checker->rm) >> checker->rs;
2114     *g = (pixel & checker->gm) >> checker->gs;
2115     *b = (pixel & checker->bm) >> checker->bs;
2116 }
2117 
2118 void
pixel_checker_get_masks(const pixel_checker_t * checker,uint32_t * am,uint32_t * rm,uint32_t * gm,uint32_t * bm)2119 pixel_checker_get_masks (const pixel_checker_t *checker,
2120                          uint32_t              *am,
2121                          uint32_t              *rm,
2122                          uint32_t              *gm,
2123                          uint32_t              *bm)
2124 {
2125     pixel_checker_require_uint32_format(checker);
2126 
2127     if (am)
2128         *am = checker->am;
2129     if (rm)
2130         *rm = checker->rm;
2131     if (gm)
2132         *gm = checker->gm;
2133     if (bm)
2134         *bm = checker->bm;
2135 }
2136 
2137 void
pixel_checker_convert_pixel_to_color(const pixel_checker_t * checker,uint32_t pixel,color_t * color)2138 pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker,
2139                                       uint32_t pixel, color_t *color)
2140 {
2141     int a, r, g, b;
2142 
2143     pixel_checker_require_uint32_format(checker);
2144 
2145     pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b);
2146 
2147     if (checker->am == 0)
2148         color->a = 1.0;
2149     else
2150         color->a = a / (double)(checker->am >> checker->as);
2151 
2152     if (checker->rm == 0)
2153         color->r = 0.0;
2154     else
2155         color->r = r / (double)(checker->rm >> checker->rs);
2156 
2157     if (checker->gm == 0)
2158         color->g = 0.0;
2159     else
2160         color->g = g / (double)(checker->gm >> checker->gs);
2161 
2162     if (checker->bm == 0)
2163         color->b = 0.0;
2164     else
2165         color->b = b / (double)(checker->bm >> checker->bs);
2166 
2167     if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
2168     {
2169 	color->r = convert_srgb_to_linear (color->r);
2170 	color->g = convert_srgb_to_linear (color->g);
2171 	color->b = convert_srgb_to_linear (color->b);
2172     }
2173 }
2174 
2175 static int32_t
convert(double v,uint32_t width,uint32_t mask,uint32_t shift,double def)2176 convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def)
2177 {
2178     int32_t r;
2179 
2180     if (!mask)
2181 	v = def;
2182 
2183     r = (v * ((mask >> shift) + 1));
2184     r -= r >> width;
2185 
2186     return r;
2187 }
2188 
2189 static void
get_limits(const pixel_checker_t * checker,double sign,color_t * color,int * ao,int * ro,int * go,int * bo)2190 get_limits (const pixel_checker_t *checker, double sign,
2191 	    color_t *color,
2192 	    int *ao, int *ro, int *go, int *bo)
2193 {
2194     color_t tmp;
2195 
2196     if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB)
2197     {
2198 	tmp.a = color->a;
2199 	tmp.r = convert_linear_to_srgb (color->r);
2200 	tmp.g = convert_linear_to_srgb (color->g);
2201 	tmp.b = convert_linear_to_srgb (color->b);
2202 
2203 	color = &tmp;
2204     }
2205 
2206     *ao = convert (color->a + sign * checker->ad,
2207 		   checker->aw, checker->am, checker->as, 1.0);
2208     *ro = convert (color->r + sign * checker->rd,
2209 		   checker->rw, checker->rm, checker->rs, 0.0);
2210     *go = convert (color->g + sign * checker->gd,
2211 		   checker->gw, checker->gm, checker->gs, 0.0);
2212     *bo = convert (color->b + sign * checker->bd,
2213 		   checker->bw, checker->bm, checker->bs, 0.0);
2214 }
2215 
2216 void
pixel_checker_get_max(const pixel_checker_t * checker,color_t * color,int * am,int * rm,int * gm,int * bm)2217 pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
2218 		       int *am, int *rm, int *gm, int *bm)
2219 {
2220     pixel_checker_require_uint32_format(checker);
2221 
2222     get_limits (checker, 1, color, am, rm, gm, bm);
2223 }
2224 
2225 void
pixel_checker_get_min(const pixel_checker_t * checker,color_t * color,int * am,int * rm,int * gm,int * bm)2226 pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
2227 		       int *am, int *rm, int *gm, int *bm)
2228 {
2229     pixel_checker_require_uint32_format(checker);
2230 
2231     get_limits (checker, - 1, color, am, rm, gm, bm);
2232 }
2233 
2234 pixman_bool_t
pixel_checker_check(const pixel_checker_t * checker,uint32_t pixel,color_t * color)2235 pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
2236 		     color_t *color)
2237 {
2238     int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
2239     int32_t ai, ri, gi, bi;
2240     pixman_bool_t result;
2241 
2242     pixel_checker_require_uint32_format(checker);
2243 
2244     pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
2245     pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
2246     pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
2247 
2248     result =
2249 	a_lo <= ai && ai <= a_hi	&&
2250 	r_lo <= ri && ri <= r_hi	&&
2251 	g_lo <= gi && gi <= g_hi	&&
2252 	b_lo <= bi && bi <= b_hi;
2253 
2254     return result;
2255 }
2256 
2257 static void
color_limits(const pixel_checker_t * checker,double limit,const color_t * color,color_t * out)2258 color_limits (const pixel_checker_t *checker,
2259 	      double limit, const color_t *color, color_t *out)
2260 {
2261     if (PIXMAN_FORMAT_A(checker->format))
2262 	out->a = color->a + limit;
2263     else
2264 	out->a = 1.;
2265 
2266     out->r = color->r + limit;
2267     out->g = color->g + limit;
2268     out->b = color->b + limit;
2269 }
2270 
2271 pixman_bool_t
pixel_checker_check_color(const pixel_checker_t * checker,const color_t * actual,const color_t * reference)2272 pixel_checker_check_color (const pixel_checker_t *checker,
2273 			   const color_t *actual, const color_t *reference)
2274 {
2275     color_t min, max;
2276     pixman_bool_t result;
2277 
2278     color_limits(checker, -DEVIATION, reference, &min);
2279     color_limits(checker, DEVIATION, reference, &max);
2280 
2281     result =
2282 	actual->a >= min.a && actual->a <= max.a &&
2283 	actual->r >= min.r && actual->r <= max.r &&
2284 	actual->g >= min.g && actual->g <= max.g &&
2285 	actual->b >= min.b && actual->b <= max.b;
2286 
2287     return result;
2288 }
2289