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