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