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