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