test/utils.c: Rename and export the pngify_pixels() function.
[profile/ivi/pixman.git] / test / utils.c
1 #define _GNU_SOURCE
2
3 #include "utils.h"
4 #include <signal.h>
5 #include <stdlib.h>
6
7 #ifdef HAVE_GETTIMEOFDAY
8 #include <sys/time.h>
9 #else
10 #include <time.h>
11 #endif
12
13 #ifdef HAVE_UNISTD_H
14 #include <unistd.h>
15 #endif
16
17 #ifdef HAVE_SYS_MMAN_H
18 #include <sys/mman.h>
19 #endif
20
21 #ifdef HAVE_FENV_H
22 #include <fenv.h>
23 #endif
24
25 #ifdef HAVE_LIBPNG
26 #include <png.h>
27 #endif
28
29 /* Random number seed
30  */
31
32 uint32_t lcg_seed;
33
34 /*----------------------------------------------------------------------------*\
35  *  CRC-32 version 2.0.0 by Craig Bruce, 2006-04-29.
36  *
37  *  This program generates the CRC-32 values for the files named in the
38  *  command-line arguments.  These are the same CRC-32 values used by GZIP,
39  *  PKZIP, and ZMODEM.  The Crc32_ComputeBuf () can also be detached and
40  *  used independently.
41  *
42  *  THIS PROGRAM IS PUBLIC-DOMAIN SOFTWARE.
43  *
44  *  Based on the byte-oriented implementation "File Verification Using CRC"
45  *  by Mark R. Nelson in Dr. Dobb's Journal, May 1992, pp. 64-67.
46  *
47  *  v1.0.0: original release.
48  *  v1.0.1: fixed printf formats.
49  *  v1.0.2: fixed something else.
50  *  v1.0.3: replaced CRC constant table by generator function.
51  *  v1.0.4: reformatted code, made ANSI C.  1994-12-05.
52  *  v2.0.0: rewrote to use memory buffer & static table, 2006-04-29.
53 \*----------------------------------------------------------------------------*/
54
55 /*----------------------------------------------------------------------------*\
56  *  NAME:
57  *     Crc32_ComputeBuf () - computes the CRC-32 value of a memory buffer
58  *  DESCRIPTION:
59  *     Computes or accumulates the CRC-32 value for a memory buffer.
60  *     The 'inCrc32' gives a previously accumulated CRC-32 value to allow
61  *     a CRC to be generated for multiple sequential buffer-fuls of data.
62  *     The 'inCrc32' for the first buffer must be zero.
63  *  ARGUMENTS:
64  *     inCrc32 - accumulated CRC-32 value, must be 0 on first call
65  *     buf     - buffer to compute CRC-32 value for
66  *     bufLen  - number of bytes in buffer
67  *  RETURNS:
68  *     crc32 - computed CRC-32 value
69  *  ERRORS:
70  *     (no errors are possible)
71 \*----------------------------------------------------------------------------*/
72
73 uint32_t
74 compute_crc32 (uint32_t    in_crc32,
75                const void *buf,
76                size_t      buf_len)
77 {
78     static const uint32_t crc_table[256] = {
79         0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
80         0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
81         0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
82         0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
83         0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
84         0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
85         0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
86         0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
87         0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
88         0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
89         0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
90         0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
91         0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
92         0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
93         0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
94         0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
95         0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
96         0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
97         0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
98         0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
99         0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
100         0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
101         0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
102         0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
103         0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
104         0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
105         0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
106         0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
107         0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
108         0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
109         0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
110         0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
111         0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
112         0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
113         0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
114         0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
115         0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
116         0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
117         0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
118         0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
119         0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
120         0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
121         0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
122     };
123
124     uint32_t              crc32;
125     unsigned char *       byte_buf;
126     size_t                i;
127
128     /* accumulate crc32 for buffer */
129     crc32 = in_crc32 ^ 0xFFFFFFFF;
130     byte_buf = (unsigned char*) buf;
131
132     for (i = 0; i < buf_len; i++)
133         crc32 = (crc32 >> 8) ^ crc_table[(crc32 ^ byte_buf[i]) & 0xFF];
134
135     return (crc32 ^ 0xFFFFFFFF);
136 }
137
138 pixman_bool_t
139 is_little_endian (void)
140 {
141     volatile uint16_t endian_check_var = 0x1234;
142
143     return (*(volatile uint8_t *)&endian_check_var == 0x34);
144 }
145
146 /* perform endian conversion of pixel data
147  */
148 void
149 image_endian_swap (pixman_image_t *img)
150 {
151     int stride = pixman_image_get_stride (img);
152     uint32_t *data = pixman_image_get_data (img);
153     int height = pixman_image_get_height (img);
154     int bpp = PIXMAN_FORMAT_BPP (pixman_image_get_format (img));
155     int i, j;
156
157     /* swap bytes only on big endian systems */
158     if (is_little_endian())
159         return;
160
161     if (bpp == 8)
162         return;
163
164     for (i = 0; i < height; i++)
165     {
166         uint8_t *line_data = (uint8_t *)data + stride * i;
167         
168         switch (bpp)
169         {
170         case 1:
171             for (j = 0; j < stride; j++)
172             {
173                 line_data[j] =
174                     ((line_data[j] & 0x80) >> 7) |
175                     ((line_data[j] & 0x40) >> 5) |
176                     ((line_data[j] & 0x20) >> 3) |
177                     ((line_data[j] & 0x10) >> 1) |
178                     ((line_data[j] & 0x08) << 1) |
179                     ((line_data[j] & 0x04) << 3) |
180                     ((line_data[j] & 0x02) << 5) |
181                     ((line_data[j] & 0x01) << 7);
182             }
183             break;
184         case 4:
185             for (j = 0; j < stride; j++)
186             {
187                 line_data[j] = (line_data[j] >> 4) | (line_data[j] << 4);
188             }
189             break;
190         case 16:
191             for (j = 0; j + 2 <= stride; j += 2)
192             {
193                 char t1 = line_data[j + 0];
194                 char t2 = line_data[j + 1];
195
196                 line_data[j + 1] = t1;
197                 line_data[j + 0] = t2;
198             }
199             break;
200         case 24:
201             for (j = 0; j + 3 <= stride; j += 3)
202             {
203                 char t1 = line_data[j + 0];
204                 char t2 = line_data[j + 1];
205                 char t3 = line_data[j + 2];
206
207                 line_data[j + 2] = t1;
208                 line_data[j + 1] = t2;
209                 line_data[j + 0] = t3;
210             }
211             break;
212         case 32:
213             for (j = 0; j + 4 <= stride; j += 4)
214             {
215                 char t1 = line_data[j + 0];
216                 char t2 = line_data[j + 1];
217                 char t3 = line_data[j + 2];
218                 char t4 = line_data[j + 3];
219
220                 line_data[j + 3] = t1;
221                 line_data[j + 2] = t2;
222                 line_data[j + 1] = t3;
223                 line_data[j + 0] = t4;
224             }
225             break;
226         default:
227             assert (FALSE);
228             break;
229         }
230     }
231 }
232
233 #define N_LEADING_PROTECTED     10
234 #define N_TRAILING_PROTECTED    10
235
236 typedef struct
237 {
238     void *addr;
239     uint32_t len;
240     uint8_t *trailing;
241     int n_bytes;
242 } info_t;
243
244 #if defined(HAVE_MPROTECT) && defined(HAVE_GETPAGESIZE) && defined(HAVE_SYS_MMAN_H) && defined(HAVE_MMAP)
245
246 /* This is apparently necessary on at least OS X */
247 #ifndef MAP_ANONYMOUS
248 #define MAP_ANONYMOUS MAP_ANON
249 #endif
250
251 void *
252 fence_malloc (int64_t len)
253 {
254     unsigned long page_size = getpagesize();
255     unsigned long page_mask = page_size - 1;
256     uint32_t n_payload_bytes = (len + page_mask) & ~page_mask;
257     uint32_t n_bytes =
258         (page_size * (N_LEADING_PROTECTED + N_TRAILING_PROTECTED + 2) +
259          n_payload_bytes) & ~page_mask;
260     uint8_t *initial_page;
261     uint8_t *leading_protected;
262     uint8_t *trailing_protected;
263     uint8_t *payload;
264     uint8_t *addr;
265
266     if (len < 0)
267         abort();
268     
269     addr = mmap (NULL, n_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS,
270                  -1, 0);
271
272     if (addr == MAP_FAILED)
273     {
274         printf ("mmap failed on %lld %u\n", (long long int)len, n_bytes);
275         return NULL;
276     }
277
278     initial_page = (uint8_t *)(((unsigned long)addr + page_mask) & ~page_mask);
279     leading_protected = initial_page + page_size;
280     payload = leading_protected + N_LEADING_PROTECTED * page_size;
281     trailing_protected = payload + n_payload_bytes;
282
283     ((info_t *)initial_page)->addr = addr;
284     ((info_t *)initial_page)->len = len;
285     ((info_t *)initial_page)->trailing = trailing_protected;
286     ((info_t *)initial_page)->n_bytes = n_bytes;
287
288     if ((mprotect (leading_protected, N_LEADING_PROTECTED * page_size,
289                   PROT_NONE) == -1) ||
290         (mprotect (trailing_protected, N_TRAILING_PROTECTED * page_size,
291                   PROT_NONE) == -1))
292     {
293         munmap (addr, n_bytes);
294         return NULL;
295     }
296
297     return payload;
298 }
299
300 void
301 fence_free (void *data)
302 {
303     uint32_t page_size = getpagesize();
304     uint8_t *payload = data;
305     uint8_t *leading_protected = payload - N_LEADING_PROTECTED * page_size;
306     uint8_t *initial_page = leading_protected - page_size;
307     info_t *info = (info_t *)initial_page;
308
309     munmap (info->addr, info->n_bytes);
310 }
311
312 #else
313
314 void *
315 fence_malloc (int64_t len)
316 {
317     return malloc (len);
318 }
319
320 void
321 fence_free (void *data)
322 {
323     free (data);
324 }
325
326 #endif
327
328 uint8_t *
329 make_random_bytes (int n_bytes)
330 {
331     uint8_t *bytes = fence_malloc (n_bytes);
332     int i;
333
334     if (!bytes)
335         return NULL;
336
337     for (i = 0; i < n_bytes; ++i)
338         bytes[i] = lcg_rand () & 0xff;
339
340     return bytes;
341 }
342
343 void
344 a8r8g8b8_to_rgba_np (uint32_t *dst, uint32_t *src, int n_pixels)
345 {
346     uint8_t *dst8 = (uint8_t *)dst;
347     int i;
348
349     for (i = 0; i < n_pixels; ++i)
350     {
351         uint32_t p = src[i];
352         uint8_t a, r, g, b;
353
354         a = (p & 0xff000000) >> 24;
355         r = (p & 0x00ff0000) >> 16;
356         g = (p & 0x0000ff00) >> 8;
357         b = (p & 0x000000ff) >> 0;
358
359         if (a != 0)
360         {
361             r = (r * 255) / a;
362             g = (g * 255) / a;
363             b = (b * 255) / a;
364         }
365
366         *dst8++ = r;
367         *dst8++ = g;
368         *dst8++ = b;
369         *dst8++ = a;
370     }
371 }
372
373 #ifdef HAVE_LIBPNG
374
375 pixman_bool_t
376 write_png (pixman_image_t *image, const char *filename)
377 {
378     int width = pixman_image_get_width (image);
379     int height = pixman_image_get_height (image);
380     int stride = width * 4;
381     uint32_t *data = malloc (height * stride);
382     pixman_image_t *copy;
383     png_struct *write_struct;
384     png_info *info_struct;
385     pixman_bool_t result = FALSE;
386     FILE *f = fopen (filename, "wb");
387     png_bytep *row_pointers;
388     int i;
389
390     if (!f)
391         return FALSE;
392
393     row_pointers = malloc (height * sizeof (png_bytep));
394
395     copy = pixman_image_create_bits (
396         PIXMAN_a8r8g8b8, width, height, data, stride);
397
398     pixman_image_composite32 (
399         PIXMAN_OP_SRC, image, NULL, copy, 0, 0, 0, 0, 0, 0, width, height);
400
401     a8r8g8b8_to_rgba_np (data, data, height * width);
402
403     for (i = 0; i < height; ++i)
404         row_pointers[i] = (png_bytep)(data + i * width);
405
406     if (!(write_struct = png_create_write_struct (
407               PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
408         goto out1;
409
410     if (!(info_struct = png_create_info_struct (write_struct)))
411         goto out2;
412
413     png_init_io (write_struct, f);
414
415     png_set_IHDR (write_struct, info_struct, width, height,
416                   8, PNG_COLOR_TYPE_RGB_ALPHA,
417                   PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
418                   PNG_FILTER_TYPE_BASE);
419
420     png_write_info (write_struct, info_struct);
421
422     png_write_image (write_struct, row_pointers);
423
424     png_write_end (write_struct, NULL);
425
426     result = TRUE;
427
428 out2:
429     png_destroy_write_struct (&write_struct, &info_struct);
430
431 out1:
432     if (fclose (f) != 0)
433         result = FALSE;
434
435     pixman_image_unref (copy);
436     free (row_pointers);
437     free (data);
438     return result;
439 }
440
441 #else /* no libpng */
442
443 pixman_bool_t
444 write_png (pixman_image_t *image, const char *filename)
445 {
446     return FALSE;
447 }
448
449 #endif
450
451 /*
452  * A function, which can be used as a core part of the test programs,
453  * intended to detect various problems with the help of fuzzing input
454  * to pixman API (according to some templates, aka "smart" fuzzing).
455  * Some general information about such testing can be found here:
456  * http://en.wikipedia.org/wiki/Fuzz_testing
457  *
458  * It may help detecting:
459  *  - crashes on bad handling of valid or reasonably invalid input to
460  *    pixman API.
461  *  - deviations from the behavior of older pixman releases.
462  *  - deviations from the behavior of the same pixman release, but
463  *    configured in a different way (for example with SIMD optimizations
464  *    disabled), or running on a different OS or hardware.
465  *
466  * The test is performed by calling a callback function a huge number
467  * of times. The callback function is expected to run some snippet of
468  * pixman code with pseudorandom variations to the data feeded to
469  * pixman API. A result of running each callback function should be
470  * some deterministic value which depends on test number (test number
471  * can be used as a seed for PRNG). When 'verbose' argument is nonzero,
472  * callback function is expected to print to stdout some information
473  * about what it does.
474  *
475  * Return values from many small tests are accumulated together and
476  * used as final checksum, which can be compared to some expected
477  * value. Running the tests not individually, but in a batch helps
478  * to reduce process start overhead and also allows to parallelize
479  * testing and utilize multiple CPU cores.
480  *
481  * The resulting executable can be run without any arguments. In
482  * this case it runs a batch of tests starting from 1 and up to
483  * 'default_number_of_iterations'. The resulting checksum is
484  * compared with 'expected_checksum' and FAIL or PASS verdict
485  * depends on the result of this comparison.
486  *
487  * If the executable is run with 2 numbers provided as command line
488  * arguments, they specify the starting and ending numbers for a test
489  * batch.
490  *
491  * If the executable is run with only one number provided as a command
492  * line argument, then this number is used to call the callback function
493  * once, and also with verbose flag set.
494  */
495 int
496 fuzzer_test_main (const char *test_name,
497                   int         default_number_of_iterations,
498                   uint32_t    expected_checksum,
499                   uint32_t    (*test_function)(int testnum, int verbose),
500                   int         argc,
501                   const char *argv[])
502 {
503     int i, n1 = 1, n2 = 0;
504     uint32_t checksum = 0;
505     int verbose = getenv ("VERBOSE") != NULL;
506
507     if (argc >= 3)
508     {
509         n1 = atoi (argv[1]);
510         n2 = atoi (argv[2]);
511         if (n2 < n1)
512         {
513             printf ("invalid test range\n");
514             return 1;
515         }
516     }
517     else if (argc >= 2)
518     {
519         n2 = atoi (argv[1]);
520         checksum = test_function (n2, 1);
521         printf ("%d: checksum=%08X\n", n2, checksum);
522         return 0;
523     }
524     else
525     {
526         n1 = 1;
527         n2 = default_number_of_iterations;
528     }
529
530 #ifdef USE_OPENMP
531     #pragma omp parallel for reduction(+:checksum) default(none) \
532                                         shared(n1, n2, test_function, verbose)
533 #endif
534     for (i = n1; i <= n2; i++)
535     {
536         uint32_t crc = test_function (i, 0);
537         if (verbose)
538             printf ("%d: %08X\n", i, crc);
539         checksum += crc;
540     }
541
542     if (n1 == 1 && n2 == default_number_of_iterations)
543     {
544         if (checksum == expected_checksum)
545         {
546             printf ("%s test passed (checksum=%08X)\n",
547                     test_name, checksum);
548         }
549         else
550         {
551             printf ("%s test failed! (checksum=%08X, expected %08X)\n",
552                     test_name, checksum, expected_checksum);
553             return 1;
554         }
555     }
556     else
557     {
558         printf ("%d-%d: checksum=%08X\n", n1, n2, checksum);
559     }
560
561     return 0;
562 }
563
564 /* Try to obtain current time in seconds */
565 double
566 gettime (void)
567 {
568 #ifdef HAVE_GETTIMEOFDAY
569     struct timeval tv;
570
571     gettimeofday (&tv, NULL);
572     return (double)((int64_t)tv.tv_sec * 1000000 + tv.tv_usec) / 1000000.;
573 #else
574     return (double)clock() / (double)CLOCKS_PER_SEC;
575 #endif
576 }
577
578 uint32_t
579 get_random_seed (void)
580 {
581     double d = gettime();
582
583     lcg_srand (*(uint32_t *)&d);
584
585     return lcg_rand_u32 ();
586 }
587
588 static const char *global_msg;
589
590 static void
591 on_alarm (int signo)
592 {
593     printf ("%s\n", global_msg);
594     exit (1);
595 }
596
597 void
598 fail_after (int seconds, const char *msg)
599 {
600 #ifdef HAVE_SIGACTION
601 #ifdef HAVE_ALARM
602     struct sigaction action;
603
604     global_msg = msg;
605
606     memset (&action, 0, sizeof (action));
607     action.sa_handler = on_alarm;
608
609     alarm (seconds);
610
611     sigaction (SIGALRM, &action, NULL);
612 #endif
613 #endif
614 }
615
616 void
617 enable_fp_exceptions (void)
618 {
619 #ifdef HAVE_FENV_H
620 #ifdef HAVE_FEENABLEEXCEPT
621     /* Note: we don't enable the FE_INEXACT trap because
622      * that happens quite commonly. It is possible that
623      * over- and underflow should similarly be considered
624      * okay, but for now the test suite passes with them
625      * enabled, and it's useful to know if they start
626      * occuring.
627      */
628     feenableexcept (FE_DIVBYZERO        |
629                     FE_INVALID          |
630                     FE_OVERFLOW         |
631                     FE_UNDERFLOW);
632 #endif
633 #endif
634 }
635
636 void *
637 aligned_malloc (size_t align, size_t size)
638 {
639     void *result;
640
641 #ifdef HAVE_POSIX_MEMALIGN
642     if (posix_memalign (&result, align, size) != 0)
643       result = NULL;
644 #else
645     result = malloc (size);
646 #endif
647
648     return result;
649 }
650
651 #define CONVERT_15(c, is_rgb)                                           \
652     (is_rgb?                                                            \
653      ((((c) >> 3) & 0x001f) |                                           \
654       (((c) >> 6) & 0x03e0) |                                           \
655       (((c) >> 9) & 0x7c00)) :                                          \
656      (((((c) >> 16) & 0xff) * 153 +                                     \
657        (((c) >>  8) & 0xff) * 301 +                                     \
658        (((c)      ) & 0xff) * 58) >> 2))
659
660 void
661 initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb)
662 {
663     int i;
664     uint32_t mask = (1 << depth) - 1;
665
666     for (i = 0; i < 32768; ++i)
667         palette->ent[i] = lcg_rand() & mask;
668
669     memset (palette->rgba, 0, sizeof (palette->rgba));
670
671     for (i = 0; i < mask + 1; ++i)
672     {
673         uint32_t rgba24;
674         pixman_bool_t retry;
675         uint32_t i15;
676
677         /* We filled the rgb->index map with random numbers, but we
678          * do need the ability to round trip, that is if some indexed
679          * color expands to an argb24, then the 15 bit version of that
680          * color must map back to the index. Anything else, we don't
681          * care about too much.
682          */
683         do
684         {
685             uint32_t old_idx;
686
687             rgba24 = lcg_rand();
688             i15 = CONVERT_15 (rgba24, is_rgb);
689
690             old_idx = palette->ent[i15];
691             if (CONVERT_15 (palette->rgba[old_idx], is_rgb) == i15)
692                 retry = 1;
693             else
694                 retry = 0;
695         } while (retry);
696
697         palette->rgba[i] = rgba24;
698         palette->ent[i15] = i;
699     }
700
701     for (i = 0; i < mask + 1; ++i)
702     {
703         assert (palette->ent[CONVERT_15 (palette->rgba[i], is_rgb)] == i);
704     }
705 }
706
707 static double
708 round_channel (double p, int m)
709 {
710     int t;
711     double r;
712
713     t = p * ((1 << m));
714     t -= t >> m;
715
716     r = t / (double)((1 << m) - 1);
717
718     return r;
719 }
720
721 void
722 round_color (pixman_format_code_t format, color_t *color)
723 {
724     if (PIXMAN_FORMAT_R (format) == 0)
725     {
726         color->r = 0.0;
727         color->g = 0.0;
728         color->b = 0.0;
729     }
730     else
731     {
732         color->r = round_channel (color->r, PIXMAN_FORMAT_R (format));
733         color->g = round_channel (color->g, PIXMAN_FORMAT_G (format));
734         color->b = round_channel (color->b, PIXMAN_FORMAT_B (format));
735     }
736
737     if (PIXMAN_FORMAT_A (format) == 0)
738         color->a = 1;
739     else
740         color->a = round_channel (color->a, PIXMAN_FORMAT_A (format));
741 }
742
743 /* Check whether @pixel is a valid quantization of the a, r, g, b
744  * parameters. Some slack is permitted.
745  */
746 void
747 pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format)
748 {
749     assert (PIXMAN_FORMAT_VIS (format));
750
751     checker->format = format;
752
753     switch (PIXMAN_FORMAT_TYPE (format))
754     {
755     case PIXMAN_TYPE_A:
756         checker->bs = 0;
757         checker->gs = 0;
758         checker->rs = 0;
759         checker->as = 0;
760         break;
761
762     case PIXMAN_TYPE_ARGB:
763         checker->bs = 0;
764         checker->gs = checker->bs + PIXMAN_FORMAT_B (format);
765         checker->rs = checker->gs + PIXMAN_FORMAT_G (format);
766         checker->as = checker->rs + PIXMAN_FORMAT_R (format);
767         break;
768
769     case PIXMAN_TYPE_ABGR:
770         checker->rs = 0;
771         checker->gs = checker->rs + PIXMAN_FORMAT_R (format);
772         checker->bs = checker->gs + PIXMAN_FORMAT_G (format);
773         checker->as = checker->bs + PIXMAN_FORMAT_B (format);
774         break;
775
776     case PIXMAN_TYPE_BGRA:
777         /* With BGRA formats we start counting at the high end of the pixel */
778         checker->bs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format);
779         checker->gs = checker->bs - PIXMAN_FORMAT_B (format);
780         checker->rs = checker->gs - PIXMAN_FORMAT_G (format);
781         checker->as = checker->rs - PIXMAN_FORMAT_R (format);
782         break;
783
784     case PIXMAN_TYPE_RGBA:
785         /* With BGRA formats we start counting at the high end of the pixel */
786         checker->rs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format);
787         checker->gs = checker->rs - PIXMAN_FORMAT_R (format);
788         checker->bs = checker->gs - PIXMAN_FORMAT_G (format);
789         checker->as = checker->bs - PIXMAN_FORMAT_B (format);
790         break;
791
792     default:
793         assert (0);
794         break;
795     }
796
797     checker->am = ((1 << PIXMAN_FORMAT_A (format)) - 1) << checker->as;
798     checker->rm = ((1 << PIXMAN_FORMAT_R (format)) - 1) << checker->rs;
799     checker->gm = ((1 << PIXMAN_FORMAT_G (format)) - 1) << checker->gs;
800     checker->bm = ((1 << PIXMAN_FORMAT_B (format)) - 1) << checker->bs;
801
802     checker->aw = PIXMAN_FORMAT_A (format);
803     checker->rw = PIXMAN_FORMAT_R (format);
804     checker->gw = PIXMAN_FORMAT_G (format);
805     checker->bw = PIXMAN_FORMAT_B (format);
806 }
807
808 void
809 pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel,
810                            int *a, int *r, int *g, int *b)
811 {
812     *a = (pixel & checker->am) >> checker->as;
813     *r = (pixel & checker->rm) >> checker->rs;
814     *g = (pixel & checker->gm) >> checker->gs;
815     *b = (pixel & checker->bm) >> checker->bs;
816 }
817
818 static int32_t
819 convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def)
820 {
821     int32_t r;
822
823     if (!mask)
824         v = def;
825
826     r = (v * ((mask >> shift) + 1));
827     r -= r >> width;
828
829     return r;
830 }
831
832 static void
833 get_limits (const pixel_checker_t *checker, double limit,
834             color_t *color,
835             int *ao, int *ro, int *go, int *bo)
836 {
837     *ao = convert (color->a + limit, checker->aw, checker->am, checker->as, 1.0);
838     *ro = convert (color->r + limit, checker->rw, checker->rm, checker->rs, 0.0);
839     *go = convert (color->g + limit, checker->gw, checker->gm, checker->gs, 0.0);
840     *bo = convert (color->b + limit, checker->bw, checker->bm, checker->bs, 0.0);
841 }
842
843 /* The acceptable deviation in units of [0.0, 1.0]
844  */
845 #define DEVIATION (0.004)
846
847 void
848 pixel_checker_get_max (const pixel_checker_t *checker, color_t *color,
849                        int *am, int *rm, int *gm, int *bm)
850 {
851     get_limits (checker, DEVIATION, color, am, rm, gm, bm);
852 }
853
854 void
855 pixel_checker_get_min (const pixel_checker_t *checker, color_t *color,
856                        int *am, int *rm, int *gm, int *bm)
857 {
858     get_limits (checker, - DEVIATION, color, am, rm, gm, bm);
859 }
860
861 pixman_bool_t
862 pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel,
863                      color_t *color)
864 {
865     int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi;
866     int32_t ai, ri, gi, bi;
867     pixman_bool_t result;
868
869     pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo);
870     pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi);
871     pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi);
872
873     result =
874         a_lo <= ai && ai <= a_hi        &&
875         r_lo <= ri && ri <= r_hi        &&
876         g_lo <= gi && gi <= g_hi        &&
877         b_lo <= bi && bi <= b_hi;
878
879     return result;
880 }