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