composite.c revision 6ba797d6
1/* 2 * Copyright © 2005 Eric Anholt 3 * Copyright © 2009 Chris Wilson 4 * Copyright © 2010 Soeren Sandmann 5 * Copyright © 2010 Red Hat, Inc. 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and its 8 * documentation for any purpose is hereby granted without fee, provided that 9 * the above copyright notice appear in all copies and that both that 10 * copyright notice and this permission notice appear in supporting 11 * documentation, and that the name of Eric Anholt not be used in 12 * advertising or publicity pertaining to distribution of the software without 13 * specific, written prior permission. Eric Anholt makes no 14 * representations about the suitability of this software for any purpose. It 15 * is provided "as is" without express or implied warranty. 16 * 17 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 19 * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR 20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 23 * PERFORMANCE OF THIS SOFTWARE. 24 */ 25#define PIXMAN_USE_INTERNAL_API 26#include <pixman.h> 27#include <stdio.h> 28#include <stdlib.h> /* abort() */ 29#include <math.h> 30#include <config.h> 31#include <time.h> 32#include "utils.h" 33 34typedef struct color_t color_t; 35typedef struct format_t format_t; 36typedef struct image_t image_t; 37typedef struct operator_t operator_t; 38 39struct color_t 40{ 41 double r, g, b, a; 42}; 43 44struct format_t 45{ 46 pixman_format_code_t format; 47 const char *name; 48}; 49 50static const color_t colors[] = 51{ 52 { 1.0, 1.0, 1.0, 1.0 }, 53 { 1.0, 1.0, 1.0, 0.0 }, 54 { 0.0, 0.0, 0.0, 1.0 }, 55 { 0.0, 0.0, 0.0, 0.0 }, 56 { 1.0, 0.0, 0.0, 1.0 }, 57 { 0.0, 1.0, 0.0, 1.0 }, 58 { 0.0, 0.0, 1.0, 1.0 }, 59 { 0.5, 0.0, 0.0, 0.5 }, 60}; 61 62static uint16_t 63_color_double_to_short (double d) 64{ 65 uint32_t i; 66 67 i = (uint32_t) (d * 65536); 68 i -= (i >> 16); 69 70 return i; 71} 72 73static void 74compute_pixman_color (const color_t *color, 75 pixman_color_t *out) 76{ 77 out->red = _color_double_to_short (color->r); 78 out->green = _color_double_to_short (color->g); 79 out->blue = _color_double_to_short (color->b); 80 out->alpha = _color_double_to_short (color->a); 81} 82 83#define REPEAT 0x01000000 84#define FLAGS 0xff000000 85 86static const int sizes[] = 87{ 88 0, 89 1, 90 1 | REPEAT, 91 10 92}; 93 94static const format_t formats[] = 95{ 96#define P(x) { PIXMAN_##x, #x } 97 98 /* 32 bpp formats */ 99 P(a8r8g8b8), 100 P(x8r8g8b8), 101 P(a8b8g8r8), 102 P(x8b8g8r8), 103 P(b8g8r8a8), 104 P(b8g8r8x8), 105 P(r8g8b8a8), 106 P(r8g8b8x8), 107 P(x2r10g10b10), 108 P(x2b10g10r10), 109 P(a2r10g10b10), 110 P(a2b10g10r10), 111 112 /* 24 bpp formats */ 113 P(r8g8b8), 114 P(b8g8r8), 115 P(r5g6b5), 116 P(b5g6r5), 117 118 /* 16 bpp formats */ 119 P(x1r5g5b5), 120 P(x1b5g5r5), 121 P(a1r5g5b5), 122 P(a1b5g5r5), 123 P(a4b4g4r4), 124 P(x4b4g4r4), 125 P(a4r4g4b4), 126 P(x4r4g4b4), 127 128 /* 8 bpp formats */ 129 P(a8), 130 P(r3g3b2), 131 P(b2g3r3), 132 P(a2r2g2b2), 133 P(a2b2g2r2), 134 P(x4a4), 135 136 /* 4 bpp formats */ 137 P(a4), 138 P(r1g2b1), 139 P(b1g2r1), 140 P(a1r1g1b1), 141 P(a1b1g1r1), 142 143 /* 1 bpp formats */ 144 P(a1) 145#undef P 146}; 147 148struct image_t 149{ 150 pixman_image_t *image; 151 const format_t *format; 152 const color_t *color; 153 pixman_repeat_t repeat; 154 int size; 155}; 156 157struct operator_t 158{ 159 pixman_op_t op; 160 const char *name; 161}; 162 163static const operator_t operators[] = 164{ 165#define P(x) { PIXMAN_OP_##x, #x } 166 P(CLEAR), 167 P(SRC), 168 P(DST), 169 P(OVER), 170 P(OVER_REVERSE), 171 P(IN), 172 P(IN_REVERSE), 173 P(OUT), 174 P(OUT_REVERSE), 175 P(ATOP), 176 P(ATOP_REVERSE), 177 P(XOR), 178 P(ADD), 179 P(SATURATE), 180 181 P(DISJOINT_CLEAR), 182 P(DISJOINT_SRC), 183 P(DISJOINT_DST), 184 P(DISJOINT_OVER), 185 P(DISJOINT_OVER_REVERSE), 186 P(DISJOINT_IN), 187 P(DISJOINT_IN_REVERSE), 188 P(DISJOINT_OUT), 189 P(DISJOINT_OUT_REVERSE), 190 P(DISJOINT_ATOP), 191 P(DISJOINT_ATOP_REVERSE), 192 P(DISJOINT_XOR), 193 194 P(CONJOINT_CLEAR), 195 P(CONJOINT_SRC), 196 P(CONJOINT_DST), 197 P(CONJOINT_OVER), 198 P(CONJOINT_OVER_REVERSE), 199 P(CONJOINT_IN), 200 P(CONJOINT_IN_REVERSE), 201 P(CONJOINT_OUT), 202 P(CONJOINT_OUT_REVERSE), 203 P(CONJOINT_ATOP), 204 P(CONJOINT_ATOP_REVERSE), 205 P(CONJOINT_XOR), 206#undef P 207}; 208 209static double 210calc_op (pixman_op_t op, double src, double dst, double srca, double dsta) 211{ 212#define mult_chan(src, dst, Fa, Fb) MIN ((src) * (Fa) + (dst) * (Fb), 1.0) 213 214 double Fa, Fb; 215 216 switch (op) 217 { 218 case PIXMAN_OP_CLEAR: 219 case PIXMAN_OP_DISJOINT_CLEAR: 220 case PIXMAN_OP_CONJOINT_CLEAR: 221 return mult_chan (src, dst, 0.0, 0.0); 222 223 case PIXMAN_OP_SRC: 224 case PIXMAN_OP_DISJOINT_SRC: 225 case PIXMAN_OP_CONJOINT_SRC: 226 return mult_chan (src, dst, 1.0, 0.0); 227 228 case PIXMAN_OP_DST: 229 case PIXMAN_OP_DISJOINT_DST: 230 case PIXMAN_OP_CONJOINT_DST: 231 return mult_chan (src, dst, 0.0, 1.0); 232 233 case PIXMAN_OP_OVER: 234 return mult_chan (src, dst, 1.0, 1.0 - srca); 235 236 case PIXMAN_OP_OVER_REVERSE: 237 return mult_chan (src, dst, 1.0 - dsta, 1.0); 238 239 case PIXMAN_OP_IN: 240 return mult_chan (src, dst, dsta, 0.0); 241 242 case PIXMAN_OP_IN_REVERSE: 243 return mult_chan (src, dst, 0.0, srca); 244 245 case PIXMAN_OP_OUT: 246 return mult_chan (src, dst, 1.0 - dsta, 0.0); 247 248 case PIXMAN_OP_OUT_REVERSE: 249 return mult_chan (src, dst, 0.0, 1.0 - srca); 250 251 case PIXMAN_OP_ATOP: 252 return mult_chan (src, dst, dsta, 1.0 - srca); 253 254 case PIXMAN_OP_ATOP_REVERSE: 255 return mult_chan (src, dst, 1.0 - dsta, srca); 256 257 case PIXMAN_OP_XOR: 258 return mult_chan (src, dst, 1.0 - dsta, 1.0 - srca); 259 260 case PIXMAN_OP_ADD: 261 return mult_chan (src, dst, 1.0, 1.0); 262 263 case PIXMAN_OP_SATURATE: 264 case PIXMAN_OP_DISJOINT_OVER_REVERSE: 265 if (srca == 0.0) 266 Fa = 1.0; 267 else 268 Fa = MIN (1.0, (1.0 - dsta) / srca); 269 return mult_chan (src, dst, Fa, 1.0); 270 271 case PIXMAN_OP_DISJOINT_OVER: 272 if (dsta == 0.0) 273 Fb = 1.0; 274 else 275 Fb = MIN (1.0, (1.0 - srca) / dsta); 276 return mult_chan (src, dst, 1.0, Fb); 277 278 case PIXMAN_OP_DISJOINT_IN: 279 if (srca == 0.0) 280 Fa = 0.0; 281 else 282 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); 283 return mult_chan (src, dst, Fa, 0.0); 284 285 case PIXMAN_OP_DISJOINT_IN_REVERSE: 286 if (dsta == 0.0) 287 Fb = 0.0; 288 else 289 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); 290 return mult_chan (src, dst, 0.0, Fb); 291 292 case PIXMAN_OP_DISJOINT_OUT: 293 if (srca == 0.0) 294 Fa = 1.0; 295 else 296 Fa = MIN (1.0, (1.0 - dsta) / srca); 297 return mult_chan (src, dst, Fa, 0.0); 298 299 case PIXMAN_OP_DISJOINT_OUT_REVERSE: 300 if (dsta == 0.0) 301 Fb = 1.0; 302 else 303 Fb = MIN (1.0, (1.0 - srca) / dsta); 304 return mult_chan (src, dst, 0.0, Fb); 305 306 case PIXMAN_OP_DISJOINT_ATOP: 307 if (srca == 0.0) 308 Fa = 0.0; 309 else 310 Fa = MAX (0.0, 1.0 - (1.0 - dsta) / srca); 311 if (dsta == 0.0) 312 Fb = 1.0; 313 else 314 Fb = MIN (1.0, (1.0 - srca) / dsta); 315 return mult_chan (src, dst, Fa, Fb); 316 317 case PIXMAN_OP_DISJOINT_ATOP_REVERSE: 318 if (srca == 0.0) 319 Fa = 1.0; 320 else 321 Fa = MIN (1.0, (1.0 - dsta) / srca); 322 if (dsta == 0.0) 323 Fb = 0.0; 324 else 325 Fb = MAX (0.0, 1.0 - (1.0 - srca) / dsta); 326 return mult_chan (src, dst, Fa, Fb); 327 328 case PIXMAN_OP_DISJOINT_XOR: 329 if (srca == 0.0) 330 Fa = 1.0; 331 else 332 Fa = MIN (1.0, (1.0 - dsta) / srca); 333 if (dsta == 0.0) 334 Fb = 1.0; 335 else 336 Fb = MIN (1.0, (1.0 - srca) / dsta); 337 return mult_chan (src, dst, Fa, Fb); 338 339 case PIXMAN_OP_CONJOINT_OVER: 340 if (dsta == 0.0) 341 Fb = 0.0; 342 else 343 Fb = MAX (0.0, 1.0 - srca / dsta); 344 return mult_chan (src, dst, 1.0, Fb); 345 346 case PIXMAN_OP_CONJOINT_OVER_REVERSE: 347 if (srca == 0.0) 348 Fa = 0.0; 349 else 350 Fa = MAX (0.0, 1.0 - dsta / srca); 351 return mult_chan (src, dst, Fa, 1.0); 352 353 case PIXMAN_OP_CONJOINT_IN: 354 if (srca == 0.0) 355 Fa = 1.0; 356 else 357 Fa = MIN (1.0, dsta / srca); 358 return mult_chan (src, dst, Fa, 0.0); 359 360 case PIXMAN_OP_CONJOINT_IN_REVERSE: 361 if (dsta == 0.0) 362 Fb = 1.0; 363 else 364 Fb = MIN (1.0, srca / dsta); 365 return mult_chan (src, dst, 0.0, Fb); 366 367 case PIXMAN_OP_CONJOINT_OUT: 368 if (srca == 0.0) 369 Fa = 0.0; 370 else 371 Fa = MAX (0.0, 1.0 - dsta / srca); 372 return mult_chan (src, dst, Fa, 0.0); 373 374 case PIXMAN_OP_CONJOINT_OUT_REVERSE: 375 if (dsta == 0.0) 376 Fb = 0.0; 377 else 378 Fb = MAX (0.0, 1.0 - srca / dsta); 379 return mult_chan (src, dst, 0.0, Fb); 380 381 case PIXMAN_OP_CONJOINT_ATOP: 382 if (srca == 0.0) 383 Fa = 1.0; 384 else 385 Fa = MIN (1.0, dsta / srca); 386 if (dsta == 0.0) 387 Fb = 0.0; 388 else 389 Fb = MAX (0.0, 1.0 - srca / dsta); 390 return mult_chan (src, dst, Fa, Fb); 391 392 case PIXMAN_OP_CONJOINT_ATOP_REVERSE: 393 if (srca == 0.0) 394 Fa = 0.0; 395 else 396 Fa = MAX (0.0, 1.0 - dsta / srca); 397 if (dsta == 0.0) 398 Fb = 1.0; 399 else 400 Fb = MIN (1.0, srca / dsta); 401 return mult_chan (src, dst, Fa, Fb); 402 403 case PIXMAN_OP_CONJOINT_XOR: 404 if (srca == 0.0) 405 Fa = 0.0; 406 else 407 Fa = MAX (0.0, 1.0 - dsta / srca); 408 if (dsta == 0.0) 409 Fb = 0.0; 410 else 411 Fb = MAX (0.0, 1.0 - srca / dsta); 412 return mult_chan (src, dst, Fa, Fb); 413 414 case PIXMAN_OP_MULTIPLY: 415 case PIXMAN_OP_SCREEN: 416 case PIXMAN_OP_OVERLAY: 417 case PIXMAN_OP_DARKEN: 418 case PIXMAN_OP_LIGHTEN: 419 case PIXMAN_OP_COLOR_DODGE: 420 case PIXMAN_OP_COLOR_BURN: 421 case PIXMAN_OP_HARD_LIGHT: 422 case PIXMAN_OP_SOFT_LIGHT: 423 case PIXMAN_OP_DIFFERENCE: 424 case PIXMAN_OP_EXCLUSION: 425 case PIXMAN_OP_HSL_HUE: 426 case PIXMAN_OP_HSL_SATURATION: 427 case PIXMAN_OP_HSL_COLOR: 428 case PIXMAN_OP_HSL_LUMINOSITY: 429 default: 430 abort(); 431 return 0; /* silence MSVC */ 432 } 433#undef mult_chan 434} 435 436static void 437do_composite (pixman_op_t op, 438 const color_t *src, 439 const color_t *mask, 440 const color_t *dst, 441 color_t *result, 442 pixman_bool_t component_alpha) 443{ 444 color_t srcval, srcalpha; 445 446 if (mask == NULL) 447 { 448 srcval = *src; 449 450 srcalpha.r = src->a; 451 srcalpha.g = src->a; 452 srcalpha.b = src->a; 453 srcalpha.a = src->a; 454 } 455 else if (component_alpha) 456 { 457 srcval.r = src->r * mask->r; 458 srcval.g = src->g * mask->g; 459 srcval.b = src->b * mask->b; 460 srcval.a = src->a * mask->a; 461 462 srcalpha.r = src->a * mask->r; 463 srcalpha.g = src->a * mask->g; 464 srcalpha.b = src->a * mask->b; 465 srcalpha.a = src->a * mask->a; 466 } 467 else 468 { 469 srcval.r = src->r * mask->a; 470 srcval.g = src->g * mask->a; 471 srcval.b = src->b * mask->a; 472 srcval.a = src->a * mask->a; 473 474 srcalpha.r = src->a * mask->a; 475 srcalpha.g = src->a * mask->a; 476 srcalpha.b = src->a * mask->a; 477 srcalpha.a = src->a * mask->a; 478 } 479 480 result->r = calc_op (op, srcval.r, dst->r, srcalpha.r, dst->a); 481 result->g = calc_op (op, srcval.g, dst->g, srcalpha.g, dst->a); 482 result->b = calc_op (op, srcval.b, dst->b, srcalpha.b, dst->a); 483 result->a = calc_op (op, srcval.a, dst->a, srcalpha.a, dst->a); 484} 485 486static void 487color_correct (pixman_format_code_t format, 488 color_t *color) 489{ 490#define MASK(x) ((1 << (x)) - 1) 491#define round_pix(pix, m) \ 492 ((int)((pix) * (MASK(m)) + .5) / (double) (MASK(m))) 493 494 if (PIXMAN_FORMAT_R (format) == 0) 495 { 496 color->r = 0.0; 497 color->g = 0.0; 498 color->b = 0.0; 499 } 500 else 501 { 502 color->r = round_pix (color->r, PIXMAN_FORMAT_R (format)); 503 color->g = round_pix (color->g, PIXMAN_FORMAT_G (format)); 504 color->b = round_pix (color->b, PIXMAN_FORMAT_B (format)); 505 } 506 507 if (PIXMAN_FORMAT_A (format) == 0) 508 color->a = 1.0; 509 else 510 color->a = round_pix (color->a, PIXMAN_FORMAT_A (format)); 511 512#undef round_pix 513#undef MASK 514} 515 516static void 517get_pixel (pixman_image_t *image, 518 pixman_format_code_t format, 519 color_t *color) 520{ 521#define MASK(N) ((1UL << (N))-1) 522 523 unsigned long rs, gs, bs, as; 524 int a, r, g, b; 525 unsigned long val; 526 527 val = *(unsigned long *) pixman_image_get_data (image); 528#ifdef WORDS_BIGENDIAN 529 val >>= 8 * sizeof(val) - PIXMAN_FORMAT_BPP (format); 530#endif 531 532 /* Number of bits in each channel */ 533 a = PIXMAN_FORMAT_A (format); 534 r = PIXMAN_FORMAT_R (format); 535 g = PIXMAN_FORMAT_G (format); 536 b = PIXMAN_FORMAT_B (format); 537 538 switch (PIXMAN_FORMAT_TYPE (format)) 539 { 540 case PIXMAN_TYPE_ARGB: 541 bs = 0; 542 gs = b + bs; 543 rs = g + gs; 544 as = r + rs; 545 break; 546 547 case PIXMAN_TYPE_ABGR: 548 rs = 0; 549 gs = r + rs; 550 bs = g + gs; 551 as = b + bs; 552 break; 553 554 case PIXMAN_TYPE_BGRA: 555 as = 0; 556 rs = PIXMAN_FORMAT_BPP (format) - (b + g + r); 557 gs = r + rs; 558 bs = g + gs; 559 break; 560 561 case PIXMAN_TYPE_RGBA: 562 as = 0; 563 bs = PIXMAN_FORMAT_BPP (format) - (b + g + r); 564 gs = b + bs; 565 rs = g + gs; 566 break; 567 568 case PIXMAN_TYPE_A: 569 as = 0; 570 rs = 0; 571 gs = 0; 572 bs = 0; 573 break; 574 575 case PIXMAN_TYPE_OTHER: 576 case PIXMAN_TYPE_COLOR: 577 case PIXMAN_TYPE_GRAY: 578 case PIXMAN_TYPE_YUY2: 579 case PIXMAN_TYPE_YV12: 580 default: 581 abort (); 582 as = 0; 583 rs = 0; 584 gs = 0; 585 bs = 0; 586 break; 587 } 588 589 if (MASK (a) != 0) 590 color->a = ((val >> as) & MASK (a)) / (double) MASK (a); 591 else 592 color->a = 1.0; 593 594 if (MASK (r) != 0) 595 { 596 color->r = ((val >> rs) & MASK (r)) / (double) MASK (r); 597 color->g = ((val >> gs) & MASK (g)) / (double) MASK (g); 598 color->b = ((val >> bs) & MASK (b)) / (double) MASK (b); 599 } 600 else 601 { 602 color->r = 0.0; 603 color->g = 0.0; 604 color->b = 0.0; 605 } 606 607#undef MASK 608} 609 610static double 611eval_diff (color_t *expected, color_t *test, pixman_format_code_t format) 612{ 613 double rscale, gscale, bscale, ascale; 614 double rdiff, gdiff, bdiff, adiff; 615 616 rscale = 1.0 * ((1 << PIXMAN_FORMAT_R (format)) - 1); 617 gscale = 1.0 * ((1 << PIXMAN_FORMAT_G (format)) - 1); 618 bscale = 1.0 * ((1 << PIXMAN_FORMAT_B (format)) - 1); 619 ascale = 1.0 * ((1 << PIXMAN_FORMAT_A (format)) - 1); 620 621 rdiff = fabs (test->r - expected->r) * rscale; 622 bdiff = fabs (test->g - expected->g) * gscale; 623 gdiff = fabs (test->b - expected->b) * bscale; 624 adiff = fabs (test->a - expected->a) * ascale; 625 626 return MAX (MAX (MAX (rdiff, gdiff), bdiff), adiff); 627} 628 629static char * 630describe_image (image_t *info, char *buf) 631{ 632 if (info->size) 633 { 634 sprintf (buf, "%s %dx%d%s", 635 info->format->name, 636 info->size, info->size, 637 info->repeat ? "R" :""); 638 } 639 else 640 { 641 sprintf (buf, "solid"); 642 } 643 644 return buf; 645} 646 647/* Test a composite of a given operation, source, mask, and destination 648 * picture. 649 * Fills the window, and samples from the 0,0 pixel corner. 650 */ 651static pixman_bool_t 652composite_test (image_t *dst, 653 const operator_t *op, 654 image_t *src, 655 image_t *mask, 656 pixman_bool_t component_alpha) 657{ 658 pixman_color_t fill; 659 pixman_rectangle16_t rect; 660 color_t expected, result, tdst, tsrc, tmsk; 661 double diff; 662 pixman_bool_t success = TRUE; 663 664 compute_pixman_color (dst->color, &fill); 665 rect.x = rect.y = 0; 666 rect.width = rect.height = dst->size; 667 pixman_image_fill_rectangles (PIXMAN_OP_SRC, dst->image, 668 &fill, 1, &rect); 669 670 if (mask != NULL) 671 { 672 pixman_image_set_component_alpha (mask->image, component_alpha); 673 pixman_image_composite (op->op, src->image, mask->image, dst->image, 674 0, 0, 675 0, 0, 676 0, 0, 677 dst->size, dst->size); 678 679 tmsk = *mask->color; 680 if (mask->size) 681 { 682 color_correct (mask->format->format, &tmsk); 683 684 if (component_alpha && 685 PIXMAN_FORMAT_R (mask->format->format) == 0) 686 { 687 /* Ax component-alpha masks expand alpha into 688 * all color channels. 689 */ 690 tmsk.r = tmsk.g = tmsk.b = tmsk.a; 691 } 692 } 693 } 694 else 695 { 696 pixman_image_composite (op->op, src->image, NULL, dst->image, 697 0, 0, 698 0, 0, 699 0, 0, 700 dst->size, dst->size); 701 } 702 get_pixel (dst->image, dst->format->format, &result); 703 704 tdst = *dst->color; 705 color_correct (dst->format->format, &tdst); 706 tsrc = *src->color; 707 if (src->size) 708 color_correct (src->format->format, &tsrc); 709 do_composite (op->op, &tsrc, mask ? &tmsk : NULL, &tdst, 710 &expected, component_alpha); 711 color_correct (dst->format->format, &expected); 712 713 diff = eval_diff (&expected, &result, dst->format->format); 714 715 /* FIXME: We should find out what deviation is acceptable. 3.0 716 * is clearly absurd for 2 bit formats for example. On the other 717 * hand currently 1.0 does not work. 718 */ 719 if (diff > 3.0) 720 { 721 char buf[40]; 722 723 sprintf (buf, "%s %scomposite", 724 op->name, 725 component_alpha ? "CA " : ""); 726 727 printf ("%s test error of %.4f --\n" 728 " R G B A\n" 729 "got: %.2f %.2f %.2f %.2f [%08lx]\n" 730 "expected: %.2f %.2f %.2f %.2f\n", 731 buf, diff, 732 result.r, result.g, result.b, result.a, 733 *(unsigned long *) pixman_image_get_data (dst->image), 734 expected.r, expected.g, expected.b, expected.a); 735 736 if (mask != NULL) 737 { 738 printf ("src color: %.2f %.2f %.2f %.2f\n" 739 "msk color: %.2f %.2f %.2f %.2f\n" 740 "dst color: %.2f %.2f %.2f %.2f\n", 741 src->color->r, src->color->g, 742 src->color->b, src->color->a, 743 mask->color->r, mask->color->g, 744 mask->color->b, mask->color->a, 745 dst->color->r, dst->color->g, 746 dst->color->b, dst->color->a); 747 printf ("src: %s, ", describe_image (src, buf)); 748 printf ("mask: %s, ", describe_image (mask, buf)); 749 printf ("dst: %s\n\n", describe_image (dst, buf)); 750 } 751 else 752 { 753 printf ("src color: %.2f %.2f %.2f %.2f\n" 754 "dst color: %.2f %.2f %.2f %.2f\n", 755 src->color->r, src->color->g, 756 src->color->b, src->color->a, 757 dst->color->r, dst->color->g, 758 dst->color->b, dst->color->a); 759 printf ("src: %s, ", describe_image (src, buf)); 760 printf ("dst: %s\n\n", describe_image (dst, buf)); 761 } 762 763 success = FALSE; 764 } 765 766 return success; 767} 768 769static void 770image_init (image_t *info, 771 int color, 772 int format, 773 int size) 774{ 775 pixman_color_t fill; 776 777 info->color = &colors[color]; 778 compute_pixman_color (info->color, &fill); 779 780 info->format = &formats[format]; 781 info->size = sizes[size] & ~FLAGS; 782 info->repeat = PIXMAN_REPEAT_NONE; 783 784 if (info->size) 785 { 786 pixman_rectangle16_t rect; 787 788 info->image = pixman_image_create_bits (info->format->format, 789 info->size, info->size, 790 NULL, 0); 791 792 rect.x = rect.y = 0; 793 rect.width = rect.height = info->size; 794 pixman_image_fill_rectangles (PIXMAN_OP_SRC, info->image, &fill, 795 1, &rect); 796 797 if (size & REPEAT) 798 { 799 pixman_image_set_repeat (info->image, PIXMAN_REPEAT_NORMAL); 800 info->repeat = PIXMAN_REPEAT_NORMAL; 801 } 802 } 803 else 804 { 805 info->image = pixman_image_create_solid_fill (&fill); 806 } 807} 808 809static void 810image_fini (image_t *info) 811{ 812 pixman_image_unref (info->image); 813} 814 815static int 816random_size (void) 817{ 818 return lcg_rand_n (ARRAY_LENGTH (sizes)); 819} 820 821static int 822random_color (void) 823{ 824 return lcg_rand_n (ARRAY_LENGTH (colors)); 825} 826 827static int 828random_format (void) 829{ 830 return lcg_rand_n (ARRAY_LENGTH (formats)); 831} 832 833static pixman_bool_t 834run_test (uint32_t seed) 835{ 836 image_t src, mask, dst; 837 const operator_t *op; 838 int ca; 839 int ok; 840 841 lcg_srand (seed); 842 843 image_init (&dst, random_color(), random_format(), 1); 844 image_init (&src, random_color(), random_format(), random_size()); 845 image_init (&mask, random_color(), random_format(), random_size()); 846 847 op = &(operators [lcg_rand_n (ARRAY_LENGTH (operators))]); 848 849 ca = lcg_rand_n (3); 850 851 switch (ca) 852 { 853 case 0: 854 ok = composite_test (&dst, op, &src, NULL, FALSE); 855 break; 856 case 1: 857 ok = composite_test (&dst, op, &src, &mask, FALSE); 858 break; 859 case 2: 860 ok = composite_test (&dst, op, &src, &mask, 861 mask.size? TRUE : FALSE); 862 break; 863 default: 864 ok = FALSE; 865 break; 866 } 867 868 image_fini (&src); 869 image_fini (&mask); 870 image_fini (&dst); 871 872 return ok; 873} 874 875int 876main (int argc, char **argv) 877{ 878#define N_TESTS (8 * 1024 * 1024) 879 int result = 0; 880 uint32_t i, seed; 881 882 if (argc > 1) 883 { 884 char *end; 885 886 i = strtol (argv[1], &end, 0); 887 888 if (end != argv[1]) 889 { 890 if (!run_test (i)) 891 return 1; 892 else 893 return 0; 894 } 895 else 896 { 897 printf ("Usage:\n\n %s <number>\n\n", argv[0]); 898 return -1; 899 } 900 } 901 902 if (getenv ("PIXMAN_RANDOMIZE_TESTS")) 903 seed = get_random_seed(); 904 else 905 seed = 1; 906 907#ifdef USE_OPENMP 908# pragma omp parallel for default(none) shared(result, argv, seed) 909#endif 910 for (i = 0; i <= N_TESTS; ++i) 911 { 912 if (!result && !run_test (i + seed)) 913 { 914 printf ("Test 0x%08X failed.\n", seed + i); 915 916 result = seed + i; 917 } 918 } 919 920 return result; 921} 922