1#ifdef HAVE_CONFIG_H 2#include <config.h> 3#endif 4 5#include <math.h> 6#include <string.h> 7 8#include "pixman-private.h" 9 10#include "pixman-combine.h" 11 12/*** per channel helper functions ***/ 13 14static void 15combine_mask_ca (comp4_t *src, comp4_t *mask) 16{ 17 comp4_t a = *mask; 18 19 comp4_t x; 20 comp2_t xa; 21 22 if (!a) 23 { 24 *(src) = 0; 25 return; 26 } 27 28 x = *(src); 29 if (a == ~0) 30 { 31 x = x >> A_SHIFT; 32 x |= x << G_SHIFT; 33 x |= x << R_SHIFT; 34 *(mask) = x; 35 return; 36 } 37 38 xa = x >> A_SHIFT; 39 UNcx4_MUL_UNcx4 (x, a); 40 *(src) = x; 41 42 UNcx4_MUL_UNc (a, xa); 43 *(mask) = a; 44} 45 46static void 47combine_mask_value_ca (comp4_t *src, const comp4_t *mask) 48{ 49 comp4_t a = *mask; 50 comp4_t x; 51 52 if (!a) 53 { 54 *(src) = 0; 55 return; 56 } 57 58 if (a == ~0) 59 return; 60 61 x = *(src); 62 UNcx4_MUL_UNcx4 (x, a); 63 *(src) = x; 64} 65 66static void 67combine_mask_alpha_ca (const comp4_t *src, comp4_t *mask) 68{ 69 comp4_t a = *(mask); 70 comp4_t x; 71 72 if (!a) 73 return; 74 75 x = *(src) >> A_SHIFT; 76 if (x == MASK) 77 return; 78 79 if (a == ~0) 80 { 81 x |= x << G_SHIFT; 82 x |= x << R_SHIFT; 83 *(mask) = x; 84 return; 85 } 86 87 UNcx4_MUL_UNc (a, x); 88 *(mask) = a; 89} 90 91/* 92 * There are two ways of handling alpha -- either as a single unified value or 93 * a separate value for each component, hence each macro must have two 94 * versions. The unified alpha version has a 'U' at the end of the name, 95 * the component version has a 'C'. Similarly, functions which deal with 96 * this difference will have two versions using the same convention. 97 */ 98 99/* 100 * All of the composing functions 101 */ 102 103static force_inline comp4_t 104combine_mask (const comp4_t *src, const comp4_t *mask, int i) 105{ 106 comp4_t s, m; 107 108 if (mask) 109 { 110 m = *(mask + i) >> A_SHIFT; 111 112 if (!m) 113 return 0; 114 } 115 116 s = *(src + i); 117 118 if (mask) 119 UNcx4_MUL_UNc (s, m); 120 121 return s; 122} 123 124static void 125combine_clear (pixman_implementation_t *imp, 126 pixman_op_t op, 127 comp4_t * dest, 128 const comp4_t * src, 129 const comp4_t * mask, 130 int width) 131{ 132 memset (dest, 0, width * sizeof(comp4_t)); 133} 134 135static void 136combine_dst (pixman_implementation_t *imp, 137 pixman_op_t op, 138 comp4_t * dest, 139 const comp4_t * src, 140 const comp4_t * mask, 141 int width) 142{ 143 return; 144} 145 146static void 147combine_src_u (pixman_implementation_t *imp, 148 pixman_op_t op, 149 comp4_t * dest, 150 const comp4_t * src, 151 const comp4_t * mask, 152 int width) 153{ 154 int i; 155 156 if (!mask) 157 memcpy (dest, src, width * sizeof (comp4_t)); 158 else 159 { 160 for (i = 0; i < width; ++i) 161 { 162 comp4_t s = combine_mask (src, mask, i); 163 164 *(dest + i) = s; 165 } 166 } 167} 168 169/* if the Src is opaque, call combine_src_u */ 170static void 171combine_over_u (pixman_implementation_t *imp, 172 pixman_op_t op, 173 comp4_t * dest, 174 const comp4_t * src, 175 const comp4_t * mask, 176 int width) 177{ 178 int i; 179 180 for (i = 0; i < width; ++i) 181 { 182 comp4_t s = combine_mask (src, mask, i); 183 comp4_t d = *(dest + i); 184 comp4_t ia = ALPHA_c (~s); 185 186 UNcx4_MUL_UNc_ADD_UNcx4 (d, ia, s); 187 *(dest + i) = d; 188 } 189} 190 191/* if the Dst is opaque, this is a noop */ 192static void 193combine_over_reverse_u (pixman_implementation_t *imp, 194 pixman_op_t op, 195 comp4_t * dest, 196 const comp4_t * src, 197 const comp4_t * mask, 198 int width) 199{ 200 int i; 201 202 for (i = 0; i < width; ++i) 203 { 204 comp4_t s = combine_mask (src, mask, i); 205 comp4_t d = *(dest + i); 206 comp4_t ia = ALPHA_c (~*(dest + i)); 207 UNcx4_MUL_UNc_ADD_UNcx4 (s, ia, d); 208 *(dest + i) = s; 209 } 210} 211 212/* if the Dst is opaque, call combine_src_u */ 213static void 214combine_in_u (pixman_implementation_t *imp, 215 pixman_op_t op, 216 comp4_t * dest, 217 const comp4_t * src, 218 const comp4_t * mask, 219 int width) 220{ 221 int i; 222 223 for (i = 0; i < width; ++i) 224 { 225 comp4_t s = combine_mask (src, mask, i); 226 comp4_t a = ALPHA_c (*(dest + i)); 227 UNcx4_MUL_UNc (s, a); 228 *(dest + i) = s; 229 } 230} 231 232/* if the Src is opaque, this is a noop */ 233static void 234combine_in_reverse_u (pixman_implementation_t *imp, 235 pixman_op_t op, 236 comp4_t * dest, 237 const comp4_t * src, 238 const comp4_t * mask, 239 int width) 240{ 241 int i; 242 243 for (i = 0; i < width; ++i) 244 { 245 comp4_t s = combine_mask (src, mask, i); 246 comp4_t d = *(dest + i); 247 comp4_t a = ALPHA_c (s); 248 UNcx4_MUL_UNc (d, a); 249 *(dest + i) = d; 250 } 251} 252 253/* if the Dst is opaque, call combine_clear */ 254static void 255combine_out_u (pixman_implementation_t *imp, 256 pixman_op_t op, 257 comp4_t * dest, 258 const comp4_t * src, 259 const comp4_t * mask, 260 int width) 261{ 262 int i; 263 264 for (i = 0; i < width; ++i) 265 { 266 comp4_t s = combine_mask (src, mask, i); 267 comp4_t a = ALPHA_c (~*(dest + i)); 268 UNcx4_MUL_UNc (s, a); 269 *(dest + i) = s; 270 } 271} 272 273/* if the Src is opaque, call combine_clear */ 274static void 275combine_out_reverse_u (pixman_implementation_t *imp, 276 pixman_op_t op, 277 comp4_t * dest, 278 const comp4_t * src, 279 const comp4_t * mask, 280 int width) 281{ 282 int i; 283 284 for (i = 0; i < width; ++i) 285 { 286 comp4_t s = combine_mask (src, mask, i); 287 comp4_t d = *(dest + i); 288 comp4_t a = ALPHA_c (~s); 289 UNcx4_MUL_UNc (d, a); 290 *(dest + i) = d; 291 } 292} 293 294/* if the Src is opaque, call combine_in_u */ 295/* if the Dst is opaque, call combine_over_u */ 296/* if both the Src and Dst are opaque, call combine_src_u */ 297static void 298combine_atop_u (pixman_implementation_t *imp, 299 pixman_op_t op, 300 comp4_t * dest, 301 const comp4_t * src, 302 const comp4_t * mask, 303 int width) 304{ 305 int i; 306 307 for (i = 0; i < width; ++i) 308 { 309 comp4_t s = combine_mask (src, mask, i); 310 comp4_t d = *(dest + i); 311 comp4_t dest_a = ALPHA_c (d); 312 comp4_t src_ia = ALPHA_c (~s); 313 314 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_a, d, src_ia); 315 *(dest + i) = s; 316 } 317} 318 319/* if the Src is opaque, call combine_over_reverse_u */ 320/* if the Dst is opaque, call combine_in_reverse_u */ 321/* if both the Src and Dst are opaque, call combine_dst_u */ 322static void 323combine_atop_reverse_u (pixman_implementation_t *imp, 324 pixman_op_t op, 325 comp4_t * dest, 326 const comp4_t * src, 327 const comp4_t * mask, 328 int width) 329{ 330 int i; 331 332 for (i = 0; i < width; ++i) 333 { 334 comp4_t s = combine_mask (src, mask, i); 335 comp4_t d = *(dest + i); 336 comp4_t src_a = ALPHA_c (s); 337 comp4_t dest_ia = ALPHA_c (~d); 338 339 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_a); 340 *(dest + i) = s; 341 } 342} 343 344/* if the Src is opaque, call combine_over_u */ 345/* if the Dst is opaque, call combine_over_reverse_u */ 346/* if both the Src and Dst are opaque, call combine_clear */ 347static void 348combine_xor_u (pixman_implementation_t *imp, 349 pixman_op_t op, 350 comp4_t * dest, 351 const comp4_t * src, 352 const comp4_t * mask, 353 int width) 354{ 355 int i; 356 357 for (i = 0; i < width; ++i) 358 { 359 comp4_t s = combine_mask (src, mask, i); 360 comp4_t d = *(dest + i); 361 comp4_t src_ia = ALPHA_c (~s); 362 comp4_t dest_ia = ALPHA_c (~d); 363 364 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (s, dest_ia, d, src_ia); 365 *(dest + i) = s; 366 } 367} 368 369static void 370combine_add_u (pixman_implementation_t *imp, 371 pixman_op_t op, 372 comp4_t * dest, 373 const comp4_t * src, 374 const comp4_t * mask, 375 int width) 376{ 377 int i; 378 379 for (i = 0; i < width; ++i) 380 { 381 comp4_t s = combine_mask (src, mask, i); 382 comp4_t d = *(dest + i); 383 UNcx4_ADD_UNcx4 (d, s); 384 *(dest + i) = d; 385 } 386} 387 388/* if the Src is opaque, call combine_add_u */ 389/* if the Dst is opaque, call combine_add_u */ 390/* if both the Src and Dst are opaque, call combine_add_u */ 391static void 392combine_saturate_u (pixman_implementation_t *imp, 393 pixman_op_t op, 394 comp4_t * dest, 395 const comp4_t * src, 396 const comp4_t * mask, 397 int width) 398{ 399 int i; 400 401 for (i = 0; i < width; ++i) 402 { 403 comp4_t s = combine_mask (src, mask, i); 404 comp4_t d = *(dest + i); 405 comp2_t sa, da; 406 407 sa = s >> A_SHIFT; 408 da = ~d >> A_SHIFT; 409 if (sa > da) 410 { 411 sa = DIV_UNc (da, sa); 412 UNcx4_MUL_UNc (s, sa); 413 } 414 ; 415 UNcx4_ADD_UNcx4 (d, s); 416 *(dest + i) = d; 417 } 418} 419 420/* 421 * PDF blend modes: 422 * The following blend modes have been taken from the PDF ISO 32000 423 * specification, which at this point in time is available from 424 * http://www.adobe.com/devnet/acrobat/pdfs/PDF32000_2008.pdf 425 * The relevant chapters are 11.3.5 and 11.3.6. 426 * The formula for computing the final pixel color given in 11.3.6 is: 427 * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs) 428 * with B() being the blend function. 429 * Note that OVER is a special case of this operation, using B(Cb, Cs) = Cs 430 * 431 * These blend modes should match the SVG filter draft specification, as 432 * it has been designed to mirror ISO 32000. Note that at the current point 433 * no released draft exists that shows this, as the formulas have not been 434 * updated yet after the release of ISO 32000. 435 * 436 * The default implementation here uses the PDF_SEPARABLE_BLEND_MODE and 437 * PDF_NON_SEPARABLE_BLEND_MODE macros, which take the blend function as an 438 * argument. Note that this implementation operates on premultiplied colors, 439 * while the PDF specification does not. Therefore the code uses the formula 440 * Cra = (1 – as) . Dca + (1 – ad) . Sca + B(Dca, ad, Sca, as) 441 */ 442 443/* 444 * Multiply 445 * B(Dca, ad, Sca, as) = Dca.Sca 446 */ 447 448static void 449combine_multiply_u (pixman_implementation_t *imp, 450 pixman_op_t op, 451 comp4_t * dest, 452 const comp4_t * src, 453 const comp4_t * mask, 454 int width) 455{ 456 int i; 457 458 for (i = 0; i < width; ++i) 459 { 460 comp4_t s = combine_mask (src, mask, i); 461 comp4_t d = *(dest + i); 462 comp4_t ss = s; 463 comp4_t src_ia = ALPHA_c (~s); 464 comp4_t dest_ia = ALPHA_c (~d); 465 466 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (ss, dest_ia, d, src_ia); 467 UNcx4_MUL_UNcx4 (d, s); 468 UNcx4_ADD_UNcx4 (d, ss); 469 470 *(dest + i) = d; 471 } 472} 473 474static void 475combine_multiply_ca (pixman_implementation_t *imp, 476 pixman_op_t op, 477 comp4_t * dest, 478 const comp4_t * src, 479 const comp4_t * mask, 480 int width) 481{ 482 int i; 483 484 for (i = 0; i < width; ++i) 485 { 486 comp4_t m = *(mask + i); 487 comp4_t s = *(src + i); 488 comp4_t d = *(dest + i); 489 comp4_t r = d; 490 comp4_t dest_ia = ALPHA_c (~d); 491 492 combine_mask_value_ca (&s, &m); 493 494 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (r, ~m, s, dest_ia); 495 UNcx4_MUL_UNcx4 (d, s); 496 UNcx4_ADD_UNcx4 (r, d); 497 498 *(dest + i) = r; 499 } 500} 501 502#define PDF_SEPARABLE_BLEND_MODE(name) \ 503 static void \ 504 combine_ ## name ## _u (pixman_implementation_t *imp, \ 505 pixman_op_t op, \ 506 comp4_t * dest, \ 507 const comp4_t * src, \ 508 const comp4_t * mask, \ 509 int width) \ 510 { \ 511 int i; \ 512 for (i = 0; i < width; ++i) { \ 513 comp4_t s = combine_mask (src, mask, i); \ 514 comp4_t d = *(dest + i); \ 515 comp1_t sa = ALPHA_c (s); \ 516 comp1_t isa = ~sa; \ 517 comp1_t da = ALPHA_c (d); \ 518 comp1_t ida = ~da; \ 519 comp4_t result; \ 520 \ 521 result = d; \ 522 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (result, isa, s, ida); \ 523 \ 524 *(dest + i) = result + \ 525 (DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \ 526 (blend_ ## name (RED_c (d), da, RED_c (s), sa) << R_SHIFT) + \ 527 (blend_ ## name (GREEN_c (d), da, GREEN_c (s), sa) << G_SHIFT) + \ 528 (blend_ ## name (BLUE_c (d), da, BLUE_c (s), sa)); \ 529 } \ 530 } \ 531 \ 532 static void \ 533 combine_ ## name ## _ca (pixman_implementation_t *imp, \ 534 pixman_op_t op, \ 535 comp4_t * dest, \ 536 const comp4_t * src, \ 537 const comp4_t * mask, \ 538 int width) \ 539 { \ 540 int i; \ 541 for (i = 0; i < width; ++i) { \ 542 comp4_t m = *(mask + i); \ 543 comp4_t s = *(src + i); \ 544 comp4_t d = *(dest + i); \ 545 comp1_t da = ALPHA_c (d); \ 546 comp1_t ida = ~da; \ 547 comp4_t result; \ 548 \ 549 combine_mask_value_ca (&s, &m); \ 550 \ 551 result = d; \ 552 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (result, ~m, s, ida); \ 553 \ 554 result += \ 555 (DIV_ONE_UNc (ALPHA_c (m) * (comp4_t)da) << A_SHIFT) + \ 556 (blend_ ## name (RED_c (d), da, RED_c (s), RED_c (m)) << R_SHIFT) + \ 557 (blend_ ## name (GREEN_c (d), da, GREEN_c (s), GREEN_c (m)) << G_SHIFT) + \ 558 (blend_ ## name (BLUE_c (d), da, BLUE_c (s), BLUE_c (m))); \ 559 \ 560 *(dest + i) = result; \ 561 } \ 562 } 563 564/* 565 * Screen 566 * B(Dca, ad, Sca, as) = Dca.sa + Sca.da - Dca.Sca 567 */ 568static inline comp4_t 569blend_screen (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 570{ 571 return DIV_ONE_UNc (sca * da + dca * sa - sca * dca); 572} 573 574PDF_SEPARABLE_BLEND_MODE (screen) 575 576/* 577 * Overlay 578 * B(Dca, Da, Sca, Sa) = 579 * if 2.Dca < Da 580 * 2.Sca.Dca 581 * otherwise 582 * Sa.Da - 2.(Da - Dca).(Sa - Sca) 583 */ 584static inline comp4_t 585blend_overlay (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 586{ 587 comp4_t rca; 588 589 if (2 * dca < da) 590 rca = 2 * sca * dca; 591 else 592 rca = sa * da - 2 * (da - dca) * (sa - sca); 593 return DIV_ONE_UNc (rca); 594} 595 596PDF_SEPARABLE_BLEND_MODE (overlay) 597 598/* 599 * Darken 600 * B(Dca, Da, Sca, Sa) = min (Sca.Da, Dca.Sa) 601 */ 602static inline comp4_t 603blend_darken (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 604{ 605 comp4_t s, d; 606 607 s = sca * da; 608 d = dca * sa; 609 return DIV_ONE_UNc (s > d ? d : s); 610} 611 612PDF_SEPARABLE_BLEND_MODE (darken) 613 614/* 615 * Lighten 616 * B(Dca, Da, Sca, Sa) = max (Sca.Da, Dca.Sa) 617 */ 618static inline comp4_t 619blend_lighten (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 620{ 621 comp4_t s, d; 622 623 s = sca * da; 624 d = dca * sa; 625 return DIV_ONE_UNc (s > d ? s : d); 626} 627 628PDF_SEPARABLE_BLEND_MODE (lighten) 629 630/* 631 * Color dodge 632 * B(Dca, Da, Sca, Sa) = 633 * if Dca == 0 634 * 0 635 * if Sca == Sa 636 * Sa.Da 637 * otherwise 638 * Sa.Da. min (1, Dca / Da / (1 - Sca/Sa)) 639 */ 640static inline comp4_t 641blend_color_dodge (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 642{ 643 if (sca >= sa) 644 { 645 return dca == 0 ? 0 : DIV_ONE_UNc (sa * da); 646 } 647 else 648 { 649 comp4_t rca = dca * sa / (sa - sca); 650 return DIV_ONE_UNc (sa * MIN (rca, da)); 651 } 652} 653 654PDF_SEPARABLE_BLEND_MODE (color_dodge) 655 656/* 657 * Color burn 658 * B(Dca, Da, Sca, Sa) = 659 * if Dca == Da 660 * Sa.Da 661 * if Sca == 0 662 * 0 663 * otherwise 664 * Sa.Da.(1 - min (1, (1 - Dca/Da).Sa / Sca)) 665 */ 666static inline comp4_t 667blend_color_burn (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 668{ 669 if (sca == 0) 670 { 671 return dca < da ? 0 : DIV_ONE_UNc (sa * da); 672 } 673 else 674 { 675 comp4_t rca = (da - dca) * sa / sca; 676 return DIV_ONE_UNc (sa * (MAX (rca, da) - rca)); 677 } 678} 679 680PDF_SEPARABLE_BLEND_MODE (color_burn) 681 682/* 683 * Hard light 684 * B(Dca, Da, Sca, Sa) = 685 * if 2.Sca < Sa 686 * 2.Sca.Dca 687 * otherwise 688 * Sa.Da - 2.(Da - Dca).(Sa - Sca) 689 */ 690static inline comp4_t 691blend_hard_light (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 692{ 693 if (2 * sca < sa) 694 return DIV_ONE_UNc (2 * sca * dca); 695 else 696 return DIV_ONE_UNc (sa * da - 2 * (da - dca) * (sa - sca)); 697} 698 699PDF_SEPARABLE_BLEND_MODE (hard_light) 700 701/* 702 * Soft light 703 * B(Dca, Da, Sca, Sa) = 704 * if (2.Sca <= Sa) 705 * Dca.(Sa - (1 - Dca/Da).(2.Sca - Sa)) 706 * otherwise if Dca.4 <= Da 707 * Dca.(Sa + (2.Sca - Sa).((16.Dca/Da - 12).Dca/Da + 3) 708 * otherwise 709 * (Dca.Sa + (SQRT (Dca/Da).Da - Dca).(2.Sca - Sa)) 710 */ 711static inline comp4_t 712blend_soft_light (comp4_t dca_org, 713 comp4_t da_org, 714 comp4_t sca_org, 715 comp4_t sa_org) 716{ 717 double dca = dca_org * (1.0 / MASK); 718 double da = da_org * (1.0 / MASK); 719 double sca = sca_org * (1.0 / MASK); 720 double sa = sa_org * (1.0 / MASK); 721 double rca; 722 723 if (2 * sca < sa) 724 { 725 if (da == 0) 726 rca = dca * sa; 727 else 728 rca = dca * sa - dca * (da - dca) * (sa - 2 * sca) / da; 729 } 730 else if (da == 0) 731 { 732 rca = 0; 733 } 734 else if (4 * dca <= da) 735 { 736 rca = dca * sa + 737 (2 * sca - sa) * dca * ((16 * dca / da - 12) * dca / da + 3); 738 } 739 else 740 { 741 rca = dca * sa + (sqrt (dca * da) - dca) * (2 * sca - sa); 742 } 743 return rca * MASK + 0.5; 744} 745 746PDF_SEPARABLE_BLEND_MODE (soft_light) 747 748/* 749 * Difference 750 * B(Dca, Da, Sca, Sa) = abs (Dca.Sa - Sca.Da) 751 */ 752static inline comp4_t 753blend_difference (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 754{ 755 comp4_t dcasa = dca * sa; 756 comp4_t scada = sca * da; 757 758 if (scada < dcasa) 759 return DIV_ONE_UNc (dcasa - scada); 760 else 761 return DIV_ONE_UNc (scada - dcasa); 762} 763 764PDF_SEPARABLE_BLEND_MODE (difference) 765 766/* 767 * Exclusion 768 * B(Dca, Da, Sca, Sa) = (Sca.Da + Dca.Sa - 2.Sca.Dca) 769 */ 770 771/* This can be made faster by writing it directly and not using 772 * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */ 773 774static inline comp4_t 775blend_exclusion (comp4_t dca, comp4_t da, comp4_t sca, comp4_t sa) 776{ 777 return DIV_ONE_UNc (sca * da + dca * sa - 2 * dca * sca); 778} 779 780PDF_SEPARABLE_BLEND_MODE (exclusion) 781 782#undef PDF_SEPARABLE_BLEND_MODE 783 784/* 785 * PDF nonseperable blend modes are implemented using the following functions 786 * to operate in Hsl space, with Cmax, Cmid, Cmin referring to the max, mid 787 * and min value of the red, green and blue components. 788 * 789 * LUM (C) = 0.3 × Cred + 0.59 × Cgreen + 0.11 × Cblue 790 * 791 * clip_color (C): 792 * l = LUM (C) 793 * min = Cmin 794 * max = Cmax 795 * if n < 0.0 796 * C = l + ( ( ( C – l ) × l ) ⁄ ( l – min ) ) 797 * if x > 1.0 798 * C = l + ( ( ( C – l ) × ( 1 – l ) ) ⁄ ( max – l ) ) 799 * return C 800 * 801 * set_lum (C, l): 802 * d = l – LUM (C) 803 * C += d 804 * return clip_color (C) 805 * 806 * SAT (C) = CH_MAX (C) - CH_MIN (C) 807 * 808 * set_sat (C, s): 809 * if Cmax > Cmin 810 * Cmid = ( ( ( Cmid – Cmin ) × s ) ⁄ ( Cmax – Cmin ) ) 811 * Cmax = s 812 * else 813 * Cmid = Cmax = 0.0 814 * Cmin = 0.0 815 * return C 816 */ 817 818/* For premultiplied colors, we need to know what happens when C is 819 * multiplied by a real number. LUM and SAT are linear: 820 * 821 * LUM (r × C) = r × LUM (C) SAT (r * C) = r * SAT (C) 822 * 823 * If we extend clip_color with an extra argument a and change 824 * 825 * if x >= 1.0 826 * 827 * into 828 * 829 * if x >= a 830 * 831 * then clip_color is also linear: 832 * 833 * r * clip_color (C, a) = clip_color (r_c, ra); 834 * 835 * for positive r. 836 * 837 * Similarly, we can extend set_lum with an extra argument that is just passed 838 * on to clip_color: 839 * 840 * r * set_lum ( C, l, a) 841 * 842 * = r × clip_color ( C + l - LUM (C), a) 843 * 844 * = clip_color ( r * C + r × l - r * LUM (C), r * a) 845 * 846 * = set_lum ( r * C, r * l, r * a) 847 * 848 * Finally, set_sat: 849 * 850 * r * set_sat (C, s) = set_sat (x * C, r * s) 851 * 852 * The above holds for all non-zero x, because the x'es in the fraction for 853 * C_mid cancel out. Specifically, it holds for x = r: 854 * 855 * r * set_sat (C, s) = set_sat (r_c, rs) 856 * 857 */ 858 859/* So, for the non-separable PDF blend modes, we have (using s, d for 860 * non-premultiplied colors, and S, D for premultiplied: 861 * 862 * Color: 863 * 864 * a_s * a_d * B(s, d) 865 * = a_s * a_d * set_lum (S/a_s, LUM (D/a_d), 1) 866 * = set_lum (S * a_d, a_s * LUM (D), a_s * a_d) 867 * 868 * 869 * Luminosity: 870 * 871 * a_s * a_d * B(s, d) 872 * = a_s * a_d * set_lum (D/a_d, LUM(S/a_s), 1) 873 * = set_lum (a_s * D, a_d * LUM(S), a_s * a_d) 874 * 875 * 876 * Saturation: 877 * 878 * a_s * a_d * B(s, d) 879 * = a_s * a_d * set_lum (set_sat (D/a_d, SAT (S/a_s)), LUM (D/a_d), 1) 880 * = set_lum (a_s * a_d * set_sat (D/a_d, SAT (S/a_s)), 881 * a_s * LUM (D), a_s * a_d) 882 * = set_lum (set_sat (a_s * D, a_d * SAT (S), a_s * LUM (D), a_s * a_d)) 883 * 884 * Hue: 885 * 886 * a_s * a_d * B(s, d) 887 * = a_s * a_d * set_lum (set_sat (S/a_s, SAT (D/a_d)), LUM (D/a_d), 1) 888 * = set_lum (set_sat (a_d * S, a_s * SAT (D)), a_s * LUM (D), a_s * a_d) 889 * 890 */ 891 892#define CH_MIN(c) (c[0] < c[1] ? (c[0] < c[2] ? c[0] : c[2]) : (c[1] < c[2] ? c[1] : c[2])) 893#define CH_MAX(c) (c[0] > c[1] ? (c[0] > c[2] ? c[0] : c[2]) : (c[1] > c[2] ? c[1] : c[2])) 894#define LUM(c) ((c[0] * 30 + c[1] * 59 + c[2] * 11) / 100) 895#define SAT(c) (CH_MAX (c) - CH_MIN (c)) 896 897#define PDF_NON_SEPARABLE_BLEND_MODE(name) \ 898 static void \ 899 combine_ ## name ## _u (pixman_implementation_t *imp, \ 900 pixman_op_t op, \ 901 comp4_t *dest, \ 902 const comp4_t *src, \ 903 const comp4_t *mask, \ 904 int width) \ 905 { \ 906 int i; \ 907 for (i = 0; i < width; ++i) \ 908 { \ 909 comp4_t s = combine_mask (src, mask, i); \ 910 comp4_t d = *(dest + i); \ 911 comp1_t sa = ALPHA_c (s); \ 912 comp1_t isa = ~sa; \ 913 comp1_t da = ALPHA_c (d); \ 914 comp1_t ida = ~da; \ 915 comp4_t result; \ 916 comp4_t sc[3], dc[3], c[3]; \ 917 \ 918 result = d; \ 919 UNcx4_MUL_UNc_ADD_UNcx4_MUL_UNc (result, isa, s, ida); \ 920 dc[0] = RED_c (d); \ 921 sc[0] = RED_c (s); \ 922 dc[1] = GREEN_c (d); \ 923 sc[1] = GREEN_c (s); \ 924 dc[2] = BLUE_c (d); \ 925 sc[2] = BLUE_c (s); \ 926 blend_ ## name (c, dc, da, sc, sa); \ 927 \ 928 *(dest + i) = result + \ 929 (DIV_ONE_UNc (sa * (comp4_t)da) << A_SHIFT) + \ 930 (DIV_ONE_UNc (c[0]) << R_SHIFT) + \ 931 (DIV_ONE_UNc (c[1]) << G_SHIFT) + \ 932 (DIV_ONE_UNc (c[2])); \ 933 } \ 934 } 935 936static void 937set_lum (comp4_t dest[3], comp4_t src[3], comp4_t sa, comp4_t lum) 938{ 939 double a, l, min, max; 940 double tmp[3]; 941 942 a = sa * (1.0 / MASK); 943 944 l = lum * (1.0 / MASK); 945 tmp[0] = src[0] * (1.0 / MASK); 946 tmp[1] = src[1] * (1.0 / MASK); 947 tmp[2] = src[2] * (1.0 / MASK); 948 949 l = l - LUM (tmp); 950 tmp[0] += l; 951 tmp[1] += l; 952 tmp[2] += l; 953 954 /* clip_color */ 955 l = LUM (tmp); 956 min = CH_MIN (tmp); 957 max = CH_MAX (tmp); 958 959 if (min < 0) 960 { 961 if (l - min == 0.0) 962 { 963 tmp[0] = 0; 964 tmp[1] = 0; 965 tmp[2] = 0; 966 } 967 else 968 { 969 tmp[0] = l + (tmp[0] - l) * l / (l - min); 970 tmp[1] = l + (tmp[1] - l) * l / (l - min); 971 tmp[2] = l + (tmp[2] - l) * l / (l - min); 972 } 973 } 974 if (max > a) 975 { 976 if (max - l == 0.0) 977 { 978 tmp[0] = a; 979 tmp[1] = a; 980 tmp[2] = a; 981 } 982 else 983 { 984 tmp[0] = l + (tmp[0] - l) * (a - l) / (max - l); 985 tmp[1] = l + (tmp[1] - l) * (a - l) / (max - l); 986 tmp[2] = l + (tmp[2] - l) * (a - l) / (max - l); 987 } 988 } 989 990 dest[0] = tmp[0] * MASK + 0.5; 991 dest[1] = tmp[1] * MASK + 0.5; 992 dest[2] = tmp[2] * MASK + 0.5; 993} 994 995static void 996set_sat (comp4_t dest[3], comp4_t src[3], comp4_t sat) 997{ 998 int id[3]; 999 comp4_t min, max; 1000 1001 if (src[0] > src[1]) 1002 { 1003 if (src[0] > src[2]) 1004 { 1005 id[0] = 0; 1006 if (src[1] > src[2]) 1007 { 1008 id[1] = 1; 1009 id[2] = 2; 1010 } 1011 else 1012 { 1013 id[1] = 2; 1014 id[2] = 1; 1015 } 1016 } 1017 else 1018 { 1019 id[0] = 2; 1020 id[1] = 0; 1021 id[2] = 1; 1022 } 1023 } 1024 else 1025 { 1026 if (src[0] > src[2]) 1027 { 1028 id[0] = 1; 1029 id[1] = 0; 1030 id[2] = 2; 1031 } 1032 else 1033 { 1034 id[2] = 0; 1035 if (src[1] > src[2]) 1036 { 1037 id[0] = 1; 1038 id[1] = 2; 1039 } 1040 else 1041 { 1042 id[0] = 2; 1043 id[1] = 1; 1044 } 1045 } 1046 } 1047 1048 max = dest[id[0]]; 1049 min = dest[id[2]]; 1050 if (max > min) 1051 { 1052 dest[id[1]] = (dest[id[1]] - min) * sat / (max - min); 1053 dest[id[0]] = sat; 1054 dest[id[2]] = 0; 1055 } 1056 else 1057 { 1058 dest[0] = dest[1] = dest[2] = 0; 1059 } 1060} 1061 1062/* 1063 * Hue: 1064 * B(Cb, Cs) = set_lum (set_sat (Cs, SAT (Cb)), LUM (Cb)) 1065 */ 1066static inline void 1067blend_hsl_hue (comp4_t c[3], 1068 comp4_t dc[3], 1069 comp4_t da, 1070 comp4_t sc[3], 1071 comp4_t sa) 1072{ 1073 c[0] = sc[0] * da; 1074 c[1] = sc[1] * da; 1075 c[2] = sc[2] * da; 1076 set_sat (c, c, SAT (dc) * sa); 1077 set_lum (c, c, sa * da, LUM (dc) * sa); 1078} 1079 1080PDF_NON_SEPARABLE_BLEND_MODE (hsl_hue) 1081 1082/* 1083 * Saturation: 1084 * B(Cb, Cs) = set_lum (set_sat (Cb, SAT (Cs)), LUM (Cb)) 1085 */ 1086static inline void 1087blend_hsl_saturation (comp4_t c[3], 1088 comp4_t dc[3], 1089 comp4_t da, 1090 comp4_t sc[3], 1091 comp4_t sa) 1092{ 1093 c[0] = dc[0] * sa; 1094 c[1] = dc[1] * sa; 1095 c[2] = dc[2] * sa; 1096 set_sat (c, c, SAT (sc) * da); 1097 set_lum (c, c, sa * da, LUM (dc) * sa); 1098} 1099 1100PDF_NON_SEPARABLE_BLEND_MODE (hsl_saturation) 1101 1102/* 1103 * Color: 1104 * B(Cb, Cs) = set_lum (Cs, LUM (Cb)) 1105 */ 1106static inline void 1107blend_hsl_color (comp4_t c[3], 1108 comp4_t dc[3], 1109 comp4_t da, 1110 comp4_t sc[3], 1111 comp4_t sa) 1112{ 1113 c[0] = sc[0] * da; 1114 c[1] = sc[1] * da; 1115 c[2] = sc[2] * da; 1116 set_lum (c, c, sa * da, LUM (dc) * sa); 1117} 1118 1119PDF_NON_SEPARABLE_BLEND_MODE (hsl_color) 1120 1121/* 1122 * Luminosity: 1123 * B(Cb, Cs) = set_lum (Cb, LUM (Cs)) 1124 */ 1125static inline void 1126blend_hsl_luminosity (comp4_t c[3], 1127 comp4_t dc[3], 1128 comp4_t da, 1129 comp4_t sc[3], 1130 comp4_t sa) 1131{ 1132 c[0] = dc[0] * sa; 1133 c[1] = dc[1] * sa; 1134 c[2] = dc[2] * sa; 1135 set_lum (c, c, sa * da, LUM (sc) * da); 1136} 1137 1138PDF_NON_SEPARABLE_BLEND_MODE (hsl_luminosity) 1139 1140#undef SAT 1141#undef LUM 1142#undef CH_MAX 1143#undef CH_MIN 1144#undef PDF_NON_SEPARABLE_BLEND_MODE 1145 1146/* All of the disjoint/conjoint composing functions 1147 * 1148 * The four entries in the first column indicate what source contributions 1149 * come from each of the four areas of the picture -- areas covered by neither 1150 * A nor B, areas covered only by A, areas covered only by B and finally 1151 * areas covered by both A and B. 1152 * 1153 * Disjoint Conjoint 1154 * Fa Fb Fa Fb 1155 * (0,0,0,0) 0 0 0 0 1156 * (0,A,0,A) 1 0 1 0 1157 * (0,0,B,B) 0 1 0 1 1158 * (0,A,B,A) 1 min((1-a)/b,1) 1 max(1-a/b,0) 1159 * (0,A,B,B) min((1-b)/a,1) 1 max(1-b/a,0) 1 1160 * (0,0,0,A) max(1-(1-b)/a,0) 0 min(1,b/a) 0 1161 * (0,0,0,B) 0 max(1-(1-a)/b,0) 0 min(a/b,1) 1162 * (0,A,0,0) min(1,(1-b)/a) 0 max(1-b/a,0) 0 1163 * (0,0,B,0) 0 min(1,(1-a)/b) 0 max(1-a/b,0) 1164 * (0,0,B,A) max(1-(1-b)/a,0) min(1,(1-a)/b) min(1,b/a) max(1-a/b,0) 1165 * (0,A,0,B) min(1,(1-b)/a) max(1-(1-a)/b,0) max(1-b/a,0) min(1,a/b) 1166 * (0,A,B,0) min(1,(1-b)/a) min(1,(1-a)/b) max(1-b/a,0) max(1-a/b,0) 1167 * 1168 * See http://marc.info/?l=xfree-render&m=99792000027857&w=2 for more 1169 * information about these operators. 1170 */ 1171 1172#define COMBINE_A_OUT 1 1173#define COMBINE_A_IN 2 1174#define COMBINE_B_OUT 4 1175#define COMBINE_B_IN 8 1176 1177#define COMBINE_CLEAR 0 1178#define COMBINE_A (COMBINE_A_OUT | COMBINE_A_IN) 1179#define COMBINE_B (COMBINE_B_OUT | COMBINE_B_IN) 1180#define COMBINE_A_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_A_IN) 1181#define COMBINE_B_OVER (COMBINE_A_OUT | COMBINE_B_OUT | COMBINE_B_IN) 1182#define COMBINE_A_ATOP (COMBINE_B_OUT | COMBINE_A_IN) 1183#define COMBINE_B_ATOP (COMBINE_A_OUT | COMBINE_B_IN) 1184#define COMBINE_XOR (COMBINE_A_OUT | COMBINE_B_OUT) 1185 1186/* portion covered by a but not b */ 1187static comp1_t 1188combine_disjoint_out_part (comp1_t a, comp1_t b) 1189{ 1190 /* min (1, (1-b) / a) */ 1191 1192 b = ~b; /* 1 - b */ 1193 if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ 1194 return MASK; /* 1 */ 1195 return DIV_UNc (b, a); /* (1-b) / a */ 1196} 1197 1198/* portion covered by both a and b */ 1199static comp1_t 1200combine_disjoint_in_part (comp1_t a, comp1_t b) 1201{ 1202 /* max (1-(1-b)/a,0) */ 1203 /* = - min ((1-b)/a - 1, 0) */ 1204 /* = 1 - min (1, (1-b)/a) */ 1205 1206 b = ~b; /* 1 - b */ 1207 if (b >= a) /* 1 - b >= a -> (1-b)/a >= 1 */ 1208 return 0; /* 1 - 1 */ 1209 return ~DIV_UNc(b, a); /* 1 - (1-b) / a */ 1210} 1211 1212/* portion covered by a but not b */ 1213static comp1_t 1214combine_conjoint_out_part (comp1_t a, comp1_t b) 1215{ 1216 /* max (1-b/a,0) */ 1217 /* = 1-min(b/a,1) */ 1218 1219 /* min (1, (1-b) / a) */ 1220 1221 if (b >= a) /* b >= a -> b/a >= 1 */ 1222 return 0x00; /* 0 */ 1223 return ~DIV_UNc(b, a); /* 1 - b/a */ 1224} 1225 1226/* portion covered by both a and b */ 1227static comp1_t 1228combine_conjoint_in_part (comp1_t a, comp1_t b) 1229{ 1230 /* min (1,b/a) */ 1231 1232 if (b >= a) /* b >= a -> b/a >= 1 */ 1233 return MASK; /* 1 */ 1234 return DIV_UNc (b, a); /* b/a */ 1235} 1236 1237#define GET_COMP(v, i) ((comp2_t) (comp1_t) ((v) >> i)) 1238 1239#define ADD(x, y, i, t) \ 1240 ((t) = GET_COMP (x, i) + GET_COMP (y, i), \ 1241 (comp4_t) ((comp1_t) ((t) | (0 - ((t) >> G_SHIFT)))) << (i)) 1242 1243#define GENERIC(x, y, i, ax, ay, t, u, v) \ 1244 ((t) = (MUL_UNc (GET_COMP (y, i), ay, (u)) + \ 1245 MUL_UNc (GET_COMP (x, i), ax, (v))), \ 1246 (comp4_t) ((comp1_t) ((t) | \ 1247 (0 - ((t) >> G_SHIFT)))) << (i)) 1248 1249static void 1250combine_disjoint_general_u (comp4_t * dest, 1251 const comp4_t *src, 1252 const comp4_t *mask, 1253 int width, 1254 comp1_t combine) 1255{ 1256 int i; 1257 1258 for (i = 0; i < width; ++i) 1259 { 1260 comp4_t s = combine_mask (src, mask, i); 1261 comp4_t d = *(dest + i); 1262 comp4_t m, n, o, p; 1263 comp2_t Fa, Fb, t, u, v; 1264 comp1_t sa = s >> A_SHIFT; 1265 comp1_t da = d >> A_SHIFT; 1266 1267 switch (combine & COMBINE_A) 1268 { 1269 default: 1270 Fa = 0; 1271 break; 1272 1273 case COMBINE_A_OUT: 1274 Fa = combine_disjoint_out_part (sa, da); 1275 break; 1276 1277 case COMBINE_A_IN: 1278 Fa = combine_disjoint_in_part (sa, da); 1279 break; 1280 1281 case COMBINE_A: 1282 Fa = MASK; 1283 break; 1284 } 1285 1286 switch (combine & COMBINE_B) 1287 { 1288 default: 1289 Fb = 0; 1290 break; 1291 1292 case COMBINE_B_OUT: 1293 Fb = combine_disjoint_out_part (da, sa); 1294 break; 1295 1296 case COMBINE_B_IN: 1297 Fb = combine_disjoint_in_part (da, sa); 1298 break; 1299 1300 case COMBINE_B: 1301 Fb = MASK; 1302 break; 1303 } 1304 m = GENERIC (s, d, 0, Fa, Fb, t, u, v); 1305 n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v); 1306 o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v); 1307 p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v); 1308 s = m | n | o | p; 1309 *(dest + i) = s; 1310 } 1311} 1312 1313static void 1314combine_disjoint_over_u (pixman_implementation_t *imp, 1315 pixman_op_t op, 1316 comp4_t * dest, 1317 const comp4_t * src, 1318 const comp4_t * mask, 1319 int width) 1320{ 1321 int i; 1322 1323 for (i = 0; i < width; ++i) 1324 { 1325 comp4_t s = combine_mask (src, mask, i); 1326 comp2_t a = s >> A_SHIFT; 1327 1328 if (s != 0x00) 1329 { 1330 comp4_t d = *(dest + i); 1331 a = combine_disjoint_out_part (d >> A_SHIFT, a); 1332 UNcx4_MUL_UNc_ADD_UNcx4 (d, a, s); 1333 1334 *(dest + i) = d; 1335 } 1336 } 1337} 1338 1339static void 1340combine_disjoint_in_u (pixman_implementation_t *imp, 1341 pixman_op_t op, 1342 comp4_t * dest, 1343 const comp4_t * src, 1344 const comp4_t * mask, 1345 int width) 1346{ 1347 combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_IN); 1348} 1349 1350static void 1351combine_disjoint_in_reverse_u (pixman_implementation_t *imp, 1352 pixman_op_t op, 1353 comp4_t * dest, 1354 const comp4_t * src, 1355 const comp4_t * mask, 1356 int width) 1357{ 1358 combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_IN); 1359} 1360 1361static void 1362combine_disjoint_out_u (pixman_implementation_t *imp, 1363 pixman_op_t op, 1364 comp4_t * dest, 1365 const comp4_t * src, 1366 const comp4_t * mask, 1367 int width) 1368{ 1369 combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_OUT); 1370} 1371 1372static void 1373combine_disjoint_out_reverse_u (pixman_implementation_t *imp, 1374 pixman_op_t op, 1375 comp4_t * dest, 1376 const comp4_t * src, 1377 const comp4_t * mask, 1378 int width) 1379{ 1380 combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_OUT); 1381} 1382 1383static void 1384combine_disjoint_atop_u (pixman_implementation_t *imp, 1385 pixman_op_t op, 1386 comp4_t * dest, 1387 const comp4_t * src, 1388 const comp4_t * mask, 1389 int width) 1390{ 1391 combine_disjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP); 1392} 1393 1394static void 1395combine_disjoint_atop_reverse_u (pixman_implementation_t *imp, 1396 pixman_op_t op, 1397 comp4_t * dest, 1398 const comp4_t * src, 1399 const comp4_t * mask, 1400 int width) 1401{ 1402 combine_disjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP); 1403} 1404 1405static void 1406combine_disjoint_xor_u (pixman_implementation_t *imp, 1407 pixman_op_t op, 1408 comp4_t * dest, 1409 const comp4_t * src, 1410 const comp4_t * mask, 1411 int width) 1412{ 1413 combine_disjoint_general_u (dest, src, mask, width, COMBINE_XOR); 1414} 1415 1416static void 1417combine_conjoint_general_u (comp4_t * dest, 1418 const comp4_t *src, 1419 const comp4_t *mask, 1420 int width, 1421 comp1_t combine) 1422{ 1423 int i; 1424 1425 for (i = 0; i < width; ++i) 1426 { 1427 comp4_t s = combine_mask (src, mask, i); 1428 comp4_t d = *(dest + i); 1429 comp4_t m, n, o, p; 1430 comp2_t Fa, Fb, t, u, v; 1431 comp1_t sa = s >> A_SHIFT; 1432 comp1_t da = d >> A_SHIFT; 1433 1434 switch (combine & COMBINE_A) 1435 { 1436 default: 1437 Fa = 0; 1438 break; 1439 1440 case COMBINE_A_OUT: 1441 Fa = combine_conjoint_out_part (sa, da); 1442 break; 1443 1444 case COMBINE_A_IN: 1445 Fa = combine_conjoint_in_part (sa, da); 1446 break; 1447 1448 case COMBINE_A: 1449 Fa = MASK; 1450 break; 1451 } 1452 1453 switch (combine & COMBINE_B) 1454 { 1455 default: 1456 Fb = 0; 1457 break; 1458 1459 case COMBINE_B_OUT: 1460 Fb = combine_conjoint_out_part (da, sa); 1461 break; 1462 1463 case COMBINE_B_IN: 1464 Fb = combine_conjoint_in_part (da, sa); 1465 break; 1466 1467 case COMBINE_B: 1468 Fb = MASK; 1469 break; 1470 } 1471 1472 m = GENERIC (s, d, 0, Fa, Fb, t, u, v); 1473 n = GENERIC (s, d, G_SHIFT, Fa, Fb, t, u, v); 1474 o = GENERIC (s, d, R_SHIFT, Fa, Fb, t, u, v); 1475 p = GENERIC (s, d, A_SHIFT, Fa, Fb, t, u, v); 1476 1477 s = m | n | o | p; 1478 1479 *(dest + i) = s; 1480 } 1481} 1482 1483static void 1484combine_conjoint_over_u (pixman_implementation_t *imp, 1485 pixman_op_t op, 1486 comp4_t * dest, 1487 const comp4_t * src, 1488 const comp4_t * mask, 1489 int width) 1490{ 1491 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OVER); 1492} 1493 1494static void 1495combine_conjoint_over_reverse_u (pixman_implementation_t *imp, 1496 pixman_op_t op, 1497 comp4_t * dest, 1498 const comp4_t * src, 1499 const comp4_t * mask, 1500 int width) 1501{ 1502 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OVER); 1503} 1504 1505static void 1506combine_conjoint_in_u (pixman_implementation_t *imp, 1507 pixman_op_t op, 1508 comp4_t * dest, 1509 const comp4_t * src, 1510 const comp4_t * mask, 1511 int width) 1512{ 1513 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_IN); 1514} 1515 1516static void 1517combine_conjoint_in_reverse_u (pixman_implementation_t *imp, 1518 pixman_op_t op, 1519 comp4_t * dest, 1520 const comp4_t * src, 1521 const comp4_t * mask, 1522 int width) 1523{ 1524 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_IN); 1525} 1526 1527static void 1528combine_conjoint_out_u (pixman_implementation_t *imp, 1529 pixman_op_t op, 1530 comp4_t * dest, 1531 const comp4_t * src, 1532 const comp4_t * mask, 1533 int width) 1534{ 1535 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_OUT); 1536} 1537 1538static void 1539combine_conjoint_out_reverse_u (pixman_implementation_t *imp, 1540 pixman_op_t op, 1541 comp4_t * dest, 1542 const comp4_t * src, 1543 const comp4_t * mask, 1544 int width) 1545{ 1546 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_OUT); 1547} 1548 1549static void 1550combine_conjoint_atop_u (pixman_implementation_t *imp, 1551 pixman_op_t op, 1552 comp4_t * dest, 1553 const comp4_t * src, 1554 const comp4_t * mask, 1555 int width) 1556{ 1557 combine_conjoint_general_u (dest, src, mask, width, COMBINE_A_ATOP); 1558} 1559 1560static void 1561combine_conjoint_atop_reverse_u (pixman_implementation_t *imp, 1562 pixman_op_t op, 1563 comp4_t * dest, 1564 const comp4_t * src, 1565 const comp4_t * mask, 1566 int width) 1567{ 1568 combine_conjoint_general_u (dest, src, mask, width, COMBINE_B_ATOP); 1569} 1570 1571static void 1572combine_conjoint_xor_u (pixman_implementation_t *imp, 1573 pixman_op_t op, 1574 comp4_t * dest, 1575 const comp4_t * src, 1576 const comp4_t * mask, 1577 int width) 1578{ 1579 combine_conjoint_general_u (dest, src, mask, width, COMBINE_XOR); 1580} 1581 1582/************************************************************************/ 1583/*********************** Per Channel functions **************************/ 1584/************************************************************************/ 1585 1586static void 1587combine_clear_ca (pixman_implementation_t *imp, 1588 pixman_op_t op, 1589 comp4_t * dest, 1590 const comp4_t * src, 1591 const comp4_t * mask, 1592 int width) 1593{ 1594 memset (dest, 0, width * sizeof(comp4_t)); 1595} 1596 1597static void 1598combine_src_ca (pixman_implementation_t *imp, 1599 pixman_op_t op, 1600 comp4_t * dest, 1601 const comp4_t * src, 1602 const comp4_t * mask, 1603 int width) 1604{ 1605 int i; 1606 1607 for (i = 0; i < width; ++i) 1608 { 1609 comp4_t s = *(src + i); 1610 comp4_t m = *(mask + i); 1611 1612 combine_mask_value_ca (&s, &m); 1613 1614 *(dest + i) = s; 1615 } 1616} 1617 1618static void 1619combine_over_ca (pixman_implementation_t *imp, 1620 pixman_op_t op, 1621 comp4_t * dest, 1622 const comp4_t * src, 1623 const comp4_t * mask, 1624 int width) 1625{ 1626 int i; 1627 1628 for (i = 0; i < width; ++i) 1629 { 1630 comp4_t s = *(src + i); 1631 comp4_t m = *(mask + i); 1632 comp4_t a; 1633 1634 combine_mask_ca (&s, &m); 1635 1636 a = ~m; 1637 if (a) 1638 { 1639 comp4_t d = *(dest + i); 1640 UNcx4_MUL_UNcx4_ADD_UNcx4 (d, a, s); 1641 s = d; 1642 } 1643 1644 *(dest + i) = s; 1645 } 1646} 1647 1648static void 1649combine_over_reverse_ca (pixman_implementation_t *imp, 1650 pixman_op_t op, 1651 comp4_t * dest, 1652 const comp4_t * src, 1653 const comp4_t * mask, 1654 int width) 1655{ 1656 int i; 1657 1658 for (i = 0; i < width; ++i) 1659 { 1660 comp4_t d = *(dest + i); 1661 comp4_t a = ~d >> A_SHIFT; 1662 1663 if (a) 1664 { 1665 comp4_t s = *(src + i); 1666 comp4_t m = *(mask + i); 1667 1668 UNcx4_MUL_UNcx4 (s, m); 1669 UNcx4_MUL_UNc_ADD_UNcx4 (s, a, d); 1670 1671 *(dest + i) = s; 1672 } 1673 } 1674} 1675 1676static void 1677combine_in_ca (pixman_implementation_t *imp, 1678 pixman_op_t op, 1679 comp4_t * dest, 1680 const comp4_t * src, 1681 const comp4_t * mask, 1682 int width) 1683{ 1684 int i; 1685 1686 for (i = 0; i < width; ++i) 1687 { 1688 comp4_t d = *(dest + i); 1689 comp2_t a = d >> A_SHIFT; 1690 comp4_t s = 0; 1691 1692 if (a) 1693 { 1694 comp4_t m = *(mask + i); 1695 1696 s = *(src + i); 1697 combine_mask_value_ca (&s, &m); 1698 1699 if (a != MASK) 1700 UNcx4_MUL_UNc (s, a); 1701 } 1702 1703 *(dest + i) = s; 1704 } 1705} 1706 1707static void 1708combine_in_reverse_ca (pixman_implementation_t *imp, 1709 pixman_op_t op, 1710 comp4_t * dest, 1711 const comp4_t * src, 1712 const comp4_t * mask, 1713 int width) 1714{ 1715 int i; 1716 1717 for (i = 0; i < width; ++i) 1718 { 1719 comp4_t s = *(src + i); 1720 comp4_t m = *(mask + i); 1721 comp4_t a; 1722 1723 combine_mask_alpha_ca (&s, &m); 1724 1725 a = m; 1726 if (a != ~0) 1727 { 1728 comp4_t d = 0; 1729 1730 if (a) 1731 { 1732 d = *(dest + i); 1733 UNcx4_MUL_UNcx4 (d, a); 1734 } 1735 1736 *(dest + i) = d; 1737 } 1738 } 1739} 1740 1741static void 1742combine_out_ca (pixman_implementation_t *imp, 1743 pixman_op_t op, 1744 comp4_t * dest, 1745 const comp4_t * src, 1746 const comp4_t * mask, 1747 int width) 1748{ 1749 int i; 1750 1751 for (i = 0; i < width; ++i) 1752 { 1753 comp4_t d = *(dest + i); 1754 comp2_t a = ~d >> A_SHIFT; 1755 comp4_t s = 0; 1756 1757 if (a) 1758 { 1759 comp4_t m = *(mask + i); 1760 1761 s = *(src + i); 1762 combine_mask_value_ca (&s, &m); 1763 1764 if (a != MASK) 1765 UNcx4_MUL_UNc (s, a); 1766 } 1767 1768 *(dest + i) = s; 1769 } 1770} 1771 1772static void 1773combine_out_reverse_ca (pixman_implementation_t *imp, 1774 pixman_op_t op, 1775 comp4_t * dest, 1776 const comp4_t * src, 1777 const comp4_t * mask, 1778 int width) 1779{ 1780 int i; 1781 1782 for (i = 0; i < width; ++i) 1783 { 1784 comp4_t s = *(src + i); 1785 comp4_t m = *(mask + i); 1786 comp4_t a; 1787 1788 combine_mask_alpha_ca (&s, &m); 1789 1790 a = ~m; 1791 if (a != ~0) 1792 { 1793 comp4_t d = 0; 1794 1795 if (a) 1796 { 1797 d = *(dest + i); 1798 UNcx4_MUL_UNcx4 (d, a); 1799 } 1800 1801 *(dest + i) = d; 1802 } 1803 } 1804} 1805 1806static void 1807combine_atop_ca (pixman_implementation_t *imp, 1808 pixman_op_t op, 1809 comp4_t * dest, 1810 const comp4_t * src, 1811 const comp4_t * mask, 1812 int width) 1813{ 1814 int i; 1815 1816 for (i = 0; i < width; ++i) 1817 { 1818 comp4_t d = *(dest + i); 1819 comp4_t s = *(src + i); 1820 comp4_t m = *(mask + i); 1821 comp4_t ad; 1822 comp2_t as = d >> A_SHIFT; 1823 1824 combine_mask_ca (&s, &m); 1825 1826 ad = ~m; 1827 1828 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as); 1829 1830 *(dest + i) = d; 1831 } 1832} 1833 1834static void 1835combine_atop_reverse_ca (pixman_implementation_t *imp, 1836 pixman_op_t op, 1837 comp4_t * dest, 1838 const comp4_t * src, 1839 const comp4_t * mask, 1840 int width) 1841{ 1842 int i; 1843 1844 for (i = 0; i < width; ++i) 1845 { 1846 comp4_t d = *(dest + i); 1847 comp4_t s = *(src + i); 1848 comp4_t m = *(mask + i); 1849 comp4_t ad; 1850 comp2_t as = ~d >> A_SHIFT; 1851 1852 combine_mask_ca (&s, &m); 1853 1854 ad = m; 1855 1856 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as); 1857 1858 *(dest + i) = d; 1859 } 1860} 1861 1862static void 1863combine_xor_ca (pixman_implementation_t *imp, 1864 pixman_op_t op, 1865 comp4_t * dest, 1866 const comp4_t * src, 1867 const comp4_t * mask, 1868 int width) 1869{ 1870 int i; 1871 1872 for (i = 0; i < width; ++i) 1873 { 1874 comp4_t d = *(dest + i); 1875 comp4_t s = *(src + i); 1876 comp4_t m = *(mask + i); 1877 comp4_t ad; 1878 comp2_t as = ~d >> A_SHIFT; 1879 1880 combine_mask_ca (&s, &m); 1881 1882 ad = ~m; 1883 1884 UNcx4_MUL_UNcx4_ADD_UNcx4_MUL_UNc (d, ad, s, as); 1885 1886 *(dest + i) = d; 1887 } 1888} 1889 1890static void 1891combine_add_ca (pixman_implementation_t *imp, 1892 pixman_op_t op, 1893 comp4_t * dest, 1894 const comp4_t * src, 1895 const comp4_t * mask, 1896 int width) 1897{ 1898 int i; 1899 1900 for (i = 0; i < width; ++i) 1901 { 1902 comp4_t s = *(src + i); 1903 comp4_t m = *(mask + i); 1904 comp4_t d = *(dest + i); 1905 1906 combine_mask_value_ca (&s, &m); 1907 1908 UNcx4_ADD_UNcx4 (d, s); 1909 1910 *(dest + i) = d; 1911 } 1912} 1913 1914static void 1915combine_saturate_ca (pixman_implementation_t *imp, 1916 pixman_op_t op, 1917 comp4_t * dest, 1918 const comp4_t * src, 1919 const comp4_t * mask, 1920 int width) 1921{ 1922 int i; 1923 1924 for (i = 0; i < width; ++i) 1925 { 1926 comp4_t s, d; 1927 comp2_t sa, sr, sg, sb, da; 1928 comp2_t t, u, v; 1929 comp4_t m, n, o, p; 1930 1931 d = *(dest + i); 1932 s = *(src + i); 1933 m = *(mask + i); 1934 1935 combine_mask_ca (&s, &m); 1936 1937 sa = (m >> A_SHIFT); 1938 sr = (m >> R_SHIFT) & MASK; 1939 sg = (m >> G_SHIFT) & MASK; 1940 sb = m & MASK; 1941 da = ~d >> A_SHIFT; 1942 1943 if (sb <= da) 1944 m = ADD (s, d, 0, t); 1945 else 1946 m = GENERIC (s, d, 0, (da << G_SHIFT) / sb, MASK, t, u, v); 1947 1948 if (sg <= da) 1949 n = ADD (s, d, G_SHIFT, t); 1950 else 1951 n = GENERIC (s, d, G_SHIFT, (da << G_SHIFT) / sg, MASK, t, u, v); 1952 1953 if (sr <= da) 1954 o = ADD (s, d, R_SHIFT, t); 1955 else 1956 o = GENERIC (s, d, R_SHIFT, (da << G_SHIFT) / sr, MASK, t, u, v); 1957 1958 if (sa <= da) 1959 p = ADD (s, d, A_SHIFT, t); 1960 else 1961 p = GENERIC (s, d, A_SHIFT, (da << G_SHIFT) / sa, MASK, t, u, v); 1962 1963 *(dest + i) = m | n | o | p; 1964 } 1965} 1966 1967static void 1968combine_disjoint_general_ca (comp4_t * dest, 1969 const comp4_t *src, 1970 const comp4_t *mask, 1971 int width, 1972 comp1_t combine) 1973{ 1974 int i; 1975 1976 for (i = 0; i < width; ++i) 1977 { 1978 comp4_t s, d; 1979 comp4_t m, n, o, p; 1980 comp4_t Fa, Fb; 1981 comp2_t t, u, v; 1982 comp4_t sa; 1983 comp1_t da; 1984 1985 s = *(src + i); 1986 m = *(mask + i); 1987 d = *(dest + i); 1988 da = d >> A_SHIFT; 1989 1990 combine_mask_ca (&s, &m); 1991 1992 sa = m; 1993 1994 switch (combine & COMBINE_A) 1995 { 1996 default: 1997 Fa = 0; 1998 break; 1999 2000 case COMBINE_A_OUT: 2001 m = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> 0), da); 2002 n = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; 2003 o = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; 2004 p = (comp4_t)combine_disjoint_out_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; 2005 Fa = m | n | o | p; 2006 break; 2007 2008 case COMBINE_A_IN: 2009 m = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> 0), da); 2010 n = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; 2011 o = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; 2012 p = (comp4_t)combine_disjoint_in_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; 2013 Fa = m | n | o | p; 2014 break; 2015 2016 case COMBINE_A: 2017 Fa = ~0; 2018 break; 2019 } 2020 2021 switch (combine & COMBINE_B) 2022 { 2023 default: 2024 Fb = 0; 2025 break; 2026 2027 case COMBINE_B_OUT: 2028 m = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> 0)); 2029 n = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; 2030 o = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; 2031 p = (comp4_t)combine_disjoint_out_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; 2032 Fb = m | n | o | p; 2033 break; 2034 2035 case COMBINE_B_IN: 2036 m = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> 0)); 2037 n = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; 2038 o = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; 2039 p = (comp4_t)combine_disjoint_in_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; 2040 Fb = m | n | o | p; 2041 break; 2042 2043 case COMBINE_B: 2044 Fb = ~0; 2045 break; 2046 } 2047 m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v); 2048 n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v); 2049 o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v); 2050 p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v); 2051 2052 s = m | n | o | p; 2053 2054 *(dest + i) = s; 2055 } 2056} 2057 2058static void 2059combine_disjoint_over_ca (pixman_implementation_t *imp, 2060 pixman_op_t op, 2061 comp4_t * dest, 2062 const comp4_t * src, 2063 const comp4_t * mask, 2064 int width) 2065{ 2066 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER); 2067} 2068 2069static void 2070combine_disjoint_in_ca (pixman_implementation_t *imp, 2071 pixman_op_t op, 2072 comp4_t * dest, 2073 const comp4_t * src, 2074 const comp4_t * mask, 2075 int width) 2076{ 2077 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_IN); 2078} 2079 2080static void 2081combine_disjoint_in_reverse_ca (pixman_implementation_t *imp, 2082 pixman_op_t op, 2083 comp4_t * dest, 2084 const comp4_t * src, 2085 const comp4_t * mask, 2086 int width) 2087{ 2088 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_IN); 2089} 2090 2091static void 2092combine_disjoint_out_ca (pixman_implementation_t *imp, 2093 pixman_op_t op, 2094 comp4_t * dest, 2095 const comp4_t * src, 2096 const comp4_t * mask, 2097 int width) 2098{ 2099 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT); 2100} 2101 2102static void 2103combine_disjoint_out_reverse_ca (pixman_implementation_t *imp, 2104 pixman_op_t op, 2105 comp4_t * dest, 2106 const comp4_t * src, 2107 const comp4_t * mask, 2108 int width) 2109{ 2110 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT); 2111} 2112 2113static void 2114combine_disjoint_atop_ca (pixman_implementation_t *imp, 2115 pixman_op_t op, 2116 comp4_t * dest, 2117 const comp4_t * src, 2118 const comp4_t * mask, 2119 int width) 2120{ 2121 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP); 2122} 2123 2124static void 2125combine_disjoint_atop_reverse_ca (pixman_implementation_t *imp, 2126 pixman_op_t op, 2127 comp4_t * dest, 2128 const comp4_t * src, 2129 const comp4_t * mask, 2130 int width) 2131{ 2132 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP); 2133} 2134 2135static void 2136combine_disjoint_xor_ca (pixman_implementation_t *imp, 2137 pixman_op_t op, 2138 comp4_t * dest, 2139 const comp4_t * src, 2140 const comp4_t * mask, 2141 int width) 2142{ 2143 combine_disjoint_general_ca (dest, src, mask, width, COMBINE_XOR); 2144} 2145 2146static void 2147combine_conjoint_general_ca (comp4_t * dest, 2148 const comp4_t *src, 2149 const comp4_t *mask, 2150 int width, 2151 comp1_t combine) 2152{ 2153 int i; 2154 2155 for (i = 0; i < width; ++i) 2156 { 2157 comp4_t s, d; 2158 comp4_t m, n, o, p; 2159 comp4_t Fa, Fb; 2160 comp2_t t, u, v; 2161 comp4_t sa; 2162 comp1_t da; 2163 2164 s = *(src + i); 2165 m = *(mask + i); 2166 d = *(dest + i); 2167 da = d >> A_SHIFT; 2168 2169 combine_mask_ca (&s, &m); 2170 2171 sa = m; 2172 2173 switch (combine & COMBINE_A) 2174 { 2175 default: 2176 Fa = 0; 2177 break; 2178 2179 case COMBINE_A_OUT: 2180 m = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> 0), da); 2181 n = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; 2182 o = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; 2183 p = (comp4_t)combine_conjoint_out_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; 2184 Fa = m | n | o | p; 2185 break; 2186 2187 case COMBINE_A_IN: 2188 m = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> 0), da); 2189 n = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> G_SHIFT), da) << G_SHIFT; 2190 o = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> R_SHIFT), da) << R_SHIFT; 2191 p = (comp4_t)combine_conjoint_in_part ((comp1_t) (sa >> A_SHIFT), da) << A_SHIFT; 2192 Fa = m | n | o | p; 2193 break; 2194 2195 case COMBINE_A: 2196 Fa = ~0; 2197 break; 2198 } 2199 2200 switch (combine & COMBINE_B) 2201 { 2202 default: 2203 Fb = 0; 2204 break; 2205 2206 case COMBINE_B_OUT: 2207 m = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> 0)); 2208 n = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; 2209 o = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; 2210 p = (comp4_t)combine_conjoint_out_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; 2211 Fb = m | n | o | p; 2212 break; 2213 2214 case COMBINE_B_IN: 2215 m = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> 0)); 2216 n = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> G_SHIFT)) << G_SHIFT; 2217 o = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> R_SHIFT)) << R_SHIFT; 2218 p = (comp4_t)combine_conjoint_in_part (da, (comp1_t) (sa >> A_SHIFT)) << A_SHIFT; 2219 Fb = m | n | o | p; 2220 break; 2221 2222 case COMBINE_B: 2223 Fb = ~0; 2224 break; 2225 } 2226 m = GENERIC (s, d, 0, GET_COMP (Fa, 0), GET_COMP (Fb, 0), t, u, v); 2227 n = GENERIC (s, d, G_SHIFT, GET_COMP (Fa, G_SHIFT), GET_COMP (Fb, G_SHIFT), t, u, v); 2228 o = GENERIC (s, d, R_SHIFT, GET_COMP (Fa, R_SHIFT), GET_COMP (Fb, R_SHIFT), t, u, v); 2229 p = GENERIC (s, d, A_SHIFT, GET_COMP (Fa, A_SHIFT), GET_COMP (Fb, A_SHIFT), t, u, v); 2230 2231 s = m | n | o | p; 2232 2233 *(dest + i) = s; 2234 } 2235} 2236 2237static void 2238combine_conjoint_over_ca (pixman_implementation_t *imp, 2239 pixman_op_t op, 2240 comp4_t * dest, 2241 const comp4_t * src, 2242 const comp4_t * mask, 2243 int width) 2244{ 2245 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OVER); 2246} 2247 2248static void 2249combine_conjoint_over_reverse_ca (pixman_implementation_t *imp, 2250 pixman_op_t op, 2251 comp4_t * dest, 2252 const comp4_t * src, 2253 const comp4_t * mask, 2254 int width) 2255{ 2256 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OVER); 2257} 2258 2259static void 2260combine_conjoint_in_ca (pixman_implementation_t *imp, 2261 pixman_op_t op, 2262 comp4_t * dest, 2263 const comp4_t * src, 2264 const comp4_t * mask, 2265 int width) 2266{ 2267 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_IN); 2268} 2269 2270static void 2271combine_conjoint_in_reverse_ca (pixman_implementation_t *imp, 2272 pixman_op_t op, 2273 comp4_t * dest, 2274 const comp4_t * src, 2275 const comp4_t * mask, 2276 int width) 2277{ 2278 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_IN); 2279} 2280 2281static void 2282combine_conjoint_out_ca (pixman_implementation_t *imp, 2283 pixman_op_t op, 2284 comp4_t * dest, 2285 const comp4_t * src, 2286 const comp4_t * mask, 2287 int width) 2288{ 2289 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_OUT); 2290} 2291 2292static void 2293combine_conjoint_out_reverse_ca (pixman_implementation_t *imp, 2294 pixman_op_t op, 2295 comp4_t * dest, 2296 const comp4_t * src, 2297 const comp4_t * mask, 2298 int width) 2299{ 2300 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_OUT); 2301} 2302 2303static void 2304combine_conjoint_atop_ca (pixman_implementation_t *imp, 2305 pixman_op_t op, 2306 comp4_t * dest, 2307 const comp4_t * src, 2308 const comp4_t * mask, 2309 int width) 2310{ 2311 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_A_ATOP); 2312} 2313 2314static void 2315combine_conjoint_atop_reverse_ca (pixman_implementation_t *imp, 2316 pixman_op_t op, 2317 comp4_t * dest, 2318 const comp4_t * src, 2319 const comp4_t * mask, 2320 int width) 2321{ 2322 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_B_ATOP); 2323} 2324 2325static void 2326combine_conjoint_xor_ca (pixman_implementation_t *imp, 2327 pixman_op_t op, 2328 comp4_t * dest, 2329 const comp4_t * src, 2330 const comp4_t * mask, 2331 int width) 2332{ 2333 combine_conjoint_general_ca (dest, src, mask, width, COMBINE_XOR); 2334} 2335 2336void 2337_pixman_setup_combiner_functions_width (pixman_implementation_t *imp) 2338{ 2339 /* Unified alpha */ 2340 imp->combine_width[PIXMAN_OP_CLEAR] = combine_clear; 2341 imp->combine_width[PIXMAN_OP_SRC] = combine_src_u; 2342 imp->combine_width[PIXMAN_OP_DST] = combine_dst; 2343 imp->combine_width[PIXMAN_OP_OVER] = combine_over_u; 2344 imp->combine_width[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u; 2345 imp->combine_width[PIXMAN_OP_IN] = combine_in_u; 2346 imp->combine_width[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u; 2347 imp->combine_width[PIXMAN_OP_OUT] = combine_out_u; 2348 imp->combine_width[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u; 2349 imp->combine_width[PIXMAN_OP_ATOP] = combine_atop_u; 2350 imp->combine_width[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u; 2351 imp->combine_width[PIXMAN_OP_XOR] = combine_xor_u; 2352 imp->combine_width[PIXMAN_OP_ADD] = combine_add_u; 2353 imp->combine_width[PIXMAN_OP_SATURATE] = combine_saturate_u; 2354 2355 /* Disjoint, unified */ 2356 imp->combine_width[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear; 2357 imp->combine_width[PIXMAN_OP_DISJOINT_SRC] = combine_src_u; 2358 imp->combine_width[PIXMAN_OP_DISJOINT_DST] = combine_dst; 2359 imp->combine_width[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_u; 2360 imp->combine_width[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_u; 2361 imp->combine_width[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_u; 2362 imp->combine_width[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_u; 2363 imp->combine_width[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_u; 2364 imp->combine_width[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_u; 2365 imp->combine_width[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_u; 2366 imp->combine_width[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_u; 2367 imp->combine_width[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_u; 2368 2369 /* Conjoint, unified */ 2370 imp->combine_width[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear; 2371 imp->combine_width[PIXMAN_OP_CONJOINT_SRC] = combine_src_u; 2372 imp->combine_width[PIXMAN_OP_CONJOINT_DST] = combine_dst; 2373 imp->combine_width[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_u; 2374 imp->combine_width[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_u; 2375 imp->combine_width[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_u; 2376 imp->combine_width[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_u; 2377 imp->combine_width[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_u; 2378 imp->combine_width[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_u; 2379 imp->combine_width[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_u; 2380 imp->combine_width[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_u; 2381 imp->combine_width[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_u; 2382 2383 imp->combine_width[PIXMAN_OP_MULTIPLY] = combine_multiply_u; 2384 imp->combine_width[PIXMAN_OP_SCREEN] = combine_screen_u; 2385 imp->combine_width[PIXMAN_OP_OVERLAY] = combine_overlay_u; 2386 imp->combine_width[PIXMAN_OP_DARKEN] = combine_darken_u; 2387 imp->combine_width[PIXMAN_OP_LIGHTEN] = combine_lighten_u; 2388 imp->combine_width[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_u; 2389 imp->combine_width[PIXMAN_OP_COLOR_BURN] = combine_color_burn_u; 2390 imp->combine_width[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u; 2391 imp->combine_width[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_u; 2392 imp->combine_width[PIXMAN_OP_DIFFERENCE] = combine_difference_u; 2393 imp->combine_width[PIXMAN_OP_EXCLUSION] = combine_exclusion_u; 2394 imp->combine_width[PIXMAN_OP_HSL_HUE] = combine_hsl_hue_u; 2395 imp->combine_width[PIXMAN_OP_HSL_SATURATION] = combine_hsl_saturation_u; 2396 imp->combine_width[PIXMAN_OP_HSL_COLOR] = combine_hsl_color_u; 2397 imp->combine_width[PIXMAN_OP_HSL_LUMINOSITY] = combine_hsl_luminosity_u; 2398 2399 /* Component alpha combiners */ 2400 imp->combine_width_ca[PIXMAN_OP_CLEAR] = combine_clear_ca; 2401 imp->combine_width_ca[PIXMAN_OP_SRC] = combine_src_ca; 2402 /* dest */ 2403 imp->combine_width_ca[PIXMAN_OP_OVER] = combine_over_ca; 2404 imp->combine_width_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca; 2405 imp->combine_width_ca[PIXMAN_OP_IN] = combine_in_ca; 2406 imp->combine_width_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca; 2407 imp->combine_width_ca[PIXMAN_OP_OUT] = combine_out_ca; 2408 imp->combine_width_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca; 2409 imp->combine_width_ca[PIXMAN_OP_ATOP] = combine_atop_ca; 2410 imp->combine_width_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca; 2411 imp->combine_width_ca[PIXMAN_OP_XOR] = combine_xor_ca; 2412 imp->combine_width_ca[PIXMAN_OP_ADD] = combine_add_ca; 2413 imp->combine_width_ca[PIXMAN_OP_SATURATE] = combine_saturate_ca; 2414 2415 /* Disjoint CA */ 2416 imp->combine_width_ca[PIXMAN_OP_DISJOINT_CLEAR] = combine_clear_ca; 2417 imp->combine_width_ca[PIXMAN_OP_DISJOINT_SRC] = combine_src_ca; 2418 imp->combine_width_ca[PIXMAN_OP_DISJOINT_DST] = combine_dst; 2419 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER] = combine_disjoint_over_ca; 2420 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OVER_REVERSE] = combine_saturate_ca; 2421 imp->combine_width_ca[PIXMAN_OP_DISJOINT_IN] = combine_disjoint_in_ca; 2422 imp->combine_width_ca[PIXMAN_OP_DISJOINT_IN_REVERSE] = combine_disjoint_in_reverse_ca; 2423 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OUT] = combine_disjoint_out_ca; 2424 imp->combine_width_ca[PIXMAN_OP_DISJOINT_OUT_REVERSE] = combine_disjoint_out_reverse_ca; 2425 imp->combine_width_ca[PIXMAN_OP_DISJOINT_ATOP] = combine_disjoint_atop_ca; 2426 imp->combine_width_ca[PIXMAN_OP_DISJOINT_ATOP_REVERSE] = combine_disjoint_atop_reverse_ca; 2427 imp->combine_width_ca[PIXMAN_OP_DISJOINT_XOR] = combine_disjoint_xor_ca; 2428 2429 /* Conjoint CA */ 2430 imp->combine_width_ca[PIXMAN_OP_CONJOINT_CLEAR] = combine_clear_ca; 2431 imp->combine_width_ca[PIXMAN_OP_CONJOINT_SRC] = combine_src_ca; 2432 imp->combine_width_ca[PIXMAN_OP_CONJOINT_DST] = combine_dst; 2433 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER] = combine_conjoint_over_ca; 2434 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OVER_REVERSE] = combine_conjoint_over_reverse_ca; 2435 imp->combine_width_ca[PIXMAN_OP_CONJOINT_IN] = combine_conjoint_in_ca; 2436 imp->combine_width_ca[PIXMAN_OP_CONJOINT_IN_REVERSE] = combine_conjoint_in_reverse_ca; 2437 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OUT] = combine_conjoint_out_ca; 2438 imp->combine_width_ca[PIXMAN_OP_CONJOINT_OUT_REVERSE] = combine_conjoint_out_reverse_ca; 2439 imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP] = combine_conjoint_atop_ca; 2440 imp->combine_width_ca[PIXMAN_OP_CONJOINT_ATOP_REVERSE] = combine_conjoint_atop_reverse_ca; 2441 imp->combine_width_ca[PIXMAN_OP_CONJOINT_XOR] = combine_conjoint_xor_ca; 2442 2443 imp->combine_width_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca; 2444 imp->combine_width_ca[PIXMAN_OP_SCREEN] = combine_screen_ca; 2445 imp->combine_width_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca; 2446 imp->combine_width_ca[PIXMAN_OP_DARKEN] = combine_darken_ca; 2447 imp->combine_width_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca; 2448 imp->combine_width_ca[PIXMAN_OP_COLOR_DODGE] = combine_color_dodge_ca; 2449 imp->combine_width_ca[PIXMAN_OP_COLOR_BURN] = combine_color_burn_ca; 2450 imp->combine_width_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca; 2451 imp->combine_width_ca[PIXMAN_OP_SOFT_LIGHT] = combine_soft_light_ca; 2452 imp->combine_width_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca; 2453 imp->combine_width_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca; 2454 2455 /* It is not clear that these make sense, so make them noops for now */ 2456 imp->combine_width_ca[PIXMAN_OP_HSL_HUE] = combine_dst; 2457 imp->combine_width_ca[PIXMAN_OP_HSL_SATURATION] = combine_dst; 2458 imp->combine_width_ca[PIXMAN_OP_HSL_COLOR] = combine_dst; 2459 imp->combine_width_ca[PIXMAN_OP_HSL_LUMINOSITY] = combine_dst; 2460} 2461 2462