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