pixman-combine32.c (29525B)
1 /* 2 * Copyright © 2000 Keith Packard, member of The XFree86 Project, Inc. 3 * 2005 Lars Knoll & Zack Rusin, Trolltech 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 Keith Packard not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Keith Packard 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 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS 16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 17 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY 18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 22 * SOFTWARE. 23 */ 24 #ifdef HAVE_CONFIG_H 25 #include <pixman-config.h> 26 #endif 27 28 #include <math.h> 29 #include <string.h> 30 31 #include "pixman-private.h" 32 #include "pixman-combine32.h" 33 34 /* component alpha helper functions */ 35 36 static void 37 combine_mask_ca (uint32_t *src, uint32_t *mask) 38 { 39 uint32_t a = *mask; 40 41 uint32_t x; 42 uint16_t xa; 43 44 if (!a) 45 { 46 *(src) = 0; 47 return; 48 } 49 50 x = *(src); 51 if (a == ~0) 52 { 53 x = x >> A_SHIFT; 54 x |= x << G_SHIFT; 55 x |= x << R_SHIFT; 56 *(mask) = x; 57 return; 58 } 59 60 xa = x >> A_SHIFT; 61 UN8x4_MUL_UN8x4 (x, a); 62 *(src) = x; 63 64 UN8x4_MUL_UN8 (a, xa); 65 *(mask) = a; 66 } 67 68 static void 69 combine_mask_value_ca (uint32_t *src, const uint32_t *mask) 70 { 71 uint32_t a = *mask; 72 uint32_t x; 73 74 if (!a) 75 { 76 *(src) = 0; 77 return; 78 } 79 80 if (a == ~0) 81 return; 82 83 x = *(src); 84 UN8x4_MUL_UN8x4 (x, a); 85 *(src) = x; 86 } 87 88 static void 89 combine_mask_alpha_ca (const uint32_t *src, uint32_t *mask) 90 { 91 uint32_t a = *(mask); 92 uint32_t x; 93 94 if (!a) 95 return; 96 97 x = *(src) >> A_SHIFT; 98 if (x == MASK) 99 return; 100 101 if (a == ~0) 102 { 103 x |= x << G_SHIFT; 104 x |= x << R_SHIFT; 105 *(mask) = x; 106 return; 107 } 108 109 UN8x4_MUL_UN8 (a, x); 110 *(mask) = a; 111 } 112 113 /* 114 * There are two ways of handling alpha -- either as a single unified value or 115 * a separate value for each component, hence each macro must have two 116 * versions. The unified alpha version has a 'u' at the end of the name, 117 * the component version has a 'ca'. Similarly, functions which deal with 118 * this difference will have two versions using the same convention. 119 */ 120 121 static force_inline uint32_t 122 combine_mask (const uint32_t *src, const uint32_t *mask, int i) 123 { 124 uint32_t s, m; 125 126 if (mask) 127 { 128 m = *(mask + i) >> A_SHIFT; 129 130 if (!m) 131 return 0; 132 } 133 134 s = *(src + i); 135 136 if (mask) 137 UN8x4_MUL_UN8 (s, m); 138 139 return s; 140 } 141 142 static void 143 combine_clear (pixman_implementation_t *imp, 144 pixman_op_t op, 145 uint32_t * dest, 146 const uint32_t * src, 147 const uint32_t * mask, 148 int width) 149 { 150 memset (dest, 0, width * sizeof (uint32_t)); 151 } 152 153 static void 154 combine_dst (pixman_implementation_t *imp, 155 pixman_op_t op, 156 uint32_t * dest, 157 const uint32_t * src, 158 const uint32_t * mask, 159 int width) 160 { 161 return; 162 } 163 164 static void 165 combine_src_u (pixman_implementation_t *imp, 166 pixman_op_t op, 167 uint32_t * dest, 168 const uint32_t * src, 169 const uint32_t * mask, 170 int width) 171 { 172 int i; 173 174 if (!mask) 175 { 176 memcpy (dest, src, width * sizeof (uint32_t)); 177 } 178 else 179 { 180 for (i = 0; i < width; ++i) 181 { 182 uint32_t s = combine_mask (src, mask, i); 183 184 *(dest + i) = s; 185 } 186 } 187 } 188 189 static void 190 combine_over_u (pixman_implementation_t *imp, 191 pixman_op_t op, 192 uint32_t * dest, 193 const uint32_t * src, 194 const uint32_t * mask, 195 int width) 196 { 197 int i; 198 199 if (!mask) 200 { 201 for (i = 0; i < width; ++i) 202 { 203 uint32_t s = *(src + i); 204 uint32_t a = ALPHA_8 (s); 205 if (a == 0xFF) 206 { 207 *(dest + i) = s; 208 } 209 else if (s) 210 { 211 uint32_t d = *(dest + i); 212 uint32_t ia = a ^ 0xFF; 213 UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s); 214 *(dest + i) = d; 215 } 216 } 217 } 218 else 219 { 220 for (i = 0; i < width; ++i) 221 { 222 uint32_t m = ALPHA_8 (*(mask + i)); 223 if (m == 0xFF) 224 { 225 uint32_t s = *(src + i); 226 uint32_t a = ALPHA_8 (s); 227 if (a == 0xFF) 228 { 229 *(dest + i) = s; 230 } 231 else if (s) 232 { 233 uint32_t d = *(dest + i); 234 uint32_t ia = a ^ 0xFF; 235 UN8x4_MUL_UN8_ADD_UN8x4 (d, ia, s); 236 *(dest + i) = d; 237 } 238 } 239 else if (m) 240 { 241 uint32_t s = *(src + i); 242 if (s) 243 { 244 uint32_t d = *(dest + i); 245 UN8x4_MUL_UN8 (s, m); 246 UN8x4_MUL_UN8_ADD_UN8x4 (d, ALPHA_8 (~s), s); 247 *(dest + i) = d; 248 } 249 } 250 } 251 } 252 } 253 254 static void 255 combine_over_reverse_u (pixman_implementation_t *imp, 256 pixman_op_t op, 257 uint32_t * dest, 258 const uint32_t * src, 259 const uint32_t * mask, 260 int width) 261 { 262 int i; 263 264 for (i = 0; i < width; ++i) 265 { 266 uint32_t s = combine_mask (src, mask, i); 267 uint32_t d = *(dest + i); 268 uint32_t ia = ALPHA_8 (~*(dest + i)); 269 UN8x4_MUL_UN8_ADD_UN8x4 (s, ia, d); 270 *(dest + i) = s; 271 } 272 } 273 274 static void 275 combine_in_u (pixman_implementation_t *imp, 276 pixman_op_t op, 277 uint32_t * dest, 278 const uint32_t * src, 279 const uint32_t * mask, 280 int width) 281 { 282 int i; 283 284 for (i = 0; i < width; ++i) 285 { 286 uint32_t s = combine_mask (src, mask, i); 287 uint32_t a = ALPHA_8 (*(dest + i)); 288 UN8x4_MUL_UN8 (s, a); 289 *(dest + i) = s; 290 } 291 } 292 293 static void 294 combine_in_reverse_u (pixman_implementation_t *imp, 295 pixman_op_t op, 296 uint32_t * dest, 297 const uint32_t * src, 298 const uint32_t * mask, 299 int width) 300 { 301 int i; 302 303 for (i = 0; i < width; ++i) 304 { 305 uint32_t s = combine_mask (src, mask, i); 306 uint32_t d = *(dest + i); 307 uint32_t a = ALPHA_8 (s); 308 UN8x4_MUL_UN8 (d, a); 309 *(dest + i) = d; 310 } 311 } 312 313 static void 314 combine_out_u (pixman_implementation_t *imp, 315 pixman_op_t op, 316 uint32_t * dest, 317 const uint32_t * src, 318 const uint32_t * mask, 319 int width) 320 { 321 int i; 322 323 for (i = 0; i < width; ++i) 324 { 325 uint32_t s = combine_mask (src, mask, i); 326 uint32_t a = ALPHA_8 (~*(dest + i)); 327 UN8x4_MUL_UN8 (s, a); 328 *(dest + i) = s; 329 } 330 } 331 332 static void 333 combine_out_reverse_u (pixman_implementation_t *imp, 334 pixman_op_t op, 335 uint32_t * dest, 336 const uint32_t * src, 337 const uint32_t * mask, 338 int width) 339 { 340 int i; 341 342 for (i = 0; i < width; ++i) 343 { 344 uint32_t s = combine_mask (src, mask, i); 345 uint32_t d = *(dest + i); 346 uint32_t a = ALPHA_8 (~s); 347 UN8x4_MUL_UN8 (d, a); 348 *(dest + i) = d; 349 } 350 } 351 352 static void 353 combine_atop_u (pixman_implementation_t *imp, 354 pixman_op_t op, 355 uint32_t * dest, 356 const uint32_t * src, 357 const uint32_t * mask, 358 int width) 359 { 360 int i; 361 362 for (i = 0; i < width; ++i) 363 { 364 uint32_t s = combine_mask (src, mask, i); 365 uint32_t d = *(dest + i); 366 uint32_t dest_a = ALPHA_8 (d); 367 uint32_t src_ia = ALPHA_8 (~s); 368 369 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_a, d, src_ia); 370 *(dest + i) = s; 371 } 372 } 373 374 static void 375 combine_atop_reverse_u (pixman_implementation_t *imp, 376 pixman_op_t op, 377 uint32_t * dest, 378 const uint32_t * src, 379 const uint32_t * mask, 380 int width) 381 { 382 int i; 383 384 for (i = 0; i < width; ++i) 385 { 386 uint32_t s = combine_mask (src, mask, i); 387 uint32_t d = *(dest + i); 388 uint32_t src_a = ALPHA_8 (s); 389 uint32_t dest_ia = ALPHA_8 (~d); 390 391 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_a); 392 *(dest + i) = s; 393 } 394 } 395 396 static void 397 combine_xor_u (pixman_implementation_t *imp, 398 pixman_op_t op, 399 uint32_t * dest, 400 const uint32_t * src, 401 const uint32_t * mask, 402 int width) 403 { 404 int i; 405 406 for (i = 0; i < width; ++i) 407 { 408 uint32_t s = combine_mask (src, mask, i); 409 uint32_t d = *(dest + i); 410 uint32_t src_ia = ALPHA_8 (~s); 411 uint32_t dest_ia = ALPHA_8 (~d); 412 413 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (s, dest_ia, d, src_ia); 414 *(dest + i) = s; 415 } 416 } 417 418 static void 419 combine_add_u (pixman_implementation_t *imp, 420 pixman_op_t op, 421 uint32_t * dest, 422 const uint32_t * src, 423 const uint32_t * mask, 424 int width) 425 { 426 int i; 427 428 for (i = 0; i < width; ++i) 429 { 430 uint32_t s = combine_mask (src, mask, i); 431 uint32_t d = *(dest + i); 432 UN8x4_ADD_UN8x4 (d, s); 433 *(dest + i) = d; 434 } 435 } 436 437 /* 438 * PDF blend modes: 439 * 440 * The following blend modes have been taken from the PDF ISO 32000 441 * specification, which at this point in time is available from 442 * 443 * http://www.adobe.com/devnet/pdf/pdf_reference.html 444 * 445 * The specific documents of interest are the PDF spec itself: 446 * 447 * http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf 448 * 449 * chapters 11.3.5 and 11.3.6 and a later supplement for Adobe Acrobat 450 * 9.1 and Reader 9.1: 451 * 452 * http://wwwimages.adobe.com/www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/adobe_supplement_iso32000_1.pdf 453 * 454 * that clarifies the specifications for blend modes ColorDodge and 455 * ColorBurn. 456 * 457 * The formula for computing the final pixel color given in 11.3.6 is: 458 * 459 * αr × Cr = (1 – αs) × αb × Cb + (1 – αb) × αs × Cs + αb × αs × B(Cb, Cs) 460 * 461 * with B() is the blend function. When B(Cb, Cs) = Cs, this formula 462 * reduces to the regular OVER operator. 463 * 464 * Cs and Cb are not premultiplied, so in our implementation we instead 465 * use: 466 * 467 * cr = (1 – αs) × cb + (1 – αb) × cs + αb × αs × B (cb/αb, cs/αs) 468 * 469 * where cr, cs, and cb are premultiplied colors, and where the 470 * 471 * αb × αs × B(cb/αb, cs/αs) 472 * 473 * part is first arithmetically simplified under the assumption that αb 474 * and αs are not 0, and then updated to produce a meaningful result when 475 * they are. 476 * 477 * For all the blend mode operators, the alpha channel is given by 478 * 479 * αr = αs + αb + αb × αs 480 */ 481 482 /* 483 * Multiply 484 * 485 * ad * as * B(d / ad, s / as) 486 * = ad * as * d/ad * s/as 487 * = d * s 488 * 489 */ 490 static void 491 combine_multiply_u (pixman_implementation_t *imp, 492 pixman_op_t op, 493 uint32_t * dest, 494 const uint32_t * src, 495 const uint32_t * mask, 496 int width) 497 { 498 int i; 499 500 for (i = 0; i < width; ++i) 501 { 502 uint32_t s = combine_mask (src, mask, i); 503 uint32_t d = *(dest + i); 504 uint32_t ss = s; 505 uint32_t src_ia = ALPHA_8 (~s); 506 uint32_t dest_ia = ALPHA_8 (~d); 507 508 UN8x4_MUL_UN8_ADD_UN8x4_MUL_UN8 (ss, dest_ia, d, src_ia); 509 UN8x4_MUL_UN8x4 (d, s); 510 UN8x4_ADD_UN8x4 (d, ss); 511 512 *(dest + i) = d; 513 } 514 } 515 516 static void 517 combine_multiply_ca (pixman_implementation_t *imp, 518 pixman_op_t op, 519 uint32_t * dest, 520 const uint32_t * src, 521 const uint32_t * mask, 522 int width) 523 { 524 int i; 525 526 for (i = 0; i < width; ++i) 527 { 528 uint32_t m = *(mask + i); 529 uint32_t s = *(src + i); 530 uint32_t d = *(dest + i); 531 uint32_t r = d; 532 uint32_t dest_ia = ALPHA_8 (~d); 533 534 combine_mask_ca (&s, &m); 535 536 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (r, ~m, s, dest_ia); 537 UN8x4_MUL_UN8x4 (d, s); 538 UN8x4_ADD_UN8x4 (r, d); 539 540 *(dest + i) = r; 541 } 542 } 543 544 #define CLAMP(v, low, high) \ 545 do \ 546 { \ 547 if (v < (low)) \ 548 v = (low); \ 549 if (v > (high)) \ 550 v = (high); \ 551 } while (0) 552 553 #define PDF_SEPARABLE_BLEND_MODE(name) \ 554 static void \ 555 combine_ ## name ## _u (pixman_implementation_t *imp, \ 556 pixman_op_t op, \ 557 uint32_t * dest, \ 558 const uint32_t * src, \ 559 const uint32_t * mask, \ 560 int width) \ 561 { \ 562 int i; \ 563 for (i = 0; i < width; ++i) \ 564 { \ 565 uint32_t s = combine_mask (src, mask, i); \ 566 uint32_t d = *(dest + i); \ 567 uint8_t sa = ALPHA_8 (s); \ 568 uint8_t isa = ~sa; \ 569 uint8_t da = ALPHA_8 (d); \ 570 uint8_t ida = ~da; \ 571 uint32_t ra, rr, rg, rb; \ 572 \ 573 ra = da * 0xff + sa * 0xff - sa * da; \ 574 rr = isa * RED_8 (d) + ida * RED_8 (s); \ 575 rg = isa * GREEN_8 (d) + ida * GREEN_8 (s); \ 576 rb = isa * BLUE_8 (d) + ida * BLUE_8 (s); \ 577 \ 578 rr += blend_ ## name (RED_8 (d), da, RED_8 (s), sa); \ 579 rg += blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), sa); \ 580 rb += blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), sa); \ 581 \ 582 CLAMP (ra, 0, 255 * 255); \ 583 CLAMP (rr, 0, 255 * 255); \ 584 CLAMP (rg, 0, 255 * 255); \ 585 CLAMP (rb, 0, 255 * 255); \ 586 \ 587 ra = DIV_ONE_UN8 (ra); \ 588 rr = DIV_ONE_UN8 (rr); \ 589 rg = DIV_ONE_UN8 (rg); \ 590 rb = DIV_ONE_UN8 (rb); \ 591 \ 592 *(dest + i) = ra << 24 | rr << 16 | rg << 8 | rb; \ 593 } \ 594 } \ 595 \ 596 static void \ 597 combine_ ## name ## _ca (pixman_implementation_t *imp, \ 598 pixman_op_t op, \ 599 uint32_t * dest, \ 600 const uint32_t * src, \ 601 const uint32_t * mask, \ 602 int width) \ 603 { \ 604 int i; \ 605 for (i = 0; i < width; ++i) \ 606 { \ 607 uint32_t m = *(mask + i); \ 608 uint32_t s = *(src + i); \ 609 uint32_t d = *(dest + i); \ 610 uint8_t da = ALPHA_8 (d); \ 611 uint8_t ida = ~da; \ 612 uint32_t ra, rr, rg, rb; \ 613 uint8_t ira, iga, iba; \ 614 \ 615 combine_mask_ca (&s, &m); \ 616 \ 617 ira = ~RED_8 (m); \ 618 iga = ~GREEN_8 (m); \ 619 iba = ~BLUE_8 (m); \ 620 \ 621 ra = da * 0xff + ALPHA_8 (s) * 0xff - ALPHA_8 (s) * da; \ 622 rr = ira * RED_8 (d) + ida * RED_8 (s); \ 623 rg = iga * GREEN_8 (d) + ida * GREEN_8 (s); \ 624 rb = iba * BLUE_8 (d) + ida * BLUE_8 (s); \ 625 \ 626 rr += blend_ ## name (RED_8 (d), da, RED_8 (s), RED_8 (m)); \ 627 rg += blend_ ## name (GREEN_8 (d), da, GREEN_8 (s), GREEN_8 (m)); \ 628 rb += blend_ ## name (BLUE_8 (d), da, BLUE_8 (s), BLUE_8 (m)); \ 629 \ 630 CLAMP (ra, 0, 255 * 255); \ 631 CLAMP (rr, 0, 255 * 255); \ 632 CLAMP (rg, 0, 255 * 255); \ 633 CLAMP (rb, 0, 255 * 255); \ 634 \ 635 ra = DIV_ONE_UN8 (ra); \ 636 rr = DIV_ONE_UN8 (rr); \ 637 rg = DIV_ONE_UN8 (rg); \ 638 rb = DIV_ONE_UN8 (rb); \ 639 \ 640 *(dest + i) = ra << 24 | rr << 16 | rg << 8 | rb; \ 641 } \ 642 } 643 644 /* 645 * Screen 646 * 647 * ad * as * B(d/ad, s/as) 648 * = ad * as * (d/ad + s/as - s/as * d/ad) 649 * = ad * s + as * d - s * d 650 */ 651 static inline int32_t 652 blend_screen (int32_t d, int32_t ad, int32_t s, int32_t as) 653 { 654 return s * ad + d * as - s * d; 655 } 656 657 PDF_SEPARABLE_BLEND_MODE (screen) 658 659 /* 660 * Overlay 661 * 662 * ad * as * B(d/ad, s/as) 663 * = ad * as * Hardlight (s, d) 664 * = if (d / ad < 0.5) 665 * as * ad * Multiply (s/as, 2 * d/ad) 666 * else 667 * as * ad * Screen (s/as, 2 * d / ad - 1) 668 * = if (d < 0.5 * ad) 669 * as * ad * s/as * 2 * d /ad 670 * else 671 * as * ad * (s/as + 2 * d / ad - 1 - s / as * (2 * d / ad - 1)) 672 * = if (2 * d < ad) 673 * 2 * s * d 674 * else 675 * ad * s + 2 * as * d - as * ad - ad * s * (2 * d / ad - 1) 676 * = if (2 * d < ad) 677 * 2 * s * d 678 * else 679 * as * ad - 2 * (ad - d) * (as - s) 680 */ 681 static inline int32_t 682 blend_overlay (int32_t d, int32_t ad, int32_t s, int32_t as) 683 { 684 uint32_t r; 685 686 if (2 * d < ad) 687 r = 2 * s * d; 688 else 689 r = as * ad - 2 * (ad - d) * (as - s); 690 691 return r; 692 } 693 694 PDF_SEPARABLE_BLEND_MODE (overlay) 695 696 /* 697 * Darken 698 * 699 * ad * as * B(d/ad, s/as) 700 * = ad * as * MIN(d/ad, s/as) 701 * = MIN (as * d, ad * s) 702 */ 703 static inline int32_t 704 blend_darken (int32_t d, int32_t ad, int32_t s, int32_t as) 705 { 706 s = ad * s; 707 d = as * d; 708 709 return s > d ? d : s; 710 } 711 712 PDF_SEPARABLE_BLEND_MODE (darken) 713 714 /* 715 * Lighten 716 * 717 * ad * as * B(d/ad, s/as) 718 * = ad * as * MAX(d/ad, s/as) 719 * = MAX (as * d, ad * s) 720 */ 721 static inline int32_t 722 blend_lighten (int32_t d, int32_t ad, int32_t s, int32_t as) 723 { 724 s = ad * s; 725 d = as * d; 726 727 return s > d ? s : d; 728 } 729 730 PDF_SEPARABLE_BLEND_MODE (lighten) 731 732 /* 733 * Hard light 734 * 735 * ad * as * B(d/ad, s/as) 736 * = if (s/as <= 0.5) 737 * ad * as * Multiply (d/ad, 2 * s/as) 738 * else 739 * ad * as * Screen (d/ad, 2 * s/as - 1) 740 * = if 2 * s <= as 741 * ad * as * d/ad * 2 * s / as 742 * else 743 * ad * as * (d/ad + (2 * s/as - 1) + d/ad * (2 * s/as - 1)) 744 * = if 2 * s <= as 745 * 2 * s * d 746 * else 747 * as * ad - 2 * (ad - d) * (as - s) 748 */ 749 static inline int32_t 750 blend_hard_light (int32_t d, int32_t ad, int32_t s, int32_t as) 751 { 752 if (2 * s < as) 753 return 2 * s * d; 754 else 755 return as * ad - 2 * (ad - d) * (as - s); 756 } 757 758 PDF_SEPARABLE_BLEND_MODE (hard_light) 759 760 /* 761 * Difference 762 * 763 * ad * as * B(s/as, d/ad) 764 * = ad * as * abs (s/as - d/ad) 765 * = if (s/as <= d/ad) 766 * ad * as * (d/ad - s/as) 767 * else 768 * ad * as * (s/as - d/ad) 769 * = if (ad * s <= as * d) 770 * as * d - ad * s 771 * else 772 * ad * s - as * d 773 */ 774 static inline int32_t 775 blend_difference (int32_t d, int32_t ad, int32_t s, int32_t as) 776 { 777 int32_t das = d * as; 778 int32_t sad = s * ad; 779 780 if (sad < das) 781 return das - sad; 782 else 783 return sad - das; 784 } 785 786 PDF_SEPARABLE_BLEND_MODE (difference) 787 788 /* 789 * Exclusion 790 * 791 * ad * as * B(s/as, d/ad) 792 * = ad * as * (d/ad + s/as - 2 * d/ad * s/as) 793 * = as * d + ad * s - 2 * s * d 794 */ 795 796 /* This can be made faster by writing it directly and not using 797 * PDF_SEPARABLE_BLEND_MODE, but that's a performance optimization */ 798 799 static inline int32_t 800 blend_exclusion (int32_t d, int32_t ad, int32_t s, int32_t as) 801 { 802 return s * ad + d * as - 2 * d * s; 803 } 804 805 PDF_SEPARABLE_BLEND_MODE (exclusion) 806 807 #undef PDF_SEPARABLE_BLEND_MODE 808 809 /* Component alpha combiners */ 810 811 static void 812 combine_clear_ca (pixman_implementation_t *imp, 813 pixman_op_t op, 814 uint32_t * dest, 815 const uint32_t * src, 816 const uint32_t * mask, 817 int width) 818 { 819 memset (dest, 0, width * sizeof(uint32_t)); 820 } 821 822 static void 823 combine_src_ca (pixman_implementation_t *imp, 824 pixman_op_t op, 825 uint32_t * dest, 826 const uint32_t * src, 827 const uint32_t * mask, 828 int width) 829 { 830 int i; 831 832 for (i = 0; i < width; ++i) 833 { 834 uint32_t s = *(src + i); 835 uint32_t m = *(mask + i); 836 837 combine_mask_value_ca (&s, &m); 838 839 *(dest + i) = s; 840 } 841 } 842 843 static void 844 combine_over_ca (pixman_implementation_t *imp, 845 pixman_op_t op, 846 uint32_t * dest, 847 const uint32_t * src, 848 const uint32_t * mask, 849 int width) 850 { 851 int i; 852 853 for (i = 0; i < width; ++i) 854 { 855 uint32_t s = *(src + i); 856 uint32_t m = *(mask + i); 857 uint32_t a; 858 859 combine_mask_ca (&s, &m); 860 861 a = ~m; 862 if (a) 863 { 864 uint32_t d = *(dest + i); 865 UN8x4_MUL_UN8x4_ADD_UN8x4 (d, a, s); 866 s = d; 867 } 868 869 *(dest + i) = s; 870 } 871 } 872 873 static void 874 combine_over_reverse_ca (pixman_implementation_t *imp, 875 pixman_op_t op, 876 uint32_t * dest, 877 const uint32_t * src, 878 const uint32_t * mask, 879 int width) 880 { 881 int i; 882 883 for (i = 0; i < width; ++i) 884 { 885 uint32_t d = *(dest + i); 886 uint32_t a = ~d >> A_SHIFT; 887 888 if (a) 889 { 890 uint32_t s = *(src + i); 891 uint32_t m = *(mask + i); 892 893 UN8x4_MUL_UN8x4 (s, m); 894 UN8x4_MUL_UN8_ADD_UN8x4 (s, a, d); 895 896 *(dest + i) = s; 897 } 898 } 899 } 900 901 static void 902 combine_in_ca (pixman_implementation_t *imp, 903 pixman_op_t op, 904 uint32_t * dest, 905 const uint32_t * src, 906 const uint32_t * mask, 907 int width) 908 { 909 int i; 910 911 for (i = 0; i < width; ++i) 912 { 913 uint32_t d = *(dest + i); 914 uint16_t a = d >> A_SHIFT; 915 uint32_t s = 0; 916 917 if (a) 918 { 919 uint32_t m = *(mask + i); 920 921 s = *(src + i); 922 combine_mask_value_ca (&s, &m); 923 924 if (a != MASK) 925 UN8x4_MUL_UN8 (s, a); 926 } 927 928 *(dest + i) = s; 929 } 930 } 931 932 static void 933 combine_in_reverse_ca (pixman_implementation_t *imp, 934 pixman_op_t op, 935 uint32_t * dest, 936 const uint32_t * src, 937 const uint32_t * mask, 938 int width) 939 { 940 int i; 941 942 for (i = 0; i < width; ++i) 943 { 944 uint32_t s = *(src + i); 945 uint32_t m = *(mask + i); 946 uint32_t a; 947 948 combine_mask_alpha_ca (&s, &m); 949 950 a = m; 951 if (a != ~0) 952 { 953 uint32_t d = 0; 954 955 if (a) 956 { 957 d = *(dest + i); 958 UN8x4_MUL_UN8x4 (d, a); 959 } 960 961 *(dest + i) = d; 962 } 963 } 964 } 965 966 static void 967 combine_out_ca (pixman_implementation_t *imp, 968 pixman_op_t op, 969 uint32_t * dest, 970 const uint32_t * src, 971 const uint32_t * mask, 972 int width) 973 { 974 int i; 975 976 for (i = 0; i < width; ++i) 977 { 978 uint32_t d = *(dest + i); 979 uint16_t a = ~d >> A_SHIFT; 980 uint32_t s = 0; 981 982 if (a) 983 { 984 uint32_t m = *(mask + i); 985 986 s = *(src + i); 987 combine_mask_value_ca (&s, &m); 988 989 if (a != MASK) 990 UN8x4_MUL_UN8 (s, a); 991 } 992 993 *(dest + i) = s; 994 } 995 } 996 997 static void 998 combine_out_reverse_ca (pixman_implementation_t *imp, 999 pixman_op_t op, 1000 uint32_t * dest, 1001 const uint32_t * src, 1002 const uint32_t * mask, 1003 int width) 1004 { 1005 int i; 1006 1007 for (i = 0; i < width; ++i) 1008 { 1009 uint32_t s = *(src + i); 1010 uint32_t m = *(mask + i); 1011 uint32_t a; 1012 1013 combine_mask_alpha_ca (&s, &m); 1014 1015 a = ~m; 1016 if (a != ~0) 1017 { 1018 uint32_t d = 0; 1019 1020 if (a) 1021 { 1022 d = *(dest + i); 1023 UN8x4_MUL_UN8x4 (d, a); 1024 } 1025 1026 *(dest + i) = d; 1027 } 1028 } 1029 } 1030 1031 static void 1032 combine_atop_ca (pixman_implementation_t *imp, 1033 pixman_op_t op, 1034 uint32_t * dest, 1035 const uint32_t * src, 1036 const uint32_t * mask, 1037 int width) 1038 { 1039 int i; 1040 1041 for (i = 0; i < width; ++i) 1042 { 1043 uint32_t d = *(dest + i); 1044 uint32_t s = *(src + i); 1045 uint32_t m = *(mask + i); 1046 uint32_t ad; 1047 uint16_t as = d >> A_SHIFT; 1048 1049 combine_mask_ca (&s, &m); 1050 1051 ad = ~m; 1052 1053 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as); 1054 1055 *(dest + i) = d; 1056 } 1057 } 1058 1059 static void 1060 combine_atop_reverse_ca (pixman_implementation_t *imp, 1061 pixman_op_t op, 1062 uint32_t * dest, 1063 const uint32_t * src, 1064 const uint32_t * mask, 1065 int width) 1066 { 1067 int i; 1068 1069 for (i = 0; i < width; ++i) 1070 { 1071 uint32_t d = *(dest + i); 1072 uint32_t s = *(src + i); 1073 uint32_t m = *(mask + i); 1074 uint32_t ad; 1075 uint16_t as = ~d >> A_SHIFT; 1076 1077 combine_mask_ca (&s, &m); 1078 1079 ad = m; 1080 1081 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as); 1082 1083 *(dest + i) = d; 1084 } 1085 } 1086 1087 static void 1088 combine_xor_ca (pixman_implementation_t *imp, 1089 pixman_op_t op, 1090 uint32_t * dest, 1091 const uint32_t * src, 1092 const uint32_t * mask, 1093 int width) 1094 { 1095 int i; 1096 1097 for (i = 0; i < width; ++i) 1098 { 1099 uint32_t d = *(dest + i); 1100 uint32_t s = *(src + i); 1101 uint32_t m = *(mask + i); 1102 uint32_t ad; 1103 uint16_t as = ~d >> A_SHIFT; 1104 1105 combine_mask_ca (&s, &m); 1106 1107 ad = ~m; 1108 1109 UN8x4_MUL_UN8x4_ADD_UN8x4_MUL_UN8 (d, ad, s, as); 1110 1111 *(dest + i) = d; 1112 } 1113 } 1114 1115 static void 1116 combine_add_ca (pixman_implementation_t *imp, 1117 pixman_op_t op, 1118 uint32_t * dest, 1119 const uint32_t * src, 1120 const uint32_t * mask, 1121 int width) 1122 { 1123 int i; 1124 1125 for (i = 0; i < width; ++i) 1126 { 1127 uint32_t s = *(src + i); 1128 uint32_t m = *(mask + i); 1129 uint32_t d = *(dest + i); 1130 1131 combine_mask_value_ca (&s, &m); 1132 1133 UN8x4_ADD_UN8x4 (d, s); 1134 1135 *(dest + i) = d; 1136 } 1137 } 1138 1139 void 1140 _pixman_setup_combiner_functions_32 (pixman_implementation_t *imp) 1141 { 1142 /* Unified alpha */ 1143 imp->combine_32[PIXMAN_OP_CLEAR] = combine_clear; 1144 imp->combine_32[PIXMAN_OP_SRC] = combine_src_u; 1145 imp->combine_32[PIXMAN_OP_DST] = combine_dst; 1146 imp->combine_32[PIXMAN_OP_OVER] = combine_over_u; 1147 imp->combine_32[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_u; 1148 imp->combine_32[PIXMAN_OP_IN] = combine_in_u; 1149 imp->combine_32[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_u; 1150 imp->combine_32[PIXMAN_OP_OUT] = combine_out_u; 1151 imp->combine_32[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_u; 1152 imp->combine_32[PIXMAN_OP_ATOP] = combine_atop_u; 1153 imp->combine_32[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_u; 1154 imp->combine_32[PIXMAN_OP_XOR] = combine_xor_u; 1155 imp->combine_32[PIXMAN_OP_ADD] = combine_add_u; 1156 1157 imp->combine_32[PIXMAN_OP_MULTIPLY] = combine_multiply_u; 1158 imp->combine_32[PIXMAN_OP_SCREEN] = combine_screen_u; 1159 imp->combine_32[PIXMAN_OP_OVERLAY] = combine_overlay_u; 1160 imp->combine_32[PIXMAN_OP_DARKEN] = combine_darken_u; 1161 imp->combine_32[PIXMAN_OP_LIGHTEN] = combine_lighten_u; 1162 imp->combine_32[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_u; 1163 imp->combine_32[PIXMAN_OP_DIFFERENCE] = combine_difference_u; 1164 imp->combine_32[PIXMAN_OP_EXCLUSION] = combine_exclusion_u; 1165 1166 /* Component alpha combiners */ 1167 imp->combine_32_ca[PIXMAN_OP_CLEAR] = combine_clear_ca; 1168 imp->combine_32_ca[PIXMAN_OP_SRC] = combine_src_ca; 1169 /* dest */ 1170 imp->combine_32_ca[PIXMAN_OP_OVER] = combine_over_ca; 1171 imp->combine_32_ca[PIXMAN_OP_OVER_REVERSE] = combine_over_reverse_ca; 1172 imp->combine_32_ca[PIXMAN_OP_IN] = combine_in_ca; 1173 imp->combine_32_ca[PIXMAN_OP_IN_REVERSE] = combine_in_reverse_ca; 1174 imp->combine_32_ca[PIXMAN_OP_OUT] = combine_out_ca; 1175 imp->combine_32_ca[PIXMAN_OP_OUT_REVERSE] = combine_out_reverse_ca; 1176 imp->combine_32_ca[PIXMAN_OP_ATOP] = combine_atop_ca; 1177 imp->combine_32_ca[PIXMAN_OP_ATOP_REVERSE] = combine_atop_reverse_ca; 1178 imp->combine_32_ca[PIXMAN_OP_XOR] = combine_xor_ca; 1179 imp->combine_32_ca[PIXMAN_OP_ADD] = combine_add_ca; 1180 1181 imp->combine_32_ca[PIXMAN_OP_MULTIPLY] = combine_multiply_ca; 1182 imp->combine_32_ca[PIXMAN_OP_SCREEN] = combine_screen_ca; 1183 imp->combine_32_ca[PIXMAN_OP_OVERLAY] = combine_overlay_ca; 1184 imp->combine_32_ca[PIXMAN_OP_DARKEN] = combine_darken_ca; 1185 imp->combine_32_ca[PIXMAN_OP_LIGHTEN] = combine_lighten_ca; 1186 imp->combine_32_ca[PIXMAN_OP_HARD_LIGHT] = combine_hard_light_ca; 1187 imp->combine_32_ca[PIXMAN_OP_DIFFERENCE] = combine_difference_ca; 1188 imp->combine_32_ca[PIXMAN_OP_EXCLUSION] = combine_exclusion_ca; 1189 }