utils.c revision 14b11b2b
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 38prng_t prng_state_data = {0}; 39prng_t *prng_state = NULL; 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 80uint32_t 81compute_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 145static uint32_t 146compute_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 234uint32_t 235compute_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 252void 253print_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 */ 286void 287image_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 375typedef 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 385unsigned long 386fence_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 399void * 400fence_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 448void 449fence_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 460static void 461fence_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 */ 478pixman_image_t * 479fence_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 545out_fail: 546 fence_free (pixels); 547 548 return NULL; 549} 550 551#else /* FENCE_MALLOC_ACTIVE */ 552 553void * 554fence_malloc (int64_t len) 555{ 556 return malloc (len); 557} 558 559void 560fence_free (void *data) 561{ 562 free (data); 563} 564 565pixman_image_t * 566fence_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 577unsigned long 578fence_get_page_size () 579{ 580 return 0; 581} 582 583#endif /* FENCE_MALLOC_ACTIVE */ 584 585uint8_t * 586make_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 598float * 599make_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 613void 614a8r8g8b8_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 652pixman_bool_t 653write_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 705out2: 706 png_destroy_write_struct (&write_struct, &info_struct); 707 708out1: 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 720pixman_bool_t 721write_png (pixman_image_t *image, const char *filename) 722{ 723 return FALSE; 724} 725 726#endif 727 728static void 729color8_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 742void 743draw_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 782static uint32_t 783call_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 */ 852int 853fuzzer_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 */ 924double 925gettime (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 937uint32_t 938get_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 949static const char *global_msg; 950 951static void 952on_alarm (int signo) 953{ 954 printf ("%s\n", global_msg); 955 exit (1); 956} 957#endif 958#endif 959 960void 961fail_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 979void 980enable_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 991void 992enable_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 1003void * 1004aligned_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 1027double 1028convert_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 1036double 1037convert_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 1045void 1046initialize_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 1092struct operator_entry { 1093 pixman_op_t op; 1094 const char *name; 1095 pixman_bool_t is_alias; 1096}; 1097 1098typedef struct operator_entry operator_entry_t; 1099 1100static 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 1179typedef struct { 1180 pixman_dither_t dither; 1181 const char *name; 1182 pixman_bool_t is_alias; 1183} dither_entry_t; 1184 1185static 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 1205struct format_entry 1206{ 1207 pixman_format_code_t format; 1208 const char *name; 1209 pixman_bool_t is_alias; 1210}; 1211 1212typedef struct format_entry format_entry_t; 1213 1214static 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/* 64bpp formats */ 1232 ENTRY (a16b16g16r16), 1233 1234/* 32bpp formats */ 1235 ENTRY (a8r8g8b8), 1236 ALIAS (a8r8g8b8, "8888"), 1237 ENTRY (x8r8g8b8), 1238 ALIAS (x8r8g8b8, "x888"), 1239 ENTRY (a8b8g8r8), 1240 ENTRY (x8b8g8r8), 1241 ENTRY (b8g8r8a8), 1242 ENTRY (b8g8r8x8), 1243 ENTRY (r8g8b8a8), 1244 ENTRY (r8g8b8x8), 1245 ENTRY (x14r6g6b6), 1246 ENTRY (x2r10g10b10), 1247 ALIAS (x2r10g10b10, "2x10"), 1248 ENTRY (a2r10g10b10), 1249 ALIAS (a2r10g10b10, "2a10"), 1250 ENTRY (x2b10g10r10), 1251 ENTRY (a2b10g10r10), 1252 1253/* sRGB formats */ 1254 ENTRY (a8r8g8b8_sRGB), 1255 ENTRY (r8g8b8_sRGB), 1256 1257/* 24bpp formats */ 1258 ENTRY (r8g8b8), 1259 ALIAS (r8g8b8, "0888"), 1260 ENTRY (b8g8r8), 1261 1262/* 16 bpp formats */ 1263 ENTRY (r5g6b5), 1264 ALIAS (r5g6b5, "0565"), 1265 ENTRY (b5g6r5), 1266 1267 ENTRY (a1r5g5b5), 1268 ALIAS (a1r5g5b5, "1555"), 1269 ENTRY (x1r5g5b5), 1270 ENTRY (a1b5g5r5), 1271 ENTRY (x1b5g5r5), 1272 ENTRY (a4r4g4b4), 1273 ALIAS (a4r4g4b4, "4444"), 1274 ENTRY (x4r4g4b4), 1275 ENTRY (a4b4g4r4), 1276 ENTRY (x4b4g4r4), 1277 1278/* 8bpp formats */ 1279 ENTRY (a8), 1280 ALIAS (a8, "8"), 1281 ENTRY (r3g3b2), 1282 ENTRY (b2g3r3), 1283 ENTRY (a2r2g2b2), 1284 ALIAS (a2r2g2b2, "2222"), 1285 ENTRY (a2b2g2r2), 1286 1287 ALIAS (c8, "x4c4 / c8"), 1288 /* ENTRY (c8), */ 1289 ALIAS (g8, "x4g4 / g8"), 1290 /* ENTRY (g8), */ 1291 1292 ENTRY (x4a4), 1293 1294 /* These format codes are identical to c8 and g8, respectively. */ 1295 /* ENTRY (x4c4), */ 1296 /* ENTRY (x4g4), */ 1297 1298/* 4 bpp formats */ 1299 ENTRY (a4), 1300 ENTRY (r1g2b1), 1301 ENTRY (b1g2r1), 1302 ENTRY (a1r1g1b1), 1303 ENTRY (a1b1g1r1), 1304 1305 ALIAS (c4, "c4"), 1306 /* ENTRY (c4), */ 1307 ALIAS (g4, "g4"), 1308 /* ENTRY (g4), */ 1309 1310/* 1bpp formats */ 1311 ENTRY (a1), 1312 1313 ALIAS (g1, "g1"), 1314 /* ENTRY (g1), */ 1315 1316/* YUV formats */ 1317 ALIAS (yuy2, "yuy2"), 1318 /* ENTRY (yuy2), */ 1319 ALIAS (yv12, "yv12"), 1320 /* ENTRY (yv12), */ 1321 1322/* Fake formats, not in pixman_format_code_t enum */ 1323 ALIAS (null, "null"), 1324 ALIAS (solid, "solid"), 1325 ALIAS (solid, "n"), 1326 ALIAS (pixbuf, "pixbuf"), 1327 ALIAS (rpixbuf, "rpixbuf"), 1328 ALIAS (unknown, "unknown"), 1329 1330#undef ENTRY 1331#undef ALIAS 1332}; 1333 1334pixman_format_code_t 1335format_from_string (const char *s) 1336{ 1337 int i; 1338 1339 for (i = 0; i < ARRAY_LENGTH (format_list); ++i) 1340 { 1341 const format_entry_t *ent = &format_list[i]; 1342 1343 if (strcasecmp (ent->name, s) == 0) 1344 return ent->format; 1345 } 1346 1347 return PIXMAN_null; 1348} 1349 1350static void 1351emit (const char *s, int *n_chars) 1352{ 1353 *n_chars += printf ("%s,", s); 1354 if (*n_chars > 60) 1355 { 1356 printf ("\n "); 1357 *n_chars = 0; 1358 } 1359 else 1360 { 1361 printf (" "); 1362 (*n_chars)++; 1363 } 1364} 1365 1366void 1367list_formats (void) 1368{ 1369 int n_chars; 1370 int i; 1371 1372 printf ("Formats:\n "); 1373 1374 n_chars = 0; 1375 for (i = 0; i < ARRAY_LENGTH (format_list); ++i) 1376 { 1377 const format_entry_t *ent = &format_list[i]; 1378 1379 if (ent->is_alias) 1380 continue; 1381 1382 emit (ent->name, &n_chars); 1383 } 1384 1385 printf ("\n\n"); 1386} 1387 1388void 1389list_operators (void) 1390{ 1391 char short_name [128] = { 0 }; 1392 int i, n_chars; 1393 1394 printf ("Operators:\n "); 1395 1396 n_chars = 0; 1397 for (i = 0; i < ARRAY_LENGTH (op_list); ++i) 1398 { 1399 const operator_entry_t *ent = &op_list[i]; 1400 int j; 1401 1402 if (ent->is_alias) 1403 continue; 1404 1405 snprintf (short_name, sizeof (short_name) - 1, "%s", 1406 ent->name + strlen ("PIXMAN_OP_")); 1407 1408 for (j = 0; short_name[j] != '\0'; ++j) 1409 short_name[j] = tolower (short_name[j]); 1410 1411 emit (short_name, &n_chars); 1412 } 1413 1414 printf ("\n\n"); 1415} 1416 1417void 1418list_dithers (void) 1419{ 1420 int n_chars; 1421 int i; 1422 1423 printf ("Dithers:\n "); 1424 1425 n_chars = 0; 1426 for (i = 0; i < ARRAY_LENGTH (dither_list); ++i) 1427 { 1428 const dither_entry_t *ent = &dither_list[i]; 1429 1430 if (ent->is_alias) 1431 continue; 1432 1433 emit (ent->name, &n_chars); 1434 } 1435 1436 printf ("\n\n"); 1437} 1438 1439pixman_op_t 1440operator_from_string (const char *s) 1441{ 1442 int i; 1443 1444 for (i = 0; i < ARRAY_LENGTH (op_list); ++i) 1445 { 1446 const operator_entry_t *ent = &op_list[i]; 1447 1448 if (ent->is_alias) 1449 { 1450 if (strcasecmp (ent->name, s) == 0) 1451 return ent->op; 1452 } 1453 else 1454 { 1455 if (strcasecmp (ent->name + strlen ("PIXMAN_OP_"), s) == 0) 1456 return ent->op; 1457 } 1458 } 1459 1460 return PIXMAN_OP_NONE; 1461} 1462 1463pixman_dither_t 1464dither_from_string (const char *s) 1465{ 1466 int i; 1467 1468 for (i = 0; i < ARRAY_LENGTH (dither_list); ++i) 1469 { 1470 const dither_entry_t *ent = &dither_list[i]; 1471 1472 if (strcasecmp (ent->name, s) == 0) 1473 return ent->dither; 1474 } 1475 1476 return PIXMAN_DITHER_NONE; 1477} 1478 1479const char * 1480operator_name (pixman_op_t op) 1481{ 1482 int i; 1483 1484 for (i = 0; i < ARRAY_LENGTH (op_list); ++i) 1485 { 1486 const operator_entry_t *ent = &op_list[i]; 1487 1488 if (ent->op == op) 1489 return ent->name; 1490 } 1491 1492 return "<unknown operator>"; 1493} 1494 1495const char * 1496format_name (pixman_format_code_t format) 1497{ 1498 int i; 1499 1500 for (i = 0; i < ARRAY_LENGTH (format_list); ++i) 1501 { 1502 const format_entry_t *ent = &format_list[i]; 1503 1504 if (ent->format == format) 1505 return ent->name; 1506 } 1507 1508 return "<unknown format>"; 1509}; 1510 1511const char * 1512dither_name (pixman_dither_t dither) 1513{ 1514 int i; 1515 1516 for (i = 0; i < ARRAY_LENGTH (dither_list); ++i) 1517 { 1518 const dither_entry_t *ent = &dither_list[i]; 1519 1520 if (ent->dither == dither) 1521 return ent->name; 1522 } 1523 1524 return "<unknown dither>"; 1525} 1526 1527#define IS_ZERO(f) (-DBL_MIN < (f) && (f) < DBL_MIN) 1528 1529typedef double (* blend_func_t) (double as, double s, double ad, double d); 1530 1531static force_inline double 1532blend_multiply (double sa, double s, double da, double d) 1533{ 1534 return d * s; 1535} 1536 1537static force_inline double 1538blend_screen (double sa, double s, double da, double d) 1539{ 1540 return d * sa + s * da - s * d; 1541} 1542 1543static force_inline double 1544blend_overlay (double sa, double s, double da, double d) 1545{ 1546 if (2 * d < da) 1547 return 2 * s * d; 1548 else 1549 return sa * da - 2 * (da - d) * (sa - s); 1550} 1551 1552static force_inline double 1553blend_darken (double sa, double s, double da, double d) 1554{ 1555 s = s * da; 1556 d = d * sa; 1557 1558 if (s > d) 1559 return d; 1560 else 1561 return s; 1562} 1563 1564static force_inline double 1565blend_lighten (double sa, double s, double da, double d) 1566{ 1567 s = s * da; 1568 d = d * sa; 1569 1570 if (s > d) 1571 return s; 1572 else 1573 return d; 1574} 1575 1576static force_inline double 1577blend_color_dodge (double sa, double s, double da, double d) 1578{ 1579 if (IS_ZERO (d)) 1580 return 0.0f; 1581 else if (d * sa >= sa * da - s * da) 1582 return sa * da; 1583 else if (IS_ZERO (sa - s)) 1584 return sa * da; 1585 else 1586 return sa * sa * d / (sa - s); 1587} 1588 1589static force_inline double 1590blend_color_burn (double sa, double s, double da, double d) 1591{ 1592 if (d >= da) 1593 return sa * da; 1594 else if (sa * (da - d) >= s * da) 1595 return 0.0f; 1596 else if (IS_ZERO (s)) 1597 return 0.0f; 1598 else 1599 return sa * (da - sa * (da - d) / s); 1600} 1601 1602static force_inline double 1603blend_hard_light (double sa, double s, double da, double d) 1604{ 1605 if (2 * s < sa) 1606 return 2 * s * d; 1607 else 1608 return sa * da - 2 * (da - d) * (sa - s); 1609} 1610 1611static force_inline double 1612blend_soft_light (double sa, double s, double da, double d) 1613{ 1614 if (2 * s <= sa) 1615 { 1616 if (IS_ZERO (da)) 1617 return d * sa; 1618 else 1619 return d * sa - d * (da - d) * (sa - 2 * s) / da; 1620 } 1621 else 1622 { 1623 if (IS_ZERO (da)) 1624 { 1625 return d * sa; 1626 } 1627 else 1628 { 1629 if (4 * d <= da) 1630 return d * sa + (2 * s - sa) * d * ((16 * d / da - 12) * d / da + 3); 1631 else 1632 return d * sa + (sqrt (d * da) - d) * (2 * s - sa); 1633 } 1634 } 1635} 1636 1637static force_inline double 1638blend_difference (double sa, double s, double da, double d) 1639{ 1640 double dsa = d * sa; 1641 double sda = s * da; 1642 1643 if (sda < dsa) 1644 return dsa - sda; 1645 else 1646 return sda - dsa; 1647} 1648 1649static force_inline double 1650blend_exclusion (double sa, double s, double da, double d) 1651{ 1652 return s * da + d * sa - 2 * d * s; 1653} 1654 1655static double 1656clamp (double d) 1657{ 1658 if (d > 1.0) 1659 return 1.0; 1660 else if (d < 0.0) 1661 return 0.0; 1662 else 1663 return d; 1664} 1665 1666static double 1667blend_channel (double as, double s, double ad, double d, 1668 blend_func_t blend) 1669{ 1670 return clamp ((1 - ad) * s + (1 - as) * d + blend (as, s, ad, d)); 1671} 1672 1673static double 1674calc_op (pixman_op_t op, double src, double dst, double srca, double dsta) 1675{ 1676#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0) 1677 1678 double Fa, Fb; 1679 1680 switch (op) 1681 { 1682 case PIXMAN_OP_CLEAR: 1683 case PIXMAN_OP_DISJOINT_CLEAR: 1684 case PIXMAN_OP_CONJOINT_CLEAR: 1685 return mult_chan (src, dst, 0.0, 0.0); 1686 1687 case PIXMAN_OP_SRC: 1688 case PIXMAN_OP_DISJOINT_SRC: 1689 case PIXMAN_OP_CONJOINT_SRC: 1690 return mult_chan (src, dst, 1.0, 0.0); 1691 1692 case PIXMAN_OP_DST: 1693 case PIXMAN_OP_DISJOINT_DST: 1694 case PIXMAN_OP_CONJOINT_DST: 1695 return mult_chan (src, dst, 0.0, 1.0); 1696 1697 case PIXMAN_OP_OVER: 1698 return mult_chan (src, dst, 1.0, 1.0 - srca); 1699 1700 case PIXMAN_OP_OVER_REVERSE: 1701 return mult_chan (src, dst, 1.0 - dsta, 1.0); 1702 1703 case PIXMAN_OP_IN: 1704 return mult_chan (src, dst, dsta, 0.0); 1705 1706 case PIXMAN_OP_IN_REVERSE: 1707 return mult_chan (src, dst, 0.0, srca); 1708 1709 case PIXMAN_OP_OUT: 1710 return mult_chan (src, dst, 1.0 - dsta, 0.0); 1711 1712 case PIXMAN_OP_OUT_REVERSE: 1713 return mult_chan (src, dst, 0.0, 1.0 - srca); 1714 1715 case PIXMAN_OP_ATOP: 1716 return mult_chan (src, dst, dsta, 1.0 - srca); 1717 1718 case PIXMAN_OP_ATOP_REVERSE: 1719 return mult_chan (src, dst, 1.0 - dsta, srca); 1720 1721 case PIXMAN_OP_XOR: 1722 return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca); 1723 1724 case PIXMAN_OP_ADD: 1725 return mult_chan (src, dst, 1.0, 1.0); 1726 1727 case PIXMAN_OP_SATURATE: 1728 case PIXMAN_OP_DISJOINT_OVER_REVERSE: 1729 if (srca == 0.0) 1730 Fa = 1.0; 1731 else 1732 Fa = MIN (1.0, (1.0 - dsta) / srca); 1733 return mult_chan (src, dst, Fa, 1.0); 1734 1735 case PIXMAN_OP_DISJOINT_OVER: 1736 if (dsta == 0.0) 1737 Fb = 1.0; 1738 else 1739 Fb = MIN (1.0, (1.0 - srca) / dsta); 1740 return mult_chan (src, dst, 1.0, Fb); 1741 1742 case PIXMAN_OP_DISJOINT_IN: 1743 if (srca == 0.0) 1744 Fa = 0.0; 1745 else 1746 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); 1747 return mult_chan (src, dst, Fa, 0.0); 1748 1749 case PIXMAN_OP_DISJOINT_IN_REVERSE: 1750 if (dsta == 0.0) 1751 Fb = 0.0; 1752 else 1753 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); 1754 return mult_chan (src, dst, 0.0, Fb); 1755 1756 case PIXMAN_OP_DISJOINT_OUT: 1757 if (srca == 0.0) 1758 Fa = 1.0; 1759 else 1760 Fa = MIN (1.0, (1.0 - dsta) / srca); 1761 return mult_chan (src, dst, Fa, 0.0); 1762 1763 case PIXMAN_OP_DISJOINT_OUT_REVERSE: 1764 if (dsta == 0.0) 1765 Fb = 1.0; 1766 else 1767 Fb = MIN (1.0, (1.0 - srca) / dsta); 1768 return mult_chan (src, dst, 0.0, Fb); 1769 1770 case PIXMAN_OP_DISJOINT_ATOP: 1771 if (srca == 0.0) 1772 Fa = 0.0; 1773 else 1774 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); 1775 if (dsta == 0.0) 1776 Fb = 1.0; 1777 else 1778 Fb = MIN (1.0, (1.0 - srca) / dsta); 1779 return mult_chan (src, dst, Fa, Fb); 1780 1781 case PIXMAN_OP_DISJOINT_ATOP_REVERSE: 1782 if (srca == 0.0) 1783 Fa = 1.0; 1784 else 1785 Fa = MIN (1.0, (1.0 - dsta) / srca); 1786 if (dsta == 0.0) 1787 Fb = 0.0; 1788 else 1789 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); 1790 return mult_chan (src, dst, Fa, Fb); 1791 1792 case PIXMAN_OP_DISJOINT_XOR: 1793 if (srca == 0.0) 1794 Fa = 1.0; 1795 else 1796 Fa = MIN (1.0, (1.0 - dsta) / srca); 1797 if (dsta == 0.0) 1798 Fb = 1.0; 1799 else 1800 Fb = MIN (1.0, (1.0 - srca) / dsta); 1801 return mult_chan (src, dst, Fa, Fb); 1802 1803 case PIXMAN_OP_CONJOINT_OVER: 1804 if (dsta == 0.0) 1805 Fb = 0.0; 1806 else 1807 Fb = MAX (0.0, 1.0 - srca / dsta); 1808 return mult_chan (src, dst, 1.0, Fb); 1809 1810 case PIXMAN_OP_CONJOINT_OVER_REVERSE: 1811 if (srca == 0.0) 1812 Fa = 0.0; 1813 else 1814 Fa = MAX (0.0, 1.0 - dsta / srca); 1815 return mult_chan (src, dst, Fa, 1.0); 1816 1817 case PIXMAN_OP_CONJOINT_IN: 1818 if (srca == 0.0) 1819 Fa = 1.0; 1820 else 1821 Fa = MIN (1.0, dsta / srca); 1822 return mult_chan (src, dst, Fa, 0.0); 1823 1824 case PIXMAN_OP_CONJOINT_IN_REVERSE: 1825 if (dsta == 0.0) 1826 Fb = 1.0; 1827 else 1828 Fb = MIN (1.0, srca / dsta); 1829 return mult_chan (src, dst, 0.0, Fb); 1830 1831 case PIXMAN_OP_CONJOINT_OUT: 1832 if (srca == 0.0) 1833 Fa = 0.0; 1834 else 1835 Fa = MAX (0.0, 1.0 - dsta / srca); 1836 return mult_chan (src, dst, Fa, 0.0); 1837 1838 case PIXMAN_OP_CONJOINT_OUT_REVERSE: 1839 if (dsta == 0.0) 1840 Fb = 0.0; 1841 else 1842 Fb = MAX (0.0, 1.0 - srca / dsta); 1843 return mult_chan (src, dst, 0.0, Fb); 1844 1845 case PIXMAN_OP_CONJOINT_ATOP: 1846 if (srca == 0.0) 1847 Fa = 1.0; 1848 else 1849 Fa = MIN (1.0, dsta / srca); 1850 if (dsta == 0.0) 1851 Fb = 0.0; 1852 else 1853 Fb = MAX (0.0, 1.0 - srca / dsta); 1854 return mult_chan (src, dst, Fa, Fb); 1855 1856 case PIXMAN_OP_CONJOINT_ATOP_REVERSE: 1857 if (srca == 0.0) 1858 Fa = 0.0; 1859 else 1860 Fa = MAX (0.0, 1.0 - dsta / srca); 1861 if (dsta == 0.0) 1862 Fb = 1.0; 1863 else 1864 Fb = MIN (1.0, srca / dsta); 1865 return mult_chan (src, dst, Fa, Fb); 1866 1867 case PIXMAN_OP_CONJOINT_XOR: 1868 if (srca == 0.0) 1869 Fa = 0.0; 1870 else 1871 Fa = MAX (0.0, 1.0 - dsta / srca); 1872 if (dsta == 0.0) 1873 Fb = 0.0; 1874 else 1875 Fb = MAX (0.0, 1.0 - srca / dsta); 1876 return mult_chan (src, dst, Fa, Fb); 1877 1878 case PIXMAN_OP_MULTIPLY: 1879 case PIXMAN_OP_SCREEN: 1880 case PIXMAN_OP_OVERLAY: 1881 case PIXMAN_OP_DARKEN: 1882 case PIXMAN_OP_LIGHTEN: 1883 case PIXMAN_OP_COLOR_DODGE: 1884 case PIXMAN_OP_COLOR_BURN: 1885 case PIXMAN_OP_HARD_LIGHT: 1886 case PIXMAN_OP_SOFT_LIGHT: 1887 case PIXMAN_OP_DIFFERENCE: 1888 case PIXMAN_OP_EXCLUSION: 1889 case PIXMAN_OP_HSL_HUE: 1890 case PIXMAN_OP_HSL_SATURATION: 1891 case PIXMAN_OP_HSL_COLOR: 1892 case PIXMAN_OP_HSL_LUMINOSITY: 1893 default: 1894 abort(); 1895 return 0; /* silence MSVC */ 1896 } 1897#undef mult_chan 1898} 1899 1900void 1901do_composite (pixman_op_t op, 1902 const color_t *src, 1903 const color_t *mask, 1904 const color_t *dst, 1905 color_t *result, 1906 pixman_bool_t component_alpha) 1907{ 1908 color_t srcval, srcalpha; 1909 1910 static const blend_func_t blend_funcs[] = 1911 { 1912 blend_multiply, 1913 blend_screen, 1914 blend_overlay, 1915 blend_darken, 1916 blend_lighten, 1917 blend_color_dodge, 1918 blend_color_burn, 1919 blend_hard_light, 1920 blend_soft_light, 1921 blend_difference, 1922 blend_exclusion, 1923 }; 1924 1925 if (mask == NULL) 1926 { 1927 srcval = *src; 1928 1929 srcalpha.r = src->a; 1930 srcalpha.g = src->a; 1931 srcalpha.b = src->a; 1932 srcalpha.a = src->a; 1933 } 1934 else if (component_alpha) 1935 { 1936 srcval.r = src->r * mask->r; 1937 srcval.g = src->g * mask->g; 1938 srcval.b = src->b * mask->b; 1939 srcval.a = src->a * mask->a; 1940 1941 srcalpha.r = src->a * mask->r; 1942 srcalpha.g = src->a * mask->g; 1943 srcalpha.b = src->a * mask->b; 1944 srcalpha.a = src->a * mask->a; 1945 } 1946 else 1947 { 1948 srcval.r = src->r * mask->a; 1949 srcval.g = src->g * mask->a; 1950 srcval.b = src->b * mask->a; 1951 srcval.a = src->a * mask->a; 1952 1953 srcalpha.r = src->a * mask->a; 1954 srcalpha.g = src->a * mask->a; 1955 srcalpha.b = src->a * mask->a; 1956 srcalpha.a = src->a * mask->a; 1957 } 1958 1959 if (op >= PIXMAN_OP_MULTIPLY) 1960 { 1961 blend_func_t func = blend_funcs[op - PIXMAN_OP_MULTIPLY]; 1962 1963 result->a = srcalpha.a + dst->a - srcalpha.a * dst->a; 1964 result->r = blend_channel (srcalpha.r, srcval.r, dst->a, dst->r, func); 1965 result->g = blend_channel (srcalpha.g, srcval.g, dst->a, dst->g, func); 1966 result->b = blend_channel (srcalpha.b, srcval.b, dst->a, dst->b, func); 1967 } 1968 else 1969 { 1970 result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a); 1971 result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a); 1972 result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a); 1973 result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a); 1974 } 1975} 1976 1977static double 1978round_channel (double p, int m) 1979{ 1980 int t; 1981 double r; 1982 1983 t = p * ((1 << m)); 1984 t -= t >> m; 1985 1986 r = t / (double)((1 << m) - 1); 1987 1988 return r; 1989} 1990 1991void 1992round_color (pixman_format_code_t format, color_t *color) 1993{ 1994 if (PIXMAN_FORMAT_R (format) == 0) 1995 { 1996 color->r = 0.0; 1997 color->g = 0.0; 1998 color->b = 0.0; 1999 } 2000 else 2001 { 2002 color->r = round_channel (color->r, PIXMAN_FORMAT_R (format)); 2003 color->g = round_channel (color->g, PIXMAN_FORMAT_G (format)); 2004 color->b = round_channel (color->b, PIXMAN_FORMAT_B (format)); 2005 } 2006 2007 if (PIXMAN_FORMAT_A (format) == 0) 2008 color->a = 1; 2009 else 2010 color->a = round_channel (color->a, PIXMAN_FORMAT_A (format)); 2011} 2012 2013/* The acceptable deviation in units of [0.0, 1.0] 2014 */ 2015#define DEVIATION (0.0128) 2016 2017/* Check whether @pixel is a valid quantization of the a, r, g, b 2018 * parameters. Some slack is permitted. 2019 */ 2020void 2021pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format) 2022{ 2023 assert (PIXMAN_FORMAT_VIS (format)); 2024 2025 checker->format = format; 2026 2027 if (format == PIXMAN_rgba_float || 2028 format == PIXMAN_rgb_float) 2029 return; 2030 2031 switch (PIXMAN_FORMAT_TYPE (format)) 2032 { 2033 case PIXMAN_TYPE_A: 2034 checker->bs = 0; 2035 checker->gs = 0; 2036 checker->rs = 0; 2037 checker->as = 0; 2038 break; 2039 2040 case PIXMAN_TYPE_ARGB: 2041 case PIXMAN_TYPE_ARGB_SRGB: 2042 checker->bs = 0; 2043 checker->gs = checker->bs + PIXMAN_FORMAT_B (format); 2044 checker->rs = checker->gs + PIXMAN_FORMAT_G (format); 2045 checker->as = checker->rs + PIXMAN_FORMAT_R (format); 2046 break; 2047 2048 case PIXMAN_TYPE_ABGR: 2049 checker->rs = 0; 2050 checker->gs = checker->rs + PIXMAN_FORMAT_R (format); 2051 checker->bs = checker->gs + PIXMAN_FORMAT_G (format); 2052 checker->as = checker->bs + PIXMAN_FORMAT_B (format); 2053 break; 2054 2055 case PIXMAN_TYPE_BGRA: 2056 /* With BGRA formats we start counting at the high end of the pixel */ 2057 checker->bs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_B (format); 2058 checker->gs = checker->bs - PIXMAN_FORMAT_B (format); 2059 checker->rs = checker->gs - PIXMAN_FORMAT_G (format); 2060 checker->as = checker->rs - PIXMAN_FORMAT_R (format); 2061 break; 2062 2063 case PIXMAN_TYPE_RGBA: 2064 /* With BGRA formats we start counting at the high end of the pixel */ 2065 checker->rs = PIXMAN_FORMAT_BPP (format) - PIXMAN_FORMAT_R (format); 2066 checker->gs = checker->rs - PIXMAN_FORMAT_R (format); 2067 checker->bs = checker->gs - PIXMAN_FORMAT_G (format); 2068 checker->as = checker->bs - PIXMAN_FORMAT_B (format); 2069 break; 2070 2071 default: 2072 assert (0); 2073 break; 2074 } 2075 2076 checker->am = ((1U << PIXMAN_FORMAT_A (format)) - 1) << checker->as; 2077 checker->rm = ((1U << PIXMAN_FORMAT_R (format)) - 1) << checker->rs; 2078 checker->gm = ((1U << PIXMAN_FORMAT_G (format)) - 1) << checker->gs; 2079 checker->bm = ((1U << PIXMAN_FORMAT_B (format)) - 1) << checker->bs; 2080 2081 checker->aw = PIXMAN_FORMAT_A (format); 2082 checker->rw = PIXMAN_FORMAT_R (format); 2083 checker->gw = PIXMAN_FORMAT_G (format); 2084 checker->bw = PIXMAN_FORMAT_B (format); 2085 2086 checker->ad = DEVIATION; 2087 checker->rd = DEVIATION; 2088 checker->gd = DEVIATION; 2089 checker->bd = DEVIATION; 2090} 2091 2092/* When dithering is enabled, we allow one extra pixel of tolerance 2093 */ 2094void 2095pixel_checker_allow_dither (pixel_checker_t *checker) 2096{ 2097 checker->ad += 1 / (double)((1 << checker->aw) - 1); 2098 checker->rd += 1 / (double)((1 << checker->rw) - 1); 2099 checker->gd += 1 / (double)((1 << checker->gw) - 1); 2100 checker->bd += 1 / (double)((1 << checker->bw) - 1); 2101} 2102 2103static void 2104pixel_checker_require_uint32_format (const pixel_checker_t *checker) 2105{ 2106 assert (checker->format != PIXMAN_rgba_float && 2107 checker->format != PIXMAN_rgb_float); 2108} 2109 2110void 2111pixel_checker_split_pixel (const pixel_checker_t *checker, uint32_t pixel, 2112 int *a, int *r, int *g, int *b) 2113{ 2114 pixel_checker_require_uint32_format(checker); 2115 2116 *a = (pixel & checker->am) >> checker->as; 2117 *r = (pixel & checker->rm) >> checker->rs; 2118 *g = (pixel & checker->gm) >> checker->gs; 2119 *b = (pixel & checker->bm) >> checker->bs; 2120} 2121 2122void 2123pixel_checker_get_masks (const pixel_checker_t *checker, 2124 uint32_t *am, 2125 uint32_t *rm, 2126 uint32_t *gm, 2127 uint32_t *bm) 2128{ 2129 pixel_checker_require_uint32_format(checker); 2130 2131 if (am) 2132 *am = checker->am; 2133 if (rm) 2134 *rm = checker->rm; 2135 if (gm) 2136 *gm = checker->gm; 2137 if (bm) 2138 *bm = checker->bm; 2139} 2140 2141void 2142pixel_checker_convert_pixel_to_color (const pixel_checker_t *checker, 2143 uint32_t pixel, color_t *color) 2144{ 2145 int a, r, g, b; 2146 2147 pixel_checker_require_uint32_format(checker); 2148 2149 pixel_checker_split_pixel (checker, pixel, &a, &r, &g, &b); 2150 2151 if (checker->am == 0) 2152 color->a = 1.0; 2153 else 2154 color->a = a / (double)(checker->am >> checker->as); 2155 2156 if (checker->rm == 0) 2157 color->r = 0.0; 2158 else 2159 color->r = r / (double)(checker->rm >> checker->rs); 2160 2161 if (checker->gm == 0) 2162 color->g = 0.0; 2163 else 2164 color->g = g / (double)(checker->gm >> checker->gs); 2165 2166 if (checker->bm == 0) 2167 color->b = 0.0; 2168 else 2169 color->b = b / (double)(checker->bm >> checker->bs); 2170 2171 if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB) 2172 { 2173 color->r = convert_srgb_to_linear (color->r); 2174 color->g = convert_srgb_to_linear (color->g); 2175 color->b = convert_srgb_to_linear (color->b); 2176 } 2177} 2178 2179static int32_t 2180convert (double v, uint32_t width, uint32_t mask, uint32_t shift, double def) 2181{ 2182 int32_t r; 2183 2184 if (!mask) 2185 v = def; 2186 2187 r = (v * ((mask >> shift) + 1)); 2188 r -= r >> width; 2189 2190 return r; 2191} 2192 2193static void 2194get_limits (const pixel_checker_t *checker, double sign, 2195 color_t *color, 2196 int *ao, int *ro, int *go, int *bo) 2197{ 2198 color_t tmp; 2199 2200 if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB) 2201 { 2202 tmp.a = color->a; 2203 tmp.r = convert_linear_to_srgb (color->r); 2204 tmp.g = convert_linear_to_srgb (color->g); 2205 tmp.b = convert_linear_to_srgb (color->b); 2206 2207 color = &tmp; 2208 } 2209 2210 *ao = convert (color->a + sign * checker->ad, 2211 checker->aw, checker->am, checker->as, 1.0); 2212 *ro = convert (color->r + sign * checker->rd, 2213 checker->rw, checker->rm, checker->rs, 0.0); 2214 *go = convert (color->g + sign * checker->gd, 2215 checker->gw, checker->gm, checker->gs, 0.0); 2216 *bo = convert (color->b + sign * checker->bd, 2217 checker->bw, checker->bm, checker->bs, 0.0); 2218} 2219 2220void 2221pixel_checker_get_max (const pixel_checker_t *checker, color_t *color, 2222 int *am, int *rm, int *gm, int *bm) 2223{ 2224 pixel_checker_require_uint32_format(checker); 2225 2226 get_limits (checker, 1, color, am, rm, gm, bm); 2227} 2228 2229void 2230pixel_checker_get_min (const pixel_checker_t *checker, color_t *color, 2231 int *am, int *rm, int *gm, int *bm) 2232{ 2233 pixel_checker_require_uint32_format(checker); 2234 2235 get_limits (checker, - 1, color, am, rm, gm, bm); 2236} 2237 2238pixman_bool_t 2239pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel, 2240 color_t *color) 2241{ 2242 int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi; 2243 int32_t ai, ri, gi, bi; 2244 pixman_bool_t result; 2245 2246 pixel_checker_require_uint32_format(checker); 2247 2248 pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo); 2249 pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi); 2250 pixel_checker_split_pixel (checker, pixel, &ai, &ri, &gi, &bi); 2251 2252 result = 2253 a_lo <= ai && ai <= a_hi && 2254 r_lo <= ri && ri <= r_hi && 2255 g_lo <= gi && gi <= g_hi && 2256 b_lo <= bi && bi <= b_hi; 2257 2258 return result; 2259} 2260 2261static void 2262color_limits (const pixel_checker_t *checker, 2263 double limit, const color_t *color, color_t *out) 2264{ 2265 if (PIXMAN_FORMAT_A(checker->format)) 2266 out->a = color->a + limit; 2267 else 2268 out->a = 1.; 2269 2270 out->r = color->r + limit; 2271 out->g = color->g + limit; 2272 out->b = color->b + limit; 2273} 2274 2275pixman_bool_t 2276pixel_checker_check_color (const pixel_checker_t *checker, 2277 const color_t *actual, const color_t *reference) 2278{ 2279 color_t min, max; 2280 pixman_bool_t result; 2281 2282 color_limits(checker, -DEVIATION, reference, &min); 2283 color_limits(checker, DEVIATION, reference, &max); 2284 2285 result = 2286 actual->a >= min.a && actual->a <= max.a && 2287 actual->r >= min.r && actual->r <= max.r && 2288 actual->g >= min.g && actual->g <= max.g && 2289 actual->b >= min.b && actual->b <= max.b; 2290 2291 return result; 2292} 2293