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