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